From ec0586ba501fdf01dc1223f62d548b4778e242b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 20 Nov 2021 22:34:51 +0100 Subject: [PATCH 01/14] Use promises to hold shader modules, for later asyncification --- Common/GPU/Vulkan/VulkanRenderManager.cpp | 4 +++ Common/Thread/Promise.h | 11 +++++++- GPU/Vulkan/PipelineManagerVulkan.cpp | 8 +++--- GPU/Vulkan/ShaderManagerVulkan.cpp | 31 +++++++++++++---------- GPU/Vulkan/ShaderManagerVulkan.h | 9 ++++--- 5 files changed, 41 insertions(+), 22 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index ba2c64f75836..0d857844b6c1 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -449,6 +449,10 @@ void VulkanRenderManager::CompileThreadFunc() { if (!run_) { break; } + + // TODO: Here we can sort the pending pipelines by vertex and fragment shaders, + // and split up further. + // Those with the same pairs of shaders should be on the same thread. for (auto &entry : toCompile) { switch (entry.type) { case CompileQueueEntry::Type::GRAPHICS: diff --git a/Common/Thread/Promise.h b/Common/Thread/Promise.h index fe2ddb380736..78cfd65f5975 100644 --- a/Common/Thread/Promise.h +++ b/Common/Thread/Promise.h @@ -33,6 +33,7 @@ class PromiseTask : public Task { // Has ownership over the data. Single use. // TODO: Split Mailbox (rx_ and tx_) up into separate proxy objects. // NOTE: Poll/BlockUntilReady should only be used from one thread. +// TODO: Make movable? template class Promise { public: @@ -47,6 +48,13 @@ class Promise { return promise; } + static Promise *AlreadyDone(T data) { + Promise *promise = new Promise(); + promise->data_ = data; + promise->ready_ = true; + return promise; + } + ~Promise() { // A promise should have been fulfilled before it's destroyed. _assert_(ready_); @@ -85,7 +93,8 @@ class Promise { private: Promise() {} + // Promise can only be constructed in Spawn. T data_ = nullptr; bool ready_ = false; - Mailbox *rx_; + Mailbox *rx_ = nullptr; }; diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 86fa279b9c65..f513f6ddd846 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -260,13 +260,13 @@ static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, ss[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; ss[0].stage = VK_SHADER_STAGE_VERTEX_BIT; ss[0].pSpecializationInfo = nullptr; - ss[0].module = vs->GetModule(); + ss[0].module = vs->GetModule()->BlockUntilReady(); ss[0].pName = "main"; ss[0].flags = 0; ss[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; ss[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; ss[1].pSpecializationInfo = nullptr; - ss[1].module = fs->GetModule(); + ss[1].module = fs->GetModule()->BlockUntilReady(); ss[1].pName = "main"; ss[1].flags = 0; @@ -369,8 +369,8 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VulkanRenderManager * key.raster = rasterKey; key.renderPass = renderPass; key.useHWTransform = useHwTransform; - key.vShader = vs->GetModule(); - key.fShader = fs->GetModule(); + key.vShader = vs->GetModule()->BlockUntilReady(); + key.fShader = fs->GetModule()->BlockUntilReady(); key.vtxFmtId = useHwTransform ? decFmt->id : 0; auto iter = pipelines_.Get(key); diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index 400f4d180c86..5c3015151572 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -42,7 +42,7 @@ #include "GPU/Vulkan/DrawEngineVulkan.h" #include "GPU/Vulkan/FramebufferManagerVulkan.h" -VkShaderModule CompileShaderModule(VulkanContext *vulkan, VkShaderStageFlagBits stage, const char *code) { +Promise *CompileShaderModule(VulkanContext *vulkan, VkShaderStageFlagBits stage, const char *code) { PROFILE_THIS_SCOPE("shadercomp"); std::string errorMessage; @@ -67,11 +67,10 @@ VkShaderModule CompileShaderModule(VulkanContext *vulkan, VkShaderStageFlagBits #endif Reporting::ReportMessage("Vulkan error in shader compilation: info: %s / code: %s", errorMessage.c_str(), code); } else { + VkShaderModule shaderModule; + success = vulkan->CreateShaderModule(spirv, &shaderModule); #ifdef SHADERLOG - OutputDebugStringA(LineNumberString(code).c_str()); -#endif -#ifdef SHADERLOG - OutputDebugStringA("OK\n"); + OutputDebugStringA("OK"); #endif } @@ -79,7 +78,7 @@ VkShaderModule CompileShaderModule(VulkanContext *vulkan, VkShaderStageFlagBits vulkan->CreateShaderModule(spirv, &shaderModule); } - return shaderModule; + return Promise::AlreadyDone(shaderModule); } @@ -96,8 +95,9 @@ VulkanFragmentShader::VulkanFragmentShader(VulkanContext *vulkan, FShaderID id, } VulkanFragmentShader::~VulkanFragmentShader() { - if (module_ != VK_NULL_HANDLE) { - vulkan_->Delete().QueueDeleteShaderModule(module_); + if (module_) { + VkShaderModule shaderModule = module_->BlockUntilReady(); + vulkan_->Delete().QueueDeleteShaderModule(shaderModule); } } @@ -120,13 +120,14 @@ VulkanVertexShader::VulkanVertexShader(VulkanContext *vulkan, VShaderID id, cons failed_ = true; return; } else { - VERBOSE_LOG(G3D, "Compiled vertex shader:\n%s\n", (const char *)code); + VERBOSE_LOG(G3D, "Compiled fragment shader:\n%s\n", (const char *)code); } } VulkanVertexShader::~VulkanVertexShader() { - if (module_ != VK_NULL_HANDLE) { - vulkan_->Delete().QueueDeleteShaderModule(module_); + if (module_) { + VkShaderModule shaderModule = module_->BlockUntilReady(); + vulkan_->Delete().QueueDeleteShaderModule(shaderModule); } } @@ -334,7 +335,9 @@ std::string ShaderManagerVulkan::DebugGetShaderString(std::string id, DebugShade VulkanVertexShader *ShaderManagerVulkan::GetVertexShaderFromModule(VkShaderModule module) { VulkanVertexShader *vs = nullptr; vsCache_.Iterate([&](const VShaderID &id, VulkanVertexShader *shader) { - if (shader->GetModule() == module) + Promise *p = shader->GetModule(); + VkShaderModule m = p->BlockUntilReady(); + if (m == module) vs = shader; }); return vs; @@ -343,7 +346,9 @@ VulkanVertexShader *ShaderManagerVulkan::GetVertexShaderFromModule(VkShaderModul VulkanFragmentShader *ShaderManagerVulkan::GetFragmentShaderFromModule(VkShaderModule module) { VulkanFragmentShader *fs = nullptr; fsCache_.Iterate([&](const FShaderID &id, VulkanFragmentShader *shader) { - if (shader->GetModule() == module) + Promise *p = shader->GetModule(); + VkShaderModule m = p->BlockUntilReady(); + if (m == module) fs = shader; }); return fs; diff --git a/GPU/Vulkan/ShaderManagerVulkan.h b/GPU/Vulkan/ShaderManagerVulkan.h index ff7e5d8c5c0a..5ab37fa723bb 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.h +++ b/GPU/Vulkan/ShaderManagerVulkan.h @@ -20,6 +20,7 @@ #include #include +#include "Common/Thread/Promise.h" #include "Common/Data/Collections/Hashmaps.h" #include "Common/GPU/Vulkan/VulkanMemory.h" #include "GPU/Common/ShaderCommon.h" @@ -43,11 +44,11 @@ class VulkanFragmentShader { bool Failed() const { return failed_; } std::string GetShaderString(DebugShaderStringType type) const; - VkShaderModule GetModule() const { return module_; } + Promise *GetModule() { return module_; } const FShaderID &GetID() { return id_; } protected: - VkShaderModule module_ = VK_NULL_HANDLE; + Promise *module_; VulkanContext *vulkan_; std::string source_; @@ -66,11 +67,11 @@ class VulkanVertexShader { bool UseHWTransform() const { return useHWTransform_; } std::string GetShaderString(DebugShaderStringType type) const; - VkShaderModule GetModule() const { return module_; } + Promise *GetModule() { return module_; } const VShaderID &GetID() { return id_; } protected: - VkShaderModule module_ = VK_NULL_HANDLE; + Promise *module_ = nullptr; VulkanContext *vulkan_; std::string source_; From 010c3b4f4bbeba4284205649b2219e59cfc087e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Jun 2022 15:30:05 +0200 Subject: [PATCH 02/14] minor sv translation fix --- assets/lang/sv_SE.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/lang/sv_SE.ini b/assets/lang/sv_SE.ini index 56ae1987d16d..fbacbb12197b 100644 --- a/assets/lang/sv_SE.ini +++ b/assets/lang/sv_SE.ini @@ -1094,8 +1094,8 @@ AVI Dump started. = AVI dump started AVI Dump stopped. = AVI dump stopped Cache ISO in RAM = Cachea hela ISO:n i RAM Change CPU Clock = Ändra CPU-frekvens (kan orsaka instabilitet) -Color Saturation = Color Saturation -Color Tint = Color Tint +Color Saturation = Färgmättnad +Color Tint = Färgförskjutning Error: load undo state is from a different game = Error: load undo state is from a different game Failed to load state for load undo. Error in the file system. = Failed to load state for load undo. Error in the file system. Floating symbols = Floating symbols From fc418ee16f1dd83e50c46d38757f9040d36cd7f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Jun 2022 16:19:14 +0200 Subject: [PATCH 03/14] Create shader modules (and compile GLSL) on worker threads --- GPU/Vulkan/ShaderManagerVulkan.cpp | 54 ++++++++++++++++-------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index 5c3015151572..80f1db03504c 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -43,42 +43,44 @@ #include "GPU/Vulkan/FramebufferManagerVulkan.h" Promise *CompileShaderModule(VulkanContext *vulkan, VkShaderStageFlagBits stage, const char *code) { - PROFILE_THIS_SCOPE("shadercomp"); + return Promise::Spawn(&g_threadManager, [=] { + PROFILE_THIS_SCOPE("shadercomp"); - std::string errorMessage; - std::vector spirv; + std::string errorMessage; + std::vector spirv; - bool success = GLSLtoSPV(stage, code, GLSLVariant::VULKAN, spirv, &errorMessage); + bool success = GLSLtoSPV(stage, code, GLSLVariant::VULKAN, spirv, &errorMessage); - VkShaderModule shaderModule = VK_NULL_HANDLE; + VkShaderModule shaderModule = VK_NULL_HANDLE; - if (!errorMessage.empty()) { - if (success) { - ERROR_LOG(G3D, "Warnings in shader compilation!"); - } else { - ERROR_LOG(G3D, "Error in shader compilation!"); - } - ERROR_LOG(G3D, "Messages: %s", errorMessage.c_str()); - ERROR_LOG(G3D, "Shader source:\n%s", code); + if (!errorMessage.empty()) { + if (success) { + ERROR_LOG(G3D, "Warnings in shader compilation!"); + } else { + ERROR_LOG(G3D, "Error in shader compilation!"); + } + ERROR_LOG(G3D, "Messages: %s", errorMessage.c_str()); + ERROR_LOG(G3D, "Shader source:\n%s", code); #ifdef SHADERLOG - OutputDebugStringA(LineNumberString(code).c_str()); - OutputDebugStringA("Error messages:\n"); - OutputDebugStringA(errorMessage.c_str()); + OutputDebugStringA(LineNumberString(code).c_str()); + OutputDebugStringA("Error messages:\n"); + OutputDebugStringA(errorMessage.c_str()); #endif - Reporting::ReportMessage("Vulkan error in shader compilation: info: %s / code: %s", errorMessage.c_str(), code); - } else { - VkShaderModule shaderModule; - success = vulkan->CreateShaderModule(spirv, &shaderModule); + Reporting::ReportMessage("Vulkan error in shader compilation: info: %s / code: %s", errorMessage.c_str(), code); + } else { + VkShaderModule shaderModule; + success = vulkan->CreateShaderModule(spirv, &shaderModule); #ifdef SHADERLOG - OutputDebugStringA("OK"); + OutputDebugStringA("OK"); #endif - } + } - if (success) { - vulkan->CreateShaderModule(spirv, &shaderModule); - } + if (success) { + vulkan->CreateShaderModule(spirv, &shaderModule); + } - return Promise::AlreadyDone(shaderModule); + return shaderModule; + }, TaskType::CPU_COMPUTE); } From e2c740827a97db793ebac6b34531154b418e9594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Jun 2022 16:24:19 +0200 Subject: [PATCH 04/14] Use shader module promises as keys in pipeline cache instead of the actual shader modules. Prevents early block. --- GPU/Vulkan/PipelineManagerVulkan.cpp | 8 ++++---- GPU/Vulkan/PipelineManagerVulkan.h | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index f513f6ddd846..72203c208c7c 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -369,8 +369,8 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VulkanRenderManager * key.raster = rasterKey; key.renderPass = renderPass; key.useHWTransform = useHwTransform; - key.vShader = vs->GetModule()->BlockUntilReady(); - key.fShader = fs->GetModule()->BlockUntilReady(); + key.vShader = vs->GetModule(); + key.fShader = fs->GetModule(); key.vtxFmtId = useHwTransform ? decFmt->id : 0; auto iter = pipelines_.Get(key); @@ -633,8 +633,8 @@ void PipelineManagerVulkan::SaveCache(FILE *file, bool saveRawPipelineCache, Sha pipelines_.Iterate([&](const VulkanPipelineKey &pkey, VulkanPipeline *value) { if (failed) return; - VulkanVertexShader *vshader = shaderManager->GetVertexShaderFromModule(pkey.vShader); - VulkanFragmentShader *fshader = shaderManager->GetFragmentShaderFromModule(pkey.fShader); + VulkanVertexShader *vshader = shaderManager->GetVertexShaderFromModule(pkey.vShader->BlockUntilReady()); + VulkanFragmentShader *fshader = shaderManager->GetFragmentShaderFromModule(pkey.fShader->BlockUntilReady()); if (!vshader || !fshader) { failed = true; return; diff --git a/GPU/Vulkan/PipelineManagerVulkan.h b/GPU/Vulkan/PipelineManagerVulkan.h index 37d542e9a09c..a6ab695cefa4 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.h +++ b/GPU/Vulkan/PipelineManagerVulkan.h @@ -18,7 +18,9 @@ #pragma once #include + #include "Common/Data/Collections/Hashmaps.h" +#include "Common/Thread/Promise.h" #include "GPU/Common/VertexDecoderCommon.h" #include "GPU/Common/ShaderId.h" @@ -33,8 +35,8 @@ class VulkanRenderManager; struct VulkanPipelineKey { VulkanPipelineRasterStateKey raster; // prim is included here VkRenderPass renderPass; - VkShaderModule vShader; - VkShaderModule fShader; + Promise *vShader; + Promise *fShader; uint32_t vtxFmtId; bool useHWTransform; From 93422f6dea961f9c1bc65f66df813bb9950e30bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Jun 2022 23:28:26 +0200 Subject: [PATCH 05/14] Don't block on shader creation until it's time to create the pipeline. --- Common/GPU/Vulkan/VulkanRenderManager.cpp | 28 +++++++++++++++++++++++ Common/GPU/Vulkan/VulkanRenderManager.h | 7 +++++- GPU/Vulkan/PipelineManagerVulkan.cpp | 25 ++------------------ 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 0d857844b6c1..45e3a78aaa25 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -29,6 +29,34 @@ bool VKRGraphicsPipeline::Create(VulkanContext *vulkan) { // Already failed to create this one. return false; } + + // Fill in the last part of the desc since now it's time to block. + VkShaderModule vs = desc->vertexShader->BlockUntilReady(); + VkShaderModule fs = desc->fragmentShader->BlockUntilReady(); + + if (!vs || !fs) { + ERROR_LOG(G3D, "Failed creating graphics pipeline - missing shader modules"); + // We're kinda screwed here? + return false; + } + + VkPipelineShaderStageCreateInfo ss[2]{}; + ss[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + ss[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + ss[0].pSpecializationInfo = nullptr; + ss[0].module = vs; + ss[0].pName = "main"; + ss[0].flags = 0; + ss[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + ss[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + ss[1].pSpecializationInfo = nullptr; + ss[1].module = fs; + ss[1].pName = "main"; + ss[1].flags = 0; + + desc->pipe.pStages = ss; + desc->pipe.stageCount = 2; + VkPipeline vkpipeline; VkResult result = vkCreateGraphicsPipelines(vulkan->GetDevice(), desc->pipelineCache, 1, &desc->pipe, nullptr, &vkpipeline); diff --git a/Common/GPU/Vulkan/VulkanRenderManager.h b/Common/GPU/Vulkan/VulkanRenderManager.h index a541bea57e57..efadc784c654 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.h +++ b/Common/GPU/Vulkan/VulkanRenderManager.h @@ -12,6 +12,7 @@ #include #include +#include "Common/Thread/Promise.h" #include "Common/System/Display.h" #include "Common/GPU/Vulkan/VulkanContext.h" #include "Common/Data/Convert/SmallDataConvert.h" @@ -121,7 +122,11 @@ struct VKRGraphicsPipelineDesc { VkPipelineDynamicStateCreateInfo ds{ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO }; VkPipelineRasterizationStateCreateInfo rs{ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO }; VkPipelineMultisampleStateCreateInfo ms{ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO }; - VkPipelineShaderStageCreateInfo shaderStageInfo[2]{}; + + // Replaced the ShaderStageInfo with promises here so we can wait for compiles to finish. + Promise *vertexShader; + Promise *fragmentShader; + VkPipelineInputAssemblyStateCreateInfo inputAssembly{ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO }; VkVertexInputAttributeDescription attrs[8]{}; VkVertexInputBindingDescription ibd{}; diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 72203c208c7c..73768e38bc73 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -256,28 +256,8 @@ static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, ms.pSampleMask = nullptr; ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - VkPipelineShaderStageCreateInfo *ss = &desc->shaderStageInfo[0]; - ss[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - ss[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - ss[0].pSpecializationInfo = nullptr; - ss[0].module = vs->GetModule()->BlockUntilReady(); - ss[0].pName = "main"; - ss[0].flags = 0; - ss[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - ss[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - ss[1].pSpecializationInfo = nullptr; - ss[1].module = fs->GetModule()->BlockUntilReady(); - ss[1].pName = "main"; - ss[1].flags = 0; - - if (!ss[0].module || !ss[1].module) { - ERROR_LOG(G3D, "Failed creating graphics pipeline - bad shaders"); - // Create a placeholder to avoid creating over and over if shader compiler broken. - VulkanPipeline *nullPipeline = new VulkanPipeline(); - nullPipeline->pipeline = VK_NULL_HANDLE; - nullPipeline->flags = 0; - return nullPipeline; - } + desc->fragmentShader = fs->GetModule(); + desc->vertexShader = vs->GetModule(); VkPipelineInputAssemblyStateCreateInfo &inputAssembly = desc->inputAssembly; inputAssembly.flags = 0; @@ -321,7 +301,6 @@ static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, VkGraphicsPipelineCreateInfo &pipe = desc->pipe; pipe.flags = 0; pipe.stageCount = 2; - pipe.pStages = ss; pipe.basePipelineIndex = 0; pipe.pColorBlendState = &desc->cbs; From 8775837c11dcdc94d8e2143f6f1f1247441e2e33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Jun 2022 23:42:04 +0200 Subject: [PATCH 06/14] Work towards finding the leak --- Common/Thread/Promise.h | 3 +-- GPU/Vulkan/ShaderManagerVulkan.cpp | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Common/Thread/Promise.h b/Common/Thread/Promise.h index 78cfd65f5975..1788eb6a4b33 100644 --- a/Common/Thread/Promise.h +++ b/Common/Thread/Promise.h @@ -59,7 +59,6 @@ class Promise { // A promise should have been fulfilled before it's destroyed. _assert_(ready_); _assert_(!rx_); - delete data_; } // Returns T if the data is ready, nullptr if it's not. @@ -93,7 +92,7 @@ class Promise { private: Promise() {} - // Promise can only be constructed in Spawn. + // Promise can only be constructed in Spawn (or AlreadyDone). T data_ = nullptr; bool ready_ = false; Mailbox *rx_ = nullptr; diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index 80f1db03504c..22ad34afbe0d 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -100,6 +100,7 @@ VulkanFragmentShader::~VulkanFragmentShader() { if (module_) { VkShaderModule shaderModule = module_->BlockUntilReady(); vulkan_->Delete().QueueDeleteShaderModule(shaderModule); + delete module_; } } @@ -130,6 +131,7 @@ VulkanVertexShader::~VulkanVertexShader() { if (module_) { VkShaderModule shaderModule = module_->BlockUntilReady(); vulkan_->Delete().QueueDeleteShaderModule(shaderModule); + delete module_; } } From 6e605fa2bcd9178b777b763d1b726249e5b5942d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Jun 2022 23:50:21 +0200 Subject: [PATCH 07/14] Fix silly logic, fixes the shader leak. --- GPU/Vulkan/ShaderManagerVulkan.cpp | 20 +++++++++----------- GPU/Vulkan/ShaderManagerVulkan.h | 2 +- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index 22ad34afbe0d..5f2d1ffb5d1f 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -42,7 +42,9 @@ #include "GPU/Vulkan/DrawEngineVulkan.h" #include "GPU/Vulkan/FramebufferManagerVulkan.h" -Promise *CompileShaderModule(VulkanContext *vulkan, VkShaderStageFlagBits stage, const char *code) { +// Most drivers treat vkCreateShaderModule as pretty much a memcpy. What actually +// takes time here, and makes this worthy of parallelization, is GLSLtoSPV. +Promise *CompileShaderModuleAsync(VulkanContext *vulkan, VkShaderStageFlagBits stage, const char *code) { return Promise::Spawn(&g_threadManager, [=] { PROFILE_THIS_SCOPE("shadercomp"); @@ -51,8 +53,6 @@ Promise *CompileShaderModule(VulkanContext *vulkan, VkShaderStag bool success = GLSLtoSPV(stage, code, GLSLVariant::VULKAN, spirv, &errorMessage); - VkShaderModule shaderModule = VK_NULL_HANDLE; - if (!errorMessage.empty()) { if (success) { ERROR_LOG(G3D, "Warnings in shader compilation!"); @@ -67,18 +67,16 @@ Promise *CompileShaderModule(VulkanContext *vulkan, VkShaderStag OutputDebugStringA(errorMessage.c_str()); #endif Reporting::ReportMessage("Vulkan error in shader compilation: info: %s / code: %s", errorMessage.c_str(), code); - } else { - VkShaderModule shaderModule; + } + + VkShaderModule shaderModule = VK_NULL_HANDLE; + if (success) { success = vulkan->CreateShaderModule(spirv, &shaderModule); #ifdef SHADERLOG OutputDebugStringA("OK"); #endif } - if (success) { - vulkan->CreateShaderModule(spirv, &shaderModule); - } - return shaderModule; }, TaskType::CPU_COMPUTE); } @@ -87,7 +85,7 @@ Promise *CompileShaderModule(VulkanContext *vulkan, VkShaderStag VulkanFragmentShader::VulkanFragmentShader(VulkanContext *vulkan, FShaderID id, const char *code) : vulkan_(vulkan), id_(id) { source_ = code; - module_ = CompileShaderModule(vulkan, VK_SHADER_STAGE_FRAGMENT_BIT, source_.c_str()); + module_ = CompileShaderModuleAsync(vulkan, VK_SHADER_STAGE_FRAGMENT_BIT, source_.c_str()); if (!module_) { failed_ = true; return; @@ -118,7 +116,7 @@ std::string VulkanFragmentShader::GetShaderString(DebugShaderStringType type) co VulkanVertexShader::VulkanVertexShader(VulkanContext *vulkan, VShaderID id, const char *code, bool useHWTransform) : vulkan_(vulkan), useHWTransform_(useHWTransform), id_(id) { source_ = code; - module_ = CompileShaderModule(vulkan, VK_SHADER_STAGE_VERTEX_BIT, source_.c_str()); + module_ = CompileShaderModuleAsync(vulkan, VK_SHADER_STAGE_VERTEX_BIT, source_.c_str()); if (!module_) { failed_ = true; return; diff --git a/GPU/Vulkan/ShaderManagerVulkan.h b/GPU/Vulkan/ShaderManagerVulkan.h index 5ab37fa723bb..50915be6a2c7 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.h +++ b/GPU/Vulkan/ShaderManagerVulkan.h @@ -48,7 +48,7 @@ class VulkanFragmentShader { const FShaderID &GetID() { return id_; } protected: - Promise *module_; + Promise *module_ = nullptr; VulkanContext *vulkan_; std::string source_; From e70103726718cb42ac166150bc58c828a1f92a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Jun 2022 23:56:51 +0200 Subject: [PATCH 08/14] Buildfix --- Common/Thread/Promise.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Common/Thread/Promise.h b/Common/Thread/Promise.h index 1788eb6a4b33..40a0029fd6ed 100644 --- a/Common/Thread/Promise.h +++ b/Common/Thread/Promise.h @@ -2,6 +2,7 @@ #include +#include "Common/Log.h" #include "Common/Thread/Channel.h" #include "Common/Thread/ThreadManager.h" From 210233ede06dbfe6da17eca975a6d1187afb7cfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Jun 2022 00:35:46 +0200 Subject: [PATCH 09/14] Buildfix --- Common/Thread/Promise.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/Thread/Promise.h b/Common/Thread/Promise.h index 40a0029fd6ed..1833a7fa0c49 100644 --- a/Common/Thread/Promise.h +++ b/Common/Thread/Promise.h @@ -94,7 +94,7 @@ class Promise { Promise() {} // Promise can only be constructed in Spawn (or AlreadyDone). - T data_ = nullptr; + T data_{}; bool ready_ = false; Mailbox *rx_ = nullptr; }; From ebe2d1b30fd6111b75ff066d49e58b6e98293f09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Jun 2022 09:55:41 +0200 Subject: [PATCH 10/14] More buildfixing --- Common/Thread/Channel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/Thread/Channel.h b/Common/Thread/Channel.h index 9ccbbd70964c..2e522caf1136 100644 --- a/Common/Thread/Channel.h +++ b/Common/Thread/Channel.h @@ -19,7 +19,7 @@ struct Mailbox { std::mutex mutex_; std::condition_variable condvar_; - T data_ = nullptr; + T data_{}; T Wait() { std::unique_lock lock(mutex_); From 2bb845a0ca5bf4b06a0c1bb2bc1a61206023204b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Jun 2022 11:34:14 +0200 Subject: [PATCH 11/14] VS 2022 warning fix --- ext/gason/gason.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/gason/gason.h b/ext/gason/gason.h index 922751099f9d..cddb3615a777 100644 --- a/ext/gason/gason.h +++ b/ext/gason/gason.h @@ -114,10 +114,10 @@ class JsonAllocator { JsonAllocator() : head(nullptr) {}; JsonAllocator(const JsonAllocator &) = delete; JsonAllocator &operator=(const JsonAllocator &) = delete; - JsonAllocator(JsonAllocator &&x) : head(x.head) { + JsonAllocator(JsonAllocator &&x) noexcept : head(x.head) { x.head = nullptr; } - JsonAllocator &operator=(JsonAllocator &&x) { + JsonAllocator &operator=(JsonAllocator &&x) noexcept { head = x.head; x.head = nullptr; return *this; From c06cf8efaaaf7ede48046d0f1cacfdb75000baca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Jun 2022 11:37:34 +0200 Subject: [PATCH 12/14] Switch Vulkan pipelines to use promises for synchronization Slightly more expensive I guess but shouldn't be much of a bottleneck. --- Common/GPU/Vulkan/VulkanQueueRunner.cpp | 31 ++++++----------------- Common/GPU/Vulkan/VulkanQueueRunner.h | 6 ++--- Common/GPU/Vulkan/VulkanRenderManager.cpp | 16 ++++++++---- Common/GPU/Vulkan/VulkanRenderManager.h | 12 +++++---- Common/Thread/Promise.h | 12 +++++++++ GPU/Vulkan/PipelineManagerVulkan.cpp | 2 +- 6 files changed, 42 insertions(+), 37 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.cpp b/Common/GPU/Vulkan/VulkanQueueRunner.cpp index b00ec67a0102..92b7fb7e8320 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.cpp +++ b/Common/GPU/Vulkan/VulkanQueueRunner.cpp @@ -1182,18 +1182,11 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c case VKRRenderCommand::BIND_GRAPHICS_PIPELINE: { - VKRGraphicsPipeline *pipeline = c.graphics_pipeline.pipeline; - if (pipeline->Pending()) { - // Stall processing, waiting for the compile queue to catch up. - std::unique_lock lock(compileDoneMutex_); - while (!pipeline->pipeline) { - compileDone_.wait(lock); - } - } - if (pipeline->pipeline != lastGraphicsPipeline && pipeline->pipeline != VK_NULL_HANDLE) { - vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline); + VkPipeline pipeline = c.graphics_pipeline.pipeline->BlockUntilReady(); + if (pipeline != lastGraphicsPipeline && pipeline != VK_NULL_HANDLE) { + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); pipelineLayout = c.pipeline.pipelineLayout; - lastGraphicsPipeline = pipeline->pipeline; + lastGraphicsPipeline = pipeline; // Reset dynamic state so it gets refreshed with the new pipeline. lastStencilWriteMask = -1; lastStencilCompareMask = -1; @@ -1204,18 +1197,11 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c case VKRRenderCommand::BIND_COMPUTE_PIPELINE: { - VKRComputePipeline *pipeline = c.compute_pipeline.pipeline; - if (pipeline->Pending()) { - // Stall processing, waiting for the compile queue to catch up. - std::unique_lock lock(compileDoneMutex_); - while (!pipeline->pipeline) { - compileDone_.wait(lock); - } - } - if (pipeline->pipeline != lastComputePipeline && pipeline->pipeline != VK_NULL_HANDLE) { - vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->pipeline); + VkPipeline pipeline = c.graphics_pipeline.pipeline->BlockUntilReady(); + if (pipeline != lastComputePipeline && pipeline != VK_NULL_HANDLE) { + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline); pipelineLayout = c.pipeline.pipelineLayout; - lastComputePipeline = pipeline->pipeline; + lastComputePipeline = pipeline; } break; } @@ -1335,7 +1321,6 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c } default: ERROR_LOG(G3D, "Unimpl queue command"); - ; } } vkCmdEndRenderPass(cmd); diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.h b/Common/GPU/Vulkan/VulkanQueueRunner.h index 401a125d6be9..1d1c4efe8ff0 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.h +++ b/Common/GPU/Vulkan/VulkanQueueRunner.h @@ -4,7 +4,7 @@ #include #include - +#include "Common/Thread/Promise.h" #include "Common/Data/Collections/Hashmaps.h" #include "Common/GPU/Vulkan/VulkanContext.h" #include "Common/GPU/Vulkan/VulkanBarrier.h" @@ -55,11 +55,11 @@ struct VkRenderData { VkPipelineLayout pipelineLayout; } pipeline; struct { - VKRGraphicsPipeline *pipeline; + Promise *pipeline; VkPipelineLayout pipelineLayout; } graphics_pipeline; struct { - VKRComputePipeline *pipeline; + Promise *pipeline; VkPipelineLayout pipelineLayout; } compute_pipeline; struct { diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 45e3a78aaa25..850af030b29e 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -5,6 +5,7 @@ #include "Common/Log.h" #include "Common/StringUtils.h" +#include "Common/TimeUtil.h" #include "Common/GPU/Vulkan/VulkanAlloc.h" #include "Common/GPU/Vulkan/VulkanContext.h" @@ -57,23 +58,26 @@ bool VKRGraphicsPipeline::Create(VulkanContext *vulkan) { desc->pipe.pStages = ss; desc->pipe.stageCount = 2; + double start = time_now_d(); VkPipeline vkpipeline; VkResult result = vkCreateGraphicsPipelines(vulkan->GetDevice(), desc->pipelineCache, 1, &desc->pipe, nullptr, &vkpipeline); + NOTICE_LOG(G3D, "Pipeline creation time: %0.2f ms", (time_now_d() - start) * 1000.0); + bool success = true; if (result == VK_INCOMPLETE) { // Bad (disallowed by spec) return value seen on Adreno in Burnout :( Try to ignore? // Would really like to log more here, we could probably attach more info to desc. // // At least create a null placeholder to avoid creating over and over if something is broken. - pipeline = VK_NULL_HANDLE; + pipeline->Post(VK_NULL_HANDLE); success = false; } else if (result != VK_SUCCESS) { - pipeline = VK_NULL_HANDLE; + pipeline->Post(VK_NULL_HANDLE); ERROR_LOG(G3D, "Failed creating graphics pipeline! result='%s'", VulkanResultToString(result)); success = false; } else { - pipeline = vkpipeline; + pipeline->Post(vkpipeline); } delete desc; @@ -91,11 +95,11 @@ bool VKRComputePipeline::Create(VulkanContext *vulkan) { bool success = true; if (result != VK_SUCCESS) { - pipeline = VK_NULL_HANDLE; + pipeline->Post(VK_NULL_HANDLE); ERROR_LOG(G3D, "Failed creating compute pipeline! result='%s'", VulkanResultToString(result)); success = false; } else { - pipeline = vkpipeline; + pipeline->Post(vkpipeline); } delete desc; @@ -478,6 +482,8 @@ void VulkanRenderManager::CompileThreadFunc() { break; } + NOTICE_LOG(G3D, "Compilation thread has %d pipelines to create", (int)toCompile.size()); + // TODO: Here we can sort the pending pipelines by vertex and fragment shaders, // and split up further. // Those with the same pairs of shaders should be on the same thread. diff --git a/Common/GPU/Vulkan/VulkanRenderManager.h b/Common/GPU/Vulkan/VulkanRenderManager.h index efadc784c654..4b6924752566 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.h +++ b/Common/GPU/Vulkan/VulkanRenderManager.h @@ -144,10 +144,12 @@ struct VKRComputePipelineDesc { // Wrapped pipeline, which will later allow for background compilation while emulating the rest of the frame. struct VKRGraphicsPipeline { VKRGraphicsPipeline() { - pipeline = VK_NULL_HANDLE; + pipeline = Promise::CreateEmpty(); } + VKRGraphicsPipelineDesc *desc = nullptr; // While non-zero, is pending and pipeline isn't valid. - std::atomic pipeline; + + Promise *pipeline; bool Create(VulkanContext *vulkan); bool Pending() const { @@ -160,7 +162,7 @@ struct VKRComputePipeline { pipeline = VK_NULL_HANDLE; } VKRComputePipelineDesc *desc = nullptr; - std::atomic pipeline; + Promise *pipeline; bool Create(VulkanContext *vulkan); bool Pending() const { @@ -261,7 +263,7 @@ class VulkanRenderManager { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER); _dbg_assert_(pipeline != nullptr); VkRenderData data{ VKRRenderCommand::BIND_GRAPHICS_PIPELINE }; - data.graphics_pipeline.pipeline = pipeline; + data.graphics_pipeline.pipeline = pipeline->pipeline; data.graphics_pipeline.pipelineLayout = pipelineLayout; curPipelineFlags_ |= flags; curRenderStep_->commands.push_back(data); @@ -271,7 +273,7 @@ class VulkanRenderManager { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER); _dbg_assert_(pipeline != nullptr); VkRenderData data{ VKRRenderCommand::BIND_COMPUTE_PIPELINE }; - data.compute_pipeline.pipeline = pipeline; + data.compute_pipeline.pipeline = pipeline->pipeline; data.compute_pipeline.pipelineLayout = pipelineLayout; curPipelineFlags_ |= flags; curRenderStep_->commands.push_back(data); diff --git a/Common/Thread/Promise.h b/Common/Thread/Promise.h index 1833a7fa0c49..1e83d6256497 100644 --- a/Common/Thread/Promise.h +++ b/Common/Thread/Promise.h @@ -56,6 +56,13 @@ class Promise { return promise; } + static Promise *CreateEmpty() { + Mailbox *mailbox = new Mailbox(); + Promise *promise = new Promise(); + promise->rx_ = mailbox; + return promise; + } + ~Promise() { // A promise should have been fulfilled before it's destroyed. _assert_(ready_); @@ -90,6 +97,11 @@ class Promise { } } + // For outside injection of data, when not using Spawn + void Post(T data) { + rx_->Send(data); + } + private: Promise() {} diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 73768e38bc73..89092838840e 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -36,7 +36,7 @@ void PipelineManagerVulkan::Clear() { pipelines_.Iterate([&](const VulkanPipelineKey &key, VulkanPipeline *value) { if (value->pipeline) { - VkPipeline pipeline = value->pipeline->pipeline; + VkPipeline pipeline = value->pipeline->pipeline->BlockUntilReady(); vulkan_->Delete().QueueDeletePipeline(pipeline); vulkan_->Delete().QueueCallback([](void *p) { VKRGraphicsPipeline *pipeline = (VKRGraphicsPipeline *)p; From 76bd2395bf98dff88e12340d195af4e76c8383d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Jun 2022 13:22:26 +0200 Subject: [PATCH 13/14] Promise: Add SpawnEmpty (couldn't come up with a better name), fix bug with multiple waiters --- Common/Thread/Channel.h | 2 +- Common/Thread/Promise.h | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Common/Thread/Channel.h b/Common/Thread/Channel.h index 2e522caf1136..b6b23fdebeb1 100644 --- a/Common/Thread/Channel.h +++ b/Common/Thread/Channel.h @@ -43,7 +43,7 @@ struct Mailbox { std::unique_lock lock(mutex_); if (!data_) { data_ = data; - condvar_.notify_one(); + condvar_.notify_all(); return true; } else { // Already has value. diff --git a/Common/Thread/Promise.h b/Common/Thread/Promise.h index 1e83d6256497..4145b4b6c159 100644 --- a/Common/Thread/Promise.h +++ b/Common/Thread/Promise.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "Common/Log.h" #include "Common/Thread/Channel.h" @@ -63,7 +64,14 @@ class Promise { return promise; } + // Allow an empty promise to spawn, too, in case we want to delay it. + void SpawnEmpty(ThreadManager *threadman, std::function fun, TaskType taskType) { + PromiseTask *task = new PromiseTask(fun, rx_, taskType); + threadman->EnqueueTask(task); + } + ~Promise() { + std::lock_guard guard(readyMutex_); // A promise should have been fulfilled before it's destroyed. _assert_(ready_); _assert_(!rx_); @@ -71,6 +79,7 @@ class Promise { // Returns T if the data is ready, nullptr if it's not. T Poll() { + std::lock_guard guard(readyMutex_); if (ready_) { return data_; } else { @@ -86,6 +95,7 @@ class Promise { } T BlockUntilReady() { + std::lock_guard guard(readyMutex_); if (ready_) { return data_; } else { @@ -108,5 +118,6 @@ class Promise { // Promise can only be constructed in Spawn (or AlreadyDone). T data_{}; bool ready_ = false; + std::mutex readyMutex_; Mailbox *rx_ = nullptr; }; From fb3f417e77faf081c47d292ae7de95a1f18ee227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 3 Sep 2022 16:13:51 +0200 Subject: [PATCH 14/14] Fix lying comment, log level reduction --- Common/GPU/Vulkan/VulkanRenderManager.cpp | 4 ++-- GPU/Vulkan/ShaderManagerVulkan.cpp | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 850af030b29e..7741fb2e448a 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -62,7 +62,7 @@ bool VKRGraphicsPipeline::Create(VulkanContext *vulkan) { VkPipeline vkpipeline; VkResult result = vkCreateGraphicsPipelines(vulkan->GetDevice(), desc->pipelineCache, 1, &desc->pipe, nullptr, &vkpipeline); - NOTICE_LOG(G3D, "Pipeline creation time: %0.2f ms", (time_now_d() - start) * 1000.0); + INFO_LOG(G3D, "Pipeline creation time: %0.2f ms", (time_now_d() - start) * 1000.0); bool success = true; if (result == VK_INCOMPLETE) { @@ -482,7 +482,7 @@ void VulkanRenderManager::CompileThreadFunc() { break; } - NOTICE_LOG(G3D, "Compilation thread has %d pipelines to create", (int)toCompile.size()); + INFO_LOG(G3D, "Compilation thread has %d pipelines to create", (int)toCompile.size()); // TODO: Here we can sort the pending pipelines by vertex and fragment shaders, // and split up further. diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index 5f2d1ffb5d1f..439602ae4637 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -88,7 +88,6 @@ VulkanFragmentShader::VulkanFragmentShader(VulkanContext *vulkan, FShaderID id, module_ = CompileShaderModuleAsync(vulkan, VK_SHADER_STAGE_FRAGMENT_BIT, source_.c_str()); if (!module_) { failed_ = true; - return; } else { VERBOSE_LOG(G3D, "Compiled fragment shader:\n%s\n", (const char *)code); } @@ -119,9 +118,8 @@ VulkanVertexShader::VulkanVertexShader(VulkanContext *vulkan, VShaderID id, cons module_ = CompileShaderModuleAsync(vulkan, VK_SHADER_STAGE_VERTEX_BIT, source_.c_str()); if (!module_) { failed_ = true; - return; } else { - VERBOSE_LOG(G3D, "Compiled fragment shader:\n%s\n", (const char *)code); + VERBOSE_LOG(G3D, "Compiled vertex shader:\n%s\n", (const char *)code); } }