diff --git a/src/rendering/vulkan/renderer/vk_renderpass.cpp b/src/rendering/vulkan/renderer/vk_renderpass.cpp index 414d221567..a82284027f 100644 --- a/src/rendering/vulkan/renderer/vk_renderpass.cpp +++ b/src/rendering/vulkan/renderer/vk_renderpass.cpp @@ -17,8 +17,6 @@ VkRenderPassManager::VkRenderPassManager() void VkRenderPassManager::Init() { CreateDynamicSetLayout(); - CreateTextureSetLayout(); - CreatePipelineLayout(); CreateDescriptorPool(); CreateDynamicSet(); } @@ -91,25 +89,42 @@ void VkRenderPassManager::CreateDynamicSetLayout() DynamicSetLayout->SetDebugName("VkRenderPassManager.DynamicSetLayout"); } -void VkRenderPassManager::CreateTextureSetLayout() +VulkanDescriptorSetLayout *VkRenderPassManager::GetTextureSetLayout(int numLayers) { + if (TextureSetLayouts.size() < (size_t)numLayers) + TextureSetLayouts.resize(numLayers); + + auto &layout = TextureSetLayouts[numLayers - 1]; + if (layout) + return layout.get(); + DescriptorSetLayoutBuilder builder; - for (int i = 0; i < 6; i++) + for (int i = 0; i < numLayers; i++) { builder.addBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); } - TextureSetLayout = builder.create(GetVulkanFrameBuffer()->device); - TextureSetLayout->SetDebugName("VkRenderPassManager.TextureSetLayout"); + layout = builder.create(GetVulkanFrameBuffer()->device); + layout->SetDebugName("VkRenderPassManager.TextureSetLayout"); + return layout.get(); } -void VkRenderPassManager::CreatePipelineLayout() +VulkanPipelineLayout* VkRenderPassManager::GetPipelineLayout(int numLayers) { + if (PipelineLayouts.size() <= (size_t)numLayers) + PipelineLayouts.resize(numLayers + 1); + + auto &layout = PipelineLayouts[numLayers]; + if (layout) + return layout.get(); + PipelineLayoutBuilder builder; builder.addSetLayout(DynamicSetLayout.get()); - builder.addSetLayout(TextureSetLayout.get()); + if (numLayers != 0) + builder.addSetLayout(GetTextureSetLayout(numLayers)); builder.addPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants)); - PipelineLayout = builder.create(GetVulkanFrameBuffer()->device); - PipelineLayout->SetDebugName("VkRenderPassManager.PipelineLayout"); + layout = builder.create(GetVulkanFrameBuffer()->device); + layout->SetDebugName("VkRenderPassManager.PipelineLayout"); + return layout.get(); } void VkRenderPassManager::CreateDescriptorPool() @@ -145,8 +160,6 @@ void VkRenderPassManager::UpdateDynamicSet() std::unique_ptr VkRenderPassManager::AllocateTextureDescriptorSet(int numLayers) { - numLayers = 6; // To do: remove this and create a TextureSetLayout for each amount to support custom materials - if (TextureDescriptorSetsLeft == 0 || TextureDescriptorsLeft < numLayers) { TextureDescriptorSetsLeft = 1000; @@ -161,7 +174,7 @@ std::unique_ptr VkRenderPassManager::AllocateTextureDescrip TextureDescriptorSetsLeft--; TextureDescriptorsLeft -= numLayers; - return TextureDescriptorPools.back()->allocate(TextureSetLayout.get()); + return TextureDescriptorPools.back()->allocate(GetTextureSetLayout(numLayers)); } ///////////////////////////////////////////////////////////////////////////// @@ -302,7 +315,7 @@ void VkRenderPassSetup::CreatePipeline(const VkRenderPassKey &key) builder.setSubpassColorAttachmentCount(key.DrawBuffers); builder.setRasterizationSamples((VkSampleCountFlagBits)key.Samples); - builder.setLayout(fb->GetRenderPassManager()->PipelineLayout.get()); + builder.setLayout(fb->GetRenderPassManager()->GetPipelineLayout(key.NumTextureLayers)); builder.setRenderPass(RenderPass.get()); Pipeline = builder.create(fb->device); Pipeline->SetDebugName("VkRenderPassSetup.Pipeline"); diff --git a/src/rendering/vulkan/renderer/vk_renderpass.h b/src/rendering/vulkan/renderer/vk_renderpass.h index 0cd966428e..ddd6997523 100644 --- a/src/rendering/vulkan/renderer/vk_renderpass.h +++ b/src/rendering/vulkan/renderer/vk_renderpass.h @@ -31,6 +31,7 @@ public: int Samples; int ClearTargets; int DrawBuffers; + int NumTextureLayers; bool UsesDepthStencil() const { return DepthTest || DepthWrite || StencilTest || (ClearTargets & (CT_Depth | CT_Stencil)); } @@ -76,10 +77,9 @@ public: int GetVertexFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs); std::unique_ptr AllocateTextureDescriptorSet(int numLayers); + VulkanPipelineLayout* GetPipelineLayout(int numLayers); std::unique_ptr DynamicSetLayout; - std::unique_ptr TextureSetLayout; - std::unique_ptr PipelineLayout; std::map> RenderPassSetup; std::unique_ptr DynamicSet; @@ -88,13 +88,15 @@ public: private: void CreateDynamicSetLayout(); - void CreateTextureSetLayout(); - void CreatePipelineLayout(); void CreateDescriptorPool(); void CreateDynamicSet(); + VulkanDescriptorSetLayout *GetTextureSetLayout(int numLayers); + int TextureDescriptorSetsLeft = 0; int TextureDescriptorsLeft = 0; std::vector> TextureDescriptorPools; std::unique_ptr DynamicDescriptorPool; + std::vector> TextureSetLayouts; + std::vector> PipelineLayouts; }; diff --git a/src/rendering/vulkan/renderer/vk_renderstate.cpp b/src/rendering/vulkan/renderer/vk_renderstate.cpp index c71ad49fbe..4ed4b3ee51 100644 --- a/src/rendering/vulkan/renderer/vk_renderstate.cpp +++ b/src/rendering/vulkan/renderer/vk_renderstate.cpp @@ -202,6 +202,7 @@ void VkRenderState::ApplyRenderPass(int dt) passKey.CullMode = mCullMode; passKey.Samples = mRenderTarget.Samples; passKey.DrawBuffers = mRenderTarget.DrawBuffers; + passKey.NumTextureLayers = mMaterial.mMaterial ? mMaterial.mMaterial->GetLayers() : 0; if (mSpecialEffect > EFF_NONE) { passKey.SpecialEffect = mSpecialEffect; @@ -417,7 +418,7 @@ void VkRenderState::ApplyPushConstants() auto fb = GetVulkanFrameBuffer(); auto passManager = fb->GetRenderPassManager(); - mCommandBuffer->pushConstants(passManager->PipelineLayout.get(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &mPushConstants); + mCommandBuffer->pushConstants(passManager->GetPipelineLayout(mRenderPassKey.NumTextureLayers), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &mPushConstants); } template @@ -499,7 +500,7 @@ void VkRenderState::ApplyMaterial() { auto fb = GetVulkanFrameBuffer(); auto passManager = fb->GetRenderPassManager(); - mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->PipelineLayout.get(), 1, base->GetDescriptorSet(mMaterial)); + mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mRenderPassKey.NumTextureLayers), 1, base->GetDescriptorSet(mMaterial)); } if (mMaterial.mMaterial && mMaterial.mMaterial->tex) @@ -517,7 +518,7 @@ void VkRenderState::ApplyDynamicSet() auto passManager = fb->GetRenderPassManager(); uint32_t offsets[4] = { mViewpointOffset, mLightBufferOffset, mMatricesOffset, mStreamDataOffset }; - mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->PipelineLayout.get(), 0, passManager->DynamicSet.get(), 4, offsets); + mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mRenderPassKey.NumTextureLayers), 0, passManager->DynamicSet.get(), 4, offsets); mLastViewpointOffset = mViewpointOffset; mLastLightBufferOffset = mLightBufferOffset;