diff options
| author | 2020-07-30 15:41:11 -0400 | |
|---|---|---|
| committer | 2020-08-16 12:02:22 -0400 | |
| commit | 4539073ce1d8fd6df03263e826d3805b4909e055 (patch) | |
| tree | d0ed30c327c5b6da9c6d6c8ba256803167f00de2 /src | |
| parent | Vk Async pipeline compilation (diff) | |
| download | yuzu-4539073ce1d8fd6df03263e826d3805b4909e055.tar.gz yuzu-4539073ce1d8fd6df03263e826d3805b4909e055.tar.xz yuzu-4539073ce1d8fd6df03263e826d3805b4909e055.zip | |
Address feedback. Bruteforce delete duplicates
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_graphics_pipeline.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 16 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.h | 19 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 18 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.h | 2 | ||||
| -rw-r--r-- | src/video_core/shader/async_shaders.cpp | 135 | ||||
| -rw-r--r-- | src/video_core/shader/async_shaders.h | 4 |
7 files changed, 116 insertions, 80 deletions
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index 39c73a139..d50bd347c 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h | |||
| @@ -54,7 +54,7 @@ public: | |||
| 54 | return renderpass; | 54 | return renderpass; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | const GraphicsPipelineCacheKey& GetCacheKey() { | 57 | const GraphicsPipelineCacheKey& GetCacheKey() const { |
| 58 | return m_key; | 58 | return m_key; |
| 59 | } | 59 | } |
| 60 | 60 | ||
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 45d4dcb8c..a7ce621ca 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -205,20 +205,20 @@ std::array<Shader*, Maxwell::MaxShaderProgram> VKPipelineCache::GetShaders() { | |||
| 205 | return last_shaders = shaders; | 205 | return last_shaders = shaders; |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | VKGraphicsPipeline& VKPipelineCache::GetGraphicsPipeline( | 208 | VKGraphicsPipeline* VKPipelineCache::GetGraphicsPipeline( |
| 209 | const GraphicsPipelineCacheKey& key, VideoCommon::Shader::AsyncShaders& async_shaders) { | 209 | const GraphicsPipelineCacheKey& key, VideoCommon::Shader::AsyncShaders& async_shaders) { |
| 210 | MICROPROFILE_SCOPE(Vulkan_PipelineCache); | 210 | MICROPROFILE_SCOPE(Vulkan_PipelineCache); |
| 211 | 211 | ||
| 212 | if (last_graphics_pipeline && last_graphics_key == key) { | 212 | if (last_graphics_pipeline && last_graphics_key == key) { |
| 213 | return *last_graphics_pipeline; | 213 | return last_graphics_pipeline; |
| 214 | } | 214 | } |
| 215 | last_graphics_key = key; | 215 | last_graphics_key = key; |
| 216 | 216 | ||
| 217 | if (device.UseAsynchronousShaders()) { | 217 | if (device.UseAsynchronousShaders()) { |
| 218 | auto work = async_shaders.GetCompletedWork(); | 218 | auto work = async_shaders.GetCompletedWork(); |
| 219 | for (std::size_t i = 0; i < work.size(); ++i) { | 219 | for (auto& w : work) { |
| 220 | auto& entry = graphics_cache.at(work[i].pipeline->GetCacheKey()); | 220 | auto& entry = graphics_cache.at(w.pipeline->GetCacheKey()); |
| 221 | entry = std::move(work[i].pipeline); | 221 | entry = std::move(w.pipeline); |
| 222 | } | 222 | } |
| 223 | const auto [pair, is_cache_miss] = graphics_cache.try_emplace(key); | 223 | const auto [pair, is_cache_miss] = graphics_cache.try_emplace(key); |
| 224 | if (is_cache_miss) { | 224 | if (is_cache_miss) { |
| @@ -227,7 +227,8 @@ VKGraphicsPipeline& VKPipelineCache::GetGraphicsPipeline( | |||
| 227 | async_shaders.QueueVulkanShader(this, bindings, program, key.renderpass_params, | 227 | async_shaders.QueueVulkanShader(this, bindings, program, key.renderpass_params, |
| 228 | key.padding, key.shaders, key.fixed_state); | 228 | key.padding, key.shaders, key.fixed_state); |
| 229 | } | 229 | } |
| 230 | return *(last_graphics_pipeline = graphics_cache.at(key).get()); | 230 | last_graphics_pipeline = graphics_cache.at(key).get(); |
| 231 | return last_graphics_pipeline; | ||
| 231 | } | 232 | } |
| 232 | 233 | ||
| 233 | const auto [pair, is_cache_miss] = graphics_cache.try_emplace(key); | 234 | const auto [pair, is_cache_miss] = graphics_cache.try_emplace(key); |
| @@ -239,7 +240,8 @@ VKGraphicsPipeline& VKPipelineCache::GetGraphicsPipeline( | |||
| 239 | update_descriptor_queue, renderpass_cache, key, | 240 | update_descriptor_queue, renderpass_cache, key, |
| 240 | bindings, program); | 241 | bindings, program); |
| 241 | } | 242 | } |
| 242 | return *(last_graphics_pipeline = entry.get()); | 243 | last_graphics_pipeline = entry.get(); |
| 244 | return last_graphics_pipeline; | ||
| 243 | } | 245 | } |
| 244 | 246 | ||
| 245 | VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCacheKey& key) { | 247 | VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCacheKey& key) { |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index c70da6da4..404f2b3f7 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h | |||
| @@ -153,31 +153,46 @@ public: | |||
| 153 | 153 | ||
| 154 | std::array<Shader*, Maxwell::MaxShaderProgram> GetShaders(); | 154 | std::array<Shader*, Maxwell::MaxShaderProgram> GetShaders(); |
| 155 | 155 | ||
| 156 | VKGraphicsPipeline& GetGraphicsPipeline(const GraphicsPipelineCacheKey& key, | 156 | VKGraphicsPipeline* GetGraphicsPipeline(const GraphicsPipelineCacheKey& key, |
| 157 | VideoCommon::Shader::AsyncShaders& async_shaders); | 157 | VideoCommon::Shader::AsyncShaders& async_shaders); |
| 158 | 158 | ||
| 159 | VKComputePipeline& GetComputePipeline(const ComputePipelineCacheKey& key); | 159 | VKComputePipeline& GetComputePipeline(const ComputePipelineCacheKey& key); |
| 160 | 160 | ||
| 161 | const VKDevice& GetDevice() { | 161 | const VKDevice& GetDevice() const { |
| 162 | return device; | 162 | return device; |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | VKScheduler& GetScheduler() { | 165 | VKScheduler& GetScheduler() { |
| 166 | return scheduler; | 166 | return scheduler; |
| 167 | } | 167 | } |
| 168 | const VKScheduler& GetScheduler() const { | ||
| 169 | return scheduler; | ||
| 170 | } | ||
| 168 | 171 | ||
| 169 | VKDescriptorPool& GetDescriptorPool() { | 172 | VKDescriptorPool& GetDescriptorPool() { |
| 170 | return descriptor_pool; | 173 | return descriptor_pool; |
| 171 | } | 174 | } |
| 172 | 175 | ||
| 176 | const VKDescriptorPool& GetDescriptorPool() const { | ||
| 177 | return descriptor_pool; | ||
| 178 | } | ||
| 179 | |||
| 173 | VKUpdateDescriptorQueue& GetUpdateDescriptorQueue() { | 180 | VKUpdateDescriptorQueue& GetUpdateDescriptorQueue() { |
| 174 | return update_descriptor_queue; | 181 | return update_descriptor_queue; |
| 175 | } | 182 | } |
| 176 | 183 | ||
| 184 | const VKUpdateDescriptorQueue& GetUpdateDescriptorQueue() const { | ||
| 185 | return update_descriptor_queue; | ||
| 186 | } | ||
| 187 | |||
| 177 | VKRenderPassCache& GetRenderpassCache() { | 188 | VKRenderPassCache& GetRenderpassCache() { |
| 178 | return renderpass_cache; | 189 | return renderpass_cache; |
| 179 | } | 190 | } |
| 180 | 191 | ||
| 192 | const VKRenderPassCache& GetRenderpassCache() const { | ||
| 193 | return renderpass_cache; | ||
| 194 | } | ||
| 195 | |||
| 181 | protected: | 196 | protected: |
| 182 | void OnShaderRemoval(Shader* shader) final; | 197 | void OnShaderRemoval(Shader* shader) final; |
| 183 | 198 | ||
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 6310e898c..fc1b51a96 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -404,10 +404,12 @@ RasterizerVulkan::RasterizerVulkan(Core::System& system, Core::Frontend::EmuWind | |||
| 404 | wfi_event{device.GetLogical().CreateNewEvent()}, async_shaders{renderer} { | 404 | wfi_event{device.GetLogical().CreateNewEvent()}, async_shaders{renderer} { |
| 405 | scheduler.SetQueryCache(query_cache); | 405 | scheduler.SetQueryCache(query_cache); |
| 406 | if (device.UseAsynchronousShaders()) { | 406 | if (device.UseAsynchronousShaders()) { |
| 407 | // The following is subject to move into the allocate workers method, to be api agnostic | ||
| 408 | |||
| 407 | // Max worker threads we should allow | 409 | // Max worker threads we should allow |
| 408 | constexpr auto MAX_THREADS = 2u; | 410 | constexpr u32 MAX_THREADS = 4; |
| 409 | // Amount of threads we should reserve for other parts of yuzu | 411 | // Amount of threads we should reserve for other parts of yuzu |
| 410 | constexpr auto RESERVED_THREADS = 6u; | 412 | constexpr u32 RESERVED_THREADS = 6; |
| 411 | // Get the amount of threads we can use(this can return zero) | 413 | // Get the amount of threads we can use(this can return zero) |
| 412 | const auto cpu_thread_count = | 414 | const auto cpu_thread_count = |
| 413 | std::max(RESERVED_THREADS, std::thread::hardware_concurrency()); | 415 | std::max(RESERVED_THREADS, std::thread::hardware_concurrency()); |
| @@ -456,16 +458,16 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 456 | key.renderpass_params = GetRenderPassParams(texceptions); | 458 | key.renderpass_params = GetRenderPassParams(texceptions); |
| 457 | key.padding = 0; | 459 | key.padding = 0; |
| 458 | 460 | ||
| 459 | auto& pipeline = pipeline_cache.GetGraphicsPipeline(key, async_shaders); | 461 | auto pipeline = pipeline_cache.GetGraphicsPipeline(key, async_shaders); |
| 460 | if (&pipeline == nullptr || pipeline.GetHandle() == VK_NULL_HANDLE) { | 462 | if (pipeline == nullptr || pipeline->GetHandle() == VK_NULL_HANDLE) { |
| 461 | // Async graphics pipeline was not ready. | 463 | // Async graphics pipeline was not ready. |
| 462 | system.GPU().TickWork(); | 464 | system.GPU().TickWork(); |
| 463 | return; | 465 | return; |
| 464 | } | 466 | } |
| 465 | 467 | ||
| 466 | scheduler.BindGraphicsPipeline(pipeline.GetHandle()); | 468 | scheduler.BindGraphicsPipeline(pipeline->GetHandle()); |
| 467 | 469 | ||
| 468 | const auto renderpass = pipeline.GetRenderPass(); | 470 | const auto renderpass = pipeline->GetRenderPass(); |
| 469 | const auto [framebuffer, render_area] = ConfigureFramebuffers(renderpass); | 471 | const auto [framebuffer, render_area] = ConfigureFramebuffers(renderpass); |
| 470 | scheduler.RequestRenderpass(renderpass, framebuffer, render_area); | 472 | scheduler.RequestRenderpass(renderpass, framebuffer, render_area); |
| 471 | 473 | ||
| @@ -475,8 +477,8 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 475 | 477 | ||
| 476 | BeginTransformFeedback(); | 478 | BeginTransformFeedback(); |
| 477 | 479 | ||
| 478 | const auto pipeline_layout = pipeline.GetLayout(); | 480 | const auto pipeline_layout = pipeline->GetLayout(); |
| 479 | const auto descriptor_set = pipeline.CommitDescriptorSet(); | 481 | const auto descriptor_set = pipeline->CommitDescriptorSet(); |
| 480 | scheduler.Record([pipeline_layout, descriptor_set, draw_params](vk::CommandBuffer cmdbuf) { | 482 | scheduler.Record([pipeline_layout, descriptor_set, draw_params](vk::CommandBuffer cmdbuf) { |
| 481 | if (descriptor_set) { | 483 | if (descriptor_set) { |
| 482 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, | 484 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 27604b9a3..f640ba649 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -287,7 +287,6 @@ private: | |||
| 287 | VKMemoryManager& memory_manager; | 287 | VKMemoryManager& memory_manager; |
| 288 | StateTracker& state_tracker; | 288 | StateTracker& state_tracker; |
| 289 | VKScheduler& scheduler; | 289 | VKScheduler& scheduler; |
| 290 | VideoCommon::Shader::AsyncShaders async_shaders; | ||
| 291 | 290 | ||
| 292 | VKStagingBufferPool staging_pool; | 291 | VKStagingBufferPool staging_pool; |
| 293 | VKDescriptorPool descriptor_pool; | 292 | VKDescriptorPool descriptor_pool; |
| @@ -307,6 +306,7 @@ private: | |||
| 307 | vk::Buffer default_buffer; | 306 | vk::Buffer default_buffer; |
| 308 | VKMemoryCommit default_buffer_commit; | 307 | VKMemoryCommit default_buffer_commit; |
| 309 | vk::Event wfi_event; | 308 | vk::Event wfi_event; |
| 309 | VideoCommon::Shader::AsyncShaders async_shaders; | ||
| 310 | 310 | ||
| 311 | std::array<View, Maxwell::NumRenderTargets> color_attachments; | 311 | std::array<View, Maxwell::NumRenderTargets> color_attachments; |
| 312 | View zeta_attachment; | 312 | View zeta_attachment; |
diff --git a/src/video_core/shader/async_shaders.cpp b/src/video_core/shader/async_shaders.cpp index 335a0d05b..c536b025b 100644 --- a/src/video_core/shader/async_shaders.cpp +++ b/src/video_core/shader/async_shaders.cpp | |||
| @@ -111,20 +111,19 @@ void AsyncShaders::QueueOpenGLShader(const OpenGL::Device& device, | |||
| 111 | VideoCommon::Shader::CompilerSettings compiler_settings, | 111 | VideoCommon::Shader::CompilerSettings compiler_settings, |
| 112 | const VideoCommon::Shader::Registry& registry, | 112 | const VideoCommon::Shader::Registry& registry, |
| 113 | VAddr cpu_addr) { | 113 | VAddr cpu_addr) { |
| 114 | WorkerParams params{device.UseAssemblyShaders() ? AsyncShaders::Backend::GLASM | 114 | auto p = std::make_unique<WorkerParams>(); |
| 115 | : AsyncShaders::Backend::OpenGL, | 115 | p->backend = device.UseAssemblyShaders() ? Backend::GLASM : Backend::OpenGL; |
| 116 | &device, | 116 | p->device = &device; |
| 117 | shader_type, | 117 | p->shader_type = shader_type; |
| 118 | uid, | 118 | p->uid = uid; |
| 119 | std::move(code), | 119 | p->code = std::move(code); |
| 120 | std::move(code_b), | 120 | p->code_b = std::move(code_b); |
| 121 | main_offset, | 121 | p->main_offset = main_offset; |
| 122 | compiler_settings, | 122 | p->compiler_settings = compiler_settings; |
| 123 | ®istry, | 123 | p->registry = ®istry; |
| 124 | cpu_addr}; | 124 | p->cpu_address = cpu_addr; |
| 125 | |||
| 126 | std::unique_lock lock(queue_mutex); | 125 | std::unique_lock lock(queue_mutex); |
| 127 | pending_queue.push_back(std::move(params)); | 126 | pending_queue.push(std::move(p)); |
| 128 | cv.notify_one(); | 127 | cv.notify_one(); |
| 129 | } | 128 | } |
| 130 | 129 | ||
| @@ -134,19 +133,19 @@ void AsyncShaders::QueueVulkanShader( | |||
| 134 | std::array<GPUVAddr, Vulkan::Maxwell::MaxShaderProgram> shaders, | 133 | std::array<GPUVAddr, Vulkan::Maxwell::MaxShaderProgram> shaders, |
| 135 | Vulkan::FixedPipelineState fixed_state) { | 134 | Vulkan::FixedPipelineState fixed_state) { |
| 136 | 135 | ||
| 137 | WorkerParams params{ | 136 | auto p = std::make_unique<WorkerParams>(); |
| 138 | .backend = AsyncShaders::Backend::Vulkan, | 137 | |
| 139 | .pp_cache = pp_cache, | 138 | p->backend = Backend::Vulkan; |
| 140 | .bindings = bindings, | 139 | p->pp_cache = pp_cache; |
| 141 | .program = program, | 140 | p->bindings = bindings; |
| 142 | .renderpass_params = renderpass_params, | 141 | p->program = program; |
| 143 | .padding = padding, | 142 | p->renderpass_params = renderpass_params; |
| 144 | .shaders = shaders, | 143 | p->padding = padding; |
| 145 | .fixed_state = fixed_state, | 144 | p->shaders = shaders; |
| 146 | }; | 145 | p->fixed_state = fixed_state; |
| 147 | 146 | ||
| 148 | std::unique_lock lock(queue_mutex); | 147 | std::unique_lock lock(queue_mutex); |
| 149 | pending_queue.push_back(std::move(params)); | 148 | pending_queue.push(std::move(p)); |
| 150 | cv.notify_one(); | 149 | cv.notify_one(); |
| 151 | } | 150 | } |
| 152 | 151 | ||
| @@ -168,64 +167,82 @@ void AsyncShaders::ShaderCompilerThread(Core::Frontend::GraphicsContext* context | |||
| 168 | if (pending_queue.empty()) { | 167 | if (pending_queue.empty()) { |
| 169 | continue; | 168 | continue; |
| 170 | } | 169 | } |
| 171 | // Pull work from queue | ||
| 172 | WorkerParams work = std::move(pending_queue.front()); | ||
| 173 | pending_queue.pop_front(); | ||
| 174 | 170 | ||
| 171 | // Pull work from queue | ||
| 172 | auto work = std::move(pending_queue.front()); | ||
| 173 | pending_queue.pop(); | ||
| 175 | lock.unlock(); | 174 | lock.unlock(); |
| 176 | 175 | ||
| 177 | if (work.backend == AsyncShaders::Backend::OpenGL || | 176 | if (work->backend == Backend::OpenGL || work->backend == Backend::GLASM) { |
| 178 | work.backend == AsyncShaders::Backend::GLASM) { | 177 | VideoCommon::Shader::Registry registry = *work->registry; |
| 179 | VideoCommon::Shader::Registry registry = *work.registry; | 178 | const ShaderIR ir(work->code, work->main_offset, work->compiler_settings, registry); |
| 180 | const ShaderIR ir(work.code, work.main_offset, work.compiler_settings, registry); | ||
| 181 | const auto scope = context->Acquire(); | 179 | const auto scope = context->Acquire(); |
| 182 | auto program = | 180 | auto program = |
| 183 | OpenGL::BuildShader(*work.device, work.shader_type, work.uid, ir, registry); | 181 | OpenGL::BuildShader(*work->device, work->shader_type, work->uid, ir, registry); |
| 184 | Result result{}; | 182 | Result result{}; |
| 185 | result.backend = work.backend; | 183 | result.backend = work->backend; |
| 186 | result.cpu_address = work.cpu_address; | 184 | result.cpu_address = work->cpu_address; |
| 187 | result.uid = work.uid; | 185 | result.uid = work->uid; |
| 188 | result.code = std::move(work.code); | 186 | result.code = std::move(work->code); |
| 189 | result.code_b = std::move(work.code_b); | 187 | result.code_b = std::move(work->code_b); |
| 190 | result.shader_type = work.shader_type; | 188 | result.shader_type = work->shader_type; |
| 191 | 189 | // LOG_CRITICAL(Render_Vulkan, "Shader hast been Compiled \t0x{:016X} id {}", | |
| 192 | if (work.backend == AsyncShaders::Backend::OpenGL) { | 190 | // result.uid, id); |
| 191 | |||
| 192 | if (work->backend == Backend::OpenGL) { | ||
| 193 | result.program.opengl = std::move(program->source_program); | 193 | result.program.opengl = std::move(program->source_program); |
| 194 | } else if (work.backend == AsyncShaders::Backend::GLASM) { | 194 | } else if (work->backend == Backend::GLASM) { |
| 195 | result.program.glasm = std::move(program->assembly_program); | 195 | result.program.glasm = std::move(program->assembly_program); |
| 196 | } | 196 | } |
| 197 | work.reset(); | ||
| 197 | 198 | ||
| 198 | { | 199 | { |
| 199 | std::unique_lock complete_lock(completed_mutex); | 200 | std::unique_lock complete_lock(completed_mutex); |
| 200 | finished_work.push_back(std::move(result)); | 201 | finished_work.push_back(std::move(result)); |
| 201 | } | 202 | } |
| 202 | 203 | } else if (work->backend == Backend::Vulkan) { | |
| 203 | } else if (work.backend == AsyncShaders::Backend::Vulkan) { | ||
| 204 | Vulkan::GraphicsPipelineCacheKey params_key{ | 204 | Vulkan::GraphicsPipelineCacheKey params_key{ |
| 205 | work.renderpass_params, | 205 | .renderpass_params = work->renderpass_params, |
| 206 | work.padding, | 206 | .padding = work->padding, |
| 207 | work.shaders, | 207 | .shaders = work->shaders, |
| 208 | work.fixed_state, | 208 | .fixed_state = work->fixed_state, |
| 209 | }; | 209 | }; |
| 210 | |||
| 210 | { | 211 | { |
| 211 | std::unique_lock complete_lock(completed_mutex); | 212 | std::unique_lock find_lock{completed_mutex}; |
| 213 | for (size_t i = 0; i < finished_work.size(); ++i) { | ||
| 214 | // This loop deletes duplicate pipelines in finished_work | ||
| 215 | // in favor of the pipeline about to be created | ||
| 216 | |||
| 217 | if (finished_work[i].pipeline && | ||
| 218 | finished_work[i].pipeline->GetCacheKey().Hash() == params_key.Hash()) { | ||
| 219 | LOG_CRITICAL(Render_Vulkan, | ||
| 220 | "Pipeliene was already here \t0x{:016X} matches 0x{:016X} ", | ||
| 221 | params_key.Hash(), | ||
| 222 | finished_work[i].pipeline->GetCacheKey().Hash()); | ||
| 223 | finished_work.erase(finished_work.begin() + i); | ||
| 224 | } | ||
| 225 | } | ||
| 226 | find_lock.unlock(); | ||
| 227 | } | ||
| 228 | |||
| 229 | auto pipeline = std::make_unique<Vulkan::VKGraphicsPipeline>( | ||
| 230 | work->pp_cache->GetDevice(), work->pp_cache->GetScheduler(), | ||
| 231 | work->pp_cache->GetDescriptorPool(), work->pp_cache->GetUpdateDescriptorQueue(), | ||
| 232 | work->pp_cache->GetRenderpassCache(), params_key, work->bindings, work->program); | ||
| 212 | 233 | ||
| 213 | // Duplicate creation of pipelines leads to instability and crashing, caused by a | 234 | { |
| 214 | // race condition but band-aid solution is locking the making of the pipeline | 235 | std::unique_lock complete_lock(completed_mutex); |
| 215 | // results in only one pipeline created at a time. | ||
| 216 | Result result{ | 236 | Result result{ |
| 217 | .backend = work.backend, | 237 | .backend = Backend::Vulkan, |
| 218 | .pipeline = std::make_unique<Vulkan::VKGraphicsPipeline>( | 238 | .pipeline = std::move(pipeline), |
| 219 | work.pp_cache->GetDevice(), work.pp_cache->GetScheduler(), | ||
| 220 | work.pp_cache->GetDescriptorPool(), | ||
| 221 | work.pp_cache->GetUpdateDescriptorQueue(), | ||
| 222 | work.pp_cache->GetRenderpassCache(), params_key, work.bindings, | ||
| 223 | work.program), | ||
| 224 | }; | 239 | }; |
| 225 | |||
| 226 | finished_work.push_back(std::move(result)); | 240 | finished_work.push_back(std::move(result)); |
| 241 | complete_lock.unlock(); | ||
| 227 | } | 242 | } |
| 228 | } | 243 | } |
| 244 | // Give a chance for another thread to get work. Lessens duplicates | ||
| 245 | std::this_thread::yield(); | ||
| 229 | } | 246 | } |
| 230 | } | 247 | } |
| 231 | 248 | ||
diff --git a/src/video_core/shader/async_shaders.h b/src/video_core/shader/async_shaders.h index 702026ce2..d4eeb8fb6 100644 --- a/src/video_core/shader/async_shaders.h +++ b/src/video_core/shader/async_shaders.h | |||
| @@ -100,7 +100,7 @@ private: | |||
| 100 | bool HasWorkQueued(); | 100 | bool HasWorkQueued(); |
| 101 | 101 | ||
| 102 | struct WorkerParams { | 102 | struct WorkerParams { |
| 103 | AsyncShaders::Backend backend; | 103 | Backend backend; |
| 104 | // For OGL | 104 | // For OGL |
| 105 | const OpenGL::Device* device; | 105 | const OpenGL::Device* device; |
| 106 | Tegra::Engines::ShaderType shader_type; | 106 | Tegra::Engines::ShaderType shader_type; |
| @@ -128,7 +128,7 @@ private: | |||
| 128 | std::atomic<bool> is_thread_exiting{}; | 128 | std::atomic<bool> is_thread_exiting{}; |
| 129 | std::vector<std::unique_ptr<Core::Frontend::GraphicsContext>> context_list; | 129 | std::vector<std::unique_ptr<Core::Frontend::GraphicsContext>> context_list; |
| 130 | std::vector<std::thread> worker_threads; | 130 | std::vector<std::thread> worker_threads; |
| 131 | std::deque<WorkerParams> pending_queue; | 131 | std::queue<std::unique_ptr<WorkerParams>> pending_queue; |
| 132 | std::vector<AsyncShaders::Result> finished_work; | 132 | std::vector<AsyncShaders::Result> finished_work; |
| 133 | Core::Frontend::EmuWindow& emu_window; | 133 | Core::Frontend::EmuWindow& emu_window; |
| 134 | }; | 134 | }; |