diff --git a/res/shaders/DrawListTask.slang b/res/shaders/DrawListTask.slang index 9e718c3..022b040 100644 --- a/res/shaders/DrawListTask.slang +++ b/res/shaders/DrawListTask.slang @@ -26,7 +26,9 @@ void taskMain( uint cull = p.cullingOffset + i; MeshletDescription meshlet = pScene.meshletInfos[m]; MeshletCullingInfo culling = pScene.cullingInfos[cull]; +#ifdef DEPTH_CULLING if(culling.anyVisible()) +#endif { uint index; InterlockedAdd(head, 1, index); diff --git a/res/shaders/ViewCullingTask.slang b/res/shaders/ViewCullingTask.slang deleted file mode 100644 index 855cc47..0000000 --- a/res/shaders/ViewCullingTask.slang +++ /dev/null @@ -1,49 +0,0 @@ -import Common; -import Scene; - -groupshared MeshPayload p; -groupshared uint head; -groupshared Frustum viewFrustum; - -[numthreads(TASK_GROUP_SIZE, 1, 1)] -[shader("amplification")] -void taskMain( - uint threadID: SV_GroupIndex, - uint groupID: SV_GroupID -){ - InstanceData instance = pScene.instances[pOffsets.instanceOffset + groupID]; - MeshData mesh = pScene.meshData[pOffsets.instanceOffset + groupID]; - if(threadID == 0) - { - head = 0; - float3 origin = viewToModel(instance.inverseTransformMatrix, float4(0, 0, 0, 1)).xyz; - const float offset = 0.0f; - float3 corners[4] = { - screenToModel(instance.inverseTransformMatrix, float4(offset, offset, -1.0f, 1.0f)).xyz, - screenToModel(instance.inverseTransformMatrix, float4(pViewParams.screenDimensions.x - offset, offset, -1.0f, 1.0f)).xyz, - screenToModel(instance.inverseTransformMatrix, float4(offset, pViewParams.screenDimensions.y - offset, -1.0f, 1.0f)).xyz, - screenToModel(instance.inverseTransformMatrix, float4(pViewParams.screenDimensions - float2(offset, offset), -1.0f, 1.0f)).xyz - }; - viewFrustum.sides[0] = computePlane(origin, corners[2], corners[0]); - viewFrustum.sides[1] = computePlane(origin, corners[1], corners[3]); - viewFrustum.sides[2] = computePlane(origin, corners[0], corners[1]); - viewFrustum.sides[3] = computePlane(origin, corners[3], corners[2]); - p.instanceId = pOffsets.instanceOffset + groupID; - } - GroupMemoryBarrierWithGroupSync(); - for(uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE) - { - uint m = mesh.meshletOffset + i; - MeshletDescription meshlet = pScene.meshletInfos[m]; -#ifdef VIEW_CULLING - if(meshlet.bounding.insideFrustum(viewFrustum)) -#endif - { - uint index; - InterlockedAdd(head, 1, index); - p.culledMeshlets[index] = m; - } - } - GroupMemoryBarrierWithGroupSync(); - DispatchMesh(head, 1, 1, p); -} \ No newline at end of file diff --git a/src/Engine/Graphics/CMakeLists.txt b/src/Engine/Graphics/CMakeLists.txt index 0ac77b0..78a7039 100644 --- a/src/Engine/Graphics/CMakeLists.txt +++ b/src/Engine/Graphics/CMakeLists.txt @@ -19,6 +19,8 @@ target_sources(Engine Meshlet.cpp Pipeline.h Pipeline.cpp + Query.h + Query.cpp RayTracing.h RayTracing.cpp RenderTarget.h @@ -52,6 +54,7 @@ target_sources(Engine Meshlet.h MeshData.h Pipeline.h + Query.h RayTracing.h RenderTarget.h Resources.h diff --git a/src/Engine/Graphics/Graphics.h b/src/Engine/Graphics/Graphics.h index acf0ff8..d0e5d54 100644 --- a/src/Engine/Graphics/Graphics.h +++ b/src/Engine/Graphics/Graphics.h @@ -30,6 +30,7 @@ DECLARE_REF(GraphicsPipeline) DECLARE_REF(ComputePipeline) DECLARE_REF(RenderCommand) DECLARE_REF(ComputeCommand) +DECLARE_REF(OcclusionQuery) DECLARE_REF(BottomLevelAS) DECLARE_REF(TopLevelAS) class Graphics { @@ -79,6 +80,8 @@ class Graphics { virtual OVertexInput createVertexInput(VertexInputStateCreateInfo createInfo) = 0; + virtual Gfx::OOcclusionQuery createOcclusionQuery() = 0; + virtual void resolveTexture(PTexture source, PTexture destination) = 0; virtual void copyTexture(PTexture src, PTexture dst) = 0; diff --git a/src/Engine/Graphics/Query.cpp b/src/Engine/Graphics/Query.cpp new file mode 100644 index 0000000..bed9887 --- /dev/null +++ b/src/Engine/Graphics/Query.cpp @@ -0,0 +1,10 @@ +#include "Query.h" + +using namespace Seele; +using namespace Seele::Gfx; + +OcclusionQuery::OcclusionQuery() +{} + +OcclusionQuery::~OcclusionQuery() +{} \ No newline at end of file diff --git a/src/Engine/Graphics/Query.h b/src/Engine/Graphics/Query.h new file mode 100644 index 0000000..4b1d107 --- /dev/null +++ b/src/Engine/Graphics/Query.h @@ -0,0 +1,19 @@ +#pragma once +#include "MinimalEngine.h" + +namespace Seele { +namespace Gfx { +class OcclusionQuery { + public: + OcclusionQuery(); + virtual ~OcclusionQuery(); + virtual void beginQuery() = 0; + virtual void endQuery() = 0; + virtual void resetQuery() = 0; + virtual uint64 getResults() = 0; + + private: +}; +DEFINE_REF(OcclusionQuery) +} // 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 22f0fd5..a30d3d8 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -16,8 +16,6 @@ using namespace Seele; -extern bool useViewCulling; - BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) { basePassLayout = graphics->createPipelineLayout("BasePassLayout"); @@ -93,7 +91,7 @@ void BasePass::render() { Array commands; Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("BasePass"); - permutation.setViewCulling(useViewCulling); + permutation.setDepthCulling(true); // always use the culling info for (VertexData* vertexData : VertexData::getList()) { vertexData->getInstanceDataSet()->updateBuffer(6, cullingBuffer); vertexData->getInstanceDataSet()->writeChanges(); diff --git a/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp b/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp index e1af606..fccef3b 100644 --- a/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp +++ b/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp @@ -4,7 +4,7 @@ using namespace Seele; extern bool usePositionOnly; -extern bool useViewCulling; +extern bool useDepthCulling; CachedDepthPass::CachedDepthPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) { depthPrepassLayout = graphics->createPipelineLayout("CachedDepthLayout"); @@ -45,13 +45,17 @@ CachedDepthPass::~CachedDepthPass() {} void CachedDepthPass::beginFrame(const Component::Camera& cam) { RenderPass::beginFrame(cam); } +uint64 numFragments = 0; + void CachedDepthPass::render() { + occlusionQuery->resetQuery(); + occlusionQuery->beginQuery(); graphics->beginRenderPass(renderPass); Array commands; Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("CachedDepthPass"); permutation.setPositionOnly(usePositionOnly); - permutation.setViewCulling(useViewCulling); + permutation.setDepthCulling(useDepthCulling); for (VertexData* vertexData : VertexData::getList()) { permutation.setVertexData(vertexData->getTypeName()); vertexData->getInstanceDataSet()->updateBuffer(6, cullingBuffer); @@ -141,11 +145,14 @@ void CachedDepthPass::render() { graphics->executeCommands(std::move(commands)); graphics->endRenderPass(); + occlusionQuery->endQuery(); + numFragments = occlusionQuery->getResults(); } void CachedDepthPass::endFrame() {} void CachedDepthPass::publishOutputs() { + occlusionQuery = graphics->createOcclusionQuery(); // If we render to a part of an image, the depth buffer itself must // still match the size of the whole image or their coordinate systems go out of sync TextureCreateInfo depthBufferInfo = { diff --git a/src/Engine/Graphics/RenderPass/CachedDepthPass.h b/src/Engine/Graphics/RenderPass/CachedDepthPass.h index 56388db..f4ba186 100644 --- a/src/Engine/Graphics/RenderPass/CachedDepthPass.h +++ b/src/Engine/Graphics/RenderPass/CachedDepthPass.h @@ -1,5 +1,6 @@ #pragma once #include "RenderPass.h" +#include "Graphics/Query.h" namespace Seele { class CachedDepthPass : public RenderPass { @@ -21,6 +22,7 @@ class CachedDepthPass : public RenderPass { Gfx::OTexture2D visibilityBuffer; Gfx::OPipelineLayout depthPrepassLayout; + Gfx::OOcclusionQuery occlusionQuery; Gfx::PShaderBuffer cullingBuffer; }; DEFINE_REF(CachedDepthPass) diff --git a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp index 1cfb3b1..83babd6 100644 --- a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp @@ -4,7 +4,7 @@ using namespace Seele; extern bool usePositionOnly; -extern bool useViewCulling; +extern bool useDepthCulling; DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) { depthTextureLayout = graphics->createDescriptorLayout("pDepthAttachment"); @@ -54,6 +54,8 @@ DepthCullingPass::~DepthCullingPass() {} void DepthCullingPass::beginFrame(const Component::Camera& cam) { RenderPass::beginFrame(cam); } +extern uint64 numFragments; + void DepthCullingPass::render() { depthAttachment.getTexture()->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, Gfx::SE_ACCESS_TRANSFER_READ_BIT, @@ -76,100 +78,107 @@ void DepthCullingPass::render() { set->updateTexture(0, Gfx::PTexture2D(depthMipTexture)); set->writeChanges(); + occlusionQuery->resetQuery(); + occlusionQuery->beginQuery(); graphics->beginRenderPass(renderPass); - Array commands; + if (useDepthCulling) { - Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("DepthPass"); - permutation.setPositionOnly(usePositionOnly); - permutation.setViewCulling(useViewCulling); - for (VertexData* vertexData : VertexData::getList()) { - permutation.setVertexData(vertexData->getTypeName()); - vertexData->getInstanceDataSet()->updateBuffer(6, cullingBuffer); - vertexData->getInstanceDataSet()->writeChanges(); - // Create Pipeline(VertexData) - // Descriptors: - // ViewData => global, static - // VertexData => per meshtype - // SceneData => per meshtype - Gfx::PermutationId id(permutation); + Array commands; - Gfx::ORenderCommand command = graphics->createRenderCommand("DepthRender"); - command->setViewport(viewport); + Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("DepthPass"); + permutation.setPositionOnly(usePositionOnly); + permutation.setDepthCulling(useDepthCulling); + for (VertexData* vertexData : VertexData::getList()) { + permutation.setVertexData(vertexData->getTypeName()); + vertexData->getInstanceDataSet()->updateBuffer(6, cullingBuffer); + vertexData->getInstanceDataSet()->writeChanges(); + // Create Pipeline(VertexData) + // Descriptors: + // ViewData => global, static + // VertexData => per meshtype + // SceneData => per meshtype + Gfx::PermutationId id(permutation); - const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id); - assert(collection != nullptr); - if (graphics->supportMeshShading()) { - Gfx::MeshPipelineCreateInfo pipelineInfo = { - .taskShader = collection->taskShader, - .meshShader = collection->meshShader, - .fragmentShader = collection->fragmentShader, - .renderPass = renderPass, - .pipelineLayout = collection->pipelineLayout, - .multisampleState = - { - .samples = viewport->getSamples(), - }, - .depthStencilState = - { - .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER, - }, - .colorBlend = - { - .attachmentCount = 1, - }, - }; - Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); - command->bindPipeline(pipeline); - } else { - Gfx::LegacyPipelineCreateInfo pipelineInfo = { - .vertexShader = collection->vertexShader, - .fragmentShader = collection->fragmentShader, - .renderPass = renderPass, - .pipelineLayout = collection->pipelineLayout, - .multisampleState = - { - .samples = viewport->getSamples(), - }, - .depthStencilState = - { - .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER, - }, - .colorBlend = - { - .attachmentCount = 1, - }, - }; - Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); - command->bindPipeline(pipeline); - } - command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(), set}); - uint32 offset = 0; - command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets), - &offset); - if (graphics->supportMeshShading()) { - command->drawMesh(vertexData->getNumInstances(), 1, 1); - } else { - const auto& materials = vertexData->getMaterialData(); - for (const auto& materialData : materials) { - for (const auto& drawCall : materialData.instances) { - // material not used for any active meshes, skip - if (materialData.instances.size() == 0) - continue; - command->bindIndexBuffer(vertexData->getIndexBuffer()); - uint32 inst = drawCall.offsets.instanceOffset; - for (const auto& meshData : drawCall.instanceMeshData) { - // all meshlets of a mesh share the same indices offset - command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, - vertexData->getIndicesOffset(meshData.meshletOffset), inst++); + Gfx::ORenderCommand command = graphics->createRenderCommand("DepthRender"); + command->setViewport(viewport); + + const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id); + assert(collection != nullptr); + if (graphics->supportMeshShading()) { + Gfx::MeshPipelineCreateInfo pipelineInfo = { + .taskShader = collection->taskShader, + .meshShader = collection->meshShader, + .fragmentShader = collection->fragmentShader, + .renderPass = renderPass, + .pipelineLayout = collection->pipelineLayout, + .multisampleState = + { + .samples = viewport->getSamples(), + }, + .depthStencilState = + { + .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER, + }, + .colorBlend = + { + .attachmentCount = 1, + }, + }; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); + } else { + Gfx::LegacyPipelineCreateInfo pipelineInfo = { + .vertexShader = collection->vertexShader, + .fragmentShader = collection->fragmentShader, + .renderPass = renderPass, + .pipelineLayout = collection->pipelineLayout, + .multisampleState = + { + .samples = viewport->getSamples(), + }, + .depthStencilState = + { + .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER, + }, + .colorBlend = + { + .attachmentCount = 1, + }, + }; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); + } + command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(), set}); + uint32 offset = 0; + command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, + sizeof(VertexData::DrawCallOffsets), &offset); + if (graphics->supportMeshShading()) { + command->drawMesh(vertexData->getNumInstances(), 1, 1); + } else { + const auto& materials = vertexData->getMaterialData(); + for (const auto& materialData : materials) { + for (const auto& drawCall : materialData.instances) { + // material not used for any active meshes, skip + if (materialData.instances.size() == 0) + continue; + command->bindIndexBuffer(vertexData->getIndexBuffer()); + uint32 inst = drawCall.offsets.instanceOffset; + for (const auto& meshData : drawCall.instanceMeshData) { + // all meshlets of a mesh share the same indices offset + command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, + vertexData->getIndicesOffset(meshData.meshletOffset), inst++); + } } } } + commands.add(std::move(command)); } - commands.add(std::move(command)); - } - graphics->executeCommands(std::move(commands)); + graphics->executeCommands(std::move(commands)); + } graphics->endRenderPass(); + occlusionQuery->endQuery(); + std::cout << "Occlusion fragments: " << occlusionQuery->getResults() + numFragments << std::endl; // 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, @@ -183,6 +192,8 @@ void DepthCullingPass::render() { void DepthCullingPass::endFrame() {} void DepthCullingPass::publishOutputs() { + occlusionQuery = graphics->createOcclusionQuery(); + uint32 width = viewport->getOwner()->getFramebufferWidth(); uint32 height = viewport->getOwner()->getFramebufferHeight(); uint32 mipLevels = static_cast(std::floor(std::log2(std::max(width, height)))) + 1; diff --git a/src/Engine/Graphics/RenderPass/DepthCullingPass.h b/src/Engine/Graphics/RenderPass/DepthCullingPass.h index 9e5d517..90f20f8 100644 --- a/src/Engine/Graphics/RenderPass/DepthCullingPass.h +++ b/src/Engine/Graphics/RenderPass/DepthCullingPass.h @@ -1,6 +1,7 @@ #pragma once #include "MinimalEngine.h" #include "RenderPass.h" +#include "Graphics/Query.h" namespace Seele { class DepthCullingPass : public RenderPass { @@ -22,6 +23,7 @@ class DepthCullingPass : public RenderPass { Gfx::ODescriptorLayout depthTextureLayout; Gfx::OPipelineLayout depthPrepassLayout; + Gfx::OOcclusionQuery occlusionQuery; Gfx::PShaderBuffer cullingBuffer; }; DEFINE_REF(DepthCullingPass) diff --git a/src/Engine/Graphics/Shader.cpp b/src/Engine/Graphics/Shader.cpp index 7a50a95..2b045ec 100644 --- a/src/Engine/Graphics/Shader.cpp +++ b/src/Engine/Graphics/Shader.cpp @@ -60,7 +60,7 @@ void ShaderCompiler::compile() { work.add([=]() { ShaderPermutation permutation = getTemplate(name); permutation.setPositionOnly(x); - permutation.setViewCulling(y); + permutation.setDepthCulling(y); permutation.setVertexData(vd->getTypeName()); OPipelineLayout layout = graphics->createPipelineLayout(pass.baseLayout->getName(), pass.baseLayout); layout->addDescriptorLayout(vd->getVertexDataLayout()); @@ -78,7 +78,7 @@ void ShaderCompiler::compile() { work.add([=]() { ShaderPermutation permutation = getTemplate(name); permutation.setPositionOnly(x); - permutation.setViewCulling(y); + permutation.setDepthCulling(y); permutation.setVertexData(vd->getTypeName()); OPipelineLayout layout = graphics->createPipelineLayout(pass.baseLayout->getName(), pass.baseLayout); layout->addDescriptorLayout(vd->getVertexDataLayout()); @@ -113,8 +113,8 @@ void ShaderCompiler::createShaders(ShaderPermutation permutation, Gfx::OPipeline if (permutation.positionOnly) { createInfo.defines["POS_ONLY"] = "1"; } - if (permutation.viewCulling) { - createInfo.defines["VIEW_CULLING"] = "1"; + if (permutation.depthCulling) { + createInfo.defines["DEPTH_CULLING"] = "1"; } if (permutation.visibilityPass) { createInfo.defines["VISIBILITY"] = "1"; diff --git a/src/Engine/Graphics/Shader.h b/src/Engine/Graphics/Shader.h index 887fbba..133491d 100644 --- a/src/Engine/Graphics/Shader.h +++ b/src/Engine/Graphics/Shader.h @@ -55,7 +55,7 @@ struct ShaderPermutation { uint8 hasTaskShader; uint8 useMaterial; uint8 positionOnly; - uint8 viewCulling; + uint8 depthCulling; uint8 visibilityPass; // TODO: lightmapping etc ShaderPermutation() { std::memset(this, 0, sizeof(ShaderPermutation)); } @@ -89,7 +89,7 @@ struct ShaderPermutation { strncpy(materialName, name.data(), sizeof(materialName)); } void setPositionOnly(bool enable) { positionOnly = enable; } - void setViewCulling(bool enable) { viewCulling = enable; } + void setDepthCulling(bool enable) { depthCulling = enable; } void setVisibilityPass(bool enable) { visibilityPass = enable; } }; // Hashed ShaderPermutation for fast lookup diff --git a/src/Engine/Graphics/Vulkan/CMakeLists.txt b/src/Engine/Graphics/Vulkan/CMakeLists.txt index 3dd3455..f08bf85 100644 --- a/src/Engine/Graphics/Vulkan/CMakeLists.txt +++ b/src/Engine/Graphics/Vulkan/CMakeLists.txt @@ -20,6 +20,8 @@ target_sources(Engine Pipeline.cpp PipelineCache.h PipelineCache.cpp + Query.h + Query.cpp Queue.h Queue.cpp RayTracing.h @@ -48,6 +50,7 @@ target_sources(Engine Graphics.h Pipeline.h PipelineCache.h + Query.h Queue.h RayTracing.h RenderPass.h diff --git a/src/Engine/Graphics/Vulkan/Command.cpp b/src/Engine/Graphics/Vulkan/Command.cpp index 3a14d0c..cc7282e 100644 --- a/src/Engine/Graphics/Vulkan/Command.cpp +++ b/src/Engine/Graphics/Vulkan/Command.cpp @@ -181,8 +181,8 @@ void RenderCommand::begin(PRenderPass renderPass, PFramebuffer framebuffer) { .renderPass = renderPass->getHandle(), .subpass = 0, .framebuffer = framebuffer->getHandle(), - .occlusionQueryEnable = 0, - .queryFlags = 0, + .occlusionQueryEnable = 1, + .queryFlags = VK_QUERY_CONTROL_PRECISE_BIT, .pipelineStatistics = 0, }; VkCommandBufferBeginInfo beginInfo = { diff --git a/src/Engine/Graphics/Vulkan/Graphics.cpp b/src/Engine/Graphics/Vulkan/Graphics.cpp index 8b90021..df0bff8 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.cpp +++ b/src/Engine/Graphics/Vulkan/Graphics.cpp @@ -12,6 +12,7 @@ #include "RayTracing.h" #include "RenderPass.h" #include "Shader.h" +#include "Query.h" #include "Window.h" #include #include @@ -96,7 +97,6 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass) { void Graphics::endRenderPass() { getGraphicsCommands()->getCommands()->endRenderPass(); - getGraphicsCommands()->submitCommands(); } void Graphics::waitDeviceIdle() { vkDeviceWaitIdle(handle); } @@ -195,6 +195,8 @@ Gfx::OPipelineLayout Graphics::createPipelineLayout(const std::string& name, Gfx Gfx::OVertexInput Graphics::createVertexInput(VertexInputStateCreateInfo createInfo) { return new VertexInput(createInfo); } +Gfx::OOcclusionQuery Graphics::createOcclusionQuery() { return new OcclusionQuery(this); } + void Graphics::resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) { PTextureBase sourceTex = source.cast(); PTextureBase destinationTex = destination.cast(); @@ -396,7 +398,6 @@ void Graphics::pickPhysicalDevice() { features.pNext = &robustness; robustness.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; robustness.pNext = &features11; - robustness.nullDescriptor = true; features11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; features11.pNext = &features12; features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; @@ -425,6 +426,7 @@ void Graphics::pickPhysicalDevice() { vkGetPhysicalDeviceProperties(physicalDevice, &props); vkGetPhysicalDeviceFeatures2(physicalDevice, &features); features.features.robustBufferAccess = 0; + features.features.inheritedQueries = true; if (Gfx::useMeshShading) { uint32 count = 0; vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &count, nullptr); diff --git a/src/Engine/Graphics/Vulkan/Graphics.h b/src/Engine/Graphics/Vulkan/Graphics.h index 997905a..5e34bc6 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.h +++ b/src/Engine/Graphics/Vulkan/Graphics.h @@ -65,6 +65,8 @@ class Graphics : public Gfx::Graphics { virtual Gfx::OVertexInput createVertexInput(VertexInputStateCreateInfo createInfo) override; + virtual Gfx::OOcclusionQuery createOcclusionQuery() 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 new file mode 100644 index 0000000..0d026a1 --- /dev/null +++ b/src/Engine/Graphics/Vulkan/Query.cpp @@ -0,0 +1,32 @@ +#include "Query.h" +#include "Command.h" + +using namespace Seele; +using namespace Seele::Vulkan; + +OcclusionQuery::OcclusionQuery(PGraphics graphics) :graphics(graphics){ + VkQueryPoolCreateInfo info = { + .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .queryType = VK_QUERY_TYPE_OCCLUSION, + .queryCount = 1, + .pipelineStatistics = 0, + }; + VK_CHECK(vkCreateQueryPool(graphics->getDevice(), &info, nullptr, &handle)); +} + +OcclusionQuery::~OcclusionQuery() { vkDestroyQueryPool(graphics->getDevice(), handle, nullptr); } + +void OcclusionQuery::beginQuery() { vkCmdBeginQuery(graphics->getGraphicsCommands()->getCommands()->getHandle(), handle, 0, VK_QUERY_CONTROL_PRECISE_BIT); } + +void OcclusionQuery::endQuery() { vkCmdEndQuery(graphics->getGraphicsCommands()->getCommands()->getHandle(), handle, 0); } + +void OcclusionQuery::resetQuery() { vkResetQueryPool(graphics->getDevice(), handle, 0, 1); } + +uint64 OcclusionQuery::getResults() { + 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; +} \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/Query.h b/src/Engine/Graphics/Vulkan/Query.h new file mode 100644 index 0000000..21e5fac --- /dev/null +++ b/src/Engine/Graphics/Vulkan/Query.h @@ -0,0 +1,22 @@ +#pragma once +#include "Enums.h" +#include "Graphics.h" +#include "Graphics/Query.h" + +namespace Seele { +namespace Vulkan { +class OcclusionQuery : public Gfx::OcclusionQuery { + 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; +}; +DEFINE_REF(OcclusionQuery) +} // 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 a4c4fc8..a49da22 100644 --- a/src/Engine/Window/GameView.cpp +++ b/src/Engine/Window/GameView.cpp @@ -18,9 +18,8 @@ using namespace Seele; bool usePositionOnly = false; -bool useViewCulling = false; +bool useDepthCulling = false; bool useLightCulling = false; -bool resetVisibility = false; GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo& createInfo, std::string dllPath) : View(graphics, window, createInfo, "Game"), scene(new Scene(graphics)), gameInterface(dllPath) { @@ -92,16 +91,13 @@ void GameView::keyCallback(KeyCode code, InputAction action, KeyModifier modifie std::cout << "Use Pos only " << usePositionOnly << std::endl; } if (code == KeyCode::KEY_O && action == InputAction::RELEASE) { - useViewCulling = !useViewCulling; - std::cout << "Use View Culling " << useViewCulling << std::endl; + useDepthCulling = !useDepthCulling; + std::cout << "Use Depth Culling " << useDepthCulling << std::endl; } if (code == KeyCode::KEY_L && action == InputAction::RELEASE) { useLightCulling = !useLightCulling; std::cout << "Use Light Culling " << useLightCulling << std::endl; } - if (code == KeyCode::KEY_R && action == InputAction::RELEASE) { - resetVisibility = true; - } } void GameView::mouseMoveCallback(double xPos, double yPos) { keyboardSystem->mouseCallback(xPos, yPos); }