diff --git a/GPU/Vulkan/DepalettizeShaderVulkan.cpp b/GPU/Vulkan/DepalettizeShaderVulkan.cpp index a55352b31c..76d74b3d72 100644 --- a/GPU/Vulkan/DepalettizeShaderVulkan.cpp +++ b/GPU/Vulkan/DepalettizeShaderVulkan.cpp @@ -69,8 +69,10 @@ DepalShaderCacheVulkan::~DepalShaderCacheVulkan() { void DepalShaderCacheVulkan::DeviceLost() { Clear(); - if (vshader_) + if (vshader_) { + vulkan2D_->PurgeVertexShader(vshader_); vulkan_->Delete().QueueDeleteShaderModule(vshader_); + } draw_ = nullptr; vulkan_ = nullptr; } @@ -107,6 +109,7 @@ DepalShaderVulkan *DepalShaderCacheVulkan::GetDepalettizeShader(uint32_t clutMod VkPipeline pipeline = vulkan2D_->GetPipeline(rp, vshader_, fshader); // Can delete the shader module now that the pipeline has been created. // Maybe don't even need to queue it.. + vulkan2D_->PurgeFragmentShader(fshader, true); vulkan_->Delete().QueueDeleteShaderModule(fshader); DepalShaderVulkan *depal = new DepalShaderVulkan(); diff --git a/GPU/Vulkan/FramebufferVulkan.cpp b/GPU/Vulkan/FramebufferVulkan.cpp index faa104aba7..40bdea27a9 100644 --- a/GPU/Vulkan/FramebufferVulkan.cpp +++ b/GPU/Vulkan/FramebufferVulkan.cpp @@ -137,24 +137,36 @@ void FramebufferManagerVulkan::DestroyDeviceObjects() { delete drawPixelsTex_; drawPixelsTex_ = nullptr; - if (fsBasicTex_ != VK_NULL_HANDLE) + if (fsBasicTex_ != VK_NULL_HANDLE) { + vulkan2D_->PurgeFragmentShader(fsBasicTex_); vulkan_->Delete().QueueDeleteShaderModule(fsBasicTex_); - if (vsBasicTex_ != VK_NULL_HANDLE) + } + if (vsBasicTex_ != VK_NULL_HANDLE) { + vulkan2D_->PurgeVertexShader(vsBasicTex_); vulkan_->Delete().QueueDeleteShaderModule(vsBasicTex_); - if (stencilFs_ != VK_NULL_HANDLE) + } + if (stencilFs_ != VK_NULL_HANDLE) { + vulkan2D_->PurgeFragmentShader(stencilFs_); vulkan_->Delete().QueueDeleteShaderModule(stencilFs_); - if (stencilVs_ != VK_NULL_HANDLE) + } + if (stencilVs_ != VK_NULL_HANDLE) { + vulkan2D_->PurgeVertexShader(stencilVs_); vulkan_->Delete().QueueDeleteShaderModule(stencilVs_); + } if (linearSampler_ != VK_NULL_HANDLE) vulkan_->Delete().QueueDeleteSampler(linearSampler_); if (nearestSampler_ != VK_NULL_HANDLE) vulkan_->Delete().QueueDeleteSampler(nearestSampler_); - if (postVs_) + if (postVs_) { + vulkan2D_->PurgeVertexShader(postVs_); vulkan_->Delete().QueueDeleteShaderModule(postVs_); - if (postFs_) + } + if (postFs_) { + vulkan2D_->PurgeFragmentShader(postFs_); vulkan_->Delete().QueueDeleteShaderModule(postFs_); + } pipelinePostShader_ = VK_NULL_HANDLE; // actual pipeline should get destroyed by vulkan2d. } @@ -586,9 +598,11 @@ void FramebufferManagerVulkan::Resized() { void FramebufferManagerVulkan::CompilePostShader() { if (postVs_) { + vulkan2D_->PurgeVertexShader(postVs_); vulkan_->Delete().QueueDeleteShaderModule(postVs_); } if (postFs_) { + vulkan2D_->PurgeFragmentShader(postFs_); vulkan_->Delete().QueueDeleteShaderModule(postFs_); } diff --git a/GPU/Vulkan/VulkanUtil.cpp b/GPU/Vulkan/VulkanUtil.cpp index 424594d641..f598086235 100644 --- a/GPU/Vulkan/VulkanUtil.cpp +++ b/GPU/Vulkan/VulkanUtil.cpp @@ -43,6 +43,10 @@ void Vulkan2D::DestroyDeviceObjects() { vulkan_->Delete().QueueDeletePipeline(it.second); } pipelines_.clear(); + for (auto pipeline : keptPipelines_) { + vulkan_->Delete().QueueDeletePipeline(pipeline); + } + keptPipelines_.clear(); VkDevice device = vulkan_->GetDevice(); if (descriptorSetLayout_ != VK_NULL_HANDLE) { @@ -134,6 +138,36 @@ void Vulkan2D::BeginFrame() { void Vulkan2D::EndFrame() { } +void Vulkan2D::PurgeVertexShader(VkShaderModule s, bool keepPipeline) { + for (auto it = pipelines_.begin(); it != pipelines_.end(); ) { + if (it->first.vs == s) { + if (keepPipeline) { + keptPipelines_.push_back(it->second); + } else { + vulkan_->Delete().QueueDeletePipeline(it->second); + } + it = pipelines_.erase(it); + } else { + ++it; + } + } +} + +void Vulkan2D::PurgeFragmentShader(VkShaderModule s, bool keepPipeline) { + for (auto it = pipelines_.begin(); it != pipelines_.end(); ) { + if (it->first.fs == s) { + if (keepPipeline) { + keptPipelines_.push_back(it->second); + } else { + vulkan_->Delete().QueueDeletePipeline(it->second); + } + it = pipelines_.erase(it); + } else { + ++it; + } + } +} + VkDescriptorSet Vulkan2D::GetDescriptorSet(VkImageView tex1, VkSampler sampler1, VkImageView tex2, VkSampler sampler2) { DescriptorSetKey key; key.imageView[0] = tex1; diff --git a/GPU/Vulkan/VulkanUtil.h b/GPU/Vulkan/VulkanUtil.h index 69c3e5357a..19b1ef4a37 100644 --- a/GPU/Vulkan/VulkanUtil.h +++ b/GPU/Vulkan/VulkanUtil.h @@ -72,6 +72,9 @@ public: void BeginFrame(); void EndFrame(); + void PurgeVertexShader(VkShaderModule s, bool keepPipeline = false); + void PurgeFragmentShader(VkShaderModule s, bool keepPipeline = false); + VkDescriptorSet GetDescriptorSet(VkImageView tex1, VkSampler sampler1, VkImageView tex2, VkSampler sampler2); struct Vertex { @@ -118,6 +121,7 @@ private: FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES]; std::map pipelines_; + std::vector keptPipelines_; };