From e5c3918989fe01d56757d605d96a53864fcae91d Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Tue, 3 Sep 2024 11:03:23 +0200 Subject: [PATCH] Apparently it is still not working??? --- benchmark.py | 4 + res/shaders/DepthCullingTask.slang | 46 +++-- res/shaders/lib/Common.slang | 2 +- src/Benchmark/PlayView.cpp | 46 +++-- src/Editor/main.cpp | 8 +- src/Engine/Graphics/Query.h | 4 +- src/Engine/Graphics/RenderPass/BasePass.cpp | 10 +- src/Engine/Graphics/RenderPass/BasePass.h | 2 +- .../Graphics/RenderPass/CachedDepthPass.cpp | 18 +- .../Graphics/RenderPass/DepthCullingPass.cpp | 15 +- .../Graphics/RenderPass/DepthCullingPass.h | 2 +- .../Graphics/RenderPass/LightCullingPass.cpp | 5 +- .../Graphics/RenderPass/LightCullingPass.h | 2 +- .../Graphics/RenderPass/VisibilityPass.cpp | 10 +- .../Graphics/RenderPass/VisibilityPass.h | 2 +- src/Engine/Graphics/VertexData.cpp | 2 +- src/Engine/Graphics/Vulkan/Graphics.cpp | 6 +- src/Engine/Graphics/Vulkan/Query.cpp | 164 +++++++++++------- src/Engine/Graphics/Vulkan/Query.h | 16 +- 19 files changed, 197 insertions(+), 167 deletions(-) create mode 100644 benchmark.py diff --git a/benchmark.py b/benchmark.py new file mode 100644 index 0000000..0e6fc25 --- /dev/null +++ b/benchmark.py @@ -0,0 +1,4 @@ +import subprocess + +subprocess.run(['build/Benchmark.exe']) +subprocess.run(['build/Benchmark.exe', 'NOCULL']) \ No newline at end of file diff --git a/res/shaders/DepthCullingTask.slang b/res/shaders/DepthCullingTask.slang index 5ede2e3..3ab5ec5 100644 --- a/res/shaders/DepthCullingTask.slang +++ b/res/shaders/DepthCullingTask.slang @@ -78,30 +78,28 @@ void taskMain( uint threadID: SV_GroupThreadID, uint groupID: SV_GroupID, ) { - 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 = isBoxVisible(mesh.bounding); - meshVisible = true; - } + 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/lib/Common.slang b/res/shaders/lib/Common.slang index 2b046e5..f6a5266 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, zf, 1.0f); + return float4(float2(texCoords.x, 1 - texCoords.y) * pViewParams.screenDimensions, 1 / zf, 1.0f); } struct Plane diff --git a/src/Benchmark/PlayView.cpp b/src/Benchmark/PlayView.cpp index a47ec06..2830ac8 100644 --- a/src/Benchmark/PlayView.cpp +++ b/src/Benchmark/PlayView.cpp @@ -15,44 +15,42 @@ PlayView::PlayView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate Gfx::PPipelineStatisticsQuery baseQuery = res->requestQuery("BASEPASS_QUERY"); Gfx::PPipelineStatisticsQuery lightCullQuery = res->requestQuery("LIGHTCULL_QUERY"); Gfx::PPipelineStatisticsQuery visibilityQuery = res->requestQuery("VISIBILITY_QUERY"); - Gfx::PTimestampQuery cachedTS = res->requestTimestampQuery("CACHED_TS"); - Gfx::PTimestampQuery depthTS = res->requestTimestampQuery("DEPTH_TS"); - Gfx::PTimestampQuery lightCullTS = res->requestTimestampQuery("LIGHTCULL_TS"); - Gfx::PTimestampQuery visibilityTS = res->requestTimestampQuery("VISIBILITY_TS"); - Gfx::PTimestampQuery baseTS = res->requestTimestampQuery("BASE_TS"); + Gfx::PTimestampQuery timestamps = res->requestTimestampQuery("TIMESTAMPS"); std::ofstream stats(fmt::format("stats{}.csv", useMeshCulling ? "" : "NOCULL")); stats << "RelTime," << "CACHED,MIPGEN,DEPTHCULL,VISIBILITY,LIGHTCULL,BASE,FrameTime," - << "CachedIAV,CachedIAP,CachedVS,CachedClipInv,CachedClipPrim,CachedFS,CachedCS," - << "DepthIAV,DepthIAP,DepthVS,DepthClipInv,DepthClipPrim,DepthFS,DepthCS," - << "BaseIAV,BaseIAP,BaseVS,BaseClipInv,BaseClipPrim,BaseFS,BaseCS," - << "LightCullIAV,LightCullIAP,LightCullVS,LightCullClipInv,LightCullClipPrim,LightCullFS,LightCullCS," - << "VisibilityIAV,VisibilityIAP,VisibilityVS,VisibilityClipInv,VisibilityClipPrim,VisibilityFS,VisibilityCS" << std::endl; + << "CachedIAV,CachedIAP,CachedVS,CachedClipInv,CachedClipPrim,CachedFS,CachedCS,CachedTS,CachedMS," + << "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; 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 cached = cachedTS->getResults(); - auto depth = depthTS->getResults(); - auto lightCull = lightCullTS->getResults(); - auto visibility = visibilityTS->getResults(); - auto base = baseTS->getResults(); + auto cachedResults = cachedQuery->getResults(); auto depthResults = depthQuery->getResults(); auto baseResults = baseQuery->getResults(); auto lightCullResults = lightCullQuery->getResults(); auto visiblityResults = visibilityQuery->getResults(); - if (start == 0) { - start = cached[0].time; + Map results; + for (uint32 i = 0; i < 11; ++i) + { + auto ts = timestamps->getResult(); + results[ts.name] = ts.time; } - int64 relTime = cached[0].time - start; - int64 cachedTime = cached[1].time - cached[0].time; - int64 mipTime = depth[1].time - depth[0].time; - int64 depthTime = depth[2].time - depth[0].time; - int64 baseTime = base[1].time - base[0].time; - int64 lightCullTime = lightCull[1].time - lightCull[0].time; - int64 visibilityTime = visibility[1].time - visibility[0].time; + if (start == 0) { + start = results.at("CachedBegin"); + } + int64 relTime = results.at("CachedBegin") - start; + int64 cachedTime = results.at("CachedEnd") - results.at("CachedBegin"); + int64 mipTime = results.at("CullingBegin") - results.at("MipBegin"); + int64 depthTime = results.at("CullingEnd") - results.at("CullingBegin"); + int64 baseTime = results.at("BaseEnd") - results.at("BaseBegin"); + int64 lightCullTime = results.at("LightCullEnd") - results.at("LightCullBegin"); + int64 visibilityTime = results.at("VisibilityEnd") - results.at("VisibilityBegin"); int64 frameTime = cachedTime + mipTime + depthTime + baseTime + lightCullTime + visibilityTime; stats << relTime << "," << cachedTime << "," << mipTime << "," << depthTime << "," diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index d22754b..def8e18 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -72,10 +72,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/Graphics/Query.h b/src/Engine/Graphics/Query.h index c4bd14d..e435f32 100644 --- a/src/Engine/Graphics/Query.h +++ b/src/Engine/Graphics/Query.h @@ -57,10 +57,8 @@ class TimestampQuery { public: TimestampQuery(); virtual ~TimestampQuery(); - virtual void begin() = 0; virtual void write(SePipelineStageFlagBits stage, const std::string& name = "") = 0; - virtual void end() = 0; - virtual Array getResults() = 0; + virtual Timestamp getResult() = 0; }; DEFINE_REF(TimestampQuery) } // namespace Gfx diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index a08eb31..8ce8096 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -26,7 +26,7 @@ void Seele::addDebugVertex(DebugVertex vert) { gDebugVertices.add(vert); } void Seele::addDebugVertices(Array verts) { gDebugVertices.addAll(verts); } BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) { - waterRenderer = new WaterRenderer(graphics, scene, viewParamsLayout); + //waterRenderer = new WaterRenderer(graphics, scene, viewParamsLayout); basePassLayout = graphics->createPipelineLayout("BasePassLayout"); basePassLayout->addDescriptorLayout(viewParamsLayout); @@ -145,7 +145,6 @@ void BasePass::render() { transparentCulling->writeChanges(); query->beginQuery(); - timestamps->begin(); timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "BaseBegin"); graphics->beginRenderPass(renderPass); Array commands; @@ -196,7 +195,7 @@ void BasePass::render() { }, .rasterizationState = { - .cullMode = Gfx::SeCullModeFlags(twoSided ? Gfx::SE_CULL_MODE_NONE : Gfx::SE_CULL_MODE_BACK_BIT), + .cullMode = Gfx::SE_CULL_MODE_NONE, }, .colorBlend = { @@ -374,7 +373,6 @@ void BasePass::render() { graphics->endRenderPass(); query->endQuery(); timestamps->write(Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, "BaseEnd"); - timestamps->end(); gDebugVertices.clear(); } @@ -426,13 +424,13 @@ void BasePass::publishOutputs() { resources->registerRenderPassOutput("BASEPASS_DEPTH", depthAttachment); timestamps = graphics->createTimestampQuery(2, "BaseTS"); - resources->registerTimestampQueryOutput("BASE_TS", timestamps); query = graphics->createPipelineStatisticsQuery("BasePassPipelineStatistics"); resources->registerQueryOutput("BASEPASS_QUERY", query); } void BasePass::createRenderPass() { cullingBuffer = resources->requestBuffer("CULLINGBUFFER"); + timestamps = resources->requestTimestampQuery("TIMESTAMPS"); Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ .colorAttachments = {msColorAttachment}, @@ -472,7 +470,7 @@ void BasePass::createRenderPass() { oLightGrid = resources->requestTexture("LIGHTCULLING_OLIGHTGRID"); tLightGrid = resources->requestTexture("LIGHTCULLING_TLIGHTGRID"); - waterRenderer->setViewport(viewport, renderPass); + //waterRenderer->setViewport(viewport, renderPass); // Debug rendering { diff --git a/src/Engine/Graphics/RenderPass/BasePass.h b/src/Engine/Graphics/RenderPass/BasePass.h index e2123c6..df99ad5 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.h +++ b/src/Engine/Graphics/RenderPass/BasePass.h @@ -45,7 +45,7 @@ class BasePass : public RenderPass { Gfx::ODescriptorLayout lightCullingLayout; Gfx::OPipelineStatisticsQuery query; - Gfx::OTimestampQuery timestamps; + Gfx::PTimestampQuery timestamps; Gfx::PShaderBuffer cullingBuffer; diff --git a/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp b/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp index ac7b6df..7fbbace 100644 --- a/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp +++ b/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp @@ -40,13 +40,10 @@ CachedDepthPass::CachedDepthPass(Gfx::PGraphics graphics, PScene scene) : Render CachedDepthPass::~CachedDepthPass() {} -void CachedDepthPass::beginFrame(const Component::Camera& cam) { - RenderPass::beginFrame(cam); -} +void CachedDepthPass::beginFrame(const Component::Camera& cam) { RenderPass::beginFrame(cam); } void CachedDepthPass::render() { query->beginQuery(); - timestamps->begin(); timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "CachedBegin"); graphics->beginRenderPass(renderPass); Array commands; @@ -78,6 +75,10 @@ void CachedDepthPass::render() { .fragmentShader = collection->fragmentShader, .renderPass = renderPass, .pipelineLayout = collection->pipelineLayout, + .rasterizationState = + { + .cullMode = Gfx::SE_CULL_MODE_NONE, + }, .colorBlend = { .attachmentCount = 1, @@ -91,6 +92,10 @@ void CachedDepthPass::render() { .fragmentShader = collection->fragmentShader, .renderPass = renderPass, .pipelineLayout = collection->pipelineLayout, + .rasterizationState = + { + .cullMode = Gfx::SE_CULL_MODE_NONE, + }, .colorBlend = { .attachmentCount = 1, @@ -128,7 +133,6 @@ void CachedDepthPass::render() { graphics->executeCommands(std::move(commands)); graphics->endRenderPass(); timestamps->write(Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, "CachedEnd"); - timestamps->end(); query->endQuery(); } @@ -163,8 +167,8 @@ void CachedDepthPass::publishOutputs() { query = graphics->createPipelineStatisticsQuery("CachedPipelineStatistics"); resources->registerQueryOutput("CACHED_QUERY", query); - timestamps = graphics->createTimestampQuery(2, "CachedTS"); - resources->registerTimestampQueryOutput("CACHED_TS", timestamps); + timestamps = graphics->createTimestampQuery(7, "CachedTS"); + resources->registerTimestampQueryOutput("TIMESTAMPS", timestamps); } void CachedDepthPass::createRenderPass() { diff --git a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp index 7aaffff..361426e 100644 --- a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp @@ -93,7 +93,6 @@ void DepthCullingPass::render() { set->updateBuffer(1, depthMipBuffer); set->writeChanges(); - timestamps->begin(); timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "MipBegin"); Gfx::OComputeCommand computeCommand = graphics->createComputeCommand("InitialReduce"); computeCommand->bindPipeline(depthInitialReduce); @@ -160,6 +159,10 @@ void DepthCullingPass::render() { .fragmentShader = collection->fragmentShader, .renderPass = renderPass, .pipelineLayout = collection->pipelineLayout, + .rasterizationState = + { + .cullMode = Gfx::SE_CULL_MODE_NONE, + }, .colorBlend = { .attachmentCount = 1, @@ -173,6 +176,10 @@ void DepthCullingPass::render() { .fragmentShader = collection->fragmentShader, .renderPass = renderPass, .pipelineLayout = collection->pipelineLayout, + .rasterizationState = + { + .cullMode = Gfx::SE_CULL_MODE_NONE, + }, .colorBlend = { .attachmentCount = 1, @@ -210,7 +217,6 @@ void DepthCullingPass::render() { graphics->executeCommands(std::move(commands)); graphics->endRenderPass(); timestamps->write(Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, "CullingEnd"); - timestamps->end(); query->endQuery(); // Sync depth read/write with compute read depthAttachment.getTexture()->pipelineBarrier( @@ -243,8 +249,6 @@ void DepthCullingPass::publishOutputs() { .data = nullptr, }, .numElements = bufferSize, - .clearValue = 0, - .createCleared = true, .dynamic = true, .name = "DepthMipBuffer", }); @@ -269,14 +273,13 @@ void DepthCullingPass::publishOutputs() { depthMipGen = graphics->createComputePipeline(pipelineCreateInfo); - timestamps = graphics->createTimestampQuery(3, "CullingTS"); - resources->registerTimestampQueryOutput("DEPTH_TS", timestamps); query = graphics->createPipelineStatisticsQuery("DepthPipelineStatistics"); resources->registerQueryOutput("DEPTH_QUERY", query); } void DepthCullingPass::createRenderPass() { cullingBuffer = resources->requestBuffer("CULLINGBUFFER"); + timestamps = resources->requestTimestampQuery("TIMESTAMPS"); depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH"); depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); diff --git a/src/Engine/Graphics/RenderPass/DepthCullingPass.h b/src/Engine/Graphics/RenderPass/DepthCullingPass.h index a0f94a4..e22a001 100644 --- a/src/Engine/Graphics/RenderPass/DepthCullingPass.h +++ b/src/Engine/Graphics/RenderPass/DepthCullingPass.h @@ -35,7 +35,7 @@ class DepthCullingPass : public RenderPass { Gfx::ODescriptorLayout depthAttachmentLayout; Gfx::OPipelineLayout depthCullingLayout; Gfx::OPipelineStatisticsQuery query; - Gfx::OTimestampQuery timestamps; + Gfx::PTimestampQuery timestamps; Gfx::OPipelineLayout depthComputeLayout; Gfx::OComputeShader depthInitialReduceShader; diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp index 1d4d232..d54967d 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp @@ -37,7 +37,6 @@ void LightCullingPass::beginFrame(const Component::Camera& cam) { void LightCullingPass::render() { query->beginQuery(); - timestamps->begin(); timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "LightCullBegin"); oLightGrid->pipelineBarrier(Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); @@ -64,7 +63,6 @@ void LightCullingPass::render() { // std::cout << "Execute" << std::endl; graphics->executeCommands(std::move(commands)); timestamps->write(Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, "LightCullEnd"); - timestamps->end(); query->endQuery(); oLightIndexList->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); @@ -227,13 +225,12 @@ void LightCullingPass::publishOutputs() { resources->registerTextureOutput("LIGHTCULLING_OLIGHTGRID", Gfx::PTexture2D(oLightGrid)); resources->registerTextureOutput("LIGHTCULLING_TLIGHTGRID", Gfx::PTexture2D(tLightGrid)); - timestamps = graphics->createTimestampQuery(2, "LightCullTS"); - resources->registerTimestampQueryOutput("LIGHTCULL_TS", timestamps); query = graphics->createPipelineStatisticsQuery("LightCullPipelineStatistics"); resources->registerQueryOutput("LIGHTCULL_QUERY", query); } void LightCullingPass::createRenderPass() { + timestamps = resources->requestTimestampQuery("TIMESTAMPS"); depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH").getTexture(); } diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.h b/src/Engine/Graphics/RenderPass/LightCullingPass.h index 0277e64..191c38f 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.h +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.h @@ -64,7 +64,7 @@ class LightCullingPass : public RenderPass { Gfx::PComputePipeline cullingPipeline; Gfx::PComputePipeline cullingEnabledPipeline; Gfx::OPipelineStatisticsQuery query; - Gfx::OTimestampQuery timestamps; + Gfx::PTimestampQuery timestamps; }; DEFINE_REF(LightCullingPass) } // namespace Seele diff --git a/src/Engine/Graphics/RenderPass/VisibilityPass.cpp b/src/Engine/Graphics/RenderPass/VisibilityPass.cpp index e73481e..278f907 100644 --- a/src/Engine/Graphics/RenderPass/VisibilityPass.cpp +++ b/src/Engine/Graphics/RenderPass/VisibilityPass.cpp @@ -26,7 +26,6 @@ void VisibilityPass::render() { visibilitySet->writeChanges(); query->beginQuery(); - timestamps->begin(); timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "VisibilityBegin"); Gfx::OComputeCommand command = graphics->createComputeCommand("VisibilityCommand"); command->bindPipeline(visibilityPipeline); @@ -36,7 +35,6 @@ void VisibilityPass::render() { commands.add(std::move(command)); graphics->executeCommands(std::move(commands)); timestamps->write(Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, "VisibilityEnd"); - timestamps->end(); query->endQuery(); cullingBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, @@ -88,11 +86,11 @@ void VisibilityPass::publishOutputs() { }); resources->registerBufferOutput("CULLINGBUFFER", cullingBuffer); - timestamps = graphics->createTimestampQuery(2, "VisibilityTS"); - resources->registerTimestampQueryOutput("VISIBILITY_TS", timestamps); - query = graphics->createPipelineStatisticsQuery("VisibilityPipelineStatistics"); resources->registerQueryOutput("VISIBILITY_QUERY", query); } -void VisibilityPass::createRenderPass() { visibilityAttachment = resources->requestRenderTarget("VISIBILITY"); } +void VisibilityPass::createRenderPass() { + visibilityAttachment = resources->requestRenderTarget("VISIBILITY"); + timestamps = resources->requestTimestampQuery("TIMESTAMPS"); +} diff --git a/src/Engine/Graphics/RenderPass/VisibilityPass.h b/src/Engine/Graphics/RenderPass/VisibilityPass.h index 43f0eff..75c681e 100644 --- a/src/Engine/Graphics/RenderPass/VisibilityPass.h +++ b/src/Engine/Graphics/RenderPass/VisibilityPass.h @@ -24,7 +24,7 @@ class VisibilityPass : public RenderPass { Gfx::OComputeShader visibilityShader; Gfx::PComputePipeline visibilityPipeline; Gfx::OPipelineStatisticsQuery query; - Gfx::OTimestampQuery timestamps; + Gfx::PTimestampQuery timestamps; // Holds culling information for every meshlet for each instance Gfx::OShaderBuffer cullingBuffer; diff --git a/src/Engine/Graphics/VertexData.cpp b/src/Engine/Graphics/VertexData.cpp index 79a2ba9..bca4524 100644 --- a/src/Engine/Graphics/VertexData.cpp +++ b/src/Engine/Graphics/VertexData.cpp @@ -11,7 +11,7 @@ using namespace Seele; -constexpr static uint64 NUM_DEFAULT_ELEMENTS = 24;//17962284; +constexpr static uint64 NUM_DEFAULT_ELEMENTS = 17962284; Map VertexData::instanceIdMap; uint64 VertexData::instanceCount = 0; uint64 VertexData::meshletCount = 0; diff --git a/src/Engine/Graphics/Vulkan/Graphics.cpp b/src/Engine/Graphics/Vulkan/Graphics.cpp index e70f982..d4550e5 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.cpp +++ b/src/Engine/Graphics/Vulkan/Graphics.cpp @@ -288,7 +288,7 @@ Gfx::OPipelineStatisticsQuery Graphics::createPipelineStatisticsQuery(const std: } Gfx::OTimestampQuery Graphics::createTimestampQuery(uint64 numTimestamps, const std::string& name) { - return new TimestampQuery(this, name, numTimestamps); + return new TimestampQuery(this, name); } void Graphics::resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) { @@ -635,9 +635,9 @@ Array Graphics::getRequiredExtensions() { for (unsigned int i = 0; i < glfwExtensionCount; i++) { extensions.add(glfwExtensions[i]); } -#if ENABLE_VALIDATION +#ifdef ENABLE_VALIDATION extensions.add(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); -#endif // ENABLE_VALIDATION +#endif return extensions; } diff --git a/src/Engine/Graphics/Vulkan/Query.cpp b/src/Engine/Graphics/Vulkan/Query.cpp index 0e2f710..e453b03 100644 --- a/src/Engine/Graphics/Vulkan/Query.cpp +++ b/src/Engine/Graphics/Vulkan/Query.cpp @@ -12,13 +12,65 @@ using namespace Seele::Vulkan; QueryPool::QueryPool(PGraphics graphics, VkQueryType type, VkQueryPipelineStatisticFlags flags, uint32 resultsStride, uint32 numBuffered, const std::string& name) - : graphics(graphics), flags(flags), numQueries(numBuffered), resultsStride(resultsStride) { + : graphics(graphics), type(type), name(name), flags(flags), numQueries(numBuffered), resultsStride(resultsStride) { + createPool(); +} + +QueryPool::~QueryPool() { + for (auto handle : pools) { + vkDestroyQueryPool(graphics->getDevice(), handle, nullptr); + } +} + +void QueryPool::begin() { + PCommand cmd = graphics->getGraphicsCommands()->getCommands(); + vkCmdResetQueryPool(cmd->getHandle(), pools.back(), head, 1); + vkCmdBeginQuery(cmd->getHandle(), pools.back(), head, 0); + cmd->setPipelineStatisticsFlags(flags); +} + +void QueryPool::end() { + PCommand cmd = graphics->getGraphicsCommands()->getCommands(); + vkCmdEndQuery(cmd->getHandle(), pools.back(), head); + std::unique_lock l(queryMutex); + head++; + if (head == numQueries) { + createPool(); + head = 0; + } + numAvailable++; + queryCV.notify_all(); +} + +void QueryPool::getQueryResults(Array& results) { + { + std::unique_lock l(queryMutex); + while (numAvailable == 0) { + queryCV.wait(l); + } + } + results.resize(resultsStride / sizeof(uint64)); + vkGetQueryPoolResults(graphics->getDevice(), pools.front(), tail, 1, resultsStride, results.data(), resultsStride, + VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT); + std::unique_lock l(queryMutex); + tail++; + if (tail == numQueries) + { + vkDestroyQueryPool(graphics->getDevice(), pools.front(), nullptr); + pools.popFront(); + tail = 0; + } + numAvailable--; +} + +void QueryPool::createPool() { + VkQueryPool handle; VkQueryPoolCreateInfo info = { .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, .pNext = nullptr, .flags = 0, .queryType = type, - .queryCount = numBuffered, + .queryCount = numQueries, .pipelineStatistics = flags, }; VK_CHECK(vkCreateQueryPool(graphics->getDevice(), &info, nullptr, &handle)); @@ -30,36 +82,12 @@ QueryPool::QueryPool(PGraphics graphics, VkQueryType type, VkQueryPipelineStatis .pObjectName = name.c_str(), }; vkSetDebugUtilsObjectNameEXT(graphics->getDevice(), &nameInfo); - PCommand cmd = graphics->getGraphicsCommands()->getCommands(); - vkCmdResetQueryPool(cmd->getHandle(), handle, head, numQueries); -} - -QueryPool::~QueryPool() { vkDestroyQueryPool(graphics->getDevice(), handle, nullptr); } - -void QueryPool::begin() { - PCommand cmd = graphics->getGraphicsCommands()->getCommands(); - vkCmdResetQueryPool(cmd->getHandle(), handle, head, 1); - vkCmdBeginQuery(cmd->getHandle(), handle, head, 0); - cmd->setPipelineStatisticsFlags(flags); -} - -void QueryPool::end() { - PCommand cmd = graphics->getGraphicsCommands()->getCommands(); - vkCmdEndQuery(cmd->getHandle(), handle, head); - std::unique_lock l(queryMutex); - head = (head + 1) % numQueries; - queryCV.notify_all(); -} - -void QueryPool::getQueryResults(Array& results) { - while (tail == head) { - std::unique_lock l(queryMutex); - queryCV.wait(l); + pools.add(handle); + if (pools.size() > 5) + { + vkDestroyQueryPool(graphics->getDevice(), pools.front(), nullptr); + pools.popFront(); } - results.resize(resultsStride / sizeof(uint64)); - vkGetQueryPoolResults(graphics->getDevice(), handle, tail, 1, resultsStride, results.data(), resultsStride, - VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT); - tail = (tail + 1) % numQueries; } OcclusionQuery::OcclusionQuery(PGraphics graphics, const std::string& name) @@ -111,48 +139,52 @@ Gfx::PipelineStatisticsResult PipelineStatisticsQuery::getResults() { }; } -TimestampQuery::TimestampQuery(PGraphics graphics, const std::string& name, uint32 numTimestamps) - : QueryPool(graphics, VK_QUERY_TYPE_TIMESTAMP, 0, sizeof(uint64), 512 * numTimestamps, name), numTimestamps(numTimestamps) { - pendingTimestamps.resize(numQueries); +TimestampQuery::TimestampQuery(PGraphics graphics, const std::string& name) + : QueryPool(graphics, VK_QUERY_TYPE_TIMESTAMP, 0, sizeof(uint64), 512, name) { } TimestampQuery::~TimestampQuery() {} -void TimestampQuery::begin() { - currentTimestamp = 0; -} - void TimestampQuery::write(Gfx::SePipelineStageFlagBits stage, const std::string& name) { PCommand cmd = graphics->getGraphicsCommands()->getCommands(); - uint32 queryIndex = (head * numTimestamps) + currentTimestamp; - vkCmdResetQueryPool(cmd->getHandle(), handle, queryIndex, 1); - vkCmdWriteTimestamp(cmd->getHandle(), cast(stage), handle, queryIndex); - pendingTimestamps[queryIndex] = name; - currentTimestamp++; -} - -void TimestampQuery::end() { - std::unique_lock l(queryMutex); - head = (head + 1) % 512; - queryCV.notify_all(); -} - -Array TimestampQuery::getResults() { - while (head == tail) { + vkCmdResetQueryPool(cmd->getHandle(), pools.back(), head, 1); + vkCmdWriteTimestamp(cmd->getHandle(), cast(stage), pools.back(), head); + pendingTimestamps.add(name); + { std::unique_lock l(queryMutex); - queryCV.wait(l); + head++; + if (head == numQueries) { + createPool(); + head = 0; + } + numAvailable++; } - Array results(numTimestamps); - uint32 firstQuery = (tail * numTimestamps); - vkGetQueryPoolResults(graphics->getDevice(), handle, firstQuery, numTimestamps, numTimestamps * sizeof(uint64), results.data(), - resultsStride, VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT); - tail = (tail + 1) % 512; - Array res; - for (uint64 i = 0; i < numTimestamps; ++i) { - res.add(Gfx::Timestamp{ - .name = pendingTimestamps[firstQuery + i], - .time = uint64((results[i] + wrapping) * graphics->getTimestampPeriod()), - }); +} + +Gfx::Timestamp TimestampQuery::getResult() { + { + std::unique_lock l(queryMutex); + while (numAvailable == 0) { + queryCV.wait(l); + } + } + uint64 result; + vkGetQueryPoolResults(graphics->getDevice(), pools.front(), tail, 1, sizeof(uint64), &result, resultsStride, + VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT); + { + std::unique_lock l(queryMutex); + tail++; + if (tail == numQueries) { + vkDestroyQueryPool(graphics->getDevice(), pools.front(), nullptr); + pools.popFront(); + tail = 0; + } + numAvailable--; + Gfx::Timestamp res = Gfx::Timestamp{ + .name = pendingTimestamps.front(), + .time = result, + }; + pendingTimestamps.popFront(); + return res; } - return res; } \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/Query.h b/src/Engine/Graphics/Vulkan/Query.h index dd65609..28158b1 100644 --- a/src/Engine/Graphics/Vulkan/Query.h +++ b/src/Engine/Graphics/Vulkan/Query.h @@ -14,14 +14,18 @@ class QueryPool { void end(); // stalls for the currently first pending query, dont call in render thread void getQueryResults(Array& results); + void createPool(); protected: PGraphics graphics; - VkQueryPool handle; + List pools; + VkQueryType type; + std::string name; VkQueryPipelineStatisticFlags flags; // ring buffer uint64 head = 0; uint64 tail = 0; + uint64 numAvailable; uint32 numQueries; uint32 resultsStride; std::mutex queryMutex; @@ -48,19 +52,15 @@ DEFINE_REF(PipelineStatisticsQuery) class TimestampQuery : public Gfx::TimestampQuery, public QueryPool { public: - TimestampQuery(PGraphics graphics, const std::string& name, uint32 numTimestamps); + TimestampQuery(PGraphics graphics, const std::string& name); virtual ~TimestampQuery(); - virtual void begin() override; virtual void write(Gfx::SePipelineStageFlagBits stage, const std::string& name = "") override; - virtual void end() override; - virtual Array getResults() override; + virtual Gfx::Timestamp getResult() override; private: uint64 wrapping = 0; uint64 lastMeasure = 0; - uint32 numTimestamps = 0; - uint32 currentTimestamp = 0; - Array pendingTimestamps; + List pendingTimestamps; }; DEFINE_REF(TimestampQuery) } // namespace Vulkan