diff --git a/Common/GPU/Vulkan/VulkanContext.cpp b/Common/GPU/Vulkan/VulkanContext.cpp index b796947096a7..3ada9e445f40 100644 --- a/Common/GPU/Vulkan/VulkanContext.cpp +++ b/Common/GPU/Vulkan/VulkanContext.cpp @@ -1790,7 +1790,7 @@ void VulkanDeleteList::PerformDeletes(VulkanContext *vulkan, VmaAllocator alloca int deleteCount = 0; for (auto &callback : callbacks_) { - callback.func(vulkan, callback.userdata); + callback(vulkan); deleteCount++; } callbacks_.clear(); diff --git a/Common/GPU/Vulkan/VulkanContext.h b/Common/GPU/Vulkan/VulkanContext.h index 30d5c1053df8..82dd15540fec 100644 --- a/Common/GPU/Vulkan/VulkanContext.h +++ b/Common/GPU/Vulkan/VulkanContext.h @@ -90,6 +90,8 @@ enum class PerfClass { FAST, }; +typedef std::function DeleteCallback; + // This is a bit repetitive... class VulkanDeleteList { struct BufferWithAlloc { @@ -127,7 +129,7 @@ class VulkanDeleteList { void QueueDeletePipelineLayout(VkPipelineLayout &pipelineLayout) { _dbg_assert_(pipelineLayout != VK_NULL_HANDLE); pipelineLayouts_.push_back(pipelineLayout); pipelineLayout = VK_NULL_HANDLE; } void QueueDeleteDescriptorSetLayout(VkDescriptorSetLayout &descSetLayout) { _dbg_assert_(descSetLayout != VK_NULL_HANDLE); descSetLayouts_.push_back(descSetLayout); descSetLayout = VK_NULL_HANDLE; } void QueueDeleteQueryPool(VkQueryPool &queryPool) { _dbg_assert_(queryPool != VK_NULL_HANDLE); queryPools_.push_back(queryPool); queryPool = VK_NULL_HANDLE; } - void QueueCallback(void (*func)(VulkanContext *vulkan, void *userdata), void *userdata) { callbacks_.push_back(Callback(func, userdata)); } + void QueueCallback(DeleteCallback func) { callbacks_.push_back(func); } void QueueDeleteBufferAllocation(VkBuffer &buffer, VmaAllocation &alloc) { _dbg_assert_(buffer != VK_NULL_HANDLE); @@ -167,7 +169,7 @@ class VulkanDeleteList { std::vector pipelineLayouts_; std::vector descSetLayouts_; std::vector queryPools_; - std::vector callbacks_; + std::vector callbacks_; int deleteCount_ = 0; }; diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.cpp b/Common/GPU/Vulkan/VulkanQueueRunner.cpp index 70f41e8f2836..89999997c2ad 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.cpp +++ b/Common/GPU/Vulkan/VulkanQueueRunner.cpp @@ -975,7 +975,7 @@ void VulkanQueueRunner::LogReadbackImage(const VKRStep &step) { INFO_LOG(Log::G3D, "%s", StepToString(vulkan_, step).c_str()); } -void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer cmd, int curFrame, QueueProfileContext &profile) { +void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer cmd, const int curFrame, QueueProfileContext &profile) { for (size_t i = 0; i < step.preTransitions.size(); i++) { const TransitionRequest &iter = step.preTransitions[i]; if (iter.aspect == VK_IMAGE_ASPECT_COLOR_BIT && iter.fb->color.layout != iter.targetLayout) { @@ -1198,6 +1198,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c case VKRRenderCommand::DRAW_INDEXED: if (pipelineOK) { + _dbg_assert_(c.drawIndexed.descSetIndex < descSets->size()); VkDescriptorSet set = (*descSets)[c.drawIndexed.descSetIndex].set; _dbg_assert_(set != VK_NULL_HANDLE); vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &set, c.drawIndexed.numUboOffsets, c.drawIndexed.uboOffsets); @@ -1210,7 +1211,8 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c case VKRRenderCommand::DRAW: if (pipelineOK) { - VkDescriptorSet set = (*descSets)[c.drawIndexed.descSetIndex].set; + _dbg_assert_(c.draw.descSetIndex < descSets->size()); + VkDescriptorSet set = (*descSets)[c.draw.descSetIndex].set; _dbg_assert_(set != VK_NULL_HANDLE); vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &set, c.draw.numUboOffsets, c.draw.uboOffsets); if (c.draw.vbuffer) { diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 60d3690f6ec0..4f8ef6416416 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -223,11 +223,10 @@ void VKRGraphicsPipeline::BlockUntilCompiled() { void VKRGraphicsPipeline::QueueForDeletion(VulkanContext *vulkan) { // Can't destroy variants here, the pipeline still lives for a while. - vulkan->Delete().QueueCallback([](VulkanContext *vulkan, void *p) { - VKRGraphicsPipeline *pipeline = (VKRGraphicsPipeline *)p; - pipeline->DestroyVariantsInstant(vulkan->GetDevice()); - delete pipeline; - }, this); + vulkan->Delete().QueueCallback([this](VulkanContext *vulkan) { + this->DestroyVariantsInstant(vulkan->GetDevice()); + delete this; + }); } u32 VKRGraphicsPipeline::GetVariantsBitmask() const { @@ -528,6 +527,7 @@ VulkanRenderManager::~VulkanRenderManager() { _dbg_assert_(!runCompileThread_); // StopThread should already have been called from DestroyBackbuffers. vulkan_->WaitUntilQueueIdle(); + vulkan_->PerformPendingDeletes(); // Some callbacks can contain a reference to the render manager. _dbg_assert_(pipelineLayouts_.empty()); @@ -1632,11 +1632,6 @@ void VulkanRenderManager::Run(VKRRenderThreadTask &task) { } frameData.Submit(vulkan_, FrameSubmitType::Pending, frameDataShared_); - // Flush descriptors. - double descStart = time_now_d(); - FlushDescriptors(task.frame); - frameData.profile.descWriteTime = time_now_d() - descStart; - if (!frameData.hasMainCommands) { // Effectively resets both main and present command buffers, since they both live in this pool. // We always record main commands first, so we don't need to reset the present command buffer separately. @@ -1649,6 +1644,12 @@ void VulkanRenderManager::Run(VKRRenderThreadTask &task) { _assert_msg_(res == VK_SUCCESS, "vkBeginCommandBuffer failed! result=%s", VulkanResultToString(res)); } + // Flush descriptors. + double descStart = time_now_d(); + int f = task.frame; + FlushDescriptors(task.frame); + frameData.profile.descWriteTime = time_now_d() - descStart; + queueRunner_.PreprocessSteps(task.steps); // Likely during shutdown, happens in headless. if (task.steps.empty() && !frameData.hasAcquired) @@ -1815,14 +1816,13 @@ VKRPipelineLayout *VulkanRenderManager::CreatePipelineLayout(BindingType *bindin } void VulkanRenderManager::DestroyPipelineLayout(VKRPipelineLayout *layout) { - for (auto iter = pipelineLayouts_.begin(); iter != pipelineLayouts_.end(); iter++) { - if (*iter == layout) { - pipelineLayouts_.erase(iter); - break; + vulkan_->Delete().QueueCallback([this, layout](VulkanContext *vulkan) { + for (auto iter = pipelineLayouts_.begin(); iter != pipelineLayouts_.end(); iter++) { + if (*iter == layout) { + pipelineLayouts_.erase(iter); + break; + } } - } - vulkan_->Delete().QueueCallback([](VulkanContext *vulkan, void *userdata) { - VKRPipelineLayout *layout = (VKRPipelineLayout *)userdata; for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { layout->frameData[i].pool.DestroyImmediately(); } @@ -1830,17 +1830,17 @@ void VulkanRenderManager::DestroyPipelineLayout(VKRPipelineLayout *layout) { vkDestroyDescriptorSetLayout(vulkan->GetDevice(), layout->descriptorSetLayout, nullptr); delete layout; - }, layout); + }); } void VulkanRenderManager::FlushDescriptors(int frame) { - for (auto iter : pipelineLayouts_) { + for (VKRPipelineLayout *iter : pipelineLayouts_) { iter->FlushDescSets(vulkan_, frame, &frameData_[frame].profile); } } void VulkanRenderManager::ResetDescriptorLists(int frame) { - for (auto iter : pipelineLayouts_) { + for (VKRPipelineLayout *iter : pipelineLayouts_) { VKRPipelineLayout::FrameData &data = iter->frameData[frame]; data.flushedDescriptors_ = 0; diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index 2af76fb00ad6..d7348f17a6e4 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -194,10 +194,9 @@ class VKShaderModule : public ShaderModule { if (module_) { VkShaderModule shaderModule = module_->BlockUntilReady(); vulkan_->Delete().QueueDeleteShaderModule(shaderModule); - vulkan_->Delete().QueueCallback([](VulkanContext *context, void *m) { - auto module = (Promise *)m; + vulkan_->Delete().QueueCallback([module = module_](VulkanContext *context) { delete module; - }, module_); + }); } } Promise *Get() const { return module_; } @@ -1783,10 +1782,9 @@ class VKFramebuffer : public Framebuffer { } ~VKFramebuffer() { _assert_msg_(buf_, "Null buf_ in VKFramebuffer - double delete?"); - buf_->Vulkan()->Delete().QueueCallback([](VulkanContext *vulkan, void *fb) { - VKRFramebuffer *vfb = static_cast(fb); - delete vfb; - }, buf_); + buf_->Vulkan()->Delete().QueueCallback([buf = buf_](VulkanContext *vulkan) { + delete buf; + }); buf_ = nullptr; } VKRFramebuffer *GetFB() const { return buf_; } diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index 9366a1d7f1ff..acf919f0b9bb 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -116,10 +116,9 @@ VulkanFragmentShader::~VulkanFragmentShader() { if (shaderModule) { vulkan_->Delete().QueueDeleteShaderModule(shaderModule); } - vulkan_->Delete().QueueCallback([](VulkanContext *vulkan, void *m) { - auto module = (Promise *)m; + vulkan_->Delete().QueueCallback([module = module_](VulkanContext *vulkan) { delete module; - }, module_); + }); } } @@ -148,10 +147,9 @@ VulkanVertexShader::~VulkanVertexShader() { if (shaderModule) { vulkan_->Delete().QueueDeleteShaderModule(shaderModule); } - vulkan_->Delete().QueueCallback([](VulkanContext *vulkan, void *m) { - auto module = (Promise *)m; + vulkan_->Delete().QueueCallback([module = module_](VulkanContext *vulkan) { delete module; - }, module_); + }); } }