From c8de306c02a92292fcb7f21f37eaa959301f5f36 Mon Sep 17 00:00:00 2001 From: Gustav Sterbrant Date: Fri, 16 Aug 2024 18:53:06 +0200 Subject: [PATCH] Batchgroup from material templates (#219) --- code/addons/dynui/im3d/im3dcontext.cc | 42 +- code/addons/dynui/im3d/im3dcontext.h | 3 - code/addons/dynui/im3d/shaders/im3d.fx | 6 +- code/addons/dynui/imguicontext.cc | 153 +- code/addons/dynui/imguicontext.h | 17 +- .../graphicsfeature/graphicsfeatureunit.cc | 81 +- .../graphicsfeature/graphicsfeatureunit.h | 6 +- code/addons/staticui/staticuicontext.cc | 19 +- code/foundation/memory/posix/posixmemory.h | 1 + code/foundation/memory/win32/win32memory.h | 1 + code/foundation/util/keyvaluepair.h | 1 - code/foundation/util/string.h | 54 +- code/render/CMakeLists.txt | 108 +- code/render/clustering/clustercontext.cc | 22 +- code/render/coregraphics/barrier.h | 70 +- code/render/coregraphics/batchgroup.cc | 57 - code/render/coregraphics/batchgroup.h | 59 - code/render/coregraphics/commandbuffer.h | 27 +- code/render/coregraphics/config.h | 49 +- code/render/coregraphics/graphicsdevice.h | 14 +- code/render/coregraphics/pass.h | 15 +- code/render/coregraphics/pixelformat.cc | 48 +- code/render/coregraphics/pixelformat.h | 5 + code/render/coregraphics/semaphore.h | 5 +- code/render/coregraphics/swapchain.h | 5 + code/render/coregraphics/texture.cc | 4 +- code/render/coregraphics/texture.h | 8 +- code/render/coregraphics/vk/vkbarrier.cc | 12 +- .../render/coregraphics/vk/vkcommandbuffer.cc | 68 +- .../coregraphics/vk/vkgraphicsdevice.cc | 266 ++- code/render/coregraphics/vk/vkloader.cc | 2 +- code/render/coregraphics/vk/vkloader.h | 5 + code/render/coregraphics/vk/vkpass.cc | 84 +- code/render/coregraphics/vk/vkpass.h | 10 +- .../render/coregraphics/vk/vkresourcetable.cc | 2 - code/render/coregraphics/vk/vksemaphore.cc | 18 +- .../render/coregraphics/vk/vkshaperenderer.cc | 10 +- code/render/coregraphics/vk/vkshaperenderer.h | 2 - .../coregraphics/vk/vksubcontexthandler.cc | 383 ++--- .../coregraphics/vk/vksubcontexthandler.h | 57 +- code/render/coregraphics/vk/vkswapchain.cc | 90 +- code/render/coregraphics/vk/vkswapchain.h | 8 +- code/render/coregraphics/vk/vktexture.cc | 23 +- code/render/coregraphics/vk/vktextureview.cc | 2 +- code/render/coregraphics/vk/vktypes.cc | 22 +- code/render/coregraphics/vk/vktypes.h | 2 - code/render/decals/decalcontext.cc | 97 +- code/render/fog/volumetricfogcontext.cc | 181 +- code/render/fog/volumetricfogcontext.h | 2 +- code/render/frame/default.json | 753 +++++++++ code/render/frame/default.json.h | 0 code/render/frame/default.yml | 397 +++++ code/render/frame/frameblit.cc | 14 +- code/render/frame/framecopy.cc | 16 +- code/render/frame/frameresolve.cc | 11 +- code/render/frame/framescript.h | 1 + code/render/frame/framescriptloader.cc | 10 +- code/render/frame/framesubmission.cc | 2 +- code/render/frame/framesubpassbatch.cc | 8 +- code/render/frame/framesubpassbatch.h | 10 +- .../frame/framesubpassfullscreeneffect.cc | 1 + code/render/frame/framesubpassorderedbatch.h | 5 +- code/render/frame/shadows.json | 105 ++ code/render/framescripts/framescripts.cc | 198 +++ code/render/framescripts/framescripts.h | 47 + .../glfw/glfwgraphicsdisplayeventhandler.cc | 7 - code/render/graphics/globalconstants.cc | 12 +- code/render/graphics/globalconstants.h | 2 +- code/render/graphics/graphicsserver.cc | 91 +- code/render/graphics/graphicsserver.h | 81 +- code/render/graphics/view.cc | 14 +- code/render/graphics/view.h | 37 +- code/render/lighting/csmutil.h | 8 +- code/render/lighting/lightcontext.cc | 213 +-- code/render/lighting/lightcontext.h | 4 +- code/render/materials/material.cc | 4 +- code/render/materials/material.h | 7 +- code/render/materials/materialtemplatetypes.h | 5 +- code/render/materials/shaderconfig.h | 29 - code/render/models/modelcontext.cc | 4 +- code/render/models/modelcontext.h | 4 +- code/render/models/nodes/shaderstatenode.cc | 6 +- code/render/models/nodes/shaderstatenode.h | 15 +- code/render/posteffects/bloomcontext.cc | 149 +- code/render/posteffects/bloomcontext.h | 2 +- .../render/posteffects/downsamplingcontext.cc | 133 +- code/render/posteffects/downsamplingcontext.h | 2 +- code/render/posteffects/histogramcontext.cc | 101 +- code/render/posteffects/histogramcontext.h | 2 +- code/render/posteffects/ssaocontext.cc | 140 +- code/render/posteffects/ssaocontext.h | 2 +- code/render/posteffects/ssrcontext.cc | 10 +- code/render/raytracing/raytracingcontext.cc | 106 +- code/render/raytracing/raytracingcontext.h | 1 - code/render/renderutil/drawfullscreenquad.cc | 2 - code/render/terrain/shaders/terrain.fx | 21 +- code/render/terrain/terraincontext.cc | 237 +-- code/render/vegetation/vegetationcontext.cc | 180 +- code/render/visibility/visibilitycontext.cc | 9 +- fips-files/generators/framescriptc.py | 1476 +++++++++++++++++ fips-files/generators/materialtemplatec.py | 160 +- fips-files/include.cmake | 66 +- syswork/frame/win32/vkdefault.json | 7 +- syswork/shaders/vk/bloom.fx | 68 +- syswork/shaders/vk/blur/blur_cs.fxh | 43 +- syswork/shaders/vk/finalize.fx | 10 +- syswork/shaders/vk/lib/geometrybase.fxh | 10 +- syswork/shaders/vk/lib/lighting_functions.fxh | 6 +- syswork/shaders/vk/lib/shadowbase.fxh | 17 + syswork/shaders/vk/lib/shared.fxh | 8 +- syswork/shaders/vk/lib/util.fxh | 4 +- syswork/shaders/vk/particle.fx | 8 +- syswork/shaders/vk/shapes.fx | 4 +- tests/testrender/rendertest.cc | 4 +- tests/testviewer/scenes/clusteredlighting.cpp | 7 +- tests/testviewer/viewerapp.cc | 26 +- tests/testvisibility/visibilitytest.cc | 13 +- toolkit/editor/CMakeLists.txt | 1 + toolkit/editor/editor/tools/camera.cc | 14 + toolkit/editor/editor/tools/camera.h | 3 + toolkit/editor/editor/ui/modules/viewport.cc | 28 +- toolkit/editor/editor/ui/uimanager.cc | 22 +- .../asseteditor/materialasseteditor.cc | 2 + toolkit/editor/render/editorframe.json | 68 + .../model/import/fbx/node/nfbxmeshnode.cc | 1 + 125 files changed, 5097 insertions(+), 2423 deletions(-) delete mode 100644 code/render/coregraphics/batchgroup.cc delete mode 100644 code/render/coregraphics/batchgroup.h create mode 100644 code/render/frame/default.json create mode 100644 code/render/frame/default.json.h create mode 100644 code/render/frame/default.yml create mode 100644 code/render/frame/shadows.json create mode 100644 code/render/framescripts/framescripts.cc create mode 100644 code/render/framescripts/framescripts.h create mode 100644 fips-files/generators/framescriptc.py create mode 100644 toolkit/editor/render/editorframe.json diff --git a/code/addons/dynui/im3d/im3dcontext.cc b/code/addons/dynui/im3d/im3dcontext.cc index 670dd99362..aed814e462 100644 --- a/code/addons/dynui/im3d/im3dcontext.cc +++ b/code/addons/dynui/im3d/im3dcontext.cc @@ -22,6 +22,8 @@ #include "frame/framecode.h" #include "imgui.h" +#include "frame/default.h" + using namespace Math; using namespace CoreGraphics; using namespace Graphics; @@ -106,8 +108,6 @@ struct Im3dState Ptr inputHandler; Im3d::Id depthLayerId; byte* vertexPtr; - - Memory::ArenaAllocator frameOpAllocator; }; static Im3dState imState; @@ -167,35 +167,34 @@ Im3dContext::Create() // map buffer imState.vertexPtr = (byte*)CoreGraphics::BufferMap(imState.vbo); - Frame::FrameCode* op = imState.frameOpAllocator.Alloc(); - op->domain = CoreGraphics::BarrierDomain::Pass; - op->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_Im3D_Pass([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { Render(cmdBuf, frame); - }; - op->buildFunc = [](const CoreGraphics::PassId pass, const uint subpass) + }); + FrameScript_default::RegisterSubgraphPipelines_Im3D_Pass([](const CoreGraphics::PassId pass, const uint subpass) { if (imState.linesPipeline != CoreGraphics::InvalidPipelineId) CoreGraphics::DestroyGraphicsPipeline(imState.linesPipeline); - imState.linesPipeline = CoreGraphics::CreateGraphicsPipeline({ imState.lines, pass, subpass, CoreGraphics::InputAssemblyKey{CoreGraphics::PrimitiveTopology::LineList, false} }); + imState.linesPipeline = CoreGraphics::CreateGraphicsPipeline({ imState.lines, pass, subpass, CoreGraphics::InputAssemblyKey{ CoreGraphics::PrimitiveTopology::LineList, false } }); if (imState.depthLinesPipeline != CoreGraphics::InvalidPipelineId) CoreGraphics::DestroyGraphicsPipeline(imState.depthLinesPipeline); - imState.depthLinesPipeline = CoreGraphics::CreateGraphicsPipeline({ imState.depthLines, pass, subpass, CoreGraphics::InputAssemblyKey{CoreGraphics::PrimitiveTopology::LineList, false} }); + imState.depthLinesPipeline = CoreGraphics::CreateGraphicsPipeline({ imState.depthLines, pass, subpass, CoreGraphics::InputAssemblyKey{ CoreGraphics::PrimitiveTopology::LineList, false } }); if (imState.trianglesPipeline != CoreGraphics::InvalidPipelineId) CoreGraphics::DestroyGraphicsPipeline(imState.trianglesPipeline); - imState.trianglesPipeline = CoreGraphics::CreateGraphicsPipeline({ imState.triangles, pass, subpass, CoreGraphics::InputAssemblyKey{CoreGraphics::PrimitiveTopology::TriangleList, false} }); + imState.trianglesPipeline = CoreGraphics::CreateGraphicsPipeline({ imState.triangles, pass, subpass, CoreGraphics::InputAssemblyKey{ CoreGraphics::PrimitiveTopology::TriangleList, false } }); if (imState.depthTrianglesPipeline != CoreGraphics::InvalidPipelineId) CoreGraphics::DestroyGraphicsPipeline(imState.depthTrianglesPipeline); - imState.depthTrianglesPipeline = CoreGraphics::CreateGraphicsPipeline({ imState.depthTriangles, pass, subpass, CoreGraphics::InputAssemblyKey{CoreGraphics::PrimitiveTopology::TriangleList, false} }); + imState.depthTrianglesPipeline = CoreGraphics::CreateGraphicsPipeline({ imState.depthTriangles, pass, subpass, CoreGraphics::InputAssemblyKey{ CoreGraphics::PrimitiveTopology::TriangleList, false } }); if (imState.pointsPipeline != CoreGraphics::InvalidPipelineId) CoreGraphics::DestroyGraphicsPipeline(imState.pointsPipeline); - imState.pointsPipeline = CoreGraphics::CreateGraphicsPipeline({ imState.points, pass, subpass, CoreGraphics::InputAssemblyKey{CoreGraphics::PrimitiveTopology::PointList, false} }); - }; - Frame::AddSubgraph("Im3D", { op }); + imState.pointsPipeline = CoreGraphics::CreateGraphicsPipeline({ imState.points, pass, subpass, CoreGraphics::InputAssemblyKey{ CoreGraphics::PrimitiveTopology::PointList, false } }); + }); + Im3d::NewFrame(); + } //------------------------------------------------------------------------------ @@ -204,7 +203,6 @@ Im3dContext::Create() void Im3dContext::Discard() { - imState.frameOpAllocator.Release(); Input::InputServer::Instance()->RemoveInputHandler(imState.inputHandler.upcast()); imState.inputHandler = nullptr; CoreGraphics::BufferUnmap(imState.vbo); @@ -368,14 +366,6 @@ Im3dContext::DrawSphere(const Math::point& pos, float radius, const Math::vec4& Im3d::PopDrawState(); } -//------------------------------------------------------------------------------ -/** -*/ -void -Im3dContext::NewFrame(const Graphics::FrameContext& ctx) -{ - Im3d::NewFrame(); -} //------------------------------------------------------------------------------ /** @@ -385,10 +375,11 @@ Im3dContext::OnPrepareView(const Ptr& view, const Graphics::Fram { AppData& ad = GetAppData(); + const Math::rectangle& viewport = view->GetViewport(); + ad.m_deltaTime = ctx.frameTime; SetGizmoSize(128, 4); - auto const & mode = CoreGraphics::WindowGetDisplayMode(CurrentWindow); - ad.m_viewportSize = Vec2((float)mode.GetWidth(), (float)mode.GetHeight()); + ad.m_viewportSize = Vec2((float)viewport.width(), (float)viewport.height()); Graphics::GraphicsEntityId cam = view->GetCamera(); Math::mat4 transform = inverse(CameraContext::GetView(cam)); @@ -535,6 +526,7 @@ Im3dContext::Render(const CoreGraphics::CmdBufferId cmdBuf, const IndexT frameIn [](Im3d::DrawList const& l) { return l.m_primType == Im3d::DrawPrimitive_Triangles && l.m_layerId == imState.depthLayerId; }); CoreGraphics::BufferFlush(imState.vbo); + Im3d::NewFrame(); } //------------------------------------------------------------------------------ diff --git a/code/addons/dynui/im3d/im3dcontext.h b/code/addons/dynui/im3d/im3dcontext.h index 6976155a8c..7bfc282034 100644 --- a/code/addons/dynui/im3d/im3dcontext.h +++ b/code/addons/dynui/im3d/im3dcontext.h @@ -59,9 +59,6 @@ class Im3dContext : public Graphics::GraphicsContext /// draw a cone static void DrawCone(const Math::mat4& modelTransform, const Math::vec4& color, uint32_t renderFlags = CheckDepth | Wireframe); - /// Start a new Im3d frame - static void NewFrame(const Graphics::FrameContext& ctx); - /// called before frame static void OnPrepareView(const Ptr& view, const Graphics::FrameContext& ctx); /// called when rendering a frame batch diff --git a/code/addons/dynui/im3d/shaders/im3d.fx b/code/addons/dynui/im3d/shaders/im3d.fx index a79f1b8b7e..215aeb2269 100644 --- a/code/addons/dynui/im3d/shaders/im3d.fx +++ b/code/addons/dynui/im3d/shaders/im3d.fx @@ -108,10 +108,10 @@ gsMain( vec2 pos1 = gl_in[1].gl_Position.xy / gl_in[1].gl_Position.w; vec2 dir = pos0 - pos1; - dir = normalize(vec2(dir.x, dir.y * RenderTargetDimensions[0].y * RenderTargetDimensions[0].z)); // correct for aspect ratio + dir = normalize(vec2(dir.x, dir.y * RenderTargetParameter[0].Dimensions.y * RenderTargetParameter[0].Dimensions.z)); // correct for aspect ratio vec2 tng0 = vec2(-dir.y, dir.x); - vec2 tng1 = tng0 * size[1] * RenderTargetDimensions[0].zw; - tng0 = tng0 * size[0] * RenderTargetDimensions[0].zw; + vec2 tng1 = tng0 * size[1] * RenderTargetParameter[0].Dimensions.zw; + tng0 = tng0 * size[0] * RenderTargetParameter[0].Dimensions.zw; // line start gl_Position = vec4((pos0 - tng0) * gl_in[0].gl_Position.w, gl_in[0].gl_Position.zw); diff --git a/code/addons/dynui/imguicontext.cc b/code/addons/dynui/imguicontext.cc index efe95513cb..fc59182b0a 100644 --- a/code/addons/dynui/imguicontext.cc +++ b/code/addons/dynui/imguicontext.cc @@ -17,6 +17,11 @@ #include "frame/framesubgraph.h" #include "core/cvar.h" +#include "frame/default.h" +#if WITH_NEBULA_EDITOR +#include "frame/editorframe.h" +#endif + using namespace Math; using namespace CoreGraphics; using namespace Base; @@ -33,22 +38,25 @@ static Core::CVar* ui_opacity; Imgui rendering function */ void -ImguiContext::ImguiDrawFunction(const CoreGraphics::CmdBufferId cmdBuf) +ImguiDrawFunction(const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport +#if WITH_NEBULA_EDITOR + , bool editor = false +#endif +) { ImDrawData* data = ImGui::GetDrawData(); // get Imgui context ImGuiIO& io = ImGui::GetIO(); - int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x); - int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y); + int fb_width = (int)(viewport.width() * io.DisplayFramebufferScale.x); + int fb_height = (int)(viewport.height() * io.DisplayFramebufferScale.y); data->ScaleClipRects(io.DisplayFramebufferScale); // get renderer //const Ptr& vboLock = renderer->GetVertexBufferLock(); //const Ptr& iboLock = renderer->GetIndexBufferLock(); IndexT currentBuffer = CoreGraphics::GetBufferedFrameIndex(); - BufferId vbo = state.vbos[currentBuffer]; - BufferId ibo = state.ibos[currentBuffer]; - const ImguiRendererParams& params = state.params; + BufferId vbo = ImguiContext::state.vbos[currentBuffer]; + BufferId ibo = ImguiContext::state.ibos[currentBuffer]; N_CMD_SCOPE(cmdBuf, NEBULA_MARKER_GRAPHICS, "ImGUI"); @@ -57,33 +65,33 @@ ImguiContext::ImguiDrawFunction(const CoreGraphics::CmdBufferId cmdBuf) // create orthogonal matrix #if __VULKAN__ - mat4 proj = orthooffcenterrh(0.0f, io.DisplaySize.x, io.DisplaySize.y, 0.0f, -1.0f, +1.0f); + mat4 proj = orthooffcenterrh(0.0f, viewport.width(), viewport.height(), 0.0f, -1.0f, +1.0f); #else - mat4 proj = orthooffcenterrh(0.0f, io.DisplaySize.x, 0.0f, io.DisplaySize.y, -1.0f, +1.0f); + mat4 proj = orthooffcenterrh(0.0f, viewport.width(), 0.0f, viewport.height(), -1.0f, +1.0f); #endif // if buffers are too small, create new buffers - if (data->TotalVtxCount > CoreGraphics::BufferGetSize(state.vbos[currentBuffer])) + if (data->TotalVtxCount > CoreGraphics::BufferGetSize(ImguiContext::state.vbos[currentBuffer])) { - CoreGraphics::BufferUnmap(state.vbos[currentBuffer]); - CoreGraphics::DestroyBuffer(state.vbos[currentBuffer]); + CoreGraphics::BufferUnmap(ImguiContext::state.vbos[currentBuffer]); + CoreGraphics::DestroyBuffer(ImguiContext::state.vbos[currentBuffer]); CoreGraphics::BufferCreateInfo vboInfo; vboInfo.name = "ImGUI VBO"_atm; vboInfo.size = Math::roundtopow2(data->TotalVtxCount); - vboInfo.elementSize = CoreGraphics::VertexLayoutGetSize(state.vlo); + vboInfo.elementSize = CoreGraphics::VertexLayoutGetSize(ImguiContext::state.vlo); vboInfo.mode = CoreGraphics::HostCached; vboInfo.usageFlags = CoreGraphics::VertexBuffer; vboInfo.data = nullptr; vboInfo.dataSize = 0; - state.vbos[currentBuffer] = CoreGraphics::CreateBuffer(vboInfo); - state.vertexPtrs[currentBuffer] = (byte*)CoreGraphics::BufferMap(state.vbos[currentBuffer]); + ImguiContext::state.vbos[currentBuffer] = CoreGraphics::CreateBuffer(vboInfo); + ImguiContext::state.vertexPtrs[currentBuffer] = (byte*)CoreGraphics::BufferMap(ImguiContext::state.vbos[currentBuffer]); } - if (data->TotalIdxCount > CoreGraphics::BufferGetSize(state.ibos[currentBuffer])) + if (data->TotalIdxCount > CoreGraphics::BufferGetSize(ImguiContext::state.ibos[currentBuffer])) { - CoreGraphics::BufferUnmap(state.ibos[currentBuffer]); - CoreGraphics::DestroyBuffer(state.ibos[currentBuffer]); + CoreGraphics::BufferUnmap(ImguiContext::state.ibos[currentBuffer]); + CoreGraphics::DestroyBuffer(ImguiContext::state.ibos[currentBuffer]); CoreGraphics::BufferCreateInfo iboInfo; iboInfo.name = "ImGUI IBO"_atm; @@ -93,21 +101,35 @@ ImguiContext::ImguiDrawFunction(const CoreGraphics::CmdBufferId cmdBuf) iboInfo.usageFlags = CoreGraphics::IndexBuffer; iboInfo.data = nullptr; iboInfo.dataSize = 0; - state.ibos[currentBuffer] = CoreGraphics::CreateBuffer(iboInfo); - state.indexPtrs[currentBuffer] = (byte*)CoreGraphics::BufferMap(state.ibos[currentBuffer]); + ImguiContext::state.ibos[currentBuffer] = CoreGraphics::CreateBuffer(iboInfo); + ImguiContext::state.indexPtrs[currentBuffer] = (byte*)CoreGraphics::BufferMap(ImguiContext::state.ibos[currentBuffer]); } // setup device - CoreGraphics::CmdSetGraphicsPipeline(cmdBuf, state.pipeline); +#if WITH_NEBULA_EDITOR + if (editor) + { + CoreGraphics::CmdSetGraphicsPipeline(cmdBuf, ImguiContext::state.editorPipeline); + } + else + { + CoreGraphics::CmdSetGraphicsPipeline(cmdBuf, ImguiContext::state.pipeline); + } +#else + CoreGraphics::CmdSetGraphicsPipeline(cmdBuf, ImguiContext::state.pipeline); +#endif // setup input buffers - CoreGraphics::CmdSetVertexLayout(cmdBuf, state.vlo); - CoreGraphics::CmdSetResourceTable(cmdBuf, state.resourceTable, NEBULA_BATCH_GROUP, GraphicsPipeline, nullptr); - CoreGraphics::CmdSetVertexBuffer(cmdBuf, 0, state.vbos[currentBuffer], 0); - CoreGraphics::CmdSetIndexBuffer(cmdBuf, IndexType::Index16, state.ibos[currentBuffer], 0); + CoreGraphics::CmdSetVertexLayout(cmdBuf, ImguiContext::state.vlo); + CoreGraphics::CmdSetResourceTable(cmdBuf, ImguiContext::state.resourceTable, NEBULA_BATCH_GROUP, GraphicsPipeline, nullptr); + CoreGraphics::CmdSetVertexBuffer(cmdBuf, 0, ImguiContext::state.vbos[currentBuffer], 0); + CoreGraphics::CmdSetIndexBuffer(cmdBuf, IndexType::Index16, ImguiContext::state.ibos[currentBuffer], 0); + CoreGraphics::CmdSetPrimitiveTopology(cmdBuf, CoreGraphics::PrimitiveTopology::TriangleList); + CoreGraphics::CmdSetViewport(cmdBuf, viewport, 0); + CoreGraphics::CmdSetScissorRect(cmdBuf, viewport, 0); // set projection - CoreGraphics::CmdPushConstants(cmdBuf, CoreGraphics::GraphicsPipeline, state.textProjectionConstant, sizeof(proj), (byte*)&proj); + CoreGraphics::CmdPushConstants(cmdBuf, CoreGraphics::GraphicsPipeline, ImguiContext::state.textProjectionConstant, sizeof(proj), (byte*)&proj); struct TextureInfo { @@ -134,12 +156,12 @@ ImguiContext::ImguiDrawFunction(const CoreGraphics::CmdBufferId cmdBuf) const SizeT indexBufferSize = commandList->IdxBuffer.size() * sizeof(ImDrawIdx); // using 16 bit indices // if we render too many vertices, we will simply assert, but should never happen really - n_assert(vertexBufferOffset + (IndexT)commandList->VtxBuffer.size() < CoreGraphics::BufferGetByteSize(state.vbos[currentBuffer])); - n_assert(indexBufferOffset + (IndexT)commandList->IdxBuffer.size() < CoreGraphics::BufferGetByteSize(state.ibos[currentBuffer])); + n_assert(vertexBufferOffset + (IndexT)commandList->VtxBuffer.size() < CoreGraphics::BufferGetByteSize(ImguiContext::state.vbos[currentBuffer])); + n_assert(indexBufferOffset + (IndexT)commandList->IdxBuffer.size() < CoreGraphics::BufferGetByteSize(ImguiContext::state.ibos[currentBuffer])); // wait for previous draws to finish... - Memory::Copy(vertexBuffer, state.vertexPtrs[currentBuffer] + vertexBufferOffset, vertexBufferSize); - Memory::Copy(indexBuffer, state.indexPtrs[currentBuffer] + indexBufferOffset, indexBufferSize); + Memory::Copy(vertexBuffer, ImguiContext::state.vertexPtrs[currentBuffer] + vertexBufferOffset, vertexBufferSize); + Memory::Copy(indexBuffer, ImguiContext::state.indexPtrs[currentBuffer] + indexBufferOffset, indexBufferSize); IndexT j; IndexT primitiveIndexOffset = 0; for (j = 0; j < commandList->CmdBuffer.size(); j++) @@ -182,7 +204,7 @@ ImguiContext::ImguiDrawFunction(const CoreGraphics::CmdBufferId cmdBuf) texInfo.mip = tex.mip; texInfo.id = CoreGraphics::TextureGetBindlessHandle(texture); - CoreGraphics::CmdPushConstants(cmdBuf, CoreGraphics::GraphicsPipeline, state.packedTextureInfo, sizeof(TextureInfo), (byte*)& texInfo); + CoreGraphics::CmdPushConstants(cmdBuf, CoreGraphics::GraphicsPipeline, ImguiContext::state.packedTextureInfo, sizeof(TextureInfo), (byte*)& texInfo); // setup primitive CoreGraphics::PrimitiveGroup primitive; @@ -207,11 +229,8 @@ ImguiContext::ImguiDrawFunction(const CoreGraphics::CmdBufferId cmdBuf) indexBufferOffset += indexBufferSize; } - CoreGraphics::BufferFlush(state.vbos[currentBuffer]); - CoreGraphics::BufferFlush(state.ibos[currentBuffer]); - - // reset clip settings - CoreGraphics::CmdResetClipToPass(cmdBuf); + CoreGraphics::BufferFlush(ImguiContext::state.vbos[currentBuffer]); + CoreGraphics::BufferFlush(ImguiContext::state.ibos[currentBuffer]); } //------------------------------------------------------------------------------ @@ -323,13 +342,10 @@ ImguiContext::Create() // allocate imgui shader state.uiShader = CoreGraphics::ShaderGet("shd:imgui/shaders/imgui.fxb"); - state.params.projVar = CoreGraphics::ShaderGetConstantBinding(state.uiShader,"TextProjectionModel"); - state.params.fontVar = CoreGraphics::ShaderGetConstantBinding(state.uiShader, "Texture"); state.prog = CoreGraphics::ShaderGetProgram(state.uiShader, CoreGraphics::ShaderFeatureMask("Static")); state.resourceTable = CoreGraphics::ShaderCreateResourceTable(state.uiShader, NEBULA_BATCH_GROUP); - state.textureConstant = CoreGraphics::ShaderGetConstantBinding(state.uiShader, "Texture"); state.textProjectionConstant = CoreGraphics::ShaderGetConstantBinding(state.uiShader, "TextProjectionModel"); state.packedTextureInfo = CoreGraphics::ShaderGetConstantBinding(state.uiShader, "PackedTextureInfo"); @@ -343,23 +359,42 @@ ImguiContext::Create() components.Append(VertexComponent(2, VertexComponent::UByte4N, 0)); state.vlo = CoreGraphics::CreateVertexLayout({ .name = "ImGui"_atm, .comps = components }); - Frame::FrameCode* op = state.frameOpAllocator.Alloc(); - op->domain = CoreGraphics::BarrierDomain::Pass; - op->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + /* + FrameScript_default::RegisterSubgraphPipelines_ImGUI_Pass([](const CoreGraphics::PassId pass, uint subpass) + { + CoreGraphics::InputAssemblyKey inputAssembly{ CoreGraphics::PrimitiveTopology::TriangleList, false }; + if (state.pipeline != CoreGraphics::InvalidPipelineId) + CoreGraphics::DestroyGraphicsPipeline(state.pipeline); + state.pipeline = CoreGraphics::CreateGraphicsPipeline({ state.prog, pass, subpass, inputAssembly }); + }); + FrameScript_default::RegisterSubgraph_ImGUI_Pass([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { #ifdef NEBULA_NO_DYNUI_ASSERTS ImguiContext::RecoverImGuiContextErrors(); #endif - ImguiContext::ImguiDrawFunction(cmdBuf); - }; - op->buildFunc = [](const CoreGraphics::PassId pass, uint subpass) + ImGui::Render(); + ImguiDrawFunction(cmdBuf, viewport); + }); + */ + +#if WITH_NEBULA_EDITOR + FrameScript_editorframe::RegisterSubgraphPipelines_ImGUI_Pass([](const CoreGraphics::PassId pass, uint subpass) { - CoreGraphics::InputAssemblyKey inputAssembly { CoreGraphics::PrimitiveTopology::TriangleList, false }; - if (state.pipeline != CoreGraphics::InvalidPipelineId) - CoreGraphics::DestroyGraphicsPipeline(state.pipeline); - state.pipeline = CoreGraphics::CreateGraphicsPipeline({ state.prog, pass, subpass, inputAssembly }); - }; - Frame::AddSubgraph("ImGUI", { op }); + CoreGraphics::InputAssemblyKey inputAssembly{ CoreGraphics::PrimitiveTopology::TriangleList, false }; + if (state.editorPipeline != CoreGraphics::InvalidPipelineId) + CoreGraphics::DestroyGraphicsPipeline(state.editorPipeline); + state.editorPipeline = CoreGraphics::CreateGraphicsPipeline({ state.prog, pass, subpass, inputAssembly }); + }); + + FrameScript_editorframe::RegisterSubgraph_ImGUI_Pass([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) + { +#ifdef NEBULA_NO_DYNUI_ASSERTS + ImguiContext::RecoverImGuiContextErrors(); +#endif + ImGui::Render(); + ImguiDrawFunction(cmdBuf, viewport, true); + }); +#endif SizeT numBuffers = CoreGraphics::GetNumBufferedFrames(); @@ -599,8 +634,6 @@ ImguiContext::Discard() Input::InputServer::Instance()->RemoveInputHandler(state.inputHandler.upcast()); state.inputHandler = nullptr; - state.frameOpAllocator.Release(); - CoreGraphics::DestroyTexture((CoreGraphics::TextureId)state.fontTexture.nebulaHandle); ImGui::DestroyContext(); } @@ -675,22 +708,8 @@ ImguiContext::NewFrame(const Graphics::FrameContext& ctx) { ImGuiIO& io = ImGui::GetIO(); io.DeltaTime = ctx.frameTime; - ImGui::NewFrame(); ImGui::GetStyle().Alpha = Core::CVarReadFloat(ui_opacity); -#ifdef IMGUI_HAS_DOCK - if (state.dockOverViewport) - ImGui::DockSpaceOverViewport(); -#endif - -} - -//------------------------------------------------------------------------------ -/** -*/ -void -ImguiContext::Render(const Graphics::FrameContext& ctx) -{ - ImGui::Render(); + ImGui::NewFrame(); } } // namespace Dynui diff --git a/code/addons/dynui/imguicontext.h b/code/addons/dynui/imguicontext.h index 91499735bf..8021427002 100644 --- a/code/addons/dynui/imguicontext.h +++ b/code/addons/dynui/imguicontext.h @@ -25,12 +25,6 @@ struct ImFont; namespace Dynui { -struct ImguiRendererParams -{ - IndexT projVar; - IndexT fontVar; -}; - struct ImguiTextureId { CoreGraphics::TextureId nebulaHandle; @@ -62,16 +56,17 @@ class ImguiContext : public Graphics::GraphicsContext static void OnWindowResized(const CoreGraphics::WindowId windowId, SizeT width, SizeT height); /// called before frame static void NewFrame(const Graphics::FrameContext& ctx); - /// called before frame - static void Render(const Graphics::FrameContext& ctx); struct ImguiState { - ImguiRendererParams params; CoreGraphics::ShaderId uiShader; CoreGraphics::ShaderProgramId prog; CoreGraphics::PipelineId pipeline; +#if WITH_NEBULA_EDITOR + CoreGraphics::PipelineId editorPipeline; +#endif + ImguiTextureId fontTexture; //CoreGraphics::TextureId fontTexture; @@ -79,7 +74,6 @@ class ImguiContext : public Graphics::GraphicsContext Util::FixedArray ibos; CoreGraphics::VertexLayoutId vlo; - IndexT textureConstant; IndexT textProjectionConstant; IndexT packedTextureInfo; CoreGraphics::ResourceTableId resourceTable; @@ -93,15 +87,12 @@ class ImguiContext : public Graphics::GraphicsContext ImFont* boldFont; ImFont* itFont; - Memory::ArenaAllocator frameOpAllocator; - Ptr inputHandler; bool dockOverViewport; }; static ImguiState state; private: - static void ImguiDrawFunction(const CoreGraphics::CmdBufferId cmdBuf); static void RecoverImGuiContextErrors(); }; diff --git a/code/addons/graphicsfeature/graphicsfeatureunit.cc b/code/addons/graphicsfeature/graphicsfeatureunit.cc index 34bbec2473..74ee613f74 100644 --- a/code/addons/graphicsfeature/graphicsfeatureunit.cc +++ b/code/addons/graphicsfeature/graphicsfeatureunit.cc @@ -43,6 +43,12 @@ #include "terrain/terraincontext.h" +#include "frame/default.h" +#include "frame/shadows.h" +#if WITH_NEBULA_EDITOR +#include "frame/editorframe.h" +#endif + using namespace Graphics; using namespace Visibility; using namespace Models; @@ -130,13 +136,18 @@ GraphicsFeatureUnit::OnActivate() }; this->wnd = CreateWindow(wndInfo); - this->defaultView = gfxServer->CreateView("mainview", this->defaultFrameScript, this->wnd); + CoreGraphics::DisplayMode mode = CoreGraphics::WindowGetDisplayMode(this->wnd); + + FrameScript_shadows::Initialize(1024, 1024); + FrameScript_default::Initialize(mode.GetWidth(), mode.GetHeight()); +#if WITH_NEBULA_EDITOR + FrameScript_editorframe::Initialize(mode.GetWidth(), mode.GetHeight()); +#endif + this->defaultView = gfxServer->CreateView("mainview", FrameScript_default::Run, Math::rectangle(0, 0, mode.GetWidth(), mode.GetHeight())); this->defaultStage = gfxServer->CreateStage("defaultStage", true); this->defaultView->SetStage(this->defaultStage); this->globalLight = Graphics::CreateEntity(); - Ptr frameScript = this->defaultView->GetFrameScript(); - Im3d::Im3dContext::Create(); Dynui::ImguiContext::Create(); //StaticUI::StaticUIContext::Create(); @@ -150,7 +161,6 @@ GraphicsFeatureUnit::OnActivate() Raytracing::RaytracingSetupSettings raytracingSettings = { .maxNumAllowedInstances = 0xFFFF, - .script = frameScript }; Raytracing::RaytracingContext::Create(raytracingSettings); Clustering::ClusterContext::Create(0.01f, 1000.0f, this->wnd); @@ -170,6 +180,7 @@ GraphicsFeatureUnit::OnActivate() Terrain::TerrainContext::Create(settings); Terrain::TerrainContext::SetSun(this->globalLight); + /* this->terrain.entity = Graphics::CreateEntity(); Graphics::RegisterEntity(this->terrain.entity); Terrain::TerrainContext::SetupTerrain(this->terrain.entity, terrainSettings.instance->height, terrainSettings.instance->decision, terrainSettings.config->raytracing); @@ -225,27 +236,42 @@ GraphicsFeatureUnit::OnActivate() Math::vec2 {terrainSettings.config->world_size_width, terrainSettings.config->world_size_height}}; Vegetation::VegetationContext::Create(vegSettings); } - } + */ + } - Lighting::LightContext::Create(frameScript); + Lighting::LightContext::Create(); Decals::DecalContext::Create(); Characters::CharacterContext::Create(); - Fog::VolumetricFogContext::Create(frameScript); + Fog::VolumetricFogContext::Create(); PostEffects::BloomContext::Create(); PostEffects::SSAOContext::Create(); PostEffects::HistogramContext::Create(); PostEffects::DownsamplingContext::Create(); - PostEffects::BloomContext::Setup(frameScript); - PostEffects::SSAOContext::Setup(frameScript); - PostEffects::HistogramContext::Setup(frameScript); + PostEffects::BloomContext::Setup(); + PostEffects::SSAOContext::Setup(); + PostEffects::HistogramContext::Setup(); PostEffects::HistogramContext::SetWindow({ 0.0f, 0.0f }, { 1.0f, 1.0f }, 1); - PostEffects::DownsamplingContext::Setup(frameScript); - - Graphics::SetupBufferConstants(frameScript); + PostEffects::DownsamplingContext::Setup(); + + Graphics::SetupBufferConstants(); + this->gfxServer->AddPreViewCall([](IndexT frameIndex, IndexT bufferIndex) { + static auto lastFrameSubmission = FrameScript_default::Submission_Scene; + FrameScript_shadows::Run(Math::rectangle(0, 0, 1024, 1024), frameIndex, bufferIndex); + FrameScript_default::Bind_Shadows(FrameScript_shadows::Submission_Shadows); + FrameScript_default::Bind_SunShadowDepth(Frame::TextureImport::FromExport(FrameScript_shadows::Export_SunShadowDepth)); + }); + this->gfxServer->SetResizeCall([](const SizeT windowWidth, const SizeT windowHeight) { + FrameScript_default::Initialize(windowWidth, windowHeight); + FrameScript_default::SetupPipelines(); +#if WITH_NEBULA_EDITOR + FrameScript_editorframe::Initialize(windowWidth, windowHeight); + FrameScript_editorframe::SetupPipelines(); +#endif + }); Lighting::LightContext::RegisterEntity(this->globalLight); - Lighting::LightContext::SetupGlobalLight(this->globalLight, Math::vec3(1), 50.000f, Math::vec3(0, 0, 0), Math::vec3(0, 0, 0), 0, 60_rad, 0_rad, true); + Lighting::LightContext::SetupGlobalLight(this->globalLight, Math::vec3(1), 50.000f, Math::vec3(0, 0, 0), Math::vec3(0, 0, 0), 0, 70_rad, 0_rad, true); ObserverContext::CreateBruteforceSystem({}); @@ -254,7 +280,6 @@ GraphicsFeatureUnit::OnActivate() Util::Array preLogicCalls = { - Im3d::Im3dContext::NewFrame, Dynui::ImguiContext::NewFrame, CameraContext::UpdateCameras, ModelContext::UpdateTransforms, @@ -287,7 +312,6 @@ GraphicsFeatureUnit::OnActivate() Raytracing::RaytracingContext::UpdateTransforms, // At the very latest point, wait for work to finish - Dynui::ImguiContext::Render, ModelContext::WaitForWork, Raytracing::RaytracingContext::WaitForJobs, Characters::CharacterContext::WaitForCharacterJobs, @@ -320,9 +344,12 @@ GraphicsFeatureUnit::OnActivate() this->graphicsManagerHandle = this->AttachManager(GraphicsManager::Create()); this->cameraManagerHandle = this->AttachManager(CameraManager::Create()); + FrameScript_default::SetupPipelines(); + FrameScript_shadows::SetupPipelines(); +#if WITH_NEBULA_EDITOR + FrameScript_editorframe::SetupPipelines(); +#endif this->defaultViewHandle = CameraManager::RegisterView(this->defaultView); - - this->defaultView->BuildFrameScript(); } //------------------------------------------------------------------------------ @@ -363,11 +390,6 @@ GraphicsFeatureUnit::OnBeginFrame() this->gfxServer->RunPreLogic(); - for (auto const& uiFunc : this->uiCallbacks) - { - uiFunc(); - } - switch (Core::CVarReadInt(this->r_debug)) { case 2: @@ -377,10 +399,6 @@ GraphicsFeatureUnit::OnBeginFrame() default: break; } - - if (Core::CVarReadInt(this->r_show_frame_inspector) > 0) - Debug::FrameScriptInspector::Run(this->defaultView->GetFrameScript()); - } //------------------------------------------------------------------------------ @@ -434,13 +452,4 @@ GraphicsFeatureUnit::OnRenderDebug() FeatureUnit::OnRenderDebug(); } -//------------------------------------------------------------------------------ -/** -*/ -void -GraphicsFeatureUnit::AddRenderUICallback(UIRenderFunc func) -{ - this->uiCallbacks.Append(func); -} - } // namespace GraphicsFeature diff --git a/code/addons/graphicsfeature/graphicsfeatureunit.h b/code/addons/graphicsfeature/graphicsfeatureunit.h index 1d7220d4ad..991ea1a3d0 100644 --- a/code/addons/graphicsfeature/graphicsfeatureunit.h +++ b/code/addons/graphicsfeature/graphicsfeatureunit.h @@ -74,10 +74,7 @@ class GraphicsFeatureUnit : public Game::FeatureUnit /// Setup terrain biome, run before OnActivate void SetupTerrainBiome(const Terrain::BiomeSettings& biomeParameters); - using UIRenderFunc = std::function; - /// add a custom UI render function - void AddRenderUICallback(UIRenderFunc func); - + Graphics::GraphicsEntityId globalLight; private: @@ -91,7 +88,6 @@ class GraphicsFeatureUnit : public Game::FeatureUnit CoreGraphics::WindowId wnd; //FIXME - Util::Array uiCallbacks; Game::ManagerHandle graphicsManagerHandle; Game::ManagerHandle cameraManagerHandle; diff --git a/code/addons/staticui/staticuicontext.cc b/code/addons/staticui/staticuicontext.cc index 63761ba8df..23fb088fee 100644 --- a/code/addons/staticui/staticuicontext.cc +++ b/code/addons/staticui/staticuicontext.cc @@ -5,10 +5,10 @@ #include "foundation/stdneb.h" #include "staticuicontext.h" #include "Ultralight/JavaScript.h" -#include "frame/framecode.h" -#include "frame/framesubgraph.h" #include "graphics/graphicsserver.h" +#include "frame/default.h" + namespace StaticUI { @@ -92,22 +92,15 @@ StaticUIContext::Create() JSObjectSetProperty(js.get().ctx(), global, nativeBoxFuncName, nativeBoxFunc, 0, nullptr); JSStringRelease(nativeBoxFuncName); - Frame::FrameCode* drawOp = new Frame::FrameCode; - drawOp->domain = CoreGraphics::BarrierDomain::Global; - drawOp->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_StaticUI_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { state.Backend->Render(cmdBuf, bufferIndex); - }; - Frame::AddSubgraph("StaticUI", { drawOp }); + }); - Frame::FrameCode* copyOp = new Frame::FrameCode; - copyOp->domain = CoreGraphics::BarrierDomain::Pass; - copyOp->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_StaticUIToBackbuffer_Pass([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { state.Backend->DrawToBackbuffer(cmdBuf, bufferIndex); - }; - Frame::AddSubgraph("StaticUI To Backbuffer", { copyOp }); - + }); } //------------------------------------------------------------------------------ diff --git a/code/foundation/memory/posix/posixmemory.h b/code/foundation/memory/posix/posixmemory.h index 2ab389b59f..c327fb9a98 100644 --- a/code/foundation/memory/posix/posixmemory.h +++ b/code/foundation/memory/posix/posixmemory.h @@ -28,6 +28,7 @@ extern int volatile HeapTypeAllocSize[NumHeapTypes]; #endif #define StackAlloc(size) alloca(size); +#define StackFree(ptr) //------------------------------------------------------------------------------ /** diff --git a/code/foundation/memory/win32/win32memory.h b/code/foundation/memory/win32/win32memory.h index 657ef438cb..0ea316e768 100644 --- a/code/foundation/memory/win32/win32memory.h +++ b/code/foundation/memory/win32/win32memory.h @@ -50,6 +50,7 @@ extern char* DuplicateCString(const char* from); extern bool IsOverlapping(const unsigned char* srcPtr, size_t srcSize, const unsigned char* dstPtr, size_t dstSize); /// Allocate memory on the stack #define StackAlloc(size) _malloca(size); +#define StackFree(ptr) _freea(ptr); //------------------------------------------------------------------------------ /** diff --git a/code/foundation/util/keyvaluepair.h b/code/foundation/util/keyvaluepair.h index 0215d1ceff..2feb659958 100644 --- a/code/foundation/util/keyvaluepair.h +++ b/code/foundation/util/keyvaluepair.h @@ -63,7 +63,6 @@ template class KeyValuePair /// read access to key const VALUETYPE& Value() const; -protected: KEYTYPE keyData = KEYTYPE(); VALUETYPE valueData = VALUETYPE(); }; diff --git a/code/foundation/util/string.h b/code/foundation/util/string.h index b58900f6b1..983d6dbb81 100644 --- a/code/foundation/util/string.h +++ b/code/foundation/util/string.h @@ -46,7 +46,6 @@ namespace Math namespace Util { class Blob; - class String { public: @@ -353,6 +352,8 @@ class String static String FromBase64(const String&); /// convert from "anything" template static String From(const T& t); + /// Hash a string + static constexpr uint Hash(const char* c, std::size_t s); /// construct a hex string from an int template @@ -691,20 +692,8 @@ String::IsValid() const inline uint32_t String::HashCode() const { - uint32_t hash = 0; const char* ptr = this->AsCharPtr(); - SizeT len = this->strLen; - SizeT i; - for (i = 0; i < len; i++) - { - hash += ptr[i]; - hash += hash << 10; - hash ^= hash >> 6; - } - hash += hash << 3; - hash ^= hash >> 11; - hash += hash << 15; - return hash; + return Hash(ptr, this->strLen); } //------------------------------------------------------------------------------ @@ -1190,6 +1179,27 @@ String::AppendMat4(const Math::mat4& val) this->Append(FromMat4(val)); } #endif + + +//------------------------------------------------------------------------------ +/** +*/ +constexpr uint +String::Hash(const char* c, std::size_t s) +{ + uint hash = 0; + std::size_t i; + for (i = 0; i < s; i++) + { + hash += c[i]; + hash += hash << 10; + hash ^= hash >> 6; + } + hash += hash << 3; + hash ^= hash >> 11; + hash += hash << 15; + return hash; +} inline auto Format = &String::Sprintf; @@ -1209,22 +1219,8 @@ Util::String operator ""_str(const char* c, std::size_t s); constexpr uint operator ""_hash(const char* c, std::size_t s) { - uint hash = 0; - const char* ptr = c; - std::size_t len = s; - std::size_t i; - for (i = 0; i < len; i++) - { - hash += ptr[i]; - hash += hash << 10; - hash ^= hash >> 6; - } - hash += hash << 3; - hash ^= hash >> 11; - hash += hash << 15; - return hash; + return Util::String::Hash(c, s); } - //------------------------------------------------------------------------------ diff --git a/code/render/CMakeLists.txt b/code/render/CMakeLists.txt index 263bf578bb..19bbb4a3f1 100644 --- a/code/render/CMakeLists.txt +++ b/code/render/CMakeLists.txt @@ -124,8 +124,6 @@ ENDIF() antialiasquality.cc antialiasquality.h barrier.h - batchgroup.cc - batchgroup.h buffer.cc buffer.h gpubuffertypes.h @@ -359,54 +357,60 @@ ENDIF() volumetricfogcontext.h ) fips_dir(frame) - fips_files( - framebarrier.cc - framebarrier.h - framebatchtype.h - frameblit.cc - frameblit.h - framecode.cc - framecode.h - framecompute.cc - framecompute.h - frameplugin.cc - frameplugin.h - frameresolve.cc - frameresolve.h - framecopy.cc - framecopy.h - #frameevent.cc - #frameevent.h - framemipmap.cc - framemipmap.h - frameop.cc - frameop.h - framepass.cc - framepass.h - framescript.cc - framescript.h - framescriptloader.cc - framescriptloader.h - framesubgraph.cc - framesubgraph.h - frameserver.cc - frameserver.h - framesubmission.cc - framesubmission.h - framesubpass.cc - framesubpass.h - framesubpassplugin.cc - framesubpassplugin.h - framesubpassbatch.cc - framesubpassbatch.h - framesubpassfullscreeneffect.cc - framesubpassfullscreeneffect.h - framesubpassorderedbatch.cc - framesubpassorderedbatch.h - framesubpassplugin.cc - framesubpassplugin.h - frameswap.cc - frameswap.h + nebula_framescript_add(default.json shadows.json) + #fips_files( + # framebarrier.cc + # framebarrier.h + # framebatchtype.h + # frameblit.cc + # frameblit.h + # framecode.cc + # framecode.h + # framecompute.cc + # framecompute.h + # frameplugin.cc + # frameplugin.h + # frameresolve.cc + # frameresolve.h + # framecopy.cc + # framecopy.h + # #frameevent.cc + # #frameevent.h + # framemipmap.cc + # framemipmap.h + # frameop.cc + # frameop.h + # framepass.cc + # framepass.h + # framescript.cc + # framescript.h + # framescriptloader.cc + # framescriptloader.h + # framesubgraph.cc + # framesubgraph.h + # frameserver.cc + # frameserver.h + # framesubmission.cc + # framesubmission.h + # framesubpass.cc + # framesubpass.h + # framesubpassplugin.cc + # framesubpassplugin.h + # framesubpassbatch.cc + # framesubpassbatch.h + # framesubpassfullscreeneffect.cc + # framesubpassfullscreeneffect.h + # framesubpassorderedbatch.cc + # framesubpassorderedbatch.h + # framesubpassplugin.cc + # framesubpassplugin.h + # frameswap.cc + # frameswap.h + #) + fips_dir(framescripts) + fips_files( + framescripts.cc + framescripts.h ) fips_dir(gi) fips_files( @@ -513,8 +517,8 @@ IF(FALSE) ENDIF() fips_dir(materials) # Add engine templates and generate glue file which is needed by the material system - nebula_material_template_compile(base.json gltf.json) - nebula_project_material_template_compile() + nebula_material_template_add(base.json gltf.json) + nebula_project_material_template_add() fips_files( material.cc diff --git a/code/render/clustering/clustercontext.cc b/code/render/clustering/clustercontext.cc index aa14802ed8..83d5531d37 100644 --- a/code/render/clustering/clustercontext.cc +++ b/code/render/clustering/clustercontext.cc @@ -11,6 +11,7 @@ #include "graphics/graphicsserver.h" #include "graphics/globalconstants.h" +#include "frame/default.h" namespace Clustering { @@ -37,8 +38,6 @@ struct float xResolution, yResolution; float invXResolution, invYResolution; - Memory::ArenaAllocator frameOpAllocator; - SizeT numThreads; } state; @@ -111,23 +110,16 @@ ClusterContext::Create(float ZNear, float ZFar, const CoreGraphics::WindowId win ResourceTableSetConstantBuffer(frameResourceTable, { state.constantBuffer, Shared::Table_Frame::ClusterUniforms_SLOT, 0, sizeof(ClusterGenerate::ClusterUniforms), 0 }); } - Frame::FrameCode* op = state.frameOpAllocator.Alloc(); - op->domain = CoreGraphics::BarrierDomain::Global; - op->queue = CoreGraphics::QueueType::ComputeQueueType; - op->bufferDeps.Add(state.clusterBuffer, - { - "ClusterBuffer" - , CoreGraphics::PipelineStage::ComputeShaderWrite - , CoreGraphics::BufferSubresourceInfo() - }); - op->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::Bind_ClusterBuffer(state.clusterBuffer); + FrameScript_default::RegisterSubgraph_ClusterAABBGeneration_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CmdSetShaderProgram(cmdBuf, state.clusterGenerateProgram); // Run the job as series of 1024 clusters at a time CmdDispatch(cmdBuf, Math::ceil((state.clusterDimensions[0] * state.clusterDimensions[1] * state.clusterDimensions[2]) / 64.0f), 1, 1); - }; - Frame::AddSubgraph("Cluster AABB Generation", { op }); + }, { + { FrameScript_default::BufferIndex::ClusterBuffer, CoreGraphics::PipelineStage::ComputeShaderWrite } + }); } //------------------------------------------------------------------------------ @@ -214,6 +206,8 @@ ClusterContext::WindowResized(const CoreGraphics::WindowId id, SizeT width, Size rwb3Info.usageFlags = CoreGraphics::ReadWriteBuffer; rwb3Info.queueSupport = CoreGraphics::GraphicsQueueSupport | CoreGraphics::ComputeQueueSupport; state.clusterBuffer = CreateBuffer(rwb3Info); + FrameScript_default::Bind_ClusterBuffer(state.clusterBuffer); + for (IndexT i = 0; i < CoreGraphics::GetNumBufferedFrames(); i++) { diff --git a/code/render/coregraphics/barrier.h b/code/render/coregraphics/barrier.h index bc49e5bebe..9d4f251e1d 100644 --- a/code/render/coregraphics/barrier.h +++ b/code/render/coregraphics/barrier.h @@ -44,17 +44,17 @@ struct TextureSubresourceInfo static TextureSubresourceInfo Texture(CoreGraphics::ImageBits bits, TextureId tex) { - return TextureSubresourceInfo(bits, 0, TextureGetNumMips(tex), 0, TextureGetNumLayers(tex)); + return TextureSubresourceInfo(bits, 0, NEBULA_ALL_MIPS, 0, NEBULA_ALL_LAYERS); } static TextureSubresourceInfo Color(TextureId tex) { - return TextureSubresourceInfo(ImageBits::ColorBits, 0, TextureGetNumMips(tex), 0, TextureGetNumLayers(tex)); + return TextureSubresourceInfo(ImageBits::ColorBits, 0, NEBULA_ALL_MIPS, 0, NEBULA_ALL_LAYERS); } static TextureSubresourceInfo DepthStencil(TextureId tex) { - return TextureSubresourceInfo(ImageBits::DepthBits | ImageBits::StencilBits, 0, TextureGetNumMips(tex), 0, TextureGetNumLayers(tex)); + return TextureSubresourceInfo(ImageBits::DepthBits | ImageBits::StencilBits, 0, NEBULA_ALL_MIPS, 0, NEBULA_ALL_LAYERS); } static TextureSubresourceInfo ColorNoMipNoLayer() @@ -156,6 +156,70 @@ struct AccelerationStructureBarrierInfo ~AccelerationStructureBarrierInfo() {}; }; +struct BarrierScope +{ + /// Make sure we have cleared the barrier scope before destroying the object + ~BarrierScope() + { + n_assert(this->textures.IsEmpty()); + n_assert(this->buffers.IsEmpty()); + } + + /// Start barrier + static BarrierScope Begin(const char* name, CmdBufferId cmdBuf) + { + return BarrierScope{ .name = name, .cmdBuf = cmdBuf, .fromStage = CoreGraphics::PipelineStage::InvalidStage, .toStage = CoreGraphics::PipelineStage::InvalidStage }; + } + + /// Add texture barrier + void AddTexture(ImageBits bits, TextureId tex, CoreGraphics::PipelineStage fromStage, CoreGraphics::PipelineStage toStage) + { + // If the barrier boundaries don't match, flush the barriers + if (this->fromStage != fromStage || this->toStage != toStage) + { + this->Flush(); + this->fromStage = fromStage; + this->toStage = toStage; + } + TextureBarrierInfo info = { .tex = tex, .subres = TextureSubresourceInfo::Texture(bits, tex) }; + textures.Append(info); + } + + /// Add buffer barrier + void AddBuffer(BufferId buf, CoreGraphics::PipelineStage fromStage, CoreGraphics::PipelineStage toStage) + { + // If the barrier boundaries don't match, flush the barriers + if (this->fromStage != fromStage || this->toStage != toStage) + { + this->Flush(); + this->fromStage = fromStage; + this->toStage = toStage; + } + BufferBarrierInfo info = { .buf = buf, .subres = CoreGraphics::BufferSubresourceInfo() }; + buffers.Append(info); + } + + /// Flush all pending changes + void Flush() + { + if (!this->textures.IsEmpty()) + CoreGraphics::CmdBarrier(this->cmdBuf, this->fromStage, this->toStage, CoreGraphics::BarrierDomain::Global, this->textures, InvalidIndex, InvalidIndex, this->name); + if (!this->buffers.IsEmpty()) + CoreGraphics::CmdBarrier(this->cmdBuf, this->fromStage, this->toStage, CoreGraphics::BarrierDomain::Global, this->buffers, InvalidIndex, InvalidIndex, this->name); + this->buffers.Clear(); + this->textures.Clear(); + } + + const char* name; + CmdBufferId cmdBuf; + CoreGraphics::PipelineStage fromStage, toStage; + Util::Array textures; + Util::Array buffers; + +private: + +}; + struct BarrierCreateInfo { Util::StringAtom name; diff --git a/code/render/coregraphics/batchgroup.cc b/code/render/coregraphics/batchgroup.cc deleted file mode 100644 index 5654aef27d..0000000000 --- a/code/render/coregraphics/batchgroup.cc +++ /dev/null @@ -1,57 +0,0 @@ -//------------------------------------------------------------------------------ -// batchgroup.cc -// (C) 2013-2020 Individual contributors, see AUTHORS file -//------------------------------------------------------------------------------ - -#include "coregraphics/batchgroup.h" -#include "graphics/graphicsserver.h" - -namespace CoreGraphics -{ - -using namespace Util; - -//------------------------------------------------------------------------------ -/** - Private constructor, only the ModelServer may create the central - ModelNodeType registry. -*/ -BatchGroup::BatchGroup() -{ - this->nameToCode.Reserve(NumBatchGroups); - this->codeToName.Reserve(NumBatchGroups); -} - -//------------------------------------------------------------------------------ -/** -*/ -BatchGroup::Code -BatchGroup::FromName(const Name& name) -{ - BatchGroup& registry = Graphics::GraphicsServer::Instance()->batchGroupRegistry; - IndexT index = registry.nameToCode.FindIndex(name); - if (InvalidIndex != index) - { - return registry.nameToCode.ValueAtIndex(index); - } - else - { - // name hasn't been registered yet - registry.codeToName.Append(name); - Code code = registry.codeToName.Size() - 1; - registry.nameToCode.Add(name, code); - return code; - } -} - -//------------------------------------------------------------------------------ -/** -*/ -BatchGroup::Name -BatchGroup::ToName(Code c) -{ - BatchGroup& registry = Graphics::GraphicsServer::Instance()->batchGroupRegistry; - return registry.codeToName[c]; -} - -} // namespace Graphics diff --git a/code/render/coregraphics/batchgroup.h b/code/render/coregraphics/batchgroup.h deleted file mode 100644 index 75dd326c17..0000000000 --- a/code/render/coregraphics/batchgroup.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once -//------------------------------------------------------------------------------ -/** - @class CoreGraphics::BatchGroup - - BatchGroup denotes a zero indexed name registry which corresponds to the - type of materials being batched during a FrameBatch. The name from the - 'batchType' field gets converted into an index in this class, which is then - used when retrieving all materials which utilizes this batch type. - - Materials have the same field in their template definition, meaning that - for each frame batch using a specific batch type, all materials with the same - batch type defined will be rendered in this pass, which acts as the bridge - between the frame shader system and the material rendering system. - - @copyright - (C) 2007 Radon Labs GmbH - (C) 2013-2020 Individual contributors, see AUTHORS file -*/ -#include "core/types.h" -#include "util/stringatom.h" -#include "util/array.h" -#include "util/dictionary.h" - -namespace Graphics { class GraphicsServer; } - -//------------------------------------------------------------------------------ -namespace CoreGraphics -{ -class BatchGroup -{ -public: - /// human readable name of a ModelNodeType - typedef Util::StringAtom Name; - /// binary code for a ModelNodeType - typedef IndexT Code; - - /// convert from string - static Code FromName(const Name& name); - /// convert to string - static Name ToName(Code c); - /// maximum number of different ModelNodeTypes - static const IndexT NumBatchGroups = 256; - /// invalid model node type code - static const IndexT InvalidBatchGroup = InvalidIndex; - -private: - friend class Graphics::GraphicsServer; - - /// constructor - BatchGroup(); - - Util::Dictionary nameToCode; - Util::Array codeToName; -}; - -} // namespace CoreGraphics -//------------------------------------------------------------------------------ - diff --git a/code/render/coregraphics/commandbuffer.h b/code/render/coregraphics/commandbuffer.h index 3f96cec764..d3c0a5bc95 100644 --- a/code/render/coregraphics/commandbuffer.h +++ b/code/render/coregraphics/commandbuffer.h @@ -103,8 +103,8 @@ ID_24_8_TYPE(CmdBufferPoolId); struct CmdBufferPoolCreateInfo { CoreGraphics::QueueType queue; - bool resetable : 1; // allow the buffer to be reset - bool shortlived : 1; // the buffer won't last long until it's destroyed or reset + bool resetable : 1; // Allow buffers created from this pool to be resetable + bool shortlived : 1; // Hint if the buffers allocated from this pool will be short lived }; /// create new command buffer pool @@ -119,11 +119,18 @@ struct CmdBufferCreateInfo QueueType usage; CmdBufferQueryBits queryTypes; +#if NEBULA_GRAPHICS_DEBUG + const char* name; +#endif + CmdBufferCreateInfo() : subBuffer(false) , pool(InvalidCmdBufferPoolId) , usage(QueueType::GraphicsQueueType) , queryTypes(CmdBufferQueryBits::Timestamps) +#if NEBULA_GRAPHICS_DEBUG + , name(nullptr) +#endif {}; }; @@ -276,8 +283,6 @@ void CmdBeginPass(const CmdBufferId id, const CoreGraphics::PassId pass); void CmdNextSubpass(const CmdBufferId id); /// End pass void CmdEndPass(const CmdBufferId id); -/// Reset clip settings to pass -void CmdResetClipToPass(const CmdBufferId id); /// Draw primitives void CmdDraw(const CmdBufferId id, const CoreGraphics::PrimitiveGroup& pg); /// Draw primitives instanced @@ -349,16 +354,10 @@ void CmdCopy( /// Blit textures void CmdBlit( const CmdBufferId id - , const CoreGraphics::TextureId from - , const Math::rectangle& fromRegion - , const CoreGraphics::ImageBits fromBits - , IndexT fromMip - , IndexT fromLayer - , const CoreGraphics::TextureId to - , const Math::rectangle& toRegion - , const CoreGraphics::ImageBits toBits - , IndexT toMip - , IndexT toLayer + , const CoreGraphics::TextureId fromTexture + , const CoreGraphics::TextureCopy& from + , const CoreGraphics::TextureId toTexture + , const CoreGraphics::TextureCopy& to ); /// Set viewport array diff --git a/code/render/coregraphics/config.h b/code/render/coregraphics/config.h index 62b73566b1..8b47c654c9 100644 --- a/code/render/coregraphics/config.h +++ b/code/render/coregraphics/config.h @@ -14,6 +14,8 @@ #include "core/rttimacros.h" #define NEBULA_WHOLE_BUFFER_SIZE (-1) +#define NEBULA_ALL_MIPS (-1) +#define NEBULA_ALL_LAYERS (-1) namespace CoreGraphics { typedef uint ConstantBufferOffset; @@ -78,14 +80,15 @@ __ImplementEnumBitOperators(CoreGraphics::ShaderVisibility); enum class ImageBits { - Auto = 0, // Special value to be used only by framescript - ColorBits = (1 << 0), - DepthBits = (1 << 1), - StencilBits = (1 << 2), - MetaBits = (1 << 3), - Plane0Bits = (1 << 4), - Plane1Bits = (1 << 5), - Plane2Bits = (1 << 6) + None = 0, + Auto = 1, // Special value to be used only by framescript + ColorBits = (1 << 1), + DepthBits = (1 << 2), + StencilBits = (1 << 3), + MetaBits = (1 << 4), + Plane0Bits = (1 << 5), + Plane1Bits = (1 << 6), + Plane2Bits = (1 << 7) }; __ImplementEnumBitOperators(CoreGraphics::ImageBits); __ImplementEnumComparisonOperators(CoreGraphics::ImageBits); @@ -280,6 +283,36 @@ PipelineStageFromString(const Util::String& str) } } +//------------------------------------------------------------------------------ +/** +*/ +inline bool +PipelineStageWrites(const PipelineStage stage) +{ + switch (stage) + { + case PipelineStage::VertexShaderWrite: + case PipelineStage::HullShaderWrite: + case PipelineStage::DomainShaderWrite: + case PipelineStage::GeometryShaderWrite: + case PipelineStage::PixelShaderWrite: + case PipelineStage::ComputeShaderWrite: + case PipelineStage::AllShadersWrite: + case PipelineStage::ColorWrite: + case PipelineStage::DepthStencilWrite: + case PipelineStage::HostWrite: + case PipelineStage::MemoryWrite: + case PipelineStage::TransferWrite: + return true; + } + return false; +} + + +//------------------------------------------------------------------------------ +/** +*/ + } // namespace CoreGraphics diff --git a/code/render/coregraphics/graphicsdevice.h b/code/render/coregraphics/graphicsdevice.h index 5265dc7b5c..8b38a83b96 100644 --- a/code/render/coregraphics/graphicsdevice.h +++ b/code/render/coregraphics/graphicsdevice.h @@ -1,8 +1,6 @@ #pragma once //------------------------------------------------------------------------------ /** - @struct CoreGraphics::GraphicsDeviceCreateInfo - The Graphics Device is the engine which drives the graphics abstraction layer @copyright @@ -185,11 +183,15 @@ uint64 NextSubmissionIndex(const CoreGraphics::QueueType queue); bool PollSubmissionIndex(const CoreGraphics::QueueType queue, uint64 index); /// Submit a command buffer, but doesn't necessarily execute it immediately -SubmissionWaitEvent SubmitCommandBuffer(const CoreGraphics::CmdBufferId cmds, CoreGraphics::QueueType type); +SubmissionWaitEvent SubmitCommandBuffer( + const CoreGraphics::CmdBufferId cmds + , CoreGraphics::QueueType type +#if NEBULA_GRAPHICS_DEBUG + , const char* name = nullptr +#endif +); /// Wait for a submission -void WaitForSubmission(SubmissionWaitEvent index, CoreGraphics::QueueType type, CoreGraphics::QueueType waitType); -/// Have a queue wait for another queue -void WaitForLastSubmission(CoreGraphics::QueueType type, CoreGraphics::QueueType waitType); +void WaitForSubmission(SubmissionWaitEvent index, CoreGraphics::QueueType type); /// Unlock constants void UnlockConstantUpdates(); diff --git a/code/render/coregraphics/pass.h b/code/render/coregraphics/pass.h index f20cc5e3ea..c2e0609950 100644 --- a/code/render/coregraphics/pass.h +++ b/code/render/coregraphics/pass.h @@ -15,6 +15,11 @@ #include "frame/framebatchtype.h" #include "coregraphics/textureview.h" +namespace Shared +{ +struct RenderTargetParameters; +} + namespace CoreGraphics { @@ -50,7 +55,7 @@ AttachmentFlagsFromString(const Util::String& string) else if (bits[i] == "Store") ret |= AttachmentFlagBits::Store; else if (bits[i] == "StoreStencil") ret |= AttachmentFlagBits::StoreStencil; else if (bits[i] == "Discard") ret |= AttachmentFlagBits::Discard; - else if (bits[i] == "DiscardStenci;") ret |= AttachmentFlagBits::DiscardStencil; + else if (bits[i] == "DiscardStencil") ret |= AttachmentFlagBits::DiscardStencil; } return ret; }; @@ -97,6 +102,8 @@ void DestroyPass(const PassId id); /// called when window is resized void PassWindowResizeCallback(const PassId id); +/// Set viewports +void PassSetRenderTargetParameters(const PassId id, const Util::FixedArray& viewports); /// get number of color attachments for entire pass (attachment list) const Util::Array& PassGetAttachments(const CoreGraphics::PassId id); @@ -106,12 +113,6 @@ const uint32_t PassGetNumSubpassAttachments(const CoreGraphics::PassId id, const /// Get pass resource table const CoreGraphics::ResourceTableId PassGetResourceTable(const CoreGraphics::PassId id); -/// get scissor rects for current subpass -const Util::FixedArray>& PassGetRects(const CoreGraphics::PassId& id); -/// get viewports for current subpass -const Util::FixedArray>& PassGetViewports(const CoreGraphics::PassId& id); - - /// get name const Util::StringAtom PassGetName(const CoreGraphics::PassId id); diff --git a/code/render/coregraphics/pixelformat.cc b/code/render/coregraphics/pixelformat.cc index e7eee8c85e..8c3b9661c1 100644 --- a/code/render/coregraphics/pixelformat.cc +++ b/code/render/coregraphics/pixelformat.cc @@ -51,6 +51,7 @@ PixelFormat::FromString(const Util::String& str) else if (str == "R32G32B32F") return R32G32B32F; else if (str == "R32G32B32") return R32G32B32; else if (str == "R11G11B10F") return R11G11B10F; + else if (str == "R9G9B9E5F") return R9G9B9E5F; else if (str == "R10G10B10X2") return R10G10B10X2; else if (str == "R10G10B10A2") return R10G10B10A2; else if (str == "D24S8") return D24S8; @@ -79,6 +80,7 @@ PixelFormat::ToString(PixelFormat::Code code) case R8G8B8A8: return "R8G8B8A8"; case SRGBA8: return "SRGBA8"; case R11G11B10F: return "R11G11B10F"; + case R9G9B9E5F: return "R9G9B9E5F"; case R5G6B5: return "R5G6B5"; case R5G5B5A1: return "R5G5B5A1"; case R4G4B4A4: return "R4G4B4A4"; @@ -114,6 +116,7 @@ PixelFormat::ToString(PixelFormat::Code code) case D16S8: return "D16S8"; case D24X8: return "D24X8"; case D24S8: return "D24S8"; + case D32: return "D32"; case D32S8: return "D32S8"; default: @@ -151,8 +154,10 @@ PixelFormat::ToSize(Code code) case R10G10B10X2: case R10G10B10A2: case R11G11B10F: + case R9G9B9E5F: case D24X8: case D24S8: + case D32: return 4; case D32S8: return 5; @@ -202,6 +207,7 @@ PixelFormat::ToChannels(Code code) case R8G8B8A8: return 4; case SRGBA8: return 4; case R11G11B10F: return 3; + case R9G9B9E5F: return 3; case R8G8B8: return 3; case R5G6B5: return 3; case R5G5B5A1: return 4; @@ -305,6 +311,7 @@ PixelFormat::ToTexelSize(Code code) case PixelFormat::R16G16B16A16F: return 8; case PixelFormat::R16G16B16A16: return 8; case PixelFormat::R11G11B10F: return 4; + case PixelFormat::R9G9B9E5F: return 4; case PixelFormat::R32F: return 4; case PixelFormat::R32: return 4; case PixelFormat::R32G32F: return 8; @@ -359,10 +366,14 @@ PixelFormat::IsDepthFormat(Code code) { switch (code) { - case PixelFormat::D24X8: - case PixelFormat::D24S8: - case PixelFormat::D32S8: return true; - default: return false; + case PixelFormat::D32: + case PixelFormat::D16S8: + case PixelFormat::D24X8: + case PixelFormat::D24S8: + case PixelFormat::D32S8: + return true; + default: + return false; } return false; } @@ -376,9 +387,34 @@ PixelFormat::IsStencilFormat(Code code) { switch (code) { + case PixelFormat::S8: + case PixelFormat::D16S8: + case PixelFormat::D24S8: + case PixelFormat::D32S8: + return true; + default: + return false; + } + return false; +} + +//------------------------------------------------------------------------------ +/** +*/ +bool +PixelFormat::IsDepthStencilFormat(Code code) +{ + switch (code) + { + case PixelFormat::S8: + case PixelFormat::D32: + case PixelFormat::D16S8: + case PixelFormat::D24X8: case PixelFormat::D24S8: - case PixelFormat::D32S8: return true; - default: return false; + case PixelFormat::D32S8: + return true; + default: + return false; } return false; } diff --git a/code/render/coregraphics/pixelformat.h b/code/render/coregraphics/pixelformat.h index 8604eeebf2..1b1051c14a 100644 --- a/code/render/coregraphics/pixelformat.h +++ b/code/render/coregraphics/pixelformat.h @@ -58,6 +58,7 @@ class PixelFormat R32G32B32F, // 96 bit float, 32 bit rgb each R32G32B32, // 96 bit integer, 32 bit rgb each R11G11B10F, // 32 bit float, 11 bits red and green, 10 bit blue + R9G9B9E5F, SRGBA8, R10G10B10X2, R10G10B10A2, @@ -66,6 +67,8 @@ class PixelFormat D32S8, D16S8, + D32, + S8, B8G8R8, B8G8R8A8, @@ -96,6 +99,8 @@ class PixelFormat static bool IsDepthFormat(Code code); /// return true if depth format static bool IsStencilFormat(Code code); + /// Return true if depth/stencil format + static bool IsDepthStencilFormat(Code code); /// Return Image bits from format static CoreGraphics::ImageBits ToImageBits(Code code); diff --git a/code/render/coregraphics/semaphore.h b/code/render/coregraphics/semaphore.h index cbb6715e06..85169ff251 100644 --- a/code/render/coregraphics/semaphore.h +++ b/code/render/coregraphics/semaphore.h @@ -30,6 +30,9 @@ enum SemaphoreType struct SemaphoreCreateInfo { +#if NEBULA_GRAPHICS_DEBUG + const char* name = nullptr; +#endif SemaphoreType type; }; @@ -47,4 +50,4 @@ void SemaphoreReset(const SemaphoreId& semaphore); } // namespace CoreGraphics -#pragma pop_macro("CreateSemaphore") \ No newline at end of file +#pragma pop_macro("CreateSemaphore") diff --git a/code/render/coregraphics/swapchain.h b/code/render/coregraphics/swapchain.h index 021d3c81eb..e6dc6ac4e4 100644 --- a/code/render/coregraphics/swapchain.h +++ b/code/render/coregraphics/swapchain.h @@ -21,6 +21,7 @@ struct SwapchainCreateInfo CoreGraphics::DisplayMode displayMode; bool vsync; GLFWwindow* window; + CoreGraphics::QueueType preferredQueue = CoreGraphics::ComputeQueueType; }; /// Create swapchain @@ -30,6 +31,10 @@ void DestroySwapchain(const SwapchainId id); /// Swap buffers void SwapchainSwap(const SwapchainId id); +/// Get queue to use for swapchain +CoreGraphics::QueueType SwapchainGetQueueType(const SwapchainId id); +/// Allocate command buffer for swapchain operations +CoreGraphics::CmdBufferId SwapchainAllocateCmds(const SwapchainId id); /// Copy to current backbuffer (call after swap) void SwapchainCopy(const SwapchainId id, const CoreGraphics::CmdBufferId cmdBuf, const CoreGraphics::TextureId source); /// Present diff --git a/code/render/coregraphics/texture.cc b/code/render/coregraphics/texture.cc index 182a8e81c1..6cf2f9cd9d 100644 --- a/code/render/coregraphics/texture.cc +++ b/code/render/coregraphics/texture.cc @@ -81,7 +81,9 @@ TextureGenerateMipmaps(const CoreGraphics::CmdBufferId cmdBuf, const TextureId i CoreGraphics::TextureSubresourceInfo{ CoreGraphics::ImageBits::ColorBits, (uint)mip + 1, 1, 0, 1 }, } }); - CoreGraphics::CmdBlit(cmdBuf, id, fromRegion, CoreGraphics::ImageBits::ColorBits, mip, 0, id, toRegion, CoreGraphics::ImageBits::ColorBits, mip + 1, 0); + CoreGraphics::TextureCopy from{ .region = fromRegion, .mip = (uint)mip, .layer = 0, .bits = CoreGraphics::ImageBits::ColorBits }; + CoreGraphics::TextureCopy to{ .region = toRegion, .mip = (uint)mip + 1, .layer = 0, .bits = CoreGraphics::ImageBits::ColorBits }; + CoreGraphics::CmdBlit(cmdBuf, id, from, id, to); CoreGraphics::CmdBarrier( cmdBuf, diff --git a/code/render/coregraphics/texture.h b/code/render/coregraphics/texture.h index ecc63b6387..86e2e80c8a 100644 --- a/code/render/coregraphics/texture.h +++ b/code/render/coregraphics/texture.h @@ -58,8 +58,8 @@ enum TextureUsage SampleTexture = 0x1, // Texture is a shader sampleable 1D, 2D, 3D or Cube texture RenderTexture = 0x2, // Texture supports to be rendered to as an attachment, also supports sampling ReadWriteTexture = 0x4, // Texture supports to be bound as an RWTexture (DX) or Image (GL/Vulkan), also supports sampling - TransferTextureSource = 0x8, // Texture supports being a copy source - TransferTextureDestination = 0x10, // Texture supports being a copy destination + TransferSourceTexture = 0x8, // Texture supports being a copy source + TransferDestinationTexture = 0x10, // Texture supports being a copy destination DeviceExclusive = 0x20 // Texture will be managed entirely by the device (copy target, RW target, etc) }; __ImplementEnumBitOperators(CoreGraphics::TextureUsage); @@ -293,8 +293,8 @@ TextureUsageFromString(const Util::String& string) if (comps[i] == "Sample") usage |= SampleTexture; else if (comps[i] == "Render") usage |= RenderTexture; else if (comps[i] == "ReadWrite") usage |= ReadWriteTexture; - else if (comps[i] == "TransferSource") usage |= TransferTextureSource; - else if (comps[i] == "TransferDestination") usage |= TransferTextureDestination; + else if (comps[i] == "TransferSource") usage |= TransferSourceTexture; + else if (comps[i] == "TransferDestination") usage |= TransferDestinationTexture; } return usage; diff --git a/code/render/coregraphics/vk/vkbarrier.cc b/code/render/coregraphics/vk/vkbarrier.cc index 2606705e8a..c884b1439e 100644 --- a/code/render/coregraphics/vk/vkbarrier.cc +++ b/code/render/coregraphics/vk/vkbarrier.cc @@ -69,9 +69,15 @@ CreateBarrier(const BarrierCreateInfo& info) bool isDepthStencil = AnyBits(subres.bits, CoreGraphics::ImageBits::DepthBits | CoreGraphics::ImageBits::StencilBits); vkInfo.imageBarriers[vkInfo.numImageBarriers].subresourceRange.aspectMask = VkTypes::AsVkImageAspectFlags(subres.bits); vkInfo.imageBarriers[vkInfo.numImageBarriers].subresourceRange.baseMipLevel = subres.mip; - vkInfo.imageBarriers[vkInfo.numImageBarriers].subresourceRange.levelCount = subres.mipCount; + if (subres.mipCount == NEBULA_ALL_MIPS) + vkInfo.imageBarriers[vkInfo.numImageBarriers].subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + else + vkInfo.imageBarriers[vkInfo.numImageBarriers].subresourceRange.levelCount = subres.mipCount; vkInfo.imageBarriers[vkInfo.numImageBarriers].subresourceRange.baseArrayLayer = subres.layer; - vkInfo.imageBarriers[vkInfo.numImageBarriers].subresourceRange.layerCount = subres.layerCount; + if (subres.layerCount == NEBULA_ALL_LAYERS) + vkInfo.imageBarriers[vkInfo.numImageBarriers].subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + else + vkInfo.imageBarriers[vkInfo.numImageBarriers].subresourceRange.layerCount = subres.layerCount; vkInfo.imageBarriers[vkInfo.numImageBarriers].image = TextureGetVkImage(info.textures[i].tex); if (info.fromQueue == QueueType::InvalidQueueType) vkInfo.imageBarriers[vkInfo.numImageBarriers].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; @@ -103,7 +109,7 @@ CreateBarrier(const BarrierCreateInfo& info) vkInfo.bufferBarriers[vkInfo.numBufferBarriers].offset = 0; vkInfo.bufferBarriers[vkInfo.numBufferBarriers].size = VK_WHOLE_SIZE; - if (info.buffers[i].subres.size == -1) + if (info.buffers[i].subres.size == NEBULA_WHOLE_BUFFER_SIZE) { vkInfo.bufferBarriers[vkInfo.numBufferBarriers].offset = 0; vkInfo.bufferBarriers[vkInfo.numBufferBarriers].size = VK_WHOLE_SIZE; diff --git a/code/render/coregraphics/vk/vkcommandbuffer.cc b/code/render/coregraphics/vk/vkcommandbuffer.cc index b2224f406e..eb194bfa46 100644 --- a/code/render/coregraphics/vk/vkcommandbuffer.cc +++ b/code/render/coregraphics/vk/vkcommandbuffer.cc @@ -209,6 +209,11 @@ CreateCmdBuffer(const CmdBufferCreateInfo& info) scissors.scissors.Resize(8); CmdBufferId ret = id; + +#if NEBULA_GRAPHICS_DEBUG + ObjectSetName(ret, info.name); +#endif + return ret; } @@ -733,7 +738,7 @@ CmdBarrier( VkTypes::AsVkAccessFlags(toStage) }; } - + // Insert barrier vkCmdPipelineBarrier(CmdBufferGetVk(id), fromFlags, @@ -742,6 +747,9 @@ CmdBarrier( numMemoryBarriers, &memBarrier, numBuffers, bufferBarriers, numImages, imageBarriers); + + StackFree(bufferBarriers); + StackFree(imageBarriers); } //------------------------------------------------------------------------------ @@ -875,6 +883,9 @@ CmdHandover( , numBuffers, bufferBarriers , numImages, imageBarriers ); + + StackFree(imageBarriers); + StackFree(bufferBarriers); } //------------------------------------------------------------------------------ @@ -954,12 +965,6 @@ CmdBeginPass(const CmdBufferId id, const PassId pass) bits |= CoreGraphics::CmdPipelineBuildBits::FramebufferLayoutInfoSet; bits &= ~CoreGraphics::CmdPipelineBuildBits::PipelineBuilt; - // Set viewports and scissors - auto viewports = PassGetViewports(pass); - CmdSetViewports(id, viewports); - auto scissors = PassGetRects(pass); - CmdSetScissors(id, scissors); - pipelineBundle.pass = pass; pipelineBundle.multisampleInfo.rasterizationSamples = framebufferInfo.pMultisampleState->rasterizationSamples; pipelineBundle.pipelineInfo.subpass = 0; @@ -990,21 +995,6 @@ CmdEndPass(const CmdBufferId id) vkCmdEndRenderPass(cmdBuf); } -//------------------------------------------------------------------------------ -/** -*/ -void -CmdResetClipToPass(const CmdBufferId id) -{ - VkPipelineBundle& pipelineBundle = commandBuffers.Get(id.id); - - // Set viewports and scissors - auto viewports = PassGetViewports(pipelineBundle.pass); - CmdSetViewports(id, viewports); - auto scissors = PassGetRects(pipelineBundle.pass); - CmdSetScissors(id, scissors); -} - //------------------------------------------------------------------------------ /** */ @@ -1316,35 +1306,29 @@ CmdCopy( void CmdBlit( const CmdBufferId id - , const CoreGraphics::TextureId from - , const Math::rectangle& fromRegion - , const CoreGraphics::ImageBits fromBits - , IndexT fromMip - , IndexT fromLayer - , const CoreGraphics::TextureId to - , const Math::rectangle& toRegion - , const CoreGraphics::ImageBits toBits - , IndexT toMip - , IndexT toLayer + , const CoreGraphics::TextureId fromTexture + , const CoreGraphics::TextureCopy& from + , const CoreGraphics::TextureId toTexture + , const CoreGraphics::TextureCopy& to ) { - n_assert(from != CoreGraphics::InvalidTextureId && to != CoreGraphics::InvalidTextureId); - n_assert(fromBits != CoreGraphics::ImageBits::Auto && toBits != CoreGraphics::ImageBits::Auto); + n_assert(fromTexture != CoreGraphics::InvalidTextureId && toTexture != CoreGraphics::InvalidTextureId); + n_assert(from.bits != CoreGraphics::ImageBits::Auto && to.bits != CoreGraphics::ImageBits::Auto); VkImageBlit blit; - blit.srcOffsets[0] = { fromRegion.left, fromRegion.top, 0 }; - blit.srcOffsets[1] = { fromRegion.right, fromRegion.bottom, 1 }; - blit.srcSubresource = { VkTypes::AsVkImageAspectFlags(fromBits), (uint32_t)fromMip, (uint32_t)fromLayer, 1 }; - blit.dstOffsets[0] = { toRegion.left, toRegion.top, 0 }; - blit.dstOffsets[1] = { toRegion.right, toRegion.bottom, 1 }; - blit.dstSubresource = { VkTypes::AsVkImageAspectFlags(toBits), (uint32_t)toMip, (uint32_t)toLayer, 1 }; + blit.srcOffsets[0] = { from.region.left, from.region.top, 0 }; + blit.srcOffsets[1] = { from.region.right, from.region.bottom, 1 }; + blit.srcSubresource = { VkTypes::AsVkImageAspectFlags(from.bits), (uint32_t)from.mip, (uint32_t)from.layer, 1 }; + blit.dstOffsets[0] = { to.region.left, to.region.top, 0 }; + blit.dstOffsets[1] = { to.region.right, to.region.bottom, 1 }; + blit.dstSubresource = { VkTypes::AsVkImageAspectFlags(to.bits), (uint32_t)to.mip, (uint32_t)to.layer, 1 }; VkCommandBuffer cmdBuf = commandBuffers.Get(id.id); vkCmdBlitImage( cmdBuf - , TextureGetVkImage(from) + , TextureGetVkImage(fromTexture) , VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL - , TextureGetVkImage(to) + , TextureGetVkImage(toTexture) , VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL , 1 , &blit diff --git a/code/render/coregraphics/vk/vkgraphicsdevice.cc b/code/render/coregraphics/vk/vkgraphicsdevice.cc index 48cc6fa2bb..b969761fbb 100644 --- a/code/render/coregraphics/vk/vkgraphicsdevice.cc +++ b/code/render/coregraphics/vk/vkgraphicsdevice.cc @@ -100,7 +100,6 @@ struct GraphicsDeviceState : CoreGraphics::GraphicsDeviceState Util::FixedArray pendingDeletes; Util::Array deletesPerSubmission; Util::FixedArray> waitEvents; - CoreGraphics::SubmissionWaitEvent mostRecentEvents[CoreGraphics::QueueType::NumQueueTypes]; struct PendingMarkers { @@ -128,14 +127,8 @@ struct GraphicsDeviceState : CoreGraphics::GraphicsDeviceState uint32_t usedExtensions; const char* extensions[64]; - uint32_t drawQueueFamily; - uint32_t computeQueueFamily; - uint32_t transferQueueFamily; - uint32_t sparseQueueFamily; - uint32_t drawQueueIdx; - uint32_t computeQueueIdx; - uint32_t transferQueueIdx; - uint32_t sparseQueueIdx; + uint32_t drawQueueFamily, computeQueueFamily, transferQueueFamily, sparseQueueFamily; + uint32_t drawQueueCount, computeQueueCount, transferQueueCount, sparseQueueCount; Util::Set usedQueueFamilies; Util::FixedArray queueFamilyMap; @@ -163,7 +156,6 @@ VkDebugUtilsMessengerEXT VkErrorDebugMessageHandle = nullptr; PFN_vkCreateDebugUtilsMessengerEXT VkCreateDebugMessenger = nullptr; PFN_vkDestroyDebugUtilsMessengerEXT VkDestroyDebugMessenger = nullptr; -PFN_vkSetDebugUtilsObjectNameEXT VkDebugObjectName = nullptr; PFN_vkSetDebugUtilsObjectTagEXT VkDebugObjectTag = nullptr; PFN_vkQueueBeginDebugUtilsLabelEXT VkQueueBeginLabel = nullptr; PFN_vkQueueEndDebugUtilsLabelEXT VkQueueEndLabel = nullptr; @@ -466,23 +458,7 @@ WaitForPresent(VkSemaphore sem) const VkQueue GetQueue(const CoreGraphics::QueueType type, const IndexT index) { - switch (type) - { - case CoreGraphics::GraphicsQueueType: - return state.queueHandler.drawQueues[index]; - break; - case CoreGraphics::ComputeQueueType: - return state.queueHandler.computeQueues[index]; - break; - case CoreGraphics::TransferQueueType: - return state.queueHandler.transferQueues[index]; - break; - case CoreGraphics::SparseQueueType: - return state.queueHandler.sparseQueues[index]; - break; - default: n_error("unhandled enum"); break; - } - return VK_NULL_HANDLE; + return state.queueHandler.queues[type][index]; } //------------------------------------------------------------------------------ @@ -524,7 +500,6 @@ SparseTextureBind(const VkImage img, const Util::Array& opaq // Set wait events in graphics device state.waitEvents[state.currentBufferedFrameIndex].Append(sparseWait); - state.mostRecentEvents[sparseWait.queue] = sparseWait; state.sparseImageBinds.Append(GraphicsDeviceState::SparseImageBind{.img = img, .opaqueBinds = opaqueBinds, .pageBinds = pageBinds}); //state.queueHandler.AppendSparseBind(CoreGraphics::SparseQueueType, img, opaqueBinds, pageBinds); @@ -780,97 +755,83 @@ CreateGraphicsDevice(const GraphicsDeviceCreateInfo& info) vkGetPhysicalDeviceQueueFamilyProperties(state.physicalDevices[state.currentDevice], &numQueues, queuesProps); vkGetPhysicalDeviceMemoryProperties(state.physicalDevices[state.currentDevice], &state.memoryProps); - state.drawQueueIdx = UINT32_MAX; - state.computeQueueIdx = UINT32_MAX; - state.transferQueueIdx = UINT32_MAX; - state.sparseQueueIdx = UINT32_MAX; + state.drawQueueFamily = UINT32_MAX; + state.computeQueueFamily = UINT32_MAX; + state.transferQueueFamily = UINT32_MAX; + state.sparseQueueFamily = UINT32_MAX; // create three queues for each family - Util::FixedArray indexMap; - indexMap.Resize(numQueues); - indexMap.Fill(0); for (i = 0; i < numQueues; i++) { - for (uint32_t j = 0; j < queuesProps[i].queueCount; j++) + int numQueues = queuesProps[i].queueCount; + // just pick whichever queue supports graphics, it will most likely only be 1 + if (AllBits(queuesProps[i].queueFlags, VK_QUEUE_GRAPHICS_BIT) + && state.drawQueueFamily == UINT32_MAX) { - // just pick whichever queue supports graphics, it will most likely only be 1 - if (AllBits(queuesProps[i].queueFlags, VK_QUEUE_GRAPHICS_BIT) - && state.drawQueueIdx == UINT32_MAX) - { - state.drawQueueFamily = i; - state.drawQueueIdx = j; - indexMap[i]++; - continue; - } + state.drawQueueFamily = i; + state.drawQueueCount = numQueues; + continue; + } - // find a compute queue which is not for graphics - if (AllBits(queuesProps[i].queueFlags, VK_QUEUE_COMPUTE_BIT) - && state.computeQueueIdx == UINT32_MAX) - { - state.computeQueueFamily = i; - state.computeQueueIdx = j; - indexMap[i]++; - continue; - } + // find a compute queue which is not for graphics + if (AllBits(queuesProps[i].queueFlags, VK_QUEUE_COMPUTE_BIT) + && state.computeQueueFamily == UINT32_MAX) + { + state.computeQueueFamily = i; + state.computeQueueCount = numQueues; + continue; + } - // find a transfer queue that is purely for transfers - if (AllBits(queuesProps[i].queueFlags, VK_QUEUE_TRANSFER_BIT) - && state.transferQueueIdx == UINT32_MAX) - { - state.transferQueueFamily = i; - state.transferQueueIdx = j; - indexMap[i]++; - continue; - } + // find a transfer queue that is purely for transfers + if (AllBits(queuesProps[i].queueFlags, VK_QUEUE_TRANSFER_BIT) + && state.transferQueueFamily == UINT32_MAX) + { + state.transferQueueFamily = i; + state.transferQueueCount = numQueues; + continue; + } - // find a sparse or transfer queue that supports sparse binding - if (AllBits(queuesProps[i].queueFlags, VK_QUEUE_SPARSE_BINDING_BIT) - && state.sparseQueueIdx == UINT32_MAX) - { - state.sparseQueueFamily = i; - state.sparseQueueIdx = j; - indexMap[i]++; - continue; - } + // find a sparse or transfer queue that supports sparse binding + if (AllBits(queuesProps[i].queueFlags, VK_QUEUE_SPARSE_BINDING_BIT) + && state.sparseQueueFamily == UINT32_MAX) + { + state.sparseQueueFamily = i; + state.sparseQueueCount = numQueues; + continue; } } // could not find pure compute queue - if (state.computeQueueIdx == UINT32_MAX) + if (state.computeQueueFamily == UINT32_MAX) { // assert that the graphics queue can handle computes - n_assert(queuesProps[state.drawQueueFamily].queueFlags& VK_QUEUE_COMPUTE_BIT); + n_assert(queuesProps[state.drawQueueFamily].queueFlags & VK_QUEUE_COMPUTE_BIT); state.computeQueueFamily = state.drawQueueFamily; - state.computeQueueIdx = state.drawQueueIdx; + state.computeQueueCount = 1; } // could not find pure transfer queue - if (state.transferQueueIdx == UINT32_MAX) + if (state.transferQueueFamily == UINT32_MAX) { // assert the draw queue can handle transfers n_assert(queuesProps[state.drawQueueFamily].queueFlags & VK_QUEUE_TRANSFER_BIT); state.transferQueueFamily = state.drawQueueFamily; - state.transferQueueIdx = state.drawQueueIdx; + state.transferQueueCount = 1; } // could not find pure transfer queue - if (state.sparseQueueIdx == UINT32_MAX) + if (state.sparseQueueFamily == UINT32_MAX) { if (queuesProps[state.transferQueueFamily].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) { state.sparseQueueFamily = state.transferQueueFamily; - - // if we have an extra transfer queue, use it for sparse bindings - if (queuesProps[state.sparseQueueFamily].queueCount > indexMap[state.sparseQueueFamily]) - state.sparseQueueIdx = indexMap[state.sparseQueueFamily]++; - else - state.sparseQueueIdx = state.transferQueueIdx; + state.sparseQueueCount = state.transferQueueCount; } else { n_warn2(queuesProps[state.drawQueueFamily].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT, "VkGraphicsDevice: No sparse binding queue could be found!\n"); state.sparseQueueFamily = state.drawQueueFamily; - state.sparseQueueIdx = state.drawQueueIdx; + state.sparseQueueCount = state.drawQueueCount; } } @@ -879,23 +840,38 @@ CreateGraphicsDevice(const GraphicsDeviceCreateInfo& info) if (state.transferQueueFamily == UINT32_MAX) n_error("VkGraphicsDevice: Could not find a queue for transfers.\n"); if (state.sparseQueueFamily == UINT32_MAX) n_warning("VkGraphicsDevice: Could not find a queue for sparse binding.\n"); + // This setup must match the enum CoreGraphics::QueueType + Util::FixedArray> queueSetup = + { + { state.drawQueueFamily, state.drawQueueCount } + , { state.computeQueueFamily, state.computeQueueCount } + , { state.transferQueueFamily, state.transferQueueCount } + , { state.sparseQueueFamily, state.sparseQueueCount } + }; + + Util::Dictionary uniqueQueues; + for (auto& [family, count] : queueSetup) + { + uniqueQueues.Emplace(family) = count; + } + // create device Util::FixedArray> prios; Util::Array queueInfos; - prios.Resize(numQueues); + prios.Resize(uniqueQueues.Size()); - for (i = 0; i < numQueues; i++) + for (i = 0; i < uniqueQueues.Size(); i++) { - if (indexMap[i] == 0) continue; - prios[i].Resize(indexMap[i]); + auto& [family, count] = uniqueQueues.KeyValuePairAtIndex(i); + prios[i].Resize(count); prios[i].Fill(1.0f); queueInfos.Append( { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, nullptr, 0, - i, - indexMap[i], + family, + count, &prios[i][0] }); } @@ -1018,24 +994,10 @@ CreateGraphicsDevice(const GraphicsDeviceCreateInfo& info) .rayTraversalPrimitiveCulling = false }; - VkPhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT groupHandlesFeature = - { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT, - .pNext = &raytracingFeatures, - .pipelineLibraryGroupHandles = true - }; - - VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT libraryFeature = - { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT, - .pNext = &groupHandlesFeature, - .graphicsPipelineLibrary = true - }; - VkPhysicalDevice16BitStorageFeatures buffer16BitFeature = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES, - .pNext = &libraryFeature, + .pNext = &raytracingFeatures, .storageBuffer16BitAccess = true, .uniformAndStorageBuffer16BitAccess = true, .storagePushConstant16 = false, @@ -1053,7 +1015,7 @@ CreateGraphicsDevice(const GraphicsDeviceCreateInfo& info) lastExtension, 0, (uint32_t)queueInfos.Size(), - &queueInfos[0], + queueInfos.Begin(), (uint32_t)numLayers, layers, state.numCaps[state.currentDevice], @@ -1066,12 +1028,7 @@ CreateGraphicsDevice(const GraphicsDeviceCreateInfo& info) n_assert(res == VK_SUCCESS); // setup queue handler - Util::FixedArray families(4); - families[GraphicsQueueType] = state.drawQueueFamily; - families[ComputeQueueType] = state.computeQueueFamily; - families[TransferQueueType] = state.transferQueueFamily; - families[SparseQueueType] = state.sparseQueueFamily; - state.queueHandler.Setup(state.devices[state.currentDevice], indexMap, families); + state.queueHandler.Setup(state.devices[state.currentDevice], queueSetup); state.usedQueueFamilies.Add(state.drawQueueFamily); state.usedQueueFamilies.Add(state.computeQueueFamily); @@ -1153,7 +1110,11 @@ CreateGraphicsDevice(const GraphicsDeviceCreateInfo& info) for (i = 0; i < info.numBufferedFrames; i++) { state.presentFences[i] = CreateFence({true}); - state.renderingFinishedSemaphores[i] = CreateSemaphore({ SemaphoreType::Binary }); + state.renderingFinishedSemaphores[i] = CreateSemaphore({ +#if NEBULA_GRAPHICS_DEBUG + .name = "Present", +#endif + .type = SemaphoreType::Binary }); } #pragma pop_macro("CreateSemaphore") @@ -1243,7 +1204,7 @@ CreateGraphicsDevice(const GraphicsDeviceCreateInfo& info) vboInfo.name = "Global Vertex Cache"; vboInfo.byteSize = info.globalVertexBufferMemorySize; vboInfo.mode = CoreGraphics::BufferAccessMode::DeviceLocal; - vboInfo.queueSupport = CoreGraphics::BufferQueueSupport::GraphicsQueueSupport | CoreGraphics::BufferQueueSupport::ComputeQueueSupport; + vboInfo.queueSupport = CoreGraphics::BufferQueueSupport::GraphicsQueueSupport | CoreGraphics::BufferQueueSupport::ComputeQueueSupport | CoreGraphics::BufferQueueSupport::TransferQueueSupport; vboInfo.usageFlags = CoreGraphics::BufferUsageFlag::VertexBuffer | CoreGraphics::BufferUsageFlag::TransferBufferDestination @@ -1257,7 +1218,7 @@ CreateGraphicsDevice(const GraphicsDeviceCreateInfo& info) iboInfo.name = "Global Index Cache"; iboInfo.byteSize = info.globalIndexBufferMemorySize; iboInfo.mode = CoreGraphics::BufferAccessMode::DeviceLocal; - iboInfo.queueSupport = CoreGraphics::BufferQueueSupport::GraphicsQueueSupport | CoreGraphics::BufferQueueSupport::ComputeQueueSupport; + iboInfo.queueSupport = CoreGraphics::BufferQueueSupport::GraphicsQueueSupport | CoreGraphics::BufferQueueSupport::ComputeQueueSupport | CoreGraphics::BufferQueueSupport::TransferQueueSupport; iboInfo.usageFlags = CoreGraphics::BufferUsageFlag::IndexBuffer | CoreGraphics::BufferUsageFlag::TransferBufferDestination @@ -1271,7 +1232,7 @@ CreateGraphicsDevice(const GraphicsDeviceCreateInfo& info) uploadInfo.name = "Global Upload Buffer"; uploadInfo.byteSize = Math::align(info.globalUploadMemorySize, state.deviceProps[state.currentDevice].properties.limits.nonCoherentAtomSize); uploadInfo.mode = CoreGraphics::BufferAccessMode::HostLocal; - uploadInfo.queueSupport = CoreGraphics::BufferQueueSupport::GraphicsQueueSupport | CoreGraphics::BufferQueueSupport::ComputeQueueSupport; + uploadInfo.queueSupport = CoreGraphics::BufferQueueSupport::GraphicsQueueSupport | CoreGraphics::BufferQueueSupport::ComputeQueueSupport | CoreGraphics::BufferQueueSupport::TransferQueueSupport; uploadInfo.usageFlags = CoreGraphics::BufferUsageFlag::TransferBufferSource; state.uploadBuffer = CoreGraphics::CreateBuffer(uploadInfo); @@ -1470,6 +1431,7 @@ LockTransferSetupCommandBuffer() cmdCreateInfo.pool = state.setupTransferCommandBufferPool; cmdCreateInfo.usage = CoreGraphics::QueueType::TransferQueueType; cmdCreateInfo.queryTypes = CoreGraphics::CmdBufferQueryBits::NoQueries; + cmdCreateInfo.name = "Setup Transfer"; state.setupTransferCommandBuffer = CoreGraphics::CreateCmdBuffer(cmdCreateInfo); CoreGraphics::CmdBeginRecord(state.setupTransferCommandBuffer, { true, false, false }); @@ -1506,6 +1468,7 @@ LockGraphicsSetupCommandBuffer() cmdCreateInfo.pool = state.setupGraphicsCommandBufferPool; cmdCreateInfo.usage = CoreGraphics::QueueType::GraphicsQueueType; cmdCreateInfo.queryTypes = CoreGraphics::CmdBufferQueryBits::NoQueries; + cmdCreateInfo.name = "Setup"; state.setupGraphicsCommandBuffer = CoreGraphics::CreateCmdBuffer(cmdCreateInfo); CoreGraphics::CmdBeginRecord(state.setupGraphicsCommandBuffer, { true, false, false }); @@ -1542,6 +1505,7 @@ LockTransferHandoverSetupCommandBuffer() cmdCreateInfo.pool = state.setupTransferCommandBufferPool; cmdCreateInfo.usage = CoreGraphics::QueueType::TransferQueueType; cmdCreateInfo.queryTypes = CoreGraphics::CmdBufferQueryBits::NoQueries; + cmdCreateInfo.name = "Transfer Handover"; state.handoverTransferCommandBuffer = CoreGraphics::CreateCmdBuffer(cmdCreateInfo); CoreGraphics::CmdBeginRecord(state.handoverTransferCommandBuffer, { true, false, false }); @@ -1590,25 +1554,29 @@ void AddSubmissionEvent(const CoreGraphics::SubmissionWaitEvent& event) { state.waitEvents[state.currentBufferedFrameIndex].Append(event); - state.mostRecentEvents[event.queue] = event; } //------------------------------------------------------------------------------ /** */ +CoreGraphics::SubmissionWaitEvent handoverWait, graphicsWait, uploadWait; CoreGraphics::SubmissionWaitEvent -SubmitCommandBuffer(const CoreGraphics::CmdBufferId cmds, CoreGraphics::QueueType type) +SubmitCommandBuffer( + const CoreGraphics::CmdBufferId cmds + , CoreGraphics::QueueType type +#if NEBULA_GRAPHICS_DEBUG + , const char* name +#endif +) { // Submit transfer and graphics commands from this frame - CoreGraphics::SubmissionWaitEvent handoverWait, graphicsWait; transferLock.Enter(); if (state.setupTransferCommandBuffer != CoreGraphics::InvalidCmdBufferId) { CmdBufferIdAcquire(state.setupTransferCommandBuffer); CmdEndMarker(state.setupTransferCommandBuffer); CmdEndRecord(state.setupTransferCommandBuffer); - CoreGraphics::SubmissionWaitEvent uploadWait; - uploadWait.timelineIndex = state.queueHandler.AppendSubmissionTimeline(CoreGraphics::TransferQueueType, CmdBufferGetVk(state.setupTransferCommandBuffer)); + uploadWait.timelineIndex = state.queueHandler.AppendSubmissionTimeline(CoreGraphics::TransferQueueType, CmdBufferGetVk(state.setupTransferCommandBuffer), "Transfer"); uploadWait.queue = CoreGraphics::TransferQueueType; // Set wait events in graphics device @@ -1627,7 +1595,7 @@ SubmitCommandBuffer(const CoreGraphics::CmdBufferId cmds, CoreGraphics::QueueTyp CmdBufferIdAcquire(state.handoverTransferCommandBuffer); CmdEndMarker(state.handoverTransferCommandBuffer); CmdEndRecord(state.handoverTransferCommandBuffer); - handoverWait.timelineIndex = state.queueHandler.AppendSubmissionTimeline(CoreGraphics::TransferQueueType, CmdBufferGetVk(state.handoverTransferCommandBuffer)); + handoverWait.timelineIndex = state.queueHandler.AppendSubmissionTimeline(CoreGraphics::TransferQueueType, CmdBufferGetVk(state.handoverTransferCommandBuffer), "Handover"); handoverWait.queue = CoreGraphics::TransferQueueType; // Set wait events in graphics device @@ -1649,12 +1617,12 @@ SubmitCommandBuffer(const CoreGraphics::CmdBufferId cmds, CoreGraphics::QueueTyp CmdEndMarker(state.setupGraphicsCommandBuffer); CmdEndRecord(state.setupGraphicsCommandBuffer); - graphicsWait.timelineIndex = state.queueHandler.AppendSubmissionTimeline(CoreGraphics::GraphicsQueueType, CmdBufferGetVk(state.setupGraphicsCommandBuffer)); + graphicsWait.timelineIndex = state.queueHandler.AppendSubmissionTimeline(CoreGraphics::GraphicsQueueType, CmdBufferGetVk(state.setupGraphicsCommandBuffer), "Setup"); graphicsWait.queue = CoreGraphics::GraphicsQueueType; // This command buffer will have handover commands, so wait for that transfer if (handoverWait != nullptr) - state.queueHandler.AppendWaitTimeline(handoverWait.timelineIndex, CoreGraphics::GraphicsQueueType, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, CoreGraphics::TransferQueueType); + state.queueHandler.AppendWaitTimeline(handoverWait.timelineIndex, CoreGraphics::GraphicsQueueType, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, handoverWait.queue); // Add wait event AddSubmissionEvent(graphicsWait); @@ -1670,7 +1638,13 @@ SubmitCommandBuffer(const CoreGraphics::CmdBufferId cmds, CoreGraphics::QueueTyp // Append submission CoreGraphics::SubmissionWaitEvent ret; - ret.timelineIndex = state.queueHandler.AppendSubmissionTimeline(type, CmdBufferGetVk(cmds)); + ret.timelineIndex = state.queueHandler.AppendSubmissionTimeline( + type + , CmdBufferGetVk(cmds) +#if NEBULA_GRAPHICS_DEBUG + , name +#endif + ); ret.queue = type; // Add wait event @@ -1686,18 +1660,9 @@ SubmitCommandBuffer(const CoreGraphics::CmdBufferId cmds, CoreGraphics::QueueTyp /** */ void -WaitForSubmission(SubmissionWaitEvent index, CoreGraphics::QueueType type, CoreGraphics::QueueType waitType) +WaitForSubmission(SubmissionWaitEvent index, CoreGraphics::QueueType type) { - state.queueHandler.AppendWaitTimeline(index.timelineIndex, type, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, waitType); -} - -//------------------------------------------------------------------------------ -/** -*/ -void -WaitForLastSubmission(CoreGraphics::QueueType type, CoreGraphics::QueueType waitType) -{ - state.queueHandler.AppendWaitTimeline(state.mostRecentEvents[waitType].timelineIndex, type, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, waitType); + state.queueHandler.AppendWaitTimeline(index.timelineIndex, type, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, index.queue); } //------------------------------------------------------------------------------ @@ -1789,20 +1754,13 @@ FinishFrame(IndexT frameIndex) state.currentFrameIndex = frameIndex; } - // Flush all pending submissions on the queues - state.queueHandler.FlushSparseBinds(nullptr); - //state.queueHandler.FlushSubmissionsTimeline(CoreGraphics::SparseQueueType, nullptr); - state.queueHandler.FlushSubmissionsTimeline(CoreGraphics::TransferQueueType, nullptr); - state.queueHandler.FlushSubmissionsTimeline(CoreGraphics::ComputeQueueType, nullptr); - // Signal rendering finished semaphore just before submitting graphics queue state.queueHandler.AppendPresentSignal( - GraphicsQueueType, + ComputeQueueType, SemaphoreGetVk(state.renderingFinishedSemaphores[state.currentBufferedFrameIndex]) ); - // Flush graphics (main) - state.queueHandler.FlushSubmissionsTimeline(CoreGraphics::GraphicsQueueType, nullptr); + state.queueHandler.FlushSubmissions(nullptr); if (!state.sparseBufferBinds.IsEmpty() || !state.sparseImageBinds.IsEmpty()) { @@ -1823,6 +1781,10 @@ FinishFrame(IndexT frameIndex) state.sparseBufferBinds.Clear(); state.sparseImageBinds.Clear(); } + + uploadWait = nullptr; + graphicsWait = nullptr; + handoverWait = nullptr; } //------------------------------------------------------------------------------ @@ -1846,7 +1808,17 @@ WaitAndClearPendingCommands() state.queueHandler.WaitIdle(SparseQueueType); vkDeviceWaitIdle(state.devices[state.currentDevice]); - Vulkan::ClearPending(); + for (int buffer = 0; buffer < state.maxNumBufferedFrames; buffer++) + { + state.currentBufferedFrameIndex = buffer; + Vulkan::ClearPending(); + + // Reset queries + for (IndexT i = 0; i < CoreGraphics::QueryType::NumQueryTypes; i++) + { + state.queries[buffer].queryFreeCount[i] = 0; + } + } } //------------------------------------------------------------------------------ diff --git a/code/render/coregraphics/vk/vkloader.cc b/code/render/coregraphics/vk/vkloader.cc index 21f4586363..3fde32ceac 100644 --- a/code/render/coregraphics/vk/vkloader.cc +++ b/code/render/coregraphics/vk/vkloader.cc @@ -10,7 +10,7 @@ #endif namespace Vulkan { - +PFN_vkSetDebugUtilsObjectNameEXT VkDebugObjectName = nullptr; //------------------------------------------------------------------------------ /** */ diff --git a/code/render/coregraphics/vk/vkloader.h b/code/render/coregraphics/vk/vkloader.h index 9111ca1af8..2f36f24e31 100644 --- a/code/render/coregraphics/vk/vkloader.h +++ b/code/render/coregraphics/vk/vkloader.h @@ -26,12 +26,16 @@ extern void InitVulkan(); /// initialize Vulkan instance, loads function pointers directly from driver extern void InitInstance(VkInstance instance); +extern PFN_vkSetDebugUtilsObjectNameEXT VkDebugObjectName; + + } // namespace Vulkan #define _IMP_VK(name) name = (PFN_##name)vkGetInstanceProcAddr(instance, #name);n_assert_fmt(name != nullptr, "Unable to get function proc: %s\n",#name); #define _DEC_VK(name) extern PFN_##name name; #define _DEF_VK(name) PFN_##name name; + #ifdef __cplusplus extern "C" { #endif @@ -217,6 +221,7 @@ _DEC_VK(vkGetRayTracingShaderGroupHandlesKHR); // mesh shaders _DEC_VK(vkCmdDrawMeshTasksEXT); + #ifdef __cplusplus } #endif diff --git a/code/render/coregraphics/vk/vkpass.cc b/code/render/coregraphics/vk/vkpass.cc index d032018b29..711a536e6a 100644 --- a/code/render/coregraphics/vk/vkpass.cc +++ b/code/render/coregraphics/vk/vkpass.cc @@ -11,6 +11,8 @@ #include "vktextureview.h" #include "coregraphics/pass.h" +#include "system_shaders/shared.h" + using namespace CoreGraphics; namespace Vulkan { @@ -130,8 +132,6 @@ GetSubpassInfo( , Util::Array& outDeps , Util::FixedArray& outAttachments , Util::Array& usedAttachmentCounts - , Util::FixedArray>>& outViewports - , Util::FixedArray>>& outScissorRects , Util::FixedArray& outPipelineInfos , uint32& numUsedAttachmentsTotal) { @@ -161,8 +161,6 @@ GetSubpassInfo( // resize rects n_assert(subpass.numViewports >= subpass.attachments.Size()); n_assert(subpass.numScissors >= subpass.attachments.Size()); - outViewports[i].Resize(subpass.numViewports); - outScissorRects[i].Resize(subpass.numScissors); outPipelineInfos[i] = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, @@ -196,13 +194,6 @@ GetSubpassInfo( ds.attachment = subpass.depth; consumedAttachments[subpass.depth] = true; - - if (subpass.attachments.IsEmpty()) - { - outViewports[i][j] = VkViewportToRect(loadInfo.viewports[subpass.depth]); - outScissorRects[i][j] = VkScissorToRect(loadInfo.rects[subpass.depth]); - j++; - } } else { @@ -225,10 +216,6 @@ GetSubpassInfo( consumedAttachments[attachment] = true; usedAttachments++; - - outViewports[i][j] = VkViewportToRect(loadInfo.viewports[ref.attachment]); - outScissorRects[i][j] = VkScissorToRect(loadInfo.rects[ref.attachment]); - j++; } for (IndexT k = 0; k < subpass.resolves.Size(); k++) @@ -522,8 +509,6 @@ SetupPass(const PassId pid) // resize subpass contents subpassDescs.Resize(loadInfo.subpasses.Size()); attachments.Resize(loadInfo.attachments.Size() + 1); - runtimeInfo.subpassViewports.Resize(loadInfo.subpasses.Size()); - runtimeInfo.subpassRects.Resize(loadInfo.subpasses.Size()); runtimeInfo.subpassPipelineInfo.Resize(loadInfo.subpasses.Size()); uint32 numUsedAttachmentsTotal = 0; @@ -534,8 +519,6 @@ SetupPass(const PassId pid) , subpassDeps , attachments , subpassAttachmentCounts - , runtimeInfo.subpassViewports - , runtimeInfo.subpassRects , runtimeInfo.subpassPipelineInfo , numUsedAttachmentsTotal); @@ -583,15 +566,15 @@ SetupPass(const PassId pid) { // setup uniform buffer for render target information ShaderId sid = CoreGraphics::ShaderGet("shd:system_shaders/shared.fxb"_atm); - loadInfo.passBlockBuffer = CoreGraphics::ShaderCreateConstantBuffer(sid, "PassBlock"); - loadInfo.renderTargetDimensionsVar = ShaderGetConstantBinding(sid, "RenderTargetDimensions"); + runtimeInfo.passBlockBuffer = CoreGraphics::ShaderCreateConstantBuffer(sid, "PassBlock", CoreGraphics::BufferAccessMode::DeviceAndHost); + runtimeInfo.renderTargetDimensionsVar = ShaderGetConstantBinding(sid, "RenderTargetParameter"); CoreGraphics::ResourceTableLayoutId tableLayout = ShaderGetResourceTableLayout(sid, NEBULA_PASS_GROUP); runtimeInfo.passDescriptorSet = CreateResourceTable(ResourceTableCreateInfo{ tableLayout, 8 }); runtimeInfo.passPipelineLayout = ShaderGetResourcePipeline(sid); CoreGraphics::ResourceTableBuffer write; - write.buf = loadInfo.passBlockBuffer; + write.buf = runtimeInfo.passBlockBuffer; write.offset = 0; write.size = NEBULA_WHOLE_BUFFER_SIZE; write.index = 0; @@ -605,39 +588,34 @@ SetupPass(const PassId pid) for (i = 0; i < loadInfo.attachments.Size(); i++) { n_assert(j < 16); // only allow 8 input attachments in the shader, so we must limit it - CoreGraphics::ResourceTableInputAttachment write; if (!loadInfo.attachmentIsDepthStencil[i]) { + CoreGraphics::ResourceTableInputAttachment write; write.tex = loadInfo.attachments[i]; write.isDepth = false; write.sampler = InvalidSamplerId; write.slot = Shared::Table_Pass::InputAttachment0_SLOT + j; write.index = 0; + ResourceTableSetInputAttachment(runtimeInfo.passDescriptorSet, write); } - else - { - write.tex = loadInfo.attachments[i]; - write.isDepth = true; - write.sampler = InvalidSamplerId; - write.slot = Shared::Table_Pass::DepthAttachment_SLOT; - write.index = 0; - } - ResourceTableSetInputAttachment(runtimeInfo.passDescriptorSet, write); } ResourceTableCommitChanges(runtimeInfo.passDescriptorSet); } // Calculate texture dimensions - Util::FixedArray dimensions(loadInfo.attachments.Size()); + Util::FixedArray params(loadInfo.attachments.Size()); for (i = 0; i < loadInfo.attachments.Size(); i++) { // update descriptor set based on images attachments TextureId tex = TextureViewGetTexture(loadInfo.attachments[i]); const CoreGraphics::TextureDimensions rtdims = TextureGetDimensions(tex); - Math::vec4& dims = dimensions[i]; - dims = Math::vec4((Math::scalar)rtdims.width, (Math::scalar)rtdims.height, 1 / (Math::scalar)rtdims.width, 1 / (Math::scalar)rtdims.height); + Shared::RenderTargetParameters& rtParams = params[i]; + Math::vec4 dimensions = Math::vec4((Math::scalar)rtdims.width, (Math::scalar)rtdims.height, 1 / (Math::scalar)rtdims.width, 1 / (Math::scalar)rtdims.height); + dimensions.storeu(rtParams.Dimensions); + rtParams.Scale[0] = 1; + rtParams.Scale[1] = 1; } - BufferUpdateArray(loadInfo.passBlockBuffer, dimensions.Begin(), dimensions.Size(), loadInfo.renderTargetDimensionsVar); + BufferUpdateArray(runtimeInfo.passBlockBuffer, params.Begin(), params.Size(), runtimeInfo.renderTargetDimensionsVar); // setup info runtimeInfo.framebufferPipelineInfo.renderPass = loadInfo.pass; @@ -725,9 +703,9 @@ DestroyPass(const PassId id) // destroy pass and our descriptor set DestroyResourceTable(runtimeInfo.passDescriptorSet); - DestroyBuffer(loadInfo.passBlockBuffer); + DestroyBuffer(runtimeInfo.passBlockBuffer); runtimeInfo.passDescriptorSet = ResourceTableId::Invalid(); - loadInfo.passBlockBuffer = BufferId::Invalid(); + runtimeInfo.passBlockBuffer = BufferId::Invalid(); DelayedDeletePass(id); } @@ -752,6 +730,16 @@ PassWindowResizeCallback(const PassId id) SetupPass(id); } +//------------------------------------------------------------------------------ +/** +*/ +void +PassSetRenderTargetParameters(const PassId id, const Util::FixedArray& viewports) +{ + VkPassRuntimeInfo& runtimeInfo = passAllocator.Get(id.id); + BufferUpdateArray(runtimeInfo.passBlockBuffer, viewports.Begin(), viewports.Size(), runtimeInfo.renderTargetDimensionsVar); +} + //------------------------------------------------------------------------------ /** */ @@ -789,24 +777,4 @@ PassGetName(const CoreGraphics::PassId id) return passAllocator.Get(id.id).name; } -//------------------------------------------------------------------------------ -/** -*/ -const Util::FixedArray>& -PassGetRects(const CoreGraphics::PassId& id) -{ - const VkPassRuntimeInfo& info = passAllocator.Get(id.id); - return info.subpassRects[info.currentSubpassIndex]; -} - -//------------------------------------------------------------------------------ -/** -*/ -const Util::FixedArray>& -PassGetViewports(const CoreGraphics::PassId& id) -{ - const VkPassRuntimeInfo& info = passAllocator.Get(id.id); - return info.subpassViewports[info.currentSubpassIndex]; -} - } // namespace Vulkan diff --git a/code/render/coregraphics/vk/vkpass.h b/code/render/coregraphics/vk/vkpass.h index 69f8e7c1e4..b10b69bc8e 100644 --- a/code/render/coregraphics/vk/vkpass.h +++ b/code/render/coregraphics/vk/vkpass.h @@ -20,9 +20,7 @@ struct VkPassLoadInfo VkDevice dev; Util::StringAtom name; - // these hold the per-pass shader state - CoreGraphics::BufferId passBlockBuffer; - IndexT renderTargetDimensionsVar; + // we need these stored for resizing Util::Array attachments; @@ -42,6 +40,10 @@ struct VkPassLoadInfo struct VkPassRuntimeInfo { + // these hold the per-pass shader state + CoreGraphics::BufferId passBlockBuffer; + IndexT renderTargetDimensionsVar; + VkGraphicsPipelineCreateInfo framebufferPipelineInfo; VkPipelineMultisampleStateCreateInfo multisampleInfo; VkPipelineViewportStateCreateInfo viewportInfo; @@ -50,8 +52,6 @@ struct VkPassRuntimeInfo CoreGraphics::ResourceTableId passDescriptorSet; CoreGraphics::ResourcePipelineId passPipelineLayout; - Util::FixedArray>> subpassRects; - Util::FixedArray>> subpassViewports; Util::FixedArray subpassPipelineInfo; CoreGraphics::PassRecordMode recordMode; }; diff --git a/code/render/coregraphics/vk/vkresourcetable.cc b/code/render/coregraphics/vk/vkresourcetable.cc index 1d5fb20ad9..f5bcbd86ac 100644 --- a/code/render/coregraphics/vk/vkresourcetable.cc +++ b/code/render/coregraphics/vk/vkresourcetable.cc @@ -16,8 +16,6 @@ namespace Vulkan { -extern PFN_vkSetDebugUtilsObjectNameEXT VkDebugObjectName; - VkResourceTableAllocator resourceTableAllocator; VkResourceTableLayoutAllocator resourceTableLayoutAllocator; VkResourcePipelineAllocator resourcePipelineAllocator; diff --git a/code/render/coregraphics/vk/vksemaphore.cc b/code/render/coregraphics/vk/vksemaphore.cc index 2603d059a6..a9068fe774 100644 --- a/code/render/coregraphics/vk/vksemaphore.cc +++ b/code/render/coregraphics/vk/vksemaphore.cc @@ -55,9 +55,25 @@ CreateSemaphore(const SemaphoreCreateInfo& info) semaphoreAllocator.Get(id) = dev; semaphoreAllocator.Get(id) = info.type; - VkResult res = vkCreateSemaphore(dev, &cinfo, nullptr, &semaphoreAllocator.Get(id)); + VkSemaphore sem; + VkResult res = vkCreateSemaphore(dev, &cinfo, nullptr, &sem); n_assert(res == VK_SUCCESS); + semaphoreAllocator.Set(id, sem); + +#if NEBULA_GRAPHICS_DEBUG + VkDebugUtilsObjectNameInfoEXT semInfo = + { + VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, + nullptr, + VK_OBJECT_TYPE_SEMAPHORE, + (uint64_t)sem, + info.name + }; + VkResult res2 = VkDebugObjectName(dev, &semInfo); + n_assert(res2 == VK_SUCCESS); +#endif + SemaphoreId ret = id; return ret; } diff --git a/code/render/coregraphics/vk/vkshaperenderer.cc b/code/render/coregraphics/vk/vkshaperenderer.cc index 028e9957b0..3f549da65a 100644 --- a/code/render/coregraphics/vk/vkshaperenderer.cc +++ b/code/render/coregraphics/vk/vkshaperenderer.cc @@ -12,6 +12,8 @@ #include "resources/resourceserver.h" #include "frame/framesubgraph.h" +#include "frame/default.h" + using namespace Base; using namespace Threading; using namespace Math; @@ -113,16 +115,13 @@ VkShapeRenderer::Open() // also create an extra vertex layout, in case we get a mesh which doesn't fit with our special layout this->vertexLayout = CreateVertexLayout(VertexLayoutCreateInfo{ .name = "Vulkan Shape Renderer"_atm, .comps = comps }); - Frame::FrameCode* op = this->frameOpAllocator.Alloc(); - op->domain = CoreGraphics::BarrierDomain::Pass; - op->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_DebugShapes_Pass([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { auto thisPtr = static_cast(VkShapeRenderer::Instance()); thisPtr->DrawShapes(cmdBuf); thisPtr->numIndicesThisFrame = 0; thisPtr->numVerticesThisFrame = 0; - }; - Frame::AddSubgraph("Debug Shapes", { op }); + }); } //------------------------------------------------------------------------------ @@ -164,7 +163,6 @@ VkShapeRenderer::Close() } this->vertexBufferPtr = this->indexBufferPtr = nullptr; - this->frameOpAllocator.Release(); // call parent class ShapeRendererBase::Close(); diff --git a/code/render/coregraphics/vk/vkshaperenderer.h b/code/render/coregraphics/vk/vkshaperenderer.h index 14c62c26ac..88fc8dfcbc 100644 --- a/code/render/coregraphics/vk/vkshaperenderer.h +++ b/code/render/coregraphics/vk/vkshaperenderer.h @@ -83,8 +83,6 @@ class VkShapeRenderer : public Base::ShapeRendererBase SizeT vertexBufferOffset; SizeT indexBufferOffset; - Memory::ArenaAllocator frameOpAllocator; - struct IndexedDraws { Util::Array primitives; diff --git a/code/render/coregraphics/vk/vksubcontexthandler.cc b/code/render/coregraphics/vk/vksubcontexthandler.cc index d34d5520c6..f9803d5295 100644 --- a/code/render/coregraphics/vk/vksubcontexthandler.cc +++ b/code/render/coregraphics/vk/vksubcontexthandler.cc @@ -9,6 +9,7 @@ namespace Vulkan { + //------------------------------------------------------------------------------ /** */ @@ -28,76 +29,78 @@ VkSubContextHandler::~VkSubContextHandler() /** */ void -VkSubContextHandler::Setup(VkDevice dev, const Util::FixedArray indexMap, const Util::FixedArray families) +VkSubContextHandler::Setup(VkDevice dev, const Util::FixedArray> queueMap) { // store device this->device = dev; - // get all queues related to their respective family (we can have more draw queues than 1, for example) - this->drawQueues.Resize(1); - this->computeQueues.Resize(1); - this->transferQueues.Resize(1); - this->sparseQueues.Resize(1); - - this->queueFamilies[CoreGraphics::GraphicsQueueType] = families[CoreGraphics::GraphicsQueueType]; - this->queueFamilies[CoreGraphics::ComputeQueueType] = families[CoreGraphics::ComputeQueueType]; - this->queueFamilies[CoreGraphics::TransferQueueType] = families[CoreGraphics::TransferQueueType]; - this->queueFamilies[CoreGraphics::SparseQueueType] = families[CoreGraphics::SparseQueueType]; - - Util::FixedArray queueUses(CoreGraphics::QueueType::NumQueueTypes, 0); - - SizeT i; - for (i = 0; i < this->drawQueues.Size(); i++) - { - IndexT& queueIndex = queueUses[families[CoreGraphics::GraphicsQueueType]]; - vkGetDeviceQueue(dev, families[CoreGraphics::GraphicsQueueType], queueIndex++, &this->drawQueues[i]); - } - - for (i = 0; i < this->computeQueues.Size(); i++) - { - IndexT& queueIndex = queueUses[families[CoreGraphics::ComputeQueueType]]; - vkGetDeviceQueue(dev, families[CoreGraphics::ComputeQueueType], queueIndex++, &this->computeQueues[i]); - } + this->queues.Resize(queueMap.Size()); + this->semaphores.Resize(queueMap.Size()); + this->semaphoreSubmissionIds.Resize(queueMap.Size()); + this->currentQueue.Resize(queueMap.Size()); + this->submissions.Resize(queueMap.Size()); - for (i = 0; i < this->transferQueues.Size(); i++) + for (int i = 0; i < queueMap.Size(); i++) { - IndexT& queueIndex = queueUses[families[CoreGraphics::TransferQueueType]]; - vkGetDeviceQueue(dev, families[CoreGraphics::TransferQueueType], queueIndex++, &this->transferQueues[i]); - } - - for (i = 0; i < this->sparseQueues.Size(); i++) - { - IndexT& queueIndex = queueUses[families[CoreGraphics::SparseQueueType]]; - vkGetDeviceQueue(dev, families[CoreGraphics::SparseQueueType], queueIndex++, &this->sparseQueues[i]); - } - - // setup timeline semaphores - this->timelineSubmissions.Resize(CoreGraphics::NumQueueTypes); - for (IndexT i = 0; i < CoreGraphics::NumQueueTypes; i++) - { - VkSemaphoreTypeCreateInfo ext = + auto& [family, count] = queueMap[i]; + this->queues[i].Resize(count); + this->semaphores[i].Resize(count); + this->semaphoreSubmissionIds[i].Resize(count); + +#if NEBULA_GRAPHICS_DEBUG + const char* name = nullptr; + switch (i) + { + case CoreGraphics::ComputeQueueType: + name = "Compute Semaphore"; + break; + case CoreGraphics::GraphicsQueueType: + name = "Graphics Semaphore"; + break; + case CoreGraphics::TransferQueueType: + name = "Transfer Semaphore"; + break; + case CoreGraphics::SparseQueueType: + name = "Sparse Semaphore"; + break; + } +#endif + for (int j = 0; j < count; j++) { - VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, - nullptr, - VkSemaphoreType::VK_SEMAPHORE_TYPE_TIMELINE, - 0 - }; - VkSemaphoreCreateInfo inf = - { - VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, - &ext, - 0 - }; - VkResult res = vkCreateSemaphore(this->device, &inf, nullptr, &semaphores[i]); - n_assert(res == VK_SUCCESS); - - semaphoreSubmissionIds[i] = 0; + vkGetDeviceQueue(dev, family, j, &this->queues[i][j]); + + VkSemaphoreTypeCreateInfo ext = + { + VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, + nullptr, + VkSemaphoreType::VK_SEMAPHORE_TYPE_TIMELINE, + 0 + }; + VkSemaphoreCreateInfo inf = + { + VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + &ext, + 0 + }; + VkResult res = vkCreateSemaphore(this->device, &inf, nullptr, &this->semaphores[i][j]); + n_assert(res == VK_SUCCESS); + this->semaphoreSubmissionIds[i][j] = 0; + +#if NEBULA_GRAPHICS_DEBUG + VkDebugUtilsObjectNameInfoEXT info = + { + VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, + nullptr, + VK_OBJECT_TYPE_SEMAPHORE, + (uint64_t)this->semaphores[i][j], + name + }; + VkResult res2 = VkDebugObjectName(this->device, &info); + n_assert(res2 == VK_SUCCESS); +#endif + } + this->currentQueue[i] = 0; } - - this->currentDrawQueue = 0; - this->currentComputeQueue = 0; - this->currentTransferQueue = 0; - this->currentSparseQueue = 0; } //------------------------------------------------------------------------------ @@ -106,7 +109,6 @@ VkSubContextHandler::Setup(VkDevice dev, const Util::FixedArray indexMap, void VkSubContextHandler::Discard() { - this->timelineSubmissions.Clear(); } //------------------------------------------------------------------------------ @@ -115,28 +117,8 @@ VkSubContextHandler::Discard() void VkSubContextHandler::SetToNextContext(const CoreGraphics::QueueType type) { - Util::FixedArray* list = nullptr; - uint* currentQueue = nullptr; - switch (type) - { - case CoreGraphics::GraphicsQueueType: - list = &this->drawQueues; - currentQueue = &this->currentDrawQueue; - break; - case CoreGraphics::ComputeQueueType: - list = &this->computeQueues; - currentQueue = &this->currentComputeQueue; - break; - case CoreGraphics::TransferQueueType: - list = &this->transferQueues; - currentQueue = &this->currentTransferQueue; - break; - case CoreGraphics::SparseQueueType: - list = &this->sparseQueues; - currentQueue = &this->currentSparseQueue; - break; - default: n_error("unhandled enum"); break; - } + Util::Array* list = &this->queues[type]; + uint* currentQueue = &this->currentQueue[type]; // progress the queue index *currentQueue = (*currentQueue + 1) % list->Size(); @@ -146,24 +128,30 @@ VkSubContextHandler::SetToNextContext(const CoreGraphics::QueueType type) /** */ uint64 -VkSubContextHandler::AppendSubmissionTimeline(CoreGraphics::QueueType type, VkCommandBuffer cmds) +VkSubContextHandler::AppendSubmissionTimeline( + CoreGraphics::QueueType type + , VkCommandBuffer cmds +#if NEBULA_GRAPHICS_DEBUG + , const char* name +#endif +) { n_assert(cmds != VK_NULL_HANDLE); - Util::Array& submissions = this->timelineSubmissions[type]; - submissions.Append(TimelineSubmission()); - TimelineSubmission& sub = submissions.Back(); uint64 ret = GetNextTimelineIndex(type); - - // If command buffer is present, add it - sub.buffers.Append(cmds); - // Add signal - sub.signalSemaphores.Append(this->semaphores[type]); + Util::Array& submissionsForQueue = this->submissions[type]; + TimelineSubmission2& sub = submissionsForQueue.Emplace(); + sub.buffers.Append(cmds); + sub.signalSemaphores.Append(this->semaphores[type][this->currentQueue[type]]); sub.signalIndices.Append(ret); + sub.queue = type; +#if NEBULA_GRAPHICS_DEBUG + sub.name = name; +#endif // Progress the semaphore counter - this->semaphoreSubmissionIds[type] = ret; + this->semaphoreSubmissionIds[type][this->currentQueue[type]] = ret; return ret; } @@ -174,7 +162,7 @@ VkSubContextHandler::AppendSubmissionTimeline(CoreGraphics::QueueType type, VkCo uint64 VkSubContextHandler::GetNextTimelineIndex(CoreGraphics::QueueType type) { - return this->semaphoreSubmissionIds[type] + 1; + return this->semaphoreSubmissionIds[type][this->currentQueue[type]] + 1; } //------------------------------------------------------------------------------ @@ -185,9 +173,11 @@ VkSubContextHandler::AppendWaitTimeline(uint64 index, CoreGraphics::QueueType ty { n_assert(type != CoreGraphics::InvalidQueueType); n_assert(index != UINT64_MAX); - TimelineSubmission& sub = this->timelineSubmissions[type].Back(); + + Util::Array& submissionsForQueue = this->submissions[type]; + TimelineSubmission2& sub = submissionsForQueue.Back(); sub.waitIndices.Append(index); - sub.waitSemaphores.Append(this->semaphores[waitType]); + sub.waitSemaphores.Append(this->semaphores[waitType][this->currentQueue[waitType]]); sub.waitFlags.Append(waitFlags); } @@ -228,18 +218,18 @@ VkSubContextHandler::AppendSparseBind(CoreGraphics::QueueType type, const VkImag } // add signal - submission.signalSemaphores.Append(this->semaphores[type]); - this->semaphoreSubmissionIds[type]++; - submission.signalIndices.Append(this->semaphoreSubmissionIds[type]); + submission.signalSemaphores.Append(this->GetSemaphore(type)); + this->IncrementSemaphoreId(type); + submission.signalIndices.Append(this->GetSemaphoreId(type)); // add wait - if (this->semaphoreSubmissionIds[CoreGraphics::GraphicsQueueType] > 0) + if (this->semaphoreSubmissionIds[CoreGraphics::GraphicsQueueType][this->currentQueue[CoreGraphics::GraphicsQueueType]] > 0) { - submission.waitSemaphores.Append(this->semaphores[CoreGraphics::GraphicsQueueType]); - submission.waitIndices.Append(this->semaphoreSubmissionIds[CoreGraphics::GraphicsQueueType]); + submission.waitSemaphores.Append(this->GetSemaphore(CoreGraphics::GraphicsQueueType)); + submission.waitIndices.Append(this->GetSemaphoreId(CoreGraphics::GraphicsQueueType)); } - return this->semaphoreSubmissionIds[type]; + return this->GetSemaphoreId(type); } //------------------------------------------------------------------------------ @@ -266,11 +256,11 @@ VkSubContextHandler::AppendSparseBind(CoreGraphics::QueueType type, const VkBuff } // add signal - submission.signalSemaphores.Append(this->semaphores[type]); - this->semaphoreSubmissionIds[type]++; - submission.signalIndices.Append(this->semaphoreSubmissionIds[type]); + submission.signalSemaphores.Append(this->GetSemaphore(type)); + this->IncrementSemaphoreId(type); + submission.signalIndices.Append(this->GetSemaphoreId(type)); - return this->semaphoreSubmissionIds[type]; + return this->GetSemaphoreId(type); } //------------------------------------------------------------------------------ @@ -279,8 +269,8 @@ VkSubContextHandler::AppendSparseBind(CoreGraphics::QueueType type, const VkBuff void VkSubContextHandler::AppendPresentSignal(CoreGraphics::QueueType type, VkSemaphore sem) { - TimelineSubmission& sub = this->timelineSubmissions[type].Back(); - + Util::Array& submissionsForQueue = this->submissions[type]; + TimelineSubmission2& sub = submissionsForQueue.Back(); sub.signalIndices.Append(0); sub.signalSemaphores.Append(sem); } @@ -288,58 +278,74 @@ VkSubContextHandler::AppendPresentSignal(CoreGraphics::QueueType type, VkSemapho //------------------------------------------------------------------------------ /** */ -void -VkSubContextHandler::FlushSubmissionsTimeline(CoreGraphics::QueueType type, VkFence fence) +void +VkSubContextHandler::FlushSubmissions(VkFence fence) { - Util::Array& submissions = this->timelineSubmissions[type]; - - // skip flush if submission list is empty - if (submissions.IsEmpty()) - return; - - Util::FixedArray submitInfos(submissions.Size()); - Util::FixedArray extensions(submissions.Size()); - for (IndexT i = 0; i < submissions.Size(); i++) + CoreGraphics::QueueType submissionOrder[] = { - TimelineSubmission& sub = submissions[i]; - - // if we have no work, return - if (sub.buffers.Size() == 0) + CoreGraphics::TransferQueueType, + CoreGraphics::SparseQueueType, + CoreGraphics::GraphicsQueueType, + CoreGraphics::ComputeQueueType + }; + for (auto queueIndex : submissionOrder) + { + Util::Array& submissionsForQueue = this->submissions[queueIndex]; + if (submissionsForQueue.IsEmpty()) continue; + Util::FixedArray submitInfos(submissionsForQueue.Size()); + Util::FixedArray timelineInfos(submissionsForQueue.Size()); - VkTimelineSemaphoreSubmitInfo ext = + for (int i = 0; i < submissionsForQueue.Size(); i++) { - .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, - .pNext = nullptr, - .waitSemaphoreValueCount = (uint32_t)sub.waitIndices.Size(), - .pWaitSemaphoreValues = sub.waitIndices.Size() > 0 ? sub.waitIndices.Begin() : nullptr, - .signalSemaphoreValueCount = (uint32_t)sub.signalIndices.Size(), - .pSignalSemaphoreValues = sub.signalIndices.Size() > 0 ? sub.signalIndices.Begin() : nullptr - }; - extensions[i] = ext; - - VkSubmitInfo info = + auto& sub = submissionsForQueue[i]; + timelineInfos[i] = + { + .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, + .pNext = nullptr, + .waitSemaphoreValueCount = (uint32_t)sub.waitIndices.Size(), + .pWaitSemaphoreValues = sub.waitIndices.Size() > 0 ? sub.waitIndices.Begin() : nullptr, + .signalSemaphoreValueCount = (uint32_t)sub.signalIndices.Size(), + .pSignalSemaphoreValues = sub.signalIndices.Size() > 0 ? sub.signalIndices.Begin() : nullptr + }; + + submitInfos[i] = + { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .pNext = &timelineInfos[i], + .waitSemaphoreCount = (uint32_t)sub.waitSemaphores.Size(), + .pWaitSemaphores = sub.waitSemaphores.Size() > 0 ? sub.waitSemaphores.Begin() : nullptr, + .pWaitDstStageMask = sub.waitFlags.Size() > 0 ? sub.waitFlags.Begin() : nullptr, + .commandBufferCount = (uint32_t)sub.buffers.Size(), + .pCommandBuffers = sub.buffers.Size() > 0 ? sub.buffers.Begin() : nullptr, + .signalSemaphoreCount = (uint32_t)sub.signalSemaphores.Size(), // if we have a finish semaphore, add it on the submit + .pSignalSemaphores = sub.signalSemaphores.Size() > 0 ? sub.signalSemaphores.Begin() : nullptr + }; + } + + CoreGraphics::QueueType type = CoreGraphics::QueueType(queueIndex); + VkQueue queue = this->GetQueue(type); + switch (type) { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .pNext = &extensions[i], - .waitSemaphoreCount = (uint32_t)sub.waitSemaphores.Size(), - .pWaitSemaphores = sub.waitSemaphores.Size() > 0 ? sub.waitSemaphores.Begin() : nullptr, - .pWaitDstStageMask = sub.waitFlags.Size() > 0 ? sub.waitFlags.Begin() : nullptr, - .commandBufferCount = (uint32_t)sub.buffers.Size(), - .pCommandBuffers = sub.buffers.Size() > 0 ? sub.buffers.Begin() : nullptr, - .signalSemaphoreCount = (uint32_t)sub.signalSemaphores.Size(), // if we have a finish semaphore, add it on the submit - .pSignalSemaphores = sub.signalSemaphores.Size() > 0 ? sub.signalSemaphores.Begin() : nullptr - }; - submitInfos[i] = info; - } - - // execute all commands - VkQueue queue = this->GetQueue(type); - VkResult res = vkQueueSubmit(queue, submitInfos.Size(), submitInfos.Begin(), fence); - n_assert(res == VK_SUCCESS); + case CoreGraphics::ComputeQueueType: + CoreGraphics::QueueBeginMarker(type, NEBULA_MARKER_COMPUTE, "Compute"); + break; + case CoreGraphics::GraphicsQueueType: + CoreGraphics::QueueBeginMarker(type, NEBULA_MARKER_GRAPHICS, "Graphics"); + break; + case CoreGraphics::TransferQueueType: + CoreGraphics::QueueBeginMarker(type, NEBULA_MARKER_TRANSFER, "Transfer"); + break; + case CoreGraphics::SparseQueueType: + CoreGraphics::QueueBeginMarker(type, NEBULA_MARKER_TRANSFER, "Sparse"); + break; + } + VkResult res = vkQueueSubmit(queue, submitInfos.Size(), submitInfos.Begin(), fence); + n_assert(res == VK_SUCCESS); - // clear submissions - submissions.Clear(); + CoreGraphics::QueueEndMarker(type); + submissionsForQueue.Clear(); + } } //------------------------------------------------------------------------------ @@ -352,13 +358,14 @@ VkSubContextHandler::Wait(CoreGraphics::QueueType type, uint64 index) if (index != UINT64_MAX) { // setup wait + VkSemaphore sem = this->GetSemaphore(type); VkSemaphoreWaitInfo waitInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, nullptr, 0, 1, - &this->semaphores[type], + &sem, &index }; VkResult res = vkWaitSemaphores(this->device, &waitInfo, UINT64_MAX); @@ -373,7 +380,7 @@ bool VkSubContextHandler::Poll(CoreGraphics::QueueType type, uint64_t index) { uint64_t lastPayload; - VkResult res = vkGetSemaphoreCounterValue(this->device, this->semaphores[type], &lastPayload); + VkResult res = vkGetSemaphoreCounterValue(this->device, this->GetSemaphore(type), &lastPayload); n_assert(res == VK_SUCCESS); return index <= lastPayload; } @@ -450,23 +457,7 @@ VkSubContextHandler::InsertFence(CoreGraphics::QueueType type, VkFence fence) void VkSubContextHandler::WaitIdle(const CoreGraphics::QueueType type) { - Util::FixedArray* list = nullptr; - switch (type) - { - case CoreGraphics::GraphicsQueueType: - list = &this->drawQueues; - break; - case CoreGraphics::ComputeQueueType: - list = &this->computeQueues; - break; - case CoreGraphics::TransferQueueType: - list = &this->transferQueues; - break; - case CoreGraphics::SparseQueueType: - list = &this->sparseQueues; - break; - default: n_error("unhandled enum"); break; - } + Util::Array* list = &this->queues[type]; for (IndexT i = 0; i < list->Size(); i++) { VkResult res = vkQueueWaitIdle((*list)[i]); @@ -480,20 +471,34 @@ VkSubContextHandler::WaitIdle(const CoreGraphics::QueueType type) VkQueue VkSubContextHandler::GetQueue(const CoreGraphics::QueueType type) { - switch (type) - { - case CoreGraphics::GraphicsQueueType: - return this->drawQueues[this->currentDrawQueue]; - case CoreGraphics::ComputeQueueType: - return this->computeQueues[this->currentComputeQueue]; - case CoreGraphics::TransferQueueType: - return this->transferQueues[this->currentTransferQueue]; - case CoreGraphics::SparseQueueType: - return this->sparseQueues[this->currentSparseQueue]; - default: - n_error("Invalid queue type %d", type); - return VK_NULL_HANDLE; - } + return this->queues[type][this->currentQueue[type]]; +} + +//------------------------------------------------------------------------------ +/** +*/ +VkSemaphore +VkSubContextHandler::GetSemaphore(const CoreGraphics::QueueType type) +{ + return this->semaphores[type][this->currentQueue[type]]; +} + +//------------------------------------------------------------------------------ +/** +*/ +uint64 +VkSubContextHandler::GetSemaphoreId(const CoreGraphics::QueueType type) +{ + return this->semaphoreSubmissionIds[type][this->currentQueue[type]]; +} + +//------------------------------------------------------------------------------ +/** +*/ +void +VkSubContextHandler::IncrementSemaphoreId(const CoreGraphics::QueueType type) +{ + this->semaphoreSubmissionIds[type][this->currentQueue[type]]++; } } // namespace Vulkan diff --git a/code/render/coregraphics/vk/vksubcontexthandler.h b/code/render/coregraphics/vk/vksubcontexthandler.h index 548a4c1dd9..1f3b429dd7 100644 --- a/code/render/coregraphics/vk/vksubcontexthandler.h +++ b/code/render/coregraphics/vk/vksubcontexthandler.h @@ -50,6 +50,26 @@ class VkSubContextHandler Util::Array waitIndices; }; + struct TimelineSubmission2 + { +#if NEBULA_GRAPHICS_DEBUG + const char* name = nullptr; +#endif + CoreGraphics::QueueType queue; + Util::Array signalIndices; + Util::Array signalSemaphores; + Util::Array buffers; + Util::Array waitFlags; + Util::Array waitSemaphores; + Util::Array waitIndices; + }; + + struct SubmissionList + { + CoreGraphics::QueueType queue; + Util::Array submissions; + }; + struct SparseBindSubmission { VkBindSparseInfo bindInfo; @@ -66,14 +86,20 @@ class VkSubContextHandler }; /// setup subcontext handler - void Setup(VkDevice dev, const Util::FixedArray indexMap, const Util::FixedArray families); + void Setup(VkDevice dev, const Util::FixedArray> indexMap); /// discard void Discard(); /// set to next context of type void SetToNextContext(const CoreGraphics::QueueType type); /// append submission to context to execute later, supports waiting for a queue - uint64 AppendSubmissionTimeline(CoreGraphics::QueueType type, VkCommandBuffer cmds); + uint64 AppendSubmissionTimeline( + CoreGraphics::QueueType type + , VkCommandBuffer cmds +#if NEBULA_GRAPHICS_DEBUG + , const char* name = nullptr +#endif + ); /// Gets the next submission id for a specific queue uint64 GetNextTimelineIndex(CoreGraphics::QueueType type); /// Append a wait for a submission timeline index @@ -84,8 +110,8 @@ class VkSubContextHandler uint64 AppendSparseBind(CoreGraphics::QueueType type, const VkBuffer buf, const Util::Array& binds); /// Append present signal void AppendPresentSignal(CoreGraphics::QueueType type, VkSemaphore sem); - /// flush submissions - void FlushSubmissionsTimeline(CoreGraphics::QueueType type, VkFence fence); + /// Flush submissions + void FlushSubmissions(VkFence fence); /// wait for timeline index void Wait(CoreGraphics::QueueType type, uint64 index); /// check to see if timeline index has passed @@ -105,21 +131,16 @@ class VkSubContextHandler private: friend const VkQueue GetQueue(const CoreGraphics::QueueType type, const IndexT index); + VkSemaphore GetSemaphore(const CoreGraphics::QueueType type); + uint64 GetSemaphoreId(const CoreGraphics::QueueType type); + void IncrementSemaphoreId(const CoreGraphics::QueueType type); + VkDevice device; - Util::FixedArray drawQueues; - Util::FixedArray computeQueues; - Util::FixedArray transferQueues; - Util::FixedArray sparseQueues; - uint currentDrawQueue; - uint currentComputeQueue; - uint currentTransferQueue; - uint currentSparseQueue; - uint queueFamilies[CoreGraphics::NumQueueTypes]; - - VkSemaphore semaphores[CoreGraphics::NumQueueTypes]; - uint64 semaphoreSubmissionIds[CoreGraphics::NumQueueTypes]; - - Util::FixedArray> timelineSubmissions; + Util::FixedArray> queues; + Util::FixedArray currentQueue; + Util::FixedArray> semaphores; + Util::FixedArray> semaphoreSubmissionIds; + Util::FixedArray> submissions; Util::Array sparseBindSubmissions; }; diff --git a/code/render/coregraphics/vk/vkswapchain.cc b/code/render/coregraphics/vk/vkswapchain.cc index 920c3c15ed..fc71b4ee5e 100644 --- a/code/render/coregraphics/vk/vkswapchain.cc +++ b/code/render/coregraphics/vk/vkswapchain.cc @@ -32,6 +32,7 @@ CreateSwapchain(const SwapchainCreateInfo& info) VkQueue& queue = swapchainAllocator.Get(id); Util::Array& images = swapchainAllocator.Get(id); Util::Array& views = swapchainAllocator.Get(id); + CoreGraphics::QueueType& queueType = swapchainAllocator.Get(id); swapchainAllocator.Set(id, info.displayMode); VkResult res = glfwCreateWindowSurface(Vulkan::GetInstance(), info.window, nullptr, &surface); n_assert(res == VK_SUCCESS); @@ -53,12 +54,12 @@ CreateSwapchain(const SwapchainCreateInfo& info) uint32_t i; for (i = 0; i < numFormats; i++) { - if (formats[i].format == VK_FORMAT_B8G8R8A8_SRGB) + if (formats[i].format == VK_FORMAT_R8G8B8A8_SRGB) { format = formats[i].format; colorSpace = formats[i].colorSpace; - mapping.r = VK_COMPONENT_SWIZZLE_R; - mapping.b = VK_COMPONENT_SWIZZLE_B; + //mapping.b = VK_COMPONENT_SWIZZLE_R; + //mapping.r = VK_COMPONENT_SWIZZLE_B; break; } } @@ -152,19 +153,33 @@ CreateSwapchain(const SwapchainCreateInfo& info) VK_NULL_HANDLE }; - // get present queue - for (IndexT i = 0; i < NumQueueTypes; i++) + VkBool32 canPresent; + res = vkGetPhysicalDeviceSurfaceSupportKHR(physicalDev, CoreGraphics::GetQueueIndex(info.preferredQueue), surface, &canPresent); + n_assert(res == VK_SUCCESS); + if (canPresent) { - VkBool32 canPresent; - res = vkGetPhysicalDeviceSurfaceSupportKHR(physicalDev, i, surface, &canPresent); - n_assert(res == VK_SUCCESS); - if (canPresent) + queue = Vulkan::GetQueue(info.preferredQueue, 0); + queueType = info.preferredQueue; + } + else + { + // get present queue + for (IndexT i = 0; i < NumQueueTypes; i++) { - queue = Vulkan::GetQueue((CoreGraphics::QueueType)i, 0); - break; + VkBool32 canPresent; + res = vkGetPhysicalDeviceSurfaceSupportKHR(physicalDev, CoreGraphics::GetQueueIndex((CoreGraphics::QueueType)i), surface, &canPresent); + n_assert(res == VK_SUCCESS); + if (canPresent) + { + queue = Vulkan::GetQueue((CoreGraphics::QueueType)i, 0); + queueType = (CoreGraphics::QueueType)i; + break; + } } } + n_assert(queue != VK_NULL_HANDLE); + // create swapchain res = vkCreateSwapchainKHR(dev, &swapchainInfo, nullptr, &swapchain); n_assert(res == VK_SUCCESS); @@ -216,6 +231,12 @@ CreateSwapchain(const SwapchainCreateInfo& info) currentBackbuffer = 0; CoreGraphics::UnlockGraphicsSetupCommandBuffer(); + CoreGraphics::CmdBufferPoolCreateInfo poolInfo; + poolInfo.shortlived = true; + poolInfo.queue = queueType; + poolInfo.resetable = false; + CoreGraphics::CmdBufferPoolId pool = CoreGraphics::CreateCmdBufferPool(poolInfo); + swapchainAllocator.Set(id, pool); SwapchainId ret = id; return ret; @@ -272,6 +293,28 @@ SwapchainSwap(const SwapchainId id) } } +//------------------------------------------------------------------------------ +/** +*/ +CoreGraphics::QueueType +SwapchainGetQueueType(const SwapchainId id) +{ + return swapchainAllocator.Get(id.id); +} + +//------------------------------------------------------------------------------ +/** +*/ +CoreGraphics::CmdBufferId +SwapchainAllocateCmds(const SwapchainId id) +{ + const CoreGraphics::CmdBufferPoolId pool = swapchainAllocator.Get(id.id); + CoreGraphics::CmdBufferCreateInfo bufInfo; + bufInfo.pool = pool; + bufInfo.name = "Swap"; + return CoreGraphics::CreateCmdBuffer(bufInfo); +} + //------------------------------------------------------------------------------ /** */ @@ -281,13 +324,13 @@ SwapchainCopy(const SwapchainId id, const CoreGraphics::CmdBufferId cmdBuf, cons const uint currentBackbuffer = swapchainAllocator.Get(id.id); const Util::Array& images = swapchainAllocator.Get(id.id); const DisplayMode& displayMode = swapchainAllocator.Get(id.id); - VkImageBlit blit; - blit.srcOffsets[0] = { 0, 0, 0 }; - blit.srcOffsets[1] = { displayMode.GetWidth(), displayMode.GetHeight(), 1 }; - blit.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - blit.dstOffsets[0] = { 0, 0, 0 }; - blit.dstOffsets[1] = { displayMode.GetWidth(), displayMode.GetHeight(), 1 }; - blit.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; + VkImageCopy copy; + + copy.srcOffset = { 0, 0, 0 }; + copy.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; + copy.dstOffset = { 0, 0, 0 }; + copy.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; + copy.extent = { (uint)displayMode.GetWidth(), (uint)displayMode.GetHeight(), 1 }; VkImage sourceImage = TextureGetVkImage(source); VkCommandBuffer vkBuf = CmdBufferGetVk(cmdBuf.id); @@ -307,15 +350,15 @@ SwapchainCopy(const SwapchainId id, const CoreGraphics::CmdBufferId cmdBuf, cons imageBarrier.subresourceRange = VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; vkCmdPipelineBarrier(vkBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0x0, 0, nullptr, 0, nullptr, 1, &imageBarrier); - vkCmdBlitImage( + vkCmdCopyImage( vkBuf , sourceImage , VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL , images[currentBackbuffer] , VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL , 1 - , &blit - , VK_FILTER_LINEAR); + , © + ); // Transition backbuffer imageBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; @@ -340,6 +383,7 @@ SwapchainPresent(const SwapchainId id) const uint currentBackbuffer = swapchainAllocator.Get(id.id); const VkSwapchainKHR& swapchain = swapchainAllocator.Get(id.id); const VkQueue& queue = swapchainAllocator.Get(id.id); + const CoreGraphics::QueueType queueType = swapchainAllocator.Get(id.id); const Util::Array& images = swapchainAllocator.Get(id.id); VkSemaphore semaphores[] = @@ -348,7 +392,7 @@ SwapchainPresent(const SwapchainId id) }; #if NEBULA_GRAPHICS_DEBUG - CoreGraphics::QueueBeginMarker(GraphicsQueueType, NEBULA_MARKER_BLACK, "Presentation"); + CoreGraphics::QueueBeginMarker(queueType, NEBULA_MARKER_BLACK, "Presentation"); #endif const VkPresentInfoKHR info = @@ -377,7 +421,7 @@ SwapchainPresent(const SwapchainId id) #if NEBULA_GRAPHICS_DEBUG - CoreGraphics::QueueEndMarker(GraphicsQueueType); + CoreGraphics::QueueEndMarker(queueType); #endif } diff --git a/code/render/coregraphics/vk/vkswapchain.h b/code/render/coregraphics/vk/vkswapchain.h index 618feea9ad..1e3f14c7ee 100644 --- a/code/render/coregraphics/vk/vkswapchain.h +++ b/code/render/coregraphics/vk/vkswapchain.h @@ -20,7 +20,9 @@ enum Swapchain_DisplayMode, Swapchain_Images, Swapchain_ImageViews, - Swapchain_Queue + Swapchain_Queue, + Swapchain_QueueType, + Swapchain_CommandPool }; typedef Ids::IdAllocator< @@ -31,7 +33,9 @@ typedef Ids::IdAllocator< CoreGraphics::DisplayMode, Util::Array, Util::Array, - VkQueue + VkQueue, + CoreGraphics::QueueType, + CoreGraphics::CmdBufferPoolId > SwapchainAllocator; extern SwapchainAllocator swapchainAllocator; diff --git a/code/render/coregraphics/vk/vktexture.cc b/code/render/coregraphics/vk/vktexture.cc index ca9dda1a50..f7cec2682f 100644 --- a/code/render/coregraphics/vk/vktexture.cc +++ b/code/render/coregraphics/vk/vktexture.cc @@ -249,7 +249,10 @@ SetupTexture(const TextureId id) extents.height = loadInfo.height; extents.depth = loadInfo.depth; - bool isDepthFormat = VkTypes::IsDepthFormat(loadInfo.format); + CoreGraphics::ImageBits bits = CoreGraphics::ImageBits::None; + + bits |= PixelFormat::IsDepthFormat(loadInfo.format) ? CoreGraphics::ImageBits::DepthBits : CoreGraphics::ImageBits::None; + bits |= PixelFormat::IsStencilFormat(loadInfo.format) ? CoreGraphics::ImageBits::StencilBits : CoreGraphics::ImageBits::None; // setup usage flags, by default, all textures can be sampled from // we automatically assign VK_IMAGE_USAGE_SAMPLED_BIT to sampled images, render textures and readwrite textures, but not for transfer textures @@ -265,7 +268,7 @@ SetupTexture(const TextureId id) VkImageUsageFlags usage = Util::BitmaskConvert(loadInfo.usage, Lookup); if (loadInfo.usage & TextureUsage::RenderTexture) - usage |= (isDepthFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); + usage |= (AnyBits(bits, ImageBits::DepthBits | ImageBits::StencilBits) ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); VkSampleCountFlagBits samples = VkTypes::AsVkSampleFlags(loadInfo.samples); VkImageViewType viewType = VkTypes::AsVkImageViewType(runtimeInfo.type); @@ -311,7 +314,7 @@ SetupTexture(const TextureId id) // Setup subresource range VkImageSubresourceRange viewRange; - viewRange.aspectMask = isDepthFormat ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; // view only supports reading depth in shader + viewRange.aspectMask = AllBits(bits, ImageBits::DepthBits) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; // view only supports reading depth in shader viewRange.baseMipLevel = loadInfo.minMip; viewRange.levelCount = loadInfo.mips - loadInfo.minMip; viewRange.baseArrayLayer = 0; @@ -403,7 +406,7 @@ SetupTexture(const TextureId id) // if used for render, find appropriate renderable format if (loadInfo.usage & TextureUsage::RenderTexture) { - if (!isDepthFormat) + if (bits == ImageBits::None) { VkFormatProperties formatProps; vkGetPhysicalDeviceFormatProperties(Vulkan::GetCurrentPhysicalDevice(), vkformat, &formatProps); @@ -434,7 +437,7 @@ SetupTexture(const TextureId id) n_assert(stat == VK_SUCCESS); // setup stencil image - if (isDepthFormat) + if (AllBits(bits, ImageBits::StencilBits)) { // setup stencil extension TextureViewCreateInfo viewCreate; @@ -456,7 +459,7 @@ SetupTexture(const TextureId id) CoreGraphics::CmdBufferId cmdBuf = CoreGraphics::LockGraphicsSetupCommandBuffer(); CoreGraphics::TextureSubresourceInfo subres( - isDepthFormat ? CoreGraphics::ImageBits::DepthBits | CoreGraphics::ImageBits::StencilBits : CoreGraphics::ImageBits::ColorBits + bits != ImageBits::None ? bits : CoreGraphics::ImageBits::ColorBits , viewRange.baseMipLevel , viewRange.levelCount , viewRange.baseArrayLayer @@ -478,7 +481,7 @@ SetupTexture(const TextureId id) } }); - if (!isDepthFormat) + if (bits == ImageBits::None) { // Clear color TextureClearColor(cmdBuf @@ -541,12 +544,12 @@ SetupTexture(const TextureId id) if (loadInfo.bindless) { if (runtimeInfo.bind == 0xFFFFFFFF) - runtimeInfo.bind = Graphics::RegisterTexture(id, runtimeInfo.type, isDepthFormat); + runtimeInfo.bind = Graphics::RegisterTexture(id, runtimeInfo.type, AllBits(bits, ImageBits::DepthBits)); else - Graphics::ReregisterTexture(id, runtimeInfo.type, runtimeInfo.bind, isDepthFormat); + Graphics::ReregisterTexture(id, runtimeInfo.type, runtimeInfo.bind, AllBits(bits, ImageBits::DepthBits)); // if this is a depth-stencil texture, also register the stencil - if (isDepthFormat) + if (AllBits(bits, ImageBits::StencilBits)) { __Lock(textureStencilExtensionAllocator, loadInfo.stencilExtension); IndexT& bind = textureStencilExtensionAllocator.Get(loadInfo.stencilExtension); diff --git a/code/render/coregraphics/vk/vktextureview.cc b/code/render/coregraphics/vk/vktextureview.cc index a2b114f941..fc37996523 100644 --- a/code/render/coregraphics/vk/vktextureview.cc +++ b/code/render/coregraphics/vk/vktextureview.cc @@ -125,7 +125,7 @@ TextureViewReload(const TextureViewId id) // First destroy the old view CoreGraphics::DelayedDeleteTextureView(id); - bool isDepthFormat = VkTypes::IsDepthFormat(loadInfo.format); + bool isDepthFormat = PixelFormat::IsDepthFormat(loadInfo.format); VkImageSubresourceRange viewRange; viewRange.aspectMask = isDepthFormat ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; // view only supports reading depth in shader viewRange.baseMipLevel = loadInfo.mip; diff --git a/code/render/coregraphics/vk/vktypes.cc b/code/render/coregraphics/vk/vktypes.cc index 796c998566..a17a90bbfc 100644 --- a/code/render/coregraphics/vk/vktypes.cc +++ b/code/render/coregraphics/vk/vktypes.cc @@ -46,6 +46,7 @@ VkTypes::AsVkFormat(CoreGraphics::PixelFormat::Code p) case PixelFormat::R16G16B16A16F: return VK_FORMAT_R16G16B16A16_SFLOAT; case PixelFormat::R16G16B16A16: return VK_FORMAT_R16G16B16A16_UINT; case PixelFormat::R11G11B10F: return VK_FORMAT_B10G11R11_UFLOAT_PACK32; + case PixelFormat::R9G9B9E5F: return VK_FORMAT_E5B9G9R9_UFLOAT_PACK32; case PixelFormat::R32F: return VK_FORMAT_R32_SFLOAT; case PixelFormat::R32: return VK_FORMAT_R32_UINT; case PixelFormat::R32G32F: return VK_FORMAT_R32G32_SFLOAT; @@ -55,6 +56,8 @@ VkTypes::AsVkFormat(CoreGraphics::PixelFormat::Code p) case PixelFormat::R32G32B32F: return VK_FORMAT_R32G32B32_SFLOAT; case PixelFormat::R32G32B32: return VK_FORMAT_R32G32B32_UINT; case PixelFormat::R10G10B10A2: return VK_FORMAT_A2B10G10R10_UINT_PACK32; + case PixelFormat::D32: return VK_FORMAT_D32_SFLOAT; + case PixelFormat::S8: return VK_FORMAT_S8_UINT; case PixelFormat::D32S8: return VK_FORMAT_D32_SFLOAT_S8_UINT; case PixelFormat::D24X8: return VK_FORMAT_X8_D24_UNORM_PACK32; case PixelFormat::D24S8: return VK_FORMAT_D24_UNORM_S8_UINT; @@ -66,23 +69,6 @@ VkTypes::AsVkFormat(CoreGraphics::PixelFormat::Code p) } } -//------------------------------------------------------------------------------ -/** -*/ -bool -VkTypes::IsDepthFormat(CoreGraphics::PixelFormat::Code p) -{ - switch (p) - { - case PixelFormat::D32S8: - case PixelFormat::D24X8: - case PixelFormat::D24S8: - return true; - default: return false; break; - } - return false; -} - //------------------------------------------------------------------------------ /** */ @@ -293,6 +279,7 @@ VkTypes::AsVkDataFormat(CoreGraphics::PixelFormat::Code p) case PixelFormat::R32G32B32F: return VK_FORMAT_R32G32B32_SFLOAT; case PixelFormat::R32G32B32: return VK_FORMAT_R32G32B32_UINT; case PixelFormat::R11G11B10F: return VK_FORMAT_B10G11R11_UFLOAT_PACK32; + case PixelFormat::R9G9B9E5F: return VK_FORMAT_E5B9G9R9_UFLOAT_PACK32; default: { n_error("VkTypes::AsVkFormat(): invalid pixel format '%d'", p); @@ -416,6 +403,7 @@ VkTypes::AsNebulaPixelFormat(VkFormat f) case VK_FORMAT_R16G16B16A16_UINT: return PixelFormat::R16G16B16A16; case VK_FORMAT_R16G16B16A16_UNORM: return PixelFormat::R16G16B16A16; case VK_FORMAT_B10G11R11_UFLOAT_PACK32: return PixelFormat::R11G11B10F; + case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: return PixelFormat::R9G9B9E5F; case VK_FORMAT_R32_SFLOAT: return PixelFormat::R32F; case VK_FORMAT_R32G32_SFLOAT: return PixelFormat::R32G32F; case VK_FORMAT_R32G32B32A32_SFLOAT: return PixelFormat::R32G32B32A32F; diff --git a/code/render/coregraphics/vk/vktypes.h b/code/render/coregraphics/vk/vktypes.h index 2f99ef767a..87426390fb 100644 --- a/code/render/coregraphics/vk/vktypes.h +++ b/code/render/coregraphics/vk/vktypes.h @@ -42,8 +42,6 @@ class VkTypes #pragma region Pixel stuff /// convert Nebula pixel format to Vulkan pixel format static VkFormat AsVkFormat(CoreGraphics::PixelFormat::Code p); - /// check if format is depth or color - static bool IsDepthFormat(CoreGraphics::PixelFormat::Code p); /// returns true if format is compressed static bool IsCompressedFormat(VkFormat p); /// convert pixel format to block size diff --git a/code/render/decals/decalcontext.cc b/code/render/decals/decalcontext.cc index fa1bd02009..23e468161d 100644 --- a/code/render/decals/decalcontext.cc +++ b/code/render/decals/decalcontext.cc @@ -16,6 +16,9 @@ #include "graphics/globalconstants.h" #include "system_shaders/decals_cluster.h" + +#include "frame/default.h" + namespace Decals { DecalContext::GenericDecalAllocator DecalContext::genericDecalAllocator; @@ -39,8 +42,6 @@ struct // these are used to update the light clustering DecalsCluster::PBRDecal pbrDecals[256]; DecalsCluster::EmissiveDecal emissiveDecals[256]; - - Memory::ArenaAllocator frameOpAllocator; } decalState; //------------------------------------------------------------------------------ @@ -108,47 +109,19 @@ DecalContext::Create() ResourceTableCommitChanges(frameResourceTable); } - // The first pass is to copy decals over - Frame::FrameCode* decalCopy = decalState.frameOpAllocator.Alloc(); - decalCopy->domain = CoreGraphics::BarrierDomain::Global; - decalCopy->queue = CoreGraphics::QueueType::ComputeQueueType; - decalCopy->bufferDeps.Add(decalState.clusterDecalsList, - { - "Decals List" - , CoreGraphics::PipelineStage::TransferWrite - , CoreGraphics::BufferSubresourceInfo() - }); - decalCopy->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::Bind_ClusterDecalList(decalState.clusterDecalsList); + FrameScript_default::Bind_ClusterDecalIndexLists(decalState.clusterDecalIndexLists); + FrameScript_default::RegisterSubgraph_DecalCopy_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CoreGraphics::BufferCopy from, to; from.offset = 0; to.offset = 0; CmdCopy(cmdBuf, decalState.stagingClusterDecalsList.buffers[bufferIndex], { from }, decalState.clusterDecalsList, { to }, sizeof(DecalsCluster::DecalLists)); - }; - - // The second pass is to cull the decals based on screen space AABBs - Frame::FrameCode* decalCull = decalState.frameOpAllocator.Alloc(); - decalCull->domain = CoreGraphics::BarrierDomain::Global; - decalCull->queue = CoreGraphics::QueueType::ComputeQueueType; - decalCull->bufferDeps.Add(decalState.clusterDecalsList, - { - "Decals List" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::BufferSubresourceInfo() - }); - decalCull->bufferDeps.Add(decalState.clusterDecalIndexLists, - { - "Decal Index Lists" - , CoreGraphics::PipelineStage::ComputeShaderWrite - , CoreGraphics::BufferSubresourceInfo() - }); - decalCull->bufferDepRefs.Add(Clustering::ClusterContext::GetClusterBuffer(), - { - "Cluster AABB" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::BufferSubresourceInfo() - }); - decalCull->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }, { + { FrameScript_default::BufferIndex::ClusterDecalList, CoreGraphics::PipelineStage::TransferWrite } + }); + + FrameScript_default::RegisterSubgraph_DecalCull_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CmdSetShaderProgram(cmdBuf, decalState.cullProgram); @@ -156,44 +129,11 @@ DecalContext::Create() std::array dimensions = Clustering::ClusterContext::GetClusterDimensions(); CmdDispatch(cmdBuf, Math::ceil((dimensions[0] * dimensions[1] * dimensions[2]) / 64.0f), 1, 1); - }; - Frame::AddSubgraph("Decal Cull", { decalCopy, decalCull }); - - Frame::FrameCode* pbrRender = decalState.frameOpAllocator.Alloc(); - pbrRender->domain = CoreGraphics::BarrierDomain::Pass; - pbrRender->bufferDeps.Add(decalState.clusterDecalIndexLists, - { - "Decal Index Lists" - , CoreGraphics::PipelineStage::PixelShaderRead - , CoreGraphics::BufferSubresourceInfo() - }); - pbrRender->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) - { - // Set resources and draw - CmdSetShaderProgram(cmdBuf, decalState.renderPBRProgram); - RenderUtil::DrawFullScreenQuad::ApplyMesh(cmdBuf); - CmdSetGraphicsPipeline(cmdBuf); - CmdDraw(cmdBuf, RenderUtil::DrawFullScreenQuad::GetPrimitiveGroup()); - }; - Frame::AddSubgraph("PBR Decals", { pbrRender }); - - Frame::FrameCode* emissiveRender = decalState.frameOpAllocator.Alloc(); - emissiveRender->domain = CoreGraphics::BarrierDomain::Pass; - emissiveRender->bufferDeps.Add(decalState.clusterDecalIndexLists, - { - "Decal Index Lists" - , CoreGraphics::PipelineStage::PixelShaderRead - , CoreGraphics::BufferSubresourceInfo() - }); - emissiveRender->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) - { - // Set resources and draw - CmdSetShaderProgram(cmdBuf, decalState.renderEmissiveProgram); - RenderUtil::DrawFullScreenQuad::ApplyMesh(cmdBuf); - CmdSetGraphicsPipeline(cmdBuf); - CmdDraw(cmdBuf, RenderUtil::DrawFullScreenQuad::GetPrimitiveGroup()); - }; - Frame::AddSubgraph("Emissive Decals", { emissiveRender }); + }, { + { FrameScript_default::BufferIndex::ClusterDecalList, CoreGraphics::PipelineStage::ComputeShaderRead } + , { FrameScript_default::BufferIndex::ClusterDecalIndexLists, CoreGraphics::PipelineStage::ComputeShaderWrite } + , { FrameScript_default::BufferIndex::ClusterBuffer, CoreGraphics::PipelineStage::ComputeShaderRead } + }); } //------------------------------------------------------------------------------ @@ -202,7 +142,6 @@ DecalContext::Create() void DecalContext::Discard() { - decalState.frameOpAllocator.Release(); } //------------------------------------------------------------------------------ @@ -369,8 +308,6 @@ DecalContext::UpdateViewDependentResources(const Ptr& view, cons } } } - //const CoreGraphics::TextureId normalCopyTex = view->GetFrameScript()->GetTexture("NormalBufferCopy"); - const CoreGraphics::TextureId depthTex = view->GetFrameScript()->GetTexture("ZBuffer"); // setup uniforms DecalsCluster::DecalUniforms decalUniforms; @@ -378,7 +315,7 @@ DecalContext::UpdateViewDependentResources(const Ptr& view, cons decalUniforms.NumPBRDecals = numPbrDecals; decalUniforms.NumEmissiveDecals = numEmissiveDecals; //decalUniforms.NormalBufferCopy = TextureGetBindlessHandle(normalCopyTex); - decalUniforms.StencilBuffer = TextureGetStencilBindlessHandle(depthTex); + decalUniforms.StencilBuffer = TextureGetStencilBindlessHandle(FrameScript_default::Texture_ZBuffer()); IndexT bufferIndex = CoreGraphics::GetBufferedFrameIndex(); diff --git a/code/render/fog/volumetricfogcontext.cc b/code/render/fog/volumetricfogcontext.cc index 462d6f007a..ae312173d6 100644 --- a/code/render/fog/volumetricfogcontext.cc +++ b/code/render/fog/volumetricfogcontext.cc @@ -15,6 +15,8 @@ #include "system_shaders/volumefog.h" #include "system_shaders/blur/blur_2d_rgba16f_cs.h" + +#include "frame/default.h" namespace Fog { @@ -34,10 +36,6 @@ struct CoreGraphics::BufferSet stagingClusterFogLists; CoreGraphics::BufferId clusterFogLists; - CoreGraphics::TextureId fogVolumeTexture0; - CoreGraphics::TextureId fogVolumeTexture1; - CoreGraphics::TextureId zBuffer; - Util::FixedArray resourceTables; float turbidity; Math::vec3 color; @@ -46,8 +44,6 @@ struct Volumefog::FogBox fogBoxes[128]; Volumefog::FogSphere fogSpheres[128]; - Memory::ArenaAllocator frameOpAllocator; - bool showUI = false; } fogState; @@ -56,6 +52,7 @@ struct CoreGraphics::ShaderId blurShader; CoreGraphics::ShaderProgramId blurXProgram, blurYProgram; Util::FixedArray blurXTable, blurYTable; + CoreGraphics::BufferId blurConstants; } blurState; @@ -79,7 +76,7 @@ VolumetricFogContext::~VolumetricFogContext() /** */ void -VolumetricFogContext::Create(const Ptr& frameScript) +VolumetricFogContext::Create() { __CreateContext(); @@ -129,7 +126,13 @@ VolumetricFogContext::Create(const Ptr& frameScript) blurState.blurXProgram = ShaderGetProgram(blurState.blurShader, CoreGraphics::ShaderFeatureMask("BlurX")); blurState.blurYProgram = ShaderGetProgram(blurState.blurShader, CoreGraphics::ShaderFeatureMask("BlurY")); blurState.blurXTable.Resize(CoreGraphics::GetNumBufferedFrames()); - blurState.blurYTable.Resize(CoreGraphics::GetNumBufferedFrames()); + blurState.blurYTable.Resize(CoreGraphics::GetNumBufferedFrames()); + + CoreGraphics::BufferCreateInfo bufInfo; + bufInfo.byteSize = sizeof(Blur2dRgba16fCs::BlurUniforms); + bufInfo.usageFlags = CoreGraphics::BufferUsageFlag::ConstantBuffer; + bufInfo.mode = CoreGraphics::BufferAccessMode::DeviceAndHost; + blurState.blurConstants = CoreGraphics::CreateBuffer(bufInfo); for (IndexT i = 0; i < blurState.blurXTable.Size(); i++) { @@ -140,51 +143,17 @@ VolumetricFogContext::Create(const Ptr& frameScript) fogState.turbidity = 0.1f; fogState.color = Math::vec3(1); - fogState.fogVolumeTexture0 = frameScript->GetTexture("VolumetricFogBuffer0"); - fogState.fogVolumeTexture1 = frameScript->GetTexture("VolumetricFogBuffer1"); - fogState.zBuffer = frameScript->GetTexture("ZBuffer"); - - // The first pass is to copy decals over - Frame::FrameCode* fogCopy = fogState.frameOpAllocator.Alloc(); - fogCopy->domain = CoreGraphics::BarrierDomain::Global; - fogCopy->queue = CoreGraphics::QueueType::ComputeQueueType; - fogCopy->bufferDeps.Add(fogState.clusterFogLists, - { - "Decals List" - , CoreGraphics::PipelineStage::TransferWrite - , CoreGraphics::BufferSubresourceInfo() - }); - fogCopy->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_FogCopy_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CoreGraphics::BufferCopy from, to; from.offset = 0; to.offset = 0; CmdCopy(cmdBuf, fogState.stagingClusterFogLists.buffers[bufferIndex], { from }, fogState.clusterFogLists, { to }, sizeof(Volumefog::FogLists)); - }; + }, { + { FrameScript_default::BufferIndex::ClusterFogList, CoreGraphics::PipelineStage::TransferWrite } + }); - // The second pass is to cull the decals based on screen space AABBs - Frame::FrameCode* fogCull = fogState.frameOpAllocator.Alloc(); - fogCull->domain = CoreGraphics::BarrierDomain::Global; - fogCull->queue = CoreGraphics::QueueType::ComputeQueueType; - fogCull->bufferDeps.Add(fogState.clusterFogLists, - { - "Fog List" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::BufferSubresourceInfo() - }); - fogCull->bufferDeps.Add(fogState.clusterFogIndexLists, - { - "Fog Index Lists" - , CoreGraphics::PipelineStage::ComputeShaderWrite - , CoreGraphics::BufferSubresourceInfo() - }); - fogCull->bufferDepRefs.Add(Clustering::ClusterContext::GetClusterBuffer(), - { - "Cluster AABB" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::BufferSubresourceInfo() - }); - fogCull->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_FogCull_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CmdSetShaderProgram(cmdBuf, fogState.cullProgram); @@ -192,30 +161,13 @@ VolumetricFogContext::Create(const Ptr& frameScript) std::array dimensions = Clustering::ClusterContext::GetClusterDimensions(); CmdDispatch(cmdBuf, Math::ceil((dimensions[0] * dimensions[1] * dimensions[2]) / 64.0f), 1, 1); - }; - Frame::AddSubgraph("Fog Cull", { fogCopy, fogCull }); - - Frame::FrameCode* fogCompute = fogState.frameOpAllocator.Alloc(); - fogCompute->domain = CoreGraphics::BarrierDomain::Global; - fogCompute->bufferDeps.Add(fogState.clusterFogIndexLists, - { - "Fog Index Lists" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::BufferSubresourceInfo() - }); - fogCompute->textureDeps.Add(fogState.fogVolumeTexture0, - { - "Fog Volume Texture 0" - , CoreGraphics::PipelineStage::ComputeShaderWrite - , CoreGraphics::TextureSubresourceInfo::Color(fogState.fogVolumeTexture0) - }); - fogCompute->textureDeps.Add(fogState.zBuffer, - { - "ZBuffer" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::TextureSubresourceInfo::DepthStencil(fogState.zBuffer) - }); - fogCompute->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }, { + { FrameScript_default::BufferIndex::ClusterFogList, CoreGraphics::PipelineStage::ComputeShaderRead } + , { FrameScript_default::BufferIndex::ClusterLightIndexLists, CoreGraphics::PipelineStage::ComputeShaderWrite } + , { FrameScript_default::BufferIndex::ClusterBuffer, CoreGraphics::PipelineStage::ComputeShaderRead } + }); + + FrameScript_default::RegisterSubgraph_FogCompute_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CmdSetShaderProgram(cmdBuf, fogState.renderProgram); @@ -223,58 +175,51 @@ VolumetricFogContext::Create(const Ptr& frameScript) CmdSetResourceTable(cmdBuf, fogState.resourceTables[bufferIndex], NEBULA_BATCH_GROUP, CoreGraphics::ComputePipeline, nullptr); // run volumetric fog compute - TextureDimensions dims = TextureGetDimensions(fogState.fogVolumeTexture0); - CmdDispatch(cmdBuf, Math::divandroundup(dims.width, 64), dims.height, 1); - }; - - Frame::FrameCode* blurX = fogState.frameOpAllocator.Alloc(); - blurX->domain = CoreGraphics::BarrierDomain::Global; - blurX->textureDeps.Add(fogState.fogVolumeTexture0, - { - "Fog Volume Texture 0" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::TextureSubresourceInfo::Color(fogState.fogVolumeTexture0) - }); - blurX->textureDeps.Add(fogState.fogVolumeTexture1, - { - "Fog Volume Texture 1" - , CoreGraphics::PipelineStage::ComputeShaderWrite - , CoreGraphics::TextureSubresourceInfo::Color(fogState.fogVolumeTexture1) - }); - blurX->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + auto [scaleX, scaleY] = FrameScript_default::TextureRelativeScale_VolumetricFogBuffer0(); + CmdDispatch(cmdBuf, Math::divandroundup(viewport.width() * scaleX, 64), viewport.height() * scaleY, 1); + }, { + { FrameScript_default::BufferIndex::ClusterFogIndexLists, CoreGraphics::PipelineStage::ComputeShaderRead } + }, { + { FrameScript_default::TextureIndex::VolumetricFogBuffer0, CoreGraphics::PipelineStage::ComputeShaderWrite } + , { FrameScript_default::TextureIndex::ZBuffer, CoreGraphics::PipelineStage::ComputeShaderRead } + }); + + FrameScript_default::RegisterSubgraph_FogBlurX_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CmdSetShaderProgram(cmdBuf, blurState.blurXProgram); CmdSetResourceTable(cmdBuf, blurState.blurXTable[bufferIndex], NEBULA_BATCH_GROUP, ComputePipeline, nullptr); + auto [scaleX, scaleY] = FrameScript_default::TextureRelativeScale_VolumetricFogBuffer0(); + Blur2dRgba16fCs::BlurUniforms blurUniforms; + blurUniforms.Viewport[0] = viewport.width() * scaleX; + blurUniforms.Viewport[1] = viewport.height() * scaleY; + CoreGraphics::BufferUpdate(blurState.blurConstants, blurUniforms); + // fog0 -> read, fog1 -> write - TextureDimensions dims = TextureGetDimensions(fogState.fogVolumeTexture0); - CmdDispatch(cmdBuf, Math::divandroundup(dims.width, Blur2dRgba16fCs::BlurTileWidth), dims.height, 1); - }; + CmdDispatch(cmdBuf, Math::divandroundup(viewport.width() * scaleX, Blur2dRgba16fCs::BlurTileWidth), viewport.height() * scaleY, 1); - Frame::FrameCode* blurY = fogState.frameOpAllocator.Alloc(); - blurY->domain = CoreGraphics::BarrierDomain::Global; - blurY->textureDeps.Add(fogState.fogVolumeTexture1, - { - "Fog Volume Texture 1" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::TextureSubresourceInfo::Color(fogState.fogVolumeTexture1) - }); - blurY->textureDeps.Add(fogState.fogVolumeTexture0, - { - "Fog Volume Texture 0" - , CoreGraphics::PipelineStage::ComputeShaderWrite - , CoreGraphics::TextureSubresourceInfo::Color(fogState.fogVolumeTexture0) - }); - blurY->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }, nullptr, { + { FrameScript_default::TextureIndex::VolumetricFogBuffer0, CoreGraphics::PipelineStage::ComputeShaderRead } + , { FrameScript_default::TextureIndex::VolumetricFogBuffer1, CoreGraphics::PipelineStage::ComputeShaderWrite } + }); + + FrameScript_default::RegisterSubgraph_FogBlurY_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CmdSetShaderProgram(cmdBuf, blurState.blurYProgram); CmdSetResourceTable(cmdBuf, blurState.blurYTable[bufferIndex], NEBULA_BATCH_GROUP, ComputePipeline, nullptr); + auto [scaleX, scaleY] = FrameScript_default::TextureRelativeScale_VolumetricFogBuffer1(); + Blur2dRgba16fCs::BlurUniforms blurUniforms; + blurUniforms.Viewport[0] = viewport.width() * scaleX; + blurUniforms.Viewport[1] = viewport.height() * scaleY; + CoreGraphics::BufferUpdate(blurState.blurConstants, blurUniforms); + // fog0 -> read, fog1 -> write - TextureDimensions dims = TextureGetDimensions(fogState.fogVolumeTexture0); - CmdDispatch(cmdBuf, Math::divandroundup(dims.height, Blur2dRgba16fCs::BlurTileWidth), dims.width, 1); - }; - Frame::AddSubgraph("Fog Compute", { fogCompute, blurX, blurY }); + CmdDispatch(cmdBuf, Math::divandroundup(viewport.height() * scaleY, Blur2dRgba16fCs::BlurTileWidth), viewport.width() * scaleX, 1); + }, nullptr, { + { FrameScript_default::TextureIndex::VolumetricFogBuffer0, CoreGraphics::PipelineStage::ComputeShaderWrite } + , { FrameScript_default::TextureIndex::VolumetricFogBuffer1, CoreGraphics::PipelineStage::ComputeShaderRead } + }); } //------------------------------------------------------------------------------ @@ -454,7 +399,7 @@ VolumetricFogContext::UpdateViewDependentResources(const Ptr& vi fogState.color.store(fogUniforms.GlobalAbsorption); fogUniforms.DownscaleFog = 4; - ResourceTableSetRWTexture(fogState.resourceTables[bufferIndex], { fogState.fogVolumeTexture0, Volumefog::Table_Batch::Lighting_SLOT, 0, CoreGraphics::InvalidSamplerId }); + ResourceTableSetRWTexture(fogState.resourceTables[bufferIndex], { FrameScript_default::Texture_VolumetricFogBuffer0(), Volumefog::Table_Batch::Lighting_SLOT, 0, CoreGraphics::InvalidSamplerId }); ResourceTableCommitChanges(fogState.resourceTables[bufferIndex]); // get per-view resource tables @@ -465,10 +410,12 @@ VolumetricFogContext::UpdateViewDependentResources(const Ptr& vi ResourceTableCommitChanges(frameResourceTable); // setup blur tables - ResourceTableSetTexture(blurState.blurXTable[bufferIndex], { fogState.fogVolumeTexture0, Blur2dRgba16fCs::Table_Batch::InputImageX_SLOT, 0, CoreGraphics::InvalidSamplerId, false }); // ping - ResourceTableSetRWTexture(blurState.blurXTable[bufferIndex], { fogState.fogVolumeTexture1, Blur2dRgba16fCs::Table_Batch::BlurImageX_SLOT, 0, CoreGraphics::InvalidSamplerId }); // pong - ResourceTableSetTexture(blurState.blurYTable[bufferIndex], { fogState.fogVolumeTexture1, Blur2dRgba16fCs::Table_Batch::InputImageY_SLOT, 0, CoreGraphics::InvalidSamplerId }); // ping - ResourceTableSetRWTexture(blurState.blurYTable[bufferIndex], { fogState.fogVolumeTexture0, Blur2dRgba16fCs::Table_Batch::BlurImageY_SLOT, 0, CoreGraphics::InvalidSamplerId }); // pong + ResourceTableSetTexture(blurState.blurXTable[bufferIndex], { FrameScript_default::Texture_VolumetricFogBuffer0(), Blur2dRgba16fCs::Table_Batch::InputImageX_SLOT, 0, CoreGraphics::InvalidSamplerId, false }); // ping + ResourceTableSetRWTexture(blurState.blurXTable[bufferIndex], { FrameScript_default::Texture_VolumetricFogBuffer1(), Blur2dRgba16fCs::Table_Batch::BlurImageX_SLOT, 0, CoreGraphics::InvalidSamplerId }); // pong + ResourceTableSetTexture(blurState.blurYTable[bufferIndex], { FrameScript_default::Texture_VolumetricFogBuffer1(), Blur2dRgba16fCs::Table_Batch::InputImageY_SLOT, 0, CoreGraphics::InvalidSamplerId }); // ping + ResourceTableSetRWTexture(blurState.blurYTable[bufferIndex], { FrameScript_default::Texture_VolumetricFogBuffer0(), Blur2dRgba16fCs::Table_Batch::BlurImageY_SLOT, 0, CoreGraphics::InvalidSamplerId }); // pong + ResourceTableSetConstantBuffer(blurState.blurXTable[bufferIndex], { blurState.blurConstants, Blur2dRgba16fCs::Table_Batch::BlurUniforms_SLOT }); + ResourceTableSetConstantBuffer(blurState.blurYTable[bufferIndex], { blurState.blurConstants, Blur2dRgba16fCs::Table_Batch::BlurUniforms_SLOT }); ResourceTableCommitChanges(blurState.blurXTable[bufferIndex]); ResourceTableCommitChanges(blurState.blurYTable[bufferIndex]); } diff --git a/code/render/fog/volumetricfogcontext.h b/code/render/fog/volumetricfogcontext.h index 700bcefeca..22154b93c9 100644 --- a/code/render/fog/volumetricfogcontext.h +++ b/code/render/fog/volumetricfogcontext.h @@ -32,7 +32,7 @@ class VolumetricFogContext : public Graphics::GraphicsContext virtual ~VolumetricFogContext(); /// setup volumetric fog context - static void Create(const Ptr& frameScript); + static void Create(); /// discard volumetric fog context static void Discard(); diff --git a/code/render/frame/default.json b/code/render/frame/default.json new file mode 100644 index 0000000000..3fe3bd0644 --- /dev/null +++ b/code/render/frame/default.json @@ -0,0 +1,753 @@ +{ + "Nebula": { + "version": 3, + "Dependencies": [ + "Shadows" + ], + "ImportBuffers": [ + "ClusterBuffer", + "ClusterLightList", + "ClusterLightIndexLists", + "ClusterDecalList", + "ClusterDecalIndexLists", + "ClusterFogList", + "ClusterFogIndexLists", + "GridLightList", + "GridLightIndexLists", + "GridDecalList", + "GridDecalIndexLists", + "GridFogList", + "GridFogIndexLists", + "RayTracingObjectBindings", + "HistogramCounters", + "TerrainVirtualPageStatuses", + "TerrainSubTextures", + "TerrainUpdateList", + "VegetationDrawCountBuffer", + "VegetationGrassDrawsBuffer", + "VegetationGrassArgumentsBuffer", + "VegetationMeshDrawsBuffer", + "VegetationMeshArgumentsBuffer" + ], + "ImportTextures": [ + "HBAOInternal0", + "HBAOInternal1", + "BloomIntermediate", + "TerrainIndirection", + "TerrainIndirectionCopy", + "TerrainAlbedoCache", + "TerrainMaterialCache", + "TerrainNormalCache", + "SunShadowDepth" + ], + "LocalTextures": [ + { + "name": "ScreenBuffer", + "format": "R11G11B10F", + "relative": true, + "usage": "Render|TransferDestination", + "relativeSize": [ 1.0, 1.0 ], + "type": "Texture2D" + }, + { + "name": "ColorBuffer", + "format": "SRGBA8", + "usage": "Render|TransferSource", + "relativeSize": [ 1.0, 1.0 ], + "type": "Texture2D" + }, + { + "name": "SceneBuffer", + "format": "SRGBA8", + "usage": "Render|TransferSource", + "relativeSize": [ 1.0, 1.0 ], + "type": "Texture2D" + }, + { + "name": "AverageLumBuffer", + "format": "R16F", + "usage": "Render|TransferSource", + "fixedSize": [ 1.0, 1.0 ], + "type": "Texture2D" + }, + { + "name": "SSAOBuffer", + "format": "R16F", + "usage": "ReadWrite", + "relativeSize": [ 1.0, 1.0 ], + "type": "Texture2D" + }, + { + "name": "BloomBuffer", + "format": "R16G16B16A16F", + "usage": "Render|TransferSource|ReadWrite", + "relativeSize": [ 1.0, 1.0 ], + "type": "Texture2D" + }, + { + "name": "LightBuffer", + "format": "R11G11B10F", + "usage": "Render|ReadWrite|TransferSource", + "relativeSize": [ 1.0, 1.0 ], + "mips": "auto", + "type": "Texture2D" + }, + { + "name": "LightDebugBuffer", + "format": "R16G16B16A16F", + "usage": "ReadWrite", + "relativeSize": [ 1.0, 1.0 ], + "type": "Texture2D" + }, + { + "name": "VolumetricFogBuffer0", + "format": "R16G16B16A16F", + "usage": "ReadWrite", + "relativeSize": [ 0.25, 0.25 ], + "type": "Texture2D" + }, + { + "name": "VolumetricFogBuffer1", + "format": "R16G16B16A16F", + "usage": "ReadWrite", + "relativeSize": [ 0.25, 0.25 ], + "type": "Texture2D" + }, + { + "name": "ZBuffer", + "format": "D32S8", + "usage": "Render|Sample", + "relativeSize": [ 1.0, 1.0 ], + "type": "Texture2D" + }, + { + "name": "Depth", + "format": "R32F", + "mips": "auto", + "usage": "Sample|ReadWrite", + "relativeSize": [ 1.0, 1.0 ], + "type": "Texture2D" + }, + { + "name": "Stencil", + "format": "R8", + "usage": "TransferDestination|Sample", + "relativeSize": [ 1.0, 1.0 ], + "type": "Texture2D" + }, + { + "name": "ReflectionBuffer", + "format": "R16G16B16A16F", + "usage": "ReadWrite", + "relativeSize": [ 1.0, 1.0 ], + "type": "Texture2D" + }, + { + "name": "NormalBuffer", + "format": "R16G16B16A16F", + "usage": "Render", + "relativeSize": [ 1.0, 1.0 ], + "type": "Texture2D" + }, + { + "_comment": "RGB = Specular reflectivity, A = Roughness", + "name": "SpecularBuffer", + "format": "R8G8B8A8", + "usage": "Render", + "relativeSize": [ 1.0, 1.0 ], + "type": "Texture2D" + }, + { + "name": "TerrainPosBuffer", + "format": "R16G16F", + "usage": "Render", + "relativeSize": [ 1.0, 1.0 ], + "type": "Texture2D" + }, + { + "name": "RayTracingTestOutput", + "format": "R16G16B16A16F", + "fixedSize": [ 640, 480 ], + "usage": "ReadWrite", + "type": "Texture2D" + } + ], + "ExportTextures": [ + "ColorBuffer", + "SceneBuffer" + ], + + "Submissions": [ + { + "name": "Compute Prepass", + "queue": "Compute", + "_comment": "Perform clustering AABB generation and run culling for clustering systems", + "ops": [ + { + "subgraph": { + "name": "Raytracing Structures Update" + } + }, + { + "subgraph": { + "name": "Cluster AABB Generation" + } + }, + { + "subgraph": { + "name": "Lights Copy" + } + }, + { + "subgraph": { + "name": "Lights Cull" + } + }, + { + "subgraph": { + "name": "Decal Copy" + } + }, + { + "subgraph": { + "name": "Decal Cull" + } + }, + { + "subgraph": { + "name": "Fog Copy" + } + }, + { + "subgraph": { + "name": "Fog Cull" + } + }, + { + "subgraph": { + "name": "Sun Terrain Shadows" + } + }, + { + "subgraph": { + "name": "Raytracing Light Grid Gen" + } + }, + { + "subgraph": { + "name": "Raytracing Light Grid Cull" + } + }, + { + "subgraph": { + "name": "Terrain Raytracing Mesh Generate" + } + } + ] + }, + + { + "name": "Prepass", + "queue": "Graphics", + "_comment": "Calculate shadow maps and depth prepass", + "ops": [ + + { + "subgraph": { + "name": "Raytracing Test" + } + }, + { + "subgraph": { + "name": "StaticUI" + } + }, + + { + "subgraph": { + "name": "Vegetation Clear Draws" + } + }, + { + "subgraph": { + "name": "Vegetation Generate Draws" + } + }, + { + "subgraph": { + "name": "Vegetation Draw CPU Readback" + } + }, + + { + "subgraph": { + "name": "Terrain Prepare" + } + }, + { + "subgraph": { + "name": "Terrain Indirection Copy" + } + }, + + { + "pass": { + "name": "Prepass", + "attachments": [ + { + "name": "ZBuffer", + "clear_depth": 1, + "clear_stencil": 0, + "flags": "Store|StoreStencil" + }, + { + "name": "TerrainPosBuffer", + "clear": [ 0, 0, 0, 255 ], + "flags": "Store" + } + ], + + "subpasses": [ + { + "name": "TerrainPass", + "subpass_dependencies": [], + "attachments": [ "TerrainPosBuffer" ], + "depth": "ZBuffer", + "ops": [ + { + "subgraph": { + "name": "Terrain Prepass" + } + } + ] + }, + { + "name": "DepthPrepass", + "subpass_dependencies": [ "TerrainPass" ], + "attachments": [], + "depth": "ZBuffer", + "ops": [ + { + "batch": { + "name": "FlatGeometryDepth" + } + }, + { + "subgraph": { + "name": "Vegetation Prepass" + } + } + ] + } + ] + + } + }, + { + "subgraph": { + "name": "Terrain Page Extract" + + } + }, + { + "subgraph": { + "name": "Terrain Update Caches" + + } + }, + { + "subgraph": { + "name": "Terrain Pages Clear" + + } + }, + { + "subgraph": { + "name": "Depth Extract" + } + }, + + { + "subgraph": { + "name": "Depth Downsample" + } + } + ] + }, + + { + "name": "Scene", + "wait_for_submissions": [ "Compute Prepass", "Prepass", "Shadows" ], + "queue": "Graphics", + "last_submit": true, + "_comment": "Main graphics submission", + "ops": [ + { + "pass": { + "name": "ForwardRendering", + "attachments": [ + { + "name": "ZBuffer", + "flags": "Store|Load|LoadStencil" + }, + { + "name": "LightBuffer", + "clear": [ 0, 0, 0, 0 ], + "flags": "Store" + }, + { + "name": "NormalBuffer", + "flags": "Store", + "clear": [ 0, 0, 0, 0 ] + }, + { + "name": "SpecularBuffer", + "flags": "Store", + "clear": [ 0, 0, 0, 0 ] + } + + ], + + "subpasses": [ + { + "name": "OpaquePass", + "subpass_dependencies": [], + "attachments": [ "LightBuffer" ], + + "resource_dependencies": [ + { + "name": "SunShadowDepth", + "stage": "PixelShaderRead" + } + ], + + "depth": "ZBuffer", + "ops": [ + { + "subgraph": { + "name": "Terrain Resolve" + } + }, + { + "subgraph": { + "name": "Vegetation Render" + } + }, + { + "batch": { + "name": "FlatGeometryLit" + } + }, + { + "batch": { + "name": "LightMeshes" + } + } + ] + }, + { + "name": "Skypass", + "subpass_dependencies": [ "OpaquePass" ], + "attachments": [ "LightBuffer" ], + "depth": "ZBuffer", + "ops": [ + { + "batch": { + "name": "Background" + } + } + ] + + }, + { + "name": "AlphaPass", + "_comment": "TODO: Move this to a separate pass later on", + "subpass_dependencies": [ "Skypass" ], + "attachments": [ "LightBuffer" ], + "depth": "ZBuffer", + "ops": [ + { + "batch": { + "name": "FlatGeometryAlphaLit" + } + } + ] + } + ] + } + }, + + + { + "subgraph": { + "name": "Vegetation Copy Indirect" + } + }, + + { + "subgraph": { + "name": "HBAO X" + } + }, + { + "subgraph": { + "name": "HBAO Y" + } + }, + { + "subgraph": { + "name": "HBAO Blur X" + } + }, + { + "subgraph": { + "name": "HBAO Blur Y" + } + }, + + { + "subgraph": { + "name": "Fog Compute" + } + }, + + { + "subgraph": { + "name": "Fog Blur X" + } + }, + + { + "subgraph": { + "name": "Fog Blur Y" + } + }, + + { + "subgraph": { + "name": "Lights Combine" + } + }, + + { + "subgraph": { + "name": "Color Downsample" + } + }, + + { + "subgraph": { + "name": "Histogram Bin" + } + }, + { + "subgraph": { + "name": "Histogram Copy" + } + }, + { + "subgraph": { + "name": "Histogram Clear" + } + }, + + { + "subgraph": { + "name": "Bloom Intermediate" + } + }, + { + "subgraph": { + "name": "Bloom Merge" + } + }, + + { + "pass": { + "name": "PostEffects", + "attachments": [ + { + "name": "ColorBuffer", + "flags": "Load|Store" + }, + { + "name": "ZBuffer", + "flags": "Load" + } + ], + + "subpasses": [ + { + "name": "FinalizePass", + "subpass_dependencies": [], + "attachments": [ + "ColorBuffer" + ], + + "resource_dependencies": [ + { + "name": "BloomBuffer", + "stage": "PixelShaderRead" + }, + { + "name": "AverageLumBuffer", + "stage": "PixelShaderRead" + }, + { + "name": "LightBuffer", + "stage": "PixelShaderRead" + }, + { + "name": "Depth", + "stage": "PixelShaderRead" + } + ], + + "ops": [ + { + "fullscreen_effect": { + "name": "Finalize", + "shader": "system_shaders/finalize", + "mask": "Alt0", + "namespace": "Finalize", + "constantBlockName": "FinalizeBlock", + "variables": [ + { + "semantic": "LuminanceTexture", + "value": "AverageLumBuffer", + "type": "textureHandle" + }, + { + "semantic": "DepthTexture", + "value": "Depth", + "type": "textureHandle" + }, + { + "semantic": "ColorTexture", + "value": "LightBuffer", + "type": "textureHandle" + }, + { + "semantic": "BloomTexture", + "value": "BloomBuffer", + "type": "textureHandle" + } + ], + "size_from_texture": "ColorBuffer" + } + } + ] + }, + + { + "name": "Direct", + "subpass_dependencies": [ + "FinalizePass" + ], + "depth": "ZBuffer", + "attachments": [ + "ColorBuffer" + ], + + "resource_dependencies": [ + { + "name": "Depth", + "stage": "PixelShaderRead" + } + ], + + "ops": [ + { + "batch": { + "name": "DirectToColor" + } + }, + { + "batch": { + "name": "ParticleUnlit" + } + }, + { + "batch": { + "name": "ParticleLit" + } + }, + { + "subgraph": { + "name": "Im3D" + } + } + ] + } + ] + } + }, + + { + "blit": { + "name": "ColorBuffer Copy", + "from": { + "tex": "ColorBuffer" + }, + "to": { + "tex": "SceneBuffer" + } + } + }, + + { + "pass": { + "name": "GUI", + "attachments": [ + { + "name": "ColorBuffer", + "flags": "Load|Store" + }, + { + "name": "ZBuffer", + "flags": "Load|Discard" + } + ], + + "subpasses": [ + { + "name": "DynUI", + "depth": "ZBuffer", + "attachments": [ + "ColorBuffer" + ], + + "resource_dependencies": [ + { + "name": "Depth", + "stage": "PixelShaderRead" + } + ], + + "ops": [ + { + "subgraph": { + "name": "Debug Shapes" + } + }, + { + "subgraph": { + "name": "StaticUI To Backbuffer" + } + } + ] + } + ] + } + }, + { + "transition": { + "name": "ColorBuffer", + "stage": "ComputeShaderRead" + } + } + ] + } + ] + } +} diff --git a/code/render/frame/default.json.h b/code/render/frame/default.json.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/code/render/frame/default.yml b/code/render/frame/default.yml new file mode 100644 index 0000000000..c15ecb483c --- /dev/null +++ b/code/render/frame/default.yml @@ -0,0 +1,397 @@ +Nebula: + version: 3 + Dependencies: + - name: Shadows + ImportBuffers: + - name: ClusterBuffer + - name: ClusterLightList + - name: ClusterLightIndexLists + ImportTextures: + - name: SunShadowDepth + LocalTextures: + - name: ScreenBuffer + format: R11G11B10F + relative: true + usage: Render|TransferDestination + relativeSize: + - 1 + - 1 + type: Texture2D + - name: ColorBuffer + format: R8G8B8A8 + usage: Render|TransferSource + relativeSize: + - 1 + - 1 + type: Texture2D + - name: ColorBufferNoGUI + format: R8G8B8A8 + usage: Render|TransferSource + relativeSize: + - 1 + - 1 + type: Texture2D + - name: ShapeBuffer + format: R8G8B8A8 + usage: Render + relativeSize: + - 1 + - 1 + type: Texture2D + - name: AverageLumBuffer + format: R16F + usage: Render|TransferSource + fixedSize: + - 1 + - 1 + type: Texture2D + - name: SSAOBuffer + format: R16F + usage: ReadWrite + relativeSize: + - 1 + - 1 + type: Texture2D + - name: BloomBuffer + format: R16G16B16A16F + usage: Render|TransferSource|ReadWrite + relativeSize: + - 1 + - 1 + type: Texture2D + - name: LightBuffer + format: R11G11B10F + usage: Render|ReadWrite|TransferSource + relativeSize: + - 1 + - 1 + mips: auto + type: Texture2D + - name: LightDebugBuffer + format: R16G16B16A16F + usage: ReadWrite + relativeSize: + - 1 + - 1 + type: Texture2D + - name: VolumetricFogBuffer0 + format: R16G16B16A16F + usage: ReadWrite + relativeSize: + - 0.25 + - 0.25 + type: Texture2D + - name: VolumetricFogBuffer1 + format: R16G16B16A16F + usage: ReadWrite + relativeSize: + - 0.25 + - 0.25 + type: Texture2D + - name: ZBuffer + format: D32S8 + usage: Render|Sample + relativeSize: + - 1 + - 1 + type: Texture2D + - name: Depth + format: R32F + mips: auto + usage: Sample|ReadWrite + relativeSize: + - 1 + - 1 + type: Texture2D + - name: Stencil + format: R8 + usage: TransferDestination|Sample + relativeSize: + - 1 + - 1 + type: Texture2D + - name: ReflectionBuffer + format: R16G16B16A16F + usage: ReadWrite + relativeSize: + - 1 + - 1 + type: Texture2D + - name: NormalBuffer + format: R16G16B16A16F + usage: Render + relativeSize: + - 1 + - 1 + type: Texture2D + - _comment: 'RGB = Specular reflectivity, A = Roughness' + name: SpecularBuffer + format: R8G8B8A8 + usage: Render + relativeSize: + - 1 + - 1 + type: Texture2D + - name: TerrainPosBuffer + format: R16G16F + usage: Render + relativeSize: + - 1 + - 1 + type: Texture2D + - name: RayTracingTestOutput + format: R16G16B16A16F + fixedSize: + - 640 + - 480 + usage: ReadWrite + type: Texture2D + ExportTextures: + - name: ColorBuffer + Submissions: + - name: Compute Prepass + queue: Compute + wait_for_queue: Graphics + _comment: >- + Perform clustering AABB generation and run culling for clustering + systems + ops: + - subgraph: + name: Cluster AABB Generation + - subgraph: + name: Lights Copy + - subgraph: + name: Lights Cull + - subgraph: + name: Decal Cull + - subgraph: + name: Fog Cull + - subgraph: + name: Sun Terrain Shadows + - subgraph: + name: Raytracing Light Update + - subgraph: + name: Terrain Raytracing Mesh Generate + - name: Prepass + queue: Graphics + _comment: Calculate shadow maps and depth prepass + ops: + - subgraph: + name: Raytracing Test + - subgraph: + name: StaticUI + - subgraph: + name: Vegetation Generate Draws + - subgraph: + name: Terrain Prepare + - pass: + name: Prepass + attachments: + - name: ZBuffer + clear_depth: 1 + clear_stencil: 0 + flags: Store|StoreStencil + - name: TerrainPosBuffer + clear: + - 0 + - 0 + - 0 + - 255 + flags: Store + subpasses: + - name: TerrainPass + subpass_dependencies: [] + attachments: + - TerrainPosBuffer + depth: ZBuffer + ops: + - subgraph: + name: Terrain Prepass + - name: DepthPrepass + subpass_dependencies: + - TerrainPass + attachments: [] + depth: ZBuffer + ops: + - batch: + name: FlatGeometryDepth + - subgraph: + name: Vegetation Prepass + - subgraph: + name: Terrain Update Caches + - subgraph: + name: Depth Extract + - subgraph: + name: Depth Downsample + - name: Forward Shading and Post Effects + wait_for_submissions: + - Compute Prepass + - Prepass + queue: Graphics + _comment: Main graphics submission + ops: + - pass: + name: ForwardRendering + attachments: + - name: ZBuffer + flags: Store|Load|LoadStencil + - name: LightBuffer + clear: + - 0 + - 0 + - 0 + - 0 + flags: Store + - name: NormalBuffer + flags: Store + clear: + - 0 + - 0 + - 0 + - 0 + - name: SpecularBuffer + flags: Store + clear: + - 0 + - 0 + - 0 + - 0 + subpasses: + - name: OpaquePass + subpass_dependencies: [] + attachments: + - LightBuffer + resource_dependencies: + - name: SunShadowDepth + stage: PixelShaderRead + depth: ZBuffer + ops: + - subgraph: + name: Terrain Resolve + - subgraph: + name: Vegetation Render + - batch: + name: FlatGeometryLit + - batch: + name: LightMeshes + - name: Skypass + subpass_dependencies: + - OpaquePass + attachments: + - LightBuffer + depth: ZBuffer + ops: + - batch: + name: Background + - name: AlphaPass + _comment: 'TODO: Move this to a separate pass later on' + subpass_dependencies: + - Skypass + attachments: + - LightBuffer + depth: ZBuffer + ops: + - batch: + name: FlatGeometryAlphaLit + - subgraph: + name: Vegetation Copy Indirect + - subgraph: + name: HBAO + disabled: + - name: SSAOBuffer + value: Black + - subgraph: + name: Fog Compute + - subgraph: + name: Lights Combine + - subgraph: + name: Color Downsample + - subgraph: + name: Histogram + - subgraph: + name: Bloom + - pass: + name: PostEffects + attachments: + - name: ColorBuffer + flags: Load|Store + - name: ZBuffer + flags: Load + subpasses: + - name: FinalizePass + subpass_dependencies: [] + attachments: + - ColorBuffer + resource_dependencies: + - name: BloomBuffer + stage: PixelShaderRead + - name: AverageLumBuffer + stage: PixelShaderRead + - name: LightBuffer + stage: PixelShaderRead + - name: Depth + stage: PixelShaderRead + ops: + - fullscreen_effect: + name: Finalize + shader_state: + shader: 'shd:system_shaders/finalize.fxb' + variables: + - semantic: LuminanceTexture + value: AverageLumBuffer + - semantic: DepthTexture + value: Depth + - semantic: ColorTexture + value: LightBuffer + - semantic: BloomTexture + value: BloomBuffer + size_from_texture: ColorBuffer + - name: Direct + subpass_dependencies: + - FinalizePass + depth: ZBuffer + attachments: + - ColorBuffer + resource_dependencies: + - name: Depth + stage: PixelShaderRead + ops: + - batch: + name: DirectToColor + - batch: + name: ParticleUnlit + - batch: + name: ParticleLit + - subgraph: + name: Im3D + - blit: + name: ColorBuffer Copy + from: + tex: ColorBuffer + to: + tex: ColorBufferNoGUI + - pass: + name: GUI + attachments: + - name: ColorBuffer + flags: Load|Store + - name: ZBuffer + flags: Load|Discard + subpasses: + - name: DynUI + depth: ZBuffer + attachments: + - ColorBuffer + resource_dependencies: + - name: Depth + stage: PixelShaderRead + ops: + - subgraph: + name: Debug Shapes + - subgraph: + name: ImGUI + - subgraph: + name: StaticUI To Backbuffer + - swap: + name: Swap + from: ColorBuffer diff --git a/code/render/frame/frameblit.cc b/code/render/frame/frameblit.cc index 2e5a5b9855..b10ac58304 100644 --- a/code/render/frame/frameblit.cc +++ b/code/render/frame/frameblit.cc @@ -58,20 +58,12 @@ FrameBlit::CompiledImpl::Run(const CoreGraphics::CmdBufferId cmdBuf, const Index CoreGraphics::TextureDimensions toDims = TextureGetDimensions(this->to); // setup regions - Math::rectangle fromRegion; - fromRegion.left = 0; - fromRegion.top = 0; - fromRegion.right = fromDims.width; - fromRegion.bottom = fromDims.height; - Math::rectangle toRegion; - toRegion.left = 0; - toRegion.top = 0; - toRegion.right = toDims.width; - toRegion.bottom = toDims.height; + CoreGraphics::TextureCopy from{ .region = { 0, 0, fromDims.width, fromDims.height }, .mip = 0, .layer = 0, .bits = this->fromBits }; + CoreGraphics::TextureCopy to{ .region = { 0, 0, toDims.width, toDims.height }, .mip = 0, .layer = 0, .bits = this->toBits }; N_CMD_SCOPE(cmdBuf, NEBULA_MARKER_TRANSFER, this->name.Value()); - CoreGraphics::CmdBlit(cmdBuf, this->from, fromRegion, this->fromBits, 0, 0, this->to, toRegion, this->toBits, 0, 0); + CoreGraphics::CmdBlit(cmdBuf, this->from, from, this->to, to); } //------------------------------------------------------------------------------ diff --git a/code/render/frame/framecopy.cc b/code/render/frame/framecopy.cc index df0f30fa37..01397611d8 100644 --- a/code/render/frame/framecopy.cc +++ b/code/render/frame/framecopy.cc @@ -56,22 +56,10 @@ FrameCopy::CompiledImpl::Run(const CoreGraphics::CmdBufferId cmdBuf, const Index // get dimensions CoreGraphics::TextureDimensions fromDims = TextureGetDimensions(this->from); CoreGraphics::TextureDimensions toDims = TextureGetDimensions(this->to); - - // setup regions - Math::rectangle fromRegion(0, 0, fromDims.width, fromDims.height); - Math::rectangle toRegion(0, 0, toDims.width, toDims.height); - N_CMD_SCOPE(cmdBuf, NEBULA_MARKER_TRANSFER, this->name.Value()); - CoreGraphics::TextureCopy from, to; - from.region = fromRegion; - from.mip = 0; - from.layer = 0; - from.bits = this->fromBits; - to.region = toRegion; - to.mip = 0; - to.layer = 0; - to.bits = this->toBits; + CoreGraphics::TextureCopy from{ .region = { 0, 0, fromDims.width, fromDims.height }, .mip = 0, .layer = 0, .bits = this->fromBits }; + CoreGraphics::TextureCopy to{ .region = { 0, 0, toDims.width, toDims.height }, .mip = 0, .layer = 0, .bits = this->toBits }; CoreGraphics::CmdCopy(cmdBuf, this->from, { from }, this->to, { to }); } diff --git a/code/render/frame/frameresolve.cc b/code/render/frame/frameresolve.cc index 65152b5193..d7fd23c462 100644 --- a/code/render/frame/frameresolve.cc +++ b/code/render/frame/frameresolve.cc @@ -104,15 +104,8 @@ FrameResolve::CompiledImpl::Run(const CoreGraphics::CmdBufferId cmdBuf, const In TextureDimensions fromDims = TextureGetDimensions(this->from); TextureDimensions toDims = TextureGetDimensions(this->to); - CoreGraphics::TextureCopy from, to; - from.region.set(0, 0, fromDims.width, fromDims.height); - from.mip = 0; - from.layer = 0; - from.bits = this->fromBits; - to.region.set(0, 0, toDims.width, toDims.height); - to.mip = 0; - to.layer = 0; - to.bits = this->toBits; + CoreGraphics::TextureCopy from{ .region = { 0, 0, fromDims.width, fromDims.height }, .mip = 0, .layer = 0, .bits = this->fromBits }; + CoreGraphics::TextureCopy to{ .region = { 0, 0, toDims.width, toDims.height }, .mip = 0, .layer = 0, .bits = this->toBits }; CmdResolve(cmdBuf, this->from, from, this->to, to); } } diff --git a/code/render/frame/framescript.h b/code/render/frame/framescript.h index aa2949db09..2e05ccdf28 100644 --- a/code/render/frame/framescript.h +++ b/code/render/frame/framescript.h @@ -28,6 +28,7 @@ namespace Graphics { class View; + class GraphicsServer; } namespace CoreGraphics diff --git a/code/render/frame/framescriptloader.cc b/code/render/frame/framescriptloader.cc index 147efa05b9..04584f1ff9 100644 --- a/code/render/frame/framescriptloader.cc +++ b/code/render/frame/framescriptloader.cc @@ -1138,9 +1138,9 @@ void FrameScriptLoader::ParseSubpassBatch(const Ptr& script, Frame::FrameSubpass* subpass, JzonValue* node) { JzonValue* name = jzon_get(node, "name"); - CoreGraphics::BatchGroup::Code batch = CoreGraphics::BatchGroup::FromName(name->string_value); + MaterialTemplates::BatchGroup batch = MaterialTemplates::BatchGroupFromName(name->string_value); n_assert(name != nullptr); - if (MaterialTemplates::Configs.FindIndex(batch) == InvalidIndex) + if (batch == MaterialTemplates::BatchGroup::Invalid) { n_warning("[FrameScript] - Skipping, batch with name '%s' because it's not rendered by any material\n", name->string_value); return; @@ -1158,7 +1158,7 @@ FrameScriptLoader::ParseSubpassBatch(const Ptr& script, Fram ParseResourceDependencies(script, op, inputs); } - op->batch = CoreGraphics::BatchGroup::FromName(name->string_value); + op->batch = batch; subpass->AddChild(op); } @@ -1169,9 +1169,9 @@ void FrameScriptLoader::ParseSubpassSortedBatch(const Ptr& script, Frame::FrameSubpass* subpass, JzonValue* node) { JzonValue* name = jzon_get(node, "name"); - CoreGraphics::BatchGroup::Code batch = CoreGraphics::BatchGroup::FromName(name->string_value); + MaterialTemplates::BatchGroup batch = MaterialTemplates::BatchGroupFromName(name->string_value); n_assert(name != nullptr); - if (MaterialTemplates::Configs.FindIndex(batch) == InvalidIndex) + if (batch == MaterialTemplates::BatchGroup::Invalid) { n_warning("Skipping, batch with name '%s' because it's not rendered by any material\n", name->string_value); return; diff --git a/code/render/frame/framesubmission.cc b/code/render/frame/framesubmission.cc index 5a2adbff8b..20387a4382 100644 --- a/code/render/frame/framesubmission.cc +++ b/code/render/frame/framesubmission.cc @@ -117,7 +117,7 @@ FrameSubmission::CompiledImpl::Run(const CoreGraphics::CmdBufferId cmdBuf, const // If a wait submission is present, append a wait for the subission we just did for (IndexT i = 0; i < this->waitSubmissions.Size(); i++) - CoreGraphics::WaitForSubmission(this->waitSubmissions[i]->submissionId, this->queue, this->waitSubmissions[i]->queue); + CoreGraphics::WaitForSubmission(this->waitSubmissions[i]->submissionId, this->queue); for (IndexT i = 0; i < this->waitQueues.Size(); i++) CoreGraphics::WaitForLastSubmission(this->queue, this->waitQueues[i]); diff --git a/code/render/frame/framesubpassbatch.cc b/code/render/frame/framesubpassbatch.cc index 2b58a43ad6..a000fde9b8 100644 --- a/code/render/frame/framesubpassbatch.cc +++ b/code/render/frame/framesubpassbatch.cc @@ -58,11 +58,11 @@ FrameSubpassBatch::AllocCompiled(Memory::ArenaAllocator& allocator) /** */ void -FrameSubpassBatch::DrawBatch(const CoreGraphics::CmdBufferId cmdBuf, CoreGraphics::BatchGroup::Code batch, const Graphics::GraphicsEntityId id, const IndexT bufferIndex) +FrameSubpassBatch::DrawBatch(const CoreGraphics::CmdBufferId cmdBuf, MaterialTemplates::BatchGroup batch, const Graphics::GraphicsEntityId id, const IndexT bufferIndex) { // get current view and visibility draw list const Visibility::ObserverContext::VisibilityDrawList* drawList = Visibility::ObserverContext::GetVisibilityDrawList(id); - const Util::Array& types = MaterialTemplates::Configs[batch]; + const Util::Array& types = MaterialTemplates::Configs[(uint)batch]; if (types.Size() != 0 && (drawList != nullptr)) { for (IndexT typeIdx = 0; typeIdx < types.Size(); typeIdx++) @@ -153,11 +153,11 @@ FrameSubpassBatch::DrawBatch(const CoreGraphics::CmdBufferId cmdBuf, CoreGraphic /** */ void -FrameSubpassBatch::DrawBatch(const CoreGraphics::CmdBufferId cmdBuf, CoreGraphics::BatchGroup::Code batch, const Graphics::GraphicsEntityId id, const SizeT numInstances, const IndexT baseInstance, const IndexT bufferIndex) +FrameSubpassBatch::DrawBatch(const CoreGraphics::CmdBufferId cmdBuf, MaterialTemplates::BatchGroup batch, const Graphics::GraphicsEntityId id, const SizeT numInstances, const IndexT baseInstance, const IndexT bufferIndex) { // get current view and visibility draw list const Visibility::ObserverContext::VisibilityDrawList* drawList = Visibility::ObserverContext::GetVisibilityDrawList(id); - const Util::Array& types = MaterialTemplates::Configs[batch]; + const Util::Array& types = MaterialTemplates::Configs[(uint)batch]; if (types.Size() != 0 && (drawList != nullptr)) { for (IndexT typeIdx = 0; typeIdx < types.Size(); typeIdx++) diff --git a/code/render/frame/framesubpassbatch.h b/code/render/frame/framesubpassbatch.h index 354b66e0d4..283a37f29f 100644 --- a/code/render/frame/framesubpassbatch.h +++ b/code/render/frame/framesubpassbatch.h @@ -8,7 +8,7 @@ */ //------------------------------------------------------------------------------ #include "frameop.h" -#include "coregraphics/batchgroup.h" +#include "materials/materialtemplates.h" #include "graphics/graphicsentity.h" namespace Frame { @@ -24,16 +24,16 @@ class FrameSubpassBatch : public FrameOp { void Run(const CoreGraphics::CmdBufferId cmdBuf, const IndexT frameIndex, const IndexT bufferIndex) override; - CoreGraphics::BatchGroup::Code batch; + MaterialTemplates::BatchGroup batch; }; FrameOp::Compiled* AllocCompiled(Memory::ArenaAllocator& allocator); - CoreGraphics::BatchGroup::Code batch; + MaterialTemplates::BatchGroup batch; /// Do the actual drawing - static void DrawBatch(const CoreGraphics::CmdBufferId cmdBuf, CoreGraphics::BatchGroup::Code batch, const Graphics::GraphicsEntityId id, const IndexT bufferIndex); + static void DrawBatch(const CoreGraphics::CmdBufferId cmdBuf, MaterialTemplates::BatchGroup batch, const Graphics::GraphicsEntityId id, const IndexT bufferIndex); /// Do the actual drawing, but with duplicate instances - static void DrawBatch(const CoreGraphics::CmdBufferId cmdBuf, CoreGraphics::BatchGroup::Code batch, const Graphics::GraphicsEntityId id, const SizeT numInstances, const IndexT baseInstance, const IndexT bufferIndex); + static void DrawBatch(const CoreGraphics::CmdBufferId cmdBuf, MaterialTemplates::BatchGroup batch, const Graphics::GraphicsEntityId id, const SizeT numInstances, const IndexT baseInstance, const IndexT bufferIndex); }; } // namespace Frame2 diff --git a/code/render/frame/framesubpassfullscreeneffect.cc b/code/render/frame/framesubpassfullscreeneffect.cc index c276b4f9a0..16677412fb 100644 --- a/code/render/frame/framesubpassfullscreeneffect.cc +++ b/code/render/frame/framesubpassfullscreeneffect.cc @@ -109,6 +109,7 @@ FrameSubpassFullscreenEffect::CompiledImpl::Run(const CoreGraphics::CmdBufferId // draw RenderUtil::DrawFullScreenQuad::ApplyMesh(cmdBuf); + CoreGraphics::CmdSetGraphicsPipeline(cmdBuf); CoreGraphics::CmdSetResourceTable(cmdBuf, this->resourceTable, NEBULA_BATCH_GROUP, CoreGraphics::GraphicsPipeline, nullptr); CoreGraphics::CmdDraw(cmdBuf, RenderUtil::DrawFullScreenQuad::GetPrimitiveGroup()); } diff --git a/code/render/frame/framesubpassorderedbatch.h b/code/render/frame/framesubpassorderedbatch.h index 2ab2b9759d..822e5dc9eb 100644 --- a/code/render/frame/framesubpassorderedbatch.h +++ b/code/render/frame/framesubpassorderedbatch.h @@ -9,7 +9,6 @@ */ //------------------------------------------------------------------------------ #include "frameop.h" -#include "coregraphics/batchgroup.h" namespace Frame { class FrameSubpassOrderedBatch : public FrameOp @@ -24,12 +23,12 @@ class FrameSubpassOrderedBatch : public FrameOp { void Run(const CoreGraphics::CmdBufferId cmdBuf, const IndexT frameIndex, const IndexT bufferIndex) override; - CoreGraphics::BatchGroup::Code batch; + MaterialTemplates::BatchGroup batch; }; FrameOp::Compiled* AllocCompiled(Memory::ArenaAllocator& allocator); - CoreGraphics::BatchGroup::Code batch; + MaterialTemplates::BatchGroup batch; }; } // namespace Frame2 diff --git a/code/render/frame/shadows.json b/code/render/frame/shadows.json new file mode 100644 index 0000000000..e95b6589c1 --- /dev/null +++ b/code/render/frame/shadows.json @@ -0,0 +1,105 @@ +{ + "Nebula": { + "version": 3, + "LocalTextures": [ + { + "name": "LocalLightShadow", + "format": "D32", + "relativeSize": [ 0.5, 0.5 ], + "layers": 16, + "usage": "Render", + "type": "Texture2DArray" + }, + { + "name": "SunShadowDepth", + "format": "D32", + "relativeSize": [1.0, 1.0], + "layers": 4, + "usage": "Render", + "type": "Texture2DArray" + }, + + ], + "ExportTextures": [ + "SunShadowDepth" + ], + "Submissions": [ + { + "name": "Shadows", + "queue": "Graphics", + "_comment": "Render and blur shadow maps", + "ops": [ + + { + "pass": { + "name": "Sun Shadows Pass", + "attachments": [ + { + "name": "SunShadowDepth", + "clear_depth": 1, + "flags": "Store" + } + ], + + "subpasses": [ + { + "name": "Sun Shadows", + "subpass_dependencies": [], + "depth": "SunShadowDepth", + "ops": [ + { + "subgraph": { + "name": "Sun Shadows" + } + } + ] + } + ] + } + + }, + + { + "pass": { + "name": "Local Shadows Pass", + "attachments": [ + { + "name": "LocalLightShadow", + "clear_depth": 1, + "flags": "Store" + } + ], + + "subpasses": [ + { + "name": "Spotlight Shadows", + "subpass_dependencies": [], + "depth": "LocalLightShadow", + "ops": [ + { + "subgraph": { + "name": "Spotlight Shadows" + } + } + ] + } + ] + } + }, + + { + "subgraph": { + "name": "Spotlight Blur" + + } + }, + { + "subgraph": { + "name": "Sun Blur" + } + } + ] + } + ] + } +} diff --git a/code/render/framescripts/framescripts.cc b/code/render/framescripts/framescripts.cc new file mode 100644 index 0000000000..2d7a7ceb0a --- /dev/null +++ b/code/render/framescripts/framescripts.cc @@ -0,0 +1,198 @@ +//------------------------------------------------------------------------------ +// @file framescripts.cc +// @copyright (C) 2024 Individual contributors, see AUTHORS file +//------------------------------------------------------------------------------ +#include "foundation/stdneb.h" +#include "framescripts.h" +#include "visibility/visibilitycontext.h" +#include "materials/materialtemplates.h" + +namespace Frame +{ + +//------------------------------------------------------------------------------ +/** +*/ +void +DrawBatch(const CoreGraphics::CmdBufferId cmdBuf, MaterialTemplates::BatchGroup batch, const Graphics::GraphicsEntityId id, const IndexT bufferIndex) +{ + const Visibility::ObserverContext::VisibilityDrawList* drawList = Visibility::ObserverContext::GetVisibilityDrawList(id); + const Util::Array& types = MaterialTemplates::Configs[(uint)batch]; + if (types.Size() != 0 && (drawList != nullptr)) + { + for (IndexT typeIdx = 0; typeIdx < types.Size(); typeIdx++) + { + MaterialTemplates::Entry* type = types[typeIdx]; + IndexT idx = drawList->visibilityTable.FindIndex(type); + if (idx != InvalidIndex) + { + N_CMD_SCOPE(cmdBuf, NEBULA_MARKER_DARK_GREEN, type->name); + + // if BeginBatch returns true if this material type has a shader for this batch + IndexT batchIndex = type->passes.FindIndex(batch); + if (batchIndex != InvalidIndex) + { + // Bind shader + const auto& pass = type->passes.ValueAtIndex(batchIndex); + CoreGraphics::CmdSetShaderProgram(cmdBuf, pass->program); + const Visibility::ObserverContext::VisibilityBatchCommand& visBatchCmd = drawList->visibilityTable.ValueAtIndex(type, idx); + uint const start = visBatchCmd.packetOffset; + uint const end = visBatchCmd.packetOffset + visBatchCmd.numDrawPackets; + Visibility::ObserverContext::VisibilityModelCommand* visModelCmd = visBatchCmd.models.Begin(); + Visibility::ObserverContext::VisibilityDrawCommand* visDrawCmd = visBatchCmd.draws.Begin(); + uint32 numInstances = 0; + uint32 baseInstance = 0; + CoreGraphics::PrimitiveGroup primGroup; + CoreGraphics::MeshId mesh = CoreGraphics::InvalidMeshId; + + for (uint packetIndex = start; packetIndex < end; ++packetIndex) + { + Models::ShaderStateNode::DrawPacket* instance = drawList->drawPackets[packetIndex]; + + // If new model node, bind model resources (vertex buffer, index buffer, vertex layout, primitive group) + if (visModelCmd && visModelCmd->offset == packetIndex) + { +#if NEBULA_GRAPHICS_DEBUG + CoreGraphics::CmdInsertMarker(cmdBuf, NEBULA_MARKER_DARK_DARK_GREEN, visModelCmd->nodeName.Value()); +#endif + // Run model setup (applies vertex/index buffer and vertex layout) + primGroup = visModelCmd->primitiveGroup; + + if (primGroup.GetNumIndices() > 0 || primGroup.GetNumVertices() > 0) + { + if (visModelCmd != nullptr && mesh != visModelCmd->mesh) + { + CoreGraphics::MeshBind(visModelCmd->mesh, cmdBuf); + mesh = visModelCmd->mesh; + + // Bind graphics pipeline + CoreGraphics::CmdSetGraphicsPipeline(cmdBuf); + } + + // Apply material + MaterialApply(visModelCmd->material, cmdBuf, pass->index); + } + + // Progress to next model command + visModelCmd++; + + if (visModelCmd == visBatchCmd.models.End()) + visModelCmd = nullptr; + } + + // If new draw setup, progress to the next one + if (visDrawCmd && visDrawCmd->offset == packetIndex) + { + numInstances = visDrawCmd->numInstances; + baseInstance = visDrawCmd->baseInstance; + visDrawCmd++; + + if (visDrawCmd == visBatchCmd.draws.End()) + visDrawCmd = nullptr; + } + + // Apply draw packet constants and draw + if (primGroup.GetNumIndices() > 0 || primGroup.GetNumVertices() > 0) + { + instance->Apply(cmdBuf, pass->index, bufferIndex); + CoreGraphics::CmdDraw(cmdBuf, numInstances, baseInstance, primGroup); + } + } + } + } + } + } +} + +//------------------------------------------------------------------------------ +/** +*/ +void +DrawBatch(const CoreGraphics::CmdBufferId cmdBuf, MaterialTemplates::BatchGroup batch, const Graphics::GraphicsEntityId id, const SizeT numInstances, const IndexT baseInstance, const IndexT bufferIndex) +{ + const Visibility::ObserverContext::VisibilityDrawList* drawList = Visibility::ObserverContext::GetVisibilityDrawList(id); + const Util::Array& types = MaterialTemplates::Configs[(uint)batch]; + + if (types.Size() != 0 && (drawList != nullptr)) + { + for (IndexT typeIdx = 0; typeIdx < types.Size(); typeIdx++) + { + MaterialTemplates::Entry* type = types[typeIdx]; + IndexT idx = drawList->visibilityTable.FindIndex(type); + if (idx != InvalidIndex) + { + N_CMD_SCOPE(cmdBuf, NEBULA_MARKER_DARK_GREEN, type->name); + + // if BeginBatch returns true if this material type has a shader for this batch + IndexT batchIndex = type->passes.FindIndex(batch); + if (batchIndex != InvalidIndex) + { + const auto& pass = type->passes.ValueAtIndex(batchIndex); + CoreGraphics::CmdSetShaderProgram(cmdBuf, pass->program); + const Visibility::ObserverContext::VisibilityBatchCommand& visBatchCmd = drawList->visibilityTable.ValueAtIndex(type, idx); + uint const start = visBatchCmd.packetOffset; + uint const end = visBatchCmd.packetOffset + visBatchCmd.numDrawPackets; + Visibility::ObserverContext::VisibilityModelCommand* visModelCmd = visBatchCmd.models.Begin(); + Visibility::ObserverContext::VisibilityDrawCommand* visDrawCmd = visBatchCmd.draws.Begin(); + uint32 baseNumInstances = 0; + uint32 baseBaseInstance = 0; + CoreGraphics::PrimitiveGroup primGroup; + CoreGraphics::MeshId mesh = CoreGraphics::InvalidMeshId; + + for (uint packetIndex = start; packetIndex < end; ++packetIndex) + { + Models::ShaderStateNode::DrawPacket* instance = drawList->drawPackets[packetIndex]; + + // If new model node, bind model resources (vertex buffer, index buffer, vertex layout, primitive group) + if (visModelCmd && visModelCmd->offset == packetIndex) + { +#if NEBULA_GRAPHICS_DEBUG + CoreGraphics::CmdInsertMarker(cmdBuf, NEBULA_MARKER_DARK_DARK_GREEN, visModelCmd->nodeName.Value()); +#endif + // Run model setup (applies vertex/index buffer and vertex layout) + primGroup = visModelCmd->primitiveGroup; + + if (primGroup.GetNumIndices() > 0 || primGroup.GetNumVertices() > 0) + { + if (mesh != visModelCmd->mesh) + { + CoreGraphics::MeshBind(visModelCmd->mesh, cmdBuf); + mesh = visModelCmd->mesh; + + // Bind graphics pipeline + CoreGraphics::CmdSetGraphicsPipeline(cmdBuf); + } + + // Apply material + MaterialApply(visModelCmd->material, cmdBuf, pass->index); + } + + // Progress to next model command + visModelCmd++; + + if (visModelCmd == visBatchCmd.models.End()) + visModelCmd = nullptr; + } + + // If new draw setup, progress to the next one + if (visDrawCmd && visDrawCmd->offset == packetIndex) + { + baseNumInstances = visDrawCmd->numInstances; + baseBaseInstance = visDrawCmd->baseInstance; + visDrawCmd++; + + if (visDrawCmd == visBatchCmd.draws.End()) + visDrawCmd = nullptr; + } + + // Apply draw packet constants and draw + instance->Apply(cmdBuf, pass->index, bufferIndex); + CoreGraphics::CmdDraw(cmdBuf, baseNumInstances * numInstances, baseBaseInstance + baseInstance, primGroup); + } + } + } + } + } +} + +} // namespace Frame diff --git a/code/render/framescripts/framescripts.h b/code/render/framescripts/framescripts.h new file mode 100644 index 0000000000..d21ee93345 --- /dev/null +++ b/code/render/framescripts/framescripts.h @@ -0,0 +1,47 @@ +#pragma once +//------------------------------------------------------------------------------ +/** + Include file for frame scripts + + @copyright + (C) 2024 Individual contributors, see AUTHORS file +*/ +//------------------------------------------------------------------------------ +#include "coregraphics/commandbuffer.h" +#include "graphics/graphicsentity.h" +#include "materials/materialtemplates.h" + +namespace Frame +{ + +struct TextureExport +{ + uint index; + CoreGraphics::TextureId tex; + CoreGraphics::PipelineStage stage; +}; + +struct TextureImport +{ + CoreGraphics::TextureId tex; + CoreGraphics::PipelineStage stage = CoreGraphics::PipelineStage::AllShadersRead; + + explicit TextureImport(const CoreGraphics::TextureId id) + { + this->tex = id; + } + + static TextureImport FromExport(const TextureExport& exp) + { + auto ret = TextureImport(exp.tex); + ret.stage = exp.stage; + return ret; + } +}; + +/// Draw +void DrawBatch(const CoreGraphics::CmdBufferId cmdBuf, MaterialTemplates::BatchGroup batch, const Graphics::GraphicsEntityId id, const IndexT bufferIndex); +/// Draw instanced +void DrawBatch(const CoreGraphics::CmdBufferId cmdBuf, MaterialTemplates::BatchGroup batch, const Graphics::GraphicsEntityId id, const SizeT numInstances, const IndexT baseInstance, const IndexT bufferIndex); + +} // namespace Frame diff --git a/code/render/graphics/glfw/glfwgraphicsdisplayeventhandler.cc b/code/render/graphics/glfw/glfwgraphicsdisplayeventhandler.cc index 18fbfa5779..8633b41360 100644 --- a/code/render/graphics/glfw/glfwgraphicsdisplayeventhandler.cc +++ b/code/render/graphics/glfw/glfwgraphicsdisplayeventhandler.cc @@ -24,7 +24,6 @@ bool GLFWGraphicsDisplayEventHandler::HandleEvent(const DisplayEvent& displayEvent) { Ptr graphicsServer = Graphics::GraphicsServer::Instance(); - Ptr frameServer = Frame::FrameServer::Instance(); #if __VULKAN__ Vulkan::VkPipelineDatabase* pipelineDatabase = Vulkan::VkPipelineDatabase::Instance(); #endif @@ -35,15 +34,9 @@ GLFWGraphicsDisplayEventHandler::HandleEvent(const DisplayEvent& displayEvent) // Invalidate pipelines pipelineDatabase->RecreatePipelines(); - // Trigger a framescript resize - frameServer->OnWindowResize(); - // Run all contexts resize calls graphicsServer->OnWindowResized(displayEvent.GetWindowId()); - // Finally, tell all framescripts to rebuild - frameServer->RebuildScripts(); - return true; } default: diff --git a/code/render/graphics/globalconstants.cc b/code/render/graphics/globalconstants.cc index c724fc4da0..177dbb76a7 100644 --- a/code/render/graphics/globalconstants.cc +++ b/code/render/graphics/globalconstants.cc @@ -5,6 +5,8 @@ #include "globalconstants.h" #include "coregraphics/shader.h" +#include "frame/default.h" + namespace Graphics { @@ -247,12 +249,12 @@ SetGlobalEnvironmentTextures(const CoreGraphics::TextureId& env, const CoreGraph /** */ void -SetupBufferConstants(const Ptr& frameScript) +SetupBufferConstants() { - state.tickParams.NormalBuffer = TextureGetBindlessHandle(frameScript->GetTexture("NormalBuffer")); - state.tickParams.SpecularBuffer = TextureGetBindlessHandle(frameScript->GetTexture("SpecularBuffer")); - state.tickParams.DepthBuffer = TextureGetBindlessHandle(frameScript->GetTexture("ZBuffer")); - state.tickParams.DepthBufferCopy = TextureGetBindlessHandle(frameScript->GetTexture("Depth")); + state.tickParams.NormalBuffer = TextureGetBindlessHandle(FrameScript_default::Texture_NormalBuffer()); + state.tickParams.SpecularBuffer = TextureGetBindlessHandle(FrameScript_default::Texture_SpecularBuffer()); + state.tickParams.DepthBuffer = TextureGetBindlessHandle(FrameScript_default::Texture_ZBuffer()); + state.tickParams.DepthBufferCopy = TextureGetBindlessHandle(FrameScript_default::Texture_Depth()); } //------------------------------------------------------------------------------ diff --git a/code/render/graphics/globalconstants.h b/code/render/graphics/globalconstants.h index 0289cd0cbd..d17260b532 100644 --- a/code/render/graphics/globalconstants.h +++ b/code/render/graphics/globalconstants.h @@ -48,7 +48,7 @@ const Shared::ShadowViewConstants& GetShadowViewConstants(); /// Set global irradiance and cubemaps void SetGlobalEnvironmentTextures(const CoreGraphics::TextureId& env, const CoreGraphics::TextureId& irr, const SizeT numMips); /// Setup gbuffer bindings -void SetupBufferConstants(const Ptr& frameScript); +void SetupBufferConstants(); /// Get per-tick resource table for graphics const CoreGraphics::ResourceTableId GetFrameResourceTable(uint32_t bufferIndex); diff --git a/code/render/graphics/graphicsserver.cc b/code/render/graphics/graphicsserver.cc index f9e9780771..4de3b1ed11 100644 --- a/code/render/graphics/graphicsserver.cc +++ b/code/render/graphics/graphicsserver.cc @@ -22,6 +22,14 @@ #include "bindlessregistry.h" #include "globalconstants.h" +#include "frame/default.h" +#include "frame/shadows.h" +#if WITH_NEBULA_EDITOR +#include "frame/editorframe.h" +#endif + +#include "coregraphics/swapchain.h" + namespace Graphics { @@ -33,6 +41,7 @@ __ImplementSingleton(Graphics::GraphicsServer); */ GraphicsServer::GraphicsServer() : isOpen(false) + , resizeCall(nullptr) { __ConstructSingleton; } @@ -84,7 +93,7 @@ GraphicsServer::Open() 8_MB, // Device <-> host mirrored memory block size }, .maxOcclusionQueries = 0x1000, - .maxTimestampQueries = 0x100, + .maxTimestampQueries = 0x400, .maxStatisticsQueries = 0x100, .numBufferedFrames = 3, .enableValidation = true, @@ -195,9 +204,6 @@ GraphicsServer::Open() CoreGraphics::RectangleMesh = RenderUtil::GeometryHelpers::CreateRectangle(); CoreGraphics::DiskMesh = RenderUtil::GeometryHelpers::CreateDisk(16); - this->frameServer = Frame::FrameServer::Create(); - this->frameServer->Open(); - this->shapeRenderer = CoreGraphics::ShapeRenderer::Create(); this->shapeRenderer->Open(); @@ -208,8 +214,6 @@ GraphicsServer::Open() if (!this->timer->IsTimeRunning()) this->timer->StartTime(); - - // tell the resource manager to load default resources once we are done setting everything up Resources::ResourceServer::Instance()->LoadDefaultResources(); } @@ -238,9 +242,6 @@ GraphicsServer::Close() this->shapeRenderer->Close(); this->shapeRenderer = nullptr; - this->frameServer->Close(); - this->frameServer = nullptr; - this->shaderServer->Close(); this->shaderServer = nullptr; @@ -283,6 +284,13 @@ void GraphicsServer::OnWindowResized(CoreGraphics::WindowId wndId) { CoreGraphics::DisplayMode const mode = CoreGraphics::WindowGetDisplayMode(wndId); + + CoreGraphics::WaitAndClearPendingCommands(); + + // First, call the resize callback to trigger an update of the frame scripts + if (this->resizeCall != nullptr) + this->resizeCall(mode.GetWidth(), mode.GetHeight()); + for (IndexT i = 0; i < this->contexts.Size(); ++i) { if (this->contexts[i]->OnWindowResized != nullptr) @@ -347,19 +355,14 @@ GraphicsServer::DiscardStage(const Ptr& stage) /** */ Ptr -GraphicsServer::CreateView(const Util::StringAtom& name, const IO::URI& framescript, const CoreGraphics::WindowId window) +GraphicsServer::CreateView(const Util::StringAtom& name, void(*render)(const Math::rectangle&, IndexT, IndexT), const Math::rectangle& viewport) { + n_assert(viewport.width() > 0 && viewport.height() > 0); Ptr view = View::Create(); - - // Make sure the window we pass is made current for the frame script loading to get the correct window - CoreGraphics::WindowId prevWindow = CoreGraphics::CurrentWindow; - CoreGraphics::WindowMakeCurrent(window); - Ptr frameScript = Frame::FrameServer::Instance()->LoadFrameScript(name.AsString() + "_framescript", framescript, window); - frameScript->window = window; - CoreGraphics::WindowMakeCurrent(prevWindow); - - view->script = frameScript; + view->SetFrameScript(render); + view->SetViewport(viewport); this->views.Append(view); + this->viewsByName.Add(name, view); // invoke all interested contexts IndexT i; @@ -378,7 +381,7 @@ Ptr GraphicsServer::CreateView(const Util::StringAtom& name) { Ptr view = View::Create(); - view->script = nullptr; + view->func = nullptr; this->views.Append(view); // invoke all interested contexts @@ -406,10 +409,8 @@ GraphicsServer::DiscardView(const Ptr& view) if (this->contexts[i]->OnDiscardView != nullptr) this->contexts[i]->OnDiscardView(view); } - view->script->Discard(); } - //------------------------------------------------------------------------------ /** */ @@ -419,7 +420,6 @@ GraphicsServer::SetCurrentView(const Ptr& view) this->currentView = view; } - //------------------------------------------------------------------------------ /** */ @@ -543,6 +543,11 @@ GraphicsServer::Render() N_SCOPE(RenderViews, Graphics); IndexT i; + for (auto& cb : this->preViewCallbacks) + { + cb(this->frameContext.frameIndex, this->frameContext.bufferIndex); + } + // Go through views and call before view for (i = 0; i < this->views.Size(); i++) { @@ -555,6 +560,11 @@ GraphicsServer::Render() view->Render(this->frameContext.frameIndex, this->frameContext.time, this->frameContext.bufferIndex); this->currentView = nullptr; } + + for (auto& cb : this->postViewCallbacks) + { + cb(this->frameContext.frameIndex, this->frameContext.bufferIndex); + } } //------------------------------------------------------------------------------ @@ -564,6 +574,41 @@ void GraphicsServer::EndFrame() { N_SCOPE(EndFrame, Graphics); + + n_assert_msg(this->swapInfo.syncFunc != nullptr, "Please provide a valid SwapInfo with 'SetSwapInfo'"); + + CoreGraphics::SwapchainId swapchain = WindowGetSwapchain(CoreGraphics::CurrentWindow); + CoreGraphics::SwapchainSwap(swapchain); + CoreGraphics::QueueType queue = CoreGraphics::SwapchainGetQueueType(swapchain); + + // Allocate command buffer to run swap + CoreGraphics::CmdBufferId cmdBuf = CoreGraphics::SwapchainAllocateCmds(swapchain); + CoreGraphics::CmdBufferBeginInfo beginInfo; + beginInfo.submitDuringPass = false; + beginInfo.resubmittable = false; + beginInfo.submitOnce = true; + CoreGraphics::CmdBeginRecord(cmdBuf, beginInfo); + CoreGraphics::CmdBeginMarker(cmdBuf, NEBULA_MARKER_TURQOISE, "Swap"); + + this->swapInfo.syncFunc(cmdBuf); + CoreGraphics::SwapchainCopy(swapchain, cmdBuf, this->swapInfo.swapSource); + + CoreGraphics::CmdEndMarker(cmdBuf); + CoreGraphics::CmdFinishQueries(cmdBuf); + CoreGraphics::CmdEndRecord(cmdBuf); + + auto submission = CoreGraphics::SubmitCommandBuffer( + cmdBuf + , queue +#if NEBULA_GRAPHICS_DEBUG + , "Swap" +#endif + + ); + CoreGraphics::WaitForSubmission(this->swapInfo.submission, queue); + CoreGraphics::DestroyCmdBuffer(cmdBuf); + + // Finish submuissions CoreGraphics::FinishFrame(this->frameContext.frameIndex); } diff --git a/code/render/graphics/graphicsserver.h b/code/render/graphics/graphicsserver.h index f697856cbe..c2f71cbdd0 100644 --- a/code/render/graphics/graphicsserver.h +++ b/code/render/graphics/graphicsserver.h @@ -15,7 +15,6 @@ #include "framesync/framesynctimer.h" #include "util/stringatom.h" #include "ids/idgenerationpool.h" -#include "coregraphics/batchgroup.h" #include "stage.h" #include "graphicsentity.h" #include "coregraphics/graphicsdevice.h" @@ -23,7 +22,6 @@ #include "coregraphics/shaderserver.h" #include "coregraphics/shaperenderer.h" #include "coregraphics/textrenderer.h" -#include "frame/frameserver.h" #include "debug/debughandler.h" namespace Graphics @@ -68,9 +66,11 @@ class GraphicsServer : public Core::RefCounted bool IsValidGraphicsEntity(const GraphicsEntityId id); /// create a new view with a new framescript - Ptr CreateView(const Util::StringAtom& name, const IO::URI& framescript, const CoreGraphics::WindowId window = CoreGraphics::InvalidWindowId); + Ptr CreateView(const Util::StringAtom& name, void(*)(const Math::rectangle&, IndexT, IndexT), const Math::rectangle& viewport); /// create a new view without a framescript Ptr CreateView(const Util::StringAtom& name); + /// Get view by name + const Ptr& GetView(const Util::StringAtom& name); /// discard view void DiscardView(const Ptr& view); /// get current view @@ -78,6 +78,24 @@ class GraphicsServer : public Core::RefCounted /// set current view (do not use unless you know what you are doing since this is normally handled by the graphicssserver) void SetCurrentView(const Ptr& view); + using PreViewCallback = void(*)(IndexT, IndexT); + using PostViewCallback = void(*)(IndexT, IndexT); + /// Add callback for rendering before the views are processed + void AddPreViewCall(PreViewCallback callback); + /// Add callback for rendering after the views are processed + void AddPostViewCall(PostViewCallback callback); + /// Set a function to be run when resize + void SetResizeCall(void(*)(const SizeT, const SizeT)); + + struct SwapInfo + { + void (*syncFunc)(CoreGraphics::CmdBufferId) = nullptr; + CoreGraphics::TextureId swapSource = CoreGraphics::InvalidTextureId; + CoreGraphics::SubmissionWaitEvent submission; + }; + /// Setup the swap info + void SetSwapInfo(const SwapInfo& info); + /// create a new stage Ptr CreateStage(const Util::StringAtom& name, bool main); /// discard stage @@ -123,7 +141,6 @@ class GraphicsServer : public Core::RefCounted void OnWindowResized(CoreGraphics::WindowId wndId); private: - friend class CoreGraphics::BatchGroup; Ids::IdGenerationPool entityPool; @@ -135,20 +152,27 @@ class GraphicsServer : public Core::RefCounted Util::Array states; Util::Array> stages; + Util::Dictionary> viewsByName; Util::Array> views; - CoreGraphics::BatchGroup batchGroupRegistry; Ptr currentView; + + Util::Array preViewCallbacks; + Util::Array postViewCallbacks; + + void (*resizeCall) (const SizeT, const SizeT); + Ptr displayDevice; bool graphicsDevice; Ptr shaderServer; Ptr shapeRenderer; Ptr textRenderer; - Ptr frameServer; Util::Array preLogicCalls, postLogicCalls; Util::Array preLogicViewCalls, postLogicViewCalls; + SwapInfo swapInfo; + bool isOpen; }; @@ -190,6 +214,15 @@ DeregisterEntity(const GraphicsEntityId id) (CONTEXTS::DeregisterEntity(id), ...); } +//------------------------------------------------------------------------------ +/** +*/ +inline const Ptr& +GraphicsServer::GetView(const Util::StringAtom& name) +{ + return this->viewsByName[name]; +} + //------------------------------------------------------------------------------ /** */ @@ -199,6 +232,42 @@ GraphicsServer::GetCurrentView() const return this->currentView; } +//------------------------------------------------------------------------------ +/** +*/ +inline void +GraphicsServer::AddPreViewCall(PreViewCallback callback) +{ + this->preViewCallbacks.Append(callback); +} + +//------------------------------------------------------------------------------ +/** +*/ +inline void +GraphicsServer::AddPostViewCall(PostViewCallback callback) +{ + this->postViewCallbacks.Append(callback); +} + +//------------------------------------------------------------------------------ +/** +*/ +inline void +GraphicsServer::SetResizeCall(void(*func)(const SizeT windowWidth, const SizeT windowHeight)) +{ + this->resizeCall = func; +} + +//------------------------------------------------------------------------------ +/** +*/ +inline void +GraphicsServer::SetSwapInfo(const SwapInfo& info) +{ + this->swapInfo = info; +} + //------------------------------------------------------------------------------ /** */ diff --git a/code/render/graphics/view.cc b/code/render/graphics/view.cc index cbfe71eac0..adf66d790d 100644 --- a/code/render/graphics/view.cc +++ b/code/render/graphics/view.cc @@ -21,7 +21,7 @@ __ImplementClass(Graphics::View, 'VIEW', Core::RefCounted); /** */ View::View() : - script(nullptr), + func(nullptr), camera(GraphicsEntityId::Invalid()), stage(nullptr), enabled(true) @@ -85,20 +85,12 @@ void View::Render(const IndexT frameIndex, const Timing::Time time, const IndexT bufferIndex) { // run the actual script - if (this->script != nullptr) + if (this->func != nullptr) { N_SCOPE(ViewExecute, Graphics); - this->script->Run(frameIndex, bufferIndex); + this->func(this->viewport, frameIndex, bufferIndex); } } -//------------------------------------------------------------------------------ -/** -*/ -void -View::BuildFrameScript() -{ - this->script->Build(); -} } // namespace Graphics diff --git a/code/render/graphics/view.h b/code/render/graphics/view.h index 7dfda782c8..adbe748d38 100644 --- a/code/render/graphics/view.h +++ b/code/render/graphics/view.h @@ -33,10 +33,12 @@ class View : public Core::RefCounted /// render through view void Render(const IndexT frameIndex, const Timing::Time time, const IndexT bufferIndex); - /// get frame script - const Ptr GetFrameScript() const; - /// Build frame script - void BuildFrameScript(); + /// Set run function + void SetFrameScript(void(*func)(const Math::rectangle& viewport, IndexT frameIndex, IndexT bufferIndex)); + /// Set viewport + void SetViewport(const Math::rectangle& rect); + /// Get viewport + const Math::rectangle& GetViewport(); /// set camera void SetCamera(const GraphicsEntityId& camera); @@ -59,7 +61,8 @@ class View : public Core::RefCounted private: friend class GraphicsServer; - Ptr script; + Math::rectangle viewport; + void (*func)(const Math::rectangle& viewport, IndexT frameIndex, IndexT bufferIndex); GraphicsEntityId camera; Ptr stage; bool enabled; @@ -131,10 +134,28 @@ View::Disable() //------------------------------------------------------------------------------ /** */ -inline const Ptr -View::GetFrameScript() const +inline void +View::SetFrameScript(void(*func)(const Math::rectangle& viewport, IndexT frameIndex, IndexT bufferIndex)) +{ + this->func = func; +} + +//------------------------------------------------------------------------------ +/** +*/ +inline void +View::SetViewport(const Math::rectangle& rect) +{ + this->viewport = rect; +} + +//------------------------------------------------------------------------------ +/** +*/ +inline const +Math::rectangle& View::GetViewport() { - return this->script; + return this->viewport; } } // namespace Graphics diff --git a/code/render/lighting/csmutil.h b/code/render/lighting/csmutil.h index d8c336a40f..9469b27fb5 100644 --- a/code/render/lighting/csmutil.h +++ b/code/render/lighting/csmutil.h @@ -55,9 +55,9 @@ class CSMUtil /// gets the shadow view transform (valid after Compute) const Math::mat4& GetShadowView() const; /// returns raw pointer to array of cascade transforms - const Util::FixedArray GetCascadeProjectionTransforms() const; + const Util::FixedArray& GetCascadeProjectionTransforms() const; /// returns raw pointer to array of cascade distances - const Util::FixedArray GetCascadeDistances() const; + const Util::FixedArray& GetCascadeDistances() const; /// gets cascade debug camera (only valid after Compute, and if the debug flag is set) const Math::mat4& GetCascadeCamera(IndexT index) const; @@ -156,7 +156,7 @@ CSMUtil::GetShadowView() const //------------------------------------------------------------------------------ /** */ -inline const Util::FixedArray +inline const Util::FixedArray& CSMUtil::GetCascadeProjectionTransforms() const { return this->cascadeProjectionTransform; @@ -165,7 +165,7 @@ CSMUtil::GetCascadeProjectionTransforms() const //------------------------------------------------------------------------------ /** */ -inline const Util::FixedArray +inline const Util::FixedArray& CSMUtil::GetCascadeDistances() const { return this->intervalDistances; diff --git a/code/render/lighting/lightcontext.cc b/code/render/lighting/lightcontext.cc index 61794d7119..b507f76174 100644 --- a/code/render/lighting/lightcontext.cc +++ b/code/render/lighting/lightcontext.cc @@ -8,9 +8,6 @@ #include "graphics/view.h" #include "graphics/cameracontext.h" #include "csmutil.h" -#include "frame/framesubgraph.h" -#include "frame/framesubpassbatch.h" -#include "frame/framecode.h" #include "resources/resourceserver.h" #include "visibility/visibilitycontext.h" #include "clustering/clustercontext.h" @@ -30,6 +27,9 @@ #include "system_shaders/combine.h" #include "system_shaders/csmblur.h" +#include "frame/default.h" +#include "frame/shadows.h" + #define CLUSTERED_LIGHTING_DEBUG 0 namespace Lighting @@ -57,14 +57,11 @@ struct CoreGraphics::TextureId terrainShadowMap = CoreGraphics::InvalidTextureId; uint terrainShadowMapSize; uint terrainSize; - CoreGraphics::BatchGroup::Code spotlightsBatchCode; - CoreGraphics::BatchGroup::Code globalLightsBatchCode; + MaterialTemplates::BatchGroup spotlightsBatchCode; + MaterialTemplates::BatchGroup globalLightsBatchCode; CSMUtil csmUtil{ Shared::NUM_CASCADES }; - Memory::ArenaAllocator frameOpAllocator; - - } lightServerState; struct @@ -97,13 +94,6 @@ struct struct { - CoreGraphics::TextureId lightingTexture; - CoreGraphics::TextureId fogTexture; - CoreGraphics::TextureId reflectionTexture; - CoreGraphics::TextureId aoTexture; -#ifdef CLUSTERED_LIGHTING_DEBUG - CoreGraphics::TextureId clusterDebugTexture; -#endif CoreGraphics::TextureId ltcLut0; CoreGraphics::TextureId ltcLut1; @@ -130,7 +120,7 @@ LightContext::~LightContext() /** */ void -LightContext::Create(const Ptr& frameScript) +LightContext::Create() { __CreateContext(); @@ -144,19 +134,11 @@ LightContext::Create(const Ptr& frameScript) #endif Graphics::GraphicsServer::Instance()->RegisterGraphicsContext(&__bundle, &__state); - textureState.fogTexture = frameScript->GetTexture("VolumetricFogBuffer0"); - textureState.reflectionTexture = frameScript->GetTexture("ReflectionBuffer"); - textureState.aoTexture = frameScript->GetTexture("SSAOBuffer"); - textureState.lightingTexture = frameScript->GetTexture("LightBuffer"); -#ifdef CLUSTERED_LIGHTING_DEBUG - textureState.clusterDebugTexture = frameScript->GetTexture("LightDebugBuffer"); -#endif - // create shadow mapping frame script - lightServerState.spotlightsBatchCode = CoreGraphics::BatchGroup::FromName("SpotLightShadow"); - lightServerState.globalLightsBatchCode = CoreGraphics::BatchGroup::FromName("GlobalShadow"); - lightServerState.globalLightShadowMap = frameScript->GetTexture("SunShadowDepth"); - lightServerState.localLightShadows = frameScript->GetTexture("LocalLightShadow"); + lightServerState.spotlightsBatchCode = MaterialTemplates::BatchGroupFromName("SpotLightShadow"); + lightServerState.globalLightsBatchCode = MaterialTemplates::BatchGroupFromName("GlobalShadow"); + lightServerState.globalLightShadowMap = FrameScript_shadows::Texture_SunShadowDepth(); + lightServerState.localLightShadows = FrameScript_shadows::Texture_LocalLightShadow(); if (lightServerState.terrainShadowMap == CoreGraphics::InvalidTextureId) lightServerState.terrainShadowMap = Resources::CreateResource("systex:white.dds", "system"); @@ -208,52 +190,39 @@ LightContext::Create(const Ptr& frameScript) { combineState.resourceTables[i] = ShaderCreateResourceTable(combineState.combineShader, NEBULA_BATCH_GROUP, combineState.resourceTables.Size()); //ResourceTableSetConstantBuffer(combineState.resourceTables[i], { CoreGraphics::GetComputeConstantBuffer(MainThreadConstantBuffer), combineState.combineUniforms, 0, false, false, sizeof(Combine::CombineUniforms), 0 }); - ResourceTableSetRWTexture(combineState.resourceTables[i], { textureState.lightingTexture, Combine::Table_Batch::Lighting_SLOT, 0, CoreGraphics::InvalidSamplerId }); - ResourceTableSetTexture(combineState.resourceTables[i], { textureState.aoTexture, Combine::Table_Batch::AO_SLOT, 0, CoreGraphics::InvalidSamplerId }); - ResourceTableSetTexture(combineState.resourceTables[i], { textureState.fogTexture, Combine::Table_Batch::Fog_SLOT, 0, CoreGraphics::InvalidSamplerId }); - ResourceTableSetTexture(combineState.resourceTables[i], { textureState.reflectionTexture, Combine::Table_Batch::Reflections_SLOT, 0, CoreGraphics::InvalidSamplerId }); + ResourceTableSetRWTexture(combineState.resourceTables[i], { FrameScript_default::Texture_LightBuffer(), Combine::Table_Batch::Lighting_SLOT, 0, CoreGraphics::InvalidSamplerId }); + ResourceTableSetTexture(combineState.resourceTables[i], { FrameScript_default::Texture_SSAOBuffer(), Combine::Table_Batch::AO_SLOT, 0, CoreGraphics::InvalidSamplerId }); + ResourceTableSetTexture(combineState.resourceTables[i], { FrameScript_default::Texture_VolumetricFogBuffer0(), Combine::Table_Batch::Fog_SLOT, 0, CoreGraphics::InvalidSamplerId }); + ResourceTableSetTexture(combineState.resourceTables[i], { FrameScript_default::Texture_ReflectionBuffer(), Combine::Table_Batch::Reflections_SLOT, 0, CoreGraphics::InvalidSamplerId }); ResourceTableCommitChanges(combineState.resourceTables[i]); } // Update main resource table clusterState.resourceTable = ShaderCreateResourceTable(clusterState.classificationShader, NEBULA_BATCH_GROUP); - ResourceTableSetRWTexture(clusterState.resourceTable, { textureState.lightingTexture, LightsCluster::Table_Batch::Lighting_SLOT, 0, CoreGraphics::InvalidSamplerId }); + ResourceTableSetRWTexture(clusterState.resourceTable, { FrameScript_default::Texture_LightBuffer(), LightsCluster::Table_Batch::Lighting_SLOT, 0, CoreGraphics::InvalidSamplerId }); #ifdef CLUSTERED_LIGHTING_DEBUG - ResourceTableSetRWTexture(clusterState.resourceTable, { textureState.clusterDebugTexture, LightsCluster::Table_Batch::DebugOutput_SLOT, 0, CoreGraphics::InvalidSamplerId }); + ResourceTableSetRWTexture(clusterState.resourceTable, { FrameScript_default::Texture_LightDebugBuffer(), LightsCluster::Table_Batch::DebugOutput_SLOT, 0, CoreGraphics::InvalidSamplerId }); #endif ResourceTableCommitChanges(clusterState.resourceTable); // allow 16 shadow casting local lights lightServerState.shadowcastingLocalLights.SetCapacity(16); - // Pass is defined in the frame script, but this is just to take control over the batch rendering - auto spotlightShadowsRender = lightServerState.frameOpAllocator.Alloc(); - spotlightShadowsRender->domain = CoreGraphics::BarrierDomain::Pass; - spotlightShadowsRender->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_shadows::RegisterSubgraph_SpotlightShadows_Pass([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { IndexT i; for (i = 0; i < lightServerState.shadowcastingLocalLights.Size(); i++) { // draw it! Ids::Id32 slice = shadowCasterSliceMap[lightServerState.shadowcastingLocalLights[i]]; - Frame::FrameSubpassBatch::DrawBatch(cmdBuf, lightServerState.spotlightsBatchCode, lightServerState.shadowcastingLocalLights[i], 1, slice, bufferIndex); + Frame::DrawBatch(cmdBuf, lightServerState.spotlightsBatchCode, lightServerState.shadowcastingLocalLights[i], 1, slice, bufferIndex); } - }; - Frame::AddSubgraph("Spotlight Shadows", { spotlightShadowsRender }); - - // Run blur pass for spot lights, which is disabled at the moment - auto spotlightShadowsBlur = lightServerState.frameOpAllocator.Alloc(); - spotlightShadowsBlur->domain = CoreGraphics::BarrierDomain::Pass; - spotlightShadowsBlur->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }); + FrameScript_shadows::RegisterSubgraph_SpotlightBlur_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { - }; - spotlightShadowsBlur->SetEnabled(false); - Frame::AddSubgraph("Spotlight Blur", { spotlightShadowsBlur }); - - // Run sun render pass, going over observers and feeding a cascade per each - auto sunShadowsRender = lightServerState.frameOpAllocator.Alloc(); - sunShadowsRender->domain = CoreGraphics::BarrierDomain::Pass; - sunShadowsRender->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }); + + FrameScript_shadows::RegisterSubgraph_SunShadows_Pass([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { if (lightServerState.globalLightEntity != Graphics::GraphicsEntityId::Invalid()) { @@ -264,99 +233,50 @@ LightContext::Create(const Ptr& frameScript) for (IndexT i = 0; i < observers.Size(); i++) { // draw it! - Frame::FrameSubpassBatch::DrawBatch(cmdBuf, lightServerState.globalLightsBatchCode, observers[i], 1, i, bufferIndex); + Frame::DrawBatch(cmdBuf, lightServerState.globalLightsBatchCode, observers[i], 1, i, bufferIndex); } } - }; - Frame::AddSubgraph("Sun Shadows", { sunShadowsRender }); - - // Copy lights from CPU buffer to GPU buffer - auto lightsCopy = lightServerState.frameOpAllocator.Alloc(); - lightsCopy->domain = CoreGraphics::BarrierDomain::Global; - lightsCopy->queue = CoreGraphics::QueueType::ComputeQueueType; - lightsCopy->bufferDeps.Add(clusterState.clusterLightsList, - { - "ClusterLightsList" - , CoreGraphics::PipelineStage::TransferWrite - , CoreGraphics::BufferSubresourceInfo() - }); - lightsCopy->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }); + + // Bind shadows + FrameScript_default::Bind_ClusterLightList(clusterState.clusterLightsList); + FrameScript_default::Bind_ClusterLightIndexLists(clusterState.clusterLightIndexLists); + FrameScript_default::RegisterSubgraph_LightsCopy_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CoreGraphics::BufferCopy from, to; from.offset = 0; to.offset = 0; CmdCopy(cmdBuf, clusterState.stagingClusterLightsList.buffers[bufferIndex], { from }, clusterState.clusterLightsList, { to }, sizeof(LightsCluster::LightLists)); - }; - - // Classify and cull is dependent on the light index lists and the AABB buffer being ready - auto lightsClassifyAndCull = lightServerState.frameOpAllocator.Alloc(); - lightsClassifyAndCull->domain = CoreGraphics::BarrierDomain::Global; - lightsClassifyAndCull->queue = CoreGraphics::QueueType::ComputeQueueType; - lightsClassifyAndCull->bufferDeps.Add(clusterState.clusterLightIndexLists, - { - "ClusterLightIndexLists" - , CoreGraphics::PipelineStage::ComputeShaderWrite - , CoreGraphics::BufferSubresourceInfo() - }); - lightsClassifyAndCull->bufferDeps.Add(clusterState.clusterLightsList, - { - "ClusterLightsList" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::BufferSubresourceInfo() - }); - lightsClassifyAndCull->bufferDepRefs.Add(Clustering::ClusterContext::GetClusterBuffer(), - { - "Cluster AABB" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::BufferSubresourceInfo() - }); - lightsClassifyAndCull->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }, { + { FrameScript_default::BufferIndex::ClusterLightList, CoreGraphics::PipelineStage::TransferWrite } + }); + + FrameScript_default::RegisterSubgraph_LightsCull_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CmdSetShaderProgram(cmdBuf, clusterState.cullProgram); // run chunks of 1024 threads at a time std::array dimensions = Clustering::ClusterContext::GetClusterDimensions(); CmdDispatch(cmdBuf, Math::ceil((dimensions[0] * dimensions[1] * dimensions[2]) / 64.0f), 1, 1); - }; - Frame::AddSubgraph("Lights Cull", { lightsCopy, lightsClassifyAndCull }); - - // Final pass combines all the lighting buffers together, later in the frame - auto lightsCombine = lightServerState.frameOpAllocator.Alloc(); - lightsCombine->domain = CoreGraphics::BarrierDomain::Global; - lightsCombine->textureDeps.Add(textureState.lightingTexture, - { - "LightBuffer" - , CoreGraphics::PipelineStage::ComputeShaderWrite - , CoreGraphics::TextureSubresourceInfo::Color(textureState.lightingTexture) - }); - lightsCombine->textureDeps.Add(textureState.aoTexture, - { - "SSAOBuffer" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::TextureSubresourceInfo::Color(textureState.aoTexture) - }); - lightsCombine->textureDeps.Add(textureState.fogTexture, - { - "VolumeFogBuffer" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::TextureSubresourceInfo::Color(textureState.fogTexture) - }); - lightsCombine->textureDeps.Add(textureState.reflectionTexture, - { - "ReflectionBuffer" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::TextureSubresourceInfo::Color(textureState.reflectionTexture) - }); - lightsCombine->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }, { + { FrameScript_default::BufferIndex::ClusterLightList, CoreGraphics::PipelineStage::ComputeShaderRead } + , { FrameScript_default::BufferIndex::ClusterLightIndexLists, CoreGraphics::PipelineStage::ComputeShaderWrite } + , { FrameScript_default::BufferIndex::ClusterBuffer, CoreGraphics::PipelineStage::ComputeShaderRead } + }); + + FrameScript_default::RegisterSubgraph_LightsCombine_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CmdSetShaderProgram(cmdBuf, combineState.combineProgram); CmdSetResourceTable(cmdBuf, combineState.resourceTables[bufferIndex], NEBULA_BATCH_GROUP, CoreGraphics::ComputePipeline, nullptr); // perform debug output - CoreGraphics::TextureDimensions dims = TextureGetDimensions(textureState.lightingTexture); - CmdDispatch(cmdBuf, Math::divandroundup(dims.width, 64), dims.height, 1); - }; - Frame::AddSubgraph("Lights Combine", { lightsCombine }); + CmdDispatch(cmdBuf, Math::divandroundup(viewport.width(), 64), viewport.height(), 1); + }, nullptr, { + { FrameScript_default::TextureIndex::LightBuffer, CoreGraphics::PipelineStage::ComputeShaderWrite } + , { FrameScript_default::TextureIndex::SSAOBuffer, CoreGraphics::PipelineStage::ComputeShaderRead } + , { FrameScript_default::TextureIndex::VolumetricFogBuffer0, CoreGraphics::PipelineStage::ComputeShaderRead } + , { FrameScript_default::TextureIndex::ReflectionBuffer, CoreGraphics::PipelineStage::ComputeShaderRead } + }); } //------------------------------------------------------------------------------ @@ -365,7 +285,6 @@ LightContext::Create(const Ptr& frameScript) void LightContext::Discard() { - lightServerState.frameOpAllocator.Release(); Graphics::GraphicsServer::Instance()->UnregisterGraphicsContext(&__bundle); } @@ -580,11 +499,11 @@ LightContext::SetupAreaLight( const MaterialTemplates::MaterialTemplateValue& value = MaterialTemplates::base::__AreaLight.__EmissiveColor; void* mem = Materials::MaterialLoader::AllocateConstantMemory(value.GetSize()); - const Materials::ShaderConfigBatchConstant* batchConstant = &MaterialTemplates::base::__AreaLight.__LightMeshes_EmissiveColor; MaterialInterfaces::ArealightMaterial* data = (MaterialInterfaces::ArealightMaterial*)StackAlloc(matTemplate->bufferSize); (color * intensity).store(data->EmissiveColor); Materials::MaterialSetConstants(material, data, sizeof(MaterialInterfaces::ArealightMaterial)); + StackFree(data); CoreGraphics::MeshId mesh; switch (shape) @@ -928,7 +847,7 @@ LightContext::OnPrepareView(const Ptr& view, const Graphics::Fra Math::mat4 textureScale = Math::scaling(0.5f, 0.5f, 1.0f); #endif Math::mat4 textureTranslation = Math::translation(0.5f, 0.5f, 0); - const Util::FixedArray transforms = lightServerState.csmUtil.GetCascadeProjectionTransforms(); + const Util::FixedArray& transforms = lightServerState.csmUtil.GetCascadeProjectionTransforms(); Math::vec4 cascadeScales[Shared::NUM_CASCADES]; Math::vec4 cascadeOffsets[Shared::NUM_CASCADES]; @@ -1009,15 +928,6 @@ LightContext::SetupTerrainShadows(const CoreGraphics::TextureId terrainShadowMap lightServerState.terrainSize = worldSize; } -//------------------------------------------------------------------------------ -/** -*/ -const CoreGraphics::TextureId -LightContext::GetLightingTexture() -{ - return textureState.lightingTexture; -} - //------------------------------------------------------------------------------ /** */ @@ -1069,6 +979,7 @@ LightContext::UpdateViewDependentResources(const Ptr& view, cons // get camera view const Math::mat4 viewTransform = Graphics::CameraContext::GetView(view->GetCamera()); + const Math::rectangle& viewport = view->GetViewport(); // update constant buffer Ids::Id32 globalLightId = genericLightAllocator.Get(cid.id); @@ -1305,15 +1216,15 @@ LightContext::UpdateViewDependentResources(const Ptr& view, cons consts.NumPointLights = numPointLights; consts.NumAreaLights = numAreaLights; consts.NumLightClusters = Clustering::ClusterContext::GetNumClusters(); - consts.SSAOBuffer = CoreGraphics::TextureGetBindlessHandle(textureState.aoTexture); + consts.SSAOBuffer = CoreGraphics::TextureGetBindlessHandle(FrameScript_default::Texture_SSAOBuffer()); IndexT offset = SetConstants(consts); ResourceTableSetConstantBuffer(frameResourceTable, { GetConstantBuffer(bufferIndex), Shared::Table_Frame::LightUniforms_SLOT, 0, sizeof(Shared::LightUniforms), (SizeT)offset }); ResourceTableCommitChanges(frameResourceTable); - TextureDimensions dims = TextureGetDimensions(textureState.lightingTexture); Combine::CombineUniforms combineConsts; - combineConsts.LowresResolution[0] = 1.0f / dims.width; - combineConsts.LowresResolution[1] = 1.0f / dims.height; + CoreGraphics::TextureDimensions lightDims = CoreGraphics::TextureGetDimensions(FrameScript_default::Texture_LightBuffer()); + combineConsts.LowresResolution[0] = 1.0f / lightDims.width; + combineConsts.LowresResolution[1] = 1.0f / lightDims.height; offset = SetConstants(combineConsts); ResourceTableSetConstantBuffer(combineState.resourceTables[bufferIndex], { GetConstantBuffer(bufferIndex), Combine::Table_Batch::CombineUniforms_SLOT, 0, sizeof(Combine::CombineUniforms), (SizeT)offset }); ResourceTableCommitChanges(combineState.resourceTables[bufferIndex]); @@ -1326,19 +1237,19 @@ void LightContext::WindowResized(const CoreGraphics::WindowId windowId, SizeT width, SizeT height) { // If window has resized, we need to update the resource table - ResourceTableSetRWTexture(clusterState.resourceTable, { textureState.lightingTexture, LightsCluster::Table_Batch::Lighting_SLOT, 0, CoreGraphics::InvalidSamplerId }); + ResourceTableSetRWTexture(clusterState.resourceTable, { FrameScript_default::Texture_LightBuffer(), LightsCluster::Table_Batch::Lighting_SLOT, 0, CoreGraphics::InvalidSamplerId }); #ifdef CLUSTERED_LIGHTING_DEBUG - ResourceTableSetRWTexture(clusterState.resourceTable, { textureState.clusterDebugTexture, LightsCluster::Table_Batch::DebugOutput_SLOT, 0, CoreGraphics::InvalidSamplerId }); + ResourceTableSetRWTexture(clusterState.resourceTable, { FrameScript_default::Texture_LightDebugBuffer(), LightsCluster::Table_Batch::DebugOutput_SLOT, 0, CoreGraphics::InvalidSamplerId }); #endif ResourceTableCommitChanges(clusterState.resourceTable); for (IndexT i = 0; i < combineState.resourceTables.Size(); i++) { - ResourceTableSetRWTexture(combineState.resourceTables[i], { textureState.lightingTexture, Combine::Table_Batch::Lighting_SLOT, 0, CoreGraphics::InvalidSamplerId }); - ResourceTableSetTexture(combineState.resourceTables[i], { textureState.aoTexture, Combine::Table_Batch::AO_SLOT, 0, CoreGraphics::InvalidSamplerId }); - ResourceTableSetTexture(combineState.resourceTables[i], { textureState.fogTexture, Combine::Table_Batch::Fog_SLOT, 0, CoreGraphics::InvalidSamplerId }); - ResourceTableSetTexture(combineState.resourceTables[i], { textureState.reflectionTexture, Combine::Table_Batch::Reflections_SLOT, 0, CoreGraphics::InvalidSamplerId }); + ResourceTableSetRWTexture(combineState.resourceTables[i], { FrameScript_default::Texture_LightBuffer(), Combine::Table_Batch::Lighting_SLOT, 0, CoreGraphics::InvalidSamplerId }); + ResourceTableSetTexture(combineState.resourceTables[i], { FrameScript_default::Texture_SSAOBuffer(), Combine::Table_Batch::AO_SLOT, 0, CoreGraphics::InvalidSamplerId }); + ResourceTableSetTexture(combineState.resourceTables[i], { FrameScript_default::Texture_VolumetricFogBuffer0(), Combine::Table_Batch::Fog_SLOT, 0, CoreGraphics::InvalidSamplerId }); + ResourceTableSetTexture(combineState.resourceTables[i], { FrameScript_default::Texture_ReflectionBuffer(), Combine::Table_Batch::Reflections_SLOT, 0, CoreGraphics::InvalidSamplerId }); ResourceTableCommitChanges(combineState.resourceTables[i]); } } diff --git a/code/render/lighting/lightcontext.h b/code/render/lighting/lightcontext.h index e777e5543d..3b957e25a9 100644 --- a/code/render/lighting/lightcontext.h +++ b/code/render/lighting/lightcontext.h @@ -46,7 +46,7 @@ class LightContext : public Graphics::GraphicsContext virtual ~LightContext(); /// setup light context - static void Create(const Ptr& frameScript); + static void Create(); /// discard light context static void Discard(); @@ -136,8 +136,6 @@ class LightContext : public Graphics::GraphicsContext /// Setup terrain shadows static void SetupTerrainShadows(const CoreGraphics::TextureId terrainShadowMap, const uint worldSize); - /// get lighting texture - static const CoreGraphics::TextureId GetLightingTexture(); /// get light index lists buffer static const CoreGraphics::BufferId GetLightIndexBuffer(); /// get light lists buffer diff --git a/code/render/materials/material.cc b/code/render/materials/material.cc index 87bfd913d9..e8b626104b 100644 --- a/code/render/materials/material.cc +++ b/code/render/materials/material.cc @@ -310,9 +310,9 @@ MaterialGetTemplate(const MaterialId mat) /** */ const Materials::BatchIndex -MaterialGetBatchIndex(const MaterialId mat, const CoreGraphics::BatchGroup::Code code) +MaterialGetBatchIndex(const MaterialId mat, const MaterialTemplates::BatchGroup batch) { - return materialAllocator.Get(mat.id)->passes[code]->index; + return materialAllocator.Get(mat.id)->passes[batch]->index; } //------------------------------------------------------------------------------ diff --git a/code/render/materials/material.h b/code/render/materials/material.h index 80f1a42102..51c7aeb462 100644 --- a/code/render/materials/material.h +++ b/code/render/materials/material.h @@ -12,22 +12,21 @@ #include "ids/id.h" #include "ids/idallocator.h" #include "resources/resourceid.h" -#include "coregraphics/batchgroup.h" #include "coregraphics/texture.h" #include "coregraphics/buffer.h" #include "materialvariant.h" + namespace MaterialTemplates { struct Entry; +enum class BatchGroup; }; namespace Materials { -struct ShaderConfigBatchConstant; struct ShaderConfigBatchTexture; - RESOURCE_ID_TYPE(MaterialId); ID_32_24_8_NAMED_TYPE(MaterialInstanceId, instance, materialId, materialGeneration, material); // 32 bits instance, 24 bits material, 8 bits type @@ -66,7 +65,7 @@ void MaterialApply(const MaterialId id, const CoreGraphics::CmdBufferId buf, Ind /// Get material shader config const MaterialTemplates::Entry* MaterialGetTemplate(const MaterialId mat); /// Get batch index from code -const Materials::BatchIndex MaterialGetBatchIndex(const MaterialId mat, const CoreGraphics::BatchGroup::Code code); +const Materials::BatchIndex MaterialGetBatchIndex(const MaterialId mat, const MaterialTemplates::BatchGroup batch); /// Get sort code uint64_t MaterialGetSortCode(const MaterialId mat); diff --git a/code/render/materials/materialtemplatetypes.h b/code/render/materials/materialtemplatetypes.h index ef73f9ce0d..00382fad60 100644 --- a/code/render/materials/materialtemplatetypes.h +++ b/code/render/materials/materialtemplatetypes.h @@ -11,6 +11,7 @@ namespace MaterialTemplates { +enum class BatchGroup; struct MaterialTemplateValue { enum Type @@ -83,8 +84,8 @@ struct Entry #ifdef WITH_NEBULA_EDITOR Util::Dictionary valuesByHash; Util::Dictionary texturesByHash; -#endif WITH_NEBULA_EDITOR - Util::Dictionary passes; +#endif + Util::Dictionary passes; Util::Array> texturesPerBatch; Util::Array> textureBatchLookup; }; diff --git a/code/render/materials/shaderconfig.h b/code/render/materials/shaderconfig.h index 9e84cc5497..b1f60ad359 100644 --- a/code/render/materials/shaderconfig.h +++ b/code/render/materials/shaderconfig.h @@ -8,7 +8,6 @@ */ //------------------------------------------------------------------------------ #include "util/hashtable.h" -#include "coregraphics/batchgroup.h" #include "coregraphics/shader.h" #include "memory/arenaallocator.h" #include "util/variant.h" @@ -22,43 +21,15 @@ namespace MaterialTemplates { - struct MaterialTemplateValue; struct MaterialTemplateTexture; } namespace Materials { -struct ShaderConfigTexture -{ - Util::String name; - CoreGraphics::TextureId defaultValue; - CoreGraphics::TextureType type; - bool system : 1; -}; - struct ShaderConfigBatchTexture { IndexT slot; const MaterialTemplates::MaterialTemplateTexture* def; }; -struct ShaderConfigConstant -{ - Util::String name; - MaterialVariant def, min, max; - bool system : 1; -}; - -struct ShaderConfigBatchConstant -{ - IndexT offset, slot, group; - const MaterialTemplates::MaterialTemplateValue* def; - - // Returns true if valid - const bool Valid() const - { - return offset != InvalidIndex && slot != InvalidIndex && group != InvalidIndex; - } -}; - } // namespace Materials diff --git a/code/render/models/modelcontext.cc b/code/render/models/modelcontext.cc index e2a8044ce7..f06e68ce7c 100644 --- a/code/render/models/modelcontext.cc +++ b/code/render/models/modelcontext.cc @@ -448,7 +448,7 @@ ModelContext::GetNodeIndex(const Graphics::GraphicsEntityId id, const Util::Stri /** */ ModelContext::MaterialInstanceContext& -ModelContext::SetupMaterialInstanceContext(const Graphics::GraphicsEntityId id, const IndexT nodeIndex, const CoreGraphics::BatchGroup::Code batch) +ModelContext::SetupMaterialInstanceContext(const Graphics::GraphicsEntityId id, const IndexT nodeIndex, const MaterialTemplates::BatchGroup batch) { // This is a bit hacky, but we really need to only do this once per node and batch. // What we do is that we get the batch index from the batch lookup map, and the variable indexes @@ -478,7 +478,7 @@ ModelContext::SetupMaterialInstanceContext(const Graphics::GraphicsEntityId id, /** */ ModelContext::MaterialInstanceContext& -ModelContext::SetupMaterialInstanceContext(const Graphics::GraphicsEntityId id, const CoreGraphics::BatchGroup::Code batch) +ModelContext::SetupMaterialInstanceContext(const Graphics::GraphicsEntityId id, const MaterialTemplates::BatchGroup batch) { return SetupMaterialInstanceContext(id, 0, batch); } diff --git a/code/render/models/modelcontext.h b/code/render/models/modelcontext.h index a9bde21bbb..1e940662ad 100644 --- a/code/render/models/modelcontext.h +++ b/code/render/models/modelcontext.h @@ -101,9 +101,9 @@ class ModelContext : public Graphics::GraphicsContext /// Get node index based on name static IndexT GetNodeIndex(const Graphics::GraphicsEntityId id, const Util::StringAtom& name); /// Setup material instance context - static MaterialInstanceContext& SetupMaterialInstanceContext(const Graphics::GraphicsEntityId id, const IndexT nodeIndex, const CoreGraphics::BatchGroup::Code batch); + static MaterialInstanceContext& SetupMaterialInstanceContext(const Graphics::GraphicsEntityId id, const IndexT nodeIndex, const MaterialTemplates::BatchGroup batch); /// Setup material instance context - static MaterialInstanceContext& SetupMaterialInstanceContext(const Graphics::GraphicsEntityId id, const CoreGraphics::BatchGroup::Code batch); + static MaterialInstanceContext& SetupMaterialInstanceContext(const Graphics::GraphicsEntityId id, const MaterialTemplates::BatchGroup batch); /// Allocate constant memory for instance constants in this frame static CoreGraphics::ConstantBufferOffset AllocateInstanceConstants(const Graphics::GraphicsEntityId id, const IndexT nodeIndex, const Materials::BatchIndex batch); /// Allocate constant memory for instance constants in this frame diff --git a/code/render/models/nodes/shaderstatenode.cc b/code/render/models/nodes/shaderstatenode.cc index 979c43f078..cd81fe1eea 100644 --- a/code/render/models/nodes/shaderstatenode.cc +++ b/code/render/models/nodes/shaderstatenode.cc @@ -124,11 +124,7 @@ ShaderStateNode::DrawPacket::Apply(const CoreGraphics::CmdBufferId cmdBuf, Index // Set per-draw resource tables IndexT prevOffset = 0; - for (IndexT i = 0; i < this->numTables; i++) - { - CoreGraphics::CmdSetResourceTable(cmdBuf, this->tables[i], this->slots[i], CoreGraphics::GraphicsPipeline, this->numOffsets[i], this->offsets[prevOffset]); - prevOffset = this->numOffsets[i]; - } + CoreGraphics::CmdSetResourceTable(cmdBuf, this->table, this->slot, CoreGraphics::GraphicsPipeline, this->numOffsets, this->offsets); } } // namespace Models diff --git a/code/render/models/nodes/shaderstatenode.h b/code/render/models/nodes/shaderstatenode.h index 3e9b5ddfc4..f8973df3af 100644 --- a/code/render/models/nodes/shaderstatenode.h +++ b/code/render/models/nodes/shaderstatenode.h @@ -24,22 +24,19 @@ class ShaderStateNode : public TransformNode virtual ~ShaderStateNode(); struct DrawPacket; - static const uint NumTables = 1; static const uint NumMaxOffsets = 4; // object, instancing, skeleton, particles struct DrawPacket { - Materials::MaterialInstanceId materialInstance; - SizeT numTables; - CoreGraphics::ResourceTableId tables[NumTables]; - uint32 numOffsets[NumTables]; - uint32 offsets[NumTables][NumMaxOffsets]; - IndexT slots[NumTables]; - #ifndef PUBLIC_BUILD - uint32_t nodeInstanceHash; Math::bbox boundingBox; + uint32_t nodeInstanceHash; #endif + Materials::MaterialInstanceId materialInstance; + CoreGraphics::ResourceTableId table; + uint32 offsets[NumMaxOffsets]; + uint8 numOffsets; + uint8 slot; /// Apply the resource table void Apply(const CoreGraphics::CmdBufferId cmdBuf, IndexT batchIndex, IndexT bufferIndex); diff --git a/code/render/posteffects/bloomcontext.cc b/code/render/posteffects/bloomcontext.cc index 0e5fabef8a..de373e8dbc 100644 --- a/code/render/posteffects/bloomcontext.cc +++ b/code/render/posteffects/bloomcontext.cc @@ -10,26 +10,25 @@ #include "bloomcontext.h" #include "system_shaders/bloom.h" + +#include "frame/default.h" namespace PostEffects { __ImplementPluginContext(PostEffects::BloomContext); struct { - CoreGraphics::ShaderProgramId program; + CoreGraphics::ShaderProgramId intermediateProgram; + CoreGraphics::ShaderProgramId mergeProgram; CoreGraphics::ShaderId shader; CoreGraphics::ResourceTableId resourceTable; CoreGraphics::BufferId constants; - CoreGraphics::TextureId bloomBuffer; - CoreGraphics::TextureId lightBuffer; - - Ptr frameScript; - + CoreGraphics::TextureId intermediateBloomTexture; + Util::FixedArray intermediateBloomBufferViews; Util::FixedArray lightBufferViews; - - Memory::ArenaAllocator frameOpAllocator; + uint numMips; } bloomState; @@ -51,19 +50,17 @@ BloomContext::~BloomContext() /** */ void -BloomContext::Setup(const Ptr& script) +BloomContext::Setup() { using namespace CoreGraphics; // setup shaders - bloomState.frameScript = script; bloomState.shader = ShaderGet("shd:system_shaders/bloom.fxb"); - bloomState.program = ShaderGetProgram(bloomState.shader, ShaderFeatureMask("Bloom")); + bloomState.intermediateProgram = ShaderGetProgram(bloomState.shader, ShaderFeatureMask("Intermediate")); + bloomState.mergeProgram = ShaderGetProgram(bloomState.shader, ShaderFeatureMask("Merge")); bloomState.resourceTable = ShaderCreateResourceTable(bloomState.shader, NEBULA_BATCH_GROUP); - bloomState.bloomBuffer = bloomState.frameScript->GetTexture("BloomBuffer"); - bloomState.lightBuffer = bloomState.frameScript->GetTexture("LightBuffer"); - TextureDimensions dims = TextureGetDimensions(bloomState.bloomBuffer); + TextureDimensions dims = TextureGetDimensions(FrameScript_default::Texture_BloomBuffer()); BufferCreateInfo bufInfo; bufInfo.byteSize = sizeof(Bloom::BloomUniforms); @@ -72,18 +69,37 @@ BloomContext::Setup(const Ptr& script) bufInfo.queueSupport = ComputeQueueSupport; bloomState.constants = CreateBuffer(bufInfo); - uint mips = TextureGetNumMips(bloomState.lightBuffer); + uint mips = TextureGetNumMips(FrameScript_default::Texture_LightBuffer()); bloomState.lightBufferViews.Resize(mips); for (IndexT i = 0; i < mips; i++) { TextureViewCreateInfo inf; - inf.format = TextureGetPixelFormat(bloomState.lightBuffer); + inf.format = TextureGetPixelFormat(FrameScript_default::Texture_LightBuffer()); inf.startMip = i; inf.numMips = 1; - inf.tex = bloomState.lightBuffer; + inf.tex = FrameScript_default::Texture_LightBuffer(); bloomState.lightBufferViews[i] = CreateTextureView(inf); } + CoreGraphics::TextureCreateInfo intermediateTextureInfo; + intermediateTextureInfo.format = TextureGetPixelFormat(FrameScript_default::Texture_LightBuffer()); + intermediateTextureInfo.width = dims.width; + intermediateTextureInfo.height = dims.height; + intermediateTextureInfo.usage = CoreGraphics::TextureUsage::ReadWriteTexture; + intermediateTextureInfo.mips = CoreGraphics::TextureAutoMips; + bloomState.intermediateBloomTexture = CoreGraphics::CreateTexture(intermediateTextureInfo); + bloomState.intermediateBloomBufferViews.Resize(mips); + for (IndexT i = 0; i < mips; i++) + { + TextureViewCreateInfo inf; + inf.format = intermediateTextureInfo.format; + inf.startMip = i; + inf.numMips = 1; + inf.tex = bloomState.intermediateBloomTexture; + bloomState.intermediateBloomBufferViews[i] = CreateTextureView(inf); + } + bloomState.numMips = mips; + Bloom::BloomUniforms uniforms; uniforms.Mips = mips; for (IndexT i = 0; i < mips; i++) @@ -95,39 +111,40 @@ BloomContext::Setup(const Ptr& script) } BufferUpdate(bloomState.constants, uniforms); - ResourceTableSetTexture(bloomState.resourceTable, { bloomState.lightBuffer, Bloom::Table_Batch::Input_SLOT }); - ResourceTableSetRWTexture(bloomState.resourceTable, { bloomState.bloomBuffer, Bloom::Table_Batch::BloomOutput_SLOT }); + ResourceTableSetTexture(bloomState.resourceTable, { FrameScript_default::Texture_LightBuffer(), Bloom::Table_Batch::Input_SLOT }); + ResourceTableSetRWTexture(bloomState.resourceTable, { FrameScript_default::Texture_BloomBuffer(), Bloom::Table_Batch::BloomOutput_SLOT }); + for (IndexT i = 0; i < mips; i++) + { + ResourceTableSetRWTexture(bloomState.resourceTable, { bloomState.intermediateBloomBufferViews[i], Bloom::Table_Batch::BloomIntermediate_SLOT, i }); + } + ResourceTableSetTexture(bloomState.resourceTable, { bloomState.intermediateBloomTexture, Bloom::Table_Batch::Intermediate_SLOT }); + ResourceTableSetConstantBuffer(bloomState.resourceTable, { bloomState.constants, Bloom::Table_Batch::BloomUniforms_SLOT }); ResourceTableCommitChanges(bloomState.resourceTable); - Frame::FrameCode* upscale = bloomState.frameOpAllocator.Alloc(); - upscale->SetName("Bloom"); - upscale->domain = BarrierDomain::Global; - upscale->textureDeps.Add( - bloomState.lightBuffer, - { - "LightBuffer" - , PipelineStage::ComputeShaderRead - , TextureSubresourceInfo::Color(bloomState.lightBuffer) - }); - upscale->textureDeps.Add( - bloomState.bloomBuffer, - { - "BloomBuffer" - , PipelineStage::ComputeShaderWrite - , TextureSubresourceInfo::Color(bloomState.bloomBuffer) - }); - upscale->func = [](const CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_BloomIntermediate_Compute([](const CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) + { + CmdSetShaderProgram(cmdBuf, bloomState.intermediateProgram); + CmdSetResourceTable(cmdBuf, bloomState.resourceTable, NEBULA_BATCH_GROUP, ComputePipeline, nullptr); + uint dispatchX = Math::divandroundup(viewport.width(), 14); + uint dispatchY = Math::divandroundup(viewport.height(), 14); + CmdDispatch(cmdBuf, dispatchX, dispatchY, bloomState.numMips); + }, nullptr, { + { FrameScript_default::TextureIndex::LightBuffer, PipelineStage::ComputeShaderRead } + , { FrameScript_default::TextureIndex::BloomIntermediate, PipelineStage::ComputeShaderWrite } + }); + + FrameScript_default::RegisterSubgraph_BloomMerge_Compute([](const CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { - TextureDimensions dims = TextureGetDimensions(bloomState.bloomBuffer); - CmdSetShaderProgram(cmdBuf, bloomState.program); + CmdSetShaderProgram(cmdBuf, bloomState.mergeProgram); CmdSetResourceTable(cmdBuf, bloomState.resourceTable, NEBULA_BATCH_GROUP, ComputePipeline, nullptr); - uint dispatchX = Math::divandroundup(dims.width, 6); - uint dispatchY = Math::divandroundup(dims.height, 6); + uint dispatchX = Math::divandroundup(viewport.width(), 256); + uint dispatchY = viewport.height(); CmdDispatch(cmdBuf, dispatchX, dispatchY, 1); - }; - - Frame::AddSubgraph("Bloom", { upscale }); + }, nullptr, { + { FrameScript_default::TextureIndex::BloomIntermediate, PipelineStage::ComputeShaderRead } + , { FrameScript_default::TextureIndex::BloomBuffer, PipelineStage::ComputeShaderWrite } + }); } //------------------------------------------------------------------------------ @@ -137,7 +154,7 @@ void BloomContext::WindowResized(const CoreGraphics::WindowId windowId, SizeT width, SizeT height) { using namespace CoreGraphics; - TextureDimensions dims = TextureGetDimensions(bloomState.bloomBuffer); + TextureDimensions dims = TextureGetDimensions(FrameScript_default::Texture_BloomBuffer()); for (auto& view : bloomState.lightBufferViews) { @@ -145,19 +162,44 @@ BloomContext::WindowResized(const CoreGraphics::WindowId windowId, SizeT width, } bloomState.lightBufferViews.Clear(); - uint mips = TextureGetNumMips(bloomState.lightBuffer); + for (auto& view : bloomState.intermediateBloomBufferViews) + { + DestroyTextureView(view); + } + bloomState.intermediateBloomBufferViews.Clear(); + DestroyTexture(bloomState.intermediateBloomTexture); + + uint mips = TextureGetNumMips(FrameScript_default::Texture_LightBuffer()); bloomState.lightBufferViews.Resize(mips); for (IndexT i = 0; i < mips; i++) { TextureViewCreateInfo inf; - inf.format = TextureGetPixelFormat(bloomState.lightBuffer); + inf.format = TextureGetPixelFormat(FrameScript_default::Texture_LightBuffer()); inf.startMip = i; inf.numMips = 1; - inf.tex = bloomState.lightBuffer; + inf.tex = FrameScript_default::Texture_LightBuffer(); bloomState.lightBufferViews[i] = CreateTextureView(inf); } + CoreGraphics::TextureCreateInfo intermediateTextureInfo; + intermediateTextureInfo.format = TextureGetPixelFormat(FrameScript_default::Texture_LightBuffer()); + intermediateTextureInfo.width = dims.width; + intermediateTextureInfo.height = dims.height; + intermediateTextureInfo.usage = CoreGraphics::TextureUsage::ReadWriteTexture; + intermediateTextureInfo.mips = CoreGraphics::TextureAutoMips; + bloomState.intermediateBloomTexture = CoreGraphics::CreateTexture(intermediateTextureInfo); + bloomState.intermediateBloomBufferViews.Resize(mips); + for (IndexT i = 0; i < mips; i++) + { + TextureViewCreateInfo inf; + inf.format = intermediateTextureInfo.format; + inf.startMip = i; + inf.numMips = 1; + inf.tex = bloomState.intermediateBloomTexture; + bloomState.intermediateBloomBufferViews[i] = CreateTextureView(inf); + } + Bloom::BloomUniforms uniforms; uniforms.Mips = mips; for (IndexT i = 0; i < mips; i++) @@ -169,8 +211,13 @@ BloomContext::WindowResized(const CoreGraphics::WindowId windowId, SizeT width, } BufferUpdate(bloomState.constants, uniforms); - ResourceTableSetTexture(bloomState.resourceTable, { bloomState.lightBuffer, Bloom::Table_Batch::Input_SLOT }); - ResourceTableSetRWTexture(bloomState.resourceTable, { bloomState.bloomBuffer, Bloom::Table_Batch::BloomOutput_SLOT }); + ResourceTableSetTexture(bloomState.resourceTable, { FrameScript_default::Texture_LightBuffer(), Bloom::Table_Batch::Input_SLOT }); + ResourceTableSetRWTexture(bloomState.resourceTable, { FrameScript_default::Texture_BloomBuffer(), Bloom::Table_Batch::BloomOutput_SLOT }); + for (IndexT i = 0; i < mips; i++) + { + ResourceTableSetRWTexture(bloomState.resourceTable, { bloomState.intermediateBloomBufferViews[i], Bloom::Table_Batch::BloomIntermediate_SLOT, i }); + } + ResourceTableSetTexture(bloomState.resourceTable, { bloomState.intermediateBloomTexture, Bloom::Table_Batch::Intermediate_SLOT }); ResourceTableSetConstantBuffer(bloomState.resourceTable, { bloomState.constants, Bloom::Table_Batch::BloomUniforms_SLOT }); ResourceTableCommitChanges(bloomState.resourceTable); } @@ -194,8 +241,6 @@ BloomContext::Create() void BloomContext::Discard() { - bloomState.frameOpAllocator.Release(); - DestroyResourceTable(bloomState.resourceTable); } diff --git a/code/render/posteffects/bloomcontext.h b/code/render/posteffects/bloomcontext.h index 9f17c10162..a0d330efc7 100644 --- a/code/render/posteffects/bloomcontext.h +++ b/code/render/posteffects/bloomcontext.h @@ -26,7 +26,7 @@ class BloomContext : public Graphics::GraphicsContext static void Discard(); /// setup bloom context - static void Setup(const Ptr& script); + static void Setup(); /// Handle window resize static void WindowResized(const CoreGraphics::WindowId windowId, SizeT width, SizeT height); diff --git a/code/render/posteffects/downsamplingcontext.cc b/code/render/posteffects/downsamplingcontext.cc index c7b0b349b5..2bdf348ff9 100644 --- a/code/render/posteffects/downsamplingcontext.cc +++ b/code/render/posteffects/downsamplingcontext.cc @@ -8,6 +8,9 @@ #include "system_shaders/downsample/downsample_cs_light.h" #include "system_shaders/downsample/downsample_cs_depth.h" #include "system_shaders/downsample/depth_extract_cs.h" + +#include "frame/default.h" + namespace PostEffects { @@ -35,12 +38,6 @@ struct CoreGraphics::BufferId depthBufferCounter; CoreGraphics::BufferId depthBufferConstants; - CoreGraphics::TextureId lightBuffer, depthBuffer, zbuffer; - - Ptr frameScript; - - Memory::ArenaAllocator frameOpAllocator; - } state; //------------------------------------------------------------------------------ @@ -148,11 +145,10 @@ SetupMipChainResources( /** */ void -DownsamplingContext::Setup(const Ptr& script) +DownsamplingContext::Setup() { using namespace CoreGraphics; - state.frameScript = script; state.downsampleColorShader = ShaderGet("shd:system_shaders/downsample/downsample_cs_light.fxb"); state.downsampleColorProgram = ShaderGetProgram(state.downsampleColorShader, ShaderFeatureMask("Downsample")); state.downsampleDepthShader = ShaderGet("shd:system_shaders/downsample/downsample_cs_depth.fxb"); @@ -165,10 +161,7 @@ DownsamplingContext::Setup(const Ptr& script) state.depthDownsampleResourceTable = ShaderCreateResourceTable(state.downsampleDepthShader, NEBULA_BATCH_GROUP); state.extractResourceTable = ShaderCreateResourceTable(state.extractShader, NEBULA_BATCH_GROUP); - state.lightBuffer = state.frameScript->GetTexture("LightBuffer"); - state.depthBuffer = state.frameScript->GetTexture("Depth"); - state.zbuffer = state.frameScript->GetTexture("ZBuffer"); - + CoreGraphics::BufferCreateInfo bufInfo; bufInfo.elementSize = sizeof(uint); bufInfo.size = 6; @@ -189,8 +182,8 @@ DownsamplingContext::Setup(const Ptr& script) state.colorBufferConstants = CoreGraphics::CreateBuffer(bufInfo); state.depthBufferConstants = CoreGraphics::CreateBuffer(bufInfo); - auto dims = TextureGetDimensions(state.lightBuffer); - auto mips = TextureGetNumMips(state.lightBuffer); + auto dims = TextureGetDimensions(FrameScript_default::Texture_LightBuffer()); + auto mips = TextureGetNumMips(FrameScript_default::Texture_LightBuffer()); uint dispatchX = DispatchSize(dims.width); uint dispatchY = DispatchSize(dims.height); @@ -201,8 +194,8 @@ DownsamplingContext::Setup(const Ptr& script) constants.Dimensions[1] = dims.height - 1; BufferUpdate(state.colorBufferConstants, constants, 0); - dims = TextureGetDimensions(state.depthBuffer); - mips = TextureGetNumMips(state.depthBuffer); + dims = TextureGetDimensions(FrameScript_default::Texture_Depth()); + mips = TextureGetNumMips(FrameScript_default::Texture_Depth()); dispatchX = DispatchSize(dims.width); dispatchY = DispatchSize(dims.height); @@ -233,7 +226,7 @@ DownsamplingContext::Setup(const Ptr& script) }); CoreGraphics::ResourceTableSetTexture(state.extractResourceTable, { - state.zbuffer, + FrameScript_default::Texture_ZBuffer(), DepthExtractCs::Table_Batch::ZBufferInput_SLOT, 0, CoreGraphics::InvalidSamplerId, @@ -242,85 +235,47 @@ DownsamplingContext::Setup(const Ptr& script) }); CoreGraphics::ResourceTableSetRWTexture(state.extractResourceTable, { - state.depthBuffer, + FrameScript_default::Texture_Depth(), DepthExtractCs::Table_Batch::DepthOutput_SLOT }); CoreGraphics::ResourceTableCommitChanges(state.extractResourceTable); - Frame::FrameCode* colorDownsamplePass = state.frameOpAllocator.Alloc(); - colorDownsamplePass->SetName("Color Downsample"); - colorDownsamplePass->domain = BarrierDomain::Global; - colorDownsamplePass->textureDeps.Add(state.lightBuffer, - { - "LightBuffer" - , PipelineStage::ComputeShaderWrite - , TextureSubresourceInfo::Color(state.lightBuffer) - }); - - colorDownsamplePass->func = [](const CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_DepthExtract_Compute([](const CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) + { + CmdSetShaderProgram(cmdBuf, state.extractProgram, false); + CmdSetResourceTable(cmdBuf, state.extractResourceTable, NEBULA_BATCH_GROUP, ComputePipeline, nullptr); + uint dispatchX = Math::divandroundup(viewport.width(), 64); + CmdDispatch(cmdBuf, dispatchX, viewport.height(), 1); + }, nullptr, { + { FrameScript_default::TextureIndex::Depth, PipelineStage::ComputeShaderWrite } + , { FrameScript_default::TextureIndex::ZBuffer, PipelineStage::ComputeShaderRead } + }); + + FrameScript_default::RegisterSubgraph_ColorDownsample_Compute([](const CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { - TextureDimensions dims = TextureGetDimensions(state.lightBuffer); CmdSetShaderProgram(cmdBuf, state.downsampleColorProgram, false); CmdSetResourceTable(cmdBuf, state.colorDownsampleResourceTable, NEBULA_BATCH_GROUP, ComputePipeline, nullptr); - uint dispatchX = Math::divandroundup(dims.width, 64); - uint dispatchY = Math::divandroundup(dims.height, 64); + uint dispatchX = Math::divandroundup(viewport.width(), 64); + uint dispatchY = Math::divandroundup(viewport.height(), 64); CmdDispatch(cmdBuf, dispatchX, dispatchY, 1); - }; - - Frame::AddSubgraph("Color Downsample", { colorDownsamplePass }); - - Frame::FrameCode* depthDownsamplePass = state.frameOpAllocator.Alloc(); - depthDownsamplePass->SetName("Depth Downsample"); - depthDownsamplePass->domain = BarrierDomain::Global; - depthDownsamplePass->textureDeps.Add(state.depthBuffer, - { - "DepthBuffer" - , PipelineStage::ComputeShaderWrite - , TextureSubresourceInfo::Color(state.depthBuffer) - }); + }, nullptr, { + { FrameScript_default::TextureIndex::LightBuffer, PipelineStage::ComputeShaderWrite } + }); - depthDownsamplePass->func = [](const CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_DepthDownsample_Compute([](const CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { - TextureDimensions dims = TextureGetDimensions(state.depthBuffer); CmdSetShaderProgram(cmdBuf, state.downsampleDepthProgram, false); CmdSetResourceTable(cmdBuf, state.depthDownsampleResourceTable, NEBULA_BATCH_GROUP, ComputePipeline, nullptr); - uint dispatchX = DispatchSize(dims.width); - uint dispatchY = DispatchSize(dims.height); + uint dispatchX = DispatchSize(viewport.width()); + uint dispatchY = DispatchSize(viewport.height()); CmdDispatch(cmdBuf, dispatchX, dispatchY, 1); - }; - - Frame::AddSubgraph("Depth Downsample", { depthDownsamplePass }); - - Frame::FrameCode* extractPass = state.frameOpAllocator.Alloc(); - extractPass->SetName("Depth Extract"); - extractPass->domain = BarrierDomain::Global; - extractPass->textureDeps.Add(state.depthBuffer, - { - "DepthBuffer" - , PipelineStage::ComputeShaderWrite - , TextureSubresourceInfo::Color(state.depthBuffer) - }); - - extractPass->textureDeps.Add(state.zbuffer, - { - "ZBuffer" - , PipelineStage::ComputeShaderRead - , TextureSubresourceInfo::DepthStencil(state.zbuffer) - }); - extractPass->func = [](const CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) - { - TextureDimensions dims = TextureGetDimensions(state.depthBuffer); - CmdSetShaderProgram(cmdBuf, state.extractProgram, false); - CmdSetResourceTable(cmdBuf, state.extractResourceTable, NEBULA_BATCH_GROUP, ComputePipeline, nullptr); - uint dispatchX = Math::divandroundup(dims.width, 64); - CmdDispatch(cmdBuf, dispatchX, dims.height, 1); - }; - - Frame::AddSubgraph("Depth Extract", { extractPass }); + }, nullptr, { + { FrameScript_default::TextureIndex::Depth, PipelineStage::ComputeShaderWrite } + }); // Setup mip chains in resource tables - SetupMipChainResources(state.lightBuffer, state.downsampledColorBufferViews, state.colorDownsampleResourceTable, "Color Downsample", false, DownsampleCsLight::Table_Batch::Input_SLOT, DownsampleCsLight::Table_Batch::Output_SLOT); - SetupMipChainResources(state.depthBuffer, state.downsampledDepthBufferViews, state.depthDownsampleResourceTable, "Depth Downsample", false, DownsampleCsDepth::Table_Batch::Input_SLOT, DownsampleCsDepth::Table_Batch::Output_SLOT); + SetupMipChainResources(FrameScript_default::Texture_LightBuffer(), state.downsampledColorBufferViews, state.colorDownsampleResourceTable, "Color Downsample", false, DownsampleCsLight::Table_Batch::Input_SLOT, DownsampleCsLight::Table_Batch::Output_SLOT); + SetupMipChainResources(FrameScript_default::Texture_Depth(), state.downsampledDepthBufferViews, state.depthDownsampleResourceTable, "Depth Downsample", false, DownsampleCsDepth::Table_Batch::Input_SLOT, DownsampleCsDepth::Table_Batch::Output_SLOT); } //------------------------------------------------------------------------------ @@ -340,11 +295,11 @@ DownsamplingContext::WindowResized(const CoreGraphics::WindowId windowId, SizeT } // Setup new views - SetupMipChainResources(state.lightBuffer, state.downsampledColorBufferViews, state.colorDownsampleResourceTable, "Color Downsample", false, DownsampleCsLight::Table_Batch::Input_SLOT, DownsampleCsLight::Table_Batch::Output_SLOT); - SetupMipChainResources(state.depthBuffer, state.downsampledDepthBufferViews, state.depthDownsampleResourceTable, "Depth Downsample", true, DownsampleCsDepth::Table_Batch::Input_SLOT, DownsampleCsDepth::Table_Batch::Output_SLOT); + SetupMipChainResources(FrameScript_default::Texture_LightBuffer(), state.downsampledColorBufferViews, state.colorDownsampleResourceTable, "Color Downsample", false, DownsampleCsLight::Table_Batch::Input_SLOT, DownsampleCsLight::Table_Batch::Output_SLOT); + SetupMipChainResources(FrameScript_default::Texture_Depth(), state.downsampledDepthBufferViews, state.depthDownsampleResourceTable, "Depth Downsample", false, DownsampleCsDepth::Table_Batch::Input_SLOT, DownsampleCsDepth::Table_Batch::Output_SLOT); - auto dims = TextureGetDimensions(state.lightBuffer); - auto mips = TextureGetNumMips(state.lightBuffer); + auto dims = TextureGetDimensions(FrameScript_default::Texture_LightBuffer()); + auto mips = TextureGetNumMips(FrameScript_default::Texture_LightBuffer()); uint dispatchX = DispatchSize(dims.width); uint dispatchY = DispatchSize(dims.height); @@ -355,8 +310,8 @@ DownsamplingContext::WindowResized(const CoreGraphics::WindowId windowId, SizeT constants.Dimensions[1] = dims.height - 1; BufferUpdate(state.colorBufferConstants, constants, 0); - dims = TextureGetDimensions(state.depthBuffer); - mips = TextureGetNumMips(state.depthBuffer); + dims = TextureGetDimensions(FrameScript_default::Texture_Depth()); + mips = TextureGetNumMips(FrameScript_default::Texture_Depth()); dispatchX = DispatchSize(dims.width); dispatchY = DispatchSize(dims.height); @@ -367,7 +322,7 @@ DownsamplingContext::WindowResized(const CoreGraphics::WindowId windowId, SizeT BufferUpdate(state.depthBufferConstants, constants, 0); CoreGraphics::ResourceTableSetTexture(state.extractResourceTable, { - state.zbuffer, + FrameScript_default::Texture_ZBuffer(), DepthExtractCs::Table_Batch::ZBufferInput_SLOT, 0, CoreGraphics::InvalidSamplerId, @@ -376,7 +331,7 @@ DownsamplingContext::WindowResized(const CoreGraphics::WindowId windowId, SizeT }); CoreGraphics::ResourceTableSetRWTexture(state.extractResourceTable, { - state.depthBuffer, + FrameScript_default::Texture_Depth(), DepthExtractCs::Table_Batch::DepthOutput_SLOT }); CoreGraphics::ResourceTableCommitChanges(state.extractResourceTable); diff --git a/code/render/posteffects/downsamplingcontext.h b/code/render/posteffects/downsamplingcontext.h index 4c6f72d682..ee29c30b2d 100644 --- a/code/render/posteffects/downsamplingcontext.h +++ b/code/render/posteffects/downsamplingcontext.h @@ -26,7 +26,7 @@ class DownsamplingContext : public Graphics::GraphicsContext static void Discard(); /// setup bloom context - static void Setup(const Ptr& script); + static void Setup(); /// Handle window resize static void WindowResized(const CoreGraphics::WindowId windowId, SizeT width, SizeT height); diff --git a/code/render/posteffects/histogramcontext.cc b/code/render/posteffects/histogramcontext.cc index c12cee4adf..b9692d2028 100644 --- a/code/render/posteffects/histogramcontext.cc +++ b/code/render/posteffects/histogramcontext.cc @@ -15,6 +15,8 @@ #include "system_shaders/shared.h" #include "core/cvar.h" +#include "frame/default.h" + namespace PostEffects { @@ -29,14 +31,8 @@ struct CoreGraphics::ResourceTableId histogramResourceTable; CoreGraphics::BufferSet histogramReadbackBuffers; - Ptr frameScript; - CoreGraphics::TextureDimensions sourceTextureDimensions; - CoreGraphics::TextureId sourceTexture; - IndexT sourceTextureBinding; Util::FixedArray downsampledColorBufferViews; - Memory::ArenaAllocator frameOpAllocator; - Math::float2 offset, size; int mip; @@ -130,7 +126,6 @@ HistogramContext::Create() void HistogramContext::Discard() { - histogramState.frameOpAllocator.Release(); } //------------------------------------------------------------------------------ @@ -139,8 +134,10 @@ HistogramContext::Discard() void HistogramContext::SetWindow(const Math::float2 offset, Math::float2 size, int mip) { - SizeT mippedWidth = histogramState.sourceTextureDimensions.width >> mip; - SizeT mippedHeight = histogramState.sourceTextureDimensions.height >> mip; + CoreGraphics::TextureId source = FrameScript_default::Texture_LightBuffer(); + auto dims = CoreGraphics::TextureGetDimensions(source); + SizeT mippedWidth = dims.width >> mip; + SizeT mippedHeight = dims.height >> mip; histogramState.offset = { mippedWidth * offset.x, mippedHeight * offset.y }; histogramState.size = { mippedWidth * size.x, mippedHeight * size.y }; histogramState.mip = mip; @@ -152,17 +149,14 @@ HistogramContext::SetWindow(const Math::float2 offset, Math::float2 size, int mi /** */ void -HistogramContext::Setup(const Ptr& script) +HistogramContext::Setup() { - histogramState.frameScript = script; - histogramState.sourceTexture = histogramState.frameScript->GetTexture("LightBuffer"); - auto dims = CoreGraphics::TextureGetDimensions(histogramState.sourceTexture); - histogramState.sourceTextureBinding = HistogramCs::Table_Batch::ColorSource_SLOT; - histogramState.sourceTextureDimensions = dims; + CoreGraphics::TextureId source = FrameScript_default::Texture_LightBuffer(); + auto dims = CoreGraphics::TextureGetDimensions(source); CoreGraphics::ResourceTableSetTexture(histogramState.histogramResourceTable, { - histogramState.sourceTexture, - histogramState.sourceTextureBinding, + source, + HistogramCs::Table_Batch::ColorSource_SLOT, 0, CoreGraphics::InvalidSamplerId, false, @@ -178,45 +172,32 @@ HistogramContext::Setup(const Ptr& script) histogramState.size.x = 1.0f; histogramState.size.y = 1.0f; - Frame::FrameCode* bucket = histogramState.frameOpAllocator.Alloc(); - bucket->SetName("Histogram Bucket"); - bucket->bufferDeps.Add(histogramState.histogramCounters, - { - "Histogram Downsample" - , CoreGraphics::PipelineStage::ComputeShaderWrite - , CoreGraphics::BufferSubresourceInfo() - }); - bucket->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::Bind_HistogramCounters(histogramState.histogramCounters); + FrameScript_default::RegisterSubgraph_HistogramBin_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CoreGraphics::CmdSetShaderProgram(cmdBuf, histogramState.histogramCategorizeProgram, false); CoreGraphics::CmdSetResourceTable(cmdBuf, histogramState.histogramResourceTable, NEBULA_BATCH_GROUP, CoreGraphics::ComputePipeline, nullptr); int groupsX = (histogramState.size.x - histogramState.offset.x) / 256; int groupsY = (histogramState.size.y - histogramState.offset.y); CoreGraphics::CmdDispatch(cmdBuf, groupsX, groupsY, 1); - }; - - Frame::FrameCode* copy = histogramState.frameOpAllocator.Alloc(); - copy->SetName("Histogram Copy To Readback"); - copy->bufferDeps.Add(histogramState.histogramCounters, - { - "Histogram Downsample" - , CoreGraphics::PipelineStage::TransferRead - , CoreGraphics::BufferSubresourceInfo() - }); - copy->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }, { + { FrameScript_default::BufferIndex::HistogramCounters, CoreGraphics::PipelineStage::ComputeShaderWrite } + }); + + FrameScript_default::RegisterSubgraph_HistogramCopy_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CoreGraphics::BarrierPush( - cmdBuf, - CoreGraphics::PipelineStage::HostRead, - CoreGraphics::PipelineStage::TransferWrite, - CoreGraphics::BarrierDomain::Global, - { - CoreGraphics::BufferBarrierInfo + cmdBuf, + CoreGraphics::PipelineStage::HostRead, + CoreGraphics::PipelineStage::TransferWrite, + CoreGraphics::BarrierDomain::Global, { + CoreGraphics::BufferBarrierInfo + { histogramState.histogramReadbackBuffers.buffers[bufferIndex], CoreGraphics::BufferSubresourceInfo() - }, - }); + }, + }); CoreGraphics::BufferCopy from, to; from.offset = 0; @@ -227,25 +208,18 @@ HistogramContext::Setup(const Ptr& script) histogramState.histogramReadbackBuffers.buffers[bufferIndex], { to }, CoreGraphics::BufferGetByteSize(histogramState.histogramCounters)); CoreGraphics::BarrierPop(cmdBuf); - }; - - Frame::FrameCode* clear = histogramState.frameOpAllocator.Alloc(); - clear->SetName("Histogram Clear"); - clear->bufferDeps.Add(histogramState.histogramCounters, - { - "Histogram Clear" - , CoreGraphics::PipelineStage::TransferWrite - , CoreGraphics::BufferSubresourceInfo() - }); - clear->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }, { + { FrameScript_default::BufferIndex::HistogramCounters, CoreGraphics::PipelineStage::TransferRead } + }); + + FrameScript_default::RegisterSubgraph_HistogramClear_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { // Clear histogram counters uint initDatas[255] = { 0 }; CoreGraphics::BufferUpload(cmdBuf, histogramState.histogramCounters, initDatas, 255, 0); - }; - - // Add subgraph - Frame::AddSubgraph("Histogram", { bucket, copy, clear }); + }, { + { FrameScript_default::BufferIndex::HistogramCounters, CoreGraphics::PipelineStage::TransferWrite } + }); } //------------------------------------------------------------------------------ @@ -314,12 +288,11 @@ HistogramContext::UpdateConstants() void HistogramContext::WindowResized(const CoreGraphics::WindowId windowId, SizeT width, SizeT height) { - histogramState.sourceTextureDimensions = CoreGraphics::TextureGetDimensions(histogramState.sourceTexture); - + CoreGraphics::TextureId source = FrameScript_default::Texture_LightBuffer(); CoreGraphics::ResourceTableSetTexture(histogramState.histogramResourceTable, { - histogramState.sourceTexture, - histogramState.sourceTextureBinding, + source, + HistogramCs::Table_Batch::ColorSource_SLOT, 0, CoreGraphics::InvalidSamplerId, false, diff --git a/code/render/posteffects/histogramcontext.h b/code/render/posteffects/histogramcontext.h index 2586fb5579..9f57afd5f1 100644 --- a/code/render/posteffects/histogramcontext.h +++ b/code/render/posteffects/histogramcontext.h @@ -29,7 +29,7 @@ class HistogramContext : public Graphics::GraphicsContext static void SetWindow(const Math::float2 offset, Math::float2 size, int mip); /// setup bloom context - static void Setup(const Ptr& script); + static void Setup(); /// update view resources static void UpdateViewResources(const Ptr& view, const Graphics::FrameContext& ctx); diff --git a/code/render/posteffects/ssaocontext.cc b/code/render/posteffects/ssaocontext.cc index 8542df2beb..0c24eaaf57 100644 --- a/code/render/posteffects/ssaocontext.cc +++ b/code/render/posteffects/ssaocontext.cc @@ -17,6 +17,8 @@ #include "system_shaders/hbao_cs.h" #include "system_shaders/hbaoblur_cs.h" +#include "frame/default.h" + namespace PostEffects { __ImplementPluginContext(PostEffects::SSAOContext); @@ -35,15 +37,9 @@ struct // read-write textures CoreGraphics::TextureId internalTargets[2]; - CoreGraphics::TextureId ssaoOutput; - CoreGraphics::TextureId zBuffer; - Ptr frameScript; - - Memory::ArenaAllocator frameOpAllocator; struct AOVariables { - float fullWidth, fullHeight; float width, height; float downsample; float nearZ, farZ; @@ -110,10 +106,8 @@ SSAOContext::Discard() /** */ void -SSAOContext::Setup(const Ptr& script) +SSAOContext::Setup() { - ssaoState.frameScript = script; - using namespace CoreGraphics; CoreGraphics::TextureCreateInfo tinfo; tinfo.name = "HBAO-Internal0"_atm; @@ -136,8 +130,6 @@ SSAOContext::Setup(const Ptr& script) ssaoState.xDirectionBlur = ShaderGetProgram(ssaoState.blurShader, ShaderFeatureMask("Alt0")); ssaoState.yDirectionBlur = ShaderGetProgram(ssaoState.blurShader, ShaderFeatureMask("Alt1")); - ssaoState.ssaoOutput = ssaoState.frameScript->GetTexture("SSAOBuffer"); - ssaoState.zBuffer = ssaoState.frameScript->GetTexture("ZBuffer"); SizeT numBuffers = CoreGraphics::GetNumBufferedFrames(); ssaoState.hbaoTable.Resize(numBuffers); ssaoState.blurTableX.Resize(numBuffers); @@ -160,19 +152,16 @@ SSAOContext::Setup(const Ptr& script) ResourceTableCommitChanges(ssaoState.blurTableX[i]); ResourceTableSetTexture(ssaoState.blurTableY[i], { ssaoState.internalTargets[0], HbaoblurCs::Table_Batch::HBAOY_SLOT, 0, CoreGraphics::InvalidSamplerId }); - ResourceTableSetRWTexture(ssaoState.blurTableY[i], { ssaoState.ssaoOutput, HbaoblurCs::Table_Batch::HBAOR_SLOT, 0, CoreGraphics::InvalidSamplerId }); + ResourceTableSetRWTexture(ssaoState.blurTableY[i], { FrameScript_default::Texture_SSAOBuffer(), HbaoblurCs::Table_Batch::HBAOR_SLOT, 0, CoreGraphics::InvalidSamplerId }); ResourceTableCommitChanges(ssaoState.blurTableY[i]); } - TextureDimensions dims = TextureGetDimensions(ssaoState.ssaoOutput); - ssaoState.vars.fullWidth = (float)dims.width; - ssaoState.vars.fullHeight = (float)dims.height; + ssaoState.vars.radius = 12.0f; ssaoState.vars.downsample = 1.0f; ssaoState.vars.sceneScale = 1.0f; #define MAX_RADIUS_PIXELS 0.5f - ssaoState.vars.maxRadiusPixels = MAX_RADIUS_PIXELS * Math::min(ssaoState.vars.fullWidth, ssaoState.vars.fullHeight); ssaoState.vars.tanAngleBias = tanf(Math::deg2rad(35.0)); ssaoState.vars.strength = 1.0f; @@ -190,23 +179,9 @@ SSAOContext::Setup(const Ptr& script) ssaoState.blurFalloff = ShaderGetConstantBinding(ssaoState.blurShader, NEBULA_SEMANTIC_FALLOFF); ssaoState.blurDepthThreshold = ShaderGetConstantBinding(ssaoState.blurShader, NEBULA_SEMANTIC_DEPTHTHRESHOLD); - // Construct subgraph - auto aoX = ssaoState.frameOpAllocator.Alloc(); - aoX->SetName("HBAO X"); - aoX->domain = CoreGraphics::BarrierDomain::Global; - aoX->textureDeps.Add(ssaoState.zBuffer, - { - "ZBuffer" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::TextureSubresourceInfo::DepthStencil(ssaoState.zBuffer) - }); - aoX->textureDeps.Add(ssaoState.internalTargets[0], - { - "SSAOBuffer0" - , CoreGraphics::PipelineStage::ComputeShaderWrite - , CoreGraphics::TextureSubresourceInfo::Color(ssaoState.internalTargets[0]) - }); - aoX->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::Bind_HBAOInternal0(Frame::TextureImport(ssaoState.internalTargets[0])); + FrameScript_default::Bind_HBAOInternal1(Frame::TextureImport(ssaoState.internalTargets[1])); + FrameScript_default::RegisterSubgraph_HBAOX_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { uint numGroupsX1 = Math::divandroundup(ssaoState.vars.width, HbaoCs::HBAOTileWidth); uint numGroupsY2 = ssaoState.vars.height; @@ -215,24 +190,12 @@ SSAOContext::Setup(const Ptr& script) CoreGraphics::CmdSetShaderProgram(cmdBuf, ssaoState.xDirectionHBAO); CoreGraphics::CmdSetResourceTable(cmdBuf, ssaoState.hbaoTable[bufferIndex], NEBULA_BATCH_GROUP, CoreGraphics::ComputePipeline, nullptr); CoreGraphics::CmdDispatch(cmdBuf, numGroupsX1, numGroupsY2, 1); - }; - - auto aoY = ssaoState.frameOpAllocator.Alloc(); - aoY->SetName("HBAO Y"); - aoY->domain = CoreGraphics::BarrierDomain::Global; - aoY->textureDeps.Add(ssaoState.internalTargets[0], - { - "SSAOBuffer0" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::TextureSubresourceInfo::Color(ssaoState.internalTargets[0]) - }); - aoY->textureDeps.Add(ssaoState.internalTargets[1], - { - "SSAOBuffer1" - , CoreGraphics::PipelineStage::ComputeShaderWrite - , CoreGraphics::TextureSubresourceInfo::Color(ssaoState.internalTargets[1]) - }); - aoY->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }, nullptr, { + { FrameScript_default::TextureIndex::ZBuffer, CoreGraphics::PipelineStage::ComputeShaderRead } + , { FrameScript_default::TextureIndex::HBAOInternal0, CoreGraphics::PipelineStage::ComputeShaderWrite } + }); + + FrameScript_default::RegisterSubgraph_HBAOY_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { uint numGroupsX2 = ssaoState.vars.width; uint numGroupsY1 = Math::divandroundup(ssaoState.vars.height, HbaoCs::HBAOTileWidth); @@ -241,24 +204,12 @@ SSAOContext::Setup(const Ptr& script) CoreGraphics::CmdSetShaderProgram(cmdBuf, ssaoState.yDirectionHBAO); CoreGraphics::CmdSetResourceTable(cmdBuf, ssaoState.hbaoTable[bufferIndex], NEBULA_BATCH_GROUP, CoreGraphics::ComputePipeline, nullptr); CoreGraphics::CmdDispatch(cmdBuf, numGroupsY1, numGroupsX2, 1); - }; - - auto blurX = ssaoState.frameOpAllocator.Alloc(); - blurX->SetName("HBAO Blur X"); - blurX->domain = CoreGraphics::BarrierDomain::Global; - blurX->textureDeps.Add(ssaoState.internalTargets[1], - { - "SSAOBuffer1" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::TextureSubresourceInfo::Color(ssaoState.internalTargets[1]) - }); - blurX->textureDeps.Add(ssaoState.internalTargets[0], - { - "SSAOBuffer0" - , CoreGraphics::PipelineStage::ComputeShaderWrite - , CoreGraphics::TextureSubresourceInfo::Color(ssaoState.internalTargets[0]) - }); - blurX->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }, nullptr, { + { FrameScript_default::TextureIndex::HBAOInternal0, CoreGraphics::PipelineStage::ComputeShaderRead } + , { FrameScript_default::TextureIndex::HBAOInternal1, CoreGraphics::PipelineStage::ComputeShaderWrite } + }); + + FrameScript_default::RegisterSubgraph_HBAOBlurX_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { uint numGroupsX1 = Math::divandroundup(ssaoState.vars.width, HbaoCs::HBAOTileWidth); uint numGroupsY2 = ssaoState.vars.height; @@ -267,24 +218,12 @@ SSAOContext::Setup(const Ptr& script) CoreGraphics::CmdSetShaderProgram(cmdBuf, ssaoState.xDirectionBlur, false); CoreGraphics::CmdSetResourceTable(cmdBuf, ssaoState.blurTableX[bufferIndex], NEBULA_BATCH_GROUP, CoreGraphics::ComputePipeline, nullptr); CoreGraphics::CmdDispatch(cmdBuf, numGroupsX1, numGroupsY2, 1); - }; - - auto blurY = ssaoState.frameOpAllocator.Alloc(); - blurY->SetName("HBAO Blur X"); - blurY->domain = CoreGraphics::BarrierDomain::Global; - blurY->textureDeps.Add(ssaoState.internalTargets[0], - { - "SSAOBuffer1" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::TextureSubresourceInfo::Color(ssaoState.internalTargets[0]) - }); - blurY->textureDeps.Add(ssaoState.ssaoOutput, - { - "SSAOOutput" - , CoreGraphics::PipelineStage::ComputeShaderWrite - , CoreGraphics::TextureSubresourceInfo::Color(ssaoState.internalTargets[1]) - }); - blurY->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }, nullptr, { + { FrameScript_default::TextureIndex::HBAOInternal0, CoreGraphics::PipelineStage::ComputeShaderWrite } + , { FrameScript_default::TextureIndex::HBAOInternal1, CoreGraphics::PipelineStage::ComputeShaderRead } + }); + + FrameScript_default::RegisterSubgraph_HBAOBlurY_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { uint numGroupsX2 = ssaoState.vars.width; uint numGroupsY1 = Math::divandroundup(ssaoState.vars.height, HbaoCs::HBAOTileWidth); @@ -293,9 +232,10 @@ SSAOContext::Setup(const Ptr& script) CoreGraphics::CmdSetShaderProgram(cmdBuf, ssaoState.yDirectionBlur, false); CoreGraphics::CmdSetResourceTable(cmdBuf, ssaoState.blurTableY[bufferIndex], NEBULA_BATCH_GROUP, CoreGraphics::ComputePipeline, nullptr); CoreGraphics::CmdDispatch(cmdBuf, numGroupsY1, numGroupsX2, 1); - }; - - Frame::AddSubgraph("HBAO", { aoX, aoY, blurX, blurY }); + }, nullptr, { + { FrameScript_default::TextureIndex::HBAOInternal0, CoreGraphics::PipelineStage::ComputeShaderRead } + , { FrameScript_default::TextureIndex::HBAOInternal1, CoreGraphics::PipelineStage::ComputeShaderWrite } + }); } //------------------------------------------------------------------------------ @@ -309,8 +249,11 @@ SSAOContext::UpdateViewDependentResources(const Ptr& view, const using namespace CoreGraphics; const CameraSettings& cameraSettings = CameraContext::GetSettings(view->GetCamera()); - ssaoState.vars.width = ssaoState.vars.fullWidth / ssaoState.vars.downsample; - ssaoState.vars.height = ssaoState.vars.fullHeight / ssaoState.vars.downsample; + const Math::rectangle& viewport = view->GetViewport(); + + ssaoState.vars.width = viewport.width() / ssaoState.vars.downsample; + ssaoState.vars.height = viewport.height() / ssaoState.vars.downsample; + ssaoState.vars.maxRadiusPixels = MAX_RADIUS_PIXELS * Math::min(viewport.width(), viewport.height()); ssaoState.vars.nearZ = cameraSettings.GetZNear() + 0.1f; ssaoState.vars.farZ = cameraSettings.GetZFar(); @@ -325,7 +268,7 @@ SSAOContext::UpdateViewDependentResources(const Ptr& view, const ssaoState.vars.invAOResolution.y = 1.0f / ssaoState.vars.height; float fov = cameraSettings.GetFov(); - ssaoState.vars.focalLength.x = 1.0f / tanf(fov * 0.5f) * (ssaoState.vars.fullHeight / ssaoState.vars.fullWidth); + ssaoState.vars.focalLength.x = 1.0f / tanf(fov * 0.5f) * (viewport.height() / float(viewport.width())); ssaoState.vars.focalLength.y = 1.0f / tanf(fov * 0.5f); Math::vec2 invFocalLength; @@ -393,6 +336,9 @@ SSAOContext::WindowResized(const CoreGraphics::WindowId id, SizeT width, SizeT h TextureWindowResized(ssaoState.internalTargets[0]); TextureWindowResized(ssaoState.internalTargets[1]); + FrameScript_default::Bind_HBAOInternal0(Frame::TextureImport(ssaoState.internalTargets[0])); + FrameScript_default::Bind_HBAOInternal1(Frame::TextureImport(ssaoState.internalTargets[1])); + IndexT i; for (i = 0; i < ssaoState.hbaoTable.Size(); i++) { @@ -407,15 +353,9 @@ SSAOContext::WindowResized(const CoreGraphics::WindowId id, SizeT width, SizeT h ResourceTableCommitChanges(ssaoState.blurTableX[i]); ResourceTableSetTexture(ssaoState.blurTableY[i], { ssaoState.internalTargets[0], HbaoblurCs::Table_Batch::HBAOY_SLOT, 0, CoreGraphics::InvalidSamplerId }); - ResourceTableSetRWTexture(ssaoState.blurTableY[i], { ssaoState.ssaoOutput, HbaoblurCs::Table_Batch::HBAOR_SLOT, 0, CoreGraphics::InvalidSamplerId }); + ResourceTableSetRWTexture(ssaoState.blurTableY[i], { FrameScript_default::Texture_SSAOBuffer(), HbaoblurCs::Table_Batch::HBAOR_SLOT, 0, CoreGraphics::InvalidSamplerId }); ResourceTableCommitChanges(ssaoState.blurTableY[i]); } - - TextureDimensions dims = TextureGetDimensions(ssaoState.ssaoOutput); - ssaoState.vars.fullWidth = (float)dims.width; - ssaoState.vars.fullHeight = (float)dims.height; - - ssaoState.vars.maxRadiusPixels = MAX_RADIUS_PIXELS * Math::min(ssaoState.vars.fullWidth, ssaoState.vars.fullHeight); } } // namespace PostEffects diff --git a/code/render/posteffects/ssaocontext.h b/code/render/posteffects/ssaocontext.h index fde2ffa4d3..fae5a9507e 100644 --- a/code/render/posteffects/ssaocontext.h +++ b/code/render/posteffects/ssaocontext.h @@ -26,7 +26,7 @@ class SSAOContext : public Graphics::GraphicsContext static void Discard(); /// setup bloom context - static void Setup(const Ptr& script); + static void Setup(); /// update view resources static void UpdateViewDependentResources(const Ptr& view, const Graphics::FrameContext& ctx); diff --git a/code/render/posteffects/ssrcontext.cc b/code/render/posteffects/ssrcontext.cc index 6ee50e924a..b7e0ac41ad 100644 --- a/code/render/posteffects/ssrcontext.cc +++ b/code/render/posteffects/ssrcontext.cc @@ -14,6 +14,8 @@ #include "system_shaders/ssr_cs.h" #include "system_shaders/ssr_resolve_cs.h" +#include "frame/default.h" + namespace PostEffects { __ImplementPluginContext(PostEffects::SSRContext); @@ -30,7 +32,6 @@ struct CoreGraphics::ShaderProgramId resolveProgram; CoreGraphics::TextureId traceBuffer; - CoreGraphics::TextureId reflectionBuffer; } ssrState; //------------------------------------------------------------------------------ @@ -78,7 +79,7 @@ SSRContext::Create() Frame::AddCallback("SSR-Resolve", [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) { N_CMD_SCOPE(cmdBuf, NEBULA_MARKER_BLUE, "Screen Space Reflections"); - TextureDimensions dims = TextureGetDimensions(ssrState.reflectionBuffer); + TextureDimensions dims = TextureGetDimensions(FrameScript_default::Texture_ReflectionBuffer()); CoreGraphics::CmdSetShaderProgram(cmdBuf, ssrState.resolveProgram); CoreGraphics::CmdSetResourceTable(cmdBuf, ssrState.ssrResolveTables[bufferIndex], NEBULA_BATCH_GROUP, CoreGraphics::ComputePipeline, nullptr); @@ -114,8 +115,7 @@ SSRContext::Setup(const Ptr& script) { SizeT numFrames = CoreGraphics::GetNumBufferedFrames(); using namespace CoreGraphics; - ssrState.traceBuffer = script->GetTexture("SSRTraceBuffer"); - ssrState.reflectionBuffer = script->GetTexture("ReflectionBuffer"); + ssrState.traceBuffer = CoreGraphics::White2D; // script->GetTexture("SSRTraceBuffer"); // create trace shader ssrState.traceShader = ShaderGet("shd:ssr_cs.fxb"); @@ -135,7 +135,7 @@ SSRContext::Setup(const Ptr& script) for (IndexT i = 0; i < numFrames; ++i) { ssrState.ssrResolveTables[i] = ShaderCreateResourceTable(ssrState.resolveShader, NEBULA_BATCH_GROUP, numFrames); - ResourceTableSetRWTexture(ssrState.ssrResolveTables[i], { ssrState.reflectionBuffer, SsrResolveCs::Table_Batch::ReflectionBuffer_SLOT, 0, InvalidSamplerId }); + ResourceTableSetRWTexture(ssrState.ssrResolveTables[i], { FrameScript_default::Texture_ReflectionBuffer(), SsrResolveCs::Table_Batch::ReflectionBuffer_SLOT, 0, InvalidSamplerId }); ResourceTableSetTexture(ssrState.ssrResolveTables[i], { ssrState.traceBuffer, SsrResolveCs::Table_Batch::TraceBuffer_SLOT, 0, InvalidSamplerId }); ResourceTableCommitChanges(ssrState.ssrResolveTables[i]); } diff --git a/code/render/raytracing/raytracingcontext.cc b/code/render/raytracing/raytracingcontext.cc index 22afeca0dc..284cddd98f 100644 --- a/code/render/raytracing/raytracingcontext.cc +++ b/code/render/raytracing/raytracingcontext.cc @@ -20,6 +20,8 @@ #include "raytracing/shaders/light_grid_cs.h" +#include "frame/default.h" + namespace Raytracing { @@ -38,12 +40,10 @@ struct Memory::RangeAllocator blasInstanceAllocator; bool topLevelNeedsReconstruction, topLevelNeedsBuild, topLevelNeedsUpdate; - Memory::ArenaAllocator frameOpAllocator; Util::HashTable> blasLookup; CoreGraphics::BufferWithStaging blasInstanceBuffer; CoreGraphics::ResourceTableSet raytracingTestTables; - CoreGraphics::TextureId raytracingTestOutput; CoreGraphics::BufferId geometryBindingBuffer; CoreGraphics::BufferWithStaging objectBindingBuffer; @@ -193,60 +193,33 @@ RaytracingContext::Create(const RaytracingSetupSettings& settings) objectBindingBufferCreateInfo.name = "Raytracing Object Binding Buffer"; objectBindingBufferCreateInfo.byteSize = sizeof(Raytracetest::Object) * settings.maxNumAllowedInstances; objectBindingBufferCreateInfo.usageFlags = CoreGraphics::BufferUsageFlag::ShaderAddress | CoreGraphics::BufferUsageFlag::ReadWriteBuffer; + objectBindingBufferCreateInfo.queueSupport = CoreGraphics::BufferQueueSupport::ComputeQueueSupport; state.objectBindingBuffer = CoreGraphics::BufferWithStaging(objectBindingBufferCreateInfo); + FrameScript_default::Bind_RayTracingObjectBindings(state.objectBindingBuffer.DeviceBuffer()); + FrameScript_default::Bind_GridLightList(state.lightGrid); + FrameScript_default::Bind_GridLightIndexLists(state.lightGridIndexLists); - Frame::FrameCode* lightGridGen = state.frameOpAllocator.Alloc(); - lightGridGen->SetName("Raytracing Light Grid Update"); - lightGridGen->domain = CoreGraphics::BarrierDomain::Global; - lightGridGen->queue = CoreGraphics::QueueType::ComputeQueueType; - lightGridGen->bufferDeps.Add(state.lightGrid, - { - "Light Grid" - , CoreGraphics::PipelineStage::ComputeShaderWrite - , CoreGraphics::BufferSubresourceInfo() - }); - lightGridGen->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_RaytracingLightGridGen_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CoreGraphics::CmdSetShaderProgram(cmdBuf, state.lightGridGenProgram); CoreGraphics::CmdSetResourceTable(cmdBuf, state.lightGridResourceTables.tables[bufferIndex], NEBULA_FRAME_GROUP, CoreGraphics::ComputePipeline, nullptr); CoreGraphics::CmdDispatch(cmdBuf, 64 * 64, 1, 1); - }; - - Frame::FrameCode* lightGridCull = state.frameOpAllocator.Alloc(); - lightGridCull->SetName("Raytracing Light Grid Cull"); - lightGridCull->domain = CoreGraphics::BarrierDomain::Global; - lightGridCull->queue = CoreGraphics::QueueType::ComputeQueueType; - lightGridCull->bufferDeps.Add(state.lightGrid, - { - "Light Grid" - , CoreGraphics::PipelineStage::ComputeShaderRead - , CoreGraphics::BufferSubresourceInfo() - }); - lightGridCull->bufferDeps.Add(state.lightGridIndexLists, - { - "Light Grid Index Lists" - , CoreGraphics::PipelineStage::ComputeShaderWrite - , CoreGraphics::BufferSubresourceInfo() - }); - lightGridCull->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }, { + { FrameScript_default::BufferIndex::GridLightList, CoreGraphics::PipelineStage::ComputeShaderWrite } + }); + + FrameScript_default::RegisterSubgraph_RaytracingLightGridCull_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CoreGraphics::CmdSetShaderProgram(cmdBuf, state.lightGridCullProgram); CoreGraphics::CmdSetResourceTable(cmdBuf, state.lightGridResourceTables.tables[bufferIndex], NEBULA_FRAME_GROUP, CoreGraphics::ComputePipeline, nullptr); CoreGraphics::CmdDispatch(cmdBuf, 64 * 64, 1, 1); - }; - Frame::AddSubgraph("Raytracing Light Update", { lightGridGen, lightGridCull }); + }, { + { FrameScript_default::BufferIndex::GridLightList, CoreGraphics::PipelineStage::ComputeShaderRead } + , { FrameScript_default::BufferIndex::GridLightIndexLists, CoreGraphics::PipelineStage::ComputeShaderWrite } + }); - Frame::FrameCode* blasUpdate = state.frameOpAllocator.Alloc(); - blasUpdate->SetName("Bottom Level Acceleration Structure Update"); - blasUpdate->domain = CoreGraphics::BarrierDomain::Global; - blasUpdate->bufferDeps.Add(state.objectBindingBuffer.DeviceBuffer(), - { - "Object Raytracing Bindings" - , CoreGraphics::PipelineStage::TransferWrite - , CoreGraphics::BufferSubresourceInfo() - }); - blasUpdate->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_RaytracingStructuresUpdate_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { if (!state.objects.IsEmpty()) state.objectBindingBuffer.Flush(cmdBuf, state.objects.ByteSize()); @@ -266,7 +239,7 @@ RaytracingContext::Create(const RaytracingSetupSettings& settings) nullptr, nullptr, { - CoreGraphics::AccelerationStructureBarrierInfo {.blas = state.blasesToRebuild[i], .type = CoreGraphics::AccelerationStructureBarrierInfo::BlasBarrier } + CoreGraphics::AccelerationStructureBarrierInfo{ .blas = state.blasesToRebuild[i], .type = CoreGraphics::AccelerationStructureBarrierInfo::BlasBarrier } } ); CoreGraphics::CmdBuildBlas(cmdBuf, state.blasesToRebuild[i]); @@ -278,7 +251,7 @@ RaytracingContext::Create(const RaytracingSetupSettings& settings) nullptr, nullptr, { - CoreGraphics::AccelerationStructureBarrierInfo {.blas = state.blasesToRebuild[i], .type = CoreGraphics::AccelerationStructureBarrierInfo::BlasBarrier} + CoreGraphics::AccelerationStructureBarrierInfo{ .blas = state.blasesToRebuild[i], .type = CoreGraphics::AccelerationStructureBarrierInfo::BlasBarrier } } ); } @@ -305,7 +278,7 @@ RaytracingContext::Create(const RaytracingSetupSettings& settings) nullptr, nullptr, { - CoreGraphics::AccelerationStructureBarrierInfo {.tlas = state.toplevelAccelerationStructure, .type = CoreGraphics::AccelerationStructureBarrierInfo::TlasBarrier } + CoreGraphics::AccelerationStructureBarrierInfo{ .tlas = state.toplevelAccelerationStructure, .type = CoreGraphics::AccelerationStructureBarrierInfo::TlasBarrier } } ); @@ -322,7 +295,7 @@ RaytracingContext::Create(const RaytracingSetupSettings& settings) nullptr, nullptr, { - CoreGraphics::AccelerationStructureBarrierInfo {.tlas = state.toplevelAccelerationStructure, .type = CoreGraphics::AccelerationStructureBarrierInfo::TlasBarrier } + CoreGraphics::AccelerationStructureBarrierInfo{ .tlas = state.toplevelAccelerationStructure, .type = CoreGraphics::AccelerationStructureBarrierInfo::TlasBarrier } } ); } @@ -336,7 +309,7 @@ RaytracingContext::Create(const RaytracingSetupSettings& settings) nullptr, nullptr, { - CoreGraphics::AccelerationStructureBarrierInfo {.tlas = state.toplevelAccelerationStructure, .type = CoreGraphics::AccelerationStructureBarrierInfo::TlasBarrier } + CoreGraphics::AccelerationStructureBarrierInfo{ .tlas = state.toplevelAccelerationStructure, .type = CoreGraphics::AccelerationStructureBarrierInfo::TlasBarrier } } ); @@ -353,30 +326,16 @@ RaytracingContext::Create(const RaytracingSetupSettings& settings) nullptr, nullptr, { - CoreGraphics::AccelerationStructureBarrierInfo {.tlas = state.toplevelAccelerationStructure, .type = CoreGraphics::AccelerationStructureBarrierInfo::TlasBarrier } + CoreGraphics::AccelerationStructureBarrierInfo{ .tlas = state.toplevelAccelerationStructure, .type = CoreGraphics::AccelerationStructureBarrierInfo::TlasBarrier } } ); } state.blasLock.Leave(); - }; - Frame::AddSubgraph("Raytracing Structures Update", { blasUpdate }); - - Frame::FrameCode* testRays = state.frameOpAllocator.Alloc(); - testRays->SetName("Ray Tracing Test Shader"); - testRays->domain = CoreGraphics::BarrierDomain::Global; - testRays->bufferDeps.Add(state.lightGridIndexLists, - { - "Light Grid Index Lists" - , CoreGraphics::PipelineStage::RayTracingShaderRead - , CoreGraphics::BufferSubresourceInfo() - }); - testRays->bufferDeps.Add(state.objectBindingBuffer.DeviceBuffer(), - { - "Object Raytracing Bindings" - , CoreGraphics::PipelineStage::RayTracingShaderRead - , CoreGraphics::BufferSubresourceInfo() - }); - testRays->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }, { + { FrameScript_default::BufferIndex::RayTracingObjectBindings, CoreGraphics::PipelineStage::TransferWrite } + }); + + FrameScript_default::RegisterSubgraph_RaytracingTest_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { if (state.toplevelAccelerationStructure != CoreGraphics::InvalidTlasId) { @@ -385,10 +344,11 @@ RaytracingContext::Create(const RaytracingSetupSettings& settings) CoreGraphics::CmdSetResourceTable(cmdBuf, state.lightGridResourceTables.tables[bufferIndex], NEBULA_FRAME_GROUP, CoreGraphics::RayTracingPipeline, nullptr); CoreGraphics::CmdRaysDispatch(cmdBuf, state.raytracingBundle.table, 640, 480, 1); } - }; - Frame::AddSubgraph("Raytracing Test", { testRays }); + }, { + { FrameScript_default::BufferIndex::GridLightIndexLists, CoreGraphics::PipelineStage::RayTracingShaderRead } + , { FrameScript_default::BufferIndex::RayTracingObjectBindings, CoreGraphics::PipelineStage::RayTracingShaderRead } + } ); - state.raytracingTestOutput = settings.script->GetTexture("RayTracingTestOutput"); state.maxAllowedInstances = settings.maxNumAllowedInstances; @@ -630,7 +590,7 @@ RaytracingContext::ReconstructTopLevelAcceleration(const Graphics::FrameContext& ); CoreGraphics::ResourceTableSetRWTexture( state.raytracingTestTables.tables[ctx.bufferIndex], - CoreGraphics::ResourceTableTexture(state.raytracingTestOutput, Raytracetest::Table_Batch::RaytracingOutput_SLOT) + CoreGraphics::ResourceTableTexture(FrameScript_default::Texture_RayTracingTestOutput(), Raytracetest::Table_Batch::RaytracingOutput_SLOT) ); CoreGraphics::ResourceTableSetRWBuffer( diff --git a/code/render/raytracing/raytracingcontext.h b/code/render/raytracing/raytracingcontext.h index 4fdda23fcf..1175d445ec 100644 --- a/code/render/raytracing/raytracingcontext.h +++ b/code/render/raytracing/raytracingcontext.h @@ -20,7 +20,6 @@ namespace Raytracing struct RaytracingSetupSettings { SizeT maxNumAllowedInstances; - const Ptr& script; }; enum ObjectType diff --git a/code/render/renderutil/drawfullscreenquad.cc b/code/render/renderutil/drawfullscreenquad.cc index 8460243883..a78adfba1b 100644 --- a/code/render/renderutil/drawfullscreenquad.cc +++ b/code/render/renderutil/drawfullscreenquad.cc @@ -100,8 +100,6 @@ DrawFullScreenQuad::ApplyMesh(const CoreGraphics::CmdBufferId id) { CoreGraphics::CmdSetVertexLayout(id, DrawFullScreenQuad::vertexLayout); CoreGraphics::CmdSetPrimitiveTopology(id, PrimitiveTopology::TriangleList); - CoreGraphics::CmdSetGraphicsPipeline(id); - CoreGraphics::CmdSetVertexBuffer(id, 0, DrawFullScreenQuad::vertexBuffer, 0); } diff --git a/code/render/terrain/shaders/terrain.fx b/code/render/terrain/shaders/terrain.fx index 059cae1771..541fe6acc7 100644 --- a/code/render/terrain/shaders/terrain.fx +++ b/code/render/terrain/shaders/terrain.fx @@ -243,7 +243,7 @@ TessellationFactorScreenSpace(vec4 p0, vec4 p1) mat4 mvp = Transform * ViewProjection; vec4 p0Proj = mvp * p0; vec4 p1Proj = mvp * p1; - float screen = max(RenderTargetDimensions[0].x, RenderTargetDimensions[0].y); + float screen = max(RenderTargetParameter[0].Dimensionsx, RenderTargetParameter[0].Dimensions.y); float dist = distance(p0Proj.xy / p0Proj.w, p1Proj.xy / p1Proj.w); return clamp(dist * screen, MinTessellation, MaxTessellation); */ @@ -264,8 +264,8 @@ TessellationFactorScreenSpace(vec4 p0, vec4 p1) clip1 /= clip1.w; // Convert to viewport coordinates - clip0.xy *= RenderTargetDimensions[0].xy; - clip1.xy *= RenderTargetDimensions[0].xy; + clip0.xy *= RenderTargetParameter[0].Dimensions.xy; + clip1.xy *= RenderTargetParameter[0].Dimensions.xy; // Return the tessellation factor based on the screen size // given by the distance of the two edge control points in screen space @@ -982,7 +982,7 @@ psGenerateLowresFallback( vec2 worldSize = vec2(WorldSizeX, WorldSizeZ); vec2 invWorldSize = 1.0f / worldSize; - vec2 texelSize = RenderTargetDimensions[0].zw; + vec2 texelSize = RenderTargetParameter[0].Dimensions.zw; vec2 pixel = vec2(gl_FragCoord.xy); vec2 uv = pixel * texelSize; vec2 pixelToWorldScale = vec2(WorldSizeX, WorldSizeZ) * texelSize; @@ -1030,7 +1030,7 @@ psGenerateLowresFallback( Material = totalMaterial; } -group(SYSTEM_GROUP) readwrite r32f image2D TerrainShadowMap; +group(SYSTEM_GROUP) readwrite rg16f image2D TerrainShadowMap; //------------------------------------------------------------------------------ /** Copy between indirection textures @@ -1060,6 +1060,7 @@ csTerrainShadows() vec3 coord = startCoord + GlobalLightDirWorldspace.xyz * stepSize; float smallestDistance = 10000000.0f; + float highestPoint = 100000.0f; vec4 plane = vec4(GlobalLightDirWorldspace.xyz, 0); for (uint i = 0; i < NumSamples; i++) { @@ -1081,6 +1082,7 @@ csTerrainShadows() // Calculate distance for contact hardening shadows float dist = distance(startCoord, sampleCoord); smallestDistance = min(smallestDistance, dist); + highestPoint = intersection.y; // Half step size in preparation of the next sample stepSize *= 0.5f; @@ -1094,14 +1096,9 @@ csTerrainShadows() coord += GlobalLightDirWorldspace.xyz * stepSize; } } - float shadow; - if (smallestDistance == 10000000.0f) - shadow = 1.0f; - else - // Do a bit of dirty inverse square falloff - shadow = (smallestDistance * smallestDistance) / (MaxDistance * MaxDistance); + float shadow = smallestDistance == 10000000.0f ? 1.0f : (smallestDistance * smallestDistance) / (MaxDistance * MaxDistance); - imageStore(TerrainShadowMap, ivec2(gl_GlobalInvocationID.xy), vec4(shadow)); + imageStore(TerrainShadowMap, ivec2(gl_GlobalInvocationID.xy), vec4(shadow, highestPoint, 0, 0)); } //------------------------------------------------------------------------------ diff --git a/code/render/terrain/terraincontext.cc b/code/render/terrain/terraincontext.cc index b9f795c5cb..94e0c942ff 100644 --- a/code/render/terrain/terraincontext.cc +++ b/code/render/terrain/terraincontext.cc @@ -26,6 +26,8 @@ #include "terrain/shaders/terrain.h" #include "terrain/shaders/terrain_mesh_generate.h" +#include "frame/default.h" + N_DECLARE_COUNTER(N_TERRAIN_TOTAL_AVAILABLE_DATA, Terrain Total Data Size); namespace Terrain @@ -57,7 +59,7 @@ const uint PhysicalTextureTilePaddedSize = PhysicalTextureTileSize + PhysicalTex const uint PhysicalTextureSize = (PhysicalTextureTileSize) * PhysicalTextureNumTiles; const uint PhysicalTexturePaddedSize = (PhysicalTextureTilePaddedSize) * PhysicalTextureNumTiles; -const uint TerrainShadowMapSize = 1024; +const uint TerrainShadowMapSize = 2048; __ImplementContext(TerrainContext, TerrainContext::terrainAllocator); @@ -90,7 +92,6 @@ struct CoreGraphics::ResourceTableId terrainShadowResourceTable; CoreGraphics::TextureId terrainPosBuffer; - Memory::ArenaAllocator frameOpAllocator; float mipLoadDistance = 1500.0f; float mipRenderPadding = 150.0f; @@ -321,7 +322,7 @@ TerrainContext::Create(const TerrainSetupSettings& settings) shadowMapInfo.name = "TerrainShadowMap"_atm; shadowMapInfo.width = TerrainShadowMapSize; shadowMapInfo.height = TerrainShadowMapSize; - shadowMapInfo.format = CoreGraphics::PixelFormat::R16F; + shadowMapInfo.format = CoreGraphics::PixelFormat::R16G16F; shadowMapInfo.usage = CoreGraphics::TextureUsage::ReadWriteTexture; terrainState.terrainShadowMap = CoreGraphics::CreateTexture(shadowMapInfo); @@ -391,7 +392,7 @@ TerrainContext::Create(const TerrainSetupSettings& settings) texInfo.width = IndirectionTextureSize; texInfo.height = IndirectionTextureSize; texInfo.format = CoreGraphics::PixelFormat::R32; - texInfo.usage = CoreGraphics::SampleTexture | CoreGraphics::TransferTextureDestination | CoreGraphics::TransferTextureSource; + texInfo.usage = CoreGraphics::SampleTexture | CoreGraphics::TransferDestinationTexture | CoreGraphics::TransferSourceTexture; texInfo.mips = IndirectionNumMips; texInfo.clear = true; texInfo.clearColorU4 = Math::uint4{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; @@ -498,7 +499,7 @@ TerrainContext::Create(const TerrainSetupSettings& settings) lowResAlbedoInfo.width = LowresFallbackSize; lowResAlbedoInfo.height = LowresFallbackSize; lowResAlbedoInfo.format = CoreGraphics::PixelFormat::R8G8B8A8; - lowResAlbedoInfo.usage = CoreGraphics::TextureUsage::RenderTexture | CoreGraphics::TextureUsage::TransferTextureDestination | CoreGraphics::TextureUsage::TransferTextureSource; + lowResAlbedoInfo.usage = CoreGraphics::TextureUsage::RenderTexture | CoreGraphics::TextureUsage::TransferDestinationTexture | CoreGraphics::TextureUsage::TransferSourceTexture; terrainVirtualTileState.lowresAlbedo = CoreGraphics::CreateTexture(lowResAlbedoInfo); CoreGraphics::TextureCreateInfo lowResNormalInfo; @@ -507,7 +508,7 @@ TerrainContext::Create(const TerrainSetupSettings& settings) lowResNormalInfo.width = LowresFallbackSize; lowResNormalInfo.height = LowresFallbackSize; lowResNormalInfo.format = CoreGraphics::PixelFormat::R8G8B8A8; - lowResNormalInfo.usage = CoreGraphics::TextureUsage::RenderTexture | CoreGraphics::TextureUsage::TransferTextureDestination | CoreGraphics::TextureUsage::TransferTextureSource; + lowResNormalInfo.usage = CoreGraphics::TextureUsage::RenderTexture | CoreGraphics::TextureUsage::TransferDestinationTexture | CoreGraphics::TextureUsage::TransferSourceTexture; terrainVirtualTileState.lowresNormal = CoreGraphics::CreateTexture(lowResNormalInfo); CoreGraphics::TextureCreateInfo lowResMaterialInfo; @@ -516,7 +517,7 @@ TerrainContext::Create(const TerrainSetupSettings& settings) lowResMaterialInfo.width = LowresFallbackSize; lowResMaterialInfo.height = LowresFallbackSize; lowResMaterialInfo.format = CoreGraphics::PixelFormat::R8G8B8A8; - lowResMaterialInfo.usage = CoreGraphics::TextureUsage::RenderTexture | CoreGraphics::TextureUsage::TransferTextureDestination | CoreGraphics::TextureUsage::TransferTextureSource; + lowResMaterialInfo.usage = CoreGraphics::TextureUsage::RenderTexture | CoreGraphics::TextureUsage::TransferDestinationTexture | CoreGraphics::TextureUsage::TransferSourceTexture; terrainVirtualTileState.lowresMaterial = CoreGraphics::CreateTexture(lowResMaterialInfo); // setup virtual sub textures buffer @@ -654,10 +655,7 @@ TerrainContext::Create(const TerrainSetupSettings& settings) if (CoreGraphics::RayTracingSupported) { - Frame::FrameCode* terrainMeshGenerate = terrainState.frameOpAllocator.Alloc(); - terrainMeshGenerate->domain = CoreGraphics::BarrierDomain::Global; - terrainMeshGenerate->queue = CoreGraphics::ComputeQueueType; - terrainMeshGenerate->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_TerrainRaytracingMeshGenerate_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { if (raytracingState.updateMesh) { @@ -674,38 +672,16 @@ TerrainContext::Create(const TerrainSetupSettings& settings) raytracingState.setupBlasFrame = bufferIndex + CoreGraphics::GetNumBufferedFrames(); } - }; + }); + } + + FrameScript_default::Bind_TerrainUpdateList(terrainVirtualTileState.pageUpdateListBuffer); + FrameScript_default::Bind_TerrainVirtualPageStatuses(terrainVirtualTileState.pageStatusBuffer); + FrameScript_default::Bind_TerrainSubTextures(terrainVirtualTileState.subTextureBuffer); + FrameScript_default::Bind_TerrainIndirection(Frame::TextureImport(terrainVirtualTileState.indirectionTexture)); + FrameScript_default::Bind_TerrainIndirectionCopy(Frame::TextureImport(terrainVirtualTileState.indirectionTextureCopy)); - Frame::AddSubgraph("Terrain Raytracing Mesh Generate", { terrainMeshGenerate }); - } - - Frame::FrameCode* terrainPrepare = terrainState.frameOpAllocator.Alloc(); - terrainPrepare->domain = CoreGraphics::BarrierDomain::Global; - terrainPrepare->bufferDeps.Add(terrainVirtualTileState.pageStatusBuffer, - { - "Page Status Buffer", - CoreGraphics::PipelineStage::TransferWrite, - CoreGraphics::BufferSubresourceInfo() - }); - terrainPrepare->bufferDeps.Add(terrainVirtualTileState.subTextureBuffer, - { - "Sub Texture Buffer", - CoreGraphics::PipelineStage::TransferWrite, - CoreGraphics::BufferSubresourceInfo() - }); - terrainPrepare->textureDeps.Add(terrainVirtualTileState.indirectionTexture, - { - "Indirection Texture", - CoreGraphics::PipelineStage::TransferWrite, - CoreGraphics::TextureSubresourceInfo::Color(terrainVirtualTileState.indirectionTexture) - }); - terrainPrepare->textureDeps.Add(terrainVirtualTileState.indirectionTextureCopy, - { - "Indirection Texture Copy", - CoreGraphics::PipelineStage::TransferRead, - CoreGraphics::TextureSubresourceInfo::Color(terrainVirtualTileState.indirectionTextureCopy) - }); - terrainPrepare->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_TerrainPrepare_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { if (terrainVirtualTileState.indirectionBufferUpdatesThisFrame.Size() > 0 || terrainVirtualTileState.indirectionBufferClearsThisFrame.Size() > 0 @@ -823,7 +799,7 @@ TerrainContext::Create(const TerrainSetupSettings& settings) CmdCopy(cmdBuf , terrainVirtualTileState.subtextureStagingBuffers.buffers[bufferIndex], { from } , terrainVirtualTileState.subTextureBuffer, { to } - , BufferGetByteSize(terrainVirtualTileState.subTextureBuffer)); + , BufferGetByteSize(terrainVirtualTileState.subTextureBuffer)); CmdBarrier(cmdBuf, PipelineStage::TransferRead, @@ -840,23 +816,15 @@ TerrainContext::Create(const TerrainSetupSettings& settings) terrainVirtualTileState.virtualSubtextureBufferUpdate = false; CmdEndMarker(cmdBuf); } - }; + }, { + { FrameScript_default::BufferIndex::TerrainVirtualPageStatuses, CoreGraphics::PipelineStage::TransferWrite } + , { FrameScript_default::BufferIndex::TerrainSubTextures, CoreGraphics::PipelineStage::TransferWrite } + }, { + { FrameScript_default::TextureIndex::TerrainIndirection, CoreGraphics::PipelineStage::TransferWrite } + , { FrameScript_default::TextureIndex::TerrainIndirectionCopy, CoreGraphics::PipelineStage::TransferRead } + }); - Frame::FrameCode* indirectionCopy = terrainState.frameOpAllocator.Alloc(); - indirectionCopy->domain = CoreGraphics::BarrierDomain::Global; - indirectionCopy->textureDeps.Add(terrainVirtualTileState.indirectionTexture, - { - "Indirection Texture", - CoreGraphics::PipelineStage::TransferRead, - CoreGraphics::TextureSubresourceInfo::Color(terrainVirtualTileState.indirectionTexture) - }); - indirectionCopy->textureDeps.Add(terrainVirtualTileState.indirectionTextureCopy, - { - "Indirection Texture Copy", - CoreGraphics::PipelineStage::TransferWrite, - CoreGraphics::TextureSubresourceInfo::Color(terrainVirtualTileState.indirectionTextureCopy) - }); - indirectionCopy->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_TerrainIndirectionCopy_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CmdBeginMarker(cmdBuf, NEBULA_MARKER_TRANSFER, "Copy Indirection Mips"); @@ -873,25 +841,12 @@ TerrainContext::Create(const TerrainSetupSettings& settings) } CmdEndMarker(cmdBuf); - }; - - Frame::AddSubgraph("Terrain Prepare", { terrainPrepare, indirectionCopy }); + }, nullptr, { + { FrameScript_default::TextureIndex::TerrainIndirection, CoreGraphics::PipelineStage::TransferRead } + , { FrameScript_default::TextureIndex::TerrainIndirectionCopy, CoreGraphics::PipelineStage::TransferWrite } + }); - Frame::FrameCode* terrainPrepass = terrainState.frameOpAllocator.Alloc(); - terrainPrepass->domain = CoreGraphics::BarrierDomain::Pass; - terrainPrepass->bufferDeps.Add(terrainVirtualTileState.pageUpdateListBuffer, - { - "Page Update List", - CoreGraphics::PipelineStage::PixelShaderWrite, - CoreGraphics::BufferSubresourceInfo() - }); - terrainPrepass->bufferDeps.Add(terrainVirtualTileState.subTextureBuffer, - { - "Sub Texture Buffer", - CoreGraphics::PipelineStage::PixelShaderRead, - CoreGraphics::BufferSubresourceInfo() - }); - terrainPrepass->buildFunc = [](const CoreGraphics::PassId pass, uint subpass) + FrameScript_default::RegisterSubgraphPipelines_TerrainPrepass_Pass([](const CoreGraphics::PassId pass, uint subpass) { if (terrainVirtualTileState.terrainPrepassPipeline != InvalidPipelineId) DestroyGraphicsPipeline(terrainVirtualTileState.terrainPrepassPipeline); @@ -902,8 +857,9 @@ TerrainContext::Create(const TerrainSetupSettings& settings) .subpass = subpass, .inputAssembly = InputAssemblyKey{ { .topo = CoreGraphics::PrimitiveTopology::PatchList, .primRestart = false } } }); - }; - terrainPrepass->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }); + + FrameScript_default::RegisterSubgraph_TerrainPrepass_Pass([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { if (terrainState.renderToggle == false) return; @@ -941,12 +897,12 @@ TerrainContext::Create(const TerrainSetupSettings& settings) CmdSetIndexBuffer(cmdBuf, IndexType::Index32, rt.ibo, 0); CmdDraw(cmdBuf, terrainVirtualTileState.numPatchesThisFrame, group); } - }; - Frame::AddSubgraph("Terrain Prepass", { terrainPrepass }); + }, { + { FrameScript_default::BufferIndex::TerrainUpdateList, CoreGraphics::PipelineStage::PixelShaderWrite } + , { FrameScript_default::BufferIndex::TerrainSubTextures, CoreGraphics::PipelineStage::PixelShaderRead } + }); - Frame::FrameCode* terrainShadows = terrainState.frameOpAllocator.Alloc(); - terrainShadows->domain = CoreGraphics::BarrierDomain::Global; - terrainShadows->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_SunTerrainShadows_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { if (!terrainState.renderToggle) return; @@ -966,18 +922,9 @@ TerrainContext::Create(const TerrainSetupSettings& settings) // Dispatch uint x = Math::divandroundup(TerrainShadowMapSize, 64); CmdDispatch(cmdBuf, x, TerrainShadowMapSize, 1); - }; - Frame::AddSubgraph("Sun Terrain Shadows", { terrainShadows }); + }); - Frame::FrameCode* pageExtract = terrainState.frameOpAllocator.Alloc(); - pageExtract->domain = CoreGraphics::BarrierDomain::Global; - pageExtract->bufferDeps.Add(terrainVirtualTileState.pageUpdateListBuffer, - { - "Page Update List", - CoreGraphics::PipelineStage::TransferRead, - CoreGraphics::BufferSubresourceInfo() - }); - pageExtract->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_TerrainUpdateCaches_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CmdBeginMarker(cmdBuf, NEBULA_MARKER_TRANSFER, "Copy Pages to Readback"); CoreGraphics::BufferCopy from, to; @@ -989,17 +936,11 @@ TerrainContext::Create(const TerrainSetupSettings& settings) sizeof(Terrain::PageUpdateList) ); CmdEndMarker(cmdBuf); - }; + }, { + { FrameScript_default::BufferIndex::TerrainUpdateList, CoreGraphics::PipelineStage::TransferRead } + }); - Frame::FrameCode* pageClear = terrainState.frameOpAllocator.Alloc(); - pageClear->domain = CoreGraphics::BarrierDomain::Global; - pageClear->bufferDeps.Add(terrainVirtualTileState.pageUpdateListBuffer, - { - "Page Update List", - CoreGraphics::PipelineStage::ComputeShaderWrite, - CoreGraphics::BufferSubresourceInfo() - }); - pageClear->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_TerrainPagesClear_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CmdBeginMarker(cmdBuf, NEBULA_MARKER_COMPUTE, "Clear Page Status Buffer"); @@ -1011,29 +952,11 @@ TerrainContext::Create(const TerrainSetupSettings& settings) CmdDispatch(cmdBuf, numDispatches, 1, 1); CmdEndMarker(cmdBuf); - }; + }, { + { FrameScript_default::BufferIndex::TerrainUpdateList, CoreGraphics::PipelineStage::ComputeShaderWrite } + }); - Frame::FrameCode* cacheUpdate = terrainState.frameOpAllocator.Alloc(); - cacheUpdate->domain = CoreGraphics::BarrierDomain::Global; - cacheUpdate->textureDeps.Add(terrainVirtualTileState.physicalAlbedoCache, - { - "Terrain Albedo Cache", - CoreGraphics::PipelineStage::ColorWrite, - TextureSubresourceInfo::Color(terrainVirtualTileState.physicalAlbedoCache) - }); - cacheUpdate->textureDeps.Add(terrainVirtualTileState.physicalMaterialCache, - { - "Terrain Albedo Cache", - CoreGraphics::PipelineStage::ColorWrite, - TextureSubresourceInfo::Color(terrainVirtualTileState.physicalMaterialCache) - }); - cacheUpdate->textureDeps.Add(terrainVirtualTileState.physicalNormalCache, - { - "Terrain Albedo Cache", - CoreGraphics::PipelineStage::ColorWrite, - TextureSubresourceInfo::Color(terrainVirtualTileState.physicalNormalCache) - }); - cacheUpdate->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_TerrainUpdateCaches_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { if (terrainVirtualTileState.updateLowres) { @@ -1063,6 +986,7 @@ TerrainContext::Create(const TerrainSetupSettings& settings) // Update textures RenderUtil::DrawFullScreenQuad::ApplyMesh(cmdBuf); + CmdSetGraphicsPipeline(cmdBuf); CmdDraw(cmdBuf, RenderUtil::DrawFullScreenQuad::GetPrimitiveGroup()); CmdEndPass(cmdBuf); @@ -1107,6 +1031,7 @@ TerrainContext::Create(const TerrainSetupSettings& settings) // apply the mesh for all quads RenderUtil::DrawFullScreenQuad::ApplyMesh(cmdBuf); + CmdSetGraphicsPipeline(cmdBuf); CmdSetResourceTable(cmdBuf, PassGetResourceTable(terrainVirtualTileState.tileUpdatePass), NEBULA_PASS_GROUP, GraphicsPipeline, nullptr); CmdSetResourceTable(cmdBuf, terrainVirtualTileState.virtualTerrainSystemResourceTable.tables[bufferIndex], NEBULA_SYSTEM_GROUP, GraphicsPipeline, nullptr); Util::Array& runtimes = terrainAllocator.GetArray(); @@ -1144,36 +1069,13 @@ TerrainContext::Create(const TerrainSetupSettings& settings) CmdEndMarker(cmdBuf); } - }; - Frame::AddSubgraph("Terrain Update Caches", { pageExtract, cacheUpdate, pageClear }); - - Frame::FrameCode* resolve = terrainState.frameOpAllocator.Alloc(); - resolve->domain = CoreGraphics::BarrierDomain::Pass; - resolve->textureDeps.Add(terrainVirtualTileState.physicalAlbedoCache, - { - "Terrain Albedo Cache", - CoreGraphics::PipelineStage::PixelShaderRead, - TextureSubresourceInfo::Color(terrainVirtualTileState.physicalAlbedoCache) - }); - resolve->textureDeps.Add(terrainVirtualTileState.physicalMaterialCache, - { - "Terrain Albedo Cache", - CoreGraphics::PipelineStage::PixelShaderRead, - TextureSubresourceInfo::Color(terrainVirtualTileState.physicalMaterialCache) - }); - resolve->textureDeps.Add(terrainVirtualTileState.physicalNormalCache, - { - "Terrain Albedo Cache", - CoreGraphics::PipelineStage::PixelShaderRead, - TextureSubresourceInfo::Color(terrainVirtualTileState.physicalNormalCache) - }); - resolve->textureDeps.Add(terrainVirtualTileState.indirectionTexture, - { - "Indirection Texture", - CoreGraphics::PipelineStage::PixelShaderRead, - TextureSubresourceInfo::Color(terrainVirtualTileState.indirectionTexture) - }); - resolve->buildFunc = [](const CoreGraphics::PassId pass, uint subpass) + }, nullptr, { + { FrameScript_default::TextureIndex::TerrainAlbedoCache, CoreGraphics::PipelineStage::ColorWrite } + , { FrameScript_default::TextureIndex::TerrainMaterialCache, CoreGraphics::PipelineStage::ColorWrite } + , { FrameScript_default::TextureIndex::TerrainNormalCache, CoreGraphics::PipelineStage::ColorWrite } + }); + + FrameScript_default::RegisterSubgraphPipelines_TerrainResolve_Pass([](const CoreGraphics::PassId pass, uint subpass) { if (terrainVirtualTileState.terrainResolvePipeline != InvalidPipelineId) DestroyGraphicsPipeline(terrainVirtualTileState.terrainResolvePipeline); @@ -1184,8 +1086,8 @@ TerrainContext::Create(const TerrainSetupSettings& settings) .subpass = subpass, .inputAssembly = InputAssemblyKey{ { .topo = CoreGraphics::PrimitiveTopology::PatchList, .primRestart = false } } }); - }; - resolve->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }); + FrameScript_default::RegisterSubgraph_TerrainResolve_Pass([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CmdSetGraphicsPipeline(cmdBuf, terrainVirtualTileState.terrainResolvePipeline); CmdSetVertexLayout(cmdBuf, terrainState.vlo); @@ -1222,8 +1124,12 @@ TerrainContext::Create(const TerrainSetupSettings& settings) CmdSetIndexBuffer(cmdBuf, IndexType::Index32, rt.ibo, 0); CmdDraw(cmdBuf, terrainVirtualTileState.numPatchesThisFrame, group); } - }; - Frame::AddSubgraph("Terrain Resolve", { resolve }); + }, nullptr, { + { FrameScript_default::TextureIndex::TerrainAlbedoCache, CoreGraphics::PipelineStage::PixelShaderRead } + , { FrameScript_default::TextureIndex::TerrainMaterialCache, CoreGraphics::PipelineStage::PixelShaderRead } + , { FrameScript_default::TextureIndex::TerrainNormalCache, CoreGraphics::PipelineStage::PixelShaderRead } + , { FrameScript_default::TextureIndex::TerrainIndirection, CoreGraphics::PipelineStage::PixelShaderRead } + }); // create vlo terrainState.layers = 1; @@ -1925,8 +1831,8 @@ TerrainContext::CullPatches(const Ptr& view, const Graphics::Fra } } }, rt.sectionBoxes.Size(), 256, {}, & sectionCullDoneCounter, & sectionCullFinishedEvent); + CoreGraphics::BufferUnmap(terrainVirtualTileState.patchConstants.buffers[ctx.bufferIndex]); } - CoreGraphics::BufferUnmap(terrainVirtualTileState.patchConstants.buffers[ctx.bufferIndex]); if (runtimes.IsEmpty()) sectionCullFinishedEvent.Signal(); } @@ -2183,10 +2089,8 @@ TerrainContext::UpdateLOD(const Ptr& view, const Graphics::Frame terrainState.cachedSunDirection = sunTransform.z_axis; } - CoreGraphics::TextureId posBuffer = view->GetFrameScript()->GetTexture("TerrainPosBuffer"); - Terrain::TerrainSystemUniforms systemUniforms; - systemUniforms.TerrainPosBuffer = CoreGraphics::TextureGetBindlessHandle(posBuffer); + systemUniforms.TerrainPosBuffer = CoreGraphics::TextureGetBindlessHandle(FrameScript_default::Texture_TerrainPosBuffer()); systemUniforms.MinLODDistance = 0.0f; systemUniforms.MaxLODDistance = terrainState.mipLoadDistance; systemUniforms.VirtualLodDistance = terrainState.mipLoadDistance; @@ -2450,7 +2354,7 @@ TerrainContext::UpdateLOD(const Ptr& view, const Graphics::Frame uniforms.HeightMap = TextureGetBindlessHandle(CoreGraphics::TextureId(rt.heightMap)); CoreGraphics::TextureDimensions dims = CoreGraphics::TextureGetDimensions(rt.heightMap); - CoreGraphics::TextureDimensions dataBufferDims = CoreGraphics::TextureGetDimensions(posBuffer); + CoreGraphics::TextureDimensions dataBufferDims = CoreGraphics::TextureGetDimensions(FrameScript_default::Texture_TerrainPosBuffer()); uniforms.VirtualTerrainTextureSize[0] = dims.width; uniforms.VirtualTerrainTextureSize[1] = dims.height; uniforms.VirtualTerrainTextureSize[2] = 1.0f / dims.width; @@ -2590,7 +2494,6 @@ TerrainContext::RenderUI(const Graphics::FrameContext& ctx) textureInfo.mip = mip; textureInfo.layer = 0; - imageSize.x = ImGui::GetWindowContentRegionMax().x - ImGui::GetWindowContentRegionMin().x; float ratio = (float)dims.height / (float)dims.width; imageSize.y = imageSize.x * ratio; diff --git a/code/render/vegetation/vegetationcontext.cc b/code/render/vegetation/vegetationcontext.cc index 8664737562..2981046663 100644 --- a/code/render/vegetation/vegetationcontext.cc +++ b/code/render/vegetation/vegetationcontext.cc @@ -18,6 +18,8 @@ #include "models/nodes/primitivenode.h" #include "system_shaders/vegetation.h" + +#include "frame/default.h" namespace Vegetation { @@ -88,8 +90,6 @@ struct Vegetation::VegetationMaterialUniforms materialUniforms; CoreGraphics::BufferId materialUniformsBuffer; - Memory::ArenaAllocator frameOpAllocator; - } vegetationState; static const uint VegetationDistributionRadius = 128; @@ -410,82 +410,39 @@ VegetationContext::Create(const VegetationSetupSettings& settings) ResourceTableCommitChanges(vegetationState.indirectArgumentsTable[i]); } - Frame::FrameCode* clear = vegetationState.frameOpAllocator.Alloc(); - clear->domain = CoreGraphics::BarrierDomain::Global; - clear->queue = CoreGraphics::ComputeQueueType; - clear->bufferDeps.Add(vegetationState.drawCountBuffer, - { - "Draw Count Buffer", - CoreGraphics::PipelineStage::ComputeShaderWrite, - CoreGraphics::BufferSubresourceInfo() - }); - clear->bufferDeps.Add(vegetationState.grassDrawCallsBuffer, - { - "Grass Draw Buffer", - CoreGraphics::PipelineStage::ComputeShaderWrite, - CoreGraphics::BufferSubresourceInfo() - }); - clear->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::Bind_VegetationDrawCountBuffer(vegetationState.drawCountBuffer); + FrameScript_default::Bind_VegetationGrassArgumentsBuffer(vegetationState.grassArgumentsBuffer); + FrameScript_default::Bind_VegetationGrassDrawsBuffer(vegetationState.grassDrawCallsBuffer); + FrameScript_default::Bind_VegetationMeshArgumentsBuffer(vegetationState.meshArgumentsBuffer); + FrameScript_default::Bind_VegetationMeshDrawsBuffer(vegetationState.meshDrawCallsBuffer); + + FrameScript_default::RegisterSubgraph_VegetationClearDraws_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CmdSetShaderProgram(cmdBuf, vegetationState.vegetationClearShader); CmdSetResourceTable(cmdBuf, vegetationState.systemResourceTable, NEBULA_SYSTEM_GROUP, ComputePipeline, nullptr); CmdDispatch(cmdBuf, 1, 1, 1); - }; + }, { + { FrameScript_default::BufferIndex::VegetationDrawCountBuffer, CoreGraphics::PipelineStage::ComputeShaderWrite } + , { FrameScript_default::BufferIndex::VegetationGrassDrawsBuffer, CoreGraphics::PipelineStage::ComputeShaderWrite } + }); - Frame::FrameCode* drawGeneration = vegetationState.frameOpAllocator.Alloc(); - drawGeneration->domain = CoreGraphics::BarrierDomain::Global; - drawGeneration->queue = CoreGraphics::ComputeQueueType; - drawGeneration->bufferDeps.Add(vegetationState.grassDrawCallsBuffer, - { - "Grass Draw Buffer", - CoreGraphics::PipelineStage::ComputeShaderWrite, - CoreGraphics::BufferSubresourceInfo() - }); - drawGeneration->bufferDeps.Add(vegetationState.meshDrawCallsBuffer, - { - "Mesh Draw Buffer", - CoreGraphics::PipelineStage::ComputeShaderWrite, - CoreGraphics::BufferSubresourceInfo() - }); - drawGeneration->bufferDeps.Add(vegetationState.grassArgumentsBuffer, - { - "Grass Uniform Buffer", - CoreGraphics::PipelineStage::ComputeShaderWrite, - CoreGraphics::BufferSubresourceInfo() - }); - drawGeneration->bufferDeps.Add(vegetationState.meshArgumentsBuffer, - { - "Mesh Uniform Buffer", - CoreGraphics::PipelineStage::ComputeShaderWrite, - CoreGraphics::BufferSubresourceInfo() - }); - drawGeneration->bufferDeps.Add(vegetationState.drawCountBuffer, - { - "Draw Count Buffer", - CoreGraphics::PipelineStage::ComputeShaderWrite, - CoreGraphics::BufferSubresourceInfo() - }); - - drawGeneration->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + FrameScript_default::RegisterSubgraph_VegetationGenerateDraws_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CmdSetShaderProgram(cmdBuf, vegetationState.vegetationGenerateDrawsShader); CmdSetResourceTable(cmdBuf, vegetationState.systemResourceTable, NEBULA_SYSTEM_GROUP, ComputePipeline, nullptr); CmdSetResourceTable(cmdBuf, vegetationState.argumentsTable, NEBULA_BATCH_GROUP, ComputePipeline, nullptr); CmdDispatch(cmdBuf, VegetationDistributionRadius / 64, VegetationDistributionRadius, 1); - }; - - Frame::FrameCode* readBack = vegetationState.frameOpAllocator.Alloc(); - readBack->domain = CoreGraphics::BarrierDomain::Global; - readBack->queue = CoreGraphics::ComputeQueueType; - readBack->bufferDeps.Add(vegetationState.drawCountBuffer, - { - "Mesh Draw Buffer", - CoreGraphics::PipelineStage::TransferRead, - CoreGraphics::BufferSubresourceInfo() - }); - readBack->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }, { + { FrameScript_default::BufferIndex::VegetationGrassDrawsBuffer, CoreGraphics::PipelineStage::ComputeShaderWrite } + , { FrameScript_default::BufferIndex::VegetationMeshDrawsBuffer, CoreGraphics::PipelineStage::ComputeShaderWrite } + , { FrameScript_default::BufferIndex::VegetationGrassArgumentsBuffer, CoreGraphics::PipelineStage::ComputeShaderWrite } + , { FrameScript_default::BufferIndex::VegetationMeshArgumentsBuffer, CoreGraphics::PipelineStage::ComputeShaderWrite } + , { FrameScript_default::BufferIndex::VegetationDrawCountBuffer, CoreGraphics::PipelineStage::ComputeShaderWrite } + }); + + FrameScript_default::RegisterSubgraph_VegetationDrawCPUReadback_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CmdBarrier(cmdBuf, PipelineStage::HostRead, @@ -515,36 +472,11 @@ VegetationContext::Create(const VegetationSetupSettings& settings) CoreGraphics::BufferSubresourceInfo() }, }); - }; - Frame::AddSubgraph("Vegetation Generate Draws", { clear, drawGeneration, readBack }); - - Frame::FrameCode* prepass = vegetationState.frameOpAllocator.Alloc(); - prepass->domain = CoreGraphics::BarrierDomain::Pass; - prepass->bufferDeps.Add(vegetationState.grassDrawCallsBuffer, - { - "Grass Draw Buffer", - CoreGraphics::PipelineStage::Indirect, - CoreGraphics::BufferSubresourceInfo() - }); - prepass->bufferDeps.Add(vegetationState.meshDrawCallsBuffer, - { - "Mesh Draw Buffer", - CoreGraphics::PipelineStage::Indirect, - CoreGraphics::BufferSubresourceInfo() - }); - prepass->bufferDeps.Add(vegetationState.grassArgumentsBuffer, - { - "Grass Uniform Buffer", - CoreGraphics::PipelineStage::UniformGraphics, - CoreGraphics::BufferSubresourceInfo() - }); - prepass->bufferDeps.Add(vegetationState.meshArgumentsBuffer, - { - "Mesh Uniform Buffer", - CoreGraphics::PipelineStage::UniformGraphics, - CoreGraphics::BufferSubresourceInfo() - }); - prepass->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }, { + { FrameScript_default::BufferIndex::VegetationDrawCountBuffer, CoreGraphics::PipelineStage::TransferRead } + }); + + FrameScript_default::RegisterSubgraph_VegetationPrepass_Pass([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { if (vegetationState.grassDrawsThisFrame > 0) { @@ -590,36 +522,14 @@ VegetationContext::Create(const VegetationSetupSettings& settings) CmdDrawIndirectIndexed(cmdBuf, vegetationState.indirectMeshDrawCallsBuffer[bufferIndex], i * MAX_MESH_INFOS, vegetationState.meshDrawsThisFrame[i], sizeof(Vegetation::DrawIndexedCommand)); } } - }; - Frame::AddSubgraph("Vegetation Prepass", { prepass }); - - Frame::FrameCode* render = vegetationState.frameOpAllocator.Alloc(); - render->domain = CoreGraphics::BarrierDomain::Pass; - render->bufferDeps.Add(vegetationState.grassDrawCallsBuffer, - { - "Grass Draw Buffer", - CoreGraphics::PipelineStage::Indirect, - CoreGraphics::BufferSubresourceInfo() - }); - render->bufferDeps.Add(vegetationState.meshDrawCallsBuffer, - { - "Mesh Draw Buffer", - CoreGraphics::PipelineStage::Indirect, - CoreGraphics::BufferSubresourceInfo() - }); - render->bufferDeps.Add(vegetationState.grassArgumentsBuffer, - { - "Grass Uniform Buffer", - CoreGraphics::PipelineStage::UniformGraphics, - CoreGraphics::BufferSubresourceInfo() - }); - render->bufferDeps.Add(vegetationState.meshArgumentsBuffer, - { - "Mesh Uniform Buffer", - CoreGraphics::PipelineStage::UniformGraphics, - CoreGraphics::BufferSubresourceInfo() - }); - render->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }, { + { FrameScript_default::BufferIndex::VegetationGrassDrawsBuffer, CoreGraphics::PipelineStage::Indirect } + , { FrameScript_default::BufferIndex::VegetationMeshDrawsBuffer, CoreGraphics::PipelineStage::Indirect } + , { FrameScript_default::BufferIndex::VegetationGrassArgumentsBuffer, CoreGraphics::PipelineStage::Indirect } + , { FrameScript_default::BufferIndex::VegetationMeshArgumentsBuffer, CoreGraphics::PipelineStage::Indirect } + }); + + FrameScript_default::RegisterSubgraph_VegetationRender_Pass([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { if (vegetationState.grassDrawsThisFrame > 0) { @@ -665,13 +575,14 @@ VegetationContext::Create(const VegetationSetupSettings& settings) CmdDrawIndirectIndexed(cmdBuf, vegetationState.indirectMeshDrawCallsBuffer[bufferIndex], i * MAX_MESH_INFOS, vegetationState.meshDrawsThisFrame[i], sizeof(Vegetation::DrawIndexedCommand)); } } - }; - Frame::AddSubgraph("Vegetation Render", { render }); - - // Gah, we need to copy from the GPU to the indirect buffers after we render - Frame::FrameCode* copy = vegetationState.frameOpAllocator.Alloc(); - copy->domain = CoreGraphics::BarrierDomain::Global; - copy->func = [](const CoreGraphics::CmdBufferId cmdBuf, const IndexT frame, const IndexT bufferIndex) + }, { + { FrameScript_default::BufferIndex::VegetationGrassDrawsBuffer, CoreGraphics::PipelineStage::Indirect } + , { FrameScript_default::BufferIndex::VegetationMeshDrawsBuffer, CoreGraphics::PipelineStage::Indirect } + , { FrameScript_default::BufferIndex::VegetationGrassArgumentsBuffer, CoreGraphics::PipelineStage::Indirect } + , { FrameScript_default::BufferIndex::VegetationMeshArgumentsBuffer, CoreGraphics::PipelineStage::Indirect } + }); + + FrameScript_default::RegisterSubgraph_VegetationCopyIndirect_Compute([](const CoreGraphics::CmdBufferId cmdBuf, const Math::rectangle& viewport, const IndexT frame, const IndexT bufferIndex) { CoreGraphics::BufferCopy from, to; from.offset = 0; @@ -681,8 +592,7 @@ VegetationContext::Create(const VegetationSetupSettings& settings) CmdCopy(cmdBuf, vegetationState.meshArgumentsBuffer, { from }, vegetationState.indirectMeshArgumentsBuffer[bufferIndex], { to }, BufferGetByteSize(vegetationState.meshArgumentsBuffer)); CmdCopy(cmdBuf, vegetationState.meshDrawCallsBuffer, { from }, vegetationState.indirectMeshDrawCallsBuffer[bufferIndex], { to }, BufferGetByteSize(vegetationState.meshDrawCallsBuffer)); - }; - Frame::AddSubgraph("Vegetation Copy Indirect", { copy }); + }); } //------------------------------------------------------------------------------ diff --git a/code/render/visibility/visibilitycontext.cc b/code/render/visibility/visibilitycontext.cc index cfbd55c6f1..7a1629b385 100644 --- a/code/render/visibility/visibilitycontext.cc +++ b/code/render/visibility/visibilitycontext.cc @@ -353,16 +353,15 @@ ObserverContext::RunVisibilityTests(const Graphics::FrameContext& ctx) // update packet and add to list Models::ShaderStateNode::DrawPacket* packet = reinterpret_cast(mem); - packet->numOffsets[0] = renderables->nodeStates[index].resourceTableOffsets.Size(); - packet->numTables = 1; - packet->tables[0] = renderables->nodeStates[index].resourceTables[CoreGraphics::GetBufferedFrameIndex()]; + packet->numOffsets = renderables->nodeStates[index].resourceTableOffsets.Size(); + packet->table = renderables->nodeStates[index].resourceTables[CoreGraphics::GetBufferedFrameIndex()]; packet->materialInstance = renderables->nodeStates[index].materialInstance; #ifndef PUBLIC_BUILD packet->boundingBox = renderables->nodeBoundingBoxes[index]; packet->nodeInstanceHash = index; #endif - memcpy(packet->offsets[0], renderables->nodeStates[index].resourceTableOffsets.Begin(), renderables->nodeStates[index].resourceTableOffsets.ByteSize()); - packet->slots[0] = NEBULA_DYNAMIC_OFFSET_GROUP; + memcpy(packet->offsets, renderables->nodeStates[index].resourceTableOffsets.Begin(), renderables->nodeStates[index].resourceTableOffsets.ByteSize()); + packet->slot = NEBULA_DYNAMIC_OFFSET_GROUP; drawList->drawPackets.Append(packet); cmd->numDrawPackets++; numDraws++; diff --git a/fips-files/generators/framescriptc.py b/fips-files/generators/framescriptc.py new file mode 100644 index 0000000000..d71ca845db --- /dev/null +++ b/fips-files/generators/framescriptc.py @@ -0,0 +1,1476 @@ +import os, platform, sys +import sjson +import ntpath +import argparse +from pathlib import Path +Version = 1 + +import sys +if __name__ == '__main__': + sys.path.insert(0,'../fips/generators') + sys.path.insert(0,'../../../fips/generators') + +import genutil as util +import IDLC +import IDLC.filewriter + +def Error(object, msg): + print('[Frame Script Compiler] error({}): {}'.format(object, msg)) + sys.exit(-1) + +def Warning(object, msg): + print('[Frame Script Compiler] warning({}): {}'.format(object, msg)) + +def Assert(cond, object, msg): + if not cond: + Error(object, msg) + +class TextureImportDefinition: + def __init__(self, parser, name): + self.name = name.replace(" ", "") + + def FormatHeader(self, file): + file.WriteLine("void Bind_{}(const Frame::TextureImport& imp);".format(self.name)) + + def FormatSource(self, file): + file.WriteLine("") + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("void") + file.WriteLine("Bind_{}(const Frame::TextureImport& imp)".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("Textures[(uint)TextureIndex::{}] = imp.tex;".format(self.name)) + file.WriteLine("TextureCurrentStage[(uint)TextureIndex::{}] = imp.stage;".format(self.name)) + file.WriteLine("TextureOriginalStage[(uint)TextureIndex::{}] = imp.stage;".format(self.name)) + file.WriteLine("TextureImageBits[(uint)TextureIndex::{}] = CoreGraphics::PixelFormat::ToImageBits(CoreGraphics::TextureGetPixelFormat(imp.tex));".format(self.name)) + file.DecreaseIndent() + file.WriteLine("}") + + def FormatAssign(self): + pass + +class BufferImportDefinition: + def __init__(self, parser, name): + self.name = name.replace(" ", "") + + def FormatHeader(self, file): + file.WriteLine("void Bind_{}(const CoreGraphics::BufferId id);".format(self.name)) + + def FormatSource(self, file): + file.WriteLine("") + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("void") + file.WriteLine("Bind_{}(const CoreGraphics::BufferId id)".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("Buffers[(uint)BufferIndex::{}] = id;".format(self.name)) + file.DecreaseIndent() + file.WriteLine("}") + + def FormatAssign(self): + pass + +class TextureExportDefinition: + def __init__(self, parser, name): + self.name = name.replace(" ", "") + parser.externs.append(self) + + def FormatExtern(self, file): + file.WriteLine("Frame::TextureExport Export_{};".format(self.name)) + + def FormatHeader(self, file): + file.WriteLine("extern Frame::TextureExport Export_{};".format(self.name)) + + def FormatSource(self, file): + file.WriteLine("Frame::TextureExport Export_{} = {{ .index = (uint)TextureIndex::{}, .tex = Textures[(uint)TextureIndex::{}], .stage = TextureCurrentStage[(uint)TextureIndex::{}] }};".format(self.name, self.name, self.name, self.name)) + +class DependencyDefinition: + def __init__(self, parser, name): + self.name = name.replace(" ", "") + + def FormatHeader(self, file): + file.WriteLine("void Bind_{}(const CoreGraphics::SubmissionWaitEvent event);".format(self.name)) + + def FormatSource(self, file): + + file.WriteLine("") + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("CoreGraphics::SubmissionWaitEvent Submission_{};".format(self.name)) + file.WriteLine("void") + file.WriteLine("Bind_{}(const CoreGraphics::SubmissionWaitEvent event)".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("Submission_{} = event;".format(self.name)) + file.DecreaseIndent() + file.WriteLine("}") + + def FormatAssign(self): + return "Submission_{} = Import_{};".format(self.name, self.name) + +class LocalTextureDefinition: + def __init__(self, parser, node): + self.name = node["name"].replace(" ", "") + self.fixedSize = None + self.relativeSize = None + self.depthFormat = False + self.stencilFormat = False + self.bits = list() + + if 'fixedSize' in node: + self.fixedSize = node['fixedSize'] + elif 'relativeSize' in node: + self.relativeSize = node['relativeSize'] + else: + Error(self.name, "Does not specify any size, please define either fixedSize or relativeSize") + self.mips = 1 + self.layers = 1 + if 'mips' in node: + self.mips = node['mips'] + if 'layers' in node: + self.layers = node['layers'] + + if 'format' not in node: + Error(self.name, 'Local texture must declare format') + self.format = node['format'] + if self.format in parser.depthFormats: + self.depthFormat = True + self.bits.append("DepthBits") + if self.format in parser.stencilFormats: + self.stencilFormat = True + self.bits.append("StencilBits") + if len(self.bits) == 0: + self.bits.append("ColorBits") + + if 'usage' in node: + self.usage = node['usage'] + else: + self.usage = 'Render' + + usageBits = self.usage.split("|") + self.usage = "" + for bit in usageBits: + self.usage += "CoreGraphics::TextureUsage::{}Texture".format(bit) + if bit != usageBits[-1]: + self.usage += " | " + + if 'type' in node: + self.type = node['type'] + else: + self.type = 'Texture2D' + + def HasDepthFormat(self): + return self.depthFormat + + def HasStencilFormat(self): + return self.depthFormat + + def FormatHeader(self, file): + pass + + def FormatSource(self, file): + file.WriteLine("") + if self.relativeSize: + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("void") + file.WriteLine("Initialize_Texture_{}(const uint frameWidth, const uint frameHeight)".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("if (Textures[(uint)TextureIndex::{}] != CoreGraphics::InvalidTextureId)".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("CoreGraphics::DestroyTexture(Textures[(uint)TextureIndex::{}]);".format(self.name)) + file.DecreaseIndent() + file.WriteLine("}") + file.WriteLine("CoreGraphics::TextureCreateInfo info;") + file.WriteLine('info.name = "{}";'.format(self.name)) + file.WriteLine("info.type = CoreGraphics::{};".format(self.type)) + file.WriteLine("info.format = CoreGraphics::PixelFormat::Code::{};".format(self.format)) + file.WriteLine("info.width = {} * frameWidth;".format(self.relativeSize[0])) + file.WriteLine("info.height = {} * frameHeight;".format(self.relativeSize[1])) + file.WriteLine("info.usage = {};".format(self.usage)) + file.WriteLine("info.mips = {};".format("CoreGraphics::TextureAutoMips" if self.mips == "auto" else self.mips)) + file.WriteLine("info.layers = {};".format(self.layers)) + file.WriteLine("Textures[(uint)TextureIndex::{}] = CoreGraphics::CreateTexture(info);".format(self.name)) + file.WriteLine("TextureImageBits[(uint)TextureIndex::{}] = CoreGraphics::PixelFormat::ToImageBits(info.format);".format(self.name, self.name)) + file.WriteLine("TextureCurrentStage[(uint)TextureIndex::{}] = CoreGraphics::PipelineStage::InvalidStage;".format(self.name)) + file.WriteLine("TextureRelativeScale[(uint)TextureIndex::{}] = {{ {}, {} }};".format(self.name, self.relativeSize[0], self.relativeSize[1])) + file.WriteLine("TextureRelativeSize[(uint)TextureIndex::{}] = {{ {} * frameWidth, {} * frameHeight }};".format(self.name, self.relativeSize[0], self.relativeSize[1])) + file.DecreaseIndent() + file.WriteLine("}") + else: + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("void") + file.WriteLine("Initialize_Texture_{}()".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("if (Textures[(uint)TextureIndex::{}] != CoreGraphics::InvalidTextureId)".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("CoreGraphics::DestroyTexture(Textures[(uint)TextureIndex::{}]);".format(self.name)) + file.DecreaseIndent() + file.WriteLine("}") + file.WriteLine("CoreGraphics::TextureCreateInfo info;") + file.WriteLine('info.name = "{}";'.format(self.name)) + file.WriteLine("info.type = CoreGraphics::{};".format(self.type)) + file.WriteLine("info.format = CoreGraphics::PixelFormat::Code::{};".format(self.format)) + file.WriteLine("info.width = {};".format(self.fixedSize[0])) + file.WriteLine("info.height = {};".format(self.fixedSize[1])) + file.WriteLine("info.usage = {};".format(self.usage)) + file.WriteLine("info.mips = {};".format("TextureAutoMips" if self.mips == "auto" else self.mips)) + file.WriteLine("info.layers = {};".format(self.layers)) + file.WriteLine("Textures[(uint)TextureIndex::{}] = CoreGraphics::CreateTexture(info);".format(self.name)) + file.WriteLine("TextureImageBits[(uint)TextureIndex::{}] = CoreGraphics::PixelFormat::ToImageBits(info.format);".format(self.name, self.name)) + file.DecreaseIndent() + file.WriteLine("}") + +class ResourceDependencyDefinition: + def __init__(self, parser, node): + self.name = node['name'] + self.stage = node['stage'] + + @classmethod + def raw(self, name, stage): + return self(None, dict(name = name, stage = stage)) + +class SubgraphDefinition: + def __init__(self, parser, node, p, subp): + self.name = "{}_{}".format(node['name'].replace(" ", ""), "Pass" if p is not None else "Compute") + self.disabledBindings = list() + self.p = p + self.subp = subp + if "disabled" in node: + for binding in node['disabled']: + self.disabledBindings.append(dict(name = binding['name'], value = binding['value'])) + + parser.externs.append(self) + + if self.p is not None and self.subp is not None: + parser.pipelines.append(self) + + def FormatExtern(self, file): + file.WriteLine("") + if len(self.disabledBindings) > 0: + file.WriteLine("bool SubgraphEnabled_{};".format(self.name)) + file.WriteLine('Util::Array> SubgraphTextureDependencies_{};'.format(self.name)) + file.WriteLine('Util::Array> SubgraphBufferDependencies_{};'.format(self.name)) + file.WriteLine("void (*Subgraph_{})(const CoreGraphics::CmdBufferId, const Math::rectangle& viewport, const IndexT, const IndexT);\n".format(self.name)) + file.WriteLine("void (*SubgraphPipelines_{})(const CoreGraphics::PassId, const uint);\n".format(self.name)) + + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine('void') + file.WriteLine('RegisterSubgraph_{}(void(*func)(const CoreGraphics::CmdBufferId, const Math::rectangle& viewport, const IndexT, const IndexT), Util::Array> bufferDeps, Util::Array> textureDeps)'.format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("Subgraph_{} = func;".format(self.name)) + file.WriteLine("SubgraphTextureDependencies_{} = textureDeps;".format(self.name)) + file.WriteLine("SubgraphBufferDependencies_{} = bufferDeps;".format(self.name)) + file.DecreaseIndent() + file.WriteLine("}") + + if self.p is not None and self.subp is not None: + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine('void') + file.WriteLine('RegisterSubgraphPipelines_{}(void(*func)(const CoreGraphics::PassId, const uint))'.format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("SubgraphPipelines_{} = func;".format(self.name)) + file.DecreaseIndent() + file.WriteLine("}") + + def FormatPipeline(self, file): + file.WriteLine("") + file.WriteLine("if (SubgraphPipelines_{} != nullptr)".format(self.name)) + file.IncreaseIndent() + file.WriteLine("SubgraphPipelines_{}(Pass_{}, {});".format(self.name, self.p.name, self.subp.index)) + file.DecreaseIndent() + file.WriteLine("else") + file.IncreaseIndent() + file.WriteLine('n_warning("No registered pipeline creation callback is registered for {}\\n");'.format(self.name)) + file.DecreaseIndent() + + def FormatHeader(self, file): + if self.p is not None and self.subp is not None: + file.WriteLine('void RegisterSubgraphPipelines_{}(void(*func)(const CoreGraphics::PassId, const uint));'.format(self.name)) + file.WriteLine('void RegisterSubgraph_{}(void(*func)(const CoreGraphics::CmdBufferId, const Math::rectangle& viewport, const IndexT, const IndexT), Util::Array> bufferDeps = nullptr, Util::Array> textureDeps = nullptr);'.format(self.name)) + + def FormatSource(self, file): + file.WriteLine("") + file.WriteLine("if (Subgraph_{} != nullptr)".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + + file.WriteLine('CoreGraphics::CmdBeginMarker(cmdBuf, NEBULA_MARKER_ORANGE, "{}");'.format(self.name)) + file.IncreaseIndent() + if self.subp == None: + file.WriteLine('Synchronize("Subgraph_{}_Sync", cmdBuf, SubgraphTextureDependencies_{}, SubgraphBufferDependencies_{});'.format(self.name, self.name, self.name)) + file.WriteLine('Subgraph_{}(cmdBuf, viewport, frameIndex, bufferIndex);'.format(self.name)) + file.DecreaseIndent() + file.WriteLine('CoreGraphics::CmdEndMarker(cmdBuf);') + + file.DecreaseIndent() + file.WriteLine("}") + + def FormatSetup(self, file): + pass + +class BatchDefinition: + def __init__(self, parser, node): + self.name = node['name'].replace(" ", "") + + def FormatHeader(self, file): + pass + + def FormatSource(self, file): + file.WriteLine("Frame::DrawBatch(cmdBuf, MaterialTemplates::BatchGroup::{}, view->GetCamera(), bufferIndex);".format(self.name)) + + def FormatSetup(self, file): + pass + +class FullscreenEffectDefinition: + def __init__(self, parser, node, p): + self.name = node['name'].replace(" ", "") + self.shader = node['shader'] + self.mask = node['mask'] + self.constantBlockName = node['constantBlockName'] + self.namespace = node['namespace'] + self.variables = list() + for var in node['variables']: + self.variables.append(dict(name = var['semantic'], value = var['value'], type = var['type'])) + self.p = p + parser.externs.append(self) + + def FormatHeader(self, file): + pass + + def FormatSource(self, file): + file.WriteLine("CoreGraphics::CmdSetGraphicsPipeline(cmdBuf, FullScreenEffect_{}_Pipeline);".format(self.name)) + file.WriteLine("CoreGraphics::CmdSetResourceTable(cmdBuf, FullScreenEffect_{}_ResourceTable, NEBULA_BATCH_GROUP, CoreGraphics::GraphicsPipeline, nullptr);".format(self.name)) + file.WriteLine("RenderUtil::DrawFullScreenQuad::ApplyMesh(cmdBuf);") + file.WriteLine("CoreGraphics::CmdDraw(cmdBuf, RenderUtil::DrawFullScreenQuad::GetPrimitiveGroup());") + + def FormatExtern(self, file): + file.WriteLine("") + file.WriteLine('#include "{}.h"'.format(self.shader)) + file.WriteLine("CoreGraphics::PipelineId FullScreenEffect_{}_Pipeline;".format(self.name)) + file.WriteLine("CoreGraphics::BufferId FullScreenEffect_{}_Constants;".format(self.name)) + file.WriteLine("CoreGraphics::ResourceTableId FullScreenEffect_{}_ResourceTable;".format(self.name)) + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("void") + file.WriteLine("Initialize_FullscreenEffect_{}()".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + + file.WriteLine('CoreGraphics::ShaderId shad = CoreGraphics::ShaderGet("shd:{}.fxb");'.format(self.shader)) + file.WriteLine('CoreGraphics::ShaderProgramId prog = CoreGraphics::ShaderGetProgram(shad, CoreGraphics::ShaderFeatureMask("{}"));'.format(self.mask)) + file.WriteLine("FullScreenEffect_{}_Pipeline = CoreGraphics::CreateGraphicsPipeline({{prog, Pass_{}, 0, CoreGraphics::InputAssemblyKey{{ CoreGraphics::PrimitiveTopology::TriangleList, false}} }});".format(self.name, self.p.name)) + file.WriteLine('FullScreenEffect_{}_ResourceTable = CoreGraphics::ShaderCreateResourceTable(shad, NEBULA_BATCH_GROUP, 1);'.format(self.name)) + file.WriteLine('{}::{} state;'.format(self.namespace, self.constantBlockName)) + for var in self.variables: + type = var['type'] + if type == "textureHandle": + file.WriteLine('state.{} = CoreGraphics::TextureGetBindlessHandle(Textures[(uint)TextureIndex::{}]);'.format(var['name'], var['value'])) + elif type == "texture": + file.WriteLine('CoreGraphics::ResourceTableSetTexture(FullScreenEffect_Finalize_ResourceTable, CoreGraphics::ResourceTableTexture(Textures[(uint)TextureIndex::{}], {}::Table_Batch::{}_SLOT));'.format(var['value'], self.namespace, var['name'])) + else: + file.WriteLine('state.{} = {};'.format(var['name'], var['value'])) + file.WriteLine('CoreGraphics::BufferCreateInfo bufInfo;') + file.WriteLine('bufInfo.name = "FullscreenEffect_{}_Constants";'.format(self.name)) + file.WriteLine('bufInfo.byteSize = sizeof({}::{});'.format(self.namespace, self.constantBlockName)) + file.WriteLine('bufInfo.data = &state;') + file.WriteLine('bufInfo.dataSize = bufInfo.byteSize;') + file.WriteLine('bufInfo.mode = CoreGraphics::HostLocal;') + file.WriteLine('bufInfo.usageFlags = CoreGraphics::ConstantBuffer;') + file.WriteLine('bufInfo.queueSupport = CoreGraphics::GraphicsQueueSupport;') + file.WriteLine('FullScreenEffect_{}_Constants = CoreGraphics::CreateBuffer(bufInfo);'.format(self.name)) + file.WriteLine('CoreGraphics::ResourceTableSetConstantBuffer(FullScreenEffect_{}_ResourceTable, CoreGraphics::ResourceTableBuffer(FullScreenEffect_{}_Constants, Finalize::Table_Batch::{}_SLOT));'.format(self.name, self.name, self.constantBlockName)) + file.WriteLine('CoreGraphics::ResourceTableCommitChanges(FullScreenEffect_{}_ResourceTable);'.format(self.name)) + file.DecreaseIndent() + file.WriteLine("}") + + def FormatSetup(self, file): + file.WriteLine("Initialize_FullscreenEffect_{}();".format(self.name)) + +class CopyDefinition: + def __init__(self, parser, node): + self.name = node['name'].replace(" ", "") + self.sourceTex = "" + self.sourceBits = "" + self.destTex = "" + self.destBits = "" + parser.externs.append(self) + + if not "from" in node: + Error(self.name, "Must define a 'from' source") + source = node['from'] + if not 'tex' in source: + Error(self.name, "Texture source must define a texture resource") + if not 'bits' in source: + Error(self.name, "Texture source must define image bits") + + self.sourceTex = source['tex'] + self.sourceBits = source['bits'] + + if not "to" in node: + Error(self.name, "copy must define a 'to' source") + dest = node['to'] + if not 'tex' in dest: + Error(self.name, "Texture destination must define a texture resource") + if not 'bits' in dest: + Error(self.name, "Texture source must define image bits") + + self.destTex = dest['tex'] + self.destBits = dest['bits'] + + def FormatHeader(self, file): + file.WriteLine("void Copy_{}(const CoreGraphics::CmdBufferId cmdBuf);".format(self.name)) + + def FormatExtern(self, file): + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("void") + file.WriteLine("Copy_{}(const CoreGraphics::CmdBufferId cmdBuf)".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("CoreGraphics::TextureDimensions fromDims = CoreGraphics::TextureGetDimensions(Textures[TextureIndex::{}]);".format(self.sourceTex)) + file.WriteLine("CoreGraphics::TextureDimensions toDims = CoreGraphics::TextureGetDimensions(Textures[TextureIndex::{}]);".format(self.destTex)) + file.WriteLine("CoreGraphics::TextureCopy from {{.region = {{0, 0, fromDims.width, fromDims.height}}, .mip = 0, .layer = 0, .bits = CoreGraphics::ImageBits::{}}};".format(self.sourceBits)) + file.WriteLine("CoreGraphics::TextureCopy to {{.region = {{0, 0, toDims.width, toDims.height}}, .mip = 0, .layer = 0, .bits = CoreGraphics::ImageBits::{}}};".format(self.destBits)) + file.WriteLine("CoreGraphics::CmdCopy(cmdBuf, Textures[TextureIndex::{}], {{from}}, Textures[TextureIndex::{}], {{to}});".format(self.sourceTex, self.destTex)) + file.DecreaseIndent() + file.WriteLine("}") + + def FormatSource(self, file): + file.WriteLine("Copy_{}(cmdBuf);".format(self.name)) + + def FormatSetup(self, file): + pass + +class BlitDefinition: + def __init__(self, parser, node): + self.name = node['name'].replace(" ", "") + self.sourceTex = "" + self.sourceBits = "" + self.destTex = "" + self.destBits = "" + + parser.externs.append(self) + if not "from" in node: + Error(self.name, "Must define a 'from' source") + source = node['from'] + if not 'tex' in source: + Error(self.name, "Texture source must define a texture resource") + + self.sourceTex = source['tex'] + + if not 'bits' in source: + self.sourceBits = "ColorBits" + else: + self.sourceBits = source['bits'] + + if not "to" in node: + Error(self.name, "copy must define a 'to' source") + dest = node['to'] + if not 'tex' in dest: + Error(self.name, "Texture destination must define a texture resource") + + self.destTex = dest['tex'] + + if not 'bits' in dest: + self.destBits = "ColorBits" + else: + self.destBits = dest['bits'] + + self.resourceDependencies = [ + ResourceDependencyDefinition.raw(name = self.sourceTex, stage = "TransferRead"), + ResourceDependencyDefinition.raw(name = self.destTex, stage = "TransferWrite") + ] + + def FormatHeader(self, file): + pass + + def FormatExtern(self, file): + file.WriteLine("") + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + + if len(self.resourceDependencies) > 0: + file.WriteLine("Util::Array> Blit_{}_TextureDependencies;".format(self.name)) + + file.WriteLine("void") + file.WriteLine("Initialize_Blit_{}()".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + if len(self.resourceDependencies) > 0: + file.WriteLine("Blit_{}_TextureDependencies.Clear();".format(self.name)) + for dep in self.resourceDependencies: + file.WriteLine('Blit_{}_TextureDependencies.Append({{ TextureIndex::{}, CoreGraphics::PipelineStage::{} }});'.format(self.name, dep.name, dep.stage)) + file.DecreaseIndent() + file.WriteLine("}") + + file.WriteLine("") + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("void") + file.WriteLine("Blit_{}(const CoreGraphics::CmdBufferId cmdBuf)".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("CoreGraphics::TextureDimensions fromDims = CoreGraphics::TextureGetDimensions(Textures[(uint)TextureIndex::{}]);".format(self.sourceTex)) + file.WriteLine("CoreGraphics::TextureDimensions toDims = CoreGraphics::TextureGetDimensions(Textures[(uint)TextureIndex::{}]);".format(self.destTex)) + file.WriteLine("CoreGraphics::TextureCopy from {{.region = {{0, 0, fromDims.width, fromDims.height}}, .mip = 0, .layer = 0, .bits = CoreGraphics::ImageBits::{}}};".format(self.sourceBits)) + file.WriteLine("CoreGraphics::TextureCopy to {{.region = {{0, 0, toDims.width, toDims.height}}, .mip = 0, .layer = 0, .bits = CoreGraphics::ImageBits::{}}};".format(self.destBits)) + file.WriteLine('N_CMD_SCOPE(cmdBuf, NEBULA_MARKER_TRANSFER, "{}");'.format(self.name)) + file.WriteLine("CoreGraphics::CmdBlit(cmdBuf, Textures[(uint)TextureIndex::{}], from, Textures[(uint)TextureIndex::{}], to);".format(self.sourceTex, self.destTex)) + file.DecreaseIndent() + file.WriteLine("}") + + def FormatSource(self, file): + file.WriteLine('Synchronize("Blit_{}_Sync", cmdBuf, Blit_{}_TextureDependencies, nullptr);'.format(self.name, self.name)) + file.WriteLine("Blit_{}(cmdBuf);".format(self.name)) + + def FormatSetup(self, file): + file.WriteLine("Initialize_Blit_{}();".format(self.name)) + +class ResolveDefinition: + def __init__(self, parser, node): + self.name = node['name'].replace(" ", "") + self.sourceTex = "" + self.sourceBits = "" + self.destTex = "" + self.destBits = "" + parser.externs.append(self) + if not "from" in node: + Error(self.name, "Must define a 'from' source") + source = node['from'] + if not 'tex' in source: + Error(self.name, "Texture source must define a texture resource") + + self.sourceTex = source['tex'] + + if not 'bits' in source: + self.sourceBits = "ColorBits" + else: + self.sourceBits = source['bits'] + + if not "to" in node: + Error(self.name, "copy must define a 'to' source") + dest = node['to'] + if not 'tex' in dest: + Error(self.name, "Texture destination must define a texture resource") + + self.destTex = dest['tex'] + + if not 'bits' in dest: + self.destBits = "ColorBits" + else: + self.destBits = dest['bits'] + + def FormatHeader(self, file): + pass + + def FormatExtern(self, file): + + file.WriteLine("") + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("void") + file.WriteLine("Resolve_{}(const CoreGraphics::CmdBufferId cmdBuf)".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("CoreGraphics::TextureDimensions fromDims = CoreGraphics::TextureGetDimensions(Textures[(uint)TextureIndex::{}]);".format(self.sourceTex)) + file.WriteLine("CoreGraphics::TextureDimensions toDims = CoreGraphics::TextureGetDimensions(Textures[(uint)TextureIndex::{}]);".format(self.destTex)) + file.WriteLine("CoreGraphics::TextureCopy from {{.region = {{0, 0, fromDims.width, fromDims.height}}, .mip = 0, .layer = 0, .bits = CoreGraphics::ImageBits::{}}};".format(self.sourceBits)) + file.WriteLine("CoreGraphics::TextureCopy to {{.region = {{0, 0, toDims.width, toDims.height}}, .mip = 0, .layer = 0, .bits = CoreGraphics::ImageBits::{}}};".format(self.destBits)) + file.WriteLine("CoreGraphics::CmdResolve(cmdBuf, Textures[(uint)TextureIndex::{}], from, Textures[(uint)TextureIndex::{}], to);".format(self.sourceTex, self.sourceBits, self.destTex, self.destBits)) + file.DecreaseIndent() + file.WriteLine("}") + + def FormatSource(self, file): + file.WriteLine("Blit_{}(cmdBuf);".format(self.name)) + +class SwapDefinition: + def __init__(self, parser, node): + self.name = node['name'].replace(" ", "") + self.source = node['from'] + parser.externs.append(self) + + self.resourceDependencies = [ + ResourceDependencyDefinition.raw(name = self.source, stage = "TransferRead"), + ] + + def FormatHeader(self, file): + pass + + def FormatExtern(self, file): + file.WriteLine("") + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + + if len(self.resourceDependencies) > 0: + file.WriteLine("Util::Array> Swap_{}_TextureDependencies;".format(self.name)) + + file.WriteLine("void") + file.WriteLine("Initialize_Swap_{}()".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + if len(self.resourceDependencies) > 0: + file.WriteLine("Swap_{}_TextureDependencies.Clear();".format(self.name)) + for dep in self.resourceDependencies: + file.WriteLine('Swap_{}_TextureDependencies.Append({{ TextureIndex::{}, CoreGraphics::PipelineStage::{} }});'.format(self.name, dep.name, dep.stage)) + file.DecreaseIndent() + file.WriteLine("}") + + def FormatSource(self, file): + file.WriteLine('CoreGraphics::QueueBeginMarker(CoreGraphics::GraphicsQueueType, NEBULA_MARKER_GRAPHICS, "Swap");') + file.WriteLine('CoreGraphics::SwapchainId swapchain = WindowGetSwapchain(CoreGraphics::CurrentWindow);') + file.WriteLine('CoreGraphics::SwapchainSwap(swapchain);') + file.WriteLine('Synchronize("Swap_{}_Sync", cmdBuf, Swap_{}_TextureDependencies, nullptr);'.format(self.name, self.name)) + file.WriteLine('CoreGraphics::SwapchainCopy(swapchain, cmdBuf, Textures[(uint)TextureIndex::{}]);'.format(self.source)) + file.WriteLine('CoreGraphics::QueueEndMarker(CoreGraphics::GraphicsQueueType);') + + def FormatSetup(self, file): + file.WriteLine("Initialize_Swap_{}();".format(self.name)) + +class TransitionDefinition: + def __init__(self, parser, node): + self.name = node['name'] + self.stage = node['stage'] + + def FormatHeader(self, file): + pass + + def FormatSetup(self, file): + pass + + def FormatSource(self, file): + file.WriteLine('Synchronize("Transition_{}", cmdBuf, {{ {{ TextureIndex::{}, CoreGraphics::PipelineStage::{} }} }}, nullptr);'.format(self.name, self.name, self.stage)) + + +class AttachmentDefinition: + def __init__(self, parser, node): + self.name = node['name'] + self.ref = None + self.clearColor = None + self.clearDepth = None + self.clearStencil = None + self.storeLoadFlags = list() + if self.name not in parser.localTextureDict: + Error(self.name, "Attachment references undeclared texture") + else: + self.ref = parser.localTextureDict[self.name] + + if "clear" in node: + self.clearColor = node['clear'] + if type(self.clearColor) is not list: + Error(self.name, "clear is not given as an array") + elif len(self.clearColor) != 4: + Error(self.name, "clear must be an array of 4 values") + if "clear_depth" in node: + self.clearDepth = node['clear_depth'] + if self.clearColor != None: + Error(self.name, "clear_depth is exclusive of clear") + if "clear_stencil" in node: + self.clearStencil = node['clear_stencil'] + if self.clearColor != None: + Error(self.name, "clear_stencil is exclusive of clear") + if "flags" in node: + storeLoadFlags = node['flags'] + for flag in storeLoadFlags.split("|"): + self.storeLoadFlags.append(flag) + if flag == "Load" and (self.clearColor is not None or self.clearDepth is not None): + Error(self.name, "Attachment can't both clear and load") + if flag == "LoadStencil" and self.clearStencil is not None: + Error(self.name, "Attachment can't both clear and load") + +class SubpassDefinition: + def __init__(self, parser, node, parent, idx): + self.name = node['name'].replace(" ", "") + self.dependencies = list() + self.index = idx + if 'resource_dependencies' in node: + for dependency in node['resource_dependencies']: + dep = ResourceDependencyDefinition(parser = parser, node = dependency) + parent.resourceDependencies.append(dep) + if 'subpass_dependencies' in node: + for dependency in node['subpass_dependencies']: + if dependency not in parent.subpassDict: + Error(self.name, "Depends on {} which is not defined".format(dependency)) + subpass_dep = parent.subpassDict[dependency] + for idx, subpass in enumerate(parent.subpasses): + if subpass.name == subpass_dep.name: + self.dependencies.append(dict(index = idx, name = subpass_dep.name)) + + self.attachments = list() + if 'attachments' in node: + for attachment in node['attachments']: + if attachment not in parent.attachmentDict: + Error(self.name, "References attachment {} which is not defined in Pass {}".format(self.name, parent.name)) + subpass_attach = parent.attachmentDict[attachment] + for idx, attachment in enumerate(parent.attachments): + if attachment.name == subpass_attach.name: + self.attachments.append(dict(index = idx, name = subpass_attach.name, ref = subpass_attach)) + + self.inputs = list() + if 'inputs' in node: + for inp in node['inputs']: + if inp not in parent.attachmentDict: + Error(self.name, "References input attachment {} which is not defined in Pass {}".format(self.name, parent.name)) + subpass_input = parent.attachmentDict[inp] + for idx, attachment in enumerate(parent.attachments): + if attachment.name == subpass_input.name: + self.inputs.append(dict(index = idx, name = subpass_input.name)) + + self.resolves = list() + if 'resolves' in node: + for res in node['resolves']: + if res not in parent.attachmentDict: + Error(self.name, "References resolve attachment {} which is not defined in Pass {}".format(self.name, parent.name)) + subpass_resolve = parent.attachmentDict[res] + for idx, attachment in enumerate(parent.attachments): + if attachment.name == subpass_resolve.name: + self.inputs.append(dict(index = idx, name = subpass_resolve.name)) + + self.depth = None + if 'depth' in node: + depth = node['depth'] + if depth not in parent.attachmentDict: + Error(self.name, "References depth attachment {} which is not defined in Pass {}".format(self.name, parent.name)) + subpass_depth = parent.attachmentDict[depth] + for idx, attachment in enumerate(parent.attachments): + if attachment.name == subpass_depth.name: + self.depth = dict(index = idx, name = subpass_depth.name, ref = subpass_depth) + + self.ops = list() + for op in node["ops"]: + if 'subgraph' in op: + self.ops.append(SubgraphDefinition(parser, op['subgraph'], parent, self)) + elif 'batch' in op: + self.ops.append(BatchDefinition(parser, op['batch'])) + elif 'fullscreen_effect' in op: + self.ops.append(FullscreenEffectDefinition(parser, op['fullscreen_effect'], parent)) + + + def FormatHeader(self, file): + numAttachments = len(self.attachments) + (1 if self.depth != None else 0) + file.WriteLine('static Util::FixedArray> Subpass_{}_Viewports({});'.format(self.name, numAttachments)) + for op in self.ops: + op.FormatHeader(file) + + def FormatSource(self, file): + file.IncreaseIndent() + file.WriteLine("// Subpass {}".format(self.name)) + for op in self.ops: + op.FormatSource(file) + file.DecreaseIndent() + + def FormatSetup(self, file): + for op in self.ops: + op.FormatSetup(file) + +class PassDefinition: + def __init__(self, parser, node): + self.name = node['name'].replace(" ", "") + self.attachments = list() + self.attachmentDict = {} + self.resourceDependencies = list() + parser.externs.append(self) + parser.passes.append(self) + for at in node["attachments"]: + attachment = AttachmentDefinition(parser, at) + self.attachments.append(attachment) + self.attachmentDict[attachment.name] = attachment + self.resourceDependencies.append(ResourceDependencyDefinition.raw(name = attachment.name, stage = "DepthStencilWrite" if attachment.ref.HasDepthFormat() or attachment.ref.HasStencilFormat() else "ColorWrite")) + + self.subpasses = list() + self.subpassDict = {} + for sub in node["subpasses"]: + subpass = SubpassDefinition(parser, sub, self, len(self.subpasses)) + self.subpasses.append(subpass) + self.subpassDict[subpass.name] = subpass + + def FormatExtern(self, file): + + file.WriteLine("") + file.WriteLine('CoreGraphics::PassId Pass_{} = CoreGraphics::InvalidPassId;'.format(self.name)) + + + if len(self.resourceDependencies) > 0: + file.WriteLine("Util::Array> Pass_{}_TextureDependencies;".format(self.name)) + + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("void") + file.WriteLine("Initialize_Pass_{}()".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("if (Pass_{} != CoreGraphics::InvalidPassId)".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("CoreGraphics::DestroyPass(Pass_{});".format(self.name)) + file.DecreaseIndent() + file.WriteLine("}") + + file.WriteLine("Pass_{}_TextureDependencies.Clear();".format(self.name)) + for dependency in self.resourceDependencies: + file.WriteLine("Pass_{}_TextureDependencies.Append({{TextureIndex::{}, CoreGraphics::PipelineStage::{}}});".format(self.name, dependency.name, dependency.stage)) + file.WriteLine("CoreGraphics::PassCreateInfo info;") + file.WriteLine('info.name = "Pass_{}";'.format(self.name)) + file.WriteLine("info.attachments.Resize({});".format(len(self.attachments))) + file.WriteLine("info.attachmentFlags.Resize({});".format(len(self.attachments))) + file.WriteLine("info.attachmentClears.Resize({});".format(len(self.attachments))) + file.WriteLine("info.attachmentDepthStencil.Resize({});".format(len(self.attachments))) + + file.WriteLine("info.subpasses.Resize({});".format(len(self.subpasses))) + for idx, subpass in enumerate(self.subpasses): + file.WriteLine("static const int Subpass_{} = {};".format(subpass.name, idx)) + + for attachment in self.attachments: + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("CoreGraphics::TextureViewCreateInfo viewInfo;") + file.WriteLine('viewInfo.name = "[Attachment] {} in {}";'.format(attachment.name, self.name)) + file.WriteLine("viewInfo.tex = Textures[(uint)TextureIndex::{}];".format(attachment.name)) + file.WriteLine("viewInfo.format = CoreGraphics::PixelFormat::Code::{};".format(attachment.ref.format)) + file.WriteLine("viewInfo.startMip = 0;") + file.WriteLine("viewInfo.numMips = 1;") + file.WriteLine("viewInfo.startLayer = 0;") + file.WriteLine("viewInfo.numLayers = {};".format(attachment.ref.layers)) + bits = "" + for bit in attachment.ref.bits: + bits += "CoreGraphics::ImageBits::{}".format(bit) + if bit != attachment.ref.bits[-1]: + bits += " | " + file.WriteLine("viewInfo.bits = {};".format(bits)) + file.WriteLine("info.attachments[Pass_{}_Attachment_{}] = CoreGraphics::CreateTextureView(viewInfo);".format(self.name, attachment.name)) + + file.WriteLine("Math::vec4 clearValue = Math::vec4(0.0f);") + flags = "CoreGraphics::AttachmentFlagBits::NoFlags" + if attachment.clearColor is not None or attachment.clearDepth is not None: + flags += " | CoreGraphics::AttachmentFlagBits::Clear" + if attachment.clearStencil is not None: + flags += " | CoreGraphics::AttachmentFlagBits::ClearStencil" + + for flag in attachment.storeLoadFlags: + flags += " | CoreGraphics::AttachmentFlagBits::{}".format(flag) + file.WriteLine("CoreGraphics::AttachmentFlagBits flags = {};".format(flags)) + + if attachment.clearColor is not None: + file.WriteLine("clearValue = Math::vec4({}, {}, {}, {});".format(attachment.clearColor[0], attachment.clearColor[1], attachment.clearColor[2], attachment.clearColor[3])) + if attachment.clearDepth is not None: + file.WriteLine("clearValue.x = {};".format(attachment.clearDepth)) + if attachment.clearStencil is not None: + file.WriteLine("clearValue.y = {};".format(attachment.clearStencil)) + + file.WriteLine("info.attachmentFlags[Pass_{}_Attachment_{}] = flags;".format(self.name, attachment.name)) + file.WriteLine("info.attachmentClears[Pass_{}_Attachment_{}] = clearValue;".format(self.name, attachment.name)) + file.WriteLine("info.attachmentDepthStencil[Pass_{}_Attachment_{}] = CoreGraphics::PixelFormat::IsDepthStencilFormat(CoreGraphics::PixelFormat::Code::{});".format(self.name, attachment.name, attachment.ref.format)) + + file.DecreaseIndent() + file.WriteLine("}") + + for subpass in self.subpasses: + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("CoreGraphics::Subpass subpass; // {}".format(subpass.name)) + numTargets = len(subpass.attachments) + for dep in subpass.dependencies: + file.WriteLine("subpass.dependencies.Append(Subpass_{});".format(dep['name'])) + for inp in subpass.inputs: + file.WriteLine("subpass.inputs.Append(Pass_{}_Attachment_{});".format(self.name, inp['name'])) + for attachment in subpass.attachments: + file.WriteLine("subpass.attachments.Append(Pass_{}_Attachment_{});".format(self.name, attachment['name'])) + for resolve in subpass.resolves: + file.WriteLine("subpass.resolves.Append(Pass_{}_Attachment_{});".format(self.name, resolve['name'])) + if subpass.depth is not None: + file.WriteLine("subpass.depth = Pass_{}_Attachment_{};".format(self.name, subpass.depth['name'])) + numTargets += 1 + file.WriteLine("subpass.numViewports = {};".format(numTargets)) + file.WriteLine("subpass.numScissors = {};".format(numTargets)) + file.WriteLine("info.subpasses[Subpass_{}] = subpass;".format(subpass.name)) + file.DecreaseIndent() + file.WriteLine("}") + file.WriteLine("Pass_{} = CoreGraphics::CreatePass(info);".format(self.name)) + file.DecreaseIndent() + file.WriteLine("}") + + def FormatHeader(self, file): + file.WriteLine('static Util::FixedArray Pass_{}_RenderTargetDimensions({});'.format(self.name, len(self.attachments))) + + for idx, attachment in enumerate(self.attachments): + file.WriteLine("static const int Pass_{}_Attachment_{} = {};".format(self.name, attachment.name, idx)) + for subpass in self.subpasses: + subpass.FormatHeader(file) + + def FormatSource(self, file): + file.WriteLine("") + if len(self.resourceDependencies) > 0: + file.WriteLine('Synchronize("Pass_{}_Sync", cmdBuf, Pass_{}_TextureDependencies, nullptr);'.format(self.name, self.name)) + file.WriteLine('CoreGraphics::CmdBeginMarker(cmdBuf, NEBULA_MARKER_GREEN, "{}");'.format(self.name)) + file.IncreaseIndent() + + for subpass in self.subpasses: + for op in subpass.ops: + if type(op) == SubgraphDefinition: + file.WriteLine('Synchronize("Subgraph_{}_Sync", cmdBuf, SubgraphTextureDependencies_{}, SubgraphBufferDependencies_{});'.format(op.name, op.name, op.name)) + + for attachment in self.attachments: + file.WriteLine('Pass_{}_RenderTargetDimensions[Pass_{}_Attachment_{}] = Shared::RenderTargetParameters{{ {{ viewport.width() * {}f, viewport.height() * {}f, 1 / float(viewport.width()) * {}f, 1 / float(viewport.height()) * {}f }}, {{ viewport.width() / TextureRelativeSize[(uint)TextureIndex::{}].first, viewport.height() / TextureRelativeSize[(uint)TextureIndex::{}].second }} }};'.format(self.name, self.name, attachment.name, attachment.ref.relativeSize[0], attachment.ref.relativeSize[1], attachment.ref.relativeSize[0], attachment.ref.relativeSize[1], attachment.ref.name, attachment.ref.name)) + file.WriteLine('CoreGraphics::PassSetRenderTargetParameters(Pass_{}, Pass_{}_RenderTargetDimensions);'.format(self.name, self.name)) + file.WriteLine('CoreGraphics::CmdBeginPass(cmdBuf, Pass_{});'.format(self.name)) + + for subpass in self.subpasses: + if subpass.depth: + file.WriteLine('Subpass_{}_Viewports[Pass_{}_Attachment_{}] = Math::rectangle(0, 0, viewport.width() * {}, viewport.height() * {});'.format(subpass.name, self.name, subpass.depth['name'], subpass.depth['ref'].ref.relativeSize[0], subpass.depth['ref'].ref.relativeSize[1])) + for attachment in subpass.attachments: + file.WriteLine('Subpass_{}_Viewports[Pass_{}_Attachment_{}] = Math::rectangle(0, 0, viewport.width() * {}, viewport.height() * {});'.format(subpass.name, self.name, attachment['name'], attachment['ref'].ref.relativeSize[0], attachment['ref'].ref.relativeSize[1])) + file.WriteLine('CoreGraphics::CmdSetViewports(cmdBuf, Subpass_{}_Viewports);'.format(subpass.name)) + file.WriteLine('CoreGraphics::CmdSetScissors(cmdBuf, Subpass_{}_Viewports);'.format(subpass.name)) + if subpass != self.subpasses[0]: + file.WriteLine("") + file.WriteLine('CoreGraphics::CmdNextSubpass(cmdBuf);') + subpass.FormatSource(file) + file.WriteLine('CoreGraphics::CmdEndPass(cmdBuf);') + file.DecreaseIndent() + + for attachment in self.attachments: + file.WriteLine("TextureCurrentStage[(uint)TextureIndex::{}] = CoreGraphics::PipelineStage::{};".format(attachment.name, "DepthStencilWrite" if attachment.ref.HasDepthFormat() or attachment.ref.HasStencilFormat() else "ColorWrite")) + file.WriteLine('CoreGraphics::CmdEndMarker(cmdBuf);') + + def FormatSetup(self, file): + file.WriteLine("Initialize_Pass_{}();".format(self.name)) + for sub in self.subpasses: + sub.FormatSetup(file) + + + +class SubmissionDefinition: + def __init__(self, parser, node): + self.name = node['name'].replace(" ", "") + self.queue = node['queue'] + self.lastSubmit = False + if 'last_submit' in node: + self.lastSubmit = node['last_submit'] + self.waitForQueue = None + self.waitForSubmissions = list() + + if 'wait_for_queue' in node: + self.waitForQueue = node['wait_for_queue'] + if 'wait_for_submissions' in node: + for wait in node['wait_for_submissions']: + self.waitForSubmissions.append(wait.replace(" ", "")) + self.ops = list() + parser.externs.append(self) + + global queues + if self.queue not in queues: + Error(self.name, '"queue" must be either Graphics, Compute, Transfer or Sparse') + + for op in node['ops']: + if 'subgraph' in op: + self.ops.append(SubgraphDefinition(parser, op['subgraph'], None, None)) + elif 'pass' in op: + self.ops.append(PassDefinition(parser, op['pass'])) + elif 'copy' in op: + self.ops.append(CopyDefinition(parser, op['copy'])) + elif 'blit' in op: + self.ops.append(BlitDefinition(parser, op['blit'])) + elif 'resolve' in op: + self.ops.append(ResolveDefinition(parser, op['resolve'])) + elif 'swap' in op: + self.ops.append(SwapDefinition(parser, op['swap'])) + elif 'transition' in op: + self.ops.append(TransitionDefinition(parser, op['transition'])) + + def FormatExtern(self, file): + file.WriteLine("CoreGraphics::CmdBufferPoolId CmdPool_{} = CoreGraphics::InvalidCmdBufferPoolId;\n".format(self.name)) + + def FormatHeader(self, file): + for op in self.ops: + op.FormatHeader(file) + + def FormatSetup(self, file): + file.WriteLine("if (CmdPool_{} != CoreGraphics::InvalidCmdBufferPoolId)".format(self.name)) + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("CoreGraphics::DestroyCmdBufferPool(CmdPool_{});".format(self.name)) + file.DecreaseIndent() + file.WriteLine("}") + file.WriteLine("CmdPool_{} = CoreGraphics::CreateCmdBufferPool({{ .queue = CoreGraphics::QueueType::{}QueueType, .resetable = false, .shortlived = true }});".format(self.name, self.queue)) + for op in self.ops: + op.FormatSetup(file) + + def FormatSource(self, file, imports): + file.WriteLine("{{ // Submission {}".format(self.name)) + file.IncreaseIndent() + file.WriteLine("CoreGraphics::CmdBufferCreateInfo cmdBufInfo;") + file.WriteLine("cmdBufInfo.pool = CmdPool_{};".format(self.name)) + file.WriteLine("cmdBufInfo.usage = CoreGraphics::QueueType::{}QueueType;".format(self.queue)) + file.WriteLine("cmdBufInfo.queryTypes = CoreGraphics::CmdBufferQueryBits::Timestamps;") + file.WriteLine("#if NEBULA_GRAPHICS_DEBUG") + file.WriteLine('cmdBufInfo.name = "{}";'.format(self.name)) + file.WriteLine("#endif // NEBULA_GRAPHICS_DEBUG") + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("CoreGraphics::CmdBufferId cmdBuf = CoreGraphics::CreateCmdBuffer(cmdBufInfo);") + file.WriteLine("CoreGraphics::CmdBufferBeginInfo beginInfo = { true, false, false };") + file.WriteLine("CoreGraphics::CmdBeginRecord(cmdBuf, beginInfo);") + deps = "" + if len(self.waitForSubmissions) > 0: + deps = "- waits for: " + for dep in self.waitForSubmissions: + deps += "{}".format(dep) + if dep != self.waitForSubmissions[-1]: + deps += ", " + if self.queue == "Graphics": + file.WriteLine('CoreGraphics::CmdBeginMarker(cmdBuf, NEBULA_MARKER_PURPLE, "{} {}");'.format(self.name, deps)) + else: + file.WriteLine('CoreGraphics::CmdBeginMarker(cmdBuf, NEBULA_MARKER_TURQOISE, "{} {}");'.format(self.name, deps)) + file.IncreaseIndent() + file.WriteLine("Graphics::FlushUpdates(cmdBuf, CoreGraphics::QueueType::{}QueueType);".format(self.queue)) + file.WriteLine("Materials::MaterialLoader::FlushMaterialBuffers(cmdBuf, CoreGraphics::QueueType::{}QueueType);".format(self.queue)) + + for op in self.ops: + op.FormatSource(file) + + if len(imports) > 0: + file.WriteLine("static Util::Array> EndOfFrameSyncs;") + file.WriteLine("EndOfFrameSyncs.Clear();") + for imp in imports: + file.WriteLine("EndOfFrameSyncs.Append({{ TextureIndex::{}, TextureOriginalStage[(uint)TextureIndex::{}] }});".format(imp.name, imp.name)) + file.WriteLine('Synchronize("End Of Frame Sync", cmdBuf, EndOfFrameSyncs, nullptr);') + + file.DecreaseIndent() + file.WriteLine("CoreGraphics::CmdEndMarker(cmdBuf);") + file.WriteLine("CoreGraphics::CmdFinishQueries(cmdBuf);") + file.WriteLine("CoreGraphics::CmdEndRecord(cmdBuf);") + file.WriteLine("Submission_{} = CoreGraphics::SubmitCommandBuffer(cmdBuf, CoreGraphics::QueueType::{}QueueType".format(self.name, self.queue)) + file.WriteLine("#if NEBULA_GRAPHICS_DEBUG") + file.WriteLine(', "{}"'.format(self.name)) + file.WriteLine("#endif") + file.WriteLine(");") + if self.waitForQueue is not None: + file.WriteLine("CoreGraphics::WaitForLastSubmission(CoreGraphics::QueueType::{}QueueType, CoreGraphics::QueueType::{}QueueType);".format(self.queue, self.waitForQueue)) + for wait in self.waitForSubmissions: + file.WriteLine("if (Submission_{} != nullptr)".format(wait)) + file.IncreaseIndent() + file.WriteLine("CoreGraphics::WaitForSubmission(Submission_{}, CoreGraphics::QueueType::{}QueueType);".format(wait, self.queue)) + file.DecreaseIndent() + + file.WriteLine("CoreGraphics::DestroyCmdBuffer(cmdBuf);") + + file.DecreaseIndent() + file.WriteLine("}") + + file.DecreaseIndent() + file.WriteLine("}") + +class FrameScriptGenerator: + def __init__(self): + self.document = None + self.depthFormats = set(["D32S8", "D32", "D24S8", "D16"]) + self.stencilFormats = set(["D32S8", "D24S8"]) + + + #------------------------------------------------------------------------------ + ## + # + def SetVersion(self, v): + self.version = v + + #------------------------------------------------------------------------------ + ## + # + def SetName(self, n): + self.name = n + + #------------------------------------------------------------------------------ + ## + # + def SetDocument(self, input): + fstream = open(input, 'r') + self.document = sjson.loads(fstream.read()) + fstream.close() + + #------------------------------------------------------------------------------ + ## + # + def Parse(self): + + self.textures = list() + self.buffers = list() + self.importBuffers = list() + self.importTextures = list() + self.localTextures = list() + self.localTextureDict = {} + self.exportTextures = list() + self.dependencies = list() + self.submissions = list() + self.externs = list() + self.passes = list() + self.pipelines = list() + if "Nebula" in self.document: + main = self.document["Nebula"] + for name, node in main.items(): + if name == "ImportTextures": + for imp in node: + tex = TextureImportDefinition(self, imp) + self.importTextures.append(tex) + elif name == "ImportBuffers": + for imp in node: + buf = BufferImportDefinition(self, imp) + self.importBuffers.append(buf) + elif name == "Dependencies": + for imp in node: + dep = DependencyDefinition(self, imp) + self.dependencies.append(dep) + elif name == "LocalTextures": + for imp in node: + tex = LocalTextureDefinition(self, imp) + self.localTextures.append(tex) + self.localTextureDict[tex.name] = tex + elif name == "ExportTextures": + for exp in node: + tex = TextureExportDefinition(self, exp) + self.exportTextures.append(tex) + elif name == "Submissions": + for imp in node: + sub = SubmissionDefinition(self, imp) + self.submissions.append(sub) + + #------------------------------------------------------------------------------ + ## + # + def FormatHeader(self, file): + + file.WriteLine("// Frame Script #version:{}#".format(self.version)) + file.WriteLine("#pragma once") + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.IncreaseIndent() + file.WriteLine("This file was generated with Nebula's Frame Script compiler tool.") + file.WriteLine("DO NOT EDIT") + file.DecreaseIndent() + file.WriteLine("*/") + file.WriteLine("") + file.WriteLine('#include "framescripts/framescripts.h"') + file.WriteLine('#include "coregraphics/texture.h"') + file.WriteLine('#include "coregraphics/buffer.h"') + file.WriteLine('#include "coregraphics/graphicsdevice.h"') + file.WriteLine('#include "coregraphics/pipeline.h"') + file.WriteLine('#include "system_shaders/shared.h"') + + file.WriteLine("namespace FrameScript_{}".format(self.name)) + file.WriteLine("{") + file.WriteLine("") + + file.WriteLine("enum class TextureIndex") + file.WriteLine("{") + file.IncreaseIndent() + for idx, texture in enumerate(self.localTextures + self.importTextures): + file.WriteLine("{} = {},".format(texture.name, idx)) + file.WriteLine("Num") + file.DecreaseIndent() + file.WriteLine("};") + + file.WriteLine("") + file.WriteLine("enum class BufferIndex") + file.WriteLine("{") + file.IncreaseIndent() + for idx, buffer in enumerate(self.importBuffers): + file.WriteLine("{} = {},".format(buffer.name, idx)) + file.WriteLine("Num") + file.DecreaseIndent() + file.WriteLine("};") + file.WriteLine("void Synchronize(const char* name, const CoreGraphics::CmdBufferId buf, const Util::Array>& textureDeps, const Util::Array>& bufferDeps);") + + + for importBuffer in self.importBuffers: + importBuffer.FormatHeader(file) + + for importTexture in self.importTextures: + importTexture.FormatHeader(file) + + for dependency in self.dependencies: + dependency.FormatHeader(file) + + for texture in self.localTextures: + texture.FormatHeader(file) + + file.WriteLine("") + file.WriteLine("/// Setup FrameScript_{}".format(self.name)) + file.WriteLine("void Initialize(const uint frameWidth, const uint frameHeight);") + file.WriteLine("void SetupPipelines();") + + + file.WriteLine("") + for submission in self.submissions: + submission.FormatHeader(file) + + + file.WriteLine("") + if len(self.localTextures + self.importTextures) > 0: + file.WriteLine("extern CoreGraphics::TextureId Textures[(uint)TextureIndex::Num];") + file.WriteLine("extern Util::Pair TextureRelativeScale[(uint)TextureIndex::Num];") + if len(self.importBuffers) > 0: + file.WriteLine("extern CoreGraphics::BufferId Buffers[(uint)BufferIndex::Num];") + + for texture in (self.localTextures + self.importTextures): + file.WriteLine("inline CoreGraphics::TextureId Texture_{}() {{ return Textures[(uint)TextureIndex::{}]; }}".format(texture.name, texture.name)) + file.WriteLine("inline Util::Pair TextureRelativeScale_{}() {{ return TextureRelativeScale[(uint)TextureIndex::{}]; }}".format(texture.name, texture.name)) + for buffer in (self.importBuffers): + file.WriteLine("inline CoreGraphics::BufferId Buffer_{}() {{ return Buffers[(uint)BufferIndex::{}]; }}".format(buffer.name, buffer.name)) + for export in self.exportTextures: + export.FormatHeader(file) + for submission in self.submissions: + file.WriteLine("extern CoreGraphics::SubmissionWaitEvent Submission_{};".format(submission.name)) + + file.WriteLine("") + file.WriteLine("/// Execute FrameScript_{}".format(self.name)) + file.WriteLine("void Run(const Math::rectangle& viewport, IndexT frameIndex, IndexT bufferIndex);") + + file.WriteLine("}} // namespace FrameScript_{}".format(self.name)) + + #------------------------------------------------------------------------------ + ## + # + def FormatSource(self, file): + file.WriteLine("// Frame Script #version:{}#".format(self.version)) + file.WriteLine("#pragma once") + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.IncreaseIndent() + file.WriteLine("This file was generated with Nebula's Frame Script compiler tool.") + file.WriteLine("DO NOT EDIT") + file.DecreaseIndent() + file.WriteLine("*/") + file.WriteLine("") + file.WriteLine('#include "{}.h"'.format(self.name)) + file.WriteLine('#include "materials/materialtemplates.h"') + file.WriteLine('#include "materials/materialloader.h"') + file.WriteLine('#include "graphics/globalconstants.h"') + file.WriteLine('#include "coregraphics/graphicsdevice.h"') + file.WriteLine('#include "frame/framesubpassbatch.h"') + file.WriteLine('#include "graphics/view.h"') + file.WriteLine('#include "coregraphics/swapchain.h"') + file.WriteLine('#include "coregraphics/barrier.h"') + file.WriteLine('#include "renderutil/drawfullscreenquad.h"') + + file.WriteLine("namespace FrameScript_{}".format(self.name)) + file.WriteLine("{") + + for submission in self.submissions: + file.WriteLine("CoreGraphics::SubmissionWaitEvent Submission_{};".format(submission.name)) + + file.WriteLine("") + if len(self.localTextures + self.importTextures) > 0: + file.WriteLine("CoreGraphics::ImageBits TextureImageBits[(uint)TextureIndex::Num] = {};") + file.WriteLine("CoreGraphics::PipelineStage TextureCurrentStage[(uint)TextureIndex::Num] = {};") + file.WriteLine("CoreGraphics::PipelineStage TextureOriginalStage[(uint)TextureIndex::Num] = {};") + file.WriteLine("CoreGraphics::TextureId Textures[(uint)TextureIndex::Num] = {};") + file.WriteLine("Util::Pair TextureRelativeScale[(uint)TextureIndex::Num] = {};") + file.WriteLine("Util::Pair TextureRelativeSize[(uint)TextureIndex::Num] = {};") + if len(self.importBuffers) > 0: + file.WriteLine("CoreGraphics::PipelineStage BufferCurrentStage[(uint)BufferIndex::Num] = {};") + file.WriteLine("CoreGraphics::BufferId Buffers[(uint)BufferIndex::Num] = {};") + + file.WriteLine("") + for extern in self.externs: + extern.FormatExtern(file) + + file.WriteLine("") + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("inline void") + file.WriteLine("Synchronize(const char* name, const CoreGraphics::CmdBufferId buf, const Util::Array>& textureDeps, const Util::Array>& bufferDeps)") + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("CoreGraphics::BarrierScope scope = CoreGraphics::BarrierScope::Begin(name, buf);") + + if len(self.importTextures + self.localTextures) > 0: + file.WriteLine("for (const auto [index, stage] : textureDeps)") + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("CoreGraphics::PipelineStage lastStage = TextureCurrentStage[(uint)index];") + file.WriteLine("if ((stage != lastStage) && Textures[(uint)index] != CoreGraphics::InvalidTextureId)") + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("scope.AddTexture(TextureImageBits[(uint)index], Textures[(uint)index], lastStage, stage);") + file.DecreaseIndent() + file.WriteLine("}") + file.WriteLine("TextureCurrentStage[(uint)index] = stage;") + + file.DecreaseIndent() + file.WriteLine("}") + + if len(self.importBuffers) > 0: + file.WriteLine("for (const auto [index, stage] : bufferDeps)") + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("CoreGraphics::PipelineStage lastStage = BufferCurrentStage[(uint)index];") + file.WriteLine("if ((stage != lastStage) && Buffers[(uint)index] != CoreGraphics::InvalidBufferId)") + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("scope.AddBuffer(Buffers[(uint)index], lastStage, stage);") + file.DecreaseIndent() + file.WriteLine("}") + file.WriteLine("BufferCurrentStage[(uint)index] = stage;") + + file.DecreaseIndent() + file.WriteLine("}") + + file.WriteLine("scope.Flush();") + file.DecreaseIndent() + file.WriteLine("}") + + for importBuffer in self.importBuffers: + importBuffer.FormatSource(file) + + for importTexture in self.importTextures: + importTexture.FormatSource(file) + + for dependency in self.dependencies: + dependency.FormatSource(file) + + for localTexture in self.localTextures: + localTexture.FormatSource(file) + + file.WriteLine("") + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("void") + file.WriteLine("InitializeTextures(const uint windowWidth, const uint windowHeight)") + file.WriteLine("{") + file.IncreaseIndent() + for localTexture in self.localTextures: + if localTexture.relativeSize: + file.WriteLine("Initialize_Texture_{}(windowWidth, windowHeight);".format(localTexture.name)) + else: + file.WriteLine("Initialize_Texture_{}();".format(localTexture.name)) + file.DecreaseIndent() + file.WriteLine("}") + + file.WriteLine("") + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("void") + file.WriteLine("InitializeSubmissions()") + file.WriteLine("{") + file.IncreaseIndent() + for p in self.submissions: + p.FormatSetup(file) + file.DecreaseIndent() + file.WriteLine("}") + + file.WriteLine("") + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("void") + file.WriteLine("InitializePipelines()") + file.WriteLine("{") + file.IncreaseIndent() + for pipeline in self.pipelines: + pipeline.FormatPipeline(file) + file.DecreaseIndent() + file.WriteLine("}") + + + file.WriteLine("") + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("void") + file.WriteLine("Initialize(const uint frameWidth, const uint frameHeight)") + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("InitializeTextures(frameWidth, frameHeight);") + file.WriteLine("InitializeSubmissions();") + file.DecreaseIndent() + file.WriteLine("}") + + file.WriteLine("") + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("void") + file.WriteLine("SetupPipelines()") + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("InitializePipelines();") + file.DecreaseIndent() + file.WriteLine("}") + + file.WriteLine("") + file.WriteLine("//------------------------------------------------------------------------------") + file.WriteLine("/**") + file.WriteLine("*/") + file.WriteLine("void") + file.WriteLine("Run(const Math::rectangle& viewport, IndexT frameIndex, IndexT bufferIndex)") + file.WriteLine("{") + file.IncreaseIndent() + file.WriteLine("const Ptr& view = Graphics::GraphicsServer::Instance()->GetCurrentView();") + for submission in self.submissions: + if submission.lastSubmit: + submission.FormatSource(file, self.importTextures) + else: + submission.FormatSource(file, []) + + for exportTexture in self.exportTextures: + file.WriteLine("Export_{} = {{ .index = (uint)TextureIndex::{}, .tex = Textures[(uint)TextureIndex::{}], .stage = TextureCurrentStage[(uint)TextureIndex::{}] }};".format(exportTexture.name, exportTexture.name, exportTexture.name, exportTexture.name)) + file.DecreaseIndent() + file.WriteLine("}") + + file.WriteLine("}} // namespace FrameScript_{}".format(self.name)) + +# Entry point for generator +if __name__ == '__main__': + globals() + + queues = set(['Graphics', 'Compute', 'Transfer', 'Sparse']) + + generator = FrameScriptGenerator() + generator.SetVersion(Version) + file = sys.argv[-3] + outH = sys.argv[-2] + outS = sys.argv[-1] + + print("Compiling frame script '{}' -> '{}' & '{}'".format(file, outH, outS)) + + headerF = IDLC.filewriter.FileWriter() + headerF.Open(outH) + + sourceF = IDLC.filewriter.FileWriter() + sourceF.Open(outS) + + generator.SetDocument(file) + generator.SetName(Path(file).stem) + generator.Parse() + + generator.FormatHeader(headerF) + headerF.Close() + generator.FormatSource(sourceF) + sourceF.Close() diff --git a/fips-files/generators/materialtemplatec.py b/fips-files/generators/materialtemplatec.py index d57d8cd7a6..c53dd7bd4f 100644 --- a/fips-files/generators/materialtemplatec.py +++ b/fips-files/generators/materialtemplatec.py @@ -218,12 +218,10 @@ def FormatHeader(self): }};\n'''.format(v.name, typeStr, accessorStr, varStr, self.interface.name, v.name, "nullptr" if len(v.desc) == 0 else '"{}"'.format(v.desc)) for p in self.passes: - ret += '\n\tEntry::Pass __{};\n'.format(p.batch) + ret += '\tEntry::Pass __{};\n'.format(p.batch) for v in self.variables: if v.type == 'texture2d': ret += '\tMaterials::ShaderConfigBatchTexture __{}_{};\n'.format(p.batch, v.name) - else: - ret += '\tMaterials::ShaderConfigBatchConstant __{}_{};\n'.format(p.batch, v.name) ret += '\n\tEntry entry = {{.name = "{}", .uniqueId = "{}"_hash, .properties = {}, .bufferName="_{}", .bufferSize=sizeof(MaterialInterfaces::{}Material), .vertexLayout = CoreGraphics::{}, .numTextures = {}}};\n'.format(self.name, self.name, self.interface.uniqueId, self.interface.name, self.interface.name, self.vertex, texCounter) ret += '\n\tvoid Setup();\n' @@ -274,7 +272,7 @@ def FormatSource(self): func += '\t\tIndexT bufferSlot = InvalidIndex;\n' func += '\t\tif (this->entry.bufferName != nullptr) bufferSlot = CoreGraphics::ShaderGetResourceSlot({}, this->entry.bufferName);\n'.format('shader') func += '\t\tthis->__{} = Entry::Pass{{.shader = shader, .program = program, .index = {}, .name = "{}", .bufferIndex=bufferSlot }};\n'.format(p.batch, passCounter, p.batch) - func += '\t\tthis->entry.passes.Add(CoreGraphics::BatchGroup::FromName("{}"), &this->__{});\n'.format(p.batch, p.batch) + func += '\t\tthis->entry.passes.Add(MaterialTemplates::BatchGroup::{}, &this->__{});\n'.format(p.batch, p.batch) func += '\t\tthis->entry.texturesPerBatch[{}].Resize({});\n'.format(passCounter, numTextures) texCounter = 0 for var in self.variables: @@ -335,12 +333,13 @@ def FormatShader(self): class MaterialTemplateGenerator: def __init__(self): self.document = None - self.documentPath = "" self.version = 0 self.materials = list() self.materialDict = {} self.interfaces = list() self.interfaceDict = {} + self.batchGroupCounter = 0 + self.batchGroupDict = {} self.name = "" #------------------------------------------------------------------------------ @@ -359,14 +358,7 @@ def SetName(self, n): ## # def SetDocument(self, input): - self.documentPath = input - self.documentBaseName = os.path.splitext(input)[0] - self.documentDirName = os.path.dirname(self.documentBaseName) - - head, tail = ntpath.split(self.documentBaseName) - self.documentFileName = tail or ntpath.basename(head) - - fstream = open(self.documentPath, 'r') + fstream = open(input, 'r') self.document = sjson.loads(fstream.read()) fstream.close() @@ -386,6 +378,10 @@ def Parse(self): if name == "Templates": for mat in node: matDef = MaterialTemplateDefinition(mat, self) + for p in matDef.passes: + if p.batch not in self.batchGroupDict: + self.batchGroupDict[p.batch] = self.batchGroupCounter + self.batchGroupCounter += 1 if matDef.inherits: matDef.variables = self.materialDict[matDef.inherits].variables + matDef.variables matDef.passes = self.materialDict[matDef.inherits].passes + matDef.passes @@ -420,7 +416,7 @@ def FormatHeader(self, f): f.WriteLine('\t{},\\'.format(int.name)) f.WriteLine("") - f.WriteLine('void SetupMaterialTemplates(Util::Dictionary& Lookup, Util::HashTable>& Configs);\n') + f.WriteLine('void SetupMaterialTemplates();\n') for mat in self.materials: f.WriteLine(mat.FormatHeader()) @@ -454,6 +450,7 @@ def BeginHeader(self, f): f.WriteLine('#include "math/vec4.h"') f.WriteLine('using namespace Util;') f.WriteLine('namespace MaterialTemplates\n{\n') + f.WriteLine('enum class BatchGroup;\n') #------------------------------------------------------------------------------ @@ -485,10 +482,10 @@ def FormatSource(self, f): setupStr += '\t__{}.Setup();\n'.format(mat.name) setupStr += '\tLookup.Add("{}"_hash, &__{}.entry);\n'.format(mat.name, mat.name) for p in mat.passes: - setupStr += '\tConfigs.Emplace(CoreGraphics::BatchGroup::FromName("{}")).Append(&__{}.entry);\n'.format(p.batch, mat.name) + setupStr += '\tConfigs[(uint)MaterialTemplates::BatchGroup::{}].Append(&__{}.entry);\n'.format(p.batch, mat.name) setupStr += '\n' f.WriteLine('struct {}::{} {}::__{};'.format(self.name, mat.name, self.name, mat.name)) - f.WriteLine('//------------------------------------------------------------------------------\n/**\n*/\nvoid\nSetupMaterialTemplates(Util::Dictionary& Lookup, Util::HashTable>& Configs)\n{{\n{}}}\n'.format(setupStr)) + f.WriteLine('//------------------------------------------------------------------------------\n/**\n*/\nvoid\nSetupMaterialTemplates()\n{{\n{}}}\n'.format(setupStr)) f.WriteLine('}} // namespace {}\n'.format(self.name)) @@ -567,109 +564,6 @@ def BeginShader(self, f): # def EndShader(self, f): f.WriteLine("") - - #------------------------------------------------------------------------------ - ## - # - def GenerateShader(self, outPath): - f = IDLC.filewriter.FileWriter() - f.Open(outPath) - self.BeginShader(f) - self.FormatShader(f) - self.EndShader(f) - f.Close() - - #------------------------------------------------------------------------------ - ## - # - def GenerateGlueHeader(self, files, outPath): - f = IDLC.filewriter.FileWriter() - f.Open(outPath) - f.WriteLine("// Material Template #version:{}#".format(self.version)) - f.WriteLine("#pragma once") - f.WriteLine("//------------------------------------------------------------------------------") - f.WriteLine("/**") - f.IncreaseIndent() - f.WriteLine("This file was generated with Nebula's Material Template compiler tool.") - f.WriteLine("DO NOT EDIT") - f.DecreaseIndent() - f.WriteLine("*/") - f.WriteLine('#include "materials/materialtemplatetypes.h"') - - enumStr = '' - for file in files: - name = Path(file).stem - enumStr += '\tENUM_{}\n'.format(name) - f.WriteLine('#include "{}"'.format(file)) - enumStr += '\tNum\n' - - f.WriteLine('namespace MaterialTemplates\n{\n') - f.WriteLine('enum class MaterialProperties\n{{\n{}}};'.format(enumStr)) - - f.WriteLine('extern Util::Dictionary Lookup;') - f.WriteLine('extern Util::HashTable> Configs;\n') - f.WriteLine('void SetupMaterialTemplates();\n') - - f.WriteLine('} // namespace MaterialTemplates\n') - - #------------------------------------------------------------------------------ - ## - # - def GenerateGlueSource(self, files, headerPath, outPath): - f = IDLC.filewriter.FileWriter() - f.Open(outPath) - f.WriteLine("// Material Template #version:{}#".format(self.version)) - f.WriteLine("#pragma once") - f.WriteLine("//------------------------------------------------------------------------------") - f.WriteLine("/**") - f.IncreaseIndent() - f.WriteLine("This file was generated with Nebula's Material Template compiler tool.") - f.WriteLine("DO NOT EDIT") - f.DecreaseIndent() - f.WriteLine("*/") - f.WriteLine('#include "{}"'.format(headerPath)) - - setupStr = '' - for file in files: - name = Path(file).stem - setupStr += '\t{}::SetupMaterialTemplates(Lookup, Configs);\n'.format(name) - f.WriteLine('#include "{}"'.format(file)) - - f.WriteLine('namespace MaterialTemplates\n{\n') - f.WriteLine('Util::Dictionary Lookup;') - f.WriteLine('Util::HashTable> Configs;\n') - - f.WriteLine('//------------------------------------------------------------------------------\n/**\n*/\nvoid\nSetupMaterialTemplates() \n{{\n{}}}'.format(setupStr)) - - f.WriteLine('} // namespace MaterialTemplates\n') - - #------------------------------------------------------------------------------ - ## - # - def GenerateGlueShader(self, files, outPath): - f = IDLC.filewriter.FileWriter() - f.Open(outPath) - f.WriteLine("// Material Template #version:{}#".format(self.version)) - f.WriteLine("#pragma once") - f.WriteLine("//------------------------------------------------------------------------------") - f.WriteLine("/**") - f.IncreaseIndent() - f.WriteLine("This file was generated with Nebula's Material Template compiler tool.") - f.WriteLine("DO NOT EDIT") - f.DecreaseIndent() - f.WriteLine("*/") - f.WriteLine("#define MATERIAL_BINDING group(BATCH_GROUP) binding(51)") - f.WriteLine("const uint MaterialBindingSlot = 51;") - f.WriteLine("const uint MaterialBufferSlot = 52;") - - bindingsContent = '' - for file in files: - fileName = Path(file).stem - f.WriteLine('#include <{}.fxh>'.format(fileName)) - bindingsContent += "\tMATERIAL_LIST_{}\n".format(fileName) - - f.WriteLine("MATERIAL_BINDING rw_buffer MaterialBindings\n{{\n{}}};".format(bindingsContent)) - # Entry point for generator if __name__ == '__main__': @@ -689,6 +583,9 @@ def GenerateGlueShader(self, files, outPath): sourceF.Open('{}/materialtemplates.cc'.format(outDir)) generator.BeginSource(sourceF) + sourceF.WriteLine('Util::Dictionary Lookup;') + sourceF.WriteLine('Util::Array Configs[(uint)MaterialTemplates::BatchGroup::Num];') + shaderF = IDLC.filewriter.FileWriter() shaderF.Open('{}/material_interfaces.fx'.format(outDir)) generator.BeginShader(shaderF) @@ -697,12 +594,28 @@ def GenerateGlueShader(self, files, outPath): path = Path(file).stem print("Compiling material template '{}' -> '{}/materialtemplates.h' & '{}/materialtemplates.cc'".format(file, outDir, outDir)) generator.SetDocument(file) - generator.Parse() generator.SetName(path) + generator.Parse() generator.FormatHeader(headerF) generator.FormatSource(sourceF) generator.FormatShader(shaderF) + enumStr = '\tInvalid = -1,\n' + for batch in generator.batchGroupDict: + enumStr += '\t{} = {},\n'.format(batch, generator.batchGroupDict[batch]) + enumStr += '\tNum\n' + headerF.WriteLine('enum class BatchGroup\n{{\n{}}};'.format(enumStr)) + + conversionStr = '' + for batch in generator.batchGroupDict: + conversionStr += '\t\tcase "{}"_hash: return BatchGroup::{};\n'.format(batch, batch) + conversionStr += '\t\tdefault: return BatchGroup::Invalid;' + headerF.WriteLine(''' +//------------------------------------------------------------------------------ +/** +*/ +inline BatchGroup\nBatchGroupFromName(const char* name)\n{{\n\tuint code = Util::String::Hash(name, strlen(name));\n\tswitch(code)\n\t{{\n{}\n\t}}\n}}\n'''.format(conversionStr)) + # Finish header enumStr = '' for file in files: @@ -711,9 +624,8 @@ def GenerateGlueShader(self, files, outPath): enumStr += '\tNum\n' headerF.WriteLine('enum class MaterialProperties\n{{\n{}}};'.format(enumStr)) - headerF.WriteLine('extern Util::Dictionary Lookup;') - headerF.WriteLine('extern Util::HashTable> Configs;\n') + headerF.WriteLine('extern Util::Array Configs[(uint)MaterialTemplates::BatchGroup::Num];\n') headerF.WriteLine('void SetupMaterialTemplates();\n') generator.EndHeader(headerF) @@ -723,10 +635,8 @@ def GenerateGlueShader(self, files, outPath): setupStr = '' for file in files: name = Path(file).stem - setupStr += '\t{}::SetupMaterialTemplates(Lookup, Configs);\n'.format(name) + setupStr += '\t{}::SetupMaterialTemplates();\n'.format(name) - sourceF.WriteLine('Util::Dictionary Lookup;') - sourceF.WriteLine('Util::HashTable> Configs;\n') sourceF.WriteLine('//------------------------------------------------------------------------------\n/**\n*/\nvoid\nSetupMaterialTemplates() \n{{\n{}}}'.format(setupStr)) generator.EndSource(sourceF) diff --git a/fips-files/include.cmake b/fips-files/include.cmake index 4cfa84a236..c5ef406c2e 100644 --- a/fips-files/include.cmake +++ b/fips-files/include.cmake @@ -283,7 +283,7 @@ macro(nebula_idl_compile) include_directories("${CMAKE_BINARY_DIR}/nidl/${CurTargetName}") endmacro() -macro(nebula_material_template_compile) +macro(nebula_material_template_add) source_group("Material Template Files" FILES ${ARGN}) set(target_has_materials 1) foreach(temp ${ARGN}) @@ -294,7 +294,7 @@ macro(nebula_material_template_compile) endforeach() endmacro() -macro(nebula_project_material_template_compile) +macro(nebula_project_material_template_add) file(GLOB project_materials ${WORK_DIR}/code/materials/*.json) source_group("Material Template Files" FILES ${project_materials}) set(target_has_materials 1) @@ -306,12 +306,13 @@ macro(nebula_project_material_template_compile) endforeach() endmacro() -macro(nebula_material_template_glue) +macro(nebula_material_template_compile) set(out_header "materialtemplates.h") set(out_source "materialtemplates.cc") set(out_shader "material_interfaces.fx") - + set(abs_output_folder "${CMAKE_BINARY_DIR}/material_templates/render/materials") + file(MAKE_DIRECTORY ${abs_output_folder}) add_custom_target(materialtemplates COMMAND ${PYTHON} ${NROOT}/fips-files/generators/materialtemplatec.py ${material_definition_files} "${abs_output_folder}" BYPRODUCTS "${abs_output_folder}/${out_header}" "${abs_output_folder}/${out_source}" "${abs_output_folder}/${out_shader}" @@ -319,7 +320,7 @@ macro(nebula_material_template_glue) DEPENDS ${NROOT}/fips-files/generators/materialtemplatec.py ${material_definition_files} VERBATIM) add_dependencies(render materialtemplates) - set_target_properties(materialtemplates PROPERTIES FOLDER MaterialDefinitions) + set_target_properties(materialtemplates PROPERTIES FOLDER "Material Definitions") source_group("materials\\Generated" FILES "${abs_output_folder}/${out_header}" "${abs_output_folder}/${out_source}" "${abs_output_folder}/${out_shader}" ) source_group("materials\\Templates" FILES "${out_header}" "${out_source}" "${out_shader}") target_sources(render PRIVATE "${abs_output_folder}/${out_header}" "${abs_output_folder}/${out_source}" "${abs_output_folder}/${out_shader}") @@ -343,10 +344,45 @@ macro(nebula_material_template_glue) DEPENDS ${SHADERC} ${depoutput} VERBATIM ) - set_target_properties(materialinterface PROPERTIES FOLDER MaterialDefinitions) + set_target_properties(materialinterface PROPERTIES FOLDER "Material Definitions") add_dependencies(materialinterface materialtemplates) add_dependencies(render materialinterface) +endmacro() +macro(nebula_framescript_add) + source_group("Frame Script Files" FILES ${ARGN}) + set(target_has_frame_script 1) + foreach(temp ${ARGN}) + get_filename_component(f_abs ${CurDir}${temp} ABSOLUTE) + list(APPEND frame_script_definition_files ${f_abs}) + source_group("${CurGroup}\\FrameScripts" FILES ${f_abs}) + target_sources(${CurTargetName} PRIVATE "${f_abs}") + endforeach() +endmacro() + +macro(nebula_framescript_compile) + set(abs_output_folder "${CMAKE_BINARY_DIR}/framescripts/render/frame") + file(MAKE_DIRECTORY ${abs_output_folder}) + + foreach(script ${frame_script_definition_files}) + get_filename_component(script_name ${script} NAME_WE) + set(out_header ${script_name}.h) + set(out_source ${script_name}.cc) + set(target_name framescript_${script_name}) + add_custom_target(${target_name} + COMMAND ${PYTHON} ${NROOT}/fips-files/generators/framescriptc.py ${script} "${abs_output_folder}/${out_header}" "${abs_output_folder}/${out_source}" + BYPRODUCTS "${abs_output_folder}/${out_header}" "${abs_output_folder}/${out_source}" + WORKING_DIRECTORY "${NROOT}" + DEPENDS ${NROOT}/fips-files/generators/framescriptc.py ${script} + VERBATIM) + add_dependencies(render ${target_name}) + set_target_properties(${target_name} PROPERTIES FOLDER "Frame Scripts") + source_group("framescripts\\Generated" FILES "${abs_output_folder}/${out_header}" "${abs_output_folder}/${out_source}" ) + source_group("framescripts\\JSON" FILES "${script}") + target_sources(render PRIVATE "${abs_output_folder}/${out_header}" "${abs_output_folder}/${out_source}") + + endforeach() + target_include_directories(render PUBLIC "${CMAKE_BINARY_DIR}/framescripts/render") endmacro() # Call inside fips_sharedlib, after calling nebula_idl_generate_cs_target @@ -661,6 +697,7 @@ macro(nebula_begin_app name type) set(target_has_shaders 0) set(target_has_flatc 0) set(target_has_materials 0) + set(target_has_frame_script 0) if(N_EDITOR) add_compile_definitions(WITH_NEBULA_EDITOR) endif() @@ -682,7 +719,10 @@ macro(nebula_end_app) target_include_directories(${curtarget} PUBLIC "${CMAKE_BINARY_DIR}/generated/") endif() if (target_has_materials) - nebula_material_template_glue() + nebula_material_template_compile() + endif() + if (target_has_frame_script) + nebula_framescript_compile() endif() set_target_properties(${curtarget} PROPERTIES ENABLE_EXPORTS false) if (TARGET system_resources-res) @@ -696,6 +736,7 @@ macro(nebula_begin_module name) set(target_has_shaders 0) set(target_has_flatc 0) set(target_has_materials 0) + set(target_has_frame_script 0) if(N_EDITOR) add_compile_definitions(WITH_NEBULA_EDITOR) endif() @@ -716,7 +757,10 @@ macro(nebula_end_module) target_include_directories(${curtarget} PUBLIC "${CMAKE_BINARY_DIR}/generated") endif() if (target_has_materials) - nebula_material_template_glue() + nebula_material_template_compile() + endif() + if (target_has_frame_script) + nebula_framescript_compile() endif() if(N_DEBUG_SYMBOLS) target_compile_options(${curtarget} PRIVATE $,/Zi,/Z7>) @@ -729,6 +773,7 @@ macro(nebula_begin_lib name) set(target_has_shaders 0) set(target_has_flatc 0) set(target_has_materials 0) + set(target_has_frame_script 0) if(N_EDITOR) add_compile_definitions(WITH_NEBULA_EDITOR) endif() @@ -748,7 +793,10 @@ macro(nebula_end_lib) target_include_directories(${curtarget} PUBLIC "${CMAKE_BINARY_DIR}/generated") endif() if (target_has_materials) - nebula_material_template_glue() + nebula_material_template_compile() + endif() + if (target_has_frame_script) + nebula_framescript_compile() endif() endmacro() diff --git a/syswork/frame/win32/vkdefault.json b/syswork/frame/win32/vkdefault.json index d75e52d071..d29bae3cda 100644 --- a/syswork/frame/win32/vkdefault.json +++ b/syswork/frame/win32/vkdefault.json @@ -681,7 +681,7 @@ } }, { - "batch": { + "subgraph": { "name": "Im3D" } } @@ -743,11 +743,6 @@ "name": "ImGUI" } }, - { - "subgraph": { - "name": "Im3D" - } - }, { "subgraph": { "name": "StaticUI To Backbuffer" diff --git a/syswork/shaders/vk/bloom.fx b/syswork/shaders/vk/bloom.fx index 2835f885ff..95e601cc2d 100644 --- a/syswork/shaders/vk/bloom.fx +++ b/syswork/shaders/vk/bloom.fx @@ -6,7 +6,7 @@ #include "lib/shared.fxh" #include "lib/techniques.fxh" -#define KERNEL_SIZE 8 +#define KERNEL_SIZE 16 sampler_state InputSampler { @@ -30,6 +30,8 @@ render_state PostEffectState texture2D Input; write rgba16f image2D BloomOutput; +texture2D Intermediate; +readwrite rgba16f image2D BloomIntermediate[14]; groupshared vec3 SampleLookup[KERNEL_SIZE][KERNEL_SIZE]; @@ -71,6 +73,7 @@ SampleTentUpscale(ivec2 center) */ [local_size_x] = KERNEL_SIZE [local_size_y] = KERNEL_SIZE +[local_size_z] = 1 shader void csUpscale() @@ -86,41 +89,74 @@ csUpscale() uvec2 outputPixel = tileStart + gl_LocalInvocationID.xy; - const uvec2 tileEndClamped = min(tileEnd, uvec2(Resolutions[0].xy)); + const uvec2 tileEndClamped = min(tileEnd, uvec2(Resolutions[gl_WorkGroupID.z].xy)); // Only run waves on pixels within the target resolution - vec3 sum = vec3(0); bool pixelOutputMask = all(lessThan(outputPixel, tileEndClamped)); - vec2 mippedDimensions = Resolutions[0].xy; - vec2 sampleUV = vec2(sampleCoord) / mippedDimensions; + vec2 mippedDimensions = Resolutions[gl_WorkGroupID.z].xy; + vec2 sampleUV = (vec2(sampleCoord) + vec2(0.5f)) / mippedDimensions; const float weights[14] = { 0.3465, 0.138, 0.1176, 0.066, 0.066, 0.061, 0.061, 0.055, 0.055, 0.050, 0.050, 0.045, 0.045, 0.040 }; - for (int i = 0; i < Mips; i++) + // All waves load into LDS + SampleLookup[gl_LocalInvocationID.x][gl_LocalInvocationID.y] = SampleCubic(Input, InputSampler, Resolutions[gl_WorkGroupID.z], sampleUV, gl_WorkGroupID.z); + barrier(); + + // Only the 14x14 kernel inside the padded one runs the tent filter + if (pixelOutputMask) { - // All waves load into LDS - SampleLookup[gl_LocalInvocationID.x][gl_LocalInvocationID.y] = SampleCubic(Input, InputSampler, Resolutions[i], sampleUV, i); - barrier(); - - // Only the 14x14 kernel inside the padded one runs the tent filter - if (pixelOutputMask) - { - sum += SampleTentUpscale(ivec2(gl_LocalInvocationID.xy) + ivec2(1)) * weights[i]; - } + vec3 sum = SampleTentUpscale(ivec2(gl_LocalInvocationID.xy) + ivec2(1)) * weights[gl_WorkGroupID.z]; + imageStore(BloomIntermediate[gl_WorkGroupID.z], ivec2(outputPixel.x, outputPixel.y), vec4(sum, 0)); } +} + + +//------------------------------------------------------------------------------ +/** +*/ +[local_size_x] = 256 +shader +void +csMerge() +{ + // Running a 16x16 kernel with a 3x3 kernel means we need a 1x1 extra radius + const uvec2 tileStart = uvec2(gl_WorkGroupID.x * 256, gl_WorkGroupID.y); + const uvec2 tileEnd = tileStart + uvec2(256, 1); + + uvec2 outputPixel = tileStart + gl_LocalInvocationID.xy; + const uvec2 tileEndClamped = min(tileEnd, uvec2(Resolutions[0].xy)); + + // Only run waves on pixels within the target resolution + vec3 sum = vec3(0); + bool pixelOutputMask = all(lessThan(outputPixel, tileEndClamped)); + vec2 uv = (vec2(outputPixel) + vec2(0.5f)) / Resolutions[0].xy; + for (int i = 0; i < Mips; i++) + { + ivec2 inputPixel = ivec2(outputPixel) >> i; + + sum += textureLod(sampler2D(Intermediate, InputSampler), uv, i).rgb; + //sum += imageLoad(BloomIntermediate[i], inputPixel).rgb; + } + if (pixelOutputMask) { vec3 weight = sum / Mips; imageStore(BloomOutput, ivec2(outputPixel.x, outputPixel.y), vec4(sum, saturate(dot(weight, weight)) * BloomIntensity)); } + } //------------------------------------------------------------------------------ /** */ -program Bloom[ string Mask = "Bloom"; ] +program Bloom[ string Mask = "Intermediate"; ] { ComputeShader = csUpscale(); }; +program BloomMerge[ string Mask = "Merge"; ] +{ + ComputeShader = csMerge(); +}; + diff --git a/syswork/shaders/vk/blur/blur_cs.fxh b/syswork/shaders/vk/blur/blur_cs.fxh index 07e05312a0..edf2871f27 100644 --- a/syswork/shaders/vk/blur/blur_cs.fxh +++ b/syswork/shaders/vk/blur/blur_cs.fxh @@ -42,6 +42,11 @@ sampler_state InputSampler AddressV = Clamp; }; +constant BlurUniforms +{ + ivec2 Viewport; +}; + #if !(BLUR_KERNEL_8 || BLUR_KERNEL_16 || BLUR_KERNEL_32 || BLUR_KERNEL_64) #define BLUR_KERNEL_16 1 #endif @@ -98,7 +103,7 @@ void csMainX() { // get full resolution and inverse full resolution - ivec2 size = imageSize(BlurImageX).xy; + ivec2 size = Viewport; // calculate offsets const int tileStart = int(gl_WorkGroupID.x) * BLUR_TILE_WIDTH; @@ -108,15 +113,20 @@ csMainX() const int x = max(0, min(apronStart + int(gl_LocalInvocationID.x), size.x - 1)); const int y = int(gl_WorkGroupID.y); - - // load into workgroup saved memory, this allows us to use the original pixel even though - // we might have replaced it with the result from this thread! + const uint z = gl_WorkGroupID.z; + + if (x >= Viewport.x || y >= Viewport.y) + SharedMemory[gl_LocalInvocationID.x] = IMAGE_LOAD_VEC(0); + else + { + // load into workgroup saved memory, this allows us to use the original pixel even though + // we might have replaced it with the result from this thread! #if IMAGE_IS_ARRAY - const uint z = gl_WorkGroupID.z; - SharedMemory[gl_LocalInvocationID.x] = IMAGE_LOAD_SWIZZLE(imageFetch2DArray(InputImageX, InputSampler, ivec3(x, y, z), 0)); + SharedMemory[gl_LocalInvocationID.x] = IMAGE_LOAD_SWIZZLE(imageFetch2DArray(InputImageX, InputSampler, ivec3(x, y, z), 0)); #else - SharedMemory[gl_LocalInvocationID.x] = IMAGE_LOAD_SWIZZLE(imageFetch2D(InputImageX, InputSampler, ivec2(x, y), 0)); + SharedMemory[gl_LocalInvocationID.x] = IMAGE_LOAD_SWIZZLE(imageFetch2D(InputImageX, InputSampler, ivec2(x, y), 0)); #endif + } groupMemoryBarrier(); barrier(); @@ -152,7 +162,7 @@ void csMainY() { // get full resolution and inverse full resolution - ivec2 size = imageSize(BlurImageY).xy; + ivec2 size = Viewport; // calculate offsets const int tileStart = int(gl_WorkGroupID.x) * BLUR_TILE_WIDTH; @@ -162,15 +172,20 @@ csMainY() const int x = int(gl_WorkGroupID.y); const int y = max(0, min(apronStart + int(gl_LocalInvocationID.x), size.y - 1)); - - // load into workgroup saved memory, this allows us to use the original pixel even though - // we might have replaced it with the result from this thread! + const uint z = gl_WorkGroupID.z; + + if (x >= Viewport.x || y >= Viewport.y) + SharedMemory[gl_LocalInvocationID.x] = IMAGE_LOAD_VEC(0); + else + { + // load into workgroup saved memory, this allows us to use the original pixel even though + // we might have replaced it with the result from this thread! #if IMAGE_IS_ARRAY - const uint z = gl_WorkGroupID.z; - SharedMemory[gl_LocalInvocationID.x] = IMAGE_LOAD_SWIZZLE(imageFetch2DArray(InputImageY, InputSampler, ivec3(x, y, z), 0)); + SharedMemory[gl_LocalInvocationID.x] = IMAGE_LOAD_SWIZZLE(imageFetch2DArray(InputImageY, InputSampler, ivec3(x, y, z), 0)); #else - SharedMemory[gl_LocalInvocationID.x] = IMAGE_LOAD_SWIZZLE(imageFetch2D(InputImageY, InputSampler, ivec2(x, y), 0)); + SharedMemory[gl_LocalInvocationID.x] = IMAGE_LOAD_SWIZZLE(imageFetch2D(InputImageY, InputSampler, ivec2(x, y), 0)); #endif + } groupMemoryBarrier(); barrier(); diff --git a/syswork/shaders/vk/finalize.fx b/syswork/shaders/vk/finalize.fx index 0dd60a6007..8f7353e73d 100644 --- a/syswork/shaders/vk/finalize.fx +++ b/syswork/shaders/vk/finalize.fx @@ -112,7 +112,7 @@ DepthOfField(float depth, vec2 uv) // perform a gaussian blur around uv vec3 sampleColor = vec3(0.0f); float dofWeight = 1.0f / MAXDOFSAMPLES; - vec2 pixelSize = RenderTargetDimensions[0].zw; + vec2 pixelSize = RenderTargetParameter[0].Dimensions.zw; vec2 uvMul = focus * filterRadius * pixelSize.xy; int i; for (i = 0; i < MAXDOFSAMPLES; i++) @@ -132,17 +132,17 @@ psMain(in vec2 UV, [color0] out vec4 color) { // get an averaged depth value - float depth = sample2DLod(DepthTexture, DefaultSampler, UV, 0).r; + float depth = sample2DLod(DepthTexture, DefaultSampler, UV * RenderTargetParameter[0].Scale, 0).r; vec4 viewPos = PixelToView(UV, depth, InvProjection); - vec3 normal = sample2DLod(NormalBuffer, DefaultSampler, UV, 0).xyz; + vec3 normal = sample2DLod(NormalBuffer, DefaultSampler, UV * RenderTargetParameter[0].Scale, 0).xyz; vec4 worldPos = ViewToWorld(viewPos, InvView); vec3 viewVec = EyePos.xyz - worldPos.xyz; vec3 viewNormal = (View * vec4(normal, 0)).xyz; - vec4 c = vec4(sample2DLod(ColorTexture, DefaultSampler, UV, 0).rgb, 1.0f); + vec4 c = vec4(sample2DLod(ColorTexture, DefaultSampler, UV * RenderTargetParameter[0].Scale, 0).rgb, 1.0f); - vec4 bloom = sample2DLod(BloomTexture, UpscaleSampler, UV, 0); + vec4 bloom = sample2DLod(BloomTexture, UpscaleSampler, UV * RenderTargetParameter[0].Scale, 0); //vec4 godray = subpassLoad(InputAttachment1); c.rgb = lerp(c.rgb, bloom.rgb, bloom.a); diff --git a/syswork/shaders/vk/lib/geometrybase.fxh b/syswork/shaders/vk/lib/geometrybase.fxh index 4f1c97e515..7682029975 100644 --- a/syswork/shaders/vk/lib/geometrybase.fxh +++ b/syswork/shaders/vk/lib/geometrybase.fxh @@ -288,7 +288,7 @@ shader void psDepthOnly() { - vec2 seed = gl_FragCoord.xy * RenderTargetDimensions[0].zw; + vec2 seed = gl_FragCoord.xy * RenderTargetParameter[0].Dimensions.zw; float dither = hash12(seed); if (dither < DitherFactor) discard; @@ -301,7 +301,7 @@ shader void psDepthOnlyAlphaMask(in vec2 UV) { - vec2 seed = gl_FragCoord.xy * RenderTargetDimensions[0].zw; + vec2 seed = gl_FragCoord.xy * RenderTargetParameter[0].Dimensions.zw; float dither = hash12(seed); if (dither < DitherFactor) discard; @@ -592,7 +592,7 @@ psUberAlphaTest( [color2] out vec4 Material ) { - vec2 seed = gl_FragCoord.xy * RenderTargetDimensions[0].zw; + vec2 seed = gl_FragCoord.xy * RenderTargetParameter[0].Dimensions.zw; vec3 rnd = vec3(hash12(seed) + hash12(seed + 0.59374) - 0.5); float dither = (rnd.z + rnd.x + rnd.y) * DitherFactor; if (dither > 1.0f) @@ -627,7 +627,7 @@ psUberVertexColor( [color2] out vec4 Material ) { - vec2 seed = gl_FragCoord.xy * RenderTargetDimensions[0].zw; + vec2 seed = gl_FragCoord.xy * RenderTargetParameter[0].Dimensions.zw; vec3 rnd = vec3(hash12(seed) + hash12(seed + 0.59374) - 0.5); float dither = (rnd.z + rnd.x + rnd.y) * DitherFactor; if (dither > 1.0f) @@ -658,7 +658,7 @@ psUberAlpha(in vec3 ViewSpacePos, [color2] out vec4 Material ) { - vec2 seed = gl_FragCoord.xy * RenderTargetDimensions[0].zw; + vec2 seed = gl_FragCoord.xy * RenderTargetParameter[0].Dimensions.zw; vec3 rnd = vec3(hash12(seed) + hash12(seed + 0.59374) - 0.5); float dither = (rnd.z + rnd.x + rnd.y) * DitherFactor; if (dither > 1.0f) diff --git a/syswork/shaders/vk/lib/lighting_functions.fxh b/syswork/shaders/vk/lib/lighting_functions.fxh index 82ee4ab1f5..bf42a6d0ed 100644 --- a/syswork/shaders/vk/lib/lighting_functions.fxh +++ b/syswork/shaders/vk/lib/lighting_functions.fxh @@ -400,7 +400,11 @@ CalculateGlobalLight(vec3 diffuseColor, vec4 material, vec3 F0, vec3 viewVec, ve vec2 terrainUv = mad(worldSpacePosition.xz, InvTerrainSize, vec2(0.5f)); //shadowFactor *= sample2DLod(TerrainShadowBuffer, CSMTextureSampler, terrainUv, 0).r; - shadowFactor *= PCFShadow(TerrainShadowBuffer, terrainUv, TerrainShadowMapPixelSize); + vec2 terrainShadow = TerrainShadows(TerrainShadowBuffer, terrainUv, TerrainShadowMapPixelSize); + float blend = abs(worldSpacePosition.y - terrainShadow.y * 0.8f) / (terrainShadow.y - terrainShadow.y * 0.8f); + shadowFactor *= terrainShadow.x * blend; + //shadowFactor *= terrainShadow.x < 1.0f ? * terrainShadow.x : 1.0f; + //shadowFactor *= lerp(1.0f, terrainShadow.x, smoothstep(terrainShadow.y * 0.8f, terrainShadow.y, worldSpacePosition.y)); shadowFactor = lerp(1.0f, shadowFactor, GlobalLightShadowIntensity); } diff --git a/syswork/shaders/vk/lib/shadowbase.fxh b/syswork/shaders/vk/lib/shadowbase.fxh index 7569409686..92b575bf49 100644 --- a/syswork/shaders/vk/lib/shadowbase.fxh +++ b/syswork/shaders/vk/lib/shadowbase.fxh @@ -416,6 +416,23 @@ PCFShadow(textureHandle shadowMap, vec2 uv, vec2 texelSize) return (samp0 + samp1 + samp2 + samp3 + samp4) * 0.2f; } +//------------------------------------------------------------------------------ +/** +*/ +vec2 +TerrainShadows(textureHandle shadowMap, vec2 uv, vec2 texelSize) +{ + vec2 shadow = vec2(0.0f); + vec3 offsets = vec3(-2, 2, 0) * texelSize.xyx; + + vec2 samp0 = sample2DLod(shadowMap, ShadowSampler, uv + offsets.xz, 0).rg; + vec2 samp1 = sample2DLod(shadowMap, ShadowSampler, uv + offsets.yz, 0).rg; + vec2 samp2 = sample2DLod(shadowMap, ShadowSampler, uv + offsets.zx, 0).rg; + vec2 samp3 = sample2DLod(shadowMap, ShadowSampler, uv + offsets.zy, 0).rg; + vec2 samp4 = sample2DLod(shadowMap, ShadowSampler, uv, 0).rg; + return (samp0 + samp1 + samp2 + samp3 + samp4) * 0.2f; +} + //------------------------------------------------------------------------------ /** */ diff --git a/syswork/shaders/vk/lib/shared.fxh b/syswork/shaders/vk/lib/shared.fxh index 027dcdfa72..882a8c264e 100644 --- a/syswork/shaders/vk/lib/shared.fxh +++ b/syswork/shaders/vk/lib/shared.fxh @@ -480,9 +480,15 @@ group(PASS_GROUP) inputAttachment InputAttachment14; group(PASS_GROUP) inputAttachment InputAttachment15; group(PASS_GROUP) inputAttachment DepthAttachment; +struct RenderTargetParameters +{ + vec4 Dimensions; // render target dimensions are size (xy) inversed size (zw) + vec2 Scale; // dimensions / viewport +}; + group(PASS_GROUP) constant PassBlock { - vec4 RenderTargetDimensions[16]; // render target dimensions are size (xy) inversed size (zw) + RenderTargetParameters RenderTargetParameter[16]; // render target dimensions are size (xy) inversed size (zw) }; #endif // SHARED_H diff --git a/syswork/shaders/vk/lib/util.fxh b/syswork/shaders/vk/lib/util.fxh index 9adae865fe..8fcd70f3c6 100644 --- a/syswork/shaders/vk/lib/util.fxh +++ b/syswork/shaders/vk/lib/util.fxh @@ -103,7 +103,7 @@ CubicWeights(float v) Sample texture using bicubic sampling */ vec3 -SampleCubic(texture2D tex, sampler samp, vec4 res, vec2 pixel, int mip) +SampleCubic(texture2D tex, sampler samp, vec4 res, vec2 pixel, uint mip) { vec2 coords = pixel * res.xy - 0.5f; vec2 fxy = fract(coords); @@ -114,7 +114,7 @@ SampleCubic(texture2D tex, sampler samp, vec4 res, vec2 pixel, int mip) vec4 c = coords.xxyy + vec2(-0.5f, 1.5f).xyxy; vec4 s = vec4(xcubic.xz + xcubic.yw, ycubic.xz + ycubic.yw); - vec4 offset = c + vec4(xcubic.yw, ycubic.yw) / s; + vec4 offset = min(max(vec4(0), c + vec4(xcubic.yw, ycubic.yw) / s), res.xxyy); offset *= res.zzww; vec3 sample0 = textureLod(sampler2D(tex, samp), offset.xz, mip).rgb; diff --git a/syswork/shaders/vk/particle.fx b/syswork/shaders/vk/particle.fx index 2661dea5e5..c713f6c281 100644 --- a/syswork/shaders/vk/particle.fx +++ b/syswork/shaders/vk/particle.fx @@ -164,7 +164,7 @@ psUnlit(in vec4 ViewSpacePosition, in vec2 UV, [color0] out vec4 FinalColor) { - vec2 pixelSize = RenderTargetDimensions[0].zw; + vec2 pixelSize = RenderTargetParameter[0].Dimensions.zw; vec2 screenUV = PixelToNormalized(gl_FragCoord.xy, pixelSize.xy); vec4 diffColor = sample2D(_Unlit.AlbedoMap, ParticleSampler, UV); @@ -185,7 +185,7 @@ psUnlit2Layers(in vec4 ViewSpacePosition, in vec2 UV, [color0] out vec4 FinalColor) { - vec2 pixelSize = RenderTargetDimensions[0].zw; + vec2 pixelSize = RenderTargetParameter[0].Dimensions.zw; vec2 screenUV = PixelToNormalized(gl_FragCoord.xy, pixelSize.xy); vec4 layer1 = sample2D(_BlendAdd.AlbedoMap, LayerSampler, UV + _BlendAdd.UVAnim1 * Time_Random_Luminance_X.x); vec4 layer2 = sample2D(_BlendAdd.Layer2, LayerSampler, UV + _BlendAdd.UVAnim2 * Time_Random_Luminance_X.x); @@ -209,7 +209,7 @@ psUnlit3Layers(in vec4 ViewSpacePosition, in vec2 UV, [color0] out vec4 FinalColor) { - vec2 pixelSize = RenderTargetDimensions[0].zw; + vec2 pixelSize = RenderTargetParameter[0].Dimensions.zw; vec2 screenUV = PixelToNormalized(gl_FragCoord.xy, pixelSize.xy); vec4 layer1 = sample2D(_BlendAdd.AlbedoMap, LayerSampler, UV + _BlendAdd.UVAnim1 * Time_Random_Luminance_X.x); vec4 layer2 = sample2D(_BlendAdd.Layer2, LayerSampler, UV + _BlendAdd.UVAnim2 * Time_Random_Luminance_X.x); @@ -234,7 +234,7 @@ psUnlit4Layers(in vec4 ViewSpacePosition, in vec2 UV, [color0] out vec4 FinalColor) { - vec2 pixelSize = RenderTargetDimensions[0].zw; + vec2 pixelSize = RenderTargetParameter[0].Dimensions.zw; vec2 screenUV = PixelToNormalized(gl_FragCoord.xy, pixelSize.xy); vec4 layer1 = sample2D(_BlendAdd.AlbedoMap, LayerSampler, UV + _BlendAdd.UVAnim1 * Time_Random_Luminance_X.x); vec4 layer2 = sample2D(_BlendAdd.Layer2, LayerSampler, UV + _BlendAdd.UVAnim2 * Time_Random_Luminance_X.x); diff --git a/syswork/shaders/vk/shapes.fx b/syswork/shaders/vk/shapes.fx index ef00ee0831..77154c5020 100644 --- a/syswork/shaders/vk/shapes.fx +++ b/syswork/shaders/vk/shapes.fx @@ -97,10 +97,10 @@ gsLines( vec2 line0 = (p1 - p0); // Aspect correct the lines - line0 = normalize(line0.yx * vec2(-RenderTargetDimensions[0].y * RenderTargetDimensions[0].z, 1)); + line0 = normalize(line0.yx * vec2(-RenderTargetParameter[0].Dimensions.y * RenderTargetParameter[0].Dimensions.z, 1)); // Scale by line width and inversed resolution - line0 *= RenderTargetDimensions[0].zw * ShapeConstants.LineWidth; + line0 *= RenderTargetParameter[0].Dimensions.zw * ShapeConstants.LineWidth; // Emit triangle strip Color = colors[0]; diff --git a/tests/testrender/rendertest.cc b/tests/testrender/rendertest.cc index c25e61705b..883fb92785 100644 --- a/tests/testrender/rendertest.cc +++ b/tests/testrender/rendertest.cc @@ -17,6 +17,8 @@ #include "graphics/view.h" #include "graphics/cameracontext.h" +#include "frame/default.h" + using namespace Timing; using namespace Graphics; namespace Test @@ -53,7 +55,7 @@ RenderTest::Run() }; CoreGraphics::WindowId wnd = CreateWindow(wndInfo); - Ptr view = gfxServer->CreateView("mainview", "frame:vkdefault.json"); + Ptr view = gfxServer->CreateView("mainview", FrameScript_default::Run, Math::rectangle(0, 0, 640, 480)); Ptr stage = gfxServer->CreateStage("stage1", true); GraphicsEntityId cam = Graphics::CreateEntity(); diff --git a/tests/testviewer/scenes/clusteredlighting.cpp b/tests/testviewer/scenes/clusteredlighting.cpp index c57f43011e..80cf9928b3 100644 --- a/tests/testviewer/scenes/clusteredlighting.cpp +++ b/tests/testviewer/scenes/clusteredlighting.cpp @@ -10,6 +10,8 @@ #include "particles/particlecontext.h" #include "characters/charactercontext.h" +#include "materials/materialtemplates.h" + using namespace Timing; using namespace Graphics; using namespace Visibility; @@ -226,7 +228,6 @@ void OpenScene() static const int NumModels = 20; int modelIndex = 0; materialContexts.Resize((NumModels * 2) * (NumModels * 2)); - CoreGraphics::BatchGroup::Code code = CoreGraphics::BatchGroup::FromName("FlatGeometryLit"); for (IndexT i = -NumModels; i < NumModels; i++) { @@ -243,12 +244,12 @@ void OpenScene() const float timeOffset = Math::rand();// (((i + NumModels)* NumModels + (j + NumModels)) % 4) / 3.0f; // create model and move it to the front - ModelContext::Setup(ent, modelRes[modelIndex], "NotA", [ent, entityIndex, modelIndex, i, j, skeletonRes, animationRes, code]() + ModelContext::Setup(ent, modelRes[modelIndex], "NotA", [ent, entityIndex, modelIndex, i, j, skeletonRes, animationRes]() { ModelContext::SetTransform(ent, Math::translation(i * 16, 0, j * 16)); uint materialIndex = i + (j + NumModels) * (NumModels * 2); - entities[entityIndex].materialInstanceContext = &ModelContext::SetupMaterialInstanceContext(ent, code); + entities[entityIndex].materialInstanceContext = &ModelContext::SetupMaterialInstanceContext(ent, MaterialTemplates::BatchGroup::FlatGeometryLit); Graphics::RegisterEntity(ent); ObservableContext::Setup(ent, VisibilityEntityType::Model); diff --git a/tests/testviewer/viewerapp.cc b/tests/testviewer/viewerapp.cc index dd28207752..6a4c8d5a8f 100644 --- a/tests/testviewer/viewerapp.cc +++ b/tests/testviewer/viewerapp.cc @@ -26,6 +26,8 @@ #include "posteffects/downsamplingcontext.h" #include "physicsinterface.h" +#include "frame/default.h" + using namespace Timing; using namespace Graphics; using namespace Visibility; @@ -124,13 +126,10 @@ SimpleViewerApplication::Open() this->wnd = CreateWindow(wndInfo); this->cam = Graphics::CreateEntity(); - this->view = gfxServer->CreateView("mainview", "frame:vkdefault.json"_uri); + Ptr view = gfxServer->CreateView("mainview", FrameScript_default::Run, Math::rectangle(0, 0, width, height)); gfxServer->SetCurrentView(this->view); this->stage = gfxServer->CreateStage("stage1", true); - // setup post effects - Ptr frameScript = this->view->GetFrameScript(); - // Create contexts, this could and should be bundled together CameraContext::Create(); ModelContext::Create(); @@ -165,10 +164,10 @@ SimpleViewerApplication::Open() //Vegetation::VegetationContext::Create(vegSettings); Clustering::ClusterContext::Create(0.1f, 10000.0f, this->wnd); - Lighting::LightContext::Create(frameScript); + Lighting::LightContext::Create(); Decals::DecalContext::Create(); Im3d::Im3dContext::Create(); - Fog::VolumetricFogContext::Create(frameScript); + Fog::VolumetricFogContext::Create(); PostEffects::BloomContext::Create(); PostEffects::SSAOContext::Create(); PostEffects::HistogramContext::Create(); @@ -176,12 +175,12 @@ SimpleViewerApplication::Open() //PostEffects::SSRContext::Create(); // setup gbuffer bindings after frame script is loaded - Graphics::SetupBufferConstants(frameScript); - PostEffects::BloomContext::Setup(frameScript); - PostEffects::SSAOContext::Setup(frameScript); + Graphics::SetupBufferConstants(); + PostEffects::BloomContext::Setup(); + PostEffects::SSAOContext::Setup(); //PostEffects::SSRContext::Setup(frameScript); - PostEffects::DownsamplingContext::Setup(frameScript); - PostEffects::HistogramContext::Setup(frameScript); + PostEffects::DownsamplingContext::Setup(); + PostEffects::HistogramContext::Setup(); PostEffects::HistogramContext::SetWindow({ 0.0f, 0.0f }, { 1.0f, 1.0f }, 1); Im3d::Im3dContext::SetGridStatus(this->showGrid); @@ -225,7 +224,6 @@ SimpleViewerApplication::Open() Util::Array preLogicCalls = { - Im3d::Im3dContext::NewFrame, Dynui::ImguiContext::NewFrame, CameraContext::UpdateCameras, ModelContext::UpdateTransforms, @@ -257,7 +255,6 @@ SimpleViewerApplication::Open() ObserverContext::GenerateDrawLists, // At the very latest point, wait for work to finish - Dynui::ImguiContext::Render, ModelContext::WaitForWork, Characters::CharacterContext::WaitForCharacterJobs, Particles::ParticleContext::WaitForParticleUpdates, @@ -282,9 +279,6 @@ SimpleViewerApplication::Open() this->consoleHandler->Setup(); this->profiler = Dynui::ImguiProfiler::Create(); - // Before starting the frame, build the frame script - this->view->BuildFrameScript(); - return true; } return false; diff --git a/tests/testvisibility/visibilitytest.cc b/tests/testvisibility/visibilitytest.cc index 28095f4af0..2e9fb5e24a 100644 --- a/tests/testvisibility/visibilitytest.cc +++ b/tests/testvisibility/visibilitytest.cc @@ -32,6 +32,8 @@ #include "dynui/imguicontext.h" #include "imgui.h" +#include "frame/default.h" + using namespace Timing; using namespace Graphics; using namespace Visibility; @@ -74,12 +76,9 @@ VisibilityTest::Run() }; CoreGraphics::WindowId wnd = CreateWindow(wndInfo); - Ptr view = gfxServer->CreateView("mainview", "frame:vkdefault.json"_uri); + Ptr view = gfxServer->CreateView("mainview", FrameScript_default::Run, Math::rectangle(0, 0, 1024, 768)); Ptr stage = gfxServer->CreateStage("stage1", true); - // setup post effects - Ptr frameScript = view->GetFrameScript(); - // create contexts, this could and should be bundled together CameraContext::Create(); ModelContext::Create(); @@ -88,9 +87,7 @@ VisibilityTest::Run() Clustering::ClusterContext::Create(0.1f, 1000.0f, wnd); Im3d::Im3dContext::Create(); Dynui::ImguiContext::Create(); - Lighting::LightContext::Create(frameScript); - - + Lighting::LightContext::Create(); // setup camera and view GraphicsEntityId cam = Graphics::CreateEntity(); @@ -168,8 +165,6 @@ VisibilityTest::Run() float zoomIn = 0.0f; float zoomOut = 0.0f; - view->BuildFrameScript(); - Timer timer; IndexT frameIndex = -1; double previousTime = 0.0f; diff --git a/toolkit/editor/CMakeLists.txt b/toolkit/editor/CMakeLists.txt index 0d3ab0ee90..71ae70c00d 100644 --- a/toolkit/editor/CMakeLists.txt +++ b/toolkit/editor/CMakeLists.txt @@ -28,6 +28,7 @@ fips_dir(.) fips_files_ex(scripts/ *.py GROUP "scripts") fips_dir(render) + nebula_framescript_add(editorframe.json) fips_files( pickingcontext.h pickingcontext.cc diff --git a/toolkit/editor/editor/tools/camera.cc b/toolkit/editor/editor/tools/camera.cc index 35a688918a..87bea394ea 100644 --- a/toolkit/editor/editor/tools/camera.cc +++ b/toolkit/editor/editor/tools/camera.cc @@ -175,6 +175,20 @@ Camera::SetProjectionMode(ProjectionMode mode) } } +//------------------------------------------------------------------------------ +/** +*/ +void +Camera::SetViewDimensions(SizeT screenWidth, SizeT screenHeight) +{ + if (this->screenWidth != screenWidth || this->screenHeight != screenHeight) + { + this->screenWidth = screenWidth; + this->screenHeight = screenHeight; + this->SetProjectionMode(this->projectionMode); + } +} + //------------------------------------------------------------------------------ /** */ diff --git a/toolkit/editor/editor/tools/camera.h b/toolkit/editor/editor/tools/camera.h index 98a7e3f54e..ca2af1fc3b 100644 --- a/toolkit/editor/editor/tools/camera.h +++ b/toolkit/editor/editor/tools/camera.h @@ -44,6 +44,9 @@ class Camera bool const GetProjectionMode() const; void SetProjectionMode(ProjectionMode mode); + /// Set view dimensions + void SetViewDimensions(SizeT screenWidth, SizeT screenHeight); + void SetTransform(Math::mat4 const& val); Math::mat4 GetViewTransform() const; diff --git a/toolkit/editor/editor/ui/modules/viewport.cc b/toolkit/editor/editor/ui/modules/viewport.cc index 103842d5c2..0d3be25c00 100644 --- a/toolkit/editor/editor/ui/modules/viewport.cc +++ b/toolkit/editor/editor/ui/modules/viewport.cc @@ -11,6 +11,8 @@ #include "dynui/imguicontext.h" #include "editor/editor/tools/selectiontool.h" +#include "frame/default.h" + namespace Presentation { @@ -42,7 +44,7 @@ Viewport::Init(Util::String const & viewName) static int unique = 0; Util::String name = viewName; name.AppendInt(unique++); - this->view = Graphics::GraphicsServer::Instance()->CreateView(name, "frame:vkdefault.json"); + this->view = Graphics::GraphicsServer::Instance()->CreateView(name, FrameScript_default::Run, Math::rectangle(0, 0, 1280, 900)); this->camera.Setup(1280, 900); this->camera.AttachToView(this->view); @@ -89,9 +91,6 @@ Viewport::Update() void Viewport::Render() { - Ptr frameServer = Frame::FrameServer::Instance(); - Ptr frame = this->view->GetFrameScript(); - if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenu("Camera")) @@ -184,7 +183,7 @@ Viewport::Render() ImGui::EndMenuBar(); } - CoreGraphics::TextureId textureId = frame->GetTexture(this->frameBuffer); + CoreGraphics::TextureId textureId = FrameScript_default::Texture_SceneBuffer(); CoreGraphics::TextureDimensions dims = CoreGraphics::TextureGetDimensions(textureId); using namespace CoreGraphics; @@ -198,22 +197,27 @@ Viewport::Render() textureInfo.mip = 0; textureInfo.layer = 0; - ImVec2 imageSize = {(float)dims.width, (float)dims.height}; - imageSize.x = ImGui::GetWindowContentRegionMax().x - ImGui::GetWindowContentRegionMin().x; - float ratio = (float)dims.height / (float)dims.width; - imageSize.y = imageSize.x * ratio; - + ImVec2 space = ImGui::GetContentRegionAvail(); ImVec2 cursorPos = ImGui::GetCursorPos(); ImVec2 windowPos = ImGui::GetWindowPos(); - ImVec2 imagePosition = {cursorPos.x + windowPos.x, cursorPos.y + windowPos.y }; + + ImVec2 imageSize = {(float)space.x, (float)space.y}; + imageSize.x = Math::max(imageSize.x, 1.0f); + imageSize.y = Math::max(imageSize.y, 1.0f); + ImVec2 uv = { space.x / dims.width, space.y / dims.height }; + this->camera.SetViewDimensions(imageSize.x, imageSize.y); //auto windowSize = ImGui::GetWindowSize(); //windowSize.y -= ImGui::GetCursorPosY() - 20; - ImGui::Image((void*)&textureInfo, imageSize, ImVec2(0, 0), ImVec2(1, 1)); + ImGui::Image((void*)&textureInfo, imageSize, ImVec2(0, 0), uv); + + ImVec2 imagePosition = { cursorPos.x + windowPos.x, cursorPos.y + windowPos.y }; this->lastViewportImagePosition = { imagePosition.x / dims.width, imagePosition.y / dims.height }; this->lastViewportImageSize = { imageSize.x / dims.width, imageSize.y / dims.height }; + auto view = Graphics::GraphicsServer::Instance()->GetView("mainview"); + view->SetViewport(Math::rectangle(0, 0, imageSize.x, imageSize.y)); this->hovered = ImGui::IsItemHovered(); if (this->hovered) diff --git a/toolkit/editor/editor/ui/uimanager.cc b/toolkit/editor/editor/ui/uimanager.cc index 2bedfd9247..3d2a11afa8 100644 --- a/toolkit/editor/editor/ui/uimanager.cc +++ b/toolkit/editor/editor/ui/uimanager.cc @@ -23,6 +23,9 @@ #include "io/filedialog.h" #include "window.h" +#include "frame/default.h" +#include "frame/editorframe.h" + namespace Editor { @@ -84,11 +87,24 @@ OnActivate() Editor::state.editorWorld->ExportLevel(path.AsCharPtr()); }, "Export", "Ctrl+Shift+E", "File"); - Dynui::ImguiContext::state.dockOverViewport = true; - - GraphicsFeature::GraphicsFeatureUnit::Instance()->AddRenderUICallback([]() + Graphics::GraphicsServer::Instance()->AddPostViewCall([](IndexT frameIndex, IndexT bufferIndex) { + ImGui::DockSpaceOverViewport(); windowServer->RunAll(); + FrameScript_editorframe::Bind_Scene(FrameScript_default::Submission_Scene); + FrameScript_editorframe::Bind_SceneBuffer(Frame::TextureImport::FromExport(FrameScript_default::Export_ColorBuffer)); + CoreGraphics::DisplayMode mode = CoreGraphics::WindowGetDisplayMode(CoreGraphics::CurrentWindow); + Math::rectangle viewport(0, 0, mode.GetWidth(), mode.GetHeight()); + FrameScript_editorframe::Run(viewport, frameIndex, bufferIndex); + + Graphics::GraphicsServer::SwapInfo swapInfo; + swapInfo.syncFunc = [](CoreGraphics::CmdBufferId cmdBuf) + { + FrameScript_editorframe::Synchronize("Present_Sync", cmdBuf, { { (FrameScript_editorframe::TextureIndex)FrameScript_editorframe::Export_EditorBuffer.index, CoreGraphics::PipelineStage::TransferRead } }, nullptr); + }; + swapInfo.submission = FrameScript_editorframe::Submission_EditorUI; + swapInfo.swapSource = FrameScript_editorframe::Export_EditorBuffer.tex; + Graphics::GraphicsServer::Instance()->SetSwapInfo(swapInfo); }); } diff --git a/toolkit/editor/editor/ui/windows/asseteditor/materialasseteditor.cc b/toolkit/editor/editor/ui/windows/asseteditor/materialasseteditor.cc index 9c108a73c3..a522249ee2 100644 --- a/toolkit/editor/editor/ui/windows/asseteditor/materialasseteditor.cc +++ b/toolkit/editor/editor/ui/windows/asseteditor/materialasseteditor.cc @@ -279,6 +279,8 @@ MaterialEditor(AssetEditor* assetEditor, AssetEditorItem* item) { ImGui::SetTooltip(kvp.Value()->desc); } + + StackFree(imguiState); } } diff --git a/toolkit/editor/render/editorframe.json b/toolkit/editor/render/editorframe.json new file mode 100644 index 0000000000..9779cf1d32 --- /dev/null +++ b/toolkit/editor/render/editorframe.json @@ -0,0 +1,68 @@ +{ + "Nebula": { + "version": 3, + "Dependencies": [ + "Scene" + ], + "ImportTextures": [ + "SceneBuffer" + ], + "LocalTextures": [ + { + "name": "EditorBuffer", + "format": "SRGBA8", + "relative": true, + "usage": "Render|TransferSource", + "relativeSize": [ 1.0, 1.0 ], + "type": "Texture2D" + } + ], + "ExportTextures": [ + "EditorBuffer", + ], + "Submissions": [ + { + "name": "Editor UI", + "queue": "Graphics", + "wait_for_submissions": [ "Scene" ], + "last_submit": true, + "_comment": "Render Editor UI", + "ops": [ + { + "pass": { + "name": "Editor", + "attachments": [ + { + "name": "EditorBuffer", + "flags": "Store" + } + ], + "subpasses": [ + { + "name": "Editor Pass", + "subpass_dependencies": [], + "attachments": [ + "EditorBuffer" + ], + "ops": [ + { + "subgraph": { + "name": "ImGUI" + } + } + ] + } + ] + } + }, + { + "transition": { + "name": "EditorBuffer", + "stage": "ComputeShaderRead" + } + } + ] + } + ] + } +} \ No newline at end of file diff --git a/toolkit/toolkitutil/model/import/fbx/node/nfbxmeshnode.cc b/toolkit/toolkitutil/model/import/fbx/node/nfbxmeshnode.cc index 2be8b0f9ac..c9a90ee018 100644 --- a/toolkit/toolkitutil/model/import/fbx/node/nfbxmeshnode.cc +++ b/toolkit/toolkitutil/model/import/fbx/node/nfbxmeshnode.cc @@ -261,6 +261,7 @@ NFbxMeshNode::ExtractMesh( } mesh.AddTriangle(meshTriangle); } + StackFree(indices); } if (AllBits(node->mesh.meshFlags, HasNormals))