From c06123e040e364773856ea5ef6a4acef2bbb4bfe Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 17 May 2023 19:08:57 +0200 Subject: [PATCH] Make VkMaterial::GetDescriptorSet thread safe --- .../vulkan/textures/vk_hwtexture.cpp | 20 +++++++++++++++++++ .../rendering/vulkan/textures/vk_hwtexture.h | 16 +++++++++++++-- .../rendering/vulkan/vk_renderstate.cpp | 2 +- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/common/rendering/vulkan/textures/vk_hwtexture.cpp b/src/common/rendering/vulkan/textures/vk_hwtexture.cpp index 0b05842fa8..9c7f0a03ed 100644 --- a/src/common/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/common/rendering/vulkan/textures/vk_hwtexture.cpp @@ -304,6 +304,7 @@ void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name) VkMaterial::VkMaterial(VulkanRenderDevice* fb, FGameTexture* tex, int scaleflags) : FMaterial(tex, scaleflags), fb(fb) { + mThreadDescriptorSets.resize(fb->MaxThreads); fb->GetDescriptorSetManager()->AddMaterial(this); } @@ -323,6 +324,9 @@ void VkMaterial::DeleteDescriptors() deleteList->Add(std::move(it.descriptor)); } mDescriptorSets.clear(); + + for (auto& list : mThreadDescriptorSets) + list.clear(); } } @@ -385,3 +389,19 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state) return mDescriptorSets.back().descriptor.get(); } +VulkanDescriptorSet* VkMaterial::GetDescriptorSet(int threadIndex, const FMaterialState& state) +{ + int clampmode = Source()->GetClampMode(state.mClampMode); + int translation = state.mTranslation; + auto translationp = IsLuminosityTranslation(translation) ? translation : intptr_t(GPalette.GetTranslation(GetTranslationType(translation), GetTranslationIndex(translation))); + for (auto& set : mThreadDescriptorSets[threadIndex]) + { + if (set.descriptor && set.clampmode == clampmode && set.remap == translationp) + return set.descriptor; + } + + std::unique_lock lock(fb->ThreadMutex); + VulkanDescriptorSet* descriptorset = GetDescriptorSet(state); + mThreadDescriptorSets[threadIndex].push_back(ThreadDescriptorEntry(clampmode, translationp, descriptorset)); + return descriptorset; +} diff --git a/src/common/rendering/vulkan/textures/vk_hwtexture.h b/src/common/rendering/vulkan/textures/vk_hwtexture.h index 2711bdb33d..99bcaa6a38 100644 --- a/src/common/rendering/vulkan/textures/vk_hwtexture.h +++ b/src/common/rendering/vulkan/textures/vk_hwtexture.h @@ -65,14 +65,16 @@ public: VkMaterial(VulkanRenderDevice* fb, FGameTexture* tex, int scaleflags); ~VkMaterial(); - VulkanDescriptorSet* GetDescriptorSet(const FMaterialState& state); - void DeleteDescriptors() override; VulkanRenderDevice* fb = nullptr; std::list::iterator it; + VulkanDescriptorSet* GetDescriptorSet(int threadIndex, const FMaterialState& state); + private: + VulkanDescriptorSet* GetDescriptorSet(const FMaterialState& state); + struct DescriptorEntry { int clampmode; @@ -87,5 +89,15 @@ private: } }; + struct ThreadDescriptorEntry + { + int clampmode; + intptr_t remap; + VulkanDescriptorSet* descriptor; + + ThreadDescriptorEntry(int cm, intptr_t f, VulkanDescriptorSet* d) : clampmode(cm), remap(f), descriptor(d) { } + }; + std::vector mDescriptorSets; + std::vector> mThreadDescriptorSets; }; diff --git a/src/common/rendering/vulkan/vk_renderstate.cpp b/src/common/rendering/vulkan/vk_renderstate.cpp index 89f53416f5..d3e716470d 100644 --- a/src/common/rendering/vulkan/vk_renderstate.cpp +++ b/src/common/rendering/vulkan/vk_renderstate.cpp @@ -486,7 +486,7 @@ void VkRenderState::ApplyMaterial() if (mMaterial.mMaterial && mMaterial.mMaterial->Source()->isHardwareCanvas()) static_cast(mMaterial.mMaterial->Source()->GetTexture())->NeedUpdate(); - VulkanDescriptorSet* descriptorset = mMaterial.mMaterial ? static_cast(mMaterial.mMaterial)->GetDescriptorSet(mMaterial) : descriptors->GetNullTextureDescriptorSet(); + VulkanDescriptorSet* descriptorset = mMaterial.mMaterial ? static_cast(mMaterial.mMaterial)->GetDescriptorSet(threadIndex, mMaterial) : descriptors->GetNullTextureDescriptorSet(); mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptors->GetFixedDescriptorSet()); mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 2, descriptorset);