diff --git a/.vscode/settings.json b/.vscode/settings.json index b270ba5..1b10449 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -20,7 +20,7 @@ "**/external": true, "**/res": true, }, - "editor.tabSize": 2, + "editor.tabSize": 4, "editor.detectIndentation": false, "lldb.displayFormat": "auto", "lldb.showDisassembly": "auto", diff --git a/res/shaders/BasePass.slang b/res/shaders/BasePass.slang index 354e117..7f9cb74 100644 --- a/res/shaders/BasePass.slang +++ b/res/shaders/BasePass.slang @@ -12,14 +12,8 @@ struct LightCullingData layout(set=5) ParameterBlock pLightCullingData; -struct FragmentOutput -{ - float4 color : SV_Target0; - uint meshletId : SV_Target1; -}; - [shader("pixel")] -FragmentOutput fragmentMain(in FragmentParameter params) +float4 fragmentMain(in FragmentParameter params) : SV_Target { LightingParameter lightingParams = params.getLightingParameter(); MaterialParameter materialParams = params.getMaterialParameter(); @@ -41,9 +35,6 @@ FragmentOutput fragmentMain(in FragmentParameter params) // gamma correction result = result / (result + float3(1.0)); result = pow(result, float3(1.0/2.2)); - FragmentOutput output; - output.color = float4(result, 1.0f); - output.meshletId = params.meshletId; - return output; + return float4(result, 1.0f); } \ No newline at end of file diff --git a/res/shaders/DepthCullingTask.slang b/res/shaders/DepthCullingTask.slang index 0a554e3..3108b5a 100644 --- a/res/shaders/DepthCullingTask.slang +++ b/res/shaders/DepthCullingTask.slang @@ -7,25 +7,31 @@ groupshared uint head; [numthreads(TASK_GROUP_SIZE, 1, 1)] [shader("amplification")] void taskMain( - uint threadID: SV_GroupIndex, - uint groupID: SV_GroupID, -){ - InstanceData instance = pScene.instances[pOffsets.instanceOffset + groupID]; - MeshData mesh = pScene.meshData[pOffsets.instanceOffset + groupID]; - //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); + uint threadID: SV_GroupIndex, + uint groupID: SV_GroupID, ) +{ + MeshData mesh = pScene.meshData[pOffsets.instanceOffset + groupID]; + if (threadID == 0) + { + head = 0; + p.instanceId = pOffsets.instanceOffset + groupID; + p.meshletOffset = mesh.meshletOffset; + p.cullingOffset = pScene.cullingOffsets[p.instanceId]; + } + GroupMemoryBarrierWithGroupSync(); + for (uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE) + { + uint m = p.meshletOffset + i; + uint cull = p.cullingOffset + i; + MeshletDescription meshlet = pScene.meshletInfos[m]; + MeshletCullingInfo culling = pScene.culledMeshlets[cull]; + if(false) + { + uint index; + InterlockedAdd(head, 1, index); + p.culledMeshlets[index] = i; + } + } + GroupMemoryBarrierWithGroupSync(); + DispatchMesh(head, 1, 1, p); } diff --git a/res/shaders/DrawListTask.slang b/res/shaders/DrawListTask.slang index f1b8829..44259dc 100644 --- a/res/shaders/DrawListTask.slang +++ b/res/shaders/DrawListTask.slang @@ -3,6 +3,7 @@ import Scene; groupshared MeshPayload p; groupshared uint head; +groupshared MeshData mesh; [numthreads(TASK_GROUP_SIZE, 1, 1)] [shader("amplification")] @@ -13,22 +14,25 @@ void taskMain( if (threadID == 0) { head = 0; + mesh = pScene.meshData[pOffsets.instanceOffset + groupID]; p.instanceId = pOffsets.instanceOffset + groupID; + p.meshletOffset = mesh.meshletOffset; + p.cullingOffset = pScene.cullingOffsets[p.instanceId]; } 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 m = p.meshletOffset + i; + uint cull = p.cullingOffset + i; + MeshletDescription meshlet = pScene.meshletInfos[m]; + MeshletCullingInfo culling = pScene.culledMeshlets[cull]; + if(culling.anyVisible()) { uint index; InterlockedAdd(head, 1, index); - p.culledMeshlets[i] = m; + p.culledMeshlets[index] = i; } } GroupMemoryBarrierWithGroupSync(); - DispatchMesh(mesh.numMeshlets, 1, 1, p); + DispatchMesh(head, 1, 1, p); } diff --git a/res/shaders/MeshletPass.slang b/res/shaders/MeshletPass.slang index 1b622e3..ebd4f0c 100644 --- a/res/shaders/MeshletPass.slang +++ b/res/shaders/MeshletPass.slang @@ -5,21 +5,25 @@ import MaterialParameter; struct PrimitiveAttributes { - uint cull: SV_CullPrimitive; + bool cull: SV_CullPrimitive; }; [numthreads(MESH_GROUP_SIZE, 1, 1)] [outputtopology("triangle")] [shader("mesh")] void meshMain( - in uint threadID: SV_GroupIndex, - in uint groupID: SV_GroupID, - in payload MeshPayload meshPayload, - out vertices FragmentParameter vertices[MAX_VERTICES], - out indices uint3 indices[MAX_PRIMITIVES] -){ - InstanceData inst = pScene.instances[meshPayload.instanceId]; - MeshletDescription m = pScene.meshletInfos[meshPayload.culledMeshlets[groupID]]; + in uint threadID: SV_GroupIndex, + in uint groupID: SV_GroupID, + in payload MeshPayload meshPayload, + out vertices FragmentParameter vertices[MAX_VERTICES], + out indices uint3 indices[MAX_PRIMITIVES], + out primitives PrimitiveAttributes prim[MAX_PRIMITIVES] +) { + // meshlet number relative to start for this instance + uint meshletNumber = meshPayload.culledMeshlets[groupID]; + InstanceData inst = pScene.instances[meshPayload.instanceId]; + MeshletDescription m = pScene.meshletInfos[meshPayload.meshletOffset + meshletNumber]; + MeshletCullingInfo cull = pScene.culledMeshlets[meshPayload.cullingOffset + meshletNumber]; SetMeshOutputCounts(m.vertexCount, m.primitiveCount); for(uint i = threadID; i < MAX_PRIMITIVES; i += MESH_GROUP_SIZE) @@ -29,7 +33,8 @@ void meshMain( 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); + indices[p] = uint3(local_idx0, local_idx1, local_idx2); + prim[p].cull = cull.triangleCulled(p); } } for(uint i = threadID; i < MAX_VERTICES; i += MESH_GROUP_SIZE) @@ -42,8 +47,6 @@ void meshMain( #else VertexAttributes attr = pVertexData.getAttributes(m.indicesOffset + vertexIndex); #endif - - attr.meshletId = -1; vertices[v] = attr.getParameter(inst.transformMatrix); } } diff --git a/res/shaders/VisibilityMeshletPass.slang b/res/shaders/VisibilityMeshletPass.slang new file mode 100644 index 0000000..cf4930a --- /dev/null +++ b/res/shaders/VisibilityMeshletPass.slang @@ -0,0 +1,55 @@ +import Common; +import Scene; +import VertexData; +import MaterialParameter; + +struct PrimitiveAttributes +{ + uint32_t prim : SV_PrimitiveID; + bool cull: SV_CullPrimitive; +}; + +[numthreads(MESH_GROUP_SIZE, 1, 1)] +[outputtopology("triangle")] +[shader("mesh")] +void meshMain( + in uint threadID: SV_GroupIndex, + in uint groupID: SV_GroupID, + in payload MeshPayload meshPayload, + out vertices FragmentParameter vertices[MAX_VERTICES], + out indices uint3 indices[MAX_PRIMITIVES], + out primitives PrimitiveAttributes prim[MAX_PRIMITIVES] +) { + // meshlet number relative to start for this instance + uint meshletNumber = meshPayload.culledMeshlets[groupID]; + InstanceData inst = pScene.instances[meshPayload.instanceId]; + MeshletDescription m = pScene.meshletInfos[meshPayload.meshletOffset + meshletNumber]; + MeshletCullingInfo cull = pScene.culledMeshlets[meshPayload.cullingOffset + meshletNumber]; + 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); + prim[p].cull = cull.triangleCulled(p); + //prim[p].prim = encodePrimitive(p, meshletNumber, meshPayload.instanceId); + } + } + 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]; +#ifdef POS_ONLY + VertexAttributes attr = pVertexData.getPosition(m.indicesOffset + vertexIndex); +#else + VertexAttributes attr = pVertexData.getAttributes(m.indicesOffset + vertexIndex); +#endif + vertices[v] = attr.getParameter(inst.transformMatrix); + } + } +} \ No newline at end of file diff --git a/res/shaders/VisibilityPass.slang b/res/shaders/VisibilityPass.slang new file mode 100644 index 0000000..e0a232e --- /dev/null +++ b/res/shaders/VisibilityPass.slang @@ -0,0 +1,8 @@ +import Scene; +import MaterialParameter; + +[shader("pixel")] +uint fragmentMain(in uint32_t encoded : SV_PrimitiveID) : SV_Target +{ + return encoded; +} \ No newline at end of file diff --git a/res/shaders/lib/MaterialParameter.slang b/res/shaders/lib/MaterialParameter.slang index 2449f8e..5888cd5 100644 --- a/res/shaders/lib/MaterialParameter.slang +++ b/res/shaders/lib/MaterialParameter.slang @@ -26,7 +26,6 @@ struct FragmentParameter float3 biTangent_WS : TANGENT1; float3 position_WS : POSITION2; float3 vertexColor : COLOR0; - uint meshletId : POSITION3; float2 texCoords[MAX_TEXCOORDS] : TEXCOORD0; MaterialParameter getMaterialParameter() { @@ -50,6 +49,13 @@ struct FragmentParameter } }; +// data passed to visibility render +struct VisibilityParameter +{ + uint32_t triangleIndex : POSITION5; + uint32_t meshletId : POSITION6; +}; + // data retrieved from VertexData struct VertexAttributes { @@ -58,7 +64,6 @@ struct VertexAttributes float3 tangent_MS; float3 biTangent_MS; float3 vertexColor; - uint meshletId; float2 texCoords[MAX_TEXCOORDS]; FragmentParameter getParameter(float4x4 transformMatrix) { @@ -66,19 +71,18 @@ struct VertexAttributes float4 worldPos = mul(transformMatrix, modelPos); float4 viewPos = mul(pViewParams.viewMatrix, worldPos); float4 clipPos = mul(pViewParams.projectionMatrix, viewPos); + FragmentParameter result; + result.position_CS = clipPos; float3x3 normalMatrix = float3x3(transformMatrix); float3 T = mul(normalMatrix, tangent_MS); float3 N = mul(normalMatrix, normal_MS); float3 B = mul(normalMatrix, biTangent_MS); - FragmentParameter result; - result.position_CS = clipPos; result.cameraPos_WS = pViewParams.cameraPos_WS.xyz; result.normal_WS = N; result.tangent_WS = T; result.biTangent_WS = B; result.position_WS = worldPos.xyz; result.vertexColor = vertexColor; - result.meshletId = meshletId; for(uint i = 0; i < MAX_TEXCOORDS; ++i) { result.texCoords[i] = texCoords[i]; diff --git a/res/shaders/lib/Scene.slang b/res/shaders/lib/Scene.slang index 2730ec4..2850832 100644 --- a/res/shaders/lib/Scene.slang +++ b/res/shaders/lib/Scene.slang @@ -2,49 +2,54 @@ import Bounding; struct MeshletDescription { - AABB bounding; - uint32_t vertexCount; - uint32_t primitiveCount; - uint32_t vertexOffset; - uint32_t primitiveOffset; - float3 color; - uint32_t indicesOffset; + AABB bounding; + uint32_t vertexCount; + uint32_t primitiveCount; + uint32_t vertexOffset; + uint32_t primitiveOffset; + float3 color; + uint32_t indicesOffset; }; struct MeshData { - AABB bounding; - uint32_t numMeshlets; - uint32_t meshletOffset; - uint32_t firstIndex; - uint32_t numIndices; + AABB bounding; + uint32_t numMeshlets; + uint32_t meshletOffset; + uint32_t firstIndex; + uint32_t numIndices; }; -static const uint MAX_VERTICES = 256; -static const uint MAX_PRIMITIVES = 256; -static const uint TASK_GROUP_SIZE = 128; -static const uint MESH_GROUP_SIZE = 32; +static const uint64_t MAX_VERTICES = 256; +static const uint64_t MAX_PRIMITIVES = 256; +static const uint64_t TASK_GROUP_SIZE = 128; +static const uint64_t MESH_GROUP_SIZE = 32; +static const uint64_t MAX_MESHLETS_PER_INSTANCE = 2048; struct InstanceData { - float4x4 transformMatrix; - float4x4 inverseTransformMatrix; + float4x4 transformMatrix; + 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; - } + uint64_t visible[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 (visible[arrIdx] & (1 << cullIdx)) != 0; + } + bool triangleCulled(uint32_t primIndex) + { + return !triangleVisible(primIndex); + } + bool anyVisible() + { + return (visible[0] + visible[1] + visible[2] + visible[3]) != 0; + } }; struct DrawCallOffsets @@ -56,20 +61,42 @@ ConstantBuffer pOffsets; struct Scene { - StructuredBuffer instances; - StructuredBuffer meshData; - StructuredBuffer meshletInfos; - StructuredBuffer primitiveIndices; - StructuredBuffer vertexIndices; - StructuredBuffer culledMeshlets; - StructuredBuffer cullingOffsets; + StructuredBuffer instances; + StructuredBuffer meshData; + StructuredBuffer meshletInfos; + StructuredBuffer primitiveIndices; + StructuredBuffer vertexIndices; + StructuredBuffer culledMeshlets; + StructuredBuffer cullingOffsets; }; -layout(set=2) +layout(set = 2) ParameterBlock pScene; +uint32_t encodePrimitive(uint32_t primitiveId, uint32_t meshletId, uint32_t instanceId) +{ + uint32_t encoded = instanceId; + encoded *= MAX_MESHLETS_PER_INSTANCE; + encoded += meshletId; + encoded *= MAX_PRIMITIVES; + encoded += primitiveId; + return encoded; +} + +uint3 decodePrimitive(uint64_t encoded) +{ + uint prim = uint(encoded % MAX_PRIMITIVES); + encoded = encoded / MAX_PRIMITIVES; + uint meshletId = uint(encoded % MAX_MESHLETS_PER_INSTANCE); + encoded = encoded / MAX_MESHLETS_PER_INSTANCE; + uint instanceId = uint(encoded); + return uint3(prim, meshletId, instanceId); +} + struct MeshPayload { - uint instanceId; - uint culledMeshlets[2048]; + uint instanceId; + uint meshletOffset; + uint cullingOffset; + uint culledMeshlets[MAX_MESHLETS_PER_INSTANCE]; }; diff --git a/res/shaders/lib/StaticMeshVertexData.slang b/res/shaders/lib/StaticMeshVertexData.slang index 3764fca..b28478c 100644 --- a/res/shaders/lib/StaticMeshVertexData.slang +++ b/res/shaders/lib/StaticMeshVertexData.slang @@ -22,14 +22,6 @@ struct StaticMeshVertexData : IVertexData { VertexAttributes attributes; attributes.position_MS = float3(positions[3 * index + 0], positions[3 * index + 1], positions[3 * index + 2]); - attributes.normal_MS = float3(0, 0, 0); - attributes.tangent_MS = float3(0, 0, 0); - attributes.biTangent_MS = float3(0, 0, 0); - for (uint i = 0; i < MAX_TEXCOORDS; ++i) - { - attributes.texCoords[i] = float2(0, 0); - } - attributes.vertexColor = float3(0, 0, 0); return attributes; } StructuredBuffer positions; diff --git a/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp b/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp index f7e7ebd..98c73e9 100644 --- a/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp +++ b/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp @@ -9,21 +9,21 @@ 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"); - } + 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", "VisibilityMeshletPass", false, true, "VisibilityPass", true, true, "DrawListTask"); + } + else + { + graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "CachedDepthPass", "LegacyPass"); + } } CachedDepthPass::~CachedDepthPass() @@ -32,117 +32,130 @@ CachedDepthPass::~CachedDepthPass() void CachedDepthPass::beginFrame(const Component::Camera &cam) { - RenderPass::beginFrame(cam); + RenderPass::beginFrame(cam); } void CachedDepthPass::render() { - graphics->beginRenderPass(renderPass); - Array commands; + 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); + Gfx::ShaderPermutation permutation; + permutation.setPositionOnly(usePositionOnly); + permutation.setViewCulling(useViewCulling); 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); + permutation.setTaskFile("DrawListTask"); + permutation.setMeshFile("VisibilityMeshletPass"); } 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); + permutation.setVertexFile("LegacyPass"); } - 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.setFragmentFile("VisibilityPass"); + for (VertexData *vertexData : VertexData::getList()) { - 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) + 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()) { - 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++); - } + 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)); } - commands.add(std::move(command)); - } - graphics->executeCommands(std::move(commands)); - graphics->endRenderPass(); + graphics->executeCommands(std::move(commands)); + graphics->endRenderPass(); + // Sync depth read/write with depth pass depth read + depthBuffer->pipelineBarrier( + Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, + Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT); + // sync visibility write with depth pass visibility write + visibilityBuffer->pipelineBarrier( + Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); } void CachedDepthPass::endFrame() @@ -151,72 +164,66 @@ 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); + // 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); + TextureCreateInfo visibilityInfo = { + .format = Gfx::SE_FORMAT_R32_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); + Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ + .colorAttachments = {visibilityAttachment}, + .depthAttachment = depthAttachment, + }; + Array dependency = { + // { + // .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/DepthPrepass.cpp b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp index 4c2258a..8fddea7 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp @@ -9,21 +9,21 @@ 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", "VisibilityMeshletPass", false, true, "VisibilityPass", true, true, "DepthCullingTask"); + } + else + { + graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "LegacyPass"); + } } DepthPrepass::~DepthPrepass() @@ -32,116 +32,138 @@ DepthPrepass::~DepthPrepass() 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); - 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); + Gfx::ShaderPermutation permutation; + permutation.setPositionOnly(usePositionOnly); + permutation.setViewCulling(useViewCulling); 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); + permutation.setTaskFile("DepthCullingTask"); + permutation.setMeshFile("VisibilityMeshletPass"); } 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); + permutation.setVertexFile("LegacyPass"); } - 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.setFragmentFile("VisibilityPass"); + for (VertexData *vertexData : VertexData::getList()) { - command->drawMesh(vertexData->getNumInstances(), 1, 1); - } - else - { - const auto &materials = vertexData->getMaterialData(); - for (const auto &materialData : materials) - { - for (const auto &drawCall : materialData.instances) + 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()) { - // 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++); - } + 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) + { + 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)); } - commands.add(std::move(command)); - } - graphics->executeCommands(std::move(commands)); - graphics->endRenderPass(); + graphics->executeCommands(std::move(commands)); + graphics->endRenderPass(); + // Sync depth read/write with compute read + depthAttachment.getTexture()->pipelineBarrier( + Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + Gfx::SE_ACCESS_SHADER_READ_BIT, + Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT + ); + // Sync depth read/write with base pass read + depthAttachment.getTexture()->pipelineBarrier( + Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, + Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT + ); + // Sync visibility write with compute read + visibilityAttachment.getTexture()->pipelineBarrier( + Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + Gfx::SE_ACCESS_SHADER_READ_BIT, + Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT + ); } void DepthPrepass::endFrame() @@ -154,59 +176,60 @@ void DepthPrepass::publishOutputs() void DepthPrepass::createRenderPass() { - 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); + 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); + 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); + 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 cc19630..2eac270 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.h +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.h @@ -18,6 +18,7 @@ public: virtual void createRenderPass() override; private: Gfx::RenderTargetAttachment depthAttachment; + Gfx::RenderTargetAttachment visibilityAttachment; Gfx::OPipelineLayout depthPrepassLayout; }; DEFINE_REF(DepthPrepass) diff --git a/src/Engine/Graphics/VertexData.cpp b/src/Engine/Graphics/VertexData.cpp index 7a9fd92..e4c443e 100644 --- a/src/Engine/Graphics/VertexData.cpp +++ b/src/Engine/Graphics/VertexData.cpp @@ -130,7 +130,7 @@ void VertexData::createDescriptors() } } Array cullingData(numMeshlets); - std::memset(cullingData.data(), 0xff, cullingData.size()); + std::memset(cullingData.data(), 0xffff, cullingData.size() * sizeof(MeshletCullingInfo)); cullingOffsetBuffer->rotateBuffer(cullingOffsets.size() * sizeof(uint32)); cullingOffsetBuffer->updateContents(ShaderBufferCreateInfo{ .sourceData = { @@ -144,18 +144,19 @@ void VertexData::createDescriptors() Gfx::SE_ACCESS_MEMORY_READ_BIT, Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - cullingBuffer->rotateBuffer(numMeshlets * sizeof(MeshletCullingInfo)); + cullingBuffer->rotateBuffer(cullingData.size() * sizeof(MeshletCullingInfo)); cullingBuffer->updateContents(ShaderBufferCreateInfo{ .sourceData = { - .size = numMeshlets * sizeof(MeshletCullingInfo), + .size = cullingData.size() * sizeof(MeshletCullingInfo), .data = (uint8 *)cullingData.data(), }, - .numElements = numMeshlets}); + .numElements = cullingData.size()}); 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 = { diff --git a/src/Engine/Graphics/Vulkan/Queue.cpp b/src/Engine/Graphics/Vulkan/Queue.cpp index a3cd316..07c5288 100644 --- a/src/Engine/Graphics/Vulkan/Queue.cpp +++ b/src/Engine/Graphics/Vulkan/Queue.cpp @@ -47,6 +47,7 @@ void Queue::submitCommandBuffer(PCommand command, const Array& sign }; VK_CHECK(vkQueueSubmit(queue, 1, &submitInfo, command->fence->getHandle())); + command->fence->submit(); command->state = Command::State::Submit; command->waitFlags.clear(); command->waitSemaphores.clear(); diff --git a/src/Engine/Graphics/Vulkan/Resources.cpp b/src/Engine/Graphics/Vulkan/Resources.cpp index 5ff366c..b160425 100644 --- a/src/Engine/Graphics/Vulkan/Resources.cpp +++ b/src/Engine/Graphics/Vulkan/Resources.cpp @@ -20,38 +20,40 @@ Semaphore::Semaphore(PGraphics graphics) Semaphore::~Semaphore() { - //graphics->getDestructionManager()->queueSemaphore(graphics->getGraphicsCommands()->getCommands(), handle); + // graphics->getDestructionManager()->queueSemaphore(graphics->getGraphicsCommands()->getCommands(), handle); } - Fence::Fence(PGraphics graphics) - : graphics(graphics) - , signaled(false) + : graphics(graphics), status(Status::Ready) { VkFenceCreateInfo info = { .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, .pNext = nullptr, - .flags = 0 - }; + .flags = 0}; VK_CHECK(vkCreateFence(graphics->getDevice(), &info, nullptr, &fence)); } Fence::~Fence() { - vkWaitForFences(graphics->getDevice(), 1, &fence, true, 100000); + vkWaitForFences(graphics->getDevice(), 1, &fence, true, 10000000); vkDestroyFence(graphics->getDevice(), fence, nullptr); } +void Fence::submit() +{ + status = Status::InUse; +} + bool Fence::isSignaled() { - if (signaled) + if (status == Status::Signalled) { return true; } VkResult r = vkGetFenceStatus(graphics->getDevice(), fence); if (r == VK_SUCCESS) { - signaled = true; + status = Status::Signalled; return true; } if (r == VK_NOT_READY) @@ -67,11 +69,14 @@ bool Fence::isSignaled() void Fence::reset() { - if (signaled) + while (status == Status::InUse) + { + wait(1000000); + } + if (status == Status::Signalled) { VK_CHECK(vkResetFences(graphics->getDevice(), 1, &fence)); - //std::cout << vkGetFenceStatus(graphics->getDevice(), fence) << std::endl; - signaled = false; + status = Status::Ready; } } @@ -81,7 +86,7 @@ void Fence::wait(uint64 timeout) VkResult r = vkWaitForFences(graphics->getDevice(), 1, fences, true, timeout); if (r == VK_SUCCESS) { - signaled = true; + status = Status::Signalled; } else if (r == VK_TIMEOUT) { @@ -111,7 +116,7 @@ void DestructionManager::notifyCommandComplete() { for (size_t i = 0; i < resources.size(); ++i) { - if(!resources[i]->isCurrentlyBound()) + if (!resources[i]->isCurrentlyBound()) { resources.removeAt(i, false); i--; @@ -131,9 +136,9 @@ SamplerHandle::~SamplerHandle() } Sampler::Sampler(PGraphics graphics, VkSamplerCreateInfo createInfo) - : graphics(graphics) - , handle(new SamplerHandle(graphics, createInfo)) -{} + : graphics(graphics), handle(new SamplerHandle(graphics, createInfo)) +{ +} Sampler::~Sampler() { diff --git a/src/Engine/Graphics/Vulkan/Resources.h b/src/Engine/Graphics/Vulkan/Resources.h index 4369110..63d0960 100644 --- a/src/Engine/Graphics/Vulkan/Resources.h +++ b/src/Engine/Graphics/Vulkan/Resources.h @@ -32,6 +32,7 @@ class Fence public: Fence(PGraphics graphics); ~Fence(); + void submit(); bool isSignaled(); void reset(); constexpr VkFence getHandle() const @@ -46,7 +47,13 @@ public: private: PGraphics graphics; - bool signaled; + enum class Status + { + Ready, + InUse, + Signalled, + }; + Status status; VkFence fence; }; DEFINE_REF(Fence) diff --git a/src/Engine/Graphics/Vulkan/Window.cpp b/src/Engine/Graphics/Vulkan/Window.cpp index 9481ae8..4b5b702 100644 --- a/src/Engine/Graphics/Vulkan/Window.cpp +++ b/src/Engine/Graphics/Vulkan/Window.cpp @@ -114,9 +114,9 @@ void Window::pollInput() void Window::beginFrame() { - imageAvailableFences[currentSemaphoreIndex]->wait(10000000000); imageAvailableFences[currentSemaphoreIndex]->reset(); vkAcquireNextImageKHR(graphics->getDevice(), swapchain, std::numeric_limits::max(), imageAvailableSemaphores[currentSemaphoreIndex]->getHandle(), imageAvailableFences[currentSemaphoreIndex]->getHandle(), ¤tImageIndex); + imageAvailableFences[currentSemaphoreIndex]->submit(); graphics->getGraphicsCommands()->getCommands()->waitForSemaphore(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, imageAvailableSemaphores[currentSemaphoreIndex]); }