diff --git a/benchmark.py b/benchmark.py index 0e6fc25..91b4e8b 100644 --- a/benchmark.py +++ b/benchmark.py @@ -1,4 +1,4 @@ import subprocess -subprocess.run(['build/Benchmark.exe']) -subprocess.run(['build/Benchmark.exe', 'NOCULL']) \ No newline at end of file +subprocess.run(['Benchmark.exe']) +subprocess.run(['Benchmark.exe', 'NOCULL']) \ No newline at end of file diff --git a/res/shaders/DepthCullingTask.slang b/res/shaders/DepthCullingTask.slang index 3ab5ec5..eadb0b3 100644 --- a/res/shaders/DepthCullingTask.slang +++ b/res/shaders/DepthCullingTask.slang @@ -30,25 +30,30 @@ groupshared bool meshVisible; ParameterBlock pDepthAttachment; bool isBoxVisible(AABB bounding) { - int2 mipDimensions = uint2(uint(pViewParams.screenDimensions.x), uint(pViewParams.screenDimensions.y)); + int2 mipDimensions = int2(int(pViewParams.screenDimensions.x), int(pViewParams.screenDimensions.y)); // now we calculate what mip level we need to only sample up to 4 texels covering the entire meshlet int2 screenCornerMin = mipDimensions; - int2 screenCornerMax = uint2(0, 0); + int2 screenCornerMax = int2(0, 0); // lower values are closer float maxDepth = bounding.projectScreenDepth(modelViewProjection, screenCornerMin, screenCornerMax); uint mipOffset = 0; -// uint mipLevel = 0; -// int2 origScreenMin = screenCornerMin; -// int2 origScreenMax = screenCornerMax; + // in theory this wouldnt work if no corner was in screen, as min would be greater that max, however we verified that with view culling while(screenCornerMax.x - screenCornerMin.x > 1 || screenCornerMax.y - screenCornerMin.y > 1) { -// mipLevel++; mipOffset += mipDimensions.x * mipDimensions.y; mipDimensions = int2(mipDimensions.x + 1, mipDimensions.y + 1) / 2; - screenCornerMin = int2(screenCornerMin.x + 1, screenCornerMin.y + 1) / 2; + screenCornerMin = int2(screenCornerMin.x, screenCornerMin.y) / 2; screenCornerMax = int2(screenCornerMax.x, screenCornerMax.y) / 2; } + //float d = 1; + //for(uint y = screenCornerMin.y; y <= screenCornerMax.y; y++) + //{ + // for(uint x = screenCornerMin.x; x <= screenCornerMax.x; x++) + // { + // d = min(pDepthAttachment.buffer[mipOffset + (y * mipDimensions.x) + x], d); + // } + //} uint i0 = mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMin.x; uint i1 = mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMax.x; @@ -64,7 +69,7 @@ bool isBoxVisible(AABB bounding) // we want to check if the minimum depth (the value farthest away) is smaller than the maximum bounding box depth // otherwise, there is no way for the meshlet to be visible float d = min(min(d1, d2), min(d3, d4)); - + if(d < maxDepth) { return true; @@ -78,28 +83,30 @@ void taskMain( uint threadID: SV_GroupThreadID, uint groupID: SV_GroupID, ) { - head = 0; - instance = pScene.instances[pOffsets.instanceOffset + groupID]; - mesh = pScene.meshData[pOffsets.instanceOffset + groupID]; - p.instanceId = pOffsets.instanceOffset + groupID; - p.meshletOffset = mesh.meshletOffset; - p.cullingOffset = pScene.cullingOffsets[p.instanceId]; - modelViewProjection = mul(mul(pViewParams.projectionMatrix, pViewParams.viewMatrix), instance.transformMatrix); - 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]); - meshVisible = mesh.bounding.insideFrustum(viewFrustum) && isBoxVisible(mesh.bounding); - //meshVisible = true; - + if(threadID == 0) + { + head = 0; + instance = pScene.instances[pOffsets.instanceOffset + groupID]; + mesh = pScene.meshData[pOffsets.instanceOffset + groupID]; + p.instanceId = pOffsets.instanceOffset + groupID; + p.meshletOffset = mesh.meshletOffset; + p.cullingOffset = pScene.cullingOffsets[p.instanceId]; + modelViewProjection = mul(mul(pViewParams.projectionMatrix, pViewParams.viewMatrix), instance.transformMatrix); + 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]); + //meshVisible = mesh.bounding.insideFrustum(viewFrustum) && isBoxVisible(mesh.bounding); + meshVisible = true; + } GroupMemoryBarrierWithGroupSync(); if(!meshVisible) { diff --git a/res/shaders/DepthMipGen.slang b/res/shaders/DepthMipGen.slang index 338e6e4..15bd015 100644 --- a/res/shaders/DepthMipGen.slang +++ b/res/shaders/DepthMipGen.slang @@ -5,57 +5,51 @@ ParameterBlock pDepthAttachment; struct MipParam { - uint srcMipOffset; - uint dstMipOffset; - uint2 srcMipDim; - uint2 dstMipDim; + uint sourceOffset; + uint destOffset; + uint2 sourceDim; + uint2 destDim; } layout(push_constant) ConstantBuffer pMipParam; -float getSrcDepth(uint2 pos) +float readBuffer(uint2 pos) { - return pDepthAttachment.buffer[pMipParam.srcMipOffset + pos.x + (pos.y * pMipParam.srcMipDim.x)]; + if(pos.x >= pMipParam.sourceDim.x || pos.y >= pMipParam.sourceDim.y) + { + return 1.0f; + } + return pDepthAttachment.buffer[pMipParam.sourceOffset + pos.x + (pos.y * pMipParam.sourceDim.x)]; } -void setDstDepth(uint2 pos, float depth) -{ - pDepthAttachment.buffer[pMipParam.dstMipOffset + pos.x + (pos.y * pMipParam.dstMipDim.x)] = depth; -} - -[numthreads(BLOCK_SIZE, BLOCK_SIZE, 1)] [shader("compute")] +[numthreads(BLOCK_SIZE, BLOCK_SIZE, 1)] void reduceLevel( - uint3 threadID: SV_GroupThreadID, - uint3 groupID: SV_GroupID, -){ - uint2 minCoords = (groupID.xy * BLOCK_SIZE + threadID.xy) * 2; - - if(minCoords.x >= pMipParam.srcMipDim.x || minCoords.y >= pMipParam.srcMipDim.y) + uint2 dispatchID: SV_DispatchThreadID, +) { + if(dispatchID.x >= pMipParam.destDim.x || dispatchID.y >= pMipParam.destDim.y) { return; } - - uint2 maxCoords = uint2(min(minCoords.x + 1, pMipParam.srcMipDim.x - 1), min(minCoords.y + 1, pMipParam.srcMipDim.y - 1)); - - float d0 = getSrcDepth(uint2(minCoords.x, minCoords.y)); - float d1 = getSrcDepth(uint2(maxCoords.x, minCoords.y)); - float d2 = getSrcDepth(uint2(minCoords.x, maxCoords.y)); - float d3 = getSrcDepth(uint2(maxCoords.x, maxCoords.y)); - - float minDepth = min(min(d0, d1), min(d2, d3)); - setDstDepth(minCoords / 2, minDepth); + uint2 readOffset = dispatchID * 2; + float d0 = readBuffer(readOffset + uint2(0, 0)); + float d1 = readBuffer(readOffset + uint2(0, 1)); + float d2 = readBuffer(readOffset + uint2(1, 0)); + float d3 = readBuffer(readOffset + uint2(1, 1)); + pDepthAttachment.buffer[pMipParam.destOffset + dispatchID.x + (dispatchID.y * pMipParam.destDim.x)] = min(min(d0, d1), min(d2, d3)); } -[numthreads(BLOCK_SIZE, BLOCK_SIZE, 1)] +// each thread reduces the a pixel indivdually +// used for mip levels where the read size is smaller than +// the group dimensions [shader("compute")] -void initialReduce( - uint3 threadID: SV_GroupThreadID, - uint3 groupID: SV_GroupID, +[numthreads(BLOCK_SIZE, BLOCK_SIZE, 1)] +void sourceCopy( + uint2 dispatchID: SV_DispatchThreadID ) { - uint width = uint(pViewParams.screenDimensions.x); - int2 groupOffset = groupID.xy * BLOCK_SIZE; - int2 texCoord = groupOffset + threadID.xy; - float fDepth = pDepthAttachment.texture.Load(int3(texCoord, 0)).r; - pDepthAttachment.buffer[texCoord.x + (texCoord.y * width)] = fDepth; + if(dispatchID.x >= pViewParams.screenDimensions.x || dispatchID.y >= pViewParams.screenDimensions.y) + { + return; + } + pDepthAttachment.buffer[dispatchID.x + (dispatchID.y * uint(pViewParams.screenDimensions.x))] = pDepthAttachment.texture[uint2(dispatchID)]; } diff --git a/res/shaders/lib/Common.slang b/res/shaders/lib/Common.slang index f6a5266..2b046e5 100644 --- a/res/shaders/lib/Common.slang +++ b/res/shaders/lib/Common.slang @@ -88,7 +88,7 @@ float4 clipToScreen(float4 clip) float oz = 1; float pz = 0 - 1; float zf = pz * ndc.z + oz; - return float4(float2(texCoords.x, 1 - texCoords.y) * pViewParams.screenDimensions, 1 / zf, 1.0f); + return float4(float2(texCoords.x, 1 - texCoords.y) * pViewParams.screenDimensions, zf, 1.0f); } struct Plane diff --git a/src/Benchmark/PlayView.cpp b/src/Benchmark/PlayView.cpp index 2830ac8..3f6cf97 100644 --- a/src/Benchmark/PlayView.cpp +++ b/src/Benchmark/PlayView.cpp @@ -8,6 +8,7 @@ using namespace Seele; PlayView::PlayView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo& createInfo, std::string dllPath, bool useMeshCulling) : GameView(graphics, window, createInfo, dllPath) { getGlobals().useDepthCulling = useMeshCulling; + renderTimestamp = graphics->createTimestampQuery(2, "RenderTimestamp"); queryThread = std::thread([&]() { PRenderGraphResources res = renderGraph.getResources(); Gfx::PPipelineStatisticsQuery cachedQuery = res->requestQuery("CACHED_QUERY"); @@ -23,21 +24,23 @@ PlayView::PlayView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate << "DepthIAV,DepthIAP,DepthVS,DepthClipInv,DepthClipPrim,DepthFS,DepthCS,DepthTS,DepthMS," << "BaseIAV,BaseIAP,BaseVS,BaseClipInv,BaseClipPrim,BaseFS,BaseCS,BaseTS,BaseMS," << "LightCullIAV,LightCullIAP,LightCullVS,LightCullClipInv,LightCullClipPrim,LightCullFS,LightCullCS,LightCullTS,LightCullMS," - << "VisibilityIAV,VisibilityIAP,VisibilityVS,VisibilityClipInv,VisibilityClipPrim,VisibilityFS,VisibilityCS,VisibilityMS,VisibilityMS," << std::endl; + << "VisibilityIAV,VisibilityIAP,VisibilityVS,VisibilityClipInv,VisibilityClipPrim,VisibilityFS,VisibilityCS,VisibilityMS," + "VisibilityMS," + << std::endl; uint64 start = 0; uint64 prevBegin = 0; std::this_thread::sleep_for(std::chrono::milliseconds(500)); stats << std::fixed << std::setprecision(0); while (getGlobals().running) { - auto cachedResults = cachedQuery->getResults(); auto depthResults = depthQuery->getResults(); auto baseResults = baseQuery->getResults(); auto lightCullResults = lightCullQuery->getResults(); auto visiblityResults = visibilityQuery->getResults(); + int64 renderBegin = renderTimestamp->getResult().time; + int64 renderEnd = renderTimestamp->getResult().time; Map results; - for (uint32 i = 0; i < 11; ++i) - { + for (uint32 i = 0; i < 11; ++i) { auto ts = timestamps->getResult(); results[ts.name] = ts.time; } @@ -53,12 +56,10 @@ PlayView::PlayView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate int64 visibilityTime = results.at("VisibilityEnd") - results.at("VisibilityBegin"); int64 frameTime = cachedTime + mipTime + depthTime + baseTime + lightCullTime + visibilityTime; - stats << relTime << "," << cachedTime << "," << mipTime << "," << depthTime << "," - << visibilityTime - << "," << lightCullTime << "," << baseTime << "," - << frameTime << "," << cachedResults << depthResults << baseResults << lightCullResults << visiblityResults << std::endl; + stats << relTime << "," << cachedTime << "," << mipTime << "," << depthTime << "," << visibilityTime << "," << lightCullTime + << "," << baseTime << "," << frameTime << "," << cachedResults << depthResults << baseResults << lightCullResults + << visiblityResults << std::endl; stats.flush(); - // std::cout << "Writing " << timestamps[0].time << std::endl; } }); } @@ -73,6 +74,10 @@ void PlayView::commitUpdate() { GameView::commitUpdate(); } void PlayView::prepareRender() { GameView::prepareRender(); } -void PlayView::render() { GameView::render(); } +void PlayView::render() { + renderTimestamp->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "RenderBegin"); + GameView::render(); + renderTimestamp->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "RenderEnd"); +} void PlayView::keyCallback(KeyCode code, InputAction action, KeyModifier modifier) { GameView::keyCallback(code, action, modifier); } diff --git a/src/Benchmark/PlayView.h b/src/Benchmark/PlayView.h index 08f3acd..6b763cd 100644 --- a/src/Benchmark/PlayView.h +++ b/src/Benchmark/PlayView.h @@ -17,6 +17,7 @@ class PlayView : public GameView { private: std::thread queryThread; + Gfx::OTimestampQuery renderTimestamp; }; DECLARE_REF(PlayView) } // namespace Seele \ No newline at end of file diff --git a/src/Editor/Window/PlayView.cpp b/src/Editor/Window/PlayView.cpp index 600451d..ed82e86 100644 --- a/src/Editor/Window/PlayView.cpp +++ b/src/Editor/Window/PlayView.cpp @@ -45,4 +45,6 @@ void PlayView::keyCallback(KeyCode code, InputAction action, KeyModifier modifie std::cout << cam.getCameraPosition() << std::endl; std::cout << tra.getRotation() << std::endl; } + if (code == KeyCode::KEY_R && action == InputAction::RELEASE) { + } } diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index def8e18..b3a676e 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -57,8 +57,11 @@ int main() { // AssetImporter::importFont(FontImportArgs{ // .filePath = "./fonts/Calibri.ttf", // }); + //AssetImporter::importMesh(MeshImportArgs{ + // .filePath = sourcePath / "import/models/cube.fbx", + //}); AssetImporter::importMesh(MeshImportArgs{ - .filePath = sourcePath / "import/models/cube.fbx", + .filePath = sourcePath / "import/models/culling.fbx", }); AssetImporter::importTexture(TextureImportArgs{ .filePath = sourcePath / "import/textures/skyboxsun5deg_tn.jpg", @@ -72,10 +75,10 @@ int main() { .filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.glb", .importPath = "Whitechapel", }); - AssetImporter::importMesh(MeshImportArgs{ - .filePath = sourcePath / "import/models/city-suburbs/source/city-suburbs.obj", - .importPath = "suburbs", - }); + //AssetImporter::importMesh(MeshImportArgs{ + // .filePath = sourcePath / "import/models/city-suburbs/source/city-suburbs.obj", + // .importPath = "suburbs", + //}); getThreadPool().waitIdle(); vd->commitMeshes(); WindowCreateInfo mainWindowInfo = { diff --git a/src/Engine/Component/Mesh.h b/src/Engine/Component/Mesh.h index c8a57c5..393d019 100644 --- a/src/Engine/Component/Mesh.h +++ b/src/Engine/Component/Mesh.h @@ -5,6 +5,7 @@ namespace Seele { namespace Component { struct Mesh { PMeshAsset asset; + Array meshletOffsets; bool isStatic = true; }; } // namespace Component diff --git a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp index 361426e..79129ad 100644 --- a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp @@ -6,10 +6,6 @@ using namespace Seele; DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) { depthAttachmentLayout = graphics->createDescriptorLayout("pDepthAttachment"); - //depthAttachmentLayout->addDescriptorBinding(Gfx::DescriptorBinding{ - // .binding = 0, - // .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - //}); depthAttachmentLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 0, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, @@ -20,16 +16,6 @@ DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : Rend .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .shaderStages = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_COMPUTE_BIT, }); - //depthAttachmentLayout->addDescriptorBinding(Gfx::DescriptorBinding{ - // .binding = 3, - // .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, - // .shaderStages = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_COMPUTE_BIT, - //}); - //depthAttachmentLayout->addDescriptorBinding(Gfx::DescriptorBinding{ - // .binding = 4, - // .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, - // .shaderStages = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_COMPUTE_BIT, - //}); depthAttachmentLayout->create(); depthCullingLayout = graphics->createPipelineLayout("DepthPrepassLayout"); @@ -94,33 +80,34 @@ void DepthCullingPass::render() { set->writeChanges(); timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "MipBegin"); - Gfx::OComputeCommand computeCommand = graphics->createComputeCommand("InitialReduce"); - computeCommand->bindPipeline(depthInitialReduce); + // First we generate a pixel value per thread, while using a whole threadgroup + // for a single one would be a waste + Gfx::OComputeCommand computeCommand = graphics->createComputeCommand("MipGen"); + computeCommand->bindPipeline(depthSourceCopy); computeCommand->bindDescriptor({viewParamsSet, set}); - UVector2 reduceDimensions = UVector2(viewport->getOwner()->getFramebufferWidth() + BLOCK_SIZE - 1, - viewport->getOwner()->getFramebufferHeight() + BLOCK_SIZE - 1) / - uint32(BLOCK_SIZE); - computeCommand->dispatch(reduceDimensions.x, reduceDimensions.y, 1); + computeCommand->dispatch((viewport->getWidth() + BLOCK_SIZE - 1) / BLOCK_SIZE, (viewport->getHeight() + BLOCK_SIZE - 1) / BLOCK_SIZE, + 1); graphics->executeCommands(std::move(computeCommand)); - - for (uint32 i = 0; i < mipOffsets.size() - 1; ++i) { + for (uint32 i = 0; i < mipOffsets.size() - 1; ++i) + { depthMipBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); - Gfx::OComputeCommand mipCommand = graphics->createComputeCommand(fmt::format("MipGenLevel{0}", i)); - mipCommand->bindPipeline(depthMipGen); - mipCommand->bindDescriptor({viewParamsSet, set}); - MipParam params = { - .srcMipOffset = mipOffsets[i], - .dstMipOffset = mipOffsets[i + 1], - .srcMipDim = mipDims[i], - .dstMipDim = mipDims[i + 1], + MipParam param = { + .sourceOffset = mipOffsets[i], + .destOffset = mipOffsets[i + 1], + .sourceDim = mipDims[i], + .destDim = mipDims[i + 1], }; - mipCommand->pushConstants(Gfx::SE_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(MipParam), ¶ms); - UVector2 threadGroups = (reduceDimensions + 1u) / 2u; - mipCommand->dispatch(threadGroups.x, threadGroups.y, 1); - graphics->executeCommands(std::move(mipCommand)); + Gfx::OComputeCommand reduceCommand = graphics->createComputeCommand("ReduceCommand"); + reduceCommand->bindPipeline(depthReduceLevel); + reduceCommand->bindDescriptor({viewParamsSet, set}); + reduceCommand->pushConstants(Gfx::SE_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(MipParam), ¶m); + auto dispatchDim = (mipDims[i + 1] + uint32(BLOCK_SIZE) - 1u) / uint32(BLOCK_SIZE); + reduceCommand->dispatch(dispatchDim.x, dispatchDim.y, 1); + graphics->executeCommands(std::move(reduceCommand)); } + depthMipBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT); @@ -256,22 +243,21 @@ void DepthCullingPass::publishOutputs() { graphics->beginShaderCompilation(ShaderCompilationInfo{ .name = "DepthMipCompute", .modules = {"DepthMipGen"}, - .entryPoints = {{"initialReduce", "DepthMipGen"}, {"reduceLevel", "DepthMipGen"}}, + .entryPoints = {{"sourceCopy", "DepthMipGen"}, {"reduceLevel", "DepthMipGen"}}, .rootSignature = depthComputeLayout, }); - depthInitialReduceShader = graphics->createComputeShader({0}); + depthSourceCopyShader = graphics->createComputeShader({0}); depthComputeLayout->create(); Gfx::ComputePipelineCreateInfo pipelineCreateInfo = { - .computeShader = depthInitialReduceShader, + .computeShader = depthSourceCopyShader, .pipelineLayout = depthComputeLayout, }; - depthInitialReduce = graphics->createComputePipeline(pipelineCreateInfo); - depthMipGenShader = graphics->createComputeShader({1}); + depthSourceCopy = graphics->createComputePipeline(pipelineCreateInfo); - pipelineCreateInfo.computeShader = depthMipGenShader; - - depthMipGen = graphics->createComputePipeline(pipelineCreateInfo); + depthReduceLevelShader = graphics->createComputeShader({1}); + pipelineCreateInfo.computeShader = depthReduceLevelShader; + depthReduceLevel = graphics->createComputePipeline(pipelineCreateInfo); query = graphics->createPipelineStatisticsQuery("DepthPipelineStatistics"); resources->registerQueryOutput("DEPTH_QUERY", query); diff --git a/src/Engine/Graphics/RenderPass/DepthCullingPass.h b/src/Engine/Graphics/RenderPass/DepthCullingPass.h index e22a001..8daadc9 100644 --- a/src/Engine/Graphics/RenderPass/DepthCullingPass.h +++ b/src/Engine/Graphics/RenderPass/DepthCullingPass.h @@ -1,8 +1,8 @@ #pragma once -#include "MinimalEngine.h" -#include "RenderPass.h" #include "Graphics/Pipeline.h" #include "Graphics/Query.h" +#include "MinimalEngine.h" +#include "RenderPass.h" namespace Seele { class DepthCullingPass : public RenderPass { @@ -20,10 +20,10 @@ class DepthCullingPass : public RenderPass { private: constexpr static uint64 BLOCK_SIZE = 32; struct MipParam { - uint32 srcMipOffset; - uint32 dstMipOffset; - UVector2 srcMipDim; - UVector2 dstMipDim; + uint32 sourceOffset; + uint32 destOffset; + UVector2 sourceDim; + UVector2 destDim; }; Array mipOffsets; @@ -38,11 +38,11 @@ class DepthCullingPass : public RenderPass { Gfx::PTimestampQuery timestamps; Gfx::OPipelineLayout depthComputeLayout; - Gfx::OComputeShader depthInitialReduceShader; - Gfx::PComputePipeline depthInitialReduce; - Gfx::OComputeShader depthMipGenShader; - Gfx::PComputePipeline depthMipGen; - + Gfx::OComputeShader depthSourceCopyShader; + Gfx::PComputePipeline depthSourceCopy; + Gfx::OComputeShader depthReduceLevelShader; + Gfx::PComputePipeline depthReduceLevel; + Gfx::PShaderBuffer cullingBuffer; }; DEFINE_REF(DepthCullingPass) diff --git a/src/Engine/Graphics/VertexData.cpp b/src/Engine/Graphics/VertexData.cpp index bca4524..b58bbbe 100644 --- a/src/Engine/Graphics/VertexData.cpp +++ b/src/Engine/Graphics/VertexData.cpp @@ -12,8 +12,6 @@ using namespace Seele; constexpr static uint64 NUM_DEFAULT_ELEMENTS = 17962284; -Map VertexData::instanceIdMap; -uint64 VertexData::instanceCount = 0; uint64 VertexData::meshletCount = 0; void VertexData::resetMeshData() { @@ -37,7 +35,7 @@ void VertexData::resetMeshData() { } } -void VertexData::updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Component::Transform& transform) { +void VertexData::updateMesh(uint32 meshletOffset, PMesh mesh, Component::Transform& transform) { std::unique_lock l(materialDataLock); PMaterialInstance referencedInstance = mesh->referencedMaterial->getHandle(); PMaterial mat = referencedInstance->getBaseMaterial(); @@ -49,8 +47,6 @@ void VertexData::updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Compo .inverseTransformMatrix = glm::inverse(transformMatrix), }; - auto [instanceId, meshletOffset] = getCullingMapping(id, meshIndex, data.numMeshlets); - referencedInstance->updateDescriptor(); if (mat->hasTransparency()) { auto params = referencedInstance->getMaterialOffsets(); @@ -260,7 +256,7 @@ void VertexData::commitMeshes() { indices.clear(); meshlets.clear(); dirty = false; - //graphics->buildBottomLevelAccelerationStructures(std::move(dataToBuild)); + // graphics->buildBottomLevelAccelerationStructures(std::move(dataToBuild)); } MeshId VertexData::allocateVertexData(uint64 numVertices) { @@ -282,8 +278,7 @@ void VertexData::serializeMesh(MeshId id, uint64 numVertices, ArchiveBuffer& buf std::unique_lock l(vertexDataLock); Array out; MeshData data = meshData[id]; - for (size_t i = 0; i < data.numMeshlets; ++i) - { + for (size_t i = 0; i < data.numMeshlets; ++i) { MeshletDescription& desc = meshlets[i + data.meshletOffset]; Meshlet m; std::memcpy(m.uniqueVertices, &vertexIndices[desc.vertexOffset], desc.vertexCount * sizeof(uint32)); @@ -299,7 +294,7 @@ void VertexData::serializeMesh(MeshId id, uint64 numVertices, ArchiveBuffer& buf Serialization::save(buffer, ind); } -uint64 VertexData::deserializeMesh(MeshId id, ArchiveBuffer& buffer) { +uint64 VertexData::deserializeMesh(MeshId id, ArchiveBuffer& buffer) { Array in; Array ind; Serialization::load(buffer, in); @@ -385,13 +380,10 @@ void VertexData::destroy() { materialData.clear(); } -VertexData::CullingMapping VertexData::getCullingMapping(entt::entity id, uint32 meshIndex, uint32 numMeshlets) { - MeshMapping key = MeshMapping{.id = id, .meshId = meshIndex}; - if (!instanceIdMap.contains(key)) { - instanceIdMap[key] = CullingMapping{.instanceId = instanceCount++, .cullingOffset = uint32(meshletCount)}; - meshletCount += numMeshlets; - } - return instanceIdMap[key]; +uint32 VertexData::addCullingMapping(MeshId id) { + uint32 result = meshletCount; + meshletCount += getMeshData(id).numMeshlets; + return result; } VertexData::VertexData() : idCounter(0), head(0), verticesAllocated(0), dirty(false) {} diff --git a/src/Engine/Graphics/VertexData.h b/src/Engine/Graphics/VertexData.h index f267d44..724c096 100644 --- a/src/Engine/Graphics/VertexData.h +++ b/src/Engine/Graphics/VertexData.h @@ -55,7 +55,7 @@ class VertexData { Gfx::PBottomLevelAS rayTracingScene; }; void resetMeshData(); - void updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Component::Transform& transform); + void updateMesh(uint32 meshletOffset, PMesh mesh, Component::Transform& transform); void createDescriptors(); void loadMesh(MeshId id, Array indices, Array meshlets); void commitMeshes(); @@ -85,12 +85,7 @@ class VertexData { virtual void init(Gfx::PGraphics graphics); virtual void destroy(); - struct CullingMapping { - uint64 instanceId; - uint32 cullingOffset; - }; - static CullingMapping getCullingMapping(entt::entity id, uint32 meshIndex, uint32 numMeshlets); - static uint64 getInstanceCount() { return instanceCount; } + uint32 addCullingMapping(MeshId id); static uint64 getMeshletCount() { return meshletCount; } protected: @@ -125,13 +120,6 @@ class VertexData { Array vertexIndices; Array indices; - struct MeshMapping { - entt::entity id; - uint32 meshId; - auto operator<=>(const MeshMapping& other) const = default; - }; - static Map instanceIdMap; - static uint64 instanceCount; static uint64 meshletCount; Gfx::PGraphics graphics; diff --git a/src/Engine/Graphics/slang-compile.cpp b/src/Engine/Graphics/slang-compile.cpp index 8e44edb..e863653 100644 --- a/src/Engine/Graphics/slang-compile.cpp +++ b/src/Engine/Graphics/slang-compile.cpp @@ -42,7 +42,7 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg option[1].value.intValue0 = 1; option[2].name = slang::CompilerOptionName::DebugInformation; option[2].value.kind = slang::CompilerOptionValueKind::Int; - option[2].value.intValue0 = SLANG_DEBUG_INFO_LEVEL_NONE; + option[2].value.intValue0 = SLANG_DEBUG_INFO_LEVEL_STANDARD; option[3].name = slang::CompilerOptionName::DebugInformationFormat; option[3].value.kind = slang::CompilerOptionValueKind::Int; option[3].value.intValue0 = SLANG_DEBUG_INFO_FORMAT_PDB; diff --git a/src/Engine/System/MeshUpdater.cpp b/src/Engine/System/MeshUpdater.cpp index c9e69e5..5940733 100644 --- a/src/Engine/System/MeshUpdater.cpp +++ b/src/Engine/System/MeshUpdater.cpp @@ -10,7 +10,12 @@ MeshUpdater::MeshUpdater(PScene scene) : ComponentSystemmeshes.size(); ++i) { + comp.meshletOffsets.add(comp.asset->meshes[i]->vertexData->addCullingMapping(comp.asset->meshes[i]->id)); + } + } for (uint32 i = 0; i < comp.asset->meshes.size(); ++i) { - comp.asset->meshes[i]->vertexData->updateMesh(id, i, comp.asset->meshes[i], transform); + comp.asset->meshes[i]->vertexData->updateMesh(comp.meshletOffsets[i], comp.asset->meshes[i], transform); } }