diff --git a/.vscode/launch.json b/.vscode/launch.json index 853ab2a..5112b5a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,12 +6,24 @@ "configurations": [ { "name": "Editor", - "type": "lldb", + "type": "cppvsdbg", "request": "launch", "program": "${workspaceRoot}/build/Editor.exe", "args": [], "cwd": "${workspaceRoot}/build", "console": "internalConsole", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ] }, { "name": "Editor (Mac)", diff --git a/cmake-variants.json b/cmake-variants.json index 17db80a..b95b28d 100644 --- a/cmake-variants.json +++ b/cmake-variants.json @@ -22,6 +22,11 @@ "short": "RelWithDebInfo", "long": "Release with debug symbols", "buildType": "RelWithDebInfo" + }, + "minsizerel": { + "short": "MinSizeRel", + "long": "Minimal size Release", + "buildType": "MinSizeRel" } } }, diff --git a/res/shaders/DepthCullingTask.slang b/res/shaders/DepthCullingTask.slang index ddb7f4d..0a554e3 100644 --- a/res/shaders/DepthCullingTask.slang +++ b/res/shaders/DepthCullingTask.slang @@ -3,47 +3,29 @@ import Scene; groupshared MeshPayload p; groupshared uint head; -groupshared Frustum viewFrustum; [numthreads(TASK_GROUP_SIZE, 1, 1)] -[outputtopology("triangle")] [shader("amplification")] void taskMain( uint threadID: SV_GroupIndex, - uint groupID: SV_GroupID + uint groupID: SV_GroupID, ){ InstanceData instance = pScene.instances[pOffsets.instanceOffset + groupID]; MeshData mesh = pScene.meshData[pOffsets.instanceOffset + groupID]; - if(threadID == 0) - { - head = 0; - float3 origin = viewToModel(instance.inverseTransformMatrix, float4(0, 0, 0, 1)).xyz; - const float offset = 0.0f; - float3 corners[4] = { - screenToModel(instance.inverseTransformMatrix, float4(offset, offset, -1.0f, 1.0f)).xyz, - screenToModel(instance.inverseTransformMatrix, float4(pViewParams.screenDimensions.x - offset, offset, -1.0f, 1.0f)).xyz, - screenToModel(instance.inverseTransformMatrix, float4(offset, pViewParams.screenDimensions.y - offset, -1.0f, 1.0f)).xyz, - screenToModel(instance.inverseTransformMatrix, float4(pViewParams.screenDimensions - float2(offset, offset), -1.0f, 1.0f)).xyz - }; - viewFrustum.sides[0] = computePlane(origin, corners[2], corners[0]); - viewFrustum.sides[1] = computePlane(origin, corners[1], corners[3]); - viewFrustum.sides[2] = computePlane(origin, corners[0], corners[1]); - viewFrustum.sides[3] = computePlane(origin, corners[3], corners[2]); - p.instanceId = pOffsets.instanceOffset + groupID; - p.cullingOffset = pScene.cullingOffsets[pOffsets.cullingCounterOffset + groupID]; - } - GroupMemoryBarrierWithGroupSync(); - for(uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE) - { - uint m = mesh.meshletOffset + i; - MeshletDescription meshlet = pScene.meshletInfos[m]; - if(meshlet.bounding.insideFrustum(viewFrustum)) - { - uint index; - InterlockedAdd(head, 1, index); - pScene.culledMeshlets[p.cullingOffset + index] = m; - } - } - GroupMemoryBarrierWithGroupSync(); - DispatchMesh(head, 1, 1, p); -} \ No newline at end of file + //head = 0; + //GroupMemoryBarrierWithGroupSync(); + //for(uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE) + //{ + // uint m = mesh.meshletOffset + i; + // MeshletDescription meshlet = pScene.meshletInfos[m]; + // MeshletCullingInfo culling = pScene.culledMeshlets[instance.meshletCullingOffset]; + // if(culling.anyVisible()) + // { + // uint index; + // InterlockedAdd(head, 1, index); + // p.culledMeshlets[index] = m; + // } + //} + //GroupMemoryBarrierWithGroupSync(); + //DispatchMesh(head, 1, 1, p); +} diff --git a/res/shaders/DrawListTask.slang b/res/shaders/DrawListTask.slang new file mode 100644 index 0000000..f1b8829 --- /dev/null +++ b/res/shaders/DrawListTask.slang @@ -0,0 +1,34 @@ +import Common; +import Scene; + +groupshared MeshPayload p; +groupshared uint head; + +[numthreads(TASK_GROUP_SIZE, 1, 1)] +[shader("amplification")] +void taskMain( + uint threadID: SV_GroupIndex, + uint groupID: SV_GroupID, ) +{ + if (threadID == 0) + { + head = 0; + p.instanceId = pOffsets.instanceOffset + groupID; + } + GroupMemoryBarrierWithGroupSync(); + MeshData mesh = pScene.meshData[p.instanceId]; + for (uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE) + { + uint m = mesh.meshletOffset + i; + //MeshletDescription meshlet = pScene.meshletInfos[m]; + //MeshletCullingInfo culling = pScene.culledMeshlets[pScene.cullingOffsets[p.instanceId] + i]; + //if(culling.anyVisible()) + { + uint index; + InterlockedAdd(head, 1, index); + p.culledMeshlets[i] = m; + } + } + GroupMemoryBarrierWithGroupSync(); + DispatchMesh(mesh.numMeshlets, 1, 1, p); +} diff --git a/res/shaders/StaticMeshletPass.slang b/res/shaders/StaticMeshletPass.slang deleted file mode 100644 index 63b2048..0000000 --- a/res/shaders/StaticMeshletPass.slang +++ /dev/null @@ -1,51 +0,0 @@ -import Common; -import BRDF; -import Scene; -import VertexData; -import MaterialParameter; - -struct PrimitiveAttributes -{ - uint cull: SV_CullPrimitive; -}; - -struct CulledMeshletList -{ - StructuredBuffer meshletIndices; -}; -ParameterBlock pCullingList; - -[numthreads(MESH_GROUP_SIZE, 1, 1)] -[outputtopology("triangle")] -[shader("mesh")] -void meshMain( - in uint threadID: SV_GroupIndex, - in uint groupID: SV_GroupID, - out vertices FragmentParameter vertices[MAX_VERTICES], - out indices uint3 indices[MAX_PRIMITIVES] -){ - uint meshletIndex = pCullingList.meshletIndices[groupID]; - MeshletDescription m = pScene.meshletInfos[meshletIndex]; - SetMeshOutputCounts(m.vertexCount, m.primitiveCount); - - for(uint i = threadID; i < MAX_PRIMITIVES; i += MESH_GROUP_SIZE) - { - uint p = min(i, m.primitiveCount - 1); - { - uint local_idx0 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 0]; - uint local_idx1 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 1]; - uint local_idx2 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 2]; - indices[p] = uint3(local_idx0, local_idx1, local_idx2); - } - } - for(uint i = threadID; i < MAX_VERTICES; i+=MESH_GROUP_SIZE) - { - uint v = min(i, m.vertexCount - 1); - { - uint vertexIndex = pScene.vertexIndices[m.vertexOffset + v]; - VertexAttributes attr = pVertexData.getAttributes(m.indicesOffset + vertexIndex); - attr.meshletId = meshletIndex; - vertices[v] = attr.getParameter(float4x4(1.0)); - } - } -} \ No newline at end of file diff --git a/res/shaders/ViewCullingTask.slang b/res/shaders/ViewCullingTask.slang index 74550cf..855cc47 100644 --- a/res/shaders/ViewCullingTask.slang +++ b/res/shaders/ViewCullingTask.slang @@ -29,7 +29,6 @@ void taskMain( viewFrustum.sides[2] = computePlane(origin, corners[0], corners[1]); viewFrustum.sides[3] = computePlane(origin, corners[3], corners[2]); p.instanceId = pOffsets.instanceOffset + groupID; - //p.cullingOffset = pScene.cullingOffsets[pOffsets.cullingCounterOffset + groupID]; } GroupMemoryBarrierWithGroupSync(); for(uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE) @@ -43,7 +42,6 @@ void taskMain( uint index; InterlockedAdd(head, 1, index); p.culledMeshlets[index] = m; - //pScene.culledMeshlets[p.cullingOffset + index] = m; } } GroupMemoryBarrierWithGroupSync(); diff --git a/res/shaders/lib/Scene.slang b/res/shaders/lib/Scene.slang index 7f1f964..2730ec4 100644 --- a/res/shaders/lib/Scene.slang +++ b/res/shaders/lib/Scene.slang @@ -31,9 +31,25 @@ struct InstanceData float4x4 inverseTransformMatrix; }; +struct MeshletCullingInfo +{ + uint64_t cull[MAX_PRIMITIVES / 64]; + // lookup if a specific triangle is visible + bool triangleVisible(uint32_t primIndex) + { + uint32_t arrIdx = primIndex / 64; + uint32_t cullIdx = primIndex % 64; + return (cull[arrIdx] & (1 << cullIdx)) != 0; + } + bool anyVisible() + { + return (cull[0] | cull[1] | cull[2] | cull[3]) != 0; + } +}; + struct DrawCallOffsets { - uint32_t instanceOffset; + uint32_t instanceOffset; }; layout(push_constant) ConstantBuffer pOffsets; @@ -45,8 +61,8 @@ struct Scene StructuredBuffer meshletInfos; StructuredBuffer primitiveIndices; StructuredBuffer vertexIndices; -// StructuredBuffer cullingOffsets; -// RWStructuredBuffer culledMeshlets; + StructuredBuffer culledMeshlets; + StructuredBuffer cullingOffsets; }; layout(set=2) ParameterBlock pScene; diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index c35721c..8edc78a 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -42,7 +42,7 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) if (graphics->supportMeshShading()) { - graphics->getShaderCompiler()->registerRenderPass(basePassLayout, "BasePass", "MeshletPass", true, true, "BasePass", true, true, "ViewCullingTask"); + graphics->getShaderCompiler()->registerRenderPass(basePassLayout, "BasePass", "MeshletPass", true, true, "BasePass", true, true, "DrawListTask"); } else { @@ -91,7 +91,7 @@ void BasePass::render() Gfx::ShaderPermutation permutation; if (graphics->supportMeshShading()) { - permutation.setTaskFile("ViewCullingTask"); + permutation.setTaskFile("DrawListTask"); permutation.setMeshFile("MeshletPass"); } else @@ -140,7 +140,7 @@ void BasePass::render() .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL, }, .colorBlend = { - .attachmentCount = 2, + .attachmentCount = 1, }, }; Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); @@ -160,7 +160,7 @@ void BasePass::render() .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL, }, .colorBlend = { - .attachmentCount = 2, + .attachmentCount = 1, }, }; Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); @@ -182,11 +182,10 @@ void BasePass::render() else { command->bindIndexBuffer(vertexData->getIndexBuffer()); - uint32 inst = drawCall.offsets.instanceOffset; for (const auto& meshData : drawCall.instanceMeshData) { // all meshlets of a mesh share the same indices offset - command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, vertexData->getIndicesOffset(meshData.meshletOffset), inst++); + command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, vertexData->getIndicesOffset(meshData.meshletOffset), 0); } } } @@ -208,17 +207,6 @@ void BasePass::publishOutputs() Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE); resources->registerRenderPassOutput("BASEPASS_COLOR", colorAttachment); - - meshletIdTexture = graphics->createTexture2D(TextureCreateInfo{ - .format = Gfx::SE_FORMAT_R32_UINT, - .width = viewport->getWidth(), - .height = viewport->getHeight(), - .usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_STORAGE_BIT, - }); - meshletIdAttachment = Gfx::RenderTargetAttachment(meshletIdTexture, - Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE); - resources->registerRenderPassOutput("BASEPASS_MESHLETID", meshletIdAttachment); } void BasePass::createRenderPass() @@ -228,7 +216,7 @@ void BasePass::createRenderPass() depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL); depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ - .colorAttachments = { colorAttachment, meshletIdAttachment }, + .colorAttachments = { colorAttachment }, .depthAttachment = depthAttachment, }; Array dependency = { @@ -245,7 +233,7 @@ void BasePass::createRenderPass() .dstSubpass = 0, .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, .dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - .srcAccess = Gfx::SE_ACCESS_NONE, + .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, .dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, }, { @@ -262,7 +250,7 @@ void BasePass::createRenderPass() .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, .dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - .dstAccess = Gfx::SE_ACCESS_NONE, + .dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, }, }; renderPass = graphics->createRenderPass(std::move(layout), std::move(dependency), viewport); diff --git a/src/Engine/Graphics/RenderPass/BasePass.h b/src/Engine/Graphics/RenderPass/BasePass.h index c80c72e..aa7f992 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.h +++ b/src/Engine/Graphics/RenderPass/BasePass.h @@ -20,12 +20,11 @@ public: private: Gfx::RenderTargetAttachment colorAttachment; Gfx::RenderTargetAttachment depthAttachment; - Gfx::RenderTargetAttachment meshletIdAttachment; + Gfx::RenderTargetAttachment visibilityAttachment; Gfx::PShaderBuffer oLightIndexList; Gfx::PShaderBuffer tLightIndexList; Gfx::PTexture2D oLightGrid; Gfx::PTexture2D tLightGrid; - Gfx::OTexture2D meshletIdTexture; Gfx::PDescriptorSet opaqueCulling; Gfx::PDescriptorSet transparentCulling; diff --git a/src/Engine/Graphics/RenderPass/CMakeLists.txt b/src/Engine/Graphics/RenderPass/CMakeLists.txt index 192817b..78eef0e 100644 --- a/src/Engine/Graphics/RenderPass/CMakeLists.txt +++ b/src/Engine/Graphics/RenderPass/CMakeLists.txt @@ -2,6 +2,8 @@ target_sources(Engine PRIVATE BasePass.h BasePass.cpp + CachedDepthPass.h + CachedDepthPass.cpp DebugPass.h DebugPass.cpp DepthPrepass.h @@ -15,10 +17,6 @@ target_sources(Engine RenderPass.cpp SkyboxRenderPass.h SkyboxRenderPass.cpp - #StaticDepthPrepass.h - #StaticDepthPrepass.cpp - #StaticBasePass.h - #StaticBasePass.cpp TextPass.h TextPass.cpp UIPass.h @@ -28,6 +26,7 @@ target_sources(Engine PUBLIC FILE_SET HEADERS FILES BasePass.h + CachedDepthPass.h DebugPass.h DepthPrepass.h LightCullingPass.h @@ -35,7 +34,5 @@ target_sources(Engine RenderGraphResources.h RenderPass.h SkyboxRenderPass.h - #StaticDepthPrepass.h - #StaticBasePass.h TextPass.h UIPass.h) \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp b/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp new file mode 100644 index 0000000..f7e7ebd --- /dev/null +++ b/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp @@ -0,0 +1,222 @@ +#include "CachedDepthPass.h" +#include "Graphics/Shader.h" + +using namespace Seele; + +extern bool usePositionOnly; +extern bool useViewCulling; + +CachedDepthPass::CachedDepthPass(Gfx::PGraphics graphics, PScene scene) + : RenderPass(graphics, scene) +{ + depthPrepassLayout = graphics->createPipelineLayout("CachedDepthLayout"); + depthPrepassLayout->addDescriptorLayout(viewParamsLayout); + depthPrepassLayout->addPushConstants(Gfx::SePushConstantRange{ + .stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, + .offset = 0, + .size = sizeof(VertexData::DrawCallOffsets), + }); + if (graphics->supportMeshShading()) + { + graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "CachedDepthPass", "MeshletPass", false, false, "", true, true, "DrawListTask"); + } + else + { + graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "CachedDepthPass", "LegacyPass"); + } +} + +CachedDepthPass::~CachedDepthPass() +{ +} + +void CachedDepthPass::beginFrame(const Component::Camera &cam) +{ + RenderPass::beginFrame(cam); +} + +void CachedDepthPass::render() +{ + graphics->beginRenderPass(renderPass); + Array commands; + + Gfx::ShaderPermutation permutation; + permutation.setPositionOnly(usePositionOnly); + permutation.setViewCulling(useViewCulling); + if (graphics->supportMeshShading()) + { + permutation.setTaskFile("DrawListTask"); + permutation.setMeshFile("MeshletPass"); + } + else + { + permutation.setVertexFile("LegacyPass"); + } + for (VertexData *vertexData : VertexData::getList()) + { + permutation.setVertexData(vertexData->getTypeName()); + + // Create Pipeline(VertexData) + // Descriptors: + // ViewData => global, static + // VertexData => per meshtype + // SceneData => per meshtype + Gfx::PermutationId id(permutation); + + Gfx::ORenderCommand command = graphics->createRenderCommand("DepthRender"); + command->setViewport(viewport); + + const Gfx::ShaderCollection *collection = graphics->getShaderCompiler()->findShaders(id); + assert(collection != nullptr); + if (graphics->supportMeshShading()) + { + Gfx::MeshPipelineCreateInfo pipelineInfo = { + .taskShader = collection->taskShader, + .meshShader = collection->meshShader, + .fragmentShader = collection->fragmentShader, + .renderPass = renderPass, + .pipelineLayout = collection->pipelineLayout, + .multisampleState = { + .samples = viewport->getSamples(), + }, + .depthStencilState = { + .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER, + }, + .colorBlend = { + .attachmentCount = 1, + }, + }; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); + } + else + { + Gfx::LegacyPipelineCreateInfo pipelineInfo = { + .vertexShader = collection->vertexShader, + .fragmentShader = collection->fragmentShader, + .renderPass = renderPass, + .pipelineLayout = collection->pipelineLayout, + .multisampleState = { + .samples = viewport->getSamples(), + }, + .depthStencilState = { + .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER, + }, + .colorBlend = { + .attachmentCount = 1, + }, + }; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); + } + command->bindDescriptor(vertexData->getVertexDataSet()); + command->bindDescriptor(viewParamsSet); + command->bindDescriptor(vertexData->getInstanceDataSet()); + uint32 offset = 0; + command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets), &offset); + if (graphics->supportMeshShading()) + { + command->drawMesh(vertexData->getNumInstances(), 1, 1); + } + else + { + const auto &materials = vertexData->getMaterialData(); + for (const auto &materialData : materials) + { + // material not used for any active meshes, skip + if (materialData.instances.size() == 0) + continue; + for (const auto &drawCall : materialData.instances) + { + command->bindIndexBuffer(vertexData->getIndexBuffer()); + uint32 inst = drawCall.offsets.instanceOffset; + for (const auto &meshData : drawCall.instanceMeshData) + { + // all meshlets of a mesh share the same indices offset + command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, vertexData->getIndicesOffset(meshData.meshletOffset), inst++); + } + } + } + } + commands.add(std::move(command)); + } + + graphics->executeCommands(std::move(commands)); + graphics->endRenderPass(); +} + +void CachedDepthPass::endFrame() +{ +} + +void CachedDepthPass::publishOutputs() +{ + // If we render to a part of an image, the depth buffer itself must + // still match the size of the whole image or their coordinate systems go out of sync + TextureCreateInfo depthBufferInfo = { + .format = Gfx::SE_FORMAT_D32_SFLOAT, + .width = viewport->getOwner()->getFramebufferWidth(), + .height = viewport->getOwner()->getFramebufferHeight(), + .usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + }; + depthBuffer = graphics->createTexture2D(depthBufferInfo); + depthAttachment = + Gfx::RenderTargetAttachment(depthBuffer, + Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE); + resources->registerRenderPassOutput("DEPTHPREPASS_DEPTH", depthAttachment); + + TextureCreateInfo visibilityInfo = { + .format = Gfx::SE_FORMAT_R32G32_UINT, + .width = viewport->getOwner()->getFramebufferWidth(), + .height = viewport->getOwner()->getFramebufferHeight(), + .usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + }; + visibilityBuffer = graphics->createTexture2D(visibilityInfo); + visibilityAttachment = + Gfx::RenderTargetAttachment(visibilityBuffer, + Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE); + resources->registerRenderPassOutput("VISIBILITY", visibilityAttachment); +} + +void CachedDepthPass::createRenderPass() +{ + Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ + .depthAttachment = depthAttachment, + }; + Array dependency = { + { + .srcSubpass = ~0U, + .dstSubpass = 0, + .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + }, + { + .srcSubpass = 0, + .dstSubpass = ~0U, + .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT, + }, + { + .srcSubpass = 0, + .dstSubpass = ~0U, + .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, + }, + { + .srcSubpass = 0, + .dstSubpass = ~0U, + .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + }}; + renderPass = graphics->createRenderPass(std::move(layout), std::move(dependency), viewport); +} diff --git a/src/Engine/Graphics/RenderPass/CachedDepthPass.h b/src/Engine/Graphics/RenderPass/CachedDepthPass.h new file mode 100644 index 0000000..cdba89d --- /dev/null +++ b/src/Engine/Graphics/RenderPass/CachedDepthPass.h @@ -0,0 +1,26 @@ +#pragma once +#include "RenderPass.h" + +namespace Seele +{ +class CachedDepthPass : public RenderPass +{ +public: + CachedDepthPass(Gfx::PGraphics graphics, PScene scene); + CachedDepthPass(CachedDepthPass&&) = default; + CachedDepthPass& operator=(CachedDepthPass&&) = default; + virtual ~CachedDepthPass(); + virtual void beginFrame(const Component::Camera& cam) override; + virtual void render() override; + virtual void endFrame() override; + virtual void publishOutputs() override; + virtual void createRenderPass() override; +private: + Gfx::RenderTargetAttachment depthAttachment; + Gfx::RenderTargetAttachment visibilityAttachment; + Gfx::OTexture2D depthBuffer; + Gfx::OTexture2D visibilityBuffer; + Gfx::OPipelineLayout depthPrepassLayout; +}; +DEFINE_REF(CachedDepthPass) +} \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp index 1958687..4c2258a 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp @@ -1,15 +1,5 @@ #include "DepthPrepass.h" -#include "Graphics/Enums.h" -#include "Graphics/Graphics.h" #include "Graphics/Shader.h" -#include "Window/Window.h" -#include "Component/Camera.h" -#include "Component/Mesh.h" -#include "Actor/CameraActor.h" -#include "Math/Vector.h" -#include "RenderGraph.h" -#include "Graphics/Command.h" -#include "Graphics/StaticMeshVertexData.h" using namespace Seele; @@ -19,137 +9,139 @@ extern bool useViewCulling; DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) { - depthPrepassLayout = graphics->createPipelineLayout("DepthPrepassLayout"); - depthPrepassLayout->addDescriptorLayout(viewParamsLayout); - depthPrepassLayout->addPushConstants(Gfx::SePushConstantRange{ - .stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, - .offset = 0, - .size = sizeof(VertexData::DrawCallOffsets), - }); - if (graphics->supportMeshShading()) - { - graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "MeshletPass", false, false, "", true, true, "ViewCullingTask"); - } - else - { - graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "LegacyPass"); - } + depthPrepassLayout = graphics->createPipelineLayout("DepthPrepassLayout"); + depthPrepassLayout->addDescriptorLayout(viewParamsLayout); + depthPrepassLayout->addPushConstants(Gfx::SePushConstantRange{ + .stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, + .offset = 0, + .size = sizeof(VertexData::DrawCallOffsets), + }); + if (graphics->supportMeshShading()) + { + graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "MeshletPass", false, false, "", true, true, "ViewCullingTask"); + } + else + { + graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "LegacyPass"); + } } DepthPrepass::~DepthPrepass() { } -void DepthPrepass::beginFrame(const Component::Camera& cam) +void DepthPrepass::beginFrame(const Component::Camera &cam) { - RenderPass::beginFrame(cam); + RenderPass::beginFrame(cam); } void DepthPrepass::render() { - graphics->beginRenderPass(renderPass); - Array commands; + graphics->beginRenderPass(renderPass); + Array commands; - Gfx::ShaderPermutation permutation; - permutation.setPositionOnly(usePositionOnly); - permutation.setViewCulling(useViewCulling); + Gfx::ShaderPermutation permutation; + permutation.setPositionOnly(usePositionOnly); + permutation.setViewCulling(useViewCulling); + if (graphics->supportMeshShading()) + { + permutation.setTaskFile("ViewCullingTask"); + permutation.setMeshFile("MeshletPass"); + } + else + { + permutation.setVertexFile("LegacyPass"); + } + for (VertexData *vertexData : VertexData::getList()) + { + permutation.setVertexData(vertexData->getTypeName()); + // Create Pipeline(VertexData) + // Descriptors: + // ViewData => global, static + // VertexData => per meshtype + // SceneData => per meshtype + Gfx::PermutationId id(permutation); + + Gfx::ORenderCommand command = graphics->createRenderCommand("DepthRender"); + command->setViewport(viewport); + + const Gfx::ShaderCollection *collection = graphics->getShaderCompiler()->findShaders(id); + assert(collection != nullptr); if (graphics->supportMeshShading()) { - permutation.setTaskFile("ViewCullingTask"); - permutation.setMeshFile("MeshletPass"); + Gfx::MeshPipelineCreateInfo pipelineInfo = { + .taskShader = collection->taskShader, + .meshShader = collection->meshShader, + .fragmentShader = collection->fragmentShader, + .renderPass = renderPass, + .pipelineLayout = collection->pipelineLayout, + .multisampleState = { + .samples = viewport->getSamples(), + }, + .depthStencilState = { + .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER, + }, + .colorBlend = { + .attachmentCount = 1, + }, + }; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); } else { - permutation.setVertexFile("LegacyPass"); + Gfx::LegacyPipelineCreateInfo pipelineInfo = { + .vertexShader = collection->vertexShader, + .fragmentShader = collection->fragmentShader, + .renderPass = renderPass, + .pipelineLayout = collection->pipelineLayout, + .multisampleState = { + .samples = viewport->getSamples(), + }, + .depthStencilState = { + .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER, + }, + .colorBlend = { + .attachmentCount = 1, + }, + }; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); } - for (VertexData* vertexData : VertexData::getList()) + command->bindDescriptor(vertexData->getVertexDataSet()); + command->bindDescriptor(viewParamsSet); + command->bindDescriptor(vertexData->getInstanceDataSet()); + uint32 offset = 0; + command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets), &offset); + if (graphics->supportMeshShading()) { - permutation.setVertexData(vertexData->getTypeName()); - const auto& materials = vertexData->getMaterialData(); - for (const auto& materialData : materials) - { - // material not used for any active meshes, skip - if (materialData.instances.size() == 0) - continue; - // Create Pipeline(VertexData) - // Descriptors: - // ViewData => global, static - // VertexData => per meshtype - // SceneData => per meshtype - Gfx::PermutationId id(permutation); - - Gfx::ORenderCommand command = graphics->createRenderCommand("DepthRender"); - command->setViewport(viewport); - - const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id); - assert(collection != nullptr); - if (graphics->supportMeshShading()) - { - Gfx::MeshPipelineCreateInfo pipelineInfo = { - .taskShader = collection->taskShader, - .meshShader = collection->meshShader, - .fragmentShader = collection->fragmentShader, - .renderPass = renderPass, - .pipelineLayout = collection->pipelineLayout, - .multisampleState = { - .samples = viewport->getSamples(),}, - .depthStencilState = { - .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER, - }, - .colorBlend = { - .attachmentCount = 1, - }, - }; - Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); - command->bindPipeline(pipeline); - } - else - { - Gfx::LegacyPipelineCreateInfo pipelineInfo = { - .vertexShader = collection->vertexShader, - .fragmentShader = collection->fragmentShader, - .renderPass = renderPass, - .pipelineLayout = collection->pipelineLayout, - .multisampleState = { - .samples = viewport->getSamples(), - }, - .depthStencilState = { - .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER, - }, - .colorBlend = { - .attachmentCount = 1, - }, - }; - Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); - command->bindPipeline(pipeline); - } - command->bindDescriptor(vertexData->getVertexDataSet()); - command->bindDescriptor(viewParamsSet); - command->bindDescriptor(vertexData->getInstanceDataSet()); - for (const auto& drawCall : materialData.instances) - { - command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets), &drawCall.offsets); - if (graphics->supportMeshShading()) - { - command->drawMesh(drawCall.instanceMeshData.size(), 1, 1); - } - else - { - command->bindIndexBuffer(vertexData->getIndexBuffer()); - uint32 inst = drawCall.offsets.instanceOffset; - for (const auto& meshData : drawCall.instanceMeshData) - { - // all meshlets of a mesh share the same indices offset - command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, vertexData->getIndicesOffset(meshData.meshletOffset), inst++); - } - } - } - commands.add(std::move(command)); - } + command->drawMesh(vertexData->getNumInstances(), 1, 1); } + else + { + const auto &materials = vertexData->getMaterialData(); + for (const auto &materialData : materials) + { + for (const auto &drawCall : materialData.instances) + { + // material not used for any active meshes, skip + if (materialData.instances.size() == 0) + continue; + command->bindIndexBuffer(vertexData->getIndexBuffer()); + uint32 inst = drawCall.offsets.instanceOffset; + for (const auto &meshData : drawCall.instanceMeshData) + { + // all meshlets of a mesh share the same indices offset + command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, vertexData->getIndicesOffset(meshData.meshletOffset), inst++); + } + } + } + } + commands.add(std::move(command)); + } - graphics->executeCommands(std::move(commands)); - graphics->endRenderPass(); + graphics->executeCommands(std::move(commands)); + graphics->endRenderPass(); } void DepthPrepass::endFrame() @@ -158,52 +150,63 @@ void DepthPrepass::endFrame() void DepthPrepass::publishOutputs() { - // If we render to a part of an image, the depth buffer itself must - // still match the size of the whole image or their coordinate systems go out of sync - TextureCreateInfo depthBufferInfo = { - .format = Gfx::SE_FORMAT_D32_SFLOAT, - .width = viewport->getOwner()->getFramebufferWidth(), - .height = viewport->getOwner()->getFramebufferHeight(), - .usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - }; - depthBuffer = graphics->createTexture2D(depthBufferInfo); - depthAttachment = - Gfx::RenderTargetAttachment(depthBuffer, - Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_GENERAL, - Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE); - resources->registerRenderPassOutput("DEPTHPREPASS_DEPTH", depthAttachment); } void DepthPrepass::createRenderPass() { - Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ - .depthAttachment = depthAttachment, - }; - Array dependency = { - { - .srcSubpass = ~0U, - .dstSubpass = 0, - .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - .dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, - .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - .dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - }, - { - .srcSubpass = 0, - .dstSubpass = ~0U, - .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - .dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - .dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT, - }, - { - .srcSubpass = 0, - .dstSubpass = ~0U, - .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - .dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, - .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - .dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, - } - }; - renderPass = graphics->createRenderPass(std::move(layout), std::move(dependency), viewport); + auto depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH"); + depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL); + depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD); + auto visibilityAttachment = resources->requestRenderTarget("VISIBILITY"); + visibilityAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + visibilityAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + visibilityAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD); + + Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ + .colorAttachments = {visibilityAttachment}, + .depthAttachment = depthAttachment, + }; + Array dependency = { + { + .srcSubpass = ~0U, + .dstSubpass = 0, + .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + }, + { + .srcSubpass = ~0U, + .dstSubpass = 0, + .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + }, + { + .srcSubpass = 0, + .dstSubpass = ~0U, + .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT, + }, + { + .srcSubpass = 0, + .dstSubpass = ~0U, + .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, + }, + { + .srcSubpass = 0, + .dstSubpass = ~0U, + .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT, + }}; + renderPass = graphics->createRenderPass(std::move(layout), std::move(dependency), viewport); } diff --git a/src/Engine/Graphics/RenderPass/DepthPrepass.h b/src/Engine/Graphics/RenderPass/DepthPrepass.h index 84f6737..cc19630 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.h +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.h @@ -18,9 +18,6 @@ public: virtual void createRenderPass() override; private: Gfx::RenderTargetAttachment depthAttachment; - - Gfx::OTexture2D depthBuffer; - Gfx::OPipelineLayout depthPrepassLayout; }; DEFINE_REF(DepthPrepass) diff --git a/src/Engine/Graphics/VertexData.cpp b/src/Engine/Graphics/VertexData.cpp index 56026d2..7a9fd92 100644 --- a/src/Engine/Graphics/VertexData.cpp +++ b/src/Engine/Graphics/VertexData.cpp @@ -15,372 +15,369 @@ constexpr static uint64 NUM_DEFAULT_ELEMENTS = 1024 * 1024; void VertexData::resetMeshData() { - std::unique_lock l(materialDataLock); - for (auto& mat : materialData) + std::unique_lock l(materialDataLock); + for (auto &mat : materialData) + { + for (auto &inst : mat.instances) { - for (auto& inst : mat.instances) - { - inst.instanceData.clear(); - inst.instanceMeshData.clear(); - } - if (mat.material != nullptr) - { - mat.material->getDescriptorLayout()->reset(); - } + inst.instanceData.clear(); + inst.instanceMeshData.clear(); } - if (dirty) + if (mat.material != nullptr) { - updateBuffers(); - dirty = false; + mat.material->getDescriptorLayout()->reset(); } + } + if (dirty) + { + updateBuffers(); + dirty = false; + } } -void VertexData::updateMesh(PMesh mesh, Component::Transform& transform) +void VertexData::updateMesh(PMesh mesh, Component::Transform &transform) { - std::unique_lock l(materialDataLock); - PMaterialInstance referencedInstance = mesh->referencedMaterial->getHandle(); - PMaterial mat = referencedInstance->getBaseMaterial(); - if (materialData.size() <= mat->getId()) - { - materialData.resize(mat->getId() + 1); - } - MaterialData& matData = materialData[mat->getId()]; - matData.material = mat; - if (matData.instances.size() <= referencedInstance->getId()) - { - matData.instances.resize(referencedInstance->getId() + 1); - } - BatchedDrawCall& matInstanceData = matData.instances[referencedInstance->getId()]; - matInstanceData.materialInstance = referencedInstance; - - Matrix4 transformMatrix = transform.toMatrix() * mesh->transform; - matInstanceData.instanceData.add(InstanceData{ - .transformMatrix = transformMatrix, - .inverseTransformMatrix = glm::inverse(transformMatrix), - }); - const auto& data = meshData[mesh->id]; - matInstanceData.instanceMeshData.add(data); - referencedInstance->updateDescriptor(); - for (size_t i = 0; i < 0; ++i) - { - auto bounding = meshlets[data.meshletOffset + i].bounding; - StaticArray corners; - Vector min = bounding.min;//bounding.center - bounding.radius * Vector(1, 1, 1); - Vector max = bounding.max;//bounding.center + bounding.radius * Vector(1, 1, 1); - corners[0] = transformMatrix * Vector4(min.x, min.y, min.z, 1); - corners[1] = transformMatrix * Vector4(min.x, min.y, max.z, 1); - corners[2] = transformMatrix * Vector4(min.x, max.y, min.z, 1); - corners[3] = transformMatrix * Vector4(min.x, max.y, max.z, 1); - corners[4] = transformMatrix * Vector4(max.x, min.y, min.z, 1); - corners[5] = transformMatrix * Vector4(max.x, min.y, max.z, 1); - corners[6] = transformMatrix * Vector4(max.x, max.y, min.z, 1); - corners[7] = transformMatrix * Vector4(max.x, max.y, max.z, 1); - addDebugVertex(DebugVertex{ .position = corners[0], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[1], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[0], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[2], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[1], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[3], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[2], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[3], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[0], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[4], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[1], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[5], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[2], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[6], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[3], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[7], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[4], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[5], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[4], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[6], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[6], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[7], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[5], .color = meshlets[data.meshletOffset + i].color }); - addDebugVertex(DebugVertex{ .position = corners[7], .color = meshlets[data.meshletOffset + i].color }); - } + std::unique_lock l(materialDataLock); + PMaterialInstance referencedInstance = mesh->referencedMaterial->getHandle(); + PMaterial mat = referencedInstance->getBaseMaterial(); + if (materialData.size() <= mat->getId()) + { + materialData.resize(mat->getId() + 1); + } + MaterialData &matData = materialData[mat->getId()]; + matData.material = mat; + if (matData.instances.size() <= referencedInstance->getId()) + { + matData.instances.resize(referencedInstance->getId() + 1); + } + BatchedDrawCall &matInstanceData = matData.instances[referencedInstance->getId()]; + matInstanceData.materialInstance = referencedInstance; + Matrix4 transformMatrix = transform.toMatrix() * mesh->transform; + matInstanceData.instanceData.add(InstanceData{ + .transformMatrix = transformMatrix, + .inverseTransformMatrix = glm::inverse(transformMatrix), + }); + const auto &data = meshData[mesh->id]; + matInstanceData.instanceMeshData.add(data); + referencedInstance->updateDescriptor(); + for (size_t i = 0; i < 0; ++i) + { + auto bounding = meshlets[data.meshletOffset + i].bounding; + StaticArray corners; + Vector min = bounding.min; // bounding.center - bounding.radius * Vector(1, 1, 1); + Vector max = bounding.max; // bounding.center + bounding.radius * Vector(1, 1, 1); + corners[0] = transformMatrix * Vector4(min.x, min.y, min.z, 1); + corners[1] = transformMatrix * Vector4(min.x, min.y, max.z, 1); + corners[2] = transformMatrix * Vector4(min.x, max.y, min.z, 1); + corners[3] = transformMatrix * Vector4(min.x, max.y, max.z, 1); + corners[4] = transformMatrix * Vector4(max.x, min.y, min.z, 1); + corners[5] = transformMatrix * Vector4(max.x, min.y, max.z, 1); + corners[6] = transformMatrix * Vector4(max.x, max.y, min.z, 1); + corners[7] = transformMatrix * Vector4(max.x, max.y, max.z, 1); + addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color}); + addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color}); + } } void VertexData::createDescriptors() { - std::unique_lock l(materialDataLock); + std::unique_lock l(materialDataLock); - instanceData.clear(); - instanceMeshData.clear(); + instanceData.clear(); + instanceMeshData.clear(); - //uint32 numMeshlets = 0; - //Array cullingOffsets; - for (auto& mat : materialData) + uint32 numMeshlets = 0; + Array cullingOffsets; + for (auto &mat : materialData) + { + for (auto &instance : mat.instances) { - for (auto& instance : mat.instances) - { - instance.offsets.instanceOffset = instanceData.size(); - //instance.offsets.cullingCounterOffset = cullingOffsets.size(); - //instance.numMeshlets = 0; - for (size_t i = 0; i < instance.instanceData.size(); ++i) - { - instanceData.add(instance.instanceData[i]); - instanceMeshData.add(instance.instanceMeshData[i]); - //instance.numMeshlets += instance.instanceMeshData[i].numMeshlets; - //cullingOffsets.add(numMeshlets); - //numMeshlets += instance.numMeshlets; - } - } + instance.offsets.instanceOffset = instanceData.size(); + // instance.offsets.cullingCounterOffset = cullingOffsets.size(); + // instance.numMeshlets = 0; + for (size_t i = 0; i < instance.instanceData.size(); ++i) + { + cullingOffsets.add(numMeshlets); + instanceData.add(instance.instanceData[i]); + instanceMeshData.add(instance.instanceMeshData[i]); + // instance.numMeshlets += instance.instanceMeshData[i].numMeshlets; + // cullingOffsets.add(numMeshlets); + numMeshlets += instance.instanceMeshData[i].numMeshlets; + } } - //cullingOffsetBuffer->rotateBuffer(cullingOffsets.size() * sizeof(uint32)); - //cullingOffsetBuffer->updateContents(ShaderBufferCreateInfo{ - // .sourceData = { - // .size = cullingOffsets.size() * sizeof(uint32), - // .data = (uint8*)cullingOffsets.data(), - // }, - // .numElements = cullingOffsets.size() - // }); - //cullingOffsetBuffer->pipelineBarrier( - // Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, - // Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, - // Gfx::SE_ACCESS_MEMORY_READ_BIT, - // Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT - //); - //cullingBuffer->rotateBuffer(numMeshlets * sizeof(uint32)); - //cullingBuffer->updateContents(ShaderBufferCreateInfo{ - // .sourceData = { - // .size = numMeshlets * sizeof(uint32), - // }, - // .numElements = numMeshlets - // }); - //cullingBuffer->pipelineBarrier( - // Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, - // Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, - // Gfx::SE_ACCESS_MEMORY_WRITE_BIT, - // Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT - //); - instanceBuffer->rotateBuffer(instanceData.size() * sizeof(InstanceData)); - instanceBuffer->updateContents(ShaderBufferCreateInfo{ - .sourceData = { - .size = instanceData.size() * sizeof(InstanceData), - .data = (uint8*)instanceData.data(), - }, - .numElements = instanceData.size() - }); - instanceBuffer->pipelineBarrier( - Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, - Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, - Gfx::SE_ACCESS_MEMORY_READ_BIT, - Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT - ); + } + Array cullingData(numMeshlets); + std::memset(cullingData.data(), 0xff, cullingData.size()); + cullingOffsetBuffer->rotateBuffer(cullingOffsets.size() * sizeof(uint32)); + cullingOffsetBuffer->updateContents(ShaderBufferCreateInfo{ + .sourceData = { + .size = cullingOffsets.size() * sizeof(uint32), + .data = (uint8 *)cullingOffsets.data(), + }, + .numElements = cullingOffsets.size()}); + cullingOffsetBuffer->pipelineBarrier( + Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, + Gfx::SE_ACCESS_MEMORY_READ_BIT, + Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - instanceMeshDataBuffer->rotateBuffer(sizeof(MeshData) * instanceMeshData.size()); - instanceMeshDataBuffer->updateContents(ShaderBufferCreateInfo{ - .sourceData = { - .size = sizeof(MeshData) * instanceMeshData.size(), - .data = (uint8*)instanceMeshData.data(), - }, - .numElements = instanceMeshData.size() - }); - instanceMeshDataBuffer->pipelineBarrier( - Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, - Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, - Gfx::SE_ACCESS_MEMORY_READ_BIT, - Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT - ); - instanceDataLayout->reset(); - descriptorSet = instanceDataLayout->allocateDescriptorSet(); - descriptorSet->updateBuffer(0, instanceBuffer); - descriptorSet->updateBuffer(1, instanceMeshDataBuffer); - descriptorSet->updateBuffer(2, meshletBuffer); - descriptorSet->updateBuffer(3, primitiveIndicesBuffer); - descriptorSet->updateBuffer(4, vertexIndicesBuffer); - //descriptorSet->updateBuffer(5, cullingOffsetBuffer); - //descriptorSet->updateBuffer(6, cullingBuffer); + cullingBuffer->rotateBuffer(numMeshlets * sizeof(MeshletCullingInfo)); + cullingBuffer->updateContents(ShaderBufferCreateInfo{ + .sourceData = { + .size = numMeshlets * sizeof(MeshletCullingInfo), + .data = (uint8 *)cullingData.data(), + }, + .numElements = numMeshlets}); + cullingBuffer->pipelineBarrier( + Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, + Gfx::SE_ACCESS_MEMORY_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + instanceBuffer->rotateBuffer(instanceData.size() * sizeof(InstanceData)); + instanceBuffer->updateContents(ShaderBufferCreateInfo{ + .sourceData = { + .size = instanceData.size() * sizeof(InstanceData), + .data = (uint8 *)instanceData.data(), + }, + .numElements = instanceData.size()}); + instanceBuffer->pipelineBarrier( + Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, + Gfx::SE_ACCESS_MEMORY_READ_BIT, + Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - descriptorSet->writeChanges(); + instanceMeshDataBuffer->rotateBuffer(sizeof(MeshData) * instanceMeshData.size()); + instanceMeshDataBuffer->updateContents(ShaderBufferCreateInfo{ + .sourceData = { + .size = sizeof(MeshData) * instanceMeshData.size(), + .data = (uint8 *)instanceMeshData.data(), + }, + .numElements = instanceMeshData.size()}); + instanceMeshDataBuffer->pipelineBarrier( + Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, + Gfx::SE_ACCESS_MEMORY_READ_BIT, + Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + instanceDataLayout->reset(); + descriptorSet = instanceDataLayout->allocateDescriptorSet(); + descriptorSet->updateBuffer(0, instanceBuffer); + descriptorSet->updateBuffer(1, instanceMeshDataBuffer); + descriptorSet->updateBuffer(2, meshletBuffer); + descriptorSet->updateBuffer(3, primitiveIndicesBuffer); + descriptorSet->updateBuffer(4, vertexIndicesBuffer); + descriptorSet->updateBuffer(5, cullingBuffer); + descriptorSet->updateBuffer(6, cullingOffsetBuffer); + + descriptorSet->writeChanges(); } void VertexData::loadMesh(MeshId id, Array loadedIndices, Array loadedMeshlets) { - assert(loadedMeshlets.size() < 2048); - std::unique_lock l(vertexDataLock); - meshlets.reserve(meshlets.size() + loadedMeshlets.size()); - vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numVerticesPerMeshlet); - primitiveIndices.reserve(primitiveIndices.size() + loadedMeshlets.size() * Gfx::numPrimitivesPerMeshlet * 3); - uint32 meshletOffset = meshlets.size(); - AABB meshAABB; - for (uint32 i = 0; i < loadedMeshlets.size(); ++i) - { - Meshlet& m = loadedMeshlets[i]; - meshAABB = meshAABB.combine(m.boundingBox); - uint32 vertexOffset = vertexIndices.size(); - vertexIndices.resize(vertexOffset + m.numVertices); - std::memcpy(vertexIndices.data() + vertexOffset, m.uniqueVertices, m.numVertices * sizeof(uint32)); - uint32 primitiveOffset = primitiveIndices.size(); - primitiveIndices.resize(primitiveOffset + (m.numPrimitives * 3)); - std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8)); - meshlets.add(MeshletDescription{ - .bounding = m.boundingBox,//.toSphere(), - .vertexCount = m.numVertices, - .primitiveCount = m.numPrimitives, - .vertexOffset = vertexOffset, - .primitiveOffset = primitiveOffset, - .color = Vector((float)rand() / RAND_MAX,(float)rand() / RAND_MAX,(float)rand() / RAND_MAX), - .indicesOffset = (uint32)meshOffsets[id], - }); - } - meshData[id] = MeshData{ - .bounding = meshAABB,//.toSphere(), - .numMeshlets = (uint32)loadedMeshlets.size(), - .meshletOffset = meshletOffset, - .firstIndex = (uint32)indices.size(), - .numIndices = (uint32)loadedIndices.size(), - }; + assert(loadedMeshlets.size() < 2048); + std::unique_lock l(vertexDataLock); + meshlets.reserve(meshlets.size() + loadedMeshlets.size()); + vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numVerticesPerMeshlet); + primitiveIndices.reserve(primitiveIndices.size() + loadedMeshlets.size() * Gfx::numPrimitivesPerMeshlet * 3); + uint32 meshletOffset = meshlets.size(); + AABB meshAABB; + for (uint32 i = 0; i < loadedMeshlets.size(); ++i) + { + Meshlet &m = loadedMeshlets[i]; + meshAABB = meshAABB.combine(m.boundingBox); + uint32 vertexOffset = vertexIndices.size(); + vertexIndices.resize(vertexOffset + m.numVertices); + std::memcpy(vertexIndices.data() + vertexOffset, m.uniqueVertices, m.numVertices * sizeof(uint32)); + uint32 primitiveOffset = primitiveIndices.size(); + primitiveIndices.resize(primitiveOffset + (m.numPrimitives * 3)); + std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8)); + meshlets.add(MeshletDescription{ + .bounding = m.boundingBox, //.toSphere(), + .vertexCount = m.numVertices, + .primitiveCount = m.numPrimitives, + .vertexOffset = vertexOffset, + .primitiveOffset = primitiveOffset, + .color = Vector((float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX), + .indicesOffset = (uint32)meshOffsets[id], + }); + } + meshData[id] = MeshData{ + .bounding = meshAABB, //.toSphere(), + .numMeshlets = (uint32)loadedMeshlets.size(), + .meshletOffset = meshletOffset, + .firstIndex = (uint32)indices.size(), + .numIndices = (uint32)loadedIndices.size(), + }; - if (!graphics->supportMeshShading()) - { - indices.resize(indices.size() + loadedIndices.size()); - std::memcpy(indices.data() + meshData[id].firstIndex, loadedIndices.data(), loadedIndices.size() * sizeof(uint32)); - indexBuffer = graphics->createIndexBuffer(IndexBufferCreateInfo{ - .sourceData = { - .size = sizeof(uint32) * indices.size(), - .data = (uint8*)indices.data(), - }, - .indexType = Gfx::SE_INDEX_TYPE_UINT32, - .name = "IndexBuffer", - }); + if (!graphics->supportMeshShading()) + { + indices.resize(indices.size() + loadedIndices.size()); + std::memcpy(indices.data() + meshData[id].firstIndex, loadedIndices.data(), loadedIndices.size() * sizeof(uint32)); + indexBuffer = graphics->createIndexBuffer(IndexBufferCreateInfo{ + .sourceData = { + .size = sizeof(uint32) * indices.size(), + .data = (uint8 *)indices.data(), + }, + .indexType = Gfx::SE_INDEX_TYPE_UINT32, + .name = "IndexBuffer", + }); + } + meshletBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + .sourceData = { + .size = sizeof(MeshletDescription) * meshlets.size(), + .data = (uint8 *)meshlets.data()}, + .numElements = meshlets.size(), + .dynamic = false, + .name = "MeshletBuffer"}); - } - meshletBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ - .sourceData = { - .size = sizeof(MeshletDescription) * meshlets.size(), - .data = (uint8*)meshlets.data() - }, - .numElements = meshlets.size(), - .dynamic = false, - .name = "MeshletBuffer" - }); - vertexIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ - .sourceData = { - .size = sizeof(uint32) * vertexIndices.size(), - .data = (uint8*)vertexIndices.data(), - }, - .numElements = vertexIndices.size(), - .dynamic = false, - .name = "VertexIndicesBuffer" - }); - primitiveIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ - .sourceData = { - .size = sizeof(uint8) * primitiveIndices.size(), - .data = (uint8*)primitiveIndices.data(), - }, - .numElements = primitiveIndices.size(), - .dynamic = false, - .name = "PrimitiveIndicesBuffer", - }); + vertexIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + .sourceData = { + .size = sizeof(uint32) * vertexIndices.size(), + .data = (uint8 *)vertexIndices.data(), + }, + .numElements = vertexIndices.size(), + .dynamic = false, + .name = "VertexIndicesBuffer"}); + + primitiveIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + .sourceData = { + .size = sizeof(uint8) * primitiveIndices.size(), + .data = (uint8 *)primitiveIndices.data(), + }, + .numElements = primitiveIndices.size(), + .dynamic = false, + .name = "PrimitiveIndicesBuffer", + }); } MeshId VertexData::allocateVertexData(uint64 numVertices) { - std::unique_lock l(vertexDataLock); - MeshId res{ idCounter++ }; - meshOffsets[res] = head; - meshVertexCounts[res] = numVertices; - head += numVertices; - if (head > verticesAllocated) - { - verticesAllocated = std::max(head, verticesAllocated + NUM_DEFAULT_ELEMENTS); - resizeBuffers(); - } - return res; + std::unique_lock l(vertexDataLock); + MeshId res{idCounter++}; + meshOffsets[res] = head; + meshVertexCounts[res] = numVertices; + head += numVertices; + if (head > verticesAllocated) + { + verticesAllocated = std::max(head, verticesAllocated + NUM_DEFAULT_ELEMENTS); + resizeBuffers(); + } + return res; } uint64 VertexData::getMeshOffset(MeshId id) { - return meshOffsets[id]; + return meshOffsets[id]; } uint64 VertexData::getMeshVertexCount(MeshId id) { - return meshVertexCounts[id]; + return meshVertexCounts[id]; } -List vertexDataList; +List vertexDataList; -List VertexData::getList() +List VertexData::getList() { - return vertexDataList; + return vertexDataList; } -VertexData* VertexData::findByTypeName(std::string name) +VertexData *VertexData::findByTypeName(std::string name) { - for (auto vd : vertexDataList) + for (auto vd : vertexDataList) + { + if (vd->getTypeName() == name) { - if (vd->getTypeName() == name) - { - return vd; - } + return vd; } - return nullptr; + } + return nullptr; } void VertexData::init(Gfx::PGraphics _graphics) { - graphics = _graphics; - verticesAllocated = NUM_DEFAULT_ELEMENTS; - instanceDataLayout = graphics->createDescriptorLayout("pScene"); + graphics = _graphics; + verticesAllocated = NUM_DEFAULT_ELEMENTS; + instanceDataLayout = graphics->createDescriptorLayout("pScene"); - // instanceData - instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 0, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, }); - // meshData - instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 1, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, }); - // meshletData - instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER }); - // primitiveIndices - instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 3, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER }); - // vertexIndices - instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 4, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER }); - // cullingList - //instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 5, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER }); - // cullingOffset - //instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 6, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER }); + // instanceData + instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ + .binding = 0, + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, + }); + // meshData + instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ + .binding = 1, + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, + }); + // meshletData + instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER}); + // primitiveIndices + instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 3, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER}); + // vertexIndices + instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 4, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER}); + // cullingList + instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 5, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER}); + // cullingOffset + instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 6, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER}); - //cullingOffsetBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ - // .dynamic = true, - // .name = "MeshletOffset", - // }); - //cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ - // .dynamic = true, - // .name = "MeshletCulling", - // }); - instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ - .dynamic = true, - .name = "InstanceBuffer", - }); - instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ - .dynamic = true, - .name = "MeshDataBuffer", - }); - instanceDataLayout->create(); - resizeBuffers(); - graphics->getShaderCompiler()->registerVertexData(this); + cullingOffsetBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + .dynamic = true, + .name = "MeshletOffset", + }); + cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + .dynamic = true, + .name = "MeshletCulling", + }); + instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + .dynamic = true, + .name = "InstanceBuffer", + }); + instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + .dynamic = true, + .name = "MeshDataBuffer", + }); + instanceDataLayout->create(); + resizeBuffers(); + graphics->getShaderCompiler()->registerVertexData(this); } void VertexData::destroy() { - instanceBuffer = nullptr; - instanceMeshDataBuffer = nullptr; - instanceDataLayout = nullptr; - meshletBuffer = nullptr; - vertexIndicesBuffer = nullptr; - primitiveIndicesBuffer = nullptr; - indexBuffer = nullptr; - meshData.clear(); - materialData.clear(); + instanceBuffer = nullptr; + instanceMeshDataBuffer = nullptr; + instanceDataLayout = nullptr; + meshletBuffer = nullptr; + vertexIndicesBuffer = nullptr; + primitiveIndicesBuffer = nullptr; + indexBuffer = nullptr; + meshData.clear(); + materialData.clear(); } VertexData::VertexData() - : idCounter(0) - , head(0) - , verticesAllocated(0) - , dirty(false) + : idCounter(0), head(0), verticesAllocated(0), dirty(false) { } diff --git a/src/Engine/Graphics/VertexData.h b/src/Engine/Graphics/VertexData.h index e11afc4..9c4fe38 100644 --- a/src/Engine/Graphics/VertexData.h +++ b/src/Engine/Graphics/VertexData.h @@ -12,60 +12,65 @@ constexpr uint64 MAX_TEXCOORDS = 8; namespace Seele { -DECLARE_REF(Mesh) -struct MeshId -{ + DECLARE_REF(Mesh) + struct MeshId + { uint64 id; - std::strong_ordering operator<=>(const MeshId& other) const + std::strong_ordering operator<=>(const MeshId &other) const { - return id <=> other.id; + return id <=> other.id; } - bool operator==(const MeshId& other) const + bool operator==(const MeshId &other) const { - return id == other.id; + return id == other.id; } -}; -class VertexData -{ -public: + }; + class VertexData + { + public: struct InstanceData { - Matrix4 transformMatrix; - Matrix4 inverseTransformMatrix; + Matrix4 transformMatrix; + Matrix4 inverseTransformMatrix; }; struct MeshData { - AABB bounding; - uint32 numMeshlets = 0; - uint32 meshletOffset = 0; - uint32 firstIndex = 0; - uint32 numIndices = 0; + AABB bounding; + uint32 numMeshlets = 0; + uint32 meshletOffset = 0; + uint32 firstIndex = 0; + uint32 numIndices = 0; }; struct DrawCallOffsets { - uint32 instanceOffset = 0; + uint32 instanceOffset = 0; + }; + + struct MeshletCullingInfo + { + uint64_t cull[256 / 64]; }; struct BatchedDrawCall { - PMaterialInstance materialInstance; - DrawCallOffsets offsets; - Array instanceData; - Array instanceMeshData; + PMaterialInstance materialInstance; + DrawCallOffsets offsets; + Array instanceData; + Array instanceMeshData; }; struct MaterialData { - PMaterial material; - Array instances; + PMaterial material; + Array instances; }; void resetMeshData(); - void updateMesh(PMesh mesh, Component::Transform& transform); + void updateMesh(PMesh mesh, Component::Transform &transform); void createDescriptors(); void loadMesh(MeshId id, Array indices, Array meshlets); MeshId allocateVertexData(uint64 numVertices); uint64 getMeshOffset(MeshId id); uint64 getMeshVertexCount(MeshId id); - virtual void serializeMesh(MeshId id, uint64 numVertices, ArchiveBuffer& buffer) = 0; - virtual void deserializeMesh(MeshId id, ArchiveBuffer& buffer) = 0; + virtual void serializeMesh(MeshId id, uint64 numVertices, ArchiveBuffer &buffer) = 0; + virtual void deserializeMesh(MeshId id, ArchiveBuffer &buffer) = 0; virtual void bindBuffers(Gfx::PRenderCommand command) = 0; virtual Gfx::PDescriptorLayout getVertexDataLayout() = 0; virtual Gfx::PDescriptorSet getVertexDataSet() = 0; @@ -73,26 +78,28 @@ public: Gfx::PIndexBuffer getIndexBuffer() { return indexBuffer; } Gfx::PDescriptorLayout getInstanceDataLayout() { return instanceDataLayout; } Gfx::PDescriptorSet getInstanceDataSet() { return descriptorSet; } - const Array& getMaterialData() const { return materialData; } - const MeshData& getMeshData(MeshId id) { return meshData[id]; } + const Array &getMaterialData() const { return materialData; } + const MeshData &getMeshData(MeshId id) { return meshData[id]; } uint64 getIndicesOffset(uint32 meshletIndex) { return meshlets[meshletIndex].indicesOffset; } - static List getList(); - static VertexData* findByTypeName(std::string name); + uint64 getNumInstances() const { return instanceData.size(); } + static List getList(); + static VertexData *findByTypeName(std::string name); virtual void init(Gfx::PGraphics graphics); virtual void destroy(); -protected: + + protected: virtual void resizeBuffers() = 0; virtual void updateBuffers() = 0; VertexData(); struct MeshletDescription { - AABB bounding; - uint32 vertexCount; - uint32 primitiveCount; - uint32 vertexOffset; - uint32 primitiveOffset; - Vector color; - uint32 indicesOffset = 0; + AABB bounding; + uint32 vertexCount; + uint32 primitiveCount; + uint32 vertexOffset; + uint32 primitiveOffset; + Vector color; + uint32 indicesOffset = 0; }; std::mutex materialDataLock; Array materialData; @@ -110,9 +117,9 @@ protected: Gfx::OShaderBuffer meshletBuffer; Gfx::OShaderBuffer vertexIndicesBuffer; Gfx::OShaderBuffer primitiveIndicesBuffer; - // temporary meshlet culling buffer, passed from task to mesh shader - //Gfx::OShaderBuffer cullingBuffer; - //Gfx::OShaderBuffer cullingOffsetBuffer; + // Holds culling information for every meshlet for each instance + Gfx::OShaderBuffer cullingBuffer; + Gfx::OShaderBuffer cullingOffsetBuffer; // for legacy pipeline Gfx::OIndexBuffer indexBuffer; // Material data @@ -122,8 +129,8 @@ protected: Gfx::OShaderBuffer instanceMeshDataBuffer; Gfx::PDescriptorSet descriptorSet; uint64 idCounter; - uint64 head; - uint64 verticesAllocated; + uint64 head; + uint64 verticesAllocated; bool dirty; -}; + }; } diff --git a/src/Engine/Graphics/Vulkan/Resources.cpp b/src/Engine/Graphics/Vulkan/Resources.cpp index b8896b7..5ff366c 100644 --- a/src/Engine/Graphics/Vulkan/Resources.cpp +++ b/src/Engine/Graphics/Vulkan/Resources.cpp @@ -75,7 +75,7 @@ void Fence::reset() } } -void Fence::wait(uint32 timeout) +void Fence::wait(uint64 timeout) { VkFence fences[] = {fence}; VkResult r = vkWaitForFences(graphics->getDevice(), 1, fences, true, timeout); diff --git a/src/Engine/Graphics/Vulkan/Resources.h b/src/Engine/Graphics/Vulkan/Resources.h index a1958d2..4369110 100644 --- a/src/Engine/Graphics/Vulkan/Resources.h +++ b/src/Engine/Graphics/Vulkan/Resources.h @@ -38,7 +38,7 @@ public: { return fence; } - void wait(uint32 timeout); + void wait(uint64 timeout); bool operator<(const Fence &other) const { return fence < other.fence; diff --git a/src/Engine/Window/GameView.cpp b/src/Engine/Window/GameView.cpp index dd03ae4..cef337a 100644 --- a/src/Engine/Window/GameView.cpp +++ b/src/Engine/Window/GameView.cpp @@ -7,8 +7,12 @@ #include "System/LightGather.h" #include "System/MeshUpdater.h" #include "System/CameraUpdater.h" -#include "Graphics/Vulkan/Graphics.h" -#include "Graphics/Vulkan/Allocator.h" +#include "Graphics/RenderPass/CachedDepthPass.h" +#include "Graphics/RenderPass/DepthPrepass.h" +#include "Graphics/RenderPass/LightCullingPass.h" +#include "Graphics/RenderPass/BasePass.h" +#include "Graphics/RenderPass/SkyboxRenderPass.h" +#include "Graphics/RenderPass/DebugPass.h" using namespace Seele; @@ -22,10 +26,9 @@ GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate , gameInterface(dllPath) { reloadGame(); - //renderGraph.addPass(new StaticDepthPrepass(graphics, scene)); + renderGraph.addPass(new CachedDepthPass(graphics, scene)); renderGraph.addPass(new DepthPrepass(graphics, scene)); renderGraph.addPass(new LightCullingPass(graphics, scene)); - //renderGraph.addPass(new StaticBasePass(graphics, scene)); renderGraph.addPass(new BasePass(graphics, scene)); renderGraph.addPass(new DebugPass(graphics, scene)); //renderGraph.addPass(new SkyboxRenderPass(graphics, scene)); diff --git a/src/Engine/Window/GameView.h b/src/Engine/Window/GameView.h index ac1357d..3545854 100644 --- a/src/Engine/Window/GameView.h +++ b/src/Engine/Window/GameView.h @@ -1,11 +1,6 @@ #pragma once #include "Window/View.h" #include "Scene/Scene.h" -#include "Graphics/RenderPass/DepthPrepass.h" -#include "Graphics/RenderPass/LightCullingPass.h" -#include "Graphics/RenderPass/BasePass.h" -#include "Graphics/RenderPass/SkyboxRenderPass.h" -#include "Graphics/RenderPass/DebugPass.h" #include "System/KeyboardInput.h" #ifdef WIN32 #include "Platform/Windows/GameInterface.h" // TODO @@ -15,34 +10,35 @@ namespace Seele { -class GameView : public View -{ -public: + class GameView : public View + { + public: GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &createInfo, std::string dllPath); virtual ~GameView(); - virtual void beginUpdate() override; - virtual void update() override; - virtual void commitUpdate() override; + virtual void beginUpdate() override; + virtual void update() override; + virtual void commitUpdate() override; - virtual void prepareRender() override; - virtual void render() override; + virtual void prepareRender() override; + virtual void render() override; - void reloadGame(); -protected: - virtual void applyArea(URect rect) override; - OScene scene; - GameInterface gameInterface; + void reloadGame(); + + protected: + virtual void applyArea(URect rect) override; + OScene scene; + GameInterface gameInterface; RenderGraph renderGraph; - PSystemGraph systemGraph; - System::PKeyboardInput keyboardSystem; - float updateTime = 0; + PSystemGraph systemGraph; + System::PKeyboardInput keyboardSystem; + float updateTime = 0; - virtual void keyCallback(Seele::KeyCode code, Seele::InputAction action, Seele::KeyModifier modifier) override; - virtual void mouseMoveCallback(double xPos, double yPos) override; - virtual void mouseButtonCallback(Seele::MouseButton button, Seele::InputAction action, Seele::KeyModifier modifier) override; - virtual void scrollCallback(double xOffset, double yOffset) override; - virtual void fileCallback(int count, const char** paths) override; -}; -DEFINE_REF(GameView) + virtual void keyCallback(Seele::KeyCode code, Seele::InputAction action, Seele::KeyModifier modifier) override; + virtual void mouseMoveCallback(double xPos, double yPos) override; + virtual void mouseButtonCallback(Seele::MouseButton button, Seele::InputAction action, Seele::KeyModifier modifier) override; + virtual void scrollCallback(double xOffset, double yOffset) override; + virtual void fileCallback(int count, const char **paths) override; + }; + DEFINE_REF(GameView) } // namespace Seele