diff options
11 files changed, 100 insertions, 34 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index b7bc11416..85ee27333 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp | |||
| @@ -59,6 +59,13 @@ std::string Image(EmitContext& ctx, IR::TextureInstInfo info, | |||
| 59 | } | 59 | } |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | bool IsTextureMsaa(EmitContext& ctx, const IR::TextureInstInfo& info) { | ||
| 63 | if (info.type == TextureType::Buffer) { | ||
| 64 | return false; | ||
| 65 | } | ||
| 66 | return ctx.info.texture_descriptors.at(info.descriptor_index).is_multisample; | ||
| 67 | } | ||
| 68 | |||
| 62 | std::string_view TextureType(IR::TextureInstInfo info, bool is_ms = false) { | 69 | std::string_view TextureType(IR::TextureInstInfo info, bool is_ms = false) { |
| 63 | if (info.is_depth) { | 70 | if (info.is_depth) { |
| 64 | switch (info.type) { | 71 | switch (info.type) { |
| @@ -535,7 +542,8 @@ void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& | |||
| 535 | ScalarS32 lod, [[maybe_unused]] const IR::Value& skip_mips) { | 542 | ScalarS32 lod, [[maybe_unused]] const IR::Value& skip_mips) { |
| 536 | const auto info{inst.Flags<IR::TextureInstInfo>()}; | 543 | const auto info{inst.Flags<IR::TextureInstInfo>()}; |
| 537 | const std::string texture{Texture(ctx, info, index)}; | 544 | const std::string texture{Texture(ctx, info, index)}; |
| 538 | const std::string_view type{TextureType(info)}; | 545 | const bool is_msaa{IsTextureMsaa(ctx, info)}; |
| 546 | const std::string_view type{TextureType(info, is_msaa)}; | ||
| 539 | ctx.Add("TXQ {},{},{},{};", inst, lod, texture, type); | 547 | ctx.Add("TXQ {},{},{},{};", inst, lod, texture, type); |
| 540 | } | 548 | } |
| 541 | 549 | ||
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp index 4be2c25ec..f335c8af0 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp | |||
| @@ -25,6 +25,13 @@ std::string Image(EmitContext& ctx, const IR::TextureInstInfo& info, const IR::V | |||
| 25 | return fmt::format("img{}{}", def.binding, index_offset); | 25 | return fmt::format("img{}{}", def.binding, index_offset); |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | bool IsTextureMsaa(EmitContext& ctx, const IR::TextureInstInfo& info) { | ||
| 29 | if (info.type == TextureType::Buffer) { | ||
| 30 | return false; | ||
| 31 | } | ||
| 32 | return ctx.info.texture_descriptors.at(info.descriptor_index).is_multisample; | ||
| 33 | } | ||
| 34 | |||
| 28 | std::string CastToIntVec(std::string_view value, const IR::TextureInstInfo& info) { | 35 | std::string CastToIntVec(std::string_view value, const IR::TextureInstInfo& info) { |
| 29 | switch (info.type) { | 36 | switch (info.type) { |
| 30 | case TextureType::Color1D: | 37 | case TextureType::Color1D: |
| @@ -463,26 +470,33 @@ void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& | |||
| 463 | std::string_view lod, const IR::Value& skip_mips_val) { | 470 | std::string_view lod, const IR::Value& skip_mips_val) { |
| 464 | const auto info{inst.Flags<IR::TextureInstInfo>()}; | 471 | const auto info{inst.Flags<IR::TextureInstInfo>()}; |
| 465 | const auto texture{Texture(ctx, info, index)}; | 472 | const auto texture{Texture(ctx, info, index)}; |
| 473 | const bool is_msaa{IsTextureMsaa(ctx, info)}; | ||
| 466 | const bool skip_mips{skip_mips_val.U1()}; | 474 | const bool skip_mips{skip_mips_val.U1()}; |
| 467 | const auto mips{ | 475 | const auto mips{skip_mips ? "0u" : fmt::format("uint(textureQueryLevels({}))", texture)}; |
| 468 | [&] { return skip_mips ? "0u" : fmt::format("uint(textureQueryLevels({}))", texture); }}; | 476 | if (is_msaa && !skip_mips) { |
| 477 | throw NotImplementedException("EmitImageQueryDimensions MSAA QueryLevels"); | ||
| 478 | } | ||
| 479 | if (info.type == TextureType::Buffer && !skip_mips) { | ||
| 480 | throw NotImplementedException("EmitImageQueryDimensions TextureType::Buffer QueryLevels"); | ||
| 481 | } | ||
| 482 | const bool uses_lod{!is_msaa && info.type != TextureType::Buffer}; | ||
| 483 | const auto lod_str{uses_lod ? fmt::format(",int({})", lod) : ""}; | ||
| 469 | switch (info.type) { | 484 | switch (info.type) { |
| 470 | case TextureType::Color1D: | 485 | case TextureType::Color1D: |
| 471 | return ctx.AddU32x4("{}=uvec4(uint(textureSize({},int({}))),0u,0u,{});", inst, texture, lod, | 486 | return ctx.AddU32x4("{}=uvec4(uint(textureSize({}{})),0u,0u,{});", inst, texture, lod_str, |
| 472 | mips()); | 487 | mips); |
| 473 | case TextureType::ColorArray1D: | 488 | case TextureType::ColorArray1D: |
| 474 | case TextureType::Color2D: | 489 | case TextureType::Color2D: |
| 475 | case TextureType::ColorCube: | 490 | case TextureType::ColorCube: |
| 476 | case TextureType::Color2DRect: | 491 | case TextureType::Color2DRect: |
| 477 | return ctx.AddU32x4("{}=uvec4(uvec2(textureSize({},int({}))),0u,{});", inst, texture, lod, | 492 | return ctx.AddU32x4("{}=uvec4(uvec2(textureSize({}{})),0u,{});", inst, texture, lod_str, |
| 478 | mips()); | 493 | mips); |
| 479 | case TextureType::ColorArray2D: | 494 | case TextureType::ColorArray2D: |
| 480 | case TextureType::Color3D: | 495 | case TextureType::Color3D: |
| 481 | case TextureType::ColorArrayCube: | 496 | case TextureType::ColorArrayCube: |
| 482 | return ctx.AddU32x4("{}=uvec4(uvec3(textureSize({},int({}))),{});", inst, texture, lod, | 497 | return ctx.AddU32x4("{}=uvec4(uvec3(textureSize({}{})),{});", inst, texture, lod_str, mips); |
| 483 | mips()); | ||
| 484 | case TextureType::Buffer: | 498 | case TextureType::Buffer: |
| 485 | throw NotImplementedException("EmitImageQueryDimensions Texture buffers"); | 499 | return ctx.AddU32x4("{}=uvec4(uint(textureSize({})),0u,0u,{});", inst, texture, mips); |
| 486 | } | 500 | } |
| 487 | throw LogicError("Unspecified image type {}", info.type.Value()); | 501 | throw LogicError("Unspecified image type {}", info.type.Value()); |
| 488 | } | 502 | } |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 3b969d915..02073c420 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | |||
| @@ -201,6 +201,13 @@ Id Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) { | |||
| 201 | } | 201 | } |
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | bool IsTextureMsaa(EmitContext& ctx, const IR::TextureInstInfo& info) { | ||
| 205 | if (info.type == TextureType::Buffer) { | ||
| 206 | return false; | ||
| 207 | } | ||
| 208 | return ctx.textures.at(info.descriptor_index).is_multisample; | ||
| 209 | } | ||
| 210 | |||
| 204 | Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) { | 211 | Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) { |
| 205 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 212 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 206 | if (info.relaxed_precision != 0) { | 213 | if (info.relaxed_precision != 0) { |
| @@ -452,24 +459,26 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i | |||
| 452 | const Id zero{ctx.u32_zero_value}; | 459 | const Id zero{ctx.u32_zero_value}; |
| 453 | const bool skip_mips{skip_mips_val.U1()}; | 460 | const bool skip_mips{skip_mips_val.U1()}; |
| 454 | const auto mips{[&] { return skip_mips ? zero : ctx.OpImageQueryLevels(ctx.U32[1], image); }}; | 461 | const auto mips{[&] { return skip_mips ? zero : ctx.OpImageQueryLevels(ctx.U32[1], image); }}; |
| 462 | const bool is_msaa{IsTextureMsaa(ctx, info)}; | ||
| 463 | const bool uses_lod{!is_msaa && info.type != TextureType::Buffer}; | ||
| 464 | const auto query{[&](Id type) { | ||
| 465 | return uses_lod ? ctx.OpImageQuerySizeLod(type, image, lod) | ||
| 466 | : ctx.OpImageQuerySize(type, image); | ||
| 467 | }}; | ||
| 455 | switch (info.type) { | 468 | switch (info.type) { |
| 456 | case TextureType::Color1D: | 469 | case TextureType::Color1D: |
| 457 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[1], image, lod), | 470 | return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[1]), zero, zero, mips()); |
| 458 | zero, zero, mips()); | ||
| 459 | case TextureType::ColorArray1D: | 471 | case TextureType::ColorArray1D: |
| 460 | case TextureType::Color2D: | 472 | case TextureType::Color2D: |
| 461 | case TextureType::ColorCube: | 473 | case TextureType::ColorCube: |
| 462 | case TextureType::Color2DRect: | 474 | case TextureType::Color2DRect: |
| 463 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[2], image, lod), | 475 | return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[2]), zero, mips()); |
| 464 | zero, mips()); | ||
| 465 | case TextureType::ColorArray2D: | 476 | case TextureType::ColorArray2D: |
| 466 | case TextureType::Color3D: | 477 | case TextureType::Color3D: |
| 467 | case TextureType::ColorArrayCube: | 478 | case TextureType::ColorArrayCube: |
| 468 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[3], image, lod), | 479 | return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[3]), mips()); |
| 469 | mips()); | ||
| 470 | case TextureType::Buffer: | 480 | case TextureType::Buffer: |
| 471 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySize(ctx.U32[1], image), zero, | 481 | return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[1]), zero, zero, mips()); |
| 472 | zero, mips()); | ||
| 473 | } | 482 | } |
| 474 | throw LogicError("Unspecified image type {}", info.type.Value()); | 483 | throw LogicError("Unspecified image type {}", info.type.Value()); |
| 475 | } | 484 | } |
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 3b97721e1..d48d4860e 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | |||
| @@ -1288,6 +1288,7 @@ void EmitContext::DefineTextures(const Info& info, u32& binding, u32& scaling_in | |||
| 1288 | .pointer_type = pointer_type, | 1288 | .pointer_type = pointer_type, |
| 1289 | .image_type = image_type, | 1289 | .image_type = image_type, |
| 1290 | .count = desc.count, | 1290 | .count = desc.count, |
| 1291 | .is_multisample = desc.is_multisample, | ||
| 1291 | }); | 1292 | }); |
| 1292 | if (profile.supported_spirv >= 0x00010400) { | 1293 | if (profile.supported_spirv >= 0x00010400) { |
| 1293 | interfaces.push_back(id); | 1294 | interfaces.push_back(id); |
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index dbc5c55b9..768a4fbb5 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h | |||
| @@ -35,6 +35,7 @@ struct TextureDefinition { | |||
| 35 | Id pointer_type; | 35 | Id pointer_type; |
| 36 | Id image_type; | 36 | Id image_type; |
| 37 | u32 count; | 37 | u32 count; |
| 38 | bool is_multisample; | ||
| 38 | }; | 39 | }; |
| 39 | 40 | ||
| 40 | struct TextureBufferDefinition { | 41 | struct TextureBufferDefinition { |
diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp index 26d066004..1a0cea9b7 100644 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp | |||
| @@ -30,7 +30,7 @@ bool ComputePipelineKey::operator==(const ComputePipelineKey& rhs) const noexcep | |||
| 30 | ComputePipeline::ComputePipeline(const Device& device, TextureCache& texture_cache_, | 30 | ComputePipeline::ComputePipeline(const Device& device, TextureCache& texture_cache_, |
| 31 | BufferCache& buffer_cache_, ProgramManager& program_manager_, | 31 | BufferCache& buffer_cache_, ProgramManager& program_manager_, |
| 32 | const Shader::Info& info_, std::string code, | 32 | const Shader::Info& info_, std::string code, |
| 33 | std::vector<u32> code_v) | 33 | std::vector<u32> code_v, bool force_context_flush) |
| 34 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, | 34 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, |
| 35 | program_manager{program_manager_}, info{info_} { | 35 | program_manager{program_manager_}, info{info_} { |
| 36 | switch (device.GetShaderBackend()) { | 36 | switch (device.GetShaderBackend()) { |
| @@ -63,6 +63,15 @@ ComputePipeline::ComputePipeline(const Device& device, TextureCache& texture_cac | |||
| 63 | writes_global_memory = !use_storage_buffers && | 63 | writes_global_memory = !use_storage_buffers && |
| 64 | std::ranges::any_of(info.storage_buffers_descriptors, | 64 | std::ranges::any_of(info.storage_buffers_descriptors, |
| 65 | [](const auto& desc) { return desc.is_written; }); | 65 | [](const auto& desc) { return desc.is_written; }); |
| 66 | if (force_context_flush) { | ||
| 67 | std::scoped_lock lock{built_mutex}; | ||
| 68 | built_fence.Create(); | ||
| 69 | // Flush this context to ensure compilation commands and fence are in the GPU pipe. | ||
| 70 | glFlush(); | ||
| 71 | built_condvar.notify_one(); | ||
| 72 | } else { | ||
| 73 | is_built = true; | ||
| 74 | } | ||
| 66 | } | 75 | } |
| 67 | 76 | ||
| 68 | void ComputePipeline::Configure() { | 77 | void ComputePipeline::Configure() { |
| @@ -142,6 +151,9 @@ void ComputePipeline::Configure() { | |||
| 142 | } | 151 | } |
| 143 | texture_cache.FillComputeImageViews(std::span(views.data(), views.size())); | 152 | texture_cache.FillComputeImageViews(std::span(views.data(), views.size())); |
| 144 | 153 | ||
| 154 | if (!is_built) { | ||
| 155 | WaitForBuild(); | ||
| 156 | } | ||
| 145 | if (assembly_program.handle != 0) { | 157 | if (assembly_program.handle != 0) { |
| 146 | program_manager.BindComputeAssemblyProgram(assembly_program.handle); | 158 | program_manager.BindComputeAssemblyProgram(assembly_program.handle); |
| 147 | } else { | 159 | } else { |
| @@ -223,4 +235,13 @@ void ComputePipeline::Configure() { | |||
| 223 | } | 235 | } |
| 224 | } | 236 | } |
| 225 | 237 | ||
| 238 | void ComputePipeline::WaitForBuild() { | ||
| 239 | if (built_fence.handle == 0) { | ||
| 240 | std::unique_lock lock{built_mutex}; | ||
| 241 | built_condvar.wait(lock, [this] { return built_fence.handle != 0; }); | ||
| 242 | } | ||
| 243 | ASSERT(glClientWaitSync(built_fence.handle, 0, GL_TIMEOUT_IGNORED) != GL_WAIT_FAILED); | ||
| 244 | is_built = true; | ||
| 245 | } | ||
| 246 | |||
| 226 | } // namespace OpenGL | 247 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.h b/src/video_core/renderer_opengl/gl_compute_pipeline.h index 6534dec32..9bcc72b59 100644 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.h +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.h | |||
| @@ -50,7 +50,8 @@ class ComputePipeline { | |||
| 50 | public: | 50 | public: |
| 51 | explicit ComputePipeline(const Device& device, TextureCache& texture_cache_, | 51 | explicit ComputePipeline(const Device& device, TextureCache& texture_cache_, |
| 52 | BufferCache& buffer_cache_, ProgramManager& program_manager_, | 52 | BufferCache& buffer_cache_, ProgramManager& program_manager_, |
| 53 | const Shader::Info& info_, std::string code, std::vector<u32> code_v); | 53 | const Shader::Info& info_, std::string code, std::vector<u32> code_v, |
| 54 | bool force_context_flush = false); | ||
| 54 | 55 | ||
| 55 | void Configure(); | 56 | void Configure(); |
| 56 | 57 | ||
| @@ -65,6 +66,8 @@ public: | |||
| 65 | } | 66 | } |
| 66 | 67 | ||
| 67 | private: | 68 | private: |
| 69 | void WaitForBuild(); | ||
| 70 | |||
| 68 | TextureCache& texture_cache; | 71 | TextureCache& texture_cache; |
| 69 | BufferCache& buffer_cache; | 72 | BufferCache& buffer_cache; |
| 70 | Tegra::MemoryManager* gpu_memory; | 73 | Tegra::MemoryManager* gpu_memory; |
| @@ -81,6 +84,11 @@ private: | |||
| 81 | 84 | ||
| 82 | bool use_storage_buffers{}; | 85 | bool use_storage_buffers{}; |
| 83 | bool writes_global_memory{}; | 86 | bool writes_global_memory{}; |
| 87 | |||
| 88 | std::mutex built_mutex; | ||
| 89 | std::condition_variable built_condvar; | ||
| 90 | OGLSync built_fence{}; | ||
| 91 | bool is_built{false}; | ||
| 84 | }; | 92 | }; |
| 85 | 93 | ||
| 86 | } // namespace OpenGL | 94 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index c115dabe1..29491e762 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp | |||
| @@ -176,7 +176,7 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c | |||
| 176 | std::array<std::string, 5> sources, | 176 | std::array<std::string, 5> sources, |
| 177 | std::array<std::vector<u32>, 5> sources_spirv, | 177 | std::array<std::vector<u32>, 5> sources_spirv, |
| 178 | const std::array<const Shader::Info*, 5>& infos, | 178 | const std::array<const Shader::Info*, 5>& infos, |
| 179 | const GraphicsPipelineKey& key_) | 179 | const GraphicsPipelineKey& key_, bool force_context_flush) |
| 180 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, program_manager{program_manager_}, | 180 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, program_manager{program_manager_}, |
| 181 | state_tracker{state_tracker_}, key{key_} { | 181 | state_tracker{state_tracker_}, key{key_} { |
| 182 | if (shader_notify) { | 182 | if (shader_notify) { |
| @@ -231,7 +231,8 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c | |||
| 231 | const bool in_parallel = thread_worker != nullptr; | 231 | const bool in_parallel = thread_worker != nullptr; |
| 232 | const auto backend = device.GetShaderBackend(); | 232 | const auto backend = device.GetShaderBackend(); |
| 233 | auto func{[this, sources = std::move(sources), sources_spirv = std::move(sources_spirv), | 233 | auto func{[this, sources = std::move(sources), sources_spirv = std::move(sources_spirv), |
| 234 | shader_notify, backend, in_parallel](ShaderContext::Context*) mutable { | 234 | shader_notify, backend, in_parallel, |
| 235 | force_context_flush](ShaderContext::Context*) mutable { | ||
| 235 | for (size_t stage = 0; stage < 5; ++stage) { | 236 | for (size_t stage = 0; stage < 5; ++stage) { |
| 236 | switch (backend) { | 237 | switch (backend) { |
| 237 | case Settings::ShaderBackend::GLSL: | 238 | case Settings::ShaderBackend::GLSL: |
| @@ -251,7 +252,7 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c | |||
| 251 | break; | 252 | break; |
| 252 | } | 253 | } |
| 253 | } | 254 | } |
| 254 | if (in_parallel) { | 255 | if (force_context_flush || in_parallel) { |
| 255 | std::scoped_lock lock{built_mutex}; | 256 | std::scoped_lock lock{built_mutex}; |
| 256 | built_fence.Create(); | 257 | built_fence.Create(); |
| 257 | // Flush this context to ensure compilation commands and fence are in the GPU pipe. | 258 | // Flush this context to ensure compilation commands and fence are in the GPU pipe. |
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.h b/src/video_core/renderer_opengl/gl_graphics_pipeline.h index 1c06b3655..7bab3be0a 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.h +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.h | |||
| @@ -78,7 +78,7 @@ public: | |||
| 78 | std::array<std::string, 5> sources, | 78 | std::array<std::string, 5> sources, |
| 79 | std::array<std::vector<u32>, 5> sources_spirv, | 79 | std::array<std::vector<u32>, 5> sources_spirv, |
| 80 | const std::array<const Shader::Info*, 5>& infos, | 80 | const std::array<const Shader::Info*, 5>& infos, |
| 81 | const GraphicsPipelineKey& key_); | 81 | const GraphicsPipelineKey& key_, bool force_context_flush = false); |
| 82 | 82 | ||
| 83 | void Configure(bool is_indexed) { | 83 | void Configure(bool is_indexed) { |
| 84 | configure_func(this, is_indexed); | 84 | configure_func(this, is_indexed); |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 7dd854e0f..626ea7dcb 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -286,7 +286,7 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | |||
| 286 | file.read(reinterpret_cast<char*>(&key), sizeof(key)); | 286 | file.read(reinterpret_cast<char*>(&key), sizeof(key)); |
| 287 | queue_work([this, key, env = std::move(env), &state, &callback](Context* ctx) mutable { | 287 | queue_work([this, key, env = std::move(env), &state, &callback](Context* ctx) mutable { |
| 288 | ctx->pools.ReleaseContents(); | 288 | ctx->pools.ReleaseContents(); |
| 289 | auto pipeline{CreateComputePipeline(ctx->pools, key, env)}; | 289 | auto pipeline{CreateComputePipeline(ctx->pools, key, env, true)}; |
| 290 | std::scoped_lock lock{state.mutex}; | 290 | std::scoped_lock lock{state.mutex}; |
| 291 | if (pipeline) { | 291 | if (pipeline) { |
| 292 | compute_cache.emplace(key, std::move(pipeline)); | 292 | compute_cache.emplace(key, std::move(pipeline)); |
| @@ -307,7 +307,7 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | |||
| 307 | env_ptrs.push_back(&env); | 307 | env_ptrs.push_back(&env); |
| 308 | } | 308 | } |
| 309 | ctx->pools.ReleaseContents(); | 309 | ctx->pools.ReleaseContents(); |
| 310 | auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs), false)}; | 310 | auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs), false, true)}; |
| 311 | std::scoped_lock lock{state.mutex}; | 311 | std::scoped_lock lock{state.mutex}; |
| 312 | if (pipeline) { | 312 | if (pipeline) { |
| 313 | graphics_cache.emplace(key, std::move(pipeline)); | 313 | graphics_cache.emplace(key, std::move(pipeline)); |
| @@ -439,7 +439,8 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline() { | |||
| 439 | 439 | ||
| 440 | std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | 440 | std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( |
| 441 | ShaderContext::ShaderPools& pools, const GraphicsPipelineKey& key, | 441 | ShaderContext::ShaderPools& pools, const GraphicsPipelineKey& key, |
| 442 | std::span<Shader::Environment* const> envs, bool build_in_parallel) try { | 442 | std::span<Shader::Environment* const> envs, bool use_shader_workers, |
| 443 | bool force_context_flush) try { | ||
| 443 | LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); | 444 | LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); |
| 444 | size_t env_index{}; | 445 | size_t env_index{}; |
| 445 | u32 total_storage_buffers{}; | 446 | u32 total_storage_buffers{}; |
| @@ -531,10 +532,10 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 531 | } | 532 | } |
| 532 | previous_program = &program; | 533 | previous_program = &program; |
| 533 | } | 534 | } |
| 534 | auto* const thread_worker{build_in_parallel ? workers.get() : nullptr}; | 535 | auto* const thread_worker{use_shader_workers ? workers.get() : nullptr}; |
| 535 | return std::make_unique<GraphicsPipeline>(device, texture_cache, buffer_cache, program_manager, | 536 | return std::make_unique<GraphicsPipeline>(device, texture_cache, buffer_cache, program_manager, |
| 536 | state_tracker, thread_worker, &shader_notify, sources, | 537 | state_tracker, thread_worker, &shader_notify, sources, |
| 537 | sources_spirv, infos, key); | 538 | sources_spirv, infos, key, force_context_flush); |
| 538 | 539 | ||
| 539 | } catch (Shader::Exception& exception) { | 540 | } catch (Shader::Exception& exception) { |
| 540 | LOG_ERROR(Render_OpenGL, "{}", exception.what()); | 541 | LOG_ERROR(Render_OpenGL, "{}", exception.what()); |
| @@ -559,8 +560,8 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( | |||
| 559 | } | 560 | } |
| 560 | 561 | ||
| 561 | std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( | 562 | std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( |
| 562 | ShaderContext::ShaderPools& pools, const ComputePipelineKey& key, | 563 | ShaderContext::ShaderPools& pools, const ComputePipelineKey& key, Shader::Environment& env, |
| 563 | Shader::Environment& env) try { | 564 | bool force_context_flush) try { |
| 564 | LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); | 565 | LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); |
| 565 | 566 | ||
| 566 | Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; | 567 | Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; |
| @@ -589,7 +590,7 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( | |||
| 589 | } | 590 | } |
| 590 | 591 | ||
| 591 | return std::make_unique<ComputePipeline>(device, texture_cache, buffer_cache, program_manager, | 592 | return std::make_unique<ComputePipeline>(device, texture_cache, buffer_cache, program_manager, |
| 592 | program.info, code, code_spirv); | 593 | program.info, code, code_spirv, force_context_flush); |
| 593 | } catch (Shader::Exception& exception) { | 594 | } catch (Shader::Exception& exception) { |
| 594 | LOG_ERROR(Render_OpenGL, "{}", exception.what()); | 595 | LOG_ERROR(Render_OpenGL, "{}", exception.what()); |
| 595 | return nullptr; | 596 | return nullptr; |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index f82420592..6b9732fca 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h | |||
| @@ -50,14 +50,16 @@ private: | |||
| 50 | 50 | ||
| 51 | std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline( | 51 | std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline( |
| 52 | ShaderContext::ShaderPools& pools, const GraphicsPipelineKey& key, | 52 | ShaderContext::ShaderPools& pools, const GraphicsPipelineKey& key, |
| 53 | std::span<Shader::Environment* const> envs, bool build_in_parallel); | 53 | std::span<Shader::Environment* const> envs, bool use_shader_workers, |
| 54 | bool force_context_flush = false); | ||
| 54 | 55 | ||
| 55 | std::unique_ptr<ComputePipeline> CreateComputePipeline(const ComputePipelineKey& key, | 56 | std::unique_ptr<ComputePipeline> CreateComputePipeline(const ComputePipelineKey& key, |
| 56 | const VideoCommon::ShaderInfo* shader); | 57 | const VideoCommon::ShaderInfo* shader); |
| 57 | 58 | ||
| 58 | std::unique_ptr<ComputePipeline> CreateComputePipeline(ShaderContext::ShaderPools& pools, | 59 | std::unique_ptr<ComputePipeline> CreateComputePipeline(ShaderContext::ShaderPools& pools, |
| 59 | const ComputePipelineKey& key, | 60 | const ComputePipelineKey& key, |
| 60 | Shader::Environment& env); | 61 | Shader::Environment& env, |
| 62 | bool force_context_flush = false); | ||
| 61 | 63 | ||
| 62 | std::unique_ptr<ShaderWorker> CreateWorkers() const; | 64 | std::unique_ptr<ShaderWorker> CreateWorkers() const; |
| 63 | 65 | ||