From 0fd331b3b5b150cea52ca52e123a295f7dabde00 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Sat, 15 Jun 2024 21:47:20 +0200 Subject: [PATCH] Adding Pipeline statistics queries --- res/shaders/Skybox.slang | 6 +- src/Editor/Asset/TextureLoader.cpp | 3 + src/Editor/main.cpp | 4 + src/Engine/Graphics/Graphics.h | 2 + src/Engine/Graphics/Pipeline.h | 4 + src/Engine/Graphics/Query.cpp | 6 + src/Engine/Graphics/Query.h | 28 ++++- src/Engine/Graphics/RenderPass/BasePass.cpp | 5 + src/Engine/Graphics/RenderPass/BasePass.h | 2 + .../Graphics/RenderPass/CachedDepthPass.cpp | 4 + .../Graphics/RenderPass/CachedDepthPass.h | 1 + .../Graphics/RenderPass/DepthCullingPass.cpp | 5 +- .../Graphics/RenderPass/DepthCullingPass.h | 1 + .../Graphics/RenderPass/LightCullingPass.cpp | 9 +- .../Graphics/RenderPass/LightCullingPass.h | 2 + src/Engine/Graphics/RenderPass/RenderGraph.h | 5 +- .../RenderPass/RenderGraphResources.cpp | 8 ++ .../RenderPass/RenderGraphResources.h | 4 + .../Graphics/RenderPass/SkyboxRenderPass.cpp | 85 +++++++++---- .../Graphics/RenderPass/VisibilityPass.cpp | 5 + .../Graphics/RenderPass/VisibilityPass.h | 2 + src/Engine/Graphics/Vulkan/Buffer.cpp | 2 +- src/Engine/Graphics/Vulkan/Command.cpp | 26 ++-- src/Engine/Graphics/Vulkan/Command.h | 6 +- src/Engine/Graphics/Vulkan/Graphics.cpp | 27 ++--- src/Engine/Graphics/Vulkan/Graphics.h | 1 + src/Engine/Graphics/Vulkan/Query.cpp | 112 +++++++++++++++--- src/Engine/Graphics/Vulkan/Query.h | 40 +++++-- src/Engine/Window/GameView.cpp | 33 +++++- src/Engine/Window/GameView.h | 1 + 30 files changed, 344 insertions(+), 95 deletions(-) diff --git a/res/shaders/Skybox.slang b/res/shaders/Skybox.slang index b191be7..c7c7d42 100644 --- a/res/shaders/Skybox.slang +++ b/res/shaders/Skybox.slang @@ -89,7 +89,7 @@ struct TextureData SamplerState sampler; }; layout(set=2) -ParameterBlock pTextures; +ParameterBlock pSkyboxTextures; static const float lowerLimit = 0.0; static const float upperLimit = 0.1; @@ -97,8 +97,8 @@ static const float upperLimit = 0.1; float4 fragmentMain( VertexShaderOutput output) : SV_Target { - float4 texture1 = pTextures.cubeMap.Sample(pTextures.sampler, output.texCoords); - float4 texture2 = pTextures.cubeMap2.Sample(pTextures.sampler, output.texCoords); + float4 texture1 = pSkyboxTextures.cubeMap.Sample(pSkyboxTextures.sampler, output.texCoords); + float4 texture2 = pSkyboxTextures.cubeMap2.Sample(pSkyboxTextures.sampler, output.texCoords); float4 finalColor = lerp(texture1, texture2, pSkyboxData.fogBlend.w); float factor = (output.texCoords.y - lowerLimit) / (upperLimit - lowerLimit); diff --git a/src/Editor/Asset/TextureLoader.cpp b/src/Editor/Asset/TextureLoader.cpp index 76e42c5..6ceca0c 100644 --- a/src/Editor/Asset/TextureLoader.cpp +++ b/src/Editor/Asset/TextureLoader.cpp @@ -64,6 +64,9 @@ void TextureLoader::import(TextureImportArgs args, PTextureAsset textureAsset) { ss << "toktx --encode etc1s "; if (args.type == TextureImportType::TEXTURE_NORMAL) { // ss << "--normal_mode "; + } + if (args.type == TextureImportType::TEXTURE_CUBEMAP) { + } ss << ktxFile << " " << args.filePath; system(ss.str().c_str()); diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index 40c998b..c52cfc9 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -59,6 +59,10 @@ int main() { AssetImporter::importMesh(MeshImportArgs{ .filePath = sourcePath / "import/models/cube.fbx", }); + AssetImporter::importTexture(TextureImportArgs{ + .filePath = sourcePath / "import/textures/skyboxsun5deg_tn.jpg", + .type = TextureImportType::TEXTURE_CUBEMAP, + }); // AssetImporter::importMesh(MeshImportArgs{ // .filePath = sourcePath / "import/models/greek-temple/source/greek-temple.fbx", // .importPath = "temple" diff --git a/src/Engine/Graphics/Graphics.h b/src/Engine/Graphics/Graphics.h index d0e5d54..605651e 100644 --- a/src/Engine/Graphics/Graphics.h +++ b/src/Engine/Graphics/Graphics.h @@ -2,6 +2,7 @@ #include "Containers/Array.h" #include "Initializer.h" #include "MinimalEngine.h" +#include "Query.h" #include "RenderTarget.h" #include "Resources.h" @@ -81,6 +82,7 @@ class Graphics { virtual OVertexInput createVertexInput(VertexInputStateCreateInfo createInfo) = 0; virtual Gfx::OOcclusionQuery createOcclusionQuery() = 0; + virtual Gfx::OPipelineStatisticsQuery createPipelineStatisticsQuery() = 0; virtual void resolveTexture(PTexture source, PTexture destination) = 0; virtual void copyTexture(PTexture src, PTexture dst) = 0; diff --git a/src/Engine/Graphics/Pipeline.h b/src/Engine/Graphics/Pipeline.h index cb21583..eae5576 100644 --- a/src/Engine/Graphics/Pipeline.h +++ b/src/Engine/Graphics/Pipeline.h @@ -35,5 +35,9 @@ class ComputePipeline { PPipelineLayout layout; }; DEFINE_REF(ComputePipeline) +class PipelineLibrary { + +}; +DEFINE_REF(PipelineLibrary) } // namespace Gfx } // namespace Seele diff --git a/src/Engine/Graphics/Query.cpp b/src/Engine/Graphics/Query.cpp index bed9887..a11533d 100644 --- a/src/Engine/Graphics/Query.cpp +++ b/src/Engine/Graphics/Query.cpp @@ -7,4 +7,10 @@ OcclusionQuery::OcclusionQuery() {} OcclusionQuery::~OcclusionQuery() +{} + +PipelineStatisticsQuery::PipelineStatisticsQuery() +{} + +PipelineStatisticsQuery::~PipelineStatisticsQuery() {} \ No newline at end of file diff --git a/src/Engine/Graphics/Query.h b/src/Engine/Graphics/Query.h index 4b1d107..94ead3f 100644 --- a/src/Engine/Graphics/Query.h +++ b/src/Engine/Graphics/Query.h @@ -3,17 +3,37 @@ namespace Seele { namespace Gfx { +struct OcclusionResult { + uint64 numFragments; +}; class OcclusionQuery { public: OcclusionQuery(); virtual ~OcclusionQuery(); virtual void beginQuery() = 0; virtual void endQuery() = 0; - virtual void resetQuery() = 0; - virtual uint64 getResults() = 0; - - private: + virtual OcclusionResult getResults() = 0; }; DEFINE_REF(OcclusionQuery) +struct PipelineStatisticsResult { + uint64 inputAssemblyVertices; + uint64 inputAssemblyPrimitives; + uint64 vertexShaderInvocations; + uint64 clippingInvocations; + uint64 clippingPrimitives; + uint64 fragmentShaderInvocations; + uint64 computeShaderInvocations; + uint64 taskShaderInvocations; + uint64 meshShaderInvocations; +}; +class PipelineStatisticsQuery { + public: + PipelineStatisticsQuery(); + virtual ~PipelineStatisticsQuery(); + virtual void beginQuery() = 0; + virtual void endQuery() = 0; + virtual PipelineStatisticsResult getResults() = 0; +}; +DEFINE_REF(PipelineStatisticsQuery) } // namespace Gfx } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index a30d3d8..ae823e9 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -87,6 +87,7 @@ void BasePass::render() { opaqueCulling->writeChanges(); transparentCulling->writeChanges(); + query->beginQuery(); graphics->beginRenderPass(renderPass); Array commands; @@ -184,6 +185,7 @@ void BasePass::render() { graphics->executeCommands(std::move(commands)); graphics->endRenderPass(); + query->endQuery(); } void BasePass::endFrame() {} @@ -205,6 +207,9 @@ void BasePass::publishOutputs() { Gfx::RenderTargetAttachment(basePassDepth, 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("BASEPASS_DEPTH", depthAttachment); + + query = graphics->createPipelineStatisticsQuery(); + resources->registerQueryOutput("BASEPASS_QUERY", query); } void BasePass::createRenderPass() { diff --git a/src/Engine/Graphics/RenderPass/BasePass.h b/src/Engine/Graphics/RenderPass/BasePass.h index 40d8a7a..69ca591 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.h +++ b/src/Engine/Graphics/RenderPass/BasePass.h @@ -35,6 +35,8 @@ class BasePass : public RenderPass { Gfx::OPipelineLayout basePassLayout; Gfx::ODescriptorLayout lightCullingLayout; + Gfx::OPipelineStatisticsQuery query; + Gfx::PShaderBuffer cullingBuffer; }; DEFINE_REF(BasePass) diff --git a/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp b/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp index f16cbf6..7fea6cb 100644 --- a/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp +++ b/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp @@ -46,6 +46,7 @@ CachedDepthPass::~CachedDepthPass() {} void CachedDepthPass::beginFrame(const Component::Camera& cam) { RenderPass::beginFrame(cam); } void CachedDepthPass::render() { + query->beginQuery(); graphics->beginRenderPass(renderPass); Array commands; @@ -141,6 +142,7 @@ void CachedDepthPass::render() { graphics->executeCommands(std::move(commands)); graphics->endRenderPass(); + query->endQuery(); } void CachedDepthPass::endFrame() {} @@ -171,6 +173,8 @@ void CachedDepthPass::publishOutputs() { 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); + query = graphics->createPipelineStatisticsQuery(); + resources->registerQueryOutput("CACHED_QUERY", query); } void CachedDepthPass::createRenderPass() { diff --git a/src/Engine/Graphics/RenderPass/CachedDepthPass.h b/src/Engine/Graphics/RenderPass/CachedDepthPass.h index 4290819..da19a64 100644 --- a/src/Engine/Graphics/RenderPass/CachedDepthPass.h +++ b/src/Engine/Graphics/RenderPass/CachedDepthPass.h @@ -21,6 +21,7 @@ class CachedDepthPass : public RenderPass { Gfx::OTexture2D depthBuffer; Gfx::OTexture2D visibilityBuffer; Gfx::OPipelineLayout depthPrepassLayout; + Gfx::OPipelineStatisticsQuery query; Gfx::PShaderBuffer cullingBuffer; }; diff --git a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp index 74752a9..478f4df 100644 --- a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp @@ -75,7 +75,7 @@ void DepthCullingPass::render() { Gfx::PDescriptorSet set = depthTextureLayout->allocateDescriptorSet(); set->updateTexture(0, Gfx::PTexture2D(depthMipTexture)); set->writeChanges(); - + query->beginQuery(); graphics->beginRenderPass(renderPass); if (useDepthCulling) { @@ -173,6 +173,7 @@ void DepthCullingPass::render() { graphics->executeCommands(std::move(commands)); } graphics->endRenderPass(); + query->endQuery(); // 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, @@ -192,6 +193,8 @@ void DepthCullingPass::publishOutputs() { TextureCreateInfo depthMipInfo = { .format = Gfx::SE_FORMAT_D32_SFLOAT, .width = width, .height = height, .mipLevels = mipLevels, .name = "DepthMipTexture"}; depthMipTexture = graphics->createTexture2D(depthMipInfo); + query = graphics->createPipelineStatisticsQuery(); + resources->registerQueryOutput("DEPTH_QUERY", query); } void DepthCullingPass::createRenderPass() { diff --git a/src/Engine/Graphics/RenderPass/DepthCullingPass.h b/src/Engine/Graphics/RenderPass/DepthCullingPass.h index 2470b18..aca64d7 100644 --- a/src/Engine/Graphics/RenderPass/DepthCullingPass.h +++ b/src/Engine/Graphics/RenderPass/DepthCullingPass.h @@ -22,6 +22,7 @@ class DepthCullingPass : public RenderPass { Gfx::RenderTargetAttachment visibilityAttachment; Gfx::ODescriptorLayout depthTextureLayout; Gfx::OPipelineLayout depthPrepassLayout; + Gfx::OPipelineStatisticsQuery query; Gfx::PShaderBuffer cullingBuffer; }; diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp index 4a751b1..0581030 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp @@ -40,6 +40,7 @@ void LightCullingPass::beginFrame(const Component::Camera& cam) { } void LightCullingPass::render() { + query->beginQuery(); depthAttachment->transferOwnership(Gfx::QueueType::COMPUTE); cullingDescriptorSet->updateTexture(0, depthAttachment); cullingDescriptorSet->updateBuffer(1, oLightIndexCounter); @@ -61,7 +62,7 @@ void LightCullingPass::render() { commands.add(std::move(computeCommand)); // std::cout << "Execute" << std::endl; graphics->executeCommands(std::move(commands)); - + 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); tLightIndexList->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, @@ -212,7 +213,11 @@ void LightCullingPass::publishOutputs() { resources->registerTextureOutput("LIGHTCULLING_TLIGHTGRID", Gfx::PTexture2D(tLightGrid)); } -void LightCullingPass::createRenderPass() { depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH").getTexture(); } +void LightCullingPass::createRenderPass() { + depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH").getTexture(); + query = graphics->createPipelineStatisticsQuery(); + resources->registerQueryOutput("LIGHTCULL_QUERY", query); +} void LightCullingPass::setupFrustums() { uint32_t viewportWidth = viewport->getWidth(); diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.h b/src/Engine/Graphics/RenderPass/LightCullingPass.h index 9341de2..ce5afaf 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.h +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.h @@ -1,4 +1,5 @@ #pragma once +#include "Graphics/Query.h" #include "Graphics/Shader.h" #include "RenderPass.h" #include "Scene/Scene.h" @@ -63,6 +64,7 @@ class LightCullingPass : public RenderPass { Gfx::OComputeShader cullingEnabledShader; Gfx::PComputePipeline cullingPipeline; Gfx::PComputePipeline cullingEnabledPipeline; + Gfx::OPipelineStatisticsQuery query; }; DEFINE_REF(LightCullingPass) } // namespace Seele diff --git a/src/Engine/Graphics/RenderPass/RenderGraph.h b/src/Engine/Graphics/RenderPass/RenderGraph.h index 62efcbc..9c66e4f 100644 --- a/src/Engine/Graphics/RenderPass/RenderGraph.h +++ b/src/Engine/Graphics/RenderPass/RenderGraph.h @@ -1,4 +1,5 @@ #pragma once +#include "RenderGraphResources.h" #include "RenderPass.h" namespace Seele { @@ -33,7 +34,9 @@ class RenderGraph { pass->endFrame(); } } - + PRenderGraphResources getResources() { + return res; + } private: PRenderGraphResources res; List passes; diff --git a/src/Engine/Graphics/RenderPass/RenderGraphResources.cpp b/src/Engine/Graphics/RenderPass/RenderGraphResources.cpp index 794bca6..3a04862 100644 --- a/src/Engine/Graphics/RenderPass/RenderGraphResources.cpp +++ b/src/Engine/Graphics/RenderPass/RenderGraphResources.cpp @@ -1,5 +1,7 @@ #include "RenderGraphResources.h" +#include "Graphics/Query.h" #include +#include using namespace Seele; @@ -17,6 +19,8 @@ Gfx::PShaderBuffer RenderGraphResources::requestBuffer(const std::string& output Gfx::PUniformBuffer RenderGraphResources::requestUniform(const std::string& outputName) { return registeredUniforms.at(outputName); } +Gfx::PPipelineStatisticsQuery RenderGraphResources::requestQuery(const std::string& outputName) { return registeredQueries.at(outputName); } + void RenderGraphResources::registerRenderPassOutput(const std::string& outputName, Gfx::RenderTargetAttachment attachment) { registeredAttachments[outputName] = attachment; } @@ -30,4 +34,8 @@ void RenderGraphResources::registerBufferOutput(const std::string& outputName, G } void RenderGraphResources::registerUniformOutput(const std::string& outputName, Gfx::PUniformBuffer buffer) { registeredUniforms[outputName] = buffer; +} + +void RenderGraphResources::registerQueryOutput(const std::string& outputName, Gfx::PPipelineStatisticsQuery query) { + registeredQueries[outputName] = query; } \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/RenderGraphResources.h b/src/Engine/Graphics/RenderPass/RenderGraphResources.h index 86666c4..fbfb391 100644 --- a/src/Engine/Graphics/RenderPass/RenderGraphResources.h +++ b/src/Engine/Graphics/RenderPass/RenderGraphResources.h @@ -1,5 +1,6 @@ #pragma once #include "Graphics/Buffer.h" +#include "Graphics/Query.h" #include "Graphics/RenderTarget.h" #include "Graphics/Texture.h" #include "MinimalEngine.h" @@ -16,16 +17,19 @@ class RenderGraphResources { Gfx::PTexture requestTexture(const std::string& outputName); Gfx::PShaderBuffer requestBuffer(const std::string& outputName); Gfx::PUniformBuffer requestUniform(const std::string& outputName); + Gfx::PPipelineStatisticsQuery requestQuery(const std::string& outputName); void registerRenderPassOutput(const std::string& outputName, Gfx::RenderTargetAttachment attachment); void registerTextureOutput(const std::string& outputName, Gfx::PTexture buffer); void registerBufferOutput(const std::string& outputName, Gfx::PShaderBuffer buffer); void registerUniformOutput(const std::string& outputName, Gfx::PUniformBuffer buffer); + void registerQueryOutput(const std::string& outputName, Gfx::PPipelineStatisticsQuery query); protected: Map registeredAttachments; Map registeredTextures; Map registeredBuffers; Map registeredUniforms; + Map registeredQueries; }; DEFINE_REF(RenderGraphResources) } // namespace Seele diff --git a/src/Engine/Graphics/RenderPass/SkyboxRenderPass.cpp b/src/Engine/Graphics/RenderPass/SkyboxRenderPass.cpp index b023352..24be324 100644 --- a/src/Engine/Graphics/RenderPass/SkyboxRenderPass.cpp +++ b/src/Engine/Graphics/RenderPass/SkyboxRenderPass.cpp @@ -3,13 +3,12 @@ #include "Graphics/Command.h" #include "Graphics/Graphics.h" - using namespace Seele; SkyboxRenderPass::SkyboxRenderPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) { skybox = Seele::Component::Skybox{ - //.day = AssetRegistry::findTexture("FS000_Day_01")->getTexture().cast(), - //.night = AssetRegistry::findTexture("FS000_Night_01")->getTexture().cast(), + .day = AssetRegistry::findTexture("", "skyboxsun5deg_tn")->getTexture().cast(), + .night = AssetRegistry::findTexture("", "skyboxsun5deg_tn")->getTexture().cast(), .fogColor = Vector(0.1, 0.1, 0.8), .blendFactor = 0, }; @@ -86,14 +85,41 @@ void SkyboxRenderPass::publishOutputs() { void SkyboxRenderPass::createRenderPass() { colorAttachment = resources->requestRenderTarget("BASEPASS_COLOR"); - // colorAttachment->loadOp = Gfx::SE_ATTACHMENT_LOAD_OP_LOAD; - depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH"); - // depthAttachment->loadOp = Gfx::SE_ATTACHMENT_LOAD_OP_LOAD; - // Gfx::ORenderTargetLayout layout = new Gfx::RenderTargetLayout{ - // .colorAttachments = { colorAttachment }, - // .depthAttachment = depthAttachment - // }; - // renderPass = graphics->createRenderPass(std::move(layout), viewport); + colorAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD); + colorAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + colorAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + depthAttachment = resources->requestRenderTarget("BASEPASS_DEPTH"); + depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD); + depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ + .colorAttachments = {colorAttachment}, + .depthAttachment = depthAttachment, + }; + Array dependency = { + { + .srcSubpass = ~0U, + .dstSubpass = 0, + .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | 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_COLOR_ATTACHMENT_OUTPUT_BIT | Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + }, + }; + renderPass = graphics->createRenderPass(std::move(layout), dependency, viewport); skyboxData.transformMatrix = Matrix4(1); skyboxData.fogColor = skybox.fogColor; @@ -108,10 +134,16 @@ void SkyboxRenderPass::createRenderPass() { .dynamic = true, }); + pipelineLayout = graphics->createPipelineLayout("SkyboxLayout"); + pipelineLayout->addDescriptorLayout(viewParamsLayout); + pipelineLayout->addDescriptorLayout(skyboxDataLayout); + pipelineLayout->addDescriptorLayout(textureLayout); + ShaderCreateInfo createInfo = { .name = "SkyboxVertex", .mainModule = "Skybox", .entryPoint = "vertexMain", + .rootSignature = pipelineLayout, }; vertexShader = graphics->createVertexShader(createInfo); @@ -119,19 +151,26 @@ void SkyboxRenderPass::createRenderPass() { createInfo.entryPoint = "fragmentMain"; fragmentShader = graphics->createFragmentShader(createInfo); - pipelineLayout = graphics->createPipelineLayout("SkyboxLayout"); - pipelineLayout->addDescriptorLayout(viewParamsLayout); - pipelineLayout->addDescriptorLayout(skyboxDataLayout); - pipelineLayout->addDescriptorLayout(textureLayout); pipelineLayout->create(); - Gfx::LegacyPipelineCreateInfo gfxInfo; - gfxInfo.vertexShader = vertexShader; - gfxInfo.fragmentShader = fragmentShader; - gfxInfo.rasterizationState.polygonMode = Gfx::SE_POLYGON_MODE_FILL; - gfxInfo.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - gfxInfo.pipelineLayout = pipelineLayout; - gfxInfo.renderPass = renderPass; - gfxInfo.multisampleState.samples = viewport->getSamples(); + Gfx::LegacyPipelineCreateInfo gfxInfo = { + .topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + .vertexShader = vertexShader, + .fragmentShader = fragmentShader, + .renderPass = renderPass, + .pipelineLayout = pipelineLayout, + .multisampleState = + { + .samples = viewport->getSamples(), + }, + .rasterizationState = + { + .polygonMode = Gfx::SE_POLYGON_MODE_FILL, + }, + .colorBlend = + { + .attachmentCount = 1, + }, + }; pipeline = graphics->createGraphicsPipeline(std::move(gfxInfo)); } diff --git a/src/Engine/Graphics/RenderPass/VisibilityPass.cpp b/src/Engine/Graphics/RenderPass/VisibilityPass.cpp index cb176c7..a777091 100644 --- a/src/Engine/Graphics/RenderPass/VisibilityPass.cpp +++ b/src/Engine/Graphics/RenderPass/VisibilityPass.cpp @@ -27,6 +27,7 @@ void VisibilityPass::render() { visibilitySet->updateBuffer(1, cullingBuffer); visibilitySet->writeChanges(); + query->beginQuery(); Gfx::OComputeCommand command = graphics->createComputeCommand("VisibilityCommand"); command->bindPipeline(visibilityPipeline); command->bindDescriptor({viewParamsSet, visibilitySet}); @@ -34,6 +35,7 @@ void VisibilityPass::render() { Array commands; commands.add(std::move(command)); graphics->executeCommands(std::move(commands)); + query->endQuery(); cullingBuffer->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 | Gfx::SE_PIPELINE_STAGE_MESH_SHADER_BIT_EXT); @@ -77,6 +79,9 @@ void VisibilityPass::publishOutputs() { cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{.dynamic = true, .name = "CullingBuffer"}); resources->registerBufferOutput("CULLINGBUFFER", cullingBuffer); + + query = graphics->createPipelineStatisticsQuery(); + resources->registerQueryOutput("VISIBILITY_QUERY", query); } void VisibilityPass::createRenderPass() { visibilityAttachment = resources->requestRenderTarget("VISIBILITY"); } diff --git a/src/Engine/Graphics/RenderPass/VisibilityPass.h b/src/Engine/Graphics/RenderPass/VisibilityPass.h index a2ffce7..abe23b2 100644 --- a/src/Engine/Graphics/RenderPass/VisibilityPass.h +++ b/src/Engine/Graphics/RenderPass/VisibilityPass.h @@ -1,4 +1,5 @@ #pragma once +#include "Graphics/Query.h" #include "RenderPass.h" namespace Seele { @@ -22,6 +23,7 @@ class VisibilityPass : public RenderPass { Gfx::OPipelineLayout visibilityLayout; Gfx::OComputeShader visibilityShader; Gfx::PComputePipeline visibilityPipeline; + Gfx::OPipelineStatisticsQuery query; // Holds culling information for every meshlet for each instance Gfx::OShaderBuffer cullingBuffer; diff --git a/src/Engine/Graphics/Vulkan/Buffer.cpp b/src/Engine/Graphics/Vulkan/Buffer.cpp index fef5fe0..2292252 100644 --- a/src/Engine/Graphics/Vulkan/Buffer.cpp +++ b/src/Engine/Graphics/Vulkan/Buffer.cpp @@ -160,7 +160,7 @@ void BufferAllocation::readContents(uint64 regionOffset, uint64 regionSize, void uint8* data; VK_CHECK(vmaMapMemory(graphics->getAllocator(), staging->allocation, (void**)&data)); - std::memcpy(buffer, data + regionOffset, regionSize); + std::memcpy(ptr, data + regionOffset, regionSize); VK_CHECK(vmaFlushAllocation(graphics->getAllocator(), staging->allocation, regionOffset, regionSize)); vmaUnmapMemory(graphics->getAllocator(), staging->allocation); graphics->getDestructionManager()->queueResourceForDestruction(std::move(staging)); diff --git a/src/Engine/Graphics/Vulkan/Command.cpp b/src/Engine/Graphics/Vulkan/Command.cpp index 0abab6b..407dfa9 100644 --- a/src/Engine/Graphics/Vulkan/Command.cpp +++ b/src/Engine/Graphics/Vulkan/Command.cpp @@ -11,7 +11,7 @@ using namespace Seele; using namespace Seele::Vulkan; -Command::Command(PGraphics graphics, PCommandPool pool) : graphics(graphics), pool(pool) { +Command::Command(PGraphics graphics, PCommandPool pool) : graphics(graphics), pool(pool), statisticsFlags(0) { VkCommandBufferAllocateInfo allocInfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, .pNext = nullptr, @@ -151,6 +151,9 @@ void Command::waitForCommand(uint32 timeout) { checkFence(); } +void Command::setPipelineStatisticsFlags(VkQueryPipelineStatisticFlags flags) +{ statisticsFlags = flags; } + void Command::bindResource(PCommandBoundResource resource) { resource->bind(); boundResources.add(resource); @@ -173,7 +176,7 @@ RenderCommand::RenderCommand(PGraphics graphics, VkCommandPool cmdPool) : graphi RenderCommand::~RenderCommand() { vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle); } -void RenderCommand::begin(PRenderPass renderPass, PFramebuffer framebuffer) { +void RenderCommand::begin(PRenderPass renderPass, PFramebuffer framebuffer, VkQueryPipelineStatisticFlags pipelineFlags) { threadId = std::this_thread::get_id(); ready = false; VkCommandBufferInheritanceInfo inheritanceInfo = { @@ -181,9 +184,9 @@ void RenderCommand::begin(PRenderPass renderPass, PFramebuffer framebuffer) { .renderPass = renderPass->getHandle(), .subpass = 0, .framebuffer = framebuffer->getHandle(), - .occlusionQueryEnable = 1, - .queryFlags = VK_QUERY_CONTROL_PRECISE_BIT, - .pipelineStatistics = 0, + .occlusionQueryEnable = 0, + .queryFlags = 0, + .pipelineStatistics = pipelineFlags, }; VkCommandBufferBeginInfo beginInfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, @@ -323,7 +326,7 @@ ComputeCommand::ComputeCommand(PGraphics graphics, VkCommandPool cmdPool) : grap ComputeCommand::~ComputeCommand() { vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle); } -void ComputeCommand::begin() { +void ComputeCommand::begin(VkQueryPipelineStatisticFlags pipelineFlags) { threadId = std::this_thread::get_id(); ready = false; VkCommandBufferInheritanceInfo inheritanceInfo = { @@ -333,7 +336,7 @@ void ComputeCommand::begin() { .framebuffer = VK_NULL_HANDLE, .occlusionQueryEnable = 0, .queryFlags = 0, - .pipelineStatistics = 0, + .pipelineStatistics = pipelineFlags, }; VkCommandBufferBeginInfo beginInfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, @@ -440,6 +443,7 @@ CommandPool::~CommandPool() { } PCommand CommandPool::getCommands() { return command; } + void CommandPool::cacheCommands(Array commands) { for (auto&& cmd : commands) { allocatedRenderCommands.add(std::move(cmd)); @@ -458,13 +462,13 @@ ORenderCommand CommandPool::createRenderCommand(const std::string& name) { ORenderCommand cmdBuffer = std::move(allocatedRenderCommands[i]); allocatedRenderCommands.removeAt(i, false); cmdBuffer->name = name; - cmdBuffer->begin(command->boundRenderPass, command->boundFramebuffer); + cmdBuffer->begin(command->boundRenderPass, command->boundFramebuffer, command->statisticsFlags); return cmdBuffer; } } ORenderCommand result = new RenderCommand(graphics, commandPool); result->name = name; - result->begin(command->boundRenderPass, command->boundFramebuffer); + result->begin(command->boundRenderPass, command->boundFramebuffer, command->statisticsFlags); return result; } @@ -474,13 +478,13 @@ OComputeCommand CommandPool::createComputeCommand(const std::string& name) { OComputeCommand cmdBuffer = std::move(allocatedComputeCommands[i]); allocatedComputeCommands.removeAt(i, false); cmdBuffer->name = name; - cmdBuffer->begin(); + cmdBuffer->begin(command->statisticsFlags); return cmdBuffer; } } OComputeCommand result = new ComputeCommand(graphics, commandPool); result->name = name; - result->begin(); + result->begin(command->statisticsFlags); return result; } diff --git a/src/Engine/Graphics/Vulkan/Command.h b/src/Engine/Graphics/Vulkan/Command.h index 33a9288..51265fe 100644 --- a/src/Engine/Graphics/Vulkan/Command.h +++ b/src/Engine/Graphics/Vulkan/Command.h @@ -29,6 +29,7 @@ class Command { void bindResource(PCommandBoundResource resource); void checkFence(); void waitForCommand(uint32 timeToWait = 1000000u); + void setPipelineStatisticsFlags(VkQueryPipelineStatisticFlags flags); PFence getFence(); PCommandPool getPool(); enum State { @@ -55,6 +56,7 @@ class Command { Array executingRenders; Array executingComputes; Array boundResources; + VkQueryPipelineStatisticFlags statisticsFlags; friend class RenderCommand; friend class CommandPool; friend class Queue; @@ -68,7 +70,7 @@ class RenderCommand : public Gfx::RenderCommand { RenderCommand(PGraphics graphics, VkCommandPool cmdPool); virtual ~RenderCommand(); constexpr VkCommandBuffer getHandle() { return handle; } - void begin(PRenderPass renderPass, PFramebuffer framebuffer); + void begin(PRenderPass renderPass, PFramebuffer framebuffer, VkQueryPipelineStatisticFlags pipelineFlags); void end(); void reset(); bool isReady(); @@ -103,7 +105,7 @@ class ComputeCommand : public Gfx::ComputeCommand { ComputeCommand(PGraphics graphics, VkCommandPool cmdPool); virtual ~ComputeCommand(); inline VkCommandBuffer getHandle() { return handle; } - void begin(); + void begin(VkQueryPipelineStatisticFlags pipelineFlags); void end(); void reset(); bool isReady(); diff --git a/src/Engine/Graphics/Vulkan/Graphics.cpp b/src/Engine/Graphics/Vulkan/Graphics.cpp index 3f211b4..232a65e 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.cpp +++ b/src/Engine/Graphics/Vulkan/Graphics.cpp @@ -233,6 +233,8 @@ Gfx::OVertexInput Graphics::createVertexInput(VertexInputStateCreateInfo createI Gfx::OOcclusionQuery Graphics::createOcclusionQuery() { return new OcclusionQuery(this); } +Gfx::OPipelineStatisticsQuery Graphics::createPipelineStatisticsQuery() { return new PipelineStatisticsQuery(this); } + void Graphics::resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) { PTextureBase sourceTex = source.cast(); PTextureBase destinationTex = destination.cast(); @@ -287,16 +289,8 @@ void Graphics::copyTexture(Gfx::PTexture source, Gfx::PTexture destination) { }, .srcOffsets = { - { - 0, - 0, - 0, - }, - { - (int32)src->getWidth(), - (int32)src->getHeight(), - (int32)src->getDepth(), - }, + {0, 0, 0}, + {(int32)src->getWidth(), (int32)src->getHeight(), (int32)src->getDepth()}, }, .dstSubresource = { @@ -307,16 +301,8 @@ void Graphics::copyTexture(Gfx::PTexture source, Gfx::PTexture destination) { }, .dstOffsets = { - { - 0, - 0, - 0, - }, - { - (int32)dst->getWidth(), - (int32)dst->getHeight(), - (int32)dst->getDepth(), - }, + {0, 0, 0}, + {(int32)dst->getWidth(), (int32)dst->getHeight(), (int32)dst->getDepth()}, }, }; PCommand command = getGraphicsCommands()->getCommands(); @@ -517,6 +503,7 @@ void Graphics::pickPhysicalDevice() { .fillModeNonSolid = true, .wideLines = true, .occlusionQueryPrecise = true, + .pipelineStatisticsQuery = true, .fragmentStoresAndAtomics = true, .shaderInt64 = true, .inheritedQueries = true, diff --git a/src/Engine/Graphics/Vulkan/Graphics.h b/src/Engine/Graphics/Vulkan/Graphics.h index b81a7ed..69002fd 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.h +++ b/src/Engine/Graphics/Vulkan/Graphics.h @@ -68,6 +68,7 @@ class Graphics : public Gfx::Graphics { virtual Gfx::OVertexInput createVertexInput(VertexInputStateCreateInfo createInfo) override; virtual Gfx::OOcclusionQuery createOcclusionQuery() override; + virtual Gfx::OPipelineStatisticsQuery createPipelineStatisticsQuery() override; virtual void resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) override; virtual void copyTexture(Gfx::PTexture src, Gfx::PTexture dst) override; diff --git a/src/Engine/Graphics/Vulkan/Query.cpp b/src/Engine/Graphics/Vulkan/Query.cpp index 82ae45b..29de33b 100644 --- a/src/Engine/Graphics/Vulkan/Query.cpp +++ b/src/Engine/Graphics/Vulkan/Query.cpp @@ -1,32 +1,116 @@ #include "Query.h" +#include "Buffer.h" #include "Command.h" +#include "Containers/Array.h" +#include "Enums.h" +#include "Graphics.h" +#include "Graphics/Query.h" +#include using namespace Seele; using namespace Seele::Vulkan; -OcclusionQuery::OcclusionQuery(PGraphics graphics) :graphics(graphics){ +QueryPool::QueryPool(PGraphics graphics, VkQueryType type, VkQueryPipelineStatisticFlags flags, uint32 resultsStride, uint32 numBuffered) + : graphics(graphics), flags(flags), numQueries(numBuffered), resultsStride(resultsStride) { VkQueryPoolCreateInfo info = { .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, .pNext = nullptr, .flags = 0, - .queryType = VK_QUERY_TYPE_OCCLUSION, - .queryCount = 1, - .pipelineStatistics = 0, + .queryType = type, + .queryCount = numBuffered, + .pipelineStatistics = flags, }; VK_CHECK(vkCreateQueryPool(graphics->getDevice(), &info, nullptr, &handle)); + //VkBufferCreateInfo bufferInfo = { + // .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + // .pNext = nullptr, + // .flags = 0, + // .size = (resultsStride + 1) * numQueries * sizeof(uint64), + // .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + //}; + //VmaAllocationCreateInfo allocInfo = { + // .flags = VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT, + // .usage = VMA_MEMORY_USAGE_AUTO, + // .requiredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + //}; + //resultsAlloc = new BufferAllocation(graphics, "QueryResults", bufferInfo, allocInfo, Gfx::QueueType::GRAPHICS); + //VK_CHECK(vmaMapMemory(graphics->getAllocator(), resultsAlloc->allocation, (void**) & resultsPtr)); } -OcclusionQuery::~OcclusionQuery() { vkDestroyQueryPool(graphics->getDevice(), handle, nullptr); } +QueryPool::~QueryPool() { vkDestroyQueryPool(graphics->getDevice(), handle, nullptr); } -void OcclusionQuery::beginQuery() { vkCmdBeginQuery(graphics->getGraphicsCommands()->getCommands()->getHandle(), handle, 0, VK_QUERY_CONTROL_PRECISE_BIT); } +void QueryPool::begin() { + vkCmdResetQueryPool(graphics->getGraphicsCommands()->getCommands()->getHandle(), handle, currentQuery, 1); + vkCmdBeginQuery(graphics->getGraphicsCommands()->getCommands()->getHandle(), handle, currentQuery, 0); + graphics->getGraphicsCommands()->getCommands()->setPipelineStatisticsFlags(flags); +} -void OcclusionQuery::endQuery() { vkCmdEndQuery(graphics->getGraphicsCommands()->getCommands()->getHandle(), handle, 0); } - -void OcclusionQuery::resetQuery() { vkCmdResetQueryPool(graphics->getGraphicsCommands()->getCommands()->getHandle(), handle, 0, 1); } - -uint64 OcclusionQuery::getResults() { +void QueryPool::end() { + vkCmdEndQuery(graphics->getGraphicsCommands()->getCommands()->getHandle(), handle, currentQuery); + //vkCmdCopyQueryPoolResults(graphics->getGraphicsCommands()->getCommands()->getHandle(), handle, currentQuery, 1, resultsAlloc->buffer, + // sizeof(uint64) * currentQuery, resultsStride + sizeof(uint64), + // VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT); graphics->getGraphicsCommands()->submitCommands(); - uint64 result; - vkGetQueryPoolResults(graphics->getDevice(), handle, 0, 1, sizeof(uint64), &result, sizeof(uint64), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT); - return result; + currentQuery = (currentQuery + 1) % numQueries; +} + +void QueryPool::getQueryResults(Array& results) { + //uint64 numInts = resultsStride / sizeof(uint64); + while (currentQuery == pendingQuery) + ; + results.resize(resultsStride/ sizeof(uint64)); + vkGetQueryPoolResults(graphics->getDevice(), handle, pendingQuery, 1, resultsStride, results.data(), resultsStride, + VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT); + //uint64* currentPtr = resultsPtr + (pendingQuery * (numInts + 1)); + //std::cout << pendingQuery << *(currentPtr + numInts) << std::endl; + //std::memcpy(results.data(), currentPtr, resultsStride); + pendingQuery = (pendingQuery + 1) % numQueries; +} + +OcclusionQuery::OcclusionQuery(PGraphics graphics) : QueryPool(graphics, VK_QUERY_TYPE_OCCLUSION, 0, sizeof(uint64), 16) {} + +OcclusionQuery::~OcclusionQuery() {} + +void OcclusionQuery::beginQuery() { begin(); } + +void OcclusionQuery::endQuery() { end(); } + +Gfx::OcclusionResult OcclusionQuery::getResults() { + Array result(1); + getQueryResults(result); + return Gfx::OcclusionResult{ + .numFragments = result[0], + }; +} + +PipelineStatisticsQuery::PipelineStatisticsQuery(PGraphics graphics) + : QueryPool(graphics, VK_QUERY_TYPE_PIPELINE_STATISTICS, + VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT | VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT | + VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT | VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT | + VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT | VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT | + VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT | + VK_QUERY_PIPELINE_STATISTIC_TASK_SHADER_INVOCATIONS_BIT_EXT | + VK_QUERY_PIPELINE_STATISTIC_MESH_SHADER_INVOCATIONS_BIT_EXT, + sizeof(PipelineStatisticsQuery), 16) {} + +PipelineStatisticsQuery::~PipelineStatisticsQuery() {} + +void PipelineStatisticsQuery::beginQuery() { begin(); } + +void PipelineStatisticsQuery::endQuery() { end(); } + +Gfx::PipelineStatisticsResult PipelineStatisticsQuery::getResults() { + Array result(9); + getQueryResults(result); + return Gfx::PipelineStatisticsResult{ + .inputAssemblyVertices = result[0], + .inputAssemblyPrimitives = result[1], + .vertexShaderInvocations = result[2], + .clippingInvocations = result[3], + .clippingPrimitives = result[4], + .fragmentShaderInvocations = result[5], + .computeShaderInvocations = result[6], + .taskShaderInvocations = result[7], + .meshShaderInvocations = result[8], + }; } \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/Query.h b/src/Engine/Graphics/Vulkan/Query.h index 21e5fac..eb6ccad 100644 --- a/src/Engine/Graphics/Vulkan/Query.h +++ b/src/Engine/Graphics/Vulkan/Query.h @@ -1,22 +1,48 @@ #pragma once -#include "Enums.h" #include "Graphics.h" #include "Graphics/Query.h" +#include "Buffer.h" namespace Seele { namespace Vulkan { -class OcclusionQuery : public Gfx::OcclusionQuery { +class QueryPool { + public: + QueryPool(PGraphics graphics, VkQueryType type, VkQueryPipelineStatisticFlags flags, uint32 resultsStride, uint32 numBuffered); + virtual ~QueryPool(); + void begin(); + void end(); + // stalls for the currently first pending query, dont call in render thread + void getQueryResults(Array& results); + + protected: + PGraphics graphics; + VkQueryPool handle; + VkQueryPipelineStatisticFlags flags; + OBufferAllocation resultsAlloc; + uint64* resultsPtr; + uint32 pendingQuery = 0; + uint32 currentQuery = 0; + uint32 numQueries; + uint32 resultsStride; +}; +class OcclusionQuery : public Gfx::OcclusionQuery, public QueryPool { public: OcclusionQuery(PGraphics graphics); virtual ~OcclusionQuery(); virtual void beginQuery() override; virtual void endQuery() override; - virtual void resetQuery() override; - virtual uint64 getResults() override; - private: - PGraphics graphics; - VkQueryPool handle; + virtual Gfx::OcclusionResult getResults() override; }; DEFINE_REF(OcclusionQuery) +class PipelineStatisticsQuery : public Gfx::PipelineStatisticsQuery, public QueryPool { + public: + PipelineStatisticsQuery(PGraphics graphics); + virtual ~PipelineStatisticsQuery(); + virtual void beginQuery() override; + virtual void endQuery() override; + virtual Gfx::PipelineStatisticsResult getResults() override; +}; +DEFINE_REF(PipelineStatisticsQuery) + } // namespace Vulkan } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Window/GameView.cpp b/src/Engine/Window/GameView.cpp index a49da22..39a8d3a 100644 --- a/src/Engine/Window/GameView.cpp +++ b/src/Engine/Window/GameView.cpp @@ -3,13 +3,15 @@ #include "Asset/AssetRegistry.h" #include "Component/KeyboardInput.h" #include "Graphics/Graphics.h" -#include "Graphics/RenderPass/CachedDepthPass.h" -#include "Graphics/RenderPass/DepthCullingPass.h" -#include "Graphics/RenderPass/VisibilityPass.h" -#include "Graphics/RenderPass/LightCullingPass.h" +#include "Graphics/Query.h" #include "Graphics/RenderPass/BasePass.h" -#include "Graphics/RenderPass/SkyboxRenderPass.h" +#include "Graphics/RenderPass/CachedDepthPass.h" #include "Graphics/RenderPass/DebugPass.h" +#include "Graphics/RenderPass/DepthCullingPass.h" +#include "Graphics/RenderPass/LightCullingPass.h" +#include "Graphics/RenderPass/RenderGraphResources.h" +#include "Graphics/RenderPass/SkyboxRenderPass.h" +#include "Graphics/RenderPass/VisibilityPass.h" #include "System/CameraUpdater.h" #include "System/LightGather.h" #include "System/MeshUpdater.h" @@ -30,9 +32,28 @@ GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate renderGraph.addPass(new LightCullingPass(graphics, scene)); renderGraph.addPass(new BasePass(graphics, scene)); renderGraph.addPass(new DebugPass(graphics, scene)); - // renderGraph.addPass(new SkyboxRenderPass(graphics, scene)); + // renderGraph.addPass(new SkyboxRenderPass(graphics, scene)); renderGraph.setViewport(viewport); renderGraph.createRenderPass(); + queryThread = std::thread([&]() { + PRenderGraphResources res = renderGraph.getResources(); + Gfx::PPipelineStatisticsQuery cachedQuery = res->requestQuery("CACHED_QUERY"); + Gfx::PPipelineStatisticsQuery depthQuery = res->requestQuery("DEPTH_QUERY"); + Gfx::PPipelineStatisticsQuery baseQuery = res->requestQuery("BASEPASS_QUERY"); + Gfx::PPipelineStatisticsQuery lightCullQuery = res->requestQuery("LIGHTCULL_QUERY"); + Gfx::PPipelineStatisticsQuery visibilityQuery = res->requestQuery("VISIBILITY_QUERY"); + while (true) { + auto cachedResults = cachedQuery->getResults(); + auto depthResults = depthQuery->getResults(); + auto baseResults = baseQuery->getResults(); + auto lightCullResults = lightCullQuery->getResults(); + auto visiblityResults = visibilityQuery->getResults(); + std::cout << "Pipeline Stats: " + << cachedResults.meshShaderInvocations + depthResults.meshShaderInvocations + baseResults.meshShaderInvocations + + lightCullResults.meshShaderInvocations + visiblityResults.meshShaderInvocations + << std::endl; + } + }); } GameView::~GameView() {} diff --git a/src/Engine/Window/GameView.h b/src/Engine/Window/GameView.h index 7fb949d..230d36c 100644 --- a/src/Engine/Window/GameView.h +++ b/src/Engine/Window/GameView.h @@ -28,6 +28,7 @@ class GameView : public View { OScene scene; GameInterface gameInterface; RenderGraph renderGraph; + std::thread queryThread; PSystemGraph systemGraph; System::PKeyboardInput keyboardSystem;