mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-27 14:12:38 +00:00
Add a level mesh viewer (--viewer cmdline arg) for better debugging
This commit is contained in:
parent
6f779c0351
commit
e28879187c
12 changed files with 973 additions and 16 deletions
|
@ -81,13 +81,17 @@ set(ZDRAY_SOURCES
|
|||
src/lightmapper/gpuraytracer.h
|
||||
src/lightmapper/stacktrace.cpp
|
||||
src/lightmapper/stacktrace.h
|
||||
src/lightmapper/levelmeshviewer.cpp
|
||||
src/lightmapper/levelmeshviewer.h
|
||||
src/lightmapper/glsl/binding_lightmapper.glsl.h
|
||||
src/lightmapper/glsl/binding_raytrace.glsl.h
|
||||
src/lightmapper/glsl/binding_textures.glsl.h
|
||||
src/lightmapper/glsl/binding_viewer.glsl.h
|
||||
src/lightmapper/glsl/frag_blur.glsl.h
|
||||
src/lightmapper/glsl/frag_copy.glsl.h
|
||||
src/lightmapper/glsl/frag_raytrace.glsl.h
|
||||
src/lightmapper/glsl/frag_resolve.glsl.h
|
||||
src/lightmapper/glsl/frag_viewer.glsl.h
|
||||
src/lightmapper/glsl/montecarlo.glsl.h
|
||||
src/lightmapper/glsl/polyfill_rayquery.glsl.h
|
||||
src/lightmapper/glsl/trace_ambient_occlusion.glsl.h
|
||||
|
@ -98,6 +102,7 @@ set(ZDRAY_SOURCES
|
|||
src/lightmapper/glsl/vert_copy.glsl.h
|
||||
src/lightmapper/glsl/vert_raytrace.glsl.h
|
||||
src/lightmapper/glsl/vert_screenquad.glsl.h
|
||||
src/lightmapper/glsl/vert_viewer.glsl.h
|
||||
src/models/model.cpp
|
||||
src/models/model.h
|
||||
src/models/model_md2.h
|
||||
|
|
97
src/lightmapper/glsl/binding_viewer.glsl.h
Normal file
97
src/lightmapper/glsl/binding_viewer.glsl.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
static const char* binding_viewer_glsl = R"glsl(
|
||||
|
||||
struct SurfaceInfo
|
||||
{
|
||||
vec3 Normal;
|
||||
float Sky;
|
||||
uint PortalIndex;
|
||||
int TextureIndex;
|
||||
float Alpha;
|
||||
float Padding0;
|
||||
uint LightStart;
|
||||
uint LightEnd;
|
||||
uint Padding1;
|
||||
uint Padding2;
|
||||
};
|
||||
|
||||
struct PortalInfo
|
||||
{
|
||||
mat4 Transformation;
|
||||
};
|
||||
|
||||
struct LightInfo
|
||||
{
|
||||
vec3 Origin;
|
||||
float Padding0;
|
||||
vec3 RelativeOrigin;
|
||||
float Padding1;
|
||||
float Radius;
|
||||
float Intensity;
|
||||
float InnerAngleCos;
|
||||
float OuterAngleCos;
|
||||
vec3 SpotDir;
|
||||
float SourceRadius;
|
||||
vec3 Color;
|
||||
float Padding3;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 0, std430) buffer SurfaceIndexBuffer { uint surfaceIndices[]; };
|
||||
layout(set = 0, binding = 1, std430) buffer SurfaceBuffer { SurfaceInfo surfaces[]; };
|
||||
layout(set = 0, binding = 2, std430) buffer LightBuffer { LightInfo lights[]; };
|
||||
layout(set = 0, binding = 3, std430) buffer LightIndexBuffer { int lightIndexes[]; };
|
||||
layout(set = 0, binding = 4, std430) buffer PortalBuffer { PortalInfo portals[]; };
|
||||
|
||||
#if defined(USE_RAYQUERY)
|
||||
|
||||
layout(set = 0, binding = 5) uniform accelerationStructureEXT acc;
|
||||
|
||||
#else
|
||||
|
||||
struct CollisionNode
|
||||
{
|
||||
vec3 center;
|
||||
float padding1;
|
||||
vec3 extents;
|
||||
float padding2;
|
||||
int left;
|
||||
int right;
|
||||
int element_index;
|
||||
int padding3;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 5, std430) buffer NodeBuffer
|
||||
{
|
||||
int nodesRoot;
|
||||
int nodebufferPadding1;
|
||||
int nodebufferPadding2;
|
||||
int nodebufferPadding3;
|
||||
CollisionNode nodes[];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct SurfaceVertex // Note: this must always match the FFlatVertex struct
|
||||
{
|
||||
vec3 pos;
|
||||
float lindex;
|
||||
vec2 uv;
|
||||
vec2 luv;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 6, std430) buffer VertexBuffer { SurfaceVertex vertices[]; };
|
||||
layout(set = 0, binding = 7, std430) buffer ElementBuffer { int elements[]; };
|
||||
|
||||
layout(set = 1, binding = 0) uniform sampler2D textures[];
|
||||
|
||||
layout(push_constant) uniform PushConstants
|
||||
{
|
||||
mat4 ViewToWorld;
|
||||
vec3 CameraPos;
|
||||
float ProjX;
|
||||
vec3 SunDir;
|
||||
float ProjY;
|
||||
vec3 SunColor;
|
||||
float SunIntensity;
|
||||
};
|
||||
|
||||
)glsl";
|
51
src/lightmapper/glsl/frag_viewer.glsl.h
Normal file
51
src/lightmapper/glsl/frag_viewer.glsl.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
static const char* frag_viewer_glsl = R"glsl(
|
||||
|
||||
#include <shaders/lightmap/binding_viewer.glsl>
|
||||
#include <shaders/lightmap/polyfill_rayquery.glsl>
|
||||
#include <shaders/lightmap/trace_levelmesh.glsl>
|
||||
#include <shaders/lightmap/trace_sunlight.glsl>
|
||||
#include <shaders/lightmap/trace_light.glsl>
|
||||
#include <shaders/lightmap/trace_ambient_occlusion.glsl>
|
||||
|
||||
layout(location = 0) in vec3 FragRay;
|
||||
layout(location = 0) out vec4 fragcolor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 incoming = vec3(0.1);
|
||||
|
||||
vec3 origin = CameraPos;
|
||||
vec3 L = normalize(FragRay);
|
||||
TraceResult result = TraceFirstHit(origin, 0.0, L, 10000.0);
|
||||
if (result.primitiveIndex != -1)
|
||||
{
|
||||
SurfaceInfo surface = GetSurface(result.primitiveIndex);
|
||||
vec3 surfacepos = origin + L * result.t;
|
||||
|
||||
if (surface.Sky == 0.0)
|
||||
{
|
||||
incoming += TraceSunLight(surfacepos, surface.Normal);
|
||||
|
||||
uint LightStart = surface.LightStart;
|
||||
uint LightEnd = surface.LightEnd;
|
||||
for (uint j = LightStart; j < LightEnd; j++)
|
||||
{
|
||||
incoming += TraceLight(surfacepos, surface.Normal, lights[lightIndexes[j]], 0.0);
|
||||
}
|
||||
|
||||
// incoming *= TraceAmbientOcclusion(surfacepos, surface.Normal);
|
||||
}
|
||||
else
|
||||
{
|
||||
incoming = SunColor;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
incoming = vec3(1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
fragcolor = vec4(incoming, 1.0);
|
||||
}
|
||||
|
||||
)glsl";
|
24
src/lightmapper/glsl/vert_viewer.glsl.h
Normal file
24
src/lightmapper/glsl/vert_viewer.glsl.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
static const char* vert_viewer_glsl = R"glsl(
|
||||
|
||||
#include <shaders/lightmap/binding_viewer.glsl>
|
||||
|
||||
layout(location = 0) out vec3 FragRay;
|
||||
|
||||
vec2 positions[4] = vec2[](
|
||||
vec2(0.0, 0.0),
|
||||
vec2(1.0, 0.0),
|
||||
vec2(0.0, 1.0),
|
||||
vec2(1.0, 1.0)
|
||||
);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 viewpos = vec4(positions[gl_VertexIndex] * 2.0 - 1.0, 1.0, 1.0);
|
||||
viewpos.x /= ProjX;
|
||||
viewpos.y = -viewpos.y / ProjY;
|
||||
FragRay = (ViewToWorld * viewpos).xyz - CameraPos;
|
||||
|
||||
gl_Position = vec4(positions[gl_VertexIndex] * 2.0 - 1.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
)glsl";
|
|
@ -5,6 +5,7 @@
|
|||
#include "vk_lightmapper.h"
|
||||
#include "renderdoc_app.h"
|
||||
#include "doom_levelmesh.h"
|
||||
#include "levelmeshviewer.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <dlfcn.h>
|
||||
|
@ -12,10 +13,14 @@
|
|||
|
||||
static RENDERDOC_API_1_4_2* rdoc_api;
|
||||
|
||||
extern bool showviewer;
|
||||
|
||||
GPURaytracer::GPURaytracer()
|
||||
{
|
||||
LoadRenderDoc();
|
||||
mDevice = std::make_unique<VulkanRenderDevice>();
|
||||
if (showviewer)
|
||||
mViewer = std::make_unique<LevelMeshViewer>();
|
||||
mDevice = std::make_unique<VulkanRenderDevice>(mViewer.get());
|
||||
PrintVulkanInfo();
|
||||
}
|
||||
|
||||
|
@ -77,6 +82,9 @@ void GPURaytracer::Raytrace(DoomLevelMesh* mesh)
|
|||
{
|
||||
mDevice->GetTextureManager()->DownloadLightmap(arrayIndex, mesh->LMTextureData.Data() + arrayIndex * mesh->LMTextureSize * mesh->LMTextureSize * 4);
|
||||
}
|
||||
|
||||
if (mViewer)
|
||||
mViewer->Exec(mDevice.get(), mesh->SunDirection, mesh->SunColor, 1.0f);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "vk_renderdevice.h"
|
||||
|
||||
class DoomLevelMesh;
|
||||
class LevelMeshViewer;
|
||||
|
||||
class GPURaytracer
|
||||
{
|
||||
|
@ -16,5 +17,6 @@ private:
|
|||
void PrintVulkanInfo();
|
||||
void LoadRenderDoc();
|
||||
|
||||
std::unique_ptr<LevelMeshViewer> mViewer;
|
||||
std::unique_ptr<VulkanRenderDevice> mDevice;
|
||||
};
|
||||
|
|
|
@ -9,6 +9,15 @@ LevelMesh::LevelMesh()
|
|||
|
||||
AddEmptyMesh();
|
||||
UpdateCollision();
|
||||
|
||||
Mesh.MaxVertices = std::max(Mesh.Vertices.Size() * 2, (unsigned int)10000);
|
||||
Mesh.MaxIndexes = std::max(Mesh.Indexes.Size() * 2, (unsigned int)10000);
|
||||
Mesh.MaxSurfaces = std::max(Mesh.SurfaceIndexes.Size() * 2, (unsigned int)10000);
|
||||
Mesh.MaxUniforms = std::max(Mesh.Uniforms.Size() * 2, (unsigned int)10000);
|
||||
Mesh.MaxSurfaceIndexes = std::max(Mesh.SurfaceIndexes.Size() * 2, (unsigned int)10000);
|
||||
Mesh.MaxNodes = (int)std::max(Collision->get_nodes().size() * 2, (size_t)10000);
|
||||
Mesh.MaxLights = 100'000;
|
||||
Mesh.MaxLightIndexes = 4 * 1024 * 1024;
|
||||
}
|
||||
|
||||
void LevelMesh::AddEmptyMesh()
|
||||
|
|
326
src/lightmapper/levelmeshviewer.cpp
Normal file
326
src/lightmapper/levelmeshviewer.cpp
Normal file
|
@ -0,0 +1,326 @@
|
|||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "levelmeshviewer.h"
|
||||
#include "vk_renderdevice.h"
|
||||
#include "framework/matrix.h"
|
||||
#include <windowsx.h>
|
||||
#include <stdexcept>
|
||||
#include <zvulkan/vulkanswapchain.h>
|
||||
|
||||
LevelMeshViewer::LevelMeshViewer()
|
||||
{
|
||||
CreateViewerWindow();
|
||||
}
|
||||
|
||||
LevelMeshViewer::~LevelMeshViewer()
|
||||
{
|
||||
DestroyViewerWindow();
|
||||
}
|
||||
|
||||
void LevelMeshViewer::RenderFrame()
|
||||
{
|
||||
RECT clientRect = {};
|
||||
GetClientRect(WindowHandle, &clientRect);
|
||||
int width = clientRect.right;
|
||||
int height = clientRect.bottom;
|
||||
if (width <= 0 || height <= 0)
|
||||
{
|
||||
Sleep(500);
|
||||
return;
|
||||
}
|
||||
|
||||
RenderDevice->ResizeSwapChain(width, height);
|
||||
|
||||
VSMatrix movematrix;
|
||||
movematrix.loadIdentity();
|
||||
movematrix.rotate((float)Yaw, 0.0f, 1.0f, 0.0);
|
||||
movematrix.rotate((float)Pitch, 1.0f, 0.0f, 0.0);
|
||||
if (MoveLeft)
|
||||
{
|
||||
CameraPos += (movematrix * FVector4(-10.0f, 0.0f, 0.0f, 1.0f)).XYZ();
|
||||
}
|
||||
if (MoveRight)
|
||||
{
|
||||
CameraPos += (movematrix * FVector4(10.0f, 0.0f, 0.0f, 1.0f)).XYZ();
|
||||
}
|
||||
if (MoveForward)
|
||||
{
|
||||
CameraPos += (movematrix * FVector4(0.0f, 0.0f, 10.0f, 1.0f)).XYZ();
|
||||
}
|
||||
if (MoveBackward)
|
||||
{
|
||||
CameraPos += (movematrix * FVector4(0.0f, 0.0f, -10.0f, 1.0f)).XYZ();
|
||||
}
|
||||
|
||||
VSMatrix worldToView;
|
||||
worldToView.loadIdentity();
|
||||
worldToView.rotate((float)-Pitch, 1.0f, 0.0f, 0.0);
|
||||
worldToView.rotate((float)-Yaw, 0.0f, 1.0f, 0.0);
|
||||
worldToView.translate(-CameraPos.X, -CameraPos.Y, -CameraPos.Z);
|
||||
|
||||
VSMatrix viewToWorld;
|
||||
worldToView.inverseMatrix(viewToWorld);
|
||||
|
||||
RenderDevice->DrawViewer(CameraPos, viewToWorld, 60.0f, width / (float)height, SunDir, SunColor, SunIntensity);
|
||||
}
|
||||
|
||||
void LevelMeshViewer::OnMouseMove(double dx, double dy)
|
||||
{
|
||||
Yaw += dx * 0.1;
|
||||
while (Yaw < 0.0) Yaw += 360.0;
|
||||
while (Yaw >= 360.0) Yaw -= 360.0;
|
||||
|
||||
Pitch += dy * 0.1;
|
||||
if (Pitch < -90.0) Pitch = -90.0;
|
||||
if (Pitch > 90.0) Pitch = 90.0;
|
||||
}
|
||||
|
||||
void LevelMeshViewer::OnKeyDown(WPARAM key)
|
||||
{
|
||||
if (key == 'A')
|
||||
{
|
||||
MoveLeft = true;
|
||||
}
|
||||
else if (key == 'D')
|
||||
{
|
||||
MoveRight = true;
|
||||
}
|
||||
else if (key == 'W')
|
||||
{
|
||||
MoveForward = true;
|
||||
}
|
||||
else if (key == 'S')
|
||||
{
|
||||
MoveBackward = true;
|
||||
}
|
||||
}
|
||||
|
||||
void LevelMeshViewer::OnKeyUp(WPARAM key)
|
||||
{
|
||||
if (key == 'A')
|
||||
{
|
||||
MoveLeft = false;
|
||||
}
|
||||
else if (key == 'D')
|
||||
{
|
||||
MoveRight = false;
|
||||
}
|
||||
else if (key == 'W')
|
||||
{
|
||||
MoveForward = false;
|
||||
}
|
||||
else if (key == 'S')
|
||||
{
|
||||
MoveBackward = false;
|
||||
}
|
||||
}
|
||||
|
||||
void LevelMeshViewer::Exec(VulkanRenderDevice* renderdevice, const FVector3& sundir, const FVector3& suncolor, float sunintensity)
|
||||
{
|
||||
RenderDevice = renderdevice;
|
||||
SunDir = sundir;
|
||||
SunColor = suncolor;
|
||||
SunIntensity = sunintensity;
|
||||
bool exitFlag = false;
|
||||
while (!exitFlag)
|
||||
{
|
||||
MSG msg = {};
|
||||
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
{
|
||||
exitFlag = true;
|
||||
break;
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
RenderFrame();
|
||||
}
|
||||
ShowWindow(WindowHandle, SW_HIDE);
|
||||
}
|
||||
|
||||
void LevelMeshViewer::CreateViewerWindow()
|
||||
{
|
||||
WNDCLASSEX classdesc = {};
|
||||
classdesc.cbSize = sizeof(WNDCLASSEX);
|
||||
classdesc.hInstance = GetModuleHandle(nullptr);
|
||||
classdesc.lpszClassName = L"LevelMeshViewerWindow";
|
||||
classdesc.lpfnWndProc = &LevelMeshViewer::WindowProc;
|
||||
classdesc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
|
||||
classdesc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
|
||||
BOOL result = RegisterClassEx(&classdesc);
|
||||
if (!result)
|
||||
throw std::runtime_error("RegisterClassEx failed");
|
||||
|
||||
HDC screenDC = GetDC(0);
|
||||
int dpi = GetDeviceCaps(screenDC, LOGPIXELSX);
|
||||
ReleaseDC(0, screenDC);
|
||||
auto applyDpi = [=](int i) { return (i * dpi + (96 / 2)) / 96; };
|
||||
|
||||
// Create and show the window
|
||||
WindowHandle = CreateWindowEx(WS_EX_APPWINDOW, L"LevelMeshViewerWindow", L"ZDRay Viewer", WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_MAXIMIZE, applyDpi(100), applyDpi(50), applyDpi(1400), applyDpi(800), 0, 0, GetModuleHandle(nullptr), this);
|
||||
if (!WindowHandle)
|
||||
throw std::runtime_error("CreateWindowEx failed");
|
||||
}
|
||||
|
||||
void LevelMeshViewer::DestroyViewerWindow()
|
||||
{
|
||||
if (WindowHandle)
|
||||
DestroyWindow(WindowHandle);
|
||||
WindowHandle = 0;
|
||||
}
|
||||
|
||||
void LevelMeshViewer::OnClose()
|
||||
{
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
|
||||
LRESULT LevelMeshViewer::OnWindowMessage(UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
/*if (msg == WM_RBUTTONDOWN)
|
||||
{
|
||||
if (!MouseLocked)
|
||||
{
|
||||
GetCursorPos(&LockPosition);
|
||||
::ShowCursor(FALSE);
|
||||
|
||||
RECT box = {};
|
||||
GetClientRect(WindowHandle, &box);
|
||||
|
||||
POINT center = {};
|
||||
center.x = box.right / 2;
|
||||
center.y = box.bottom / 2;
|
||||
ClientToScreen(WindowHandle, ¢er);
|
||||
|
||||
SetCursorPos(center.x, center.y);
|
||||
MouseLocked = true;
|
||||
}
|
||||
}
|
||||
else if (msg == WM_RBUTTONUP)
|
||||
{
|
||||
if (MouseLocked)
|
||||
{
|
||||
MouseLocked = false;
|
||||
SetCursorPos(LockPosition.x, LockPosition.y);
|
||||
::ShowCursor(TRUE);
|
||||
}
|
||||
}
|
||||
else*/ if (msg == WM_MOUSEMOVE)
|
||||
{
|
||||
if (MouseLocked && GetFocus() != 0)
|
||||
{
|
||||
RECT box = {};
|
||||
GetClientRect(WindowHandle, &box);
|
||||
|
||||
POINT center = {};
|
||||
center.x = box.right / 2;
|
||||
center.y = box.bottom / 2;
|
||||
int mousex = GET_X_LPARAM(lparam) - center.x;
|
||||
int mousey = GET_Y_LPARAM(lparam) - center.y;
|
||||
|
||||
ClientToScreen(WindowHandle, ¢er);
|
||||
SetCursorPos(center.x, center.y);
|
||||
|
||||
double dpiscale = GetDpiScale();
|
||||
OnMouseMove(mousex / dpiscale, mousey / dpiscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetCursor((HCURSOR)LoadImage(0, IDC_ARROW, IMAGE_CURSOR, LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_SHARED));
|
||||
}
|
||||
}
|
||||
else if (msg == WM_SETFOCUS)
|
||||
{
|
||||
if (MouseLocked)
|
||||
{
|
||||
GetCursorPos(&LockPosition);
|
||||
::ShowCursor(FALSE);
|
||||
|
||||
RECT box = {};
|
||||
GetClientRect(WindowHandle, &box);
|
||||
|
||||
POINT center = {};
|
||||
center.x = box.right / 2;
|
||||
center.y = box.bottom / 2;
|
||||
ClientToScreen(WindowHandle, ¢er);
|
||||
|
||||
SetCursorPos(center.x, center.y);
|
||||
}
|
||||
}
|
||||
else if (msg == WM_KILLFOCUS)
|
||||
{
|
||||
if (MouseLocked)
|
||||
{
|
||||
SetCursorPos(LockPosition.x, LockPosition.y);
|
||||
::ShowCursor(TRUE);
|
||||
}
|
||||
}
|
||||
else if (msg == WM_CLOSE)
|
||||
{
|
||||
OnClose();
|
||||
return 0;
|
||||
}
|
||||
else if (msg == WM_KEYDOWN)
|
||||
{
|
||||
OnKeyDown(wparam);
|
||||
}
|
||||
else if (msg == WM_KEYUP)
|
||||
{
|
||||
OnKeyUp(wparam);
|
||||
}
|
||||
|
||||
return DefWindowProc(WindowHandle, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
double LevelMeshViewer::GetDpiScale() const
|
||||
{
|
||||
return GetDpiForWindow(WindowHandle) / 96.0;
|
||||
}
|
||||
|
||||
int LevelMeshViewer::GetPixelWidth() const
|
||||
{
|
||||
RECT box = {};
|
||||
GetClientRect(WindowHandle, &box);
|
||||
return box.right;
|
||||
}
|
||||
|
||||
int LevelMeshViewer::GetPixelHeight() const
|
||||
{
|
||||
RECT box = {};
|
||||
GetClientRect(WindowHandle, &box);
|
||||
return box.bottom;
|
||||
}
|
||||
|
||||
LRESULT LevelMeshViewer::WindowProc(HWND windowhandle, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
if (msg == WM_CREATE)
|
||||
{
|
||||
CREATESTRUCT* createstruct = (CREATESTRUCT*)lparam;
|
||||
LevelMeshViewer* viewport = (LevelMeshViewer*)createstruct->lpCreateParams;
|
||||
viewport->WindowHandle = windowhandle;
|
||||
SetWindowLongPtr(windowhandle, GWLP_USERDATA, (LONG_PTR)viewport);
|
||||
return viewport->OnWindowMessage(msg, wparam, lparam);
|
||||
}
|
||||
else
|
||||
{
|
||||
LevelMeshViewer* viewport = (LevelMeshViewer*)GetWindowLongPtr(windowhandle, GWLP_USERDATA);
|
||||
if (viewport)
|
||||
{
|
||||
LRESULT result = viewport->OnWindowMessage(msg, wparam, lparam);
|
||||
if (msg == WM_DESTROY)
|
||||
{
|
||||
SetWindowLongPtr(windowhandle, GWLP_USERDATA, 0);
|
||||
viewport->WindowHandle = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DefWindowProc(windowhandle, msg, wparam, lparam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
67
src/lightmapper/levelmeshviewer.h
Normal file
67
src/lightmapper/levelmeshviewer.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
#pragma once
|
||||
|
||||
#include "framework/vectors.h"
|
||||
|
||||
class VulkanRenderDevice;
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#define WIN32_MEAN_AND_LEAN
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
|
||||
class LevelMeshViewer
|
||||
{
|
||||
public:
|
||||
LevelMeshViewer();
|
||||
~LevelMeshViewer();
|
||||
|
||||
void Exec(VulkanRenderDevice* renderdevice, const FVector3& sundir, const FVector3& suncolor, float sunintensity);
|
||||
HWND GetWindowHandle() { return WindowHandle; }
|
||||
|
||||
private:
|
||||
void RenderFrame();
|
||||
|
||||
void OnMouseMove(double dx, double dy);
|
||||
void OnKeyDown(WPARAM key);
|
||||
void OnKeyUp(WPARAM key);
|
||||
void OnClose();
|
||||
|
||||
void CreateViewerWindow();
|
||||
void DestroyViewerWindow();
|
||||
|
||||
double GetDpiScale() const;
|
||||
int GetPixelWidth() const;
|
||||
int GetPixelHeight() const;
|
||||
|
||||
LRESULT OnWindowMessage(UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
|
||||
VulkanRenderDevice* RenderDevice = nullptr;
|
||||
HWND WindowHandle = 0;
|
||||
bool MouseLocked = true;
|
||||
POINT LockPosition = {};
|
||||
|
||||
double Yaw = 0.0;
|
||||
double Pitch = 0.0;
|
||||
|
||||
bool MoveLeft = false;
|
||||
bool MoveRight = false;
|
||||
bool MoveForward = false;
|
||||
bool MoveBackward = false;
|
||||
FVector3 CameraPos = FVector3(0.0f, 70.0f, -128.0f);
|
||||
FVector3 SunDir = FVector3(0.0f, 0.0f, 0.0f);
|
||||
FVector3 SunColor = FVector3(0.0f, 0.0f, 0.0f);
|
||||
float SunIntensity = 0.0f;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class LevelMeshViewer
|
||||
{
|
||||
public:
|
||||
LevelMeshViewer() { }
|
||||
void Exec(VulkanRenderDevice* renderdevice) { }
|
||||
};
|
||||
|
||||
#endif
|
|
@ -3,8 +3,21 @@
|
|||
#include "vk_levelmesh.h"
|
||||
#include "vk_lightmapper.h"
|
||||
#include "stacktrace.h"
|
||||
#include "levelmeshviewer.h"
|
||||
#include "framework/matrix.h"
|
||||
#include "glsl/vert_viewer.glsl.h"
|
||||
#include "glsl/frag_viewer.glsl.h"
|
||||
#include "glsl/binding_viewer.glsl.h"
|
||||
#include "glsl/polyfill_rayquery.glsl.h"
|
||||
#include "glsl/montecarlo.glsl.h"
|
||||
#include "glsl/trace_ambient_occlusion.glsl.h"
|
||||
#include "glsl/trace_bounce.glsl.h"
|
||||
#include "glsl/trace_levelmesh.glsl.h"
|
||||
#include "glsl/trace_light.glsl.h"
|
||||
#include "glsl/trace_sunlight.glsl.h"
|
||||
#include <zvulkan/vulkanbuilders.h>
|
||||
#include <zvulkan/vulkancompatibledevice.h>
|
||||
#include <zvulkan/vulkanswapchain.h>
|
||||
#include <stdexcept>
|
||||
|
||||
extern bool VKDebug;
|
||||
|
@ -21,16 +34,43 @@ void VulkanPrintLog(const char* typestr, const std::string& msg)
|
|||
printf(" %s\n", CaptureStackTraceText(2).c_str());
|
||||
}
|
||||
|
||||
VulkanRenderDevice::VulkanRenderDevice()
|
||||
VulkanRenderDevice::VulkanRenderDevice(LevelMeshViewer* viewer)
|
||||
{
|
||||
auto instance = VulkanInstanceBuilder()
|
||||
.DebugLayer(VKDebug)
|
||||
.Create();
|
||||
if (viewer)
|
||||
{
|
||||
#ifdef WIN32
|
||||
auto instance = VulkanInstanceBuilder()
|
||||
.RequireSurfaceExtensions()
|
||||
.DebugLayer(VKDebug)
|
||||
.Create();
|
||||
|
||||
device = VulkanDeviceBuilder()
|
||||
.OptionalRayQuery()
|
||||
.RequireExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME)
|
||||
.Create(instance);
|
||||
auto surface = VulkanSurfaceBuilder()
|
||||
.Win32Window(viewer->GetWindowHandle())
|
||||
.Create(instance);
|
||||
|
||||
device = VulkanDeviceBuilder()
|
||||
.Surface(surface)
|
||||
.OptionalRayQuery()
|
||||
.RequireExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME)
|
||||
.Create(instance);
|
||||
|
||||
swapchain = VulkanSwapChainBuilder()
|
||||
.Create(device.get());
|
||||
#else
|
||||
VulkanError("No viewer supported on this platform");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
auto instance = VulkanInstanceBuilder()
|
||||
.DebugLayer(VKDebug)
|
||||
.Create();
|
||||
|
||||
device = VulkanDeviceBuilder()
|
||||
.OptionalRayQuery()
|
||||
.RequireExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME)
|
||||
.Create(instance);
|
||||
}
|
||||
|
||||
useRayQuery = !NoRtx && device->PhysicalDevice.Features.RayQuery.rayQuery;
|
||||
|
||||
|
@ -44,6 +84,8 @@ VulkanRenderDevice::VulkanRenderDevice()
|
|||
descriptors->AddBindlessTextureIndex(GetTextureManager()->GetNullTextureView(), GetSamplerManager()->Get());
|
||||
descriptors->AddBindlessTextureIndex(GetTextureManager()->GetNullTextureView(), GetSamplerManager()->Get());
|
||||
descriptors->UpdateBindlessDescriptorSet();
|
||||
|
||||
CreateViewerObjects();
|
||||
}
|
||||
|
||||
VulkanRenderDevice::~VulkanRenderDevice()
|
||||
|
@ -51,6 +93,238 @@ VulkanRenderDevice::~VulkanRenderDevice()
|
|||
vkDeviceWaitIdle(device->device);
|
||||
}
|
||||
|
||||
void VulkanRenderDevice::DrawViewer(const FVector3& cameraPos, const VSMatrix& viewToWorld, float fovy, float aspect, const FVector3& sundir, const FVector3& suncolor, float sunintensity)
|
||||
{
|
||||
int imageIndex = GetCommands()->AcquireImage();
|
||||
if (imageIndex < 0)
|
||||
{
|
||||
Sleep(500);
|
||||
return;
|
||||
}
|
||||
|
||||
WriteDescriptors write;
|
||||
write.AddBuffer(Viewer.DescriptorSet.get(), 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, GetLevelMesh()->GetSurfaceIndexBuffer());
|
||||
write.AddBuffer(Viewer.DescriptorSet.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, GetLevelMesh()->GetSurfaceBuffer());
|
||||
write.AddBuffer(Viewer.DescriptorSet.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, GetLevelMesh()->GetLightBuffer());
|
||||
write.AddBuffer(Viewer.DescriptorSet.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, GetLevelMesh()->GetLightIndexBuffer());
|
||||
write.AddBuffer(Viewer.DescriptorSet.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, GetLevelMesh()->GetPortalBuffer());
|
||||
if (useRayQuery)
|
||||
{
|
||||
write.AddAccelerationStructure(Viewer.DescriptorSet.get(), 5, GetLevelMesh()->GetAccelStruct());
|
||||
}
|
||||
else
|
||||
{
|
||||
write.AddBuffer(Viewer.DescriptorSet.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, GetLevelMesh()->GetNodeBuffer());
|
||||
}
|
||||
write.AddBuffer(Viewer.DescriptorSet.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, GetLevelMesh()->GetVertexBuffer());
|
||||
write.AddBuffer(Viewer.DescriptorSet.get(), 7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, GetLevelMesh()->GetIndexBuffer());
|
||||
write.Execute(device.get());
|
||||
|
||||
auto commands = GetCommands()->GetDrawCommands();
|
||||
|
||||
RenderPassBegin()
|
||||
.RenderPass(Viewer.RenderPass.get())
|
||||
.Framebuffer(Framebuffers[imageIndex].get())
|
||||
.RenderArea(0, 0, CurrentWidth, CurrentHeight)
|
||||
.AddClearColor(0.0f, 0.0f, 0.0f, 1.0f)
|
||||
.AddClearDepth(1.0f)
|
||||
.Execute(commands);
|
||||
|
||||
VkViewport viewport = {};
|
||||
viewport.width = (float)CurrentWidth;
|
||||
viewport.height = (float)CurrentHeight;
|
||||
viewport.maxDepth = 1.0f;
|
||||
commands->setViewport(0, 1, &viewport);
|
||||
|
||||
VkRect2D scissor = {};
|
||||
scissor.extent.width = CurrentWidth;
|
||||
scissor.extent.height = CurrentHeight;
|
||||
commands->setScissor(0, 1, &scissor);
|
||||
|
||||
float f = 1.0f / std::tan(fovy * (pi::pif() / 360.0f));
|
||||
|
||||
ViewerPushConstants pushconstants;
|
||||
pushconstants.ViewToWorld = viewToWorld;
|
||||
pushconstants.CameraPos = cameraPos;
|
||||
pushconstants.ProjX = f / aspect;
|
||||
pushconstants.ProjY = f;
|
||||
pushconstants.SunDir = sundir;
|
||||
pushconstants.SunColor = suncolor;
|
||||
pushconstants.SunIntensity = sunintensity;
|
||||
|
||||
commands->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, Viewer.PipelineLayout.get(), 0, Viewer.DescriptorSet.get());
|
||||
commands->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, Viewer.PipelineLayout.get(), 1, descriptors->GetBindlessSet());
|
||||
commands->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, Viewer.Pipeline.get());
|
||||
commands->pushConstants(Viewer.PipelineLayout.get(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ViewerPushConstants), &pushconstants);
|
||||
commands->draw(4, 1, 0, 0);
|
||||
commands->endRenderPass();
|
||||
|
||||
GetCommands()->SubmitAndWait(imageIndex);
|
||||
}
|
||||
|
||||
static FString LoadPrivateShaderLump(const char* lumpname)
|
||||
{
|
||||
static std::map<FString, FString> sources =
|
||||
{
|
||||
{ "shaders/lightmap/binding_viewer.glsl", binding_viewer_glsl },
|
||||
{ "shaders/lightmap/montecarlo.glsl", montecarlo_glsl },
|
||||
{ "shaders/lightmap/polyfill_rayquery.glsl", polyfill_rayquery_glsl },
|
||||
{ "shaders/lightmap/trace_ambient_occlusion.glsl", trace_ambient_occlusion_glsl },
|
||||
{ "shaders/lightmap/trace_bounce.glsl", trace_bounce_glsl },
|
||||
{ "shaders/lightmap/trace_levelmesh.glsl", trace_levelmesh_glsl },
|
||||
{ "shaders/lightmap/trace_light.glsl", trace_light_glsl },
|
||||
{ "shaders/lightmap/trace_sunlight.glsl", trace_sunlight_glsl },
|
||||
};
|
||||
|
||||
auto it = sources.find(lumpname);
|
||||
if (it != sources.end())
|
||||
return it->second;
|
||||
else
|
||||
return FString();
|
||||
}
|
||||
|
||||
static FString LoadPublicShaderLump(const char* lumpname)
|
||||
{
|
||||
return LoadPrivateShaderLump(lumpname);
|
||||
}
|
||||
|
||||
static ShaderIncludeResult OnInclude(FString headerName, FString includerName, size_t depth, bool system)
|
||||
{
|
||||
if (depth > 8)
|
||||
{
|
||||
return ShaderIncludeResult("Too much include recursion!");
|
||||
}
|
||||
|
||||
FString includeguardname;
|
||||
includeguardname << "_HEADERGUARD_" << headerName.GetChars();
|
||||
includeguardname.ReplaceChars("/\\.", '_');
|
||||
|
||||
FString code;
|
||||
code << "#ifndef " << includeguardname.GetChars() << "\n";
|
||||
code << "#define " << includeguardname.GetChars() << "\n";
|
||||
code << "#line 1\n";
|
||||
|
||||
if (system)
|
||||
code << LoadPrivateShaderLump(headerName.GetChars()).GetChars() << "\n";
|
||||
else
|
||||
code << LoadPublicShaderLump(headerName.GetChars()).GetChars() << "\n";
|
||||
|
||||
code << "#endif\n";
|
||||
|
||||
return ShaderIncludeResult(headerName.GetChars(), code.GetChars());
|
||||
}
|
||||
|
||||
void VulkanRenderDevice::CreateViewerObjects()
|
||||
{
|
||||
DescriptorSetLayoutBuilder builder;
|
||||
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.AddBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.AddBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.AddBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
if (useRayQuery)
|
||||
{
|
||||
builder.AddBinding(5, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
}
|
||||
builder.AddBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.AddBinding(7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.DebugName("Viewer.DescriptorSetLayout");
|
||||
Viewer.DescriptorSetLayout = builder.Create(device.get());
|
||||
|
||||
Viewer.DescriptorPool = DescriptorPoolBuilder()
|
||||
.AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1)
|
||||
.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 6)
|
||||
.MaxSets(1)
|
||||
.DebugName("Viewer.DescriptorPool")
|
||||
.Create(device.get());
|
||||
|
||||
Viewer.DescriptorSet = Viewer.DescriptorPool->allocate(Viewer.DescriptorSetLayout.get());
|
||||
Viewer.DescriptorSet->SetDebugName("raytrace.descriptorSet1");
|
||||
|
||||
std::string versionBlock = R"(
|
||||
#version 460
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
#extension GL_EXT_nonuniform_qualifier : enable
|
||||
)";
|
||||
|
||||
if (useRayQuery)
|
||||
{
|
||||
versionBlock += "#extension GL_EXT_ray_query : require\r\n";
|
||||
versionBlock += "#define USE_RAYQUERY\r\n";
|
||||
}
|
||||
|
||||
auto onIncludeLocal = [](std::string headerName, std::string includerName, size_t depth) { return OnInclude(headerName.c_str(), includerName.c_str(), depth, false); };
|
||||
auto onIncludeSystem = [](std::string headerName, std::string includerName, size_t depth) { return OnInclude(headerName.c_str(), includerName.c_str(), depth, true); };
|
||||
|
||||
Viewer.VertexShader = ShaderBuilder()
|
||||
.Type(ShaderType::Vertex)
|
||||
.AddSource("versionblock", versionBlock)
|
||||
.AddSource("vert_viewer.glsl", vert_viewer_glsl)
|
||||
.OnIncludeLocal(onIncludeLocal)
|
||||
.OnIncludeSystem(onIncludeSystem)
|
||||
.DebugName("Viewer.VertexShader")
|
||||
.Create("vertex", device.get());
|
||||
|
||||
Viewer.FragmentShader = ShaderBuilder()
|
||||
.Type(ShaderType::Fragment)
|
||||
.AddSource("versionblock", versionBlock)
|
||||
.AddSource("frag_viewer.glsl", frag_viewer_glsl)
|
||||
.OnIncludeLocal(onIncludeLocal)
|
||||
.OnIncludeSystem(onIncludeSystem)
|
||||
.DebugName("Viewer.FragmentShader")
|
||||
.Create("vertex", device.get());
|
||||
|
||||
Viewer.PipelineLayout = PipelineLayoutBuilder()
|
||||
.AddSetLayout(Viewer.DescriptorSetLayout.get())
|
||||
.AddSetLayout(descriptors->GetBindlessLayout())
|
||||
.AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ViewerPushConstants))
|
||||
.DebugName("Viewer.PipelineLayout")
|
||||
.Create(device.get());
|
||||
|
||||
Viewer.RenderPass = RenderPassBuilder()
|
||||
.AddAttachment(VK_FORMAT_B8G8R8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
|
||||
.AddSubpass()
|
||||
.AddSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
|
||||
.Create(device.get());
|
||||
|
||||
Viewer.Pipeline = GraphicsPipelineBuilder()
|
||||
.RenderPass(Viewer.RenderPass.get())
|
||||
.Layout(Viewer.PipelineLayout.get())
|
||||
.Topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
|
||||
.AddVertexShader(Viewer.VertexShader.get())
|
||||
.AddFragmentShader(Viewer.FragmentShader.get())
|
||||
.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT)
|
||||
.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR)
|
||||
.DebugName("Viewer.Pipeline")
|
||||
.Create(device.get());
|
||||
}
|
||||
|
||||
void VulkanRenderDevice::ResizeSwapChain(int width, int height)
|
||||
{
|
||||
if (width <= 0 || height <= 0 || (width == CurrentWidth && height == CurrentHeight && swapchain->Lost()))
|
||||
return;
|
||||
|
||||
CurrentWidth = width;
|
||||
CurrentHeight = height;
|
||||
Framebuffers.clear();
|
||||
|
||||
swapchain->Create(width, height, 1, true, false, false);
|
||||
|
||||
for (int imageIndex = 0; imageIndex < swapchain->ImageCount(); imageIndex++)
|
||||
{
|
||||
Framebuffers.push_back(FramebufferBuilder()
|
||||
.RenderPass(Viewer.RenderPass.get())
|
||||
.AddAttachment(swapchain->GetImageView(imageIndex))
|
||||
.Size(width, height)
|
||||
.DebugName("framebuffer")
|
||||
.Create(GetDevice()));
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkCommandBufferManager::VkCommandBufferManager(VulkanRenderDevice* fb) : fb(fb)
|
||||
|
@ -59,9 +333,26 @@ VkCommandBufferManager::VkCommandBufferManager(VulkanRenderDevice* fb) : fb(fb)
|
|||
.QueueFamily(fb->GetDevice()->GraphicsFamily)
|
||||
.DebugName("mCommandPool")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
mImageAvailableSemaphore = SemaphoreBuilder()
|
||||
.DebugName("mImageAvailableSemaphore")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
mRenderFinishedSemaphore = SemaphoreBuilder()
|
||||
.DebugName("mRenderFinishedSemaphore")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
mPresentFinishedFence = FenceBuilder()
|
||||
.DebugName("mPresentFinishedFence")
|
||||
.Create(fb->GetDevice());
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::SubmitAndWait()
|
||||
int VkCommandBufferManager::AcquireImage()
|
||||
{
|
||||
return fb->GetSwapChain()->AcquireImage(mImageAvailableSemaphore.get());
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::SubmitAndWait(int imageIndex)
|
||||
{
|
||||
if (mTransferCommands)
|
||||
{
|
||||
|
@ -76,6 +367,24 @@ void VkCommandBufferManager::SubmitAndWait()
|
|||
vkDeviceWaitIdle(fb->GetDevice()->device);
|
||||
}
|
||||
|
||||
if (imageIndex >= 0 && mDrawCommands)
|
||||
{
|
||||
mDrawCommands->end();
|
||||
|
||||
QueueSubmit()
|
||||
.AddCommandBuffer(mDrawCommands.get())
|
||||
.AddWait(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mImageAvailableSemaphore.get())
|
||||
.AddSignal(mRenderFinishedSemaphore.get())
|
||||
.Execute(fb->GetDevice(), fb->GetDevice()->GraphicsQueue, mPresentFinishedFence.get());
|
||||
|
||||
DrawDeleteList->Add(std::move(mDrawCommands));
|
||||
|
||||
fb->GetSwapChain()->QueuePresent(imageIndex, mRenderFinishedSemaphore.get());
|
||||
|
||||
vkWaitForFences(fb->GetDevice()->device, 1, &mPresentFinishedFence->fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
|
||||
vkResetFences(fb->GetDevice()->device, 1, &mPresentFinishedFence->fence);
|
||||
}
|
||||
|
||||
TransferDeleteList = std::make_unique<DeleteList>();
|
||||
DrawDeleteList = std::make_unique<DeleteList>();
|
||||
}
|
||||
|
@ -90,6 +399,16 @@ VulkanCommandBuffer* VkCommandBufferManager::GetTransferCommands()
|
|||
return mTransferCommands.get();
|
||||
}
|
||||
|
||||
VulkanCommandBuffer* VkCommandBufferManager::GetDrawCommands()
|
||||
{
|
||||
if (!mDrawCommands)
|
||||
{
|
||||
mDrawCommands = mCommandPool->createBuffer();
|
||||
mDrawCommands->begin();
|
||||
}
|
||||
return mDrawCommands.get();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkTextureManager::VkTextureManager(VulkanRenderDevice* fb) : fb(fb)
|
||||
|
@ -102,7 +421,7 @@ void VkTextureManager::CreateNullTexture()
|
|||
NullTexture = ImageBuilder()
|
||||
.Format(VK_FORMAT_R8G8B8A8_UNORM)
|
||||
.Size(1, 1)
|
||||
.Usage(VK_IMAGE_USAGE_SAMPLED_BIT)
|
||||
.Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)
|
||||
.DebugName("VkTextureManager.NullTexture")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
|
@ -124,7 +443,7 @@ void VkTextureManager::CreateNullTexture()
|
|||
|
||||
PipelineBarrier()
|
||||
.AddImage(NullTexture.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
@ -138,7 +457,7 @@ void VkTextureManager::CreateNullTexture()
|
|||
|
||||
PipelineBarrier()
|
||||
.AddImage(NullTexture.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
|
||||
void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCount)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "framework/textureid.h"
|
||||
#include "zvulkan/vulkanobjects.h"
|
||||
#include "zvulkan/vulkanbuilders.h"
|
||||
#include "framework/matrix.h"
|
||||
#include <stdexcept>
|
||||
|
||||
class VkLevelMesh;
|
||||
|
@ -12,14 +13,18 @@ class VkCommandBufferManager;
|
|||
class VkDescriptorSetManager;
|
||||
class VkTextureManager;
|
||||
class VkSamplerManager;
|
||||
class VulkanSwapChain;
|
||||
class LevelMeshViewer;
|
||||
class VSMatrix;
|
||||
|
||||
class VulkanRenderDevice
|
||||
{
|
||||
public:
|
||||
VulkanRenderDevice();
|
||||
VulkanRenderDevice(LevelMeshViewer* viewer);
|
||||
~VulkanRenderDevice();
|
||||
|
||||
VulkanDevice* GetDevice() { return device.get(); }
|
||||
VulkanSwapChain* GetSwapChain() { return swapchain.get(); }
|
||||
VkCommandBufferManager* GetCommands() { return commands.get(); }
|
||||
VkDescriptorSetManager* GetDescriptorSetManager() { return descriptors.get(); }
|
||||
VkTextureManager* GetTextureManager() { return textures.get(); }
|
||||
|
@ -31,16 +36,38 @@ public:
|
|||
|
||||
bool IsRayQueryEnabled() const { return useRayQuery; }
|
||||
|
||||
void ResizeSwapChain(int width, int height);
|
||||
void DrawViewer(const FVector3& cameraPos, const VSMatrix& viewToWorld, float fovy, float aspect, const FVector3& sundir, const FVector3& suncolor, float sunintensity);
|
||||
|
||||
bool useRayQuery = false;
|
||||
|
||||
private:
|
||||
void CreateViewerObjects();
|
||||
|
||||
std::shared_ptr<VulkanDevice> device;
|
||||
std::shared_ptr<VulkanSwapChain> swapchain;
|
||||
std::unique_ptr<VkCommandBufferManager> commands;
|
||||
std::unique_ptr<VkDescriptorSetManager> descriptors;
|
||||
std::unique_ptr<VkTextureManager> textures;
|
||||
std::unique_ptr<VkSamplerManager> samplers;
|
||||
std::unique_ptr<VkLevelMesh> levelmesh;
|
||||
std::unique_ptr<VkLightmapper> lightmapper;
|
||||
|
||||
struct
|
||||
{
|
||||
std::unique_ptr<VulkanDescriptorSetLayout> DescriptorSetLayout;
|
||||
std::unique_ptr<VulkanDescriptorPool> DescriptorPool;
|
||||
std::unique_ptr<VulkanDescriptorSet> DescriptorSet;
|
||||
std::unique_ptr<VulkanShader> VertexShader;
|
||||
std::unique_ptr<VulkanShader> FragmentShader;
|
||||
std::unique_ptr<VulkanRenderPass> RenderPass;
|
||||
std::unique_ptr<VulkanPipelineLayout> PipelineLayout;
|
||||
std::unique_ptr<VulkanPipeline> Pipeline;
|
||||
} Viewer;
|
||||
|
||||
int CurrentWidth = 0;
|
||||
int CurrentHeight = 0;
|
||||
std::vector<std::unique_ptr<VulkanFramebuffer>> Framebuffers;
|
||||
};
|
||||
|
||||
class VkCommandBufferManager
|
||||
|
@ -48,13 +75,16 @@ class VkCommandBufferManager
|
|||
public:
|
||||
VkCommandBufferManager(VulkanRenderDevice* fb);
|
||||
|
||||
void SubmitAndWait();
|
||||
void SubmitAndWait(int imageIndex = -1);
|
||||
|
||||
VulkanCommandBuffer* GetTransferCommands();
|
||||
VulkanCommandBuffer* GetDrawCommands();
|
||||
|
||||
void PushGroup(VulkanCommandBuffer* cmdbuffer, const FString& name) { }
|
||||
void PopGroup(VulkanCommandBuffer* cmdbuffer) { }
|
||||
|
||||
int AcquireImage();
|
||||
|
||||
class DeleteList
|
||||
{
|
||||
public:
|
||||
|
@ -90,6 +120,20 @@ private:
|
|||
std::unique_ptr<VulkanCommandPool> mCommandPool;
|
||||
std::unique_ptr<VulkanCommandBuffer> mTransferCommands;
|
||||
std::unique_ptr<VulkanCommandBuffer> mDrawCommands;
|
||||
std::unique_ptr<VulkanSemaphore> mImageAvailableSemaphore;
|
||||
std::unique_ptr<VulkanSemaphore> mRenderFinishedSemaphore;
|
||||
std::unique_ptr<VulkanFence> mPresentFinishedFence;
|
||||
};
|
||||
|
||||
struct ViewerPushConstants
|
||||
{
|
||||
VSMatrix ViewToWorld;
|
||||
FVector3 CameraPos;
|
||||
float ProjX;
|
||||
FVector3 SunDir;
|
||||
float ProjY;
|
||||
FVector3 SunColor;
|
||||
float SunIntensity;
|
||||
};
|
||||
|
||||
class VkTextureImage
|
||||
|
|
|
@ -118,6 +118,7 @@ int LMDims = 1024;
|
|||
bool VKDebug = false;
|
||||
bool DumpMesh = false;
|
||||
bool NoRtx = false;
|
||||
bool showviewer = false;
|
||||
|
||||
int ambientSampleCount = 2048;
|
||||
|
||||
|
@ -160,10 +161,11 @@ static option long_opts[] =
|
|||
{"dump-mesh", no_argument, 0, 1004},
|
||||
{"preview", no_argument, 0, 1005},
|
||||
{"no-rtx", no_argument, 0, 1006},
|
||||
{"viewer", no_argument, 0, 1007},
|
||||
{0,0,0,0}
|
||||
};
|
||||
|
||||
static const char short_opts[] = "wVgGvbNrReEm:o:f:p:s:d:PqtzZXx5cj:S:D:::";
|
||||
static const char short_opts[] = "wVgGvbNrReEm:o:f:p:s:d:PqtzZXx5cj:S:D::::";
|
||||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
||||
|
@ -480,6 +482,9 @@ static void ParseArgs(int argc, char **argv)
|
|||
case 1006:
|
||||
NoRtx = true;
|
||||
break;
|
||||
case 1007:
|
||||
showviewer = true;
|
||||
break;
|
||||
case 1000:
|
||||
ShowUsage();
|
||||
exit(0);
|
||||
|
|
Loading…
Reference in a new issue