diff --git a/src/rendering/vulkan/renderer/vk_renderpass.cpp b/src/rendering/vulkan/renderer/vk_renderpass.cpp index a90c825e81..7567ee90fa 100644 --- a/src/rendering/vulkan/renderer/vk_renderpass.cpp +++ b/src/rendering/vulkan/renderer/vk_renderpass.cpp @@ -215,17 +215,25 @@ VulkanDescriptorSet* VkRenderPassManager::GetNullTextureDescriptorSet() { if (!NullTextureDescriptorSet) { - NullTextureDescriptorSet = AllocateTextureDescriptorSet(1); + NullTextureDescriptorSet = AllocateTextureDescriptorSet(SHADER_MIN_REQUIRED_TEXTURE_LAYERS); auto fb = GetVulkanFrameBuffer(); WriteDescriptors update; - update.addCombinedImageSampler(NullTextureDescriptorSet.get(), 0, NullTextureView.get(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + for (int i = 0; i < SHADER_MIN_REQUIRED_TEXTURE_LAYERS; i++) + { + update.addCombinedImageSampler(NullTextureDescriptorSet.get(), i, NullTextureView.get(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + } update.updateSets(fb->device); } return NullTextureDescriptorSet.get(); } +VulkanImageView* VkRenderPassManager::GetNullTextureView() +{ + return NullTextureView.get(); +} + void VkRenderPassManager::UpdateDynamicSet() { auto fb = GetVulkanFrameBuffer(); diff --git a/src/rendering/vulkan/renderer/vk_renderpass.h b/src/rendering/vulkan/renderer/vk_renderpass.h index 37fd05ed66..c2c3b3e8e1 100644 --- a/src/rendering/vulkan/renderer/vk_renderpass.h +++ b/src/rendering/vulkan/renderer/vk_renderpass.h @@ -94,6 +94,7 @@ public: VulkanPipelineLayout* GetPipelineLayout(int numLayers); VulkanDescriptorSet* GetNullTextureDescriptorSet(); + VulkanImageView* GetNullTextureView(); std::unique_ptr DynamicSetLayout; std::map> RenderPassSetup; diff --git a/src/rendering/vulkan/renderer/vk_renderstate.cpp b/src/rendering/vulkan/renderer/vk_renderstate.cpp index b0851f1176..f5cc42e76a 100644 --- a/src/rendering/vulkan/renderer/vk_renderstate.cpp +++ b/src/rendering/vulkan/renderer/vk_renderstate.cpp @@ -228,7 +228,8 @@ void VkRenderState::ApplyRenderPass(int dt) pipelineKey.StencilPassOp = mStencilOp; pipelineKey.ColorMask = mColorMask; pipelineKey.CullMode = mCullMode; - pipelineKey.NumTextureLayers = mMaterial.mMaterial ? mMaterial.mMaterial->GetLayers() : 4; // Always force minimum 1 texture as the shader requires it + pipelineKey.NumTextureLayers = mMaterial.mMaterial ? mMaterial.mMaterial->GetLayers() : 0; + pipelineKey.NumTextureLayers = std::max(pipelineKey.NumTextureLayers, SHADER_MIN_REQUIRED_TEXTURE_LAYERS);// Always force minimum 8 textures as the shader requires it if (mSpecialEffect > EFF_NONE) { pipelineKey.SpecialEffect = mSpecialEffect; diff --git a/src/rendering/vulkan/shaders/vk_shader.h b/src/rendering/vulkan/shaders/vk_shader.h index feb897ef00..a9936293c0 100644 --- a/src/rendering/vulkan/shaders/vk_shader.h +++ b/src/rendering/vulkan/shaders/vk_shader.h @@ -8,6 +8,8 @@ #include "name.h" #include "hwrenderer/scene/hw_renderstate.h" +#define SHADER_MIN_REQUIRED_TEXTURE_LAYERS 8 + class VulkanDevice; class VulkanShader; diff --git a/src/rendering/vulkan/textures/vk_hwtexture.cpp b/src/rendering/vulkan/textures/vk_hwtexture.cpp index d91807206b..c8784b6c5b 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/rendering/vulkan/textures/vk_hwtexture.cpp @@ -33,6 +33,7 @@ #include "vulkan/renderer/vk_renderpass.h" #include "vulkan/renderer/vk_postprocess.h" #include "vulkan/renderer/vk_renderbuffers.h" +#include "vulkan/shaders/vk_shader.h" #include "vk_hwtexture.h" VkHardwareTexture *VkHardwareTexture::First = nullptr; @@ -144,7 +145,7 @@ VulkanDescriptorSet *VkHardwareTexture::GetDescriptorSet(const FMaterialState &s int numLayers = mat->GetLayers(); auto fb = GetVulkanFrameBuffer(); - auto descriptor = fb->GetRenderPassManager()->AllocateTextureDescriptorSet(numLayers); + auto descriptor = fb->GetRenderPassManager()->AllocateTextureDescriptorSet(std::max(numLayers, SHADER_MIN_REQUIRED_TEXTURE_LAYERS)); descriptor->SetDebugName("VkHardwareTexture.mDescriptorSets"); @@ -158,6 +159,13 @@ VulkanDescriptorSet *VkHardwareTexture::GetDescriptorSet(const FMaterialState &s auto systex = static_cast(mat->GetLayer(i, 0, &layer)); update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer, 0, mat->isExpanded() ? CTF_Expand : 0)->View.get(), sampler, systex->mImage.Layout); } + + auto dummyImage = fb->GetRenderPassManager()->GetNullTextureView(); + for (int i = numLayers; i < SHADER_MIN_REQUIRED_TEXTURE_LAYERS; i++) + { + update.addCombinedImageSampler(descriptor.get(), i, dummyImage, sampler, mImage.Layout); + } + update.updateSets(fb->device); mDescriptorSets.emplace_back(clampmode, flags, std::move(descriptor)); return mDescriptorSets.back().descriptor.get();