From 53eedf06e37cc544b094bfbe466518afbbaa0b62 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Dec 2022 14:52:06 -0800 Subject: [PATCH 1/3] Vulkan: Track pipeline desc using a refcount. Not very safe to not allow deletes, and don't want to force Draw objects on the deleter (this is referenced by them.) --- Common/GPU/Vulkan/VulkanRenderManager.cpp | 1 + Common/GPU/Vulkan/VulkanRenderManager.h | 7 +++++-- Common/GPU/Vulkan/thin3d_vulkan.cpp | 6 ++++-- GPU/Vulkan/PipelineManagerVulkan.cpp | 3 ++- GPU/Vulkan/PipelineManagerVulkan.h | 6 +++++- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 4f95a24458..56a293c70e 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -512,6 +512,7 @@ VKRGraphicsPipeline *VulkanRenderManager::CreateGraphicsPipeline(VKRGraphicsPipe _dbg_assert_(desc->vertexShader); _dbg_assert_(desc->fragmentShader); pipeline->desc = desc; + pipeline->desc->AddRef(); if (curRenderStep_) { // The common case pipelinesToCheck_.push_back(pipeline); diff --git a/Common/GPU/Vulkan/VulkanRenderManager.h b/Common/GPU/Vulkan/VulkanRenderManager.h index c15d9027a2..e4845f9924 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.h +++ b/Common/GPU/Vulkan/VulkanRenderManager.h @@ -22,6 +22,7 @@ #include "Common/GPU/MiscTypes.h" #include "Common/GPU/Vulkan/VulkanQueueRunner.h" #include "Common/GPU/Vulkan/VulkanFramebuffer.h" +#include "Common/GPU/thin3d.h" // Forward declaration VK_DEFINE_HANDLE(VmaAllocation); @@ -74,7 +75,7 @@ struct BoundingRect { }; // All the data needed to create a graphics pipeline. -struct VKRGraphicsPipelineDesc { +struct VKRGraphicsPipelineDesc : Draw::RefCountedObject { VkPipelineCache pipelineCache = VK_NULL_HANDLE; VkPipelineColorBlendStateCreateInfo cbs{ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO }; VkPipelineColorBlendAttachmentState blend0{}; @@ -120,6 +121,8 @@ struct VKRGraphicsPipeline { for (size_t i = 0; i < (size_t)RenderPassType::TYPE_COUNT; i++) { delete pipeline[i]; } + if (desc) + desc->Release(); } bool Create(VulkanContext *vulkan, VkRenderPass compatibleRenderPass, RenderPassType rpType, VkSampleCountFlagBits sampleCount); @@ -133,7 +136,7 @@ struct VKRGraphicsPipeline { void LogCreationFailure() const; - VKRGraphicsPipelineDesc *desc = nullptr; // not owned! + VKRGraphicsPipelineDesc *desc = nullptr; Promise *pipeline[(size_t)RenderPassType::TYPE_COUNT]{}; VkSampleCountFlagBits SampleCount() const { return sampleCount_; } diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index 8381256640..1edf619f3d 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -264,6 +264,7 @@ public: VKPipeline(VulkanContext *vulkan, size_t size, PipelineFlags _flags, const char *tag) : vulkan_(vulkan), flags(_flags), tag_(tag) { uboSize_ = (int)size; ubo_ = new uint8_t[uboSize_]; + vkrDesc = new VKRGraphicsPipelineDesc(); } ~VKPipeline() { DEBUG_LOG(G3D, "Queueing %s (pipeline) for release", tag_.c_str()); @@ -274,6 +275,7 @@ public: dep->Release(); } delete[] ubo_; + vkrDesc->Release(); } void SetDynamicUniformData(const void *data, size_t size) { @@ -291,7 +293,7 @@ public: } VKRGraphicsPipeline *pipeline = nullptr; - VKRGraphicsPipelineDesc vkrDesc; + VKRGraphicsPipelineDesc *vkrDesc = nullptr; PipelineFlags flags; std::vector deps; @@ -1163,7 +1165,7 @@ Pipeline *VKContext::CreateGraphicsPipeline(const PipelineDesc &desc, const char VKPipeline *pipeline = new VKPipeline(vulkan_, desc.uniformDesc ? desc.uniformDesc->uniformBufferSize : 16 * sizeof(float), pipelineFlags, tag); - VKRGraphicsPipelineDesc &gDesc = pipeline->vkrDesc; + VKRGraphicsPipelineDesc &gDesc = *pipeline->vkrDesc; std::vector stages; stages.resize(desc.shaders.size()); diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 0c081c3f78..f5ba269229 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -181,7 +181,8 @@ static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, VkPipelineLayout layout, PipelineFlags pipelineFlags, VkSampleCountFlagBits sampleCount, const VulkanPipelineRasterStateKey &key, const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, VulkanGeometryShader *gs, bool useHwTransform, u32 variantBitmask) { VulkanPipeline *vulkanPipeline = new VulkanPipeline(); - VKRGraphicsPipelineDesc *desc = &vulkanPipeline->desc; + vulkanPipeline->desc = new VKRGraphicsPipelineDesc(); + VKRGraphicsPipelineDesc *desc = vulkanPipeline->desc; desc->pipelineCache = pipelineCache; PROFILE_THIS_SCOPE("pipelinebuild"); diff --git a/GPU/Vulkan/PipelineManagerVulkan.h b/GPU/Vulkan/PipelineManagerVulkan.h index dcd13c54c5..5b5400ff1b 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.h +++ b/GPU/Vulkan/PipelineManagerVulkan.h @@ -54,8 +54,12 @@ struct VulkanPipelineKey { // Simply wraps a Vulkan pipeline, providing some metadata. struct VulkanPipeline { + ~VulkanPipeline() { + desc->Release(); + } + VKRGraphicsPipeline *pipeline; - VKRGraphicsPipelineDesc desc; + VKRGraphicsPipelineDesc *desc; PipelineFlags pipelineFlags; // PipelineFlags enum above. bool UsesBlendConstant() const { return (pipelineFlags & PipelineFlags::USES_BLEND_CONSTANT) != 0; } From 78ed8d45a7cd96ac0af8a9fdda5f6185730a5ae3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Dec 2022 14:53:10 -0800 Subject: [PATCH 2/3] Vulkan: Defer deletion of shader module promises. --- Common/GPU/Vulkan/thin3d_vulkan.cpp | 5 ++++- GPU/Vulkan/ShaderManagerVulkan.cpp | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index 1edf619f3d..08aed9a332 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -203,7 +203,10 @@ public: DEBUG_LOG(G3D, "Queueing %s (shmodule %p) for release", tag_.c_str(), module_); VkShaderModule shaderModule = module_->BlockUntilReady(); vulkan_->Delete().QueueDeleteShaderModule(shaderModule); - delete module_; + vulkan_->Delete().QueueCallback([](void *m) { + auto module = (Promise *)m; + delete module; + }, module_); } } Promise *Get() const { return module_; } diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index e895e21af6..89e3744f4a 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -120,7 +120,10 @@ VulkanFragmentShader::~VulkanFragmentShader() { if (module_) { VkShaderModule shaderModule = module_->BlockUntilReady(); vulkan_->Delete().QueueDeleteShaderModule(shaderModule); - delete module_; + vulkan_->Delete().QueueCallback([](void *m) { + auto module = (Promise *)m; + delete module; + }, module_); } } @@ -150,7 +153,10 @@ VulkanVertexShader::~VulkanVertexShader() { if (module_) { VkShaderModule shaderModule = module_->BlockUntilReady(); vulkan_->Delete().QueueDeleteShaderModule(shaderModule); - delete module_; + vulkan_->Delete().QueueCallback([](void *m) { + auto module = (Promise *)m; + delete module; + }, module_); } } @@ -180,7 +186,10 @@ VulkanGeometryShader::~VulkanGeometryShader() { if (module_) { VkShaderModule shaderModule = module_->BlockUntilReady(); vulkan_->Delete().QueueDeleteShaderModule(shaderModule); - delete module_; + vulkan_->Delete().QueueCallback([](void *m) { + auto module = (Promise *)m; + delete module; + }, module_); } } From 3f620dba58da1e07d9da445e52e7ada956530c77 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Dec 2022 14:56:58 -0800 Subject: [PATCH 3/3] Vulkan: Reduce some logging when things are fast. On startup especially this spams sometimes. --- Common/GPU/Vulkan/VulkanRenderManager.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 56a293c70e..fab538a0a4 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -101,8 +101,12 @@ bool VKRGraphicsPipeline::Create(VulkanContext *vulkan, VkRenderPass compatibleR double start = time_now_d(); VkPipeline vkpipeline; VkResult result = vkCreateGraphicsPipelines(vulkan->GetDevice(), desc->pipelineCache, 1, &pipe, nullptr, &vkpipeline); + double taken_ms = (time_now_d() - start) * 1000.0; - INFO_LOG(G3D, "Pipeline creation time: %0.2f ms", (time_now_d() - start) * 1000.0); + if (taken_ms < 0.1) + DEBUG_LOG(G3D, "Pipeline creation time: %0.2f ms (fast)", taken_ms); + else + INFO_LOG(G3D, "Pipeline creation time: %0.2f ms", taken_ms); bool success = true; if (result == VK_INCOMPLETE) {