From e00b382d4a85231a28d3c098448216eace65d1ce Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Mon, 10 May 2021 23:57:55 +0200 Subject: [PATCH] Provisional light culling --- res/shaders/ComputeFrustums.slang | 2 +- res/shaders/ForwardPlus.slang | 22 +- res/shaders/LightCulling.slang | 29 +- res/shaders/lib/Common.slang | 14 +- res/shaders/lib/LightEnv.slang | 2 +- src/Engine/Asset/TextureLoader.cpp | 2 +- src/Engine/Containers/Array.h | 4 +- src/Engine/Graphics/Graphics.h | 11 +- src/Engine/Graphics/GraphicsInitializer.h | 12 +- src/Engine/Graphics/GraphicsResources.cpp | 20 +- src/Engine/Graphics/GraphicsResources.h | 42 ++- src/Engine/Graphics/RenderPass/BasePass.cpp | 45 ++-- src/Engine/Graphics/RenderPass/BasePass.h | 4 +- .../Graphics/RenderPass/DepthPrepass.cpp | 21 +- src/Engine/Graphics/RenderPass/DepthPrepass.h | 1 - .../Graphics/RenderPass/LightCullingPass.cpp | 252 +++++++++++++++--- .../Graphics/RenderPass/LightCullingPass.h | 42 ++- .../Graphics/RenderPass/RenderGraph.cpp | 36 +++ src/Engine/Graphics/RenderPass/RenderGraph.h | 9 +- src/Engine/Graphics/RenderPass/RenderPass.h | 7 +- src/Engine/Graphics/Vulkan/VulkanBuffer.cpp | 118 +++++--- .../Graphics/Vulkan/VulkanCommandBuffer.cpp | 201 +++++++++++--- .../Graphics/Vulkan/VulkanCommandBuffer.h | 62 ++++- .../Graphics/Vulkan/VulkanDescriptorSets.cpp | 57 ++-- .../Graphics/Vulkan/VulkanDescriptorSets.h | 13 +- src/Engine/Graphics/Vulkan/VulkanGraphics.cpp | 94 ++++++- src/Engine/Graphics/Vulkan/VulkanGraphics.h | 10 +- .../Graphics/Vulkan/VulkanGraphicsEnums.cpp | 77 ++++++ .../Graphics/Vulkan/VulkanGraphicsEnums.h | 2 + .../Vulkan/VulkanGraphicsResources.cpp | 1 - .../Graphics/Vulkan/VulkanGraphicsResources.h | 55 +++- src/Engine/Graphics/Vulkan/VulkanShader.cpp | 1 + src/Engine/Graphics/Vulkan/VulkanTexture.cpp | 72 +++-- src/Engine/Graphics/Vulkan/VulkanViewport.cpp | 10 +- src/Engine/Material/MaterialAsset.cpp | 2 +- src/Engine/Material/ShaderExpression.cpp | 15 ++ src/Engine/Material/ShaderExpression.h | 10 +- src/Engine/Scene/Scene.cpp | 8 + src/Engine/Scene/Scene.h | 3 +- src/Engine/Window/SceneRenderPath.cpp | 10 + src/Engine/Window/SceneRenderPath.h | 4 +- 41 files changed, 1072 insertions(+), 330 deletions(-) diff --git a/res/shaders/ComputeFrustums.slang b/res/shaders/ComputeFrustums.slang index 7c3931e..fbed51c 100644 --- a/res/shaders/ComputeFrustums.slang +++ b/res/shaders/ComputeFrustums.slang @@ -8,7 +8,7 @@ struct ComputeShaderInput uint groupIndex : SV_GroupIndex; }; -layout(set = 0, binding = 0, std430) +layout(set = 0, binding = 1, std430) cbuffer DispatchParams { uint3 numThreadGroups; diff --git a/res/shaders/ForwardPlus.slang b/res/shaders/ForwardPlus.slang index 7a0852b..e5f64fb 100644 --- a/res/shaders/ForwardPlus.slang +++ b/res/shaders/ForwardPlus.slang @@ -8,10 +8,10 @@ import MATERIAL_IMPORT; import PrimitiveSceneData; import MaterialParameter; -//layout(set = 0, binding = 2) -//StructuredBuffer lightIndexList; -//layout(set = 0, binding = 3) -//RWTexture2D lightGrid; +layout(set = INDEX_LIGHT_ENV, binding = 1) +StructuredBuffer lightIndexList; +layout(set = INDEX_LIGHT_ENV, binding = 2) +RWTexture2D lightGrid; struct VertexStageOutput @@ -56,20 +56,20 @@ float4 fragmentMain( float3 result = float3(0, 0, 0); - for (int i = 0; i < gLightEnv.numDirectionalLights; i++) + for (int i = 0; i < gLightEnv[0].numDirectionalLights; i++) { - result += gLightEnv.directionalLights[i].illuminate(materialParams, brdf, viewDir); + result += gLightEnv[0].directionalLights[i].illuminate(materialParams, brdf, viewDir); } uint2 tileIndex = uint2(floor(materialParams.clipPosition.xy) / BLOCK_SIZE); - //uint startOffset = lightGrid[tileIndex].x; - //uint lightCount = lightGrid[tileIndex].y; + uint startOffset = lightGrid[tileIndex].x; + uint lightCount = lightGrid[tileIndex].y; - for (int j = 0; j < gLightEnv.numPointLights; ++j) + for (int j = 0; j < gLightEnv[0].numPointLights; ++j) { - //uint lightIndex = lightIndexList[startOffset + j]; - PointLight pointLight = gLightEnv.pointLights[j]; + uint lightIndex = lightIndexList[startOffset + j]; + PointLight pointLight = gLightEnv[0].pointLights[lightIndex]; result += pointLight.illuminate(materialParams, brdf, viewDir); } diff --git a/res/shaders/LightCulling.slang b/res/shaders/LightCulling.slang index f27c070..3fb866c 100644 --- a/res/shaders/LightCulling.slang +++ b/res/shaders/LightCulling.slang @@ -8,7 +8,7 @@ struct ComputeShaderInput uint3 dispatchThreadID : SV_DispatchThreadID; uint groupIndex : SV_GroupIndex; }; -layout(binding = 0) +layout(set = INDEX_VIEW_PARAMS, binding = 1) cbuffer DispatchParams { uint3 numThreadGroups; @@ -17,23 +17,23 @@ cbuffer DispatchParams uint pad1; } -layout(binding = 2) -RWTexture2D depthTextureVS; -layout(binding = 4) +layout(set = INDEX_VIEW_PARAMS, binding = 2) +Texture2D depthTextureVS; +layout(set = INDEX_VIEW_PARAMS, binding = 3) StructuredBuffer frustums; -layout(binding = 5) +layout(set = INDEX_VIEW_PARAMS, binding = 4) RWStructuredBuffer oLightIndexCounter; -layout(binding = 6) +layout(set = INDEX_VIEW_PARAMS, binding = 5) RWStructuredBuffer tLightIndexCounter; -layout(binding = 7) +layout(set = INDEX_VIEW_PARAMS, binding = 6) RWStructuredBuffer oLightIndexList; -layout(binding = 8) +layout(set = INDEX_VIEW_PARAMS, binding = 7) RWStructuredBuffer tLightIndexList; -layout(binding = 9) +layout(set = INDEX_VIEW_PARAMS, binding = 8) RWTexture2D oLightGrid; -layout(binding = 10) +layout(set = INDEX_VIEW_PARAMS, binding = 9) RWTexture2D tLightGrid; groupshared uint uMinDepth; @@ -71,9 +71,10 @@ void tAppendLight(uint lightIndex) } [numthreads(BLOCK_SIZE, BLOCK_SIZE, 1)] +[shader("compute")] void cullLights(ComputeShaderInput in) { - int2 texCoord = in.dispatchThreadID.xy; + int3 texCoord = int3(in.dispatchThreadID.xy, 0); float fDepth = depthTextureVS.Load(texCoord).r; uint uDepth = asuint(fDepth); @@ -101,10 +102,10 @@ void cullLights(ComputeShaderInput in) Plane minPlane = {float3(0, 0, -1), -minDepthVS}; - for ( uint i = in.groupIndex; i < lights.numPointLights; i += BLOCK_SIZE * BLOCK_SIZE ) + for ( uint i = in.groupIndex; i < gLightEnv[0].numPointLights; i += BLOCK_SIZE * BLOCK_SIZE ) { - PointLight light = lights.pointLights[i]; - //if(light.insideFrustum(groupFrustum, nearClipVS, maxDepthVS)) + PointLight light = gLightEnv[0].pointLights[i]; + //if(gLightEnv.insideFrustum(groupFrustum, nearClipVS, maxDepthVS)) { //InterlockedAdd(tLightCount, 1, index); //if(index < 1024) diff --git a/res/shaders/lib/Common.slang b/res/shaders/lib/Common.slang index e0aa45a..c2cef05 100644 --- a/res/shaders/lib/Common.slang +++ b/res/shaders/lib/Common.slang @@ -6,24 +6,18 @@ struct ViewParameter { float4x4 viewMatrix; float4x4 projectionMatrix; + float4x4 inverseProjection; + float2 screenDimensions; float4 cameraPos_WS; } layout(set = INDEX_VIEW_PARAMS, binding = 0, std430) ConstantBuffer gViewParams; -struct ScreenToViewParams -{ - float4x4 inverseProjection; - float2 screenDimensions; -} -layout(set = INDEX_VIEW_PARAMS, binding = 1, std430) -ConstantBuffer gScreenToViewParams; - // Convert clip space coordinates to view space float4 clipToView( float4 clip ) { // View space position. - float4 view = mul( gScreenToViewParams.inverseProjection, clip ); + float4 view = mul( gViewParams.inverseProjection, clip ); // Perspective projection. view = view / view.w; @@ -34,7 +28,7 @@ float4 clipToView( float4 clip ) float4 screenToView( float4 screen ) { // Convert to normalized texture coordinates - float2 texCoord = screen.xy / gScreenToViewParams.screenDimensions; + float2 texCoord = screen.xy / gViewParams.screenDimensions; // Convert to clip space float4 clip = float4( float2( texCoord.x, -texCoord.y ) * 2.0f - 1.0f, screen.z, screen.w ); diff --git a/res/shaders/lib/LightEnv.slang b/res/shaders/lib/LightEnv.slang index 757e553..9384a88 100644 --- a/res/shaders/lib/LightEnv.slang +++ b/res/shaders/lib/LightEnv.slang @@ -69,4 +69,4 @@ struct Lights }; layout(set = INDEX_LIGHT_ENV, binding = 0, std430) -ConstantBuffer gLightEnv; +StructuredBuffer gLightEnv; diff --git a/src/Engine/Asset/TextureLoader.cpp b/src/Engine/Asset/TextureLoader.cpp index 6752a15..73a3027 100644 --- a/src/Engine/Asset/TextureLoader.cpp +++ b/src/Engine/Asset/TextureLoader.cpp @@ -32,7 +32,7 @@ void TextureLoader::importAsset(const std::filesystem::path& filePath) AssetRegistry::get().textures[asset->getFileName()] = asset; futures.add(std::async(std::launch::async, [this, filePath, asset] () mutable { using namespace std::chrono_literals; - std::this_thread::sleep_for(5s); + //std::this_thread::sleep_for(5s); Gfx::PTexture2D texture = import(filePath); asset->setTexture(texture); asset->setStatus(Asset::Status::Ready); diff --git a/src/Engine/Containers/Array.h b/src/Engine/Containers/Array.h index 07150cb..496fed1 100644 --- a/src/Engine/Containers/Array.h +++ b/src/Engine/Containers/Array.h @@ -70,7 +70,7 @@ namespace Seele _data = new T[other.allocated]; assert(_data != nullptr); markIteratorDirty(); - std::copy(other.begin(), other.end(), beginIt); + std::copy(other.begin(), other.end(), begin()); } Array(Array &&other) noexcept : arraySize(std::move(other.arraySize)) @@ -97,7 +97,7 @@ namespace Seele } arraySize = other.arraySize; markIteratorDirty(); - std::copy(other.begin(), other.end(), beginIt); + std::copy(other.begin(), other.end(), begin()); } return *this; } diff --git a/src/Engine/Graphics/Graphics.h b/src/Engine/Graphics/Graphics.h index 2367426..0879294 100644 --- a/src/Engine/Graphics/Graphics.h +++ b/src/Engine/Graphics/Graphics.h @@ -33,20 +33,23 @@ public: virtual void beginRenderPass(PRenderPass renderPass) = 0; virtual void endRenderPass() = 0; - virtual void executeCommands(Array commands) = 0; + virtual void executeCommands(const Array& commands) = 0; + virtual void executeCommands(const Array& commands) = 0; virtual PTexture2D createTexture2D(const TextureCreateInfo &createInfo) = 0; virtual PUniformBuffer createUniformBuffer(const UniformBufferCreateInfo &bulkData) = 0; - virtual PStructuredBuffer createStructuredBuffer(const BulkResourceData &bulkData) = 0; + virtual PStructuredBuffer createStructuredBuffer(const StructuredBufferCreateInfo &bulkData) = 0; virtual PVertexBuffer createVertexBuffer(const VertexBufferCreateInfo &bulkData) = 0; virtual PIndexBuffer createIndexBuffer(const IndexBufferCreateInfo &bulkData) = 0; - virtual PRenderCommand createRenderCommand() = 0; + virtual PRenderCommand createRenderCommand(const std::string& name = "") = 0; + virtual PComputeCommand createComputeCommand(const std::string& name = "") = 0; virtual PVertexDeclaration createVertexDeclaration(const Array& element) = 0; virtual PVertexShader createVertexShader(const ShaderCreateInfo& createInfo) = 0; virtual PControlShader createControlShader(const ShaderCreateInfo& createInfo) = 0; virtual PEvaluationShader createEvaluationShader(const ShaderCreateInfo& createInfo) = 0; virtual PGeometryShader createGeometryShader(const ShaderCreateInfo& createInfo) = 0; virtual PFragmentShader createFragmentShader(const ShaderCreateInfo& createInfo) = 0; + virtual PComputeShader createComputeShader(const ShaderCreateInfo& createInfo) = 0; virtual PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) = 0; virtual PComputePipeline createComputePipeline(const ComputePipelineCreateInfo& createInfo) = 0; virtual PSamplerState createSamplerState(const SamplerCreateInfo& createInfo) = 0; @@ -54,6 +57,8 @@ public: virtual PDescriptorLayout createDescriptorLayout(const std::string& name = "") = 0; virtual PPipelineLayout createPipelineLayout() = 0; + virtual void copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) = 0; + PVertexBuffer getNullVertexBuffer(); protected: diff --git a/src/Engine/Graphics/GraphicsInitializer.h b/src/Engine/Graphics/GraphicsInitializer.h index 2be5ac1..750d1ee 100644 --- a/src/Engine/Graphics/GraphicsInitializer.h +++ b/src/Engine/Graphics/GraphicsInitializer.h @@ -59,7 +59,7 @@ struct BulkResourceData { uint32 size; uint8 *data; - Gfx::QueueType owner; + Gfx::QueueType owner = Gfx::QueueType::GRAPHICS; BulkResourceData() : size(0), data(nullptr), owner(Gfx::QueueType::GRAPHICS) { @@ -116,6 +116,15 @@ struct UniformBufferCreateInfo { } }; +struct StructuredBufferCreateInfo +{ + BulkResourceData resourceData; + uint8 bDynamic: 1; + StructuredBufferCreateInfo() + : resourceData(), bDynamic(0) + { + } +}; struct ShaderCreateInfo { //It's possible to input multiple source files for materials or vertexFactories @@ -208,6 +217,7 @@ DECLARE_NAME_REF(Gfx, ControlShader) DECLARE_NAME_REF(Gfx, EvaluationShader) DECLARE_NAME_REF(Gfx, GeometryShader) DECLARE_NAME_REF(Gfx, FragmentShader) +DECLARE_NAME_REF(Gfx, ComputeShader) DECLARE_NAME_REF(Gfx, PipelineLayout) DECLARE_NAME_REF(Gfx, RenderPass) struct GraphicsPipelineCreateInfo diff --git a/src/Engine/Graphics/GraphicsResources.cpp b/src/Engine/Graphics/GraphicsResources.cpp index 365270c..9f52931 100644 --- a/src/Engine/Graphics/GraphicsResources.cpp +++ b/src/Engine/Graphics/GraphicsResources.cpp @@ -109,7 +109,7 @@ void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorTyp descriptorBindings[bindingIndex] = binding; } -PDescriptorSet DescriptorLayout::allocatedDescriptorSet() +PDescriptorSet DescriptorLayout::allocateDescriptorSet() { PDescriptorSet result; allocator->allocateDescriptorSet(result); @@ -168,8 +168,14 @@ void QueueOwnedResource::transferOwnership(QueueType newOwner) if(mapping.needsTransfer(currentOwner, newOwner)) { executeOwnershipBarrier(newOwner); - currentOwner = newOwner; } + currentOwner = newOwner; +} + +void QueueOwnedResource::pipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess, SePipelineStageFlags dstStage) +{ + // maybe add some checks + executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); } Buffer::Buffer(QueueFamilyMapping mapping, QueueType startQueue) @@ -314,6 +320,16 @@ RenderCommand::~RenderCommand() { } +ComputeCommand::ComputeCommand() +{ + +} + +ComputeCommand::~ComputeCommand() +{ + +} + RenderTargetLayout::RenderTargetLayout() : inputAttachments() , colorAttachments() diff --git a/src/Engine/Graphics/GraphicsResources.h b/src/Engine/Graphics/GraphicsResources.h index 544c32d..344cc6f 100644 --- a/src/Engine/Graphics/GraphicsResources.h +++ b/src/Engine/Graphics/GraphicsResources.h @@ -148,14 +148,6 @@ private: }; DEFINE_REF(ShaderMap) -class ComputeShader -{ -public: - ComputeShader() {} - virtual ~ComputeShader() {} -}; -DEFINE_REF(ComputeShader) - class DescriptorBinding { public: @@ -233,7 +225,7 @@ public: virtual void create() = 0; virtual void addDescriptorBinding(uint32 binding, SeDescriptorType type, uint32 arrayCount = 1); virtual void reset(); - virtual PDescriptorSet allocatedDescriptorSet(); + virtual PDescriptorSet allocateDescriptorSet(); const Array &getBindings() const { return descriptorBindings; } inline uint32 getSetIndex() const { return setIndex; } @@ -301,9 +293,12 @@ public: //Preliminary checks to see if the barrier should be executed at all void transferOwnership(QueueType newOwner); + void pipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess, SePipelineStageFlags dstStage); protected: virtual void executeOwnershipBarrier(QueueType newOwner) = 0; + virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, + SeAccessFlags dstAccess, SePipelineStageFlags dstStage) = 0; Gfx::QueueType currentOwner; QueueFamilyMapping mapping; }; @@ -353,6 +348,8 @@ protected: Array contents; // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(QueueType newOwner) = 0; + virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, + SeAccessFlags dstAccess, SePipelineStageFlags dstStage) = 0; }; DEFINE_REF(UniformBuffer) @@ -374,6 +371,8 @@ public: protected: // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(QueueType newOwner) = 0; + virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, + SeAccessFlags dstAccess, SePipelineStageFlags dstStage) = 0; uint32 numVertices; uint32 vertexSize; }; @@ -396,6 +395,8 @@ public: protected: // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(QueueType newOwner) = 0; + virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, + SeAccessFlags dstAccess, SePipelineStageFlags dstStage) = 0; Gfx::SeIndexType indexType; uint32 numIndices; }; @@ -409,6 +410,8 @@ public: protected: // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(QueueType newOwner) = 0; + virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, + SeAccessFlags dstAccess, SePipelineStageFlags dstStage) = 0; }; DEFINE_REF(StructuredBuffer) @@ -480,10 +483,14 @@ public: virtual uint32 getSizeX() const = 0; virtual uint32 getSizeY() const = 0; virtual SeSampleCountFlags getNumSamples() const = 0; + virtual void changeLayout(SeImageLayout newLayout) = 0; virtual class Texture2D* getTexture2D() { return nullptr; } + virtual void* getNativeHandle() { return nullptr; } protected: // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(QueueType newOwner) = 0; + virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, + SeAccessFlags dstAccess, SePipelineStageFlags dstStage) = 0; }; DEFINE_REF(Texture) class Texture2D : public Texture @@ -496,10 +503,13 @@ public: virtual uint32 getSizeX() const = 0; virtual uint32 getSizeY() const = 0; virtual SeSampleCountFlags getNumSamples() const = 0; + virtual void changeLayout(SeImageLayout newLayout) = 0; virtual class Texture2D* getTexture2D() { return this; } protected: //Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(QueueType newOwner) = 0; + virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, + SeAccessFlags dstAccess, SePipelineStageFlags dstStage) = 0; }; DEFINE_REF(Texture2D) @@ -517,8 +527,22 @@ public: virtual void bindVertexBuffer(const Array& streams) = 0; virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) = 0; virtual void draw(const MeshBatchElement& data) = 0; + std::string name; }; DEFINE_REF(RenderCommand) +class ComputeCommand +{ +public: + ComputeCommand(); + virtual ~ComputeCommand(); + virtual bool isReady() = 0; + virtual void bindPipeline(Gfx::PComputePipeline pipeline) = 0; + virtual void bindDescriptor(Gfx::PDescriptorSet set) = 0; + virtual void bindDescriptor(const Array& sets) = 0; + virtual void dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) = 0; + std::string name; +}; +DEFINE_REF(ComputeCommand) class Window { diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index 821f4c9..ad52e46 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -38,7 +38,7 @@ void BasePassMeshProcessor::addMeshBatch( assert(collection != nullptr); for(uint32 i = 0; i < batch.elements.size(); ++i) { - Gfx::PDescriptorSet descriptorSet = primitiveLayout->allocatedDescriptorSet(); + Gfx::PDescriptorSet descriptorSet = primitiveLayout->allocateDescriptorSet(); descriptorSet->updateBuffer(0, batch.elements[i].uniformBuffer); descriptorSet->writeChanges(); cachedPrimitiveSets.add(descriptorSet); @@ -92,14 +92,12 @@ BasePass::BasePass(PRenderGraph renderGraph, const PScene scene, Gfx::PGraphics basePassLayout = graphics->createPipelineLayout(); lightLayout = graphics->createDescriptorLayout("LightLayout"); - lightLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - uniformInitializer.resourceData.size = sizeof(LightEnv); - uniformInitializer.resourceData.data = nullptr; - uniformInitializer.bDynamic = true; - lightUniform = graphics->createUniformBuffer(uniformInitializer); + lightLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); + lightLayout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); + lightLayout->addDescriptorBinding(2, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE); lightLayout->create(); basePassLayout->addDescriptorLayout(INDEX_LIGHT_ENV, lightLayout); - descriptorSets[INDEX_LIGHT_ENV] = lightLayout->allocatedDescriptorSet(); + descriptorSets[INDEX_LIGHT_ENV] = lightLayout->allocateDescriptorSet(); viewLayout = graphics->createDescriptorLayout("ViewLayout"); viewLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER); @@ -107,14 +105,9 @@ BasePass::BasePass(PRenderGraph renderGraph, const PScene scene, Gfx::PGraphics uniformInitializer.resourceData.data = (uint8*)&viewParams; uniformInitializer.bDynamic = true; viewParamBuffer = graphics->createUniformBuffer(uniformInitializer); - viewLayout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - uniformInitializer.resourceData.size = sizeof(ScreenToViewParameter); - uniformInitializer.resourceData.data = (uint8*)&screenToViewParams; - uniformInitializer.bDynamic = true; - screenToViewParamBuffer = graphics->createUniformBuffer(uniformInitializer); viewLayout->create(); basePassLayout->addDescriptorLayout(INDEX_VIEW_PARAMS, viewLayout); - descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocatedDescriptorSet(); + descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocateDescriptorSet(); primitiveLayout = graphics->createDescriptorLayout("PrimitiveLayout"); primitiveLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER); @@ -131,25 +124,16 @@ void BasePass::beginFrame() processor->clearCommands(); primitiveLayout->reset(); BulkResourceData uniformUpdate; - uniformUpdate.size = sizeof(LightEnv); - uniformUpdate.data = (uint8*)&scene->getLightEnvironment(); - lightUniform->updateContents(uniformUpdate); - descriptorSets[INDEX_LIGHT_ENV]->updateBuffer(0, lightUniform); - descriptorSets[INDEX_LIGHT_ENV]->writeChanges(); viewParams.viewMatrix = source->getViewMatrix(); viewParams.projectionMatrix = source->getProjectionMatrix(); viewParams.cameraPosition = Vector4(source->getCameraPosition(), 0); - screenToViewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix); - screenToViewParams.screenDimensions = Vector2(static_cast(viewport->getSizeX()), static_cast(viewport->getSizeY())); + viewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix); + viewParams.screenDimensions = Vector2(static_cast(viewport->getSizeX()), static_cast(viewport->getSizeY())); uniformUpdate.size = sizeof(ViewParameter); uniformUpdate.data = (uint8*)&viewParams; viewParamBuffer->updateContents(uniformUpdate); - uniformUpdate.size = sizeof(ScreenToViewParameter); - uniformUpdate.data = (uint8*)&screenToViewParams; - screenToViewParamBuffer->updateContents(uniformUpdate); descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(0, viewParamBuffer); - descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(1, screenToViewParamBuffer); descriptorSets[INDEX_VIEW_PARAMS]->writeChanges(); for(auto &&meshBatch : scene->getStaticMeshes()) { @@ -159,6 +143,17 @@ void BasePass::beginFrame() void BasePass::render() { + descriptorSets[INDEX_LIGHT_ENV]->updateBuffer(0, scene->getLightBuffer()); + + 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); + oLightGrid->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); + descriptorSets[INDEX_LIGHT_ENV]->updateBuffer(1, oLightIndexList); + descriptorSets[INDEX_LIGHT_ENV]->updateTexture(2, oLightGrid); + descriptorSets[INDEX_LIGHT_ENV]->writeChanges(); graphics->beginRenderPass(renderPass); for (auto &&meshBatch : scene->getStaticMeshes()) { @@ -184,6 +179,8 @@ void BasePass::createRenderPass() depthAttachment->loadOp = Gfx::SE_ATTACHMENT_LOAD_OP_LOAD; Gfx::PRenderTargetLayout layout = new Gfx::RenderTargetLayout(colorAttachment, depthAttachment); renderPass = graphics->createRenderPass(layout); + oLightIndexList = renderGraph->requestBuffer("LIGHTCULLING_OLIGHTLIST"); + oLightGrid = renderGraph->requestTexture("LIGHTCULLING_OLIGHTGRID"); } void BasePass::modifyRenderPassMacros(Map& defines) diff --git a/src/Engine/Graphics/RenderPass/BasePass.h b/src/Engine/Graphics/RenderPass/BasePass.h index a342b47..8ffbeca 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.h +++ b/src/Engine/Graphics/RenderPass/BasePass.h @@ -54,13 +54,13 @@ private: Gfx::PPipelineLayout basePassLayout; // Set 0: Light environment static constexpr uint32 INDEX_LIGHT_ENV = 0; + Gfx::PStructuredBuffer oLightIndexList; + Gfx::PTexture oLightGrid; Gfx::PDescriptorLayout lightLayout; - Gfx::PUniformBuffer lightUniform; // Set 1: viewParameter static constexpr uint32 INDEX_VIEW_PARAMS = 1; Gfx::PDescriptorLayout viewLayout; Gfx::PUniformBuffer viewParamBuffer; - Gfx::PUniformBuffer screenToViewParamBuffer; // Set 2: materials, generated static constexpr uint32 INDEX_MATERIAL = 2; // Set 3: primitive scene data diff --git a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp index f52fa2b..7e2bb5a 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp @@ -37,7 +37,7 @@ void DepthPrepassMeshProcessor::addMeshBatch( assert(collection != nullptr); for(uint32 i = 0; i < batch.elements.size(); ++i) { - Gfx::PDescriptorSet descriptorSet = primitiveLayout->allocatedDescriptorSet(); + Gfx::PDescriptorSet descriptorSet = primitiveLayout->allocateDescriptorSet(); descriptorSet->updateBuffer(0, batch.elements[i].uniformBuffer); descriptorSet->writeChanges(); cachedPrimitiveSets.add(descriptorSet); @@ -97,14 +97,9 @@ DepthPrepass::DepthPrepass(PRenderGraph renderGraph, const PScene scene, Gfx::PG uniformInitializer.resourceData.data = (uint8*)&viewParams; uniformInitializer.bDynamic = true; viewParamBuffer = graphics->createUniformBuffer(uniformInitializer); - viewLayout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - uniformInitializer.resourceData.size = sizeof(ScreenToViewParameter); - uniformInitializer.resourceData.data = (uint8*)&screenToViewParams; - uniformInitializer.bDynamic = true; - screenToViewParamBuffer = graphics->createUniformBuffer(uniformInitializer); viewLayout->create(); depthPrepassLayout->addDescriptorLayout(INDEX_VIEW_PARAMS, viewLayout); - descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocatedDescriptorSet(); + descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocateDescriptorSet(); primitiveLayout = graphics->createDescriptorLayout("PrimitiveLayout"); primitiveLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER); @@ -125,16 +120,12 @@ void DepthPrepass::beginFrame() viewParams.viewMatrix = source->getViewMatrix(); viewParams.projectionMatrix = source->getProjectionMatrix(); viewParams.cameraPosition = Vector4(source->getCameraPosition(), 0); - screenToViewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix); - screenToViewParams.screenDimensions = Vector2(static_cast(viewport->getSizeX()), static_cast(viewport->getSizeY())); + viewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix); + viewParams.screenDimensions = Vector2(static_cast(viewport->getSizeX()), static_cast(viewport->getSizeY())); uniformUpdate.size = sizeof(ViewParameter); uniformUpdate.data = (uint8*)&viewParams; viewParamBuffer->updateContents(uniformUpdate); - uniformUpdate.size = sizeof(ScreenToViewParameter); - uniformUpdate.data = (uint8*)&screenToViewParams; - screenToViewParamBuffer->updateContents(uniformUpdate); descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(0, viewParamBuffer); - descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(1, screenToViewParamBuffer); descriptorSets[INDEX_VIEW_PARAMS]->writeChanges(); for(auto &&meshBatch : scene->getStaticMeshes()) { @@ -144,6 +135,10 @@ void DepthPrepass::beginFrame() void DepthPrepass::render() { + depthAttachment->getTexture()->pipelineBarrier( + Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT); + depthAttachment->getTexture()->transferOwnership(Gfx::QueueType::GRAPHICS); graphics->beginRenderPass(renderPass); for (auto &&meshBatch : scene->getStaticMeshes()) { diff --git a/src/Engine/Graphics/RenderPass/DepthPrepass.h b/src/Engine/Graphics/RenderPass/DepthPrepass.h index 75b3f11..85247ff 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.h +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.h @@ -55,7 +55,6 @@ private: static constexpr uint32 INDEX_VIEW_PARAMS = 0; Gfx::PDescriptorLayout viewLayout; Gfx::PUniformBuffer viewParamBuffer; - Gfx::PUniformBuffer screenToViewParamBuffer; // Set 1: materials, generated static constexpr uint32 INDEX_MATERIAL = 1; // Set 2: primitive scene data diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp index 8dabda9..283fe4a 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp @@ -1,12 +1,15 @@ #include "LightCullingPass.h" #include "Graphics/Graphics.h" +#include "Scene/Scene.h" #include "Scene/Actor/CameraActor.h" #include "Scene/Components/CameraComponent.h" +#include "RenderGraph.h" using namespace Seele; -LightCullingPass::LightCullingPass(PRenderGraph renderGraph, Gfx::PViewport viewport, Gfx::PGraphics graphics, PCameraActor camera) +LightCullingPass::LightCullingPass(PRenderGraph renderGraph, const PScene scene, Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor camera) : RenderPass(renderGraph) + , scene(scene) , viewport(viewport) , graphics(graphics) , source(camera->getCameraComponent()) @@ -20,46 +23,58 @@ LightCullingPass::~LightCullingPass() void LightCullingPass::beginFrame() { - uint32_t viewportWidth = viewport->getSizeX(); - uint32_t viewportHeight = viewport->getSizeY(); + BulkResourceData uniformUpdate; + viewParams.viewMatrix = source->getViewMatrix(); + viewParams.projectionMatrix = source->getProjectionMatrix(); + viewParams.cameraPosition = Vector4(source->getCameraPosition(), 0); + viewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix); + viewParams.screenDimensions = Vector2(static_cast(viewport->getSizeX()), static_cast(viewport->getSizeY())); + uniformUpdate.size = sizeof(ViewParameter); + uniformUpdate.data = (uint8*)&viewParams; + viewParamsBuffer->updateContents(uniformUpdate); - glm::uvec3 numThreads = glm::ceil(glm::vec3(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1)); - glm::uvec3 numThreadGroups = glm::ceil(glm::vec3(numThreads.x / (float)BLOCK_SIZE, numThreads.y / (float)BLOCK_SIZE, 1)); - - dispatchParams.numThreads = numThreads; - dispatchParams.numThreadGroups = numThreadGroups; - ScreenToView screenToView; - screenToView.inverseProjection = glm::inverse(source->getProjectionMatrix()); - screenToView.screenDimensions = glm::vec2(viewportWidth, viewportHeight); - - frustumShader = renderDevice->createComputeShader(loadPlaintext("./_Game/shaders/ComputeFrustums.slang"), "computeFrustums"); - frustumDescriptorLayout = renderDevice->createDescriptorLayout(); - frustumDescriptorLayout->addDescriptorBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - frustumDescriptorLayout->addDescriptorBinding(1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - frustumDescriptorLayout->addDescriptorBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); - frustumLayout = renderDevice->createPipelineLayout(); - frustumLayout->addPushConstants(init::PushConstantRange(VK_SHADER_STAGE_COMPUTE_BIT, sizeof(DispatchParams), 0)); - frustumLayout->addDescriptorLayout(0, frustumDescriptorLayout); - frustumLayout->create(); - frustumShader->setPipelineLayout(frustumLayout); - RHIResourceCreateInfo frustumInfo; - frustumBuffer = renderDevice->createStructuredBuffer(sizeof(Frustum), sizeof(Frustum) * numThreads.x * numThreads.y * numThreads.z, BufferUsageFlags::BUF_UnorderedAccess, frustumInfo); - dispatchParamsBuffer = renderDevice->createUniformBuffer(&dispatchParams, sizeof(DispatchParams), UniformBuffer_MultiFrame); - screenToViewParams = renderDevice->createUniformBuffer(&screenToView, sizeof(ScreenToView), UniformBuffer_MultiFrame); - frustumDescriptorSet = frustumDescriptorLayout->allocateDescriptorSet(); - frustumDescriptorSet->updateBuffer(0, dispatchParamsBuffer); - frustumDescriptorSet->updateBuffer(1, screenToViewParams); - frustumDescriptorSet->updateBuffer(2, frustumBuffer); - frustumDescriptorSet->writeChanges(); - renderDevice->setComputeShader(frustumShader); - renderDevice->bindComputeDescriptors(frustumLayout, frustumDescriptorSet); - renderDevice->dispatchComputeShader(numThreadGroups.x, numThreadGroups.y, numThreadGroups.z); - renderDevice->pipelineBarrier(frustumBuffer, VK_ACCESS_SHADER_WRITE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + cullingDescriptorLayout->reset(); + lightEnvDescriptorLayout->reset(); + cullingDescriptorSet = cullingDescriptorLayout->allocateDescriptorSet(); + lightEnvDescriptorSet = lightEnvDescriptorLayout->allocateDescriptorSet(); + cullingDescriptorSet->updateBuffer(0, viewParamsBuffer); + cullingDescriptorSet->updateBuffer(1, dispatchParamsBuffer); + cullingDescriptorSet->updateBuffer(3, frustumBuffer); + cullingDescriptorSet->updateBuffer(4, oLightIndexCounter); + cullingDescriptorSet->updateBuffer(5, tLightIndexCounter); + cullingDescriptorSet->updateBuffer(6, oLightIndexList); + cullingDescriptorSet->updateBuffer(7, tLightIndexList); + cullingDescriptorSet->updateTexture(8, oLightGrid); + cullingDescriptorSet->updateTexture(9, tLightGrid); } void LightCullingPass::render() { - + oLightIndexList->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); + 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); + depthAttachment->pipelineBarrier( + Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + depthAttachment->changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL); + depthAttachment->transferOwnership(Gfx::QueueType::COMPUTE); + + cullingDescriptorSet->updateTexture(2, depthAttachment); + cullingDescriptorSet->writeChanges(); + lightEnvDescriptorSet->updateBuffer(0, scene->getLightBuffer()); + lightEnvDescriptorSet->writeChanges(); + Gfx::PComputeCommand computeCommand = graphics->createComputeCommand("CullingCommand"); + computeCommand->bindPipeline(cullingPipeline); + Array descriptorSets = {cullingDescriptorSet, lightEnvDescriptorSet}; + computeCommand->bindDescriptor(descriptorSets); + computeCommand->dispatch(dispatchParams.numThreadGroups.x, dispatchParams.numThreadGroups.y, dispatchParams.numThreadGroups.z); + Array commands = {computeCommand}; + graphics->executeCommands(commands); + depthAttachment->changeLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + depthAttachment->transferOwnership(Gfx::QueueType::GRAPHICS); } void LightCullingPass::endFrame() @@ -69,15 +84,172 @@ void LightCullingPass::endFrame() void LightCullingPass::publishOutputs() { - + setupFrustums(); + BulkResourceData resourceData; + StructuredBufferCreateInfo createInfo; + resourceData.size = sizeof(uint32); + resourceData.data = nullptr; + resourceData.owner = Gfx::QueueType::COMPUTE; + createInfo.bDynamic = false; + createInfo.resourceData = resourceData; + oLightIndexCounter = graphics->createStructuredBuffer(createInfo); + tLightIndexCounter = graphics->createStructuredBuffer(createInfo); + resourceData.size = sizeof(uint32_t) * dispatchParams.numThreadGroups.x * dispatchParams.numThreadGroups.y * dispatchParams.numThreadGroups.z * 1024; + oLightIndexList = graphics->createStructuredBuffer(createInfo); + tLightIndexList = graphics->createStructuredBuffer(createInfo); + renderGraph->registerBufferOutput("LIGHTCULLING_OLIGHTLIST", oLightIndexList); + renderGraph->registerBufferOutput("LIGHTCULLING_TLIGHTLIST", tLightIndexList); + TextureCreateInfo textureInfo; + textureInfo.width = dispatchParams.numThreadGroups.x; + textureInfo.height = dispatchParams.numThreadGroups.y; + textureInfo.format = Gfx::SE_FORMAT_R16G16_UINT; + textureInfo.usage = Gfx::SE_IMAGE_USAGE_STORAGE_BIT; + oLightGrid = graphics->createTexture2D(textureInfo); + tLightGrid = graphics->createTexture2D(textureInfo); + renderGraph->registerTextureOutput("LIGHTCULLING_OLIGHTGRID", oLightGrid); + renderGraph->registerTextureOutput("LIGHTCULLING_TLIGHTGRID", tLightGrid); } -void LightCullingPass::createRenderPass() + +void LightCullingPass::createRenderPass() { - + cullingDescriptorLayout = graphics->createDescriptorLayout("CullingLayout"); + + //ViewParams + cullingDescriptorLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + //Dispatchparams + cullingDescriptorLayout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + //DepthTexture + cullingDescriptorLayout->addDescriptorBinding(2, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE); + //Frustums + cullingDescriptorLayout->addDescriptorBinding(3, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); + //o_lightIndexCounter + cullingDescriptorLayout->addDescriptorBinding(4, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); + //t_lightIndexCounter + cullingDescriptorLayout->addDescriptorBinding(5, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); + //o_lightIndexList + cullingDescriptorLayout->addDescriptorBinding(6, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); + //t_lightIndexList + cullingDescriptorLayout->addDescriptorBinding(7, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); + //o_lightGrid + cullingDescriptorLayout->addDescriptorBinding(8, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE); + //t_lightGrid + cullingDescriptorLayout->addDescriptorBinding(9, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE); + + + lightEnvDescriptorLayout = graphics->createDescriptorLayout("LightEnv"); + //LightEnv + lightEnvDescriptorLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); + + cullingLayout = graphics->createPipelineLayout(); + cullingLayout->addDescriptorLayout(0, cullingDescriptorLayout); + cullingLayout->addDescriptorLayout(1, lightEnvDescriptorLayout); + cullingLayout->create(); + + ShaderCreateInfo createInfo; + createInfo.name = "Culling"; + + std::ifstream codeStream("./shaders/LightCulling.slang", std::ios::ate); + auto fileSize = codeStream.tellg(); + codeStream.seekg(0); + Array buffer(static_cast(fileSize)); + codeStream.read(buffer.data(), fileSize); + + createInfo.shaderCode.add(std::string(buffer.data())); + createInfo.entryPoint = "cullLights"; + createInfo.defines["INDEX_VIEW_PARAMS"] = "0"; + createInfo.defines["INDEX_LIGHT_ENV"] = "1"; + createInfo.defines["NUM_MATERIAL_TEXCOORDS"] = "0"; + cullingShader = graphics->createComputeShader(createInfo); + + ComputePipelineCreateInfo pipelineInfo; + pipelineInfo.computeShader = cullingShader; + pipelineInfo.pipelineLayout = cullingLayout; + cullingPipeline = graphics->createComputePipeline(pipelineInfo); + + depthAttachment = renderGraph->requestRenderTarget("DEPTHPREPASS_DEPTH")->getTexture(); } void LightCullingPass::modifyRenderPassMacros(Map& defines) { - +} + +void LightCullingPass::setupFrustums() +{ + uint32_t viewportWidth = viewport->getSizeX(); + uint32_t viewportHeight = viewport->getSizeY(); + + glm::uvec3 numThreads = glm::ceil(glm::vec3(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1)); + glm::uvec3 numThreadGroups = glm::ceil(glm::vec3(numThreads.x / (float)BLOCK_SIZE, numThreads.y / (float)BLOCK_SIZE, 1)); + + viewParams.viewMatrix = source->getViewMatrix(); + viewParams.projectionMatrix = source->getProjectionMatrix(); + viewParams.inverseProjectionMatrix = glm::inverse(source->getProjectionMatrix()); + viewParams.screenDimensions = glm::vec2(viewportWidth, viewportHeight); + viewParams.cameraPosition = Vector4(source->getCameraPosition(), 0); + dispatchParams.numThreads = numThreads; + dispatchParams.numThreadGroups = numThreadGroups; + + Gfx::PDescriptorLayout frustumDescriptorLayout = graphics->createDescriptorLayout("FrustumLayout"); + frustumDescriptorLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + frustumDescriptorLayout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + frustumDescriptorLayout->addDescriptorBinding(2, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); + frustumLayout = graphics->createPipelineLayout(); + frustumLayout->addDescriptorLayout(0, frustumDescriptorLayout); + frustumLayout->create(); + ShaderCreateInfo createInfo; + createInfo.name = "Frustum"; + + std::ifstream codeStream("./shaders/ComputeFrustums.slang", std::ios::ate); + auto fileSize = codeStream.tellg(); + codeStream.seekg(0); + Array buffer(static_cast(fileSize)); + codeStream.read(buffer.data(), fileSize); + + createInfo.shaderCode.add(std::string(buffer.data())); + createInfo.entryPoint = "computeFrustums"; + createInfo.defines["INDEX_VIEW_PARAMS"] = "0"; + frustumShader = graphics->createComputeShader(createInfo); + + + ComputePipelineCreateInfo pipelineInfo; + pipelineInfo.computeShader = frustumShader; + pipelineInfo.pipelineLayout = frustumLayout; + frustumPipeline = graphics->createComputePipeline(pipelineInfo); + + BulkResourceData resourceInfo; + UniformBufferCreateInfo uniformInfo; + resourceInfo.size = sizeof(ViewParameter); + resourceInfo.data = (uint8*)&viewParams; + resourceInfo.owner = Gfx::QueueType::COMPUTE; + uniformInfo.resourceData = resourceInfo; + uniformInfo.bDynamic = false; + viewParamsBuffer = graphics->createUniformBuffer(uniformInfo); + + resourceInfo.size = sizeof(DispatchParams); + resourceInfo.data = (uint8*)&dispatchParams; + uniformInfo.resourceData = resourceInfo; + uniformInfo.bDynamic = false; + dispatchParamsBuffer = graphics->createUniformBuffer(uniformInfo); + + StructuredBufferCreateInfo structuredInfo; + resourceInfo.size = sizeof(Frustum) * numThreads.x * numThreads.y * numThreads.z; + resourceInfo.data = nullptr; + structuredInfo.resourceData = resourceInfo; + structuredInfo.bDynamic = false; + frustumBuffer = graphics->createStructuredBuffer(structuredInfo); + + frustumDescriptorSet = frustumDescriptorLayout->allocateDescriptorSet(); + frustumDescriptorSet->updateBuffer(0, viewParamsBuffer); + frustumDescriptorSet->updateBuffer(1, dispatchParamsBuffer); + frustumDescriptorSet->updateBuffer(2, frustumBuffer); + frustumDescriptorSet->writeChanges(); + + Gfx::PComputeCommand command = graphics->createComputeCommand("FrustumCommand"); + command->bindPipeline(frustumPipeline); + command->bindDescriptor(frustumDescriptorSet); + command->dispatch(numThreadGroups.x, numThreadGroups.y, numThreadGroups.z); + Array commands = {command}; + graphics->executeCommands(commands); + frustumBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); } \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.h b/src/Engine/Graphics/RenderPass/LightCullingPass.h index 661a1a3..ea730d5 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.h +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.h @@ -1,16 +1,17 @@ #pragma once #include "RenderPass.h" +#include "Graphics/GraphicsResources.h" namespace Seele { DECLARE_REF(CameraActor) DECLARE_REF(CameraComponent) -DECLARE_NAME_REF(Gfx, Viewport) -DECLARE_NAME_REF(Gfx, Graphics) +DECLARE_REF(Scene) +DECLARE_REF(Viewport) class LightCullingPass : public RenderPass { public: - LightCullingPass(PRenderGraph renderGraph, Gfx::PViewport viewport, Gfx::PGraphics graphics, PCameraActor camera); + LightCullingPass(PRenderGraph renderGraph, const PScene scene, Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor camera); virtual ~LightCullingPass(); virtual void beginFrame() override; virtual void render() override; @@ -19,7 +20,9 @@ public: virtual void createRenderPass() override; static void modifyRenderPassMacros(Map& defines); private: + void setupFrustums(); static constexpr uint32 BLOCK_SIZE = 8; + static constexpr uint32 INDEX_LIGHT_ENV = 1; _declspec(align(16)) struct DispatchParams { glm::uvec3 numThreadGroups; @@ -39,13 +42,36 @@ private: { Plane planes[4]; }; - struct ScreenToView - { - Matrix4 inverseProjection; - Vector2 screenDimensions; - }; + + PScene scene; Gfx::PViewport viewport; Gfx::PGraphics graphics; + + Gfx::PStructuredBuffer frustumBuffer; + Gfx::PUniformBuffer dispatchParamsBuffer; + Gfx::PUniformBuffer viewParamsBuffer; + Gfx::PDescriptorSet frustumDescriptorSet; + Gfx::PComputeShader frustumShader; + Gfx::PPipelineLayout frustumLayout; + Gfx::PComputePipeline frustumPipeline; + + Gfx::PTexture2D depthAttachment; + //Gfx::PTexture2D depthComputeTexture; + Gfx::PStructuredBuffer frustums; + Gfx::PStructuredBuffer oLightIndexCounter; + Gfx::PStructuredBuffer tLightIndexCounter; + Gfx::PStructuredBuffer oLightIndexList; + Gfx::PStructuredBuffer tLightIndexList; + Gfx::PTexture2D oLightGrid; + Gfx::PTexture2D tLightGrid; + Gfx::PDescriptorSet lightEnvDescriptorSet; + Gfx::PDescriptorSet cullingDescriptorSet; + Gfx::PDescriptorLayout lightEnvDescriptorLayout; + Gfx::PDescriptorLayout cullingDescriptorLayout; + Gfx::PComputeShader cullingShader; + Gfx::PPipelineLayout cullingLayout; + Gfx::PComputePipeline cullingPipeline; PCameraComponent source; }; +DEFINE_REF(LightCullingPass) } // namespace Seele diff --git a/src/Engine/Graphics/RenderPass/RenderGraph.cpp b/src/Engine/Graphics/RenderPass/RenderGraph.cpp index 08441f2..192ce65 100644 --- a/src/Engine/Graphics/RenderPass/RenderGraph.cpp +++ b/src/Engine/Graphics/RenderPass/RenderGraph.cpp @@ -23,6 +23,11 @@ void RenderGraph::setup() } } +void RenderGraph::addRenderPass(PRenderPass renderPass) +{ + renderPasses.add(renderPass); +} + Gfx::PRenderTargetAttachment RenderGraph::requestRenderTarget(const std::string& outputName) { if(registeredAttachments.find(outputName) == registeredAttachments.end()) @@ -33,7 +38,38 @@ Gfx::PRenderTargetAttachment RenderGraph::requestRenderTarget(const std::string& return registeredAttachments[outputName]; } +Gfx::PTexture RenderGraph::requestTexture(const std::string& outputName) +{ + if(registeredTextures.find(outputName) == registeredTextures.end()) + { + std::cout << "Attachment " << outputName << " not found" << std::endl; + return nullptr; + } + return registeredTextures[outputName]; +} + + +Gfx::PStructuredBuffer RenderGraph::requestBuffer(const std::string& outputName) +{ + if(registeredBuffers.find(outputName) == registeredBuffers.end()) + { + std::cout << "Attachment " << outputName << " not found" << std::endl; + return nullptr; + } + return registeredBuffers[outputName]; +} + void RenderGraph::registerRenderPassOutput(const std::string& outputName, Gfx::PRenderTargetAttachment attachment) { registeredAttachments[outputName] = attachment; +} + +void RenderGraph::registerTextureOutput(const std::string& outputName, Gfx::PTexture texture) +{ + registeredTextures[outputName] = texture; +} + +void RenderGraph::registerBufferOutput(const std::string& outputName, Gfx::PStructuredBuffer buffer) +{ + registeredBuffers[outputName] = buffer; } \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/RenderGraph.h b/src/Engine/Graphics/RenderPass/RenderGraph.h index 27d3268..b8ea3e7 100644 --- a/src/Engine/Graphics/RenderPass/RenderGraph.h +++ b/src/Engine/Graphics/RenderPass/RenderGraph.h @@ -11,10 +11,17 @@ public: RenderGraph(); ~RenderGraph(); void setup(); + void addRenderPass(PRenderPass renderPass); Gfx::PRenderTargetAttachment requestRenderTarget(const std::string& outputName); - void registerRenderPassOutput(const std::string& ouputName, Gfx::PRenderTargetAttachment attachment); + Gfx::PTexture requestTexture(const std::string& outputName); + Gfx::PStructuredBuffer requestBuffer(const std::string& outputName); + void registerRenderPassOutput(const std::string& outputName, Gfx::PRenderTargetAttachment attachment); + void registerTextureOutput(const std::string& outputName, Gfx::PTexture buffer); + void registerBufferOutput(const std::string& outputName, Gfx::PStructuredBuffer buffer); private: Map registeredAttachments; + Map registeredTextures; + Map registeredBuffers; List renderPasses; }; DEFINE_REF(RenderGraph) diff --git a/src/Engine/Graphics/RenderPass/RenderPass.h b/src/Engine/Graphics/RenderPass/RenderPass.h index 75f3263..738360b 100644 --- a/src/Engine/Graphics/RenderPass/RenderPass.h +++ b/src/Engine/Graphics/RenderPass/RenderPass.h @@ -21,13 +21,10 @@ protected: { Matrix4 viewMatrix; Matrix4 projectionMatrix; - Vector4 cameraPosition; - } viewParams; - struct ScreenToViewParameter - { Matrix4 inverseProjectionMatrix; Vector2 screenDimensions; - } screenToViewParams; + Vector4 cameraPosition; + } viewParams; Gfx::PRenderPass renderPass; PRenderGraph renderGraph; }; diff --git a/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp index 97858ed..0ae3b5b 100644 --- a/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp @@ -16,21 +16,19 @@ struct PendingBuffer static Map pendingBuffers; -ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType) +ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic) : graphics(graphics) , currentBuffer(0) , size(size) - , currentOwner(queueType) + , owner(queueType) { - if (usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT || - usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT || - usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) - { - numBuffers = 1; - } - else + if(bDynamic) { numBuffers = Gfx::numFramesBuffered; + } + else + { + numBuffers = 1; } usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; @@ -63,7 +61,7 @@ ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags u ShaderBuffer::~ShaderBuffer() { - auto cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); + auto cmdBuffer = graphics->getQueueCommands(owner)->getCommands(); auto &deletionQueue = graphics->getDeletionQueue(); VkDevice device = graphics->getDevice(); VkBuffer buf[Gfx::numFramesBuffered]; @@ -85,25 +83,25 @@ void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { VkBufferMemoryBarrier barrier = init::BufferMemoryBarrier(); - PCommandBufferManager sourceManager = graphics->getQueueCommands(currentOwner); + PCommandBufferManager sourceManager = graphics->getQueueCommands(owner); PCommandBufferManager dstManager = nullptr; VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping(); - barrier.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(currentOwner); + barrier.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(owner); barrier.dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner); assert(barrier.srcQueueFamilyIndex != barrier.dstQueueFamilyIndex); - if (currentOwner == Gfx::QueueType::TRANSFER || currentOwner == Gfx::QueueType::DEDICATED_TRANSFER) + if (owner == Gfx::QueueType::TRANSFER || owner == Gfx::QueueType::DEDICATED_TRANSFER) { barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; } - else if (currentOwner == Gfx::QueueType::COMPUTE) + else if (owner == Gfx::QueueType::COMPUTE) { barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; srcStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; } - else if (currentOwner == Gfx::QueueType::GRAPHICS) + else if (owner == Gfx::QueueType::GRAPHICS) { barrier.srcAccessMask = getSourceAccessMask(); srcStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; @@ -135,17 +133,36 @@ void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) VkCommandBuffer srcCommand = sourceManager->getCommands()->getHandle(); VkCommandBuffer dstCommand = dstManager->getCommands()->getHandle(); VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered]; - for (uint32_t i = 0; i < numBuffers; ++i) + barrier.offset = 0; + barrier.size = size; + for (uint32 i = 0; i < numBuffers; ++i) { dynamicBarriers[i] = barrier; dynamicBarriers[i].buffer = buffers[i].buffer; - dynamicBarriers[i].offset = 0; - dynamicBarriers[i].size = size; } vkCmdPipelineBarrier(srcCommand, srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr); vkCmdPipelineBarrier(dstCommand, srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr); sourceManager->submitCommands(); - currentOwner = newOwner; +} + +void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) +{ + PCmdBuffer commandBuffer = graphics->getQueueCommands(owner)->getCommands(); + VkBufferMemoryBarrier barrier = init::BufferMemoryBarrier(); + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstAccessMask = dstAccess; + barrier.srcAccessMask = srcAccess; + barrier.offset = 0; + barrier.size = size; + VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered]; + for(uint32 i = 0; i < numBuffers; ++i) + { + dynamicBarriers[i] = barrier; + dynamicBarriers[i].buffer = buffers[i].buffer; + } + vkCmdPipelineBarrier(commandBuffer->getHandle(), srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr); } void *ShaderBuffer::lock(bool bWriteOnly) @@ -168,7 +185,7 @@ void *ShaderBuffer::lock(bool bWriteOnly) PendingBuffer pending; pending.bWriteOnly = bWriteOnly; - pending.prevQueue = currentOwner; + pending.prevQueue = owner; if (bWriteOnly) { //requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER); @@ -178,12 +195,12 @@ void *ShaderBuffer::lock(bool bWriteOnly) } else { - PCmdBuffer current = graphics->getQueueCommands(currentOwner)->getCommands(); - graphics->getQueueCommands(currentOwner)->submitCommands(); - graphics->getQueueCommands(currentOwner)->waitForCommands(current); + PCmdBuffer current = graphics->getQueueCommands(owner)->getCommands(); + graphics->getQueueCommands(owner)->submitCommands(); + current->waitForCommand(); requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER); - VkCommandBuffer handle = graphics->getQueueCommands(currentOwner)->getCommands()->getHandle(); + VkCommandBuffer handle = graphics->getQueueCommands(owner)->getCommands()->getHandle(); VkBufferMemoryBarrier barrier = init::BufferMemoryBarrier(); @@ -205,8 +222,8 @@ void *ShaderBuffer::lock(bool bWriteOnly) vkCmdCopyBuffer(handle, buffers[currentBuffer].buffer, stagingBuffer->getHandle(), 1, ®ions); - graphics->getQueueCommands(currentOwner)->submitCommands(); - vkQueueWaitIdle(graphics->getQueueCommands(currentOwner)->getQueue()->getHandle()); + graphics->getQueueCommands(owner)->submitCommands(); + vkQueueWaitIdle(graphics->getQueueCommands(owner)->getQueue()->getHandle()); stagingBuffer->flushMappedMemory(); pending.stagingBuffer = stagingBuffer; @@ -230,14 +247,14 @@ void ShaderBuffer::unlock() if (pending.bWriteOnly) { PStagingBuffer stagingBuffer = pending.stagingBuffer; - PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); + PCmdBuffer cmdBuffer = graphics->getQueueCommands(owner)->getCommands(); VkCommandBuffer cmdHandle = cmdBuffer->getHandle(); VkBufferCopy region; std::memset(®ion, 0, sizeof(VkBufferCopy)); region.size = size; vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion); - graphics->getQueueCommands(currentOwner)->submitCommands(); + graphics->getQueueCommands(owner)->submitCommands(); } //requestOwnershipTransfer(pending.prevQueue); graphics->getStagingManager()->releaseStagingBuffer(pending.stagingBuffer); @@ -246,7 +263,7 @@ void ShaderBuffer::unlock() UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &createInfo) : Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo.resourceData) - , Vulkan::ShaderBuffer(graphics, createInfo.resourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, createInfo.resourceData.owner) + , Vulkan::ShaderBuffer(graphics, createInfo.resourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, currentOwner, createInfo.bDynamic) , dedicatedStagingBuffer(nullptr) { if(createInfo.bDynamic) @@ -291,14 +308,14 @@ void UniformBuffer::unlock() if(dedicatedStagingBuffer != nullptr) { dedicatedStagingBuffer->flushMappedMemory(); - PCmdBuffer cmdBuffer = graphics->getQueueCommands(ShaderBuffer::currentOwner)->getCommands(); + PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); VkCommandBuffer cmdHandle = cmdBuffer->getHandle(); VkBufferCopy region; std::memset(®ion, 0, sizeof(VkBufferCopy)); region.size = ShaderBuffer::size; vkCmdCopyBuffer(cmdHandle, dedicatedStagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion); - graphics->getQueueCommands(ShaderBuffer::currentOwner)->submitCommands(); + graphics->getQueueCommands(currentOwner)->submitCommands(); } else { @@ -309,7 +326,6 @@ void UniformBuffer::unlock() void UniformBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { Gfx::QueueOwnedResource::transferOwnership(newOwner); - Vulkan::ShaderBuffer::currentOwner = newOwner; } void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) @@ -317,6 +333,12 @@ void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); } +void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) +{ + Vulkan::ShaderBuffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); +} + VkAccessFlags UniformBuffer::getSourceAccessMask() { return VK_ACCESS_MEMORY_WRITE_BIT; @@ -327,14 +349,14 @@ VkAccessFlags UniformBuffer::getDestAccessMask() return VK_ACCESS_UNIFORM_READ_BIT; } -StructuredBuffer::StructuredBuffer(PGraphics graphics, const BulkResourceData &resourceData) - : Gfx::StructuredBuffer(graphics->getFamilyMapping(), resourceData.owner) - , Vulkan::ShaderBuffer(graphics, resourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, resourceData.owner) +StructuredBuffer::StructuredBuffer(PGraphics graphics, const StructuredBufferCreateInfo &resourceData) + : Gfx::StructuredBuffer(graphics->getFamilyMapping(), resourceData.resourceData.owner) + , Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, currentOwner, resourceData.bDynamic) { - if (resourceData.data != nullptr) + if (resourceData.resourceData.data != nullptr) { void *data = lock(); - std::memcpy(data, resourceData.data, resourceData.size); + std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size); unlock(); } } @@ -353,6 +375,12 @@ void StructuredBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); } +void StructuredBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) +{ + Vulkan::ShaderBuffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); +} + VkAccessFlags StructuredBuffer::getSourceAccessMask() { return VK_ACCESS_MEMORY_WRITE_BIT; @@ -365,7 +393,7 @@ VkAccessFlags StructuredBuffer::getDestAccessMask() VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData) : Gfx::VertexBuffer(graphics->getFamilyMapping(), resourceData.numVertices, resourceData.vertexSize, resourceData.resourceData.owner) - , Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, resourceData.resourceData.owner) + , Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, currentOwner) { if (resourceData.resourceData.data != nullptr) { @@ -389,6 +417,12 @@ void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); } +void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) +{ + Vulkan::ShaderBuffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); +} + VkAccessFlags VertexBuffer::getSourceAccessMask() { return VK_ACCESS_MEMORY_WRITE_BIT; @@ -401,7 +435,7 @@ VkAccessFlags VertexBuffer::getDestAccessMask() IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData) : Gfx::IndexBuffer(graphics->getFamilyMapping(), resourceData.resourceData.size, resourceData.indexType, resourceData.resourceData.owner) - , Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, resourceData.resourceData.owner) + , Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, currentOwner) { if (resourceData.resourceData.data != nullptr) { @@ -425,6 +459,12 @@ void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); } +void IndexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) +{ + Vulkan::ShaderBuffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); +} + VkAccessFlags IndexBuffer::getSourceAccessMask() { return VK_ACCESS_MEMORY_WRITE_BIT; diff --git a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp index c2e7282..68e532d 100644 --- a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp @@ -84,20 +84,38 @@ void CmdBuffer::endRenderPass() state = State::InsideBegin; } -void CmdBuffer::executeCommands(Array commands) +void CmdBuffer::executeCommands(const Array& commands) { assert(state == State::RenderPassActive); Array cmdBuffers(commands.size()); for (uint32 i = 0; i < commands.size(); ++i) { - auto command = commands[i].cast(); + auto command = commands[i].cast(); // Cache array and size to save on pointer access for(auto boundDescriptor : command->boundDescriptors) { boundDescriptor->currentlyBound = this; } command->end(); - executingCommands.add(command); + executingRenders.add(command); + cmdBuffers[i] = command->getHandle(); + } + vkCmdExecuteCommands(handle, (uint32)cmdBuffers.size(), cmdBuffers.data()); +} + +void CmdBuffer::executeCommands(const Array& commands) +{ + Array cmdBuffers(commands.size()); + for (uint32 i = 0; i < commands.size(); ++i) + { + auto command = commands[i].cast(); + // Cache array and size to save on pointer access + for(auto boundDescriptor : command->boundDescriptors) + { + boundDescriptor->currentlyBound = this; + } + command->end(); + executingComputes.add(command); cmdBuffers[i] = command->getHandle(); } vkCmdExecuteCommands(handle, (uint32)cmdBuffers.size(), cmdBuffers.data()); @@ -117,11 +135,16 @@ void CmdBuffer::refreshFence() { vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); fence->reset(); - for(auto command : executingCommands) + for(auto command : executingComputes) { command->reset(); } - executingCommands.clear(); + executingComputes.clear(); + for(auto command : executingRenders) + { + command->reset(); + } + executingRenders.clear(); state = State::ReadyBegin; } } @@ -131,6 +154,13 @@ void CmdBuffer::refreshFence() } } +void CmdBuffer::waitForCommand(uint32 timeout) +{ + fence->wait(timeout); + refreshFence(); +} + + PFence CmdBuffer::getFence() { return fence; @@ -141,7 +171,7 @@ PCommandBufferManager CmdBuffer::getManager() return manager; } -SecondaryCmdBuffer::SecondaryCmdBuffer(PGraphics graphics, VkCommandPool cmdPool) +SecondaryCmdBuffer::SecondaryCmdBuffer(PGraphics graphics, VkCommandPool cmdPool) : CmdBufferBase(graphics, cmdPool) , ready(true) { @@ -152,27 +182,13 @@ SecondaryCmdBuffer::SecondaryCmdBuffer(PGraphics graphics, VkCommandPool cmdPool VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle)); } -SecondaryCmdBuffer::~SecondaryCmdBuffer() +SecondaryCmdBuffer::~SecondaryCmdBuffer() { vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle); } -void SecondaryCmdBuffer::begin(PCmdBuffer parent) -{ - ready = false; - VkCommandBufferBeginInfo beginInfo = - init::CommandBufferBeginInfo(); - VkCommandBufferInheritanceInfo inheritanceInfo = - init::CommandBufferInheritanceInfo(); - inheritanceInfo.framebuffer = parent->framebuffer->getHandle(); - inheritanceInfo.renderPass = parent->renderPass->getHandle(); - inheritanceInfo.subpass = parent->subpassIndex; - beginInfo.pInheritanceInfo = &inheritanceInfo; - beginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; - VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo)); -} -void SecondaryCmdBuffer::end() +void SecondaryCmdBuffer::end() { VK_CHECK(vkEndCommandBuffer(handle)); } @@ -188,12 +204,37 @@ void SecondaryCmdBuffer::reset() ready = true; } -bool SecondaryCmdBuffer::isReady() +RenderCommand::RenderCommand(PGraphics graphics, VkCommandPool cmdPool) + : SecondaryCmdBuffer(graphics, cmdPool) +{} + + +RenderCommand::~RenderCommand() +{ +} + +void RenderCommand::begin(PCmdBuffer parent) +{ + ready = false; + VkCommandBufferBeginInfo beginInfo = + init::CommandBufferBeginInfo(); + VkCommandBufferInheritanceInfo inheritanceInfo = + init::CommandBufferInheritanceInfo(); + inheritanceInfo.framebuffer = parent->framebuffer->getHandle(); + inheritanceInfo.renderPass = parent->renderPass->getHandle(); + inheritanceInfo.subpass = parent->subpassIndex; + beginInfo.pInheritanceInfo = &inheritanceInfo; + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; + VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo)); +} + + +bool RenderCommand::isReady() { return ready; } -void SecondaryCmdBuffer::setViewport(Gfx::PViewport viewport) +void RenderCommand::setViewport(Gfx::PViewport viewport) { VkViewport vp = viewport.cast()->getHandle(); VkRect2D scissors = init::Rect2D(viewport->getSizeX(), viewport->getSizeY(), viewport->getOffsetX(), viewport->getOffsetY()); @@ -201,19 +242,19 @@ void SecondaryCmdBuffer::setViewport(Gfx::PViewport viewport) vkCmdSetScissor(handle, 0, 1, &scissors); } -void SecondaryCmdBuffer::bindPipeline(Gfx::PGraphicsPipeline gfxPipeline) +void RenderCommand::bindPipeline(Gfx::PGraphicsPipeline gfxPipeline) { pipeline = gfxPipeline.cast(); pipeline->bind(handle); } -void SecondaryCmdBuffer::bindDescriptor(Gfx::PDescriptorSet descriptorSet) +void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) { auto descriptor = descriptorSet.cast(); boundDescriptors.add(descriptor.getHandle()); VkDescriptorSet setHandle = descriptor->getHandle(); vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), descriptorSet->getSetIndex(), 1, &setHandle, 0, nullptr); } -void SecondaryCmdBuffer::bindDescriptor(const Array& descriptorSets) +void RenderCommand::bindDescriptor(const Array& descriptorSets) { VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()]; for(uint32 i = 0; i < descriptorSets.size(); ++i) @@ -225,7 +266,7 @@ void SecondaryCmdBuffer::bindDescriptor(const Array& descri vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, 0, nullptr); delete[] sets; } -void SecondaryCmdBuffer::bindVertexBuffer(const Array& streams) +void RenderCommand::bindVertexBuffer(const Array& streams) { Array buffers(streams.size()); Array offsets(streams.size()); @@ -237,16 +278,76 @@ void SecondaryCmdBuffer::bindVertexBuffer(const Array& stream }; vkCmdBindVertexBuffers(handle, 0, (uint32)streams.size(), buffers.data(), offsets.data()); } -void SecondaryCmdBuffer::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) +void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) { PIndexBuffer buf = indexBuffer.cast(); vkCmdBindIndexBuffer(handle, buf->getHandle(), 0, cast(buf->getIndexType())); } -void SecondaryCmdBuffer::draw(const MeshBatchElement& data) +void RenderCommand::draw(const MeshBatchElement& data) { vkCmdDrawIndexed(handle, data.indexBuffer->getNumIndices(), data.numInstances, data.minVertexIndex, data.baseVertexIndex, 0); } +ComputeCommand::ComputeCommand(PGraphics graphics, VkCommandPool cmdPool) + : SecondaryCmdBuffer(graphics, cmdPool) +{ +} + +ComputeCommand::~ComputeCommand() +{ +} + +void ComputeCommand::begin(PCmdBuffer parent) +{ + ready = false; + VkCommandBufferBeginInfo beginInfo = + init::CommandBufferBeginInfo(); + VkCommandBufferInheritanceInfo inheritanceInfo = + init::CommandBufferInheritanceInfo(); + inheritanceInfo.framebuffer = VK_NULL_HANDLE; + inheritanceInfo.renderPass = VK_NULL_HANDLE; + inheritanceInfo.subpass = 0; + beginInfo.pInheritanceInfo = &inheritanceInfo; + VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo)); +} + +bool ComputeCommand::isReady() +{ + return ready; +} + +void ComputeCommand::bindPipeline(Gfx::PComputePipeline computePipeline) +{ + pipeline = computePipeline.cast(); + pipeline->bind(handle); +} + +void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) +{ + auto descriptor = descriptorSet.cast(); + boundDescriptors.add(descriptor.getHandle()); + VkDescriptorSet setHandle = descriptor->getHandle(); + vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), descriptorSet->getSetIndex(), 1, &setHandle, 0, nullptr); +} + +void ComputeCommand::bindDescriptor(const Array& descriptorSets) +{ + VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()]; + for(uint32 i = 0; i < descriptorSets.size(); ++i) + { + auto descriptorSet = descriptorSets[i].cast(); + boundDescriptors.add(descriptorSet.getHandle()); + sets[descriptorSet->getSetIndex()] = descriptorSet->getHandle(); + } + vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, 0, nullptr); + delete[] sets; +} + +void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) +{ + vkCmdDispatch(handle, threadX, threadY, threadZ); +} + CommandBufferManager::CommandBufferManager(PGraphics graphics, PQueue queue) : graphics(graphics), queue(queue), queueFamilyIndex(queue->getFamilyIndex()) { @@ -275,20 +376,40 @@ PCmdBuffer CommandBufferManager::getCommands() return activeCmdBuffer; } -PSecondaryCmdBuffer CommandBufferManager::createSecondaryCmdBuffer() +PRenderCommand CommandBufferManager::createRenderCommand(const std::string& name) { - std::scoped_lock lck(allocatedSecondBufferLock); - for (uint32 i = 0; i < allocatedSecondBuffers.size(); ++i) + std::scoped_lock lck(allocatedRenderLock); + for (uint32 i = 0; i < allocatedRenderCommands.size(); ++i) { - PSecondaryCmdBuffer cmdBuffer = allocatedSecondBuffers[i]; - if (cmdBuffer->isReady()) + PRenderCommand cmdBuffer = allocatedRenderCommands[i]; + if (cmdBuffer->ready) { cmdBuffer->begin(activeCmdBuffer); return cmdBuffer; } } - PSecondaryCmdBuffer result = new SecondaryCmdBuffer(graphics, commandPool); - allocatedSecondBuffers.add(result); + PRenderCommand result = new RenderCommand(graphics, commandPool); + result->name = name; + allocatedRenderCommands.add(result); + result->begin(activeCmdBuffer); + return result; +} + +PComputeCommand CommandBufferManager::createComputeCommand(const std::string& name) +{ + std::scoped_lock lck(allocatedComputeLock); + for (uint32 i = 0; i < allocatedComputeCommands.size(); ++i) + { + PComputeCommand cmdBuffer = allocatedComputeCommands[i]; + if (cmdBuffer->ready) + { + cmdBuffer->begin(activeCmdBuffer); + return cmdBuffer; + } + } + PComputeCommand result = new ComputeCommand(graphics, commandPool); + result->name = name; + allocatedComputeCommands.add(result); result->begin(activeCmdBuffer); return result; } @@ -332,9 +453,3 @@ void CommandBufferManager::submitCommands(PSemaphore signalSemaphore) allocatedBuffers.add(activeCmdBuffer); activeCmdBuffer->begin(); } - -void CommandBufferManager::waitForCommands(PCmdBuffer cmdBuffer, uint32 timeout) -{ - cmdBuffer->fence->wait(timeout); - cmdBuffer->refreshFence(); -} diff --git a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h index ee55923..4897254 100644 --- a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h +++ b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h @@ -29,7 +29,8 @@ protected: }; DEFINE_REF(CmdBufferBase) -DECLARE_REF(SecondaryCmdBuffer) +DECLARE_REF(RenderCommand) +DECLARE_REF(ComputeCommand) DECLARE_REF(CommandBufferManager) class CmdBuffer : public CmdBufferBase { @@ -40,9 +41,11 @@ public: void end(); void beginRenderPass(PRenderPass renderPass, PFramebuffer framebuffer); void endRenderPass(); - void executeCommands(Array secondaryCommands); + void executeCommands(const Array& secondaryCommands); + void executeCommands(const Array& secondaryCommands); void addWaitSemaphore(VkPipelineStageFlags stages, PSemaphore waitSemaphore); void refreshFence(); + void waitForCommand(uint32 timeToWait = 1000000u); PFence getFence(); PCommandBufferManager getManager(); enum State @@ -63,23 +66,40 @@ private: State state; Array waitSemaphores; Array waitFlags; - Array executingCommands; - friend class SecondaryCmdBuffer; + Array executingRenders; + Array executingComputes; + friend class RenderCommand; friend class CommandBufferManager; friend class Queue; }; DEFINE_REF(CmdBuffer) DECLARE_REF(GraphicsPipeline) +DECLARE_REF(ComputePipeline) DECLARE_REF(DescriptorSet) -class SecondaryCmdBuffer : public Gfx::RenderCommand, public CmdBufferBase + +class SecondaryCmdBuffer: public CmdBufferBase { public: SecondaryCmdBuffer(PGraphics graphics, VkCommandPool cmdPool); virtual ~SecondaryCmdBuffer(); - void begin(PCmdBuffer parent); + virtual void begin(PCmdBuffer parent) = 0; void end(); void reset(); + bool ready; + +protected: + Array boundDescriptors; + friend class CmdBuffer; +}; +DEFINE_REF(SecondaryCmdBuffer); + +class RenderCommand : public Gfx::RenderCommand, public SecondaryCmdBuffer +{ +public: + RenderCommand(PGraphics graphics, VkCommandPool cmdPool); + virtual ~RenderCommand(); + virtual void begin(PCmdBuffer parent) override; virtual bool isReady() override; virtual void setViewport(Gfx::PViewport viewport) override; virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) override; @@ -91,12 +111,26 @@ public: private: PGraphicsPipeline pipeline; - Array boundDescriptors; - bool ready; friend class CmdBuffer; }; -DEFINE_REF(SecondaryCmdBuffer) +DEFINE_REF(RenderCommand) +class ComputeCommand : public Gfx::ComputeCommand, public SecondaryCmdBuffer +{ +public: + ComputeCommand(PGraphics graphics, VkCommandPool cmdPool); + virtual ~ComputeCommand(); + virtual void begin(PCmdBuffer parent) override; + virtual bool isReady() override; + virtual void bindPipeline(Gfx::PComputePipeline pipeline) override; + virtual void bindDescriptor(Gfx::PDescriptorSet set) override; + virtual void bindDescriptor(const Array& sets) override; + virtual void dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) override; +private: + PComputePipeline pipeline; + friend class CmdBuffer; +}; +DEFINE_REF(ComputeCommand) class CommandBufferManager { public: @@ -107,9 +141,9 @@ public: return queue; } PCmdBuffer getCommands(); - PSecondaryCmdBuffer createSecondaryCmdBuffer(); + PRenderCommand createRenderCommand(const std::string& name); + PComputeCommand createComputeCommand(const std::string& name); void submitCommands(PSemaphore signalSemaphore = nullptr); - void waitForCommands(PCmdBuffer cmdBuffer, uint32 timeToWait = 1000000u); private: PGraphics graphics; @@ -119,8 +153,10 @@ private: PCmdBuffer activeCmdBuffer; std::mutex allocatedBufferLock; Array allocatedBuffers; - std::mutex allocatedSecondBufferLock; - Array allocatedSecondBuffers; + std::mutex allocatedRenderLock; + std::mutex allocatedComputeLock; + Array allocatedRenderCommands; + Array allocatedComputeCommands; }; DEFINE_REF(CommandBufferManager) } // namespace Vulkan diff --git a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp index 5fcf94f..aae194a 100644 --- a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp @@ -117,7 +117,7 @@ DescriptorSet::~DescriptorSet() void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer) { PUniformBuffer vulkanBuffer = uniformBuffer.cast(); - UniformBuffer* cachedBuffer = reinterpret_cast(cachedData[Gfx::currentFrameIndex][binding]); + UniformBuffer* cachedBuffer = reinterpret_cast(cachedData[binding]); /*if(vulkanBuffer->isDataEquals(cachedBuffer)) { std::cout << "uniform data equal, skip" << std::endl; @@ -125,32 +125,32 @@ void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBu }*/ bufferInfos.add(init::DescriptorBufferInfo(vulkanBuffer->getHandle(), 0, vulkanBuffer->getSize())); - VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle[Gfx::currentFrameIndex], VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, binding, &bufferInfos.back()); + VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, binding, &bufferInfos.back()); writeDescriptors.add(writeDescriptor); - cachedData[Gfx::currentFrameIndex][binding] = new UniformBuffer(*vulkanBuffer.getHandle()); + cachedData[binding] = new UniformBuffer(*vulkanBuffer.getHandle()); } void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PStructuredBuffer uniformBuffer) { PStructuredBuffer vulkanBuffer = uniformBuffer.cast(); - StructuredBuffer* cachedBuffer = reinterpret_cast(cachedData[Gfx::currentFrameIndex][binding]); + StructuredBuffer* cachedBuffer = reinterpret_cast(cachedData[binding]); if(vulkanBuffer.getHandle() == cachedBuffer) { return; } bufferInfos.add(init::DescriptorBufferInfo(vulkanBuffer->getHandle(), 0, vulkanBuffer->getSize())); - VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle[Gfx::currentFrameIndex], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, binding, &bufferInfos.back()); + VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, binding, &bufferInfos.back()); writeDescriptors.add(writeDescriptor); - cachedData[Gfx::currentFrameIndex][binding] = vulkanBuffer.getHandle(); + cachedData[binding] = vulkanBuffer.getHandle(); } void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSamplerState samplerState) { PSamplerState vulkanSampler = samplerState.cast(); - SamplerState* cachedSampler = reinterpret_cast(cachedData[Gfx::currentFrameIndex][binding]); + SamplerState* cachedSampler = reinterpret_cast(cachedData[binding]); if(vulkanSampler.getHandle() == cachedSampler) { return; @@ -162,16 +162,16 @@ void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSamplerState samplerSt VK_IMAGE_LAYOUT_UNDEFINED); imageInfos.add(imageInfo); - VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle[Gfx::currentFrameIndex], VK_DESCRIPTOR_TYPE_SAMPLER, binding, &imageInfos.back()); + VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle, VK_DESCRIPTOR_TYPE_SAMPLER, binding, &imageInfos.back()); writeDescriptors.add(writeDescriptor); - cachedData[Gfx::currentFrameIndex][binding] = vulkanSampler.getHandle(); + cachedData[binding] = vulkanSampler.getHandle(); } void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSamplerState samplerState) { TextureHandle* vulkanTexture = TextureBase::cast(texture); - TextureHandle* cachedTexture = reinterpret_cast(cachedData[Gfx::currentFrameIndex][binding]); + TextureHandle* cachedTexture = reinterpret_cast(cachedData[binding]); if(vulkanTexture == cachedTexture) { return; @@ -181,7 +181,7 @@ void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx:: init::DescriptorImageInfo( VK_NULL_HANDLE, vulkanTexture->getView(), - vulkanTexture->getLayout()); + cast(vulkanTexture->getLayout())); if (samplerState != nullptr) { PSamplerState vulkanSampler = samplerState.cast(); @@ -190,7 +190,7 @@ void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx:: imageInfos.add(imageInfo); VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet( - setHandle[Gfx::currentFrameIndex], + setHandle, samplerState != nullptr ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, binding, &imageInfos.back()); @@ -200,7 +200,7 @@ void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx:: } writeDescriptors.add(writeDescriptor); - cachedData[Gfx::currentFrameIndex][binding] = vulkanTexture; + cachedData[binding] = vulkanTexture; } bool DescriptorSet::operator<(Gfx::PDescriptorSet other) @@ -220,8 +220,8 @@ void DescriptorSet::writeChanges() { if(isCurrentlyBound()) { - graphics->getGraphicsCommands()->waitForCommands(currentlyBound); - currentlyBound = nullptr; + currentlyBound->waitForCommand(1000000000u); + assert(!isCurrentlyBound()); } vkUpdateDescriptorSets(graphics->getDevice(), (uint32)writeDescriptors.size(), writeDescriptors.data(), 0, nullptr); writeDescriptors.clear(); @@ -258,7 +258,11 @@ DescriptorAllocator::DescriptorAllocator(PGraphics graphics, DescriptorLayout &l poolSizes.add(size); } } - VkDescriptorPoolCreateInfo createInfo = init::DescriptorPoolCreateInfo((uint32)poolSizes.size(), poolSizes.data(), maxSets * Gfx::numFramesBuffered); + VkDescriptorPoolCreateInfo createInfo + = init::DescriptorPoolCreateInfo( + (uint32)poolSizes.size(), + poolSizes.data(), + maxSets * Gfx::numFramesBuffered); VK_CHECK(vkCreateDescriptorPool(graphics->getDevice(), &createInfo, nullptr, &poolHandle)); } @@ -271,14 +275,8 @@ DescriptorAllocator::~DescriptorAllocator() void DescriptorAllocator::allocateDescriptorSet(Gfx::PDescriptorSet &descriptorSet) { VkDescriptorSetLayout layoutHandle = layout.getHandle(); - VkDescriptorSetLayout layoutArray[Gfx::numFramesBuffered]; - for (uint32 i = 0; i < Gfx::numFramesBuffered; i++) - { - layoutArray[i] = layoutHandle; - } - VkDescriptorSetAllocateInfo allocInfo = - init::DescriptorSetAllocateInfo(poolHandle, layoutArray, Gfx::numFramesBuffered); + init::DescriptorSetAllocateInfo(poolHandle, &layoutHandle, 1); for(uint32 setIndex = 0; setIndex < cachedHandles.size(); ++setIndex) { @@ -290,18 +288,17 @@ void DescriptorAllocator::allocateDescriptorSet(Gfx::PDescriptorSet &descriptorS if(cachedHandles[setIndex]->getHandle() == VK_NULL_HANDLE) { //If it hasnt been initialized, allocate it - VK_CHECK(vkAllocateDescriptorSets(graphics->getDevice(), &allocInfo, cachedHandles[setIndex]->setHandle)); + VK_CHECK(vkAllocateDescriptorSets(graphics->getDevice(), &allocInfo, &cachedHandles[setIndex]->setHandle)); + } cachedHandles[setIndex]->currentlyInUse = true; descriptorSet = cachedHandles[setIndex]; PDescriptorSet vulkanSet = descriptorSet.cast(); - for(uint32 frameIndex = 0; frameIndex < Gfx::numFramesBuffered; ++frameIndex) - { - vulkanSet->cachedData[frameIndex].resize(layout.bindings.size()); - // Not really pretty, but this way the set knows which ones are valid - std::memset(vulkanSet->cachedData[frameIndex].data(), 0, sizeof(void*) * vulkanSet->cachedData[frameIndex].size()); - } + vulkanSet->cachedData.resize(layout.bindings.size()); + // Not really pretty, but this way the set knows which ones are valid + std::memset(vulkanSet->cachedData.data(), 0, sizeof(void*) * vulkanSet->cachedData.size()); + //Found set, stop searching return; } diff --git a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h index 1a265d2..1cc5407 100644 --- a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h +++ b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h @@ -60,9 +60,12 @@ class DescriptorSet : public Gfx::DescriptorSet { public: DescriptorSet(PGraphics graphics, PDescriptorAllocator owner) - : graphics(graphics), owner(owner), currentlyInUse(false), currentlyBound(nullptr) + : setHandle(VK_NULL_HANDLE) + , graphics(graphics) + , owner(owner) + , currentlyInUse(false) + , currentlyBound(nullptr) { - std::memset(setHandle, 0, sizeof(setHandle)); } virtual ~DescriptorSet(); virtual void writeChanges(); @@ -86,7 +89,7 @@ public: } inline VkDescriptorSet getHandle() const { - return setHandle[Gfx::currentFrameIndex]; + return setHandle; } virtual uint32 getSetIndex() const; @@ -97,8 +100,8 @@ private: // contains the previously bound resources at every binding // since the layout is fixed, trying to bind a texture to a buffer // would not work anyways, so casts should be safe - Array cachedData[Gfx::numFramesBuffered]; - VkDescriptorSet setHandle[Gfx::numFramesBuffered]; + Array cachedData; + VkDescriptorSet setHandle; PGraphics graphics; PDescriptorAllocator owner; PCmdBuffer currentlyBound; diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp b/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp index 843ed98..184010d 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp @@ -81,13 +81,19 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass) void Graphics::endRenderPass() { getGraphicsCommands()->getCommands()->endRenderPass(); + getGraphicsCommands()->submitCommands(); } -void Graphics::executeCommands(Array commands) +void Graphics::executeCommands(const Array& commands) { getGraphicsCommands()->getCommands()->executeCommands(commands); } +void Graphics::executeCommands(const Array& commands) +{ + getComputeCommands()->getCommands()->executeCommands(commands); +} + Gfx::PTexture2D Graphics::createTexture2D(const TextureCreateInfo &createInfo) { PTexture2D result = new Texture2D(this, createInfo); @@ -100,7 +106,7 @@ Gfx::PUniformBuffer Graphics::createUniformBuffer(const UniformBufferCreateInfo return uniformBuffer; } -Gfx::PStructuredBuffer Graphics::createStructuredBuffer(const BulkResourceData &bulkData) +Gfx::PStructuredBuffer Graphics::createStructuredBuffer(const StructuredBufferCreateInfo &bulkData) { PStructuredBuffer structuredBuffer = new StructuredBuffer(this, bulkData); return structuredBuffer; @@ -116,9 +122,15 @@ Gfx::PIndexBuffer Graphics::createIndexBuffer(const IndexBufferCreateInfo &bulkD PIndexBuffer indexBuffer = new IndexBuffer(this, bulkData); return indexBuffer; } -Gfx::PRenderCommand Graphics::createRenderCommand() +Gfx::PRenderCommand Graphics::createRenderCommand(const std::string& name) { - PSecondaryCmdBuffer cmdBuffer = getGraphicsCommands()->createSecondaryCmdBuffer(); + PRenderCommand cmdBuffer = getGraphicsCommands()->createRenderCommand(name); + return cmdBuffer; +} + +Gfx::PComputeCommand Graphics::createComputeCommand(const std::string& name) +{ + PComputeCommand cmdBuffer = getComputeCommands()->createComputeCommand(name); return cmdBuffer; } @@ -158,6 +170,13 @@ Gfx::PFragmentShader Graphics::createFragmentShader(const ShaderCreateInfo& crea shader->create(createInfo); return shader; } +Gfx::PComputeShader Graphics::createComputeShader(const ShaderCreateInfo& createInfo) +{ + PComputeShader shader = new ComputeShader(this); + shader->create(createInfo); + return shader; +} + Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) { PGraphicsPipeline pipeline = pipelineCache->createPipeline(createInfo); @@ -189,6 +208,73 @@ Gfx::PPipelineLayout Graphics::createPipelineLayout() return layout; } +void Graphics::copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) +{ + Texture2D* src = (Texture2D*)srcTexture->getTexture2D(); + Texture2D* dst = (Texture2D*)dstTexture->getTexture2D(); + TextureHandle* srcHandle = (TextureHandle*)src->getNativeHandle(); + TextureHandle* dstHandle = (TextureHandle*)dst->getNativeHandle(); + Gfx::SeImageLayout srcLayout = srcHandle->getLayout(); + Gfx::SeImageLayout dstLayout = dstHandle->getLayout(); + Gfx::QueueType dstOwner = dstHandle->currentOwner; + src->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + dst->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + dstTexture->transferOwnership(srcHandle->currentOwner); + PCmdBuffer cmdBuffer = getQueueCommands(srcHandle->currentOwner)->getCommands(); + if(srcHandle->getAspect() != dstHandle->getAspect()) + { + /*VkMemoryRequirements imageRequirements; + vkGetImageMemoryRequirements(handle, srcHandle->getImage(), &imageRequirements); + PStructuredBuffer tempBuffer = createStructuredBuffer(); + VkBufferImageCopy bufferImageCopy; + bufferImageCopy.bufferOffset = 0; + bufferImageCopy.bufferRowLength = srcTexture->getSizeX(); + bufferImageCopy.bufferImageHeight = srcTexture->getSizeY(); + bufferImageCopy.imageExtent.width = srcTexture->getSizeX(); + bufferImageCopy.imageExtent.height = srcTexture->getSizeY(); + bufferImageCopy.imageExtent.depth = 1; + bufferImageCopy.imageOffset.x = 0; + bufferImageCopy.imageOffset.y = 0; + bufferImageCopy.imageOffset.z = 0; + bufferImageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + bufferImageCopy.imageSubresource.baseArrayLayer = 0; + bufferImageCopy.imageSubresource.layerCount = 1; + bufferImageCopy.imageSubresource.mipLevel = 0; + + vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), srcHandle->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, tempBufferAllocation->getHandle(), 1, &bufferImageCopy); + + bufferImageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + + vkCmdCopyBufferToImage(cmdBuffer->getHandle(), tempBufferAllocation->getHandle(), dstHandle->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferImageCopy); + delete tempBufferAllocation;*/ + throw new std::logic_error("Not yet implemented!"); + } + else if (src->getSizeX() != dst->getSizeX() + || src->getSizeY() != dst->getSizeY()) + { + throw new std::logic_error("Not yet implemented!"); + } + else + { + VkImageCopy copy; + std::memset(©, 0, sizeof(VkImageCopy)); + copy.extent.width = srcTexture->getSizeX(); + copy.extent.height = srcTexture->getSizeY(); + copy.extent.depth = 1; + copy.srcSubresource.aspectMask = srcHandle->getAspect(); + copy.srcSubresource.layerCount = 1; + copy.dstSubresource.aspectMask = dstHandle->getAspect(); + copy.dstSubresource.layerCount = 1; + vkCmdCopyImage(cmdBuffer->getHandle(), + srcHandle->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + dstHandle->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, ©); + src->changeLayout(srcLayout); + dst->changeLayout(dstLayout); + dstTexture->transferOwnership(dstOwner); + } +} + VkInstance Graphics::getInstance() const { return instance; diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphics.h b/src/Engine/Graphics/Vulkan/VulkanGraphics.h index 7a3ab27..09d1507 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphics.h +++ b/src/Engine/Graphics/Vulkan/VulkanGraphics.h @@ -45,20 +45,23 @@ public: virtual void beginRenderPass(Gfx::PRenderPass renderPass) override; virtual void endRenderPass() override; - virtual void executeCommands(Array commands) override; + virtual void executeCommands(const Array& commands) override; + virtual void executeCommands(const Array& commands) override; virtual Gfx::PTexture2D createTexture2D(const TextureCreateInfo &createInfo) override; virtual Gfx::PUniformBuffer createUniformBuffer(const UniformBufferCreateInfo &bulkData) override; - virtual Gfx::PStructuredBuffer createStructuredBuffer(const BulkResourceData &bulkData) override; + virtual Gfx::PStructuredBuffer createStructuredBuffer(const StructuredBufferCreateInfo &bulkData) override; virtual Gfx::PVertexBuffer createVertexBuffer(const VertexBufferCreateInfo &bulkData) override; virtual Gfx::PIndexBuffer createIndexBuffer(const IndexBufferCreateInfo &bulkData) override; - virtual Gfx::PRenderCommand createRenderCommand() override; + virtual Gfx::PRenderCommand createRenderCommand(const std::string& name) override; + virtual Gfx::PComputeCommand createComputeCommand(const std::string& name) override; virtual Gfx::PVertexDeclaration createVertexDeclaration(const Array& element) override; virtual Gfx::PVertexShader createVertexShader(const ShaderCreateInfo& createInfo) override; virtual Gfx::PControlShader createControlShader(const ShaderCreateInfo& createInfo) override; virtual Gfx::PEvaluationShader createEvaluationShader(const ShaderCreateInfo& createInfo) override; virtual Gfx::PGeometryShader createGeometryShader(const ShaderCreateInfo& createInfo) override; virtual Gfx::PFragmentShader createFragmentShader(const ShaderCreateInfo& createInfo) override; + virtual Gfx::PComputeShader createComputeShader(const ShaderCreateInfo& createInfo) override; virtual Gfx::PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) override; virtual Gfx::PComputePipeline createComputePipeline(const ComputePipelineCreateInfo& createInfo) override; virtual Gfx::PSamplerState createSamplerState(const SamplerCreateInfo& createInfo) override; @@ -66,6 +69,7 @@ public: virtual Gfx::PDescriptorLayout createDescriptorLayout(const std::string& name = "") override; virtual Gfx::PPipelineLayout createPipelineLayout() override; + virtual void copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) override; protected: Array getRequiredExtensions(); void initInstance(GraphicsInitializer initInfo); diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.cpp b/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.cpp index b18e2a8..ddc6ecb 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.cpp @@ -1093,6 +1093,83 @@ Seele::Gfx::SeFormat Seele::Vulkan::cast(const VkFormat &format) return SE_FORMAT_MAX_ENUM; } } + +VkImageLayout Seele::Vulkan::cast(const Gfx::SeImageLayout &imageLayout) +{ + switch (imageLayout) + { + case SE_IMAGE_LAYOUT_UNDEFINED: + return VK_IMAGE_LAYOUT_UNDEFINED; + case SE_IMAGE_LAYOUT_GENERAL: + return VK_IMAGE_LAYOUT_GENERAL; + case SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + case SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + case SE_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: + return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + case SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + case SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + case SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + case SE_IMAGE_LAYOUT_PREINITIALIZED: + return VK_IMAGE_LAYOUT_PREINITIALIZED; + case SE_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: + return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL; + case SE_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: + return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL; + case SE_IMAGE_LAYOUT_PRESENT_SRC_KHR: + return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + case SE_IMAGE_LAYOUT_SHARED_PRESENT_KHR: + return VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR; + case SE_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV: + return VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV; + case SE_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT: + return VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT; + default: + return VK_IMAGE_LAYOUT_MAX_ENUM; + } +} +Gfx::SeImageLayout Seele::Vulkan::cast(const VkImageLayout &imageLayout) +{ + switch (imageLayout) + { + case VK_IMAGE_LAYOUT_UNDEFINED: + return SE_IMAGE_LAYOUT_UNDEFINED; + case VK_IMAGE_LAYOUT_GENERAL: + return SE_IMAGE_LAYOUT_GENERAL; + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + return SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + return SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: + return SE_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + return SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + return SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + return SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + case VK_IMAGE_LAYOUT_PREINITIALIZED: + return SE_IMAGE_LAYOUT_PREINITIALIZED; + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: + return SE_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL; + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: + return SE_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL; + case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: + return SE_IMAGE_LAYOUT_PRESENT_SRC_KHR; + case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR: + return SE_IMAGE_LAYOUT_SHARED_PRESENT_KHR; + case VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV: + return SE_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV; + case VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT: + return SE_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT; + default: + return SE_IMAGE_LAYOUT_MAX_ENUM; + } +} VkAttachmentStoreOp Seele::Vulkan::cast(const Gfx::SeAttachmentStoreOp &storeOp) { switch (storeOp) diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.h b/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.h index 51f73ab..e69297a 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.h +++ b/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.h @@ -34,6 +34,8 @@ VkShaderStageFlagBits cast(const Gfx::SeShaderStageFlagBits &stage); Gfx::SeShaderStageFlagBits cast(const VkShaderStageFlagBits &stage); VkFormat cast(const Gfx::SeFormat &format); Gfx::SeFormat cast(const VkFormat &format); +VkImageLayout cast(const Gfx::SeImageLayout &imageLayout); +Gfx::SeImageLayout cast(const VkImageLayout &imageLayout); VkAttachmentStoreOp cast(const Gfx::SeAttachmentStoreOp &storeOp); Gfx::SeAttachmentStoreOp cast(const VkAttachmentStoreOp &storeOp); VkAttachmentLoadOp cast(const Gfx::SeAttachmentLoadOp &loadOp); diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.cpp b/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.cpp index 90d9afd..007c34a 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.cpp @@ -49,7 +49,6 @@ void QueueOwnedResourceDeletion::run() } } - Semaphore::Semaphore(PGraphics graphics) : graphics(graphics) { diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h b/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h index 535de4a..0a9ebfa 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h +++ b/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h @@ -1,7 +1,7 @@ #pragma once #include -#include "Graphics/GraphicsResources.h" #include +#include "Graphics/GraphicsResources.h" namespace Seele { @@ -88,7 +88,7 @@ private: class ShaderBuffer { public: - ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType); + ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic = false); virtual ~ShaderBuffer(); VkBuffer getHandle() const { @@ -115,11 +115,14 @@ protected: PGraphics graphics; uint32 currentBuffer; uint32 size; - Gfx::QueueType currentOwner; + Gfx::QueueType& owner; BufferAllocation buffers[Gfx::numFramesBuffered]; uint32 numBuffers; void executeOwnershipBarrier(Gfx::QueueType newOwner); + void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); + virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) = 0; virtual VkAccessFlags getSourceAccessMask() = 0; @@ -139,11 +142,14 @@ public: virtual void unlock() override; protected: // Inherited via Vulkan::Buffer - virtual void requestOwnershipTransfer(Gfx::QueueType newOwner); virtual VkAccessFlags getSourceAccessMask(); virtual VkAccessFlags getDestAccessMask(); + virtual void requestOwnershipTransfer(Gfx::QueueType newOwner); // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(Gfx::QueueType newOwner); + virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); + private: PStagingBuffer dedicatedStagingBuffer; }; @@ -152,7 +158,7 @@ DEFINE_REF(UniformBuffer) class StructuredBuffer : public Gfx::StructuredBuffer, public ShaderBuffer { public: - StructuredBuffer(PGraphics graphics, const BulkResourceData &resourceData); + StructuredBuffer(PGraphics graphics, const StructuredBufferCreateInfo &resourceData); virtual ~StructuredBuffer(); protected: @@ -162,6 +168,10 @@ protected: virtual void requestOwnershipTransfer(Gfx::QueueType newOwner); // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(Gfx::QueueType newOwner); + virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); +private: + PStagingBuffer dedicatedStagingBuffer; }; DEFINE_REF(StructuredBuffer) @@ -178,6 +188,8 @@ protected: virtual void requestOwnershipTransfer(Gfx::QueueType newOwner); // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(Gfx::QueueType newOwner); + virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); }; DEFINE_REF(VertexBuffer) @@ -189,11 +201,13 @@ public: protected: // Inherited via Vulkan::Buffer - virtual void requestOwnershipTransfer(Gfx::QueueType newOwner); virtual VkAccessFlags getSourceAccessMask(); virtual VkAccessFlags getDestAccessMask(); + virtual void requestOwnershipTransfer(Gfx::QueueType newOwner); // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(Gfx::QueueType newOwner); + virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); }; DEFINE_REF(IndexBuffer) @@ -201,14 +215,18 @@ class TextureHandle { public: TextureHandle(PGraphics graphics, VkImageViewType viewType, - const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE); + const TextureCreateInfo& createInfo, Gfx::QueueType& owner, VkImage existingImage = VK_NULL_HANDLE); virtual ~TextureHandle(); + inline VkImage getImage() const + { + return image; + } inline VkImageView getView() const { return defaultView; } - inline VkImageLayout getLayout() const + inline Gfx::SeImageLayout getLayout() const { return layout; } @@ -233,10 +251,13 @@ public: return aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); } void executeOwnershipBarrier(Gfx::QueueType newOwner); - void changeLayout(VkImageLayout newLayout); + void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); + void changeLayout(Gfx::SeImageLayout newLayout); - Gfx::QueueType currentOwner; private: + //Updates via reference + Gfx::QueueType& currentOwner; PGraphics graphics; PSubAllocation allocation; uint32 sizeX; @@ -250,21 +271,22 @@ private: VkImage image; VkImageView defaultView; VkImageAspectFlags aspect; - VkImageLayout layout; + Gfx::SeImageLayout layout; friend class TextureBase; friend class Texture2D; + friend class Graphics; }; class TextureBase { public: static TextureHandle* cast(Gfx::PTexture texture); - void changeLayout(VkImageLayout newLayout); protected: TextureHandle* textureHandle; + friend class Graphics; }; - +DECLARE_REF(TextureBase) class Texture2D : public Gfx::Texture2D, public TextureBase { public: @@ -286,6 +308,11 @@ public: { return textureHandle->getNumSamples(); } + virtual void changeLayout(Gfx::SeImageLayout newLayout) override; + virtual void* getNativeHandle() override + { + return textureHandle; + } inline VkImage getHandle() const { return textureHandle->image; @@ -301,6 +328,8 @@ public: protected: // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(Gfx::QueueType newOwner); + virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); }; DEFINE_REF(Texture2D) diff --git a/src/Engine/Graphics/Vulkan/VulkanShader.cpp b/src/Engine/Graphics/Vulkan/VulkanShader.cpp index cf3ab4a..a712161 100644 --- a/src/Engine/Graphics/Vulkan/VulkanShader.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanShader.cpp @@ -120,6 +120,7 @@ void Shader::create(const ShaderCreateInfo& createInfo) char const* diagnostics = spGetDiagnosticOutput(request); std::cout << "Compile error for shader " << createInfo.name << std::endl; std::cout << diagnostics << std::endl; + return; } size_t dataSize = 0; const uint32* data = reinterpret_cast(spGetEntryPointCode(request, entryPointIndex, &dataSize)); diff --git a/src/Engine/Graphics/Vulkan/VulkanTexture.cpp b/src/Engine/Graphics/Vulkan/VulkanTexture.cpp index dd437b8..ee977f5 100644 --- a/src/Engine/Graphics/Vulkan/VulkanTexture.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanTexture.cpp @@ -30,8 +30,8 @@ VkImageAspectFlags getAspectFromFormat(Gfx::SeFormat format) } TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, - const TextureCreateInfo& createInfo, VkImage existingImage) - : currentOwner(createInfo.resourceData.owner) + const TextureCreateInfo& createInfo, Gfx::QueueType& owner, VkImage existingImage) + : currentOwner(owner) , graphics(graphics) , sizeX(createInfo.width) , sizeY(createInfo.height) @@ -43,7 +43,7 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, , usage(createInfo.usage) , image(existingImage) , aspect(getAspectFromFormat(createInfo.format)) - , layout(VK_IMAGE_LAYOUT_UNDEFINED) + , layout(Gfx::SE_IMAGE_LAYOUT_UNDEFINED) { if (existingImage == VK_NULL_HANDLE) { @@ -79,18 +79,18 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, break; } - info.initialLayout = layout; + info.initialLayout = cast(layout); info.mipLevels = mipLevels; info.arrayLayers = arrayCount * layerCount; info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; info.samples = (VkSampleCountFlagBits)samples; info.tiling = VK_IMAGE_TILING_OPTIMAL; info.usage = usage; - //To upload to the image we need to specify transfer dst - if(createInfo.resourceData.size > 0) - { - info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; - } + // Most of these flags will almost always be used + info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; + info.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT; + VK_CHECK(vkCreateImage(graphics->getDevice(), &info, nullptr, &image)); VkMemoryDedicatedRequirements memDedicatedRequirements; @@ -112,7 +112,7 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, const BulkResourceData& resourceData = createInfo.resourceData; if(resourceData.size > 0) { - changeLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); PStagingBuffer staging = graphics->getStagingManager()->allocateStagingBuffer(resourceData.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); void* data = staging->getMappedPointer(); std::memcpy(data, resourceData.data, resourceData.size); @@ -136,11 +136,15 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, staging->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); // When loading a texture from a file, we will almost always use it as a texture map for fragment shaders - changeLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + changeLayout(Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } - if(usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) + else if(usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - changeLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + changeLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + } + else + { + changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL); } VkImageViewCreateInfo viewInfo = @@ -176,17 +180,20 @@ TextureHandle* TextureBase::cast(Gfx::PTexture texture) return nullptr; } -void TextureHandle::changeLayout(VkImageLayout newLayout) +void TextureHandle::changeLayout(Gfx::SeImageLayout newLayout) { VkImageMemoryBarrier barrier = init::ImageMemoryBarrier( image, - layout, - newLayout); + cast(layout), + cast(newLayout)); + barrier.subresourceRange = + init::ImageSubresourceRange(aspect); PCommandBufferManager cmdManager = graphics->getQueueCommands(currentOwner); vkCmdPipelineBarrier(cmdManager->getCommands()->getHandle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier); + cmdManager->submitCommands(); layout = newLayout; } @@ -195,8 +202,8 @@ void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner) VkImageMemoryBarrier imageBarrier = init::ImageMemoryBarrier(); imageBarrier.image = image; - imageBarrier.oldLayout = layout; - imageBarrier.newLayout = layout; + imageBarrier.oldLayout = cast(layout); + imageBarrier.newLayout = cast(layout); imageBarrier.subresourceRange = init::ImageSubresourceRange(aspect); PCommandBufferManager sourceManager = graphics->getQueueCommands(currentOwner); PCommandBufferManager dstManager = nullptr; @@ -248,26 +255,49 @@ void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner) VkCommandBuffer destCmd = dstManager->getCommands()->getHandle(); vkCmdPipelineBarrier(sourceCmd, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &imageBarrier); vkCmdPipelineBarrier(destCmd, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &imageBarrier); + currentOwner = newOwner; sourceManager->submitCommands(); } -void TextureBase::changeLayout(VkImageLayout newLayout) +void TextureHandle::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { - textureHandle->changeLayout(newLayout); + VkImageMemoryBarrier imageBarrier = + init::ImageMemoryBarrier( + image, + cast(layout), + cast(layout) + ); + imageBarrier.srcAccessMask = srcAccess; + imageBarrier.dstAccessMask = dstAccess; + imageBarrier.subresourceRange = init::ImageSubresourceRange(aspect); + PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); + vkCmdPipelineBarrier(cmdBuffer->getHandle(), srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &imageBarrier); } Texture2D::Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage) : Gfx::Texture2D(graphics->getFamilyMapping(), createInfo.resourceData.owner) { textureHandle = new TextureHandle(graphics, createInfo.bArray ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D, - createInfo, existingImage); + createInfo, currentOwner, existingImage); } Texture2D::~Texture2D() { } +void Texture2D::changeLayout(Gfx::SeImageLayout newLayout) +{ + textureHandle->changeLayout(newLayout); +} + void Texture2D::executeOwnershipBarrier(Gfx::QueueType newOwner) { textureHandle->executeOwnershipBarrier(newOwner); +} + +void Texture2D::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) +{ + textureHandle->executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); } \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanViewport.cpp b/src/Engine/Graphics/Vulkan/VulkanViewport.cpp index f3b5f4e..cece238 100644 --- a/src/Engine/Graphics/Vulkan/VulkanViewport.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanViewport.cpp @@ -162,7 +162,7 @@ void Window::advanceBackBuffer() imageAcquiredSemaphore = imageAcquired[semaphoreIndex]; currentImageIndex = imageIndex; - backBufferImages[currentImageIndex]->changeLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + backBufferImages[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); PCmdBuffer cmdBuffer = graphics->getGraphicsCommands()->getCommands(); graphics->getGraphicsCommands()->getCommands()->addWaitSemaphore(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, imageAcquiredSemaphore); graphics->getGraphicsCommands()->submitCommands(); @@ -193,7 +193,7 @@ void Window::recreateSwapchain(const WindowCreateInfo &windowInfo) void Window::present() { - backBufferImages[currentImageIndex]->changeLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + backBufferImages[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_PRESENT_SRC_KHR); graphics->getGraphicsCommands()->submitCommands(renderFinished[currentImageIndex]); VkSemaphore renderFinishedHandle = renderFinished[currentImageIndex]->getHandle(); VkPresentInfoKHR info; @@ -258,7 +258,6 @@ void Window::createSwapchain() Array swapchainImages(numSwapchainImages); VK_CHECK(vkGetSwapchainImagesKHR(graphics->getDevice(), swapchain, &numSwapchainImages, swapchainImages.data())); - PCmdBuffer cmdBuffer = graphics->getGraphicsCommands()->getCommands(); TextureCreateInfo backBufferCreateInfo; backBufferCreateInfo.width = sizeX; @@ -274,10 +273,11 @@ void Window::createSwapchain() VkClearColorValue clearColor; std::memset(&clearColor, 0, sizeof(VkClearColorValue)); - backBufferImages[i]->changeLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + backBufferImages[i]->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); VkImageSubresourceRange range = init::ImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT); + PCmdBuffer cmdBuffer = graphics->getGraphicsCommands()->getCommands(); vkCmdClearColorImage(cmdBuffer->getHandle(), backBufferImages[i]->getHandle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1, &range); - backBufferImages[i]->changeLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + backBufferImages[i]->changeLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); } graphics->getGraphicsCommands()->submitCommands(); currentImageIndex = -1; diff --git a/src/Engine/Material/MaterialAsset.cpp b/src/Engine/Material/MaterialAsset.cpp index 4b386ad..cc332e3 100644 --- a/src/Engine/Material/MaterialAsset.cpp +++ b/src/Engine/Material/MaterialAsset.cpp @@ -32,7 +32,7 @@ void MaterialAsset::endFrame() void MaterialAsset::updateDescriptorData() { layout->reset(); - descriptorSet = layout->allocatedDescriptorSet(); + descriptorSet = layout->allocateDescriptorSet(); BulkResourceData uniformUpdate; uniformUpdate.size = uniformDataSize; uniformUpdate.data = uniformData; diff --git a/src/Engine/Material/ShaderExpression.cpp b/src/Engine/Material/ShaderExpression.cpp index d99cdae..78ed264 100644 --- a/src/Engine/Material/ShaderExpression.cpp +++ b/src/Engine/Material/ShaderExpression.cpp @@ -70,4 +70,19 @@ SamplerParameter::~SamplerParameter() void SamplerParameter::updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8*) { descriptorSet->updateSampler(binding, data); +} + +CombinedTextureParameter::CombinedTextureParameter(std::string name, uint32 byteOffset, uint32 binding) + : ShaderParameter(name, byteOffset, binding) +{ +} + +CombinedTextureParameter::~CombinedTextureParameter() +{ + +} + +void CombinedTextureParameter::updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) +{ + descriptorSet->updateTexture(binding, data->getTexture(), sampler); } \ No newline at end of file diff --git a/src/Engine/Material/ShaderExpression.h b/src/Engine/Material/ShaderExpression.h index eb6446e..3a5fdb2 100644 --- a/src/Engine/Material/ShaderExpression.h +++ b/src/Engine/Material/ShaderExpression.h @@ -60,5 +60,13 @@ struct SamplerParameter : public ShaderParameter virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) override; }; DEFINE_REF(SamplerParameter) - +struct CombinedTextureParameter : public ShaderParameter +{ + PTextureAsset data; + Gfx::PSamplerState sampler; + CombinedTextureParameter(std::string name, uint32 byteOffset, uint32 binding); + virtual ~CombinedTextureParameter(); + virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) override; +}; +DEFINE_REF(CombinedTextureParameter) } // namespace Seele diff --git a/src/Engine/Scene/Scene.cpp b/src/Engine/Scene/Scene.cpp index d29492b..d06ba7d 100644 --- a/src/Engine/Scene/Scene.cpp +++ b/src/Engine/Scene/Scene.cpp @@ -27,6 +27,14 @@ Scene::Scene(Gfx::PGraphics graphics) lightEnv.pointLights[i].positionWS = Vector4(frand() * 200-100, frand(), frand() * 200-100, 1); } lightEnv.numPointLights = MAX_POINT_LIGHTS; + + BulkResourceData lightInit; + StructuredBufferCreateInfo structuredInfo; + lightInit.size = sizeof(LightEnv); + lightInit.data = (uint8*)&lightEnv; + structuredInfo.resourceData = lightInit; + structuredInfo.bDynamic = false; + lightBuffer = graphics->createStructuredBuffer(structuredInfo); } Scene::~Scene() diff --git a/src/Engine/Scene/Scene.h b/src/Engine/Scene/Scene.h index 498fdfc..238eeef 100644 --- a/src/Engine/Scene/Scene.h +++ b/src/Engine/Scene/Scene.h @@ -46,13 +46,14 @@ public: const Array& getPrimitives() const { return primitives; } const Array& getStaticMeshes() const { return staticMeshes; } - const LightEnv& getLightEnvironment() const { return lightEnv; } + const Gfx::PStructuredBuffer& getLightBuffer() const { return lightBuffer; } UPSceneUpdater& getSceneUpdater() { return updater; } private: Array staticMeshes; Array rootActors; Array primitives; LightEnv lightEnv; + Gfx::PStructuredBuffer lightBuffer; Gfx::PGraphics graphics; UPSceneUpdater updater; }; diff --git a/src/Engine/Window/SceneRenderPath.cpp b/src/Engine/Window/SceneRenderPath.cpp index c1c4c30..d76610f 100644 --- a/src/Engine/Window/SceneRenderPath.cpp +++ b/src/Engine/Window/SceneRenderPath.cpp @@ -12,7 +12,11 @@ SceneRenderPath::SceneRenderPath(PScene scene, Gfx::PGraphics graphics, Gfx::PVi { renderGraph = new RenderGraph(); depthPrepass = new DepthPrepass(renderGraph, scene, graphics, target, source); + lightCullingPass = new LightCullingPass(renderGraph, scene, graphics, target, source); basePass = new BasePass(renderGraph, scene, graphics, target, source); + renderGraph->addRenderPass(depthPrepass); + renderGraph->addRenderPass(lightCullingPass); + renderGraph->addRenderPass(basePass); renderGraph->setup(); } @@ -33,14 +37,20 @@ void SceneRenderPath::init() void SceneRenderPath::beginFrame() { depthPrepass->beginFrame(); + lightCullingPass->beginFrame(); + basePass->beginFrame(); } void SceneRenderPath::render() { depthPrepass->render(); + lightCullingPass->render(); + basePass->render(); } void SceneRenderPath::endFrame() { depthPrepass->endFrame(); + lightCullingPass->endFrame(); + basePass->endFrame(); } diff --git a/src/Engine/Window/SceneRenderPath.h b/src/Engine/Window/SceneRenderPath.h index ac3d9fb..c4ee5ec 100644 --- a/src/Engine/Window/SceneRenderPath.h +++ b/src/Engine/Window/SceneRenderPath.h @@ -1,7 +1,8 @@ #pragma once #include "RenderPath.h" -#include "Graphics/RenderPass/BasePass.h" #include "Graphics/RenderPass/DepthPrepass.h" +#include "Graphics/RenderPass/LightCullingPass.h" +#include "Graphics/RenderPass/BasePass.h" namespace Seele { @@ -22,6 +23,7 @@ protected: PScene scene; PRenderGraph renderGraph; PDepthPrepass depthPrepass; + PLightCullingPass lightCullingPass; PBasePass basePass; };