diff options
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 129 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.h | 7 |
2 files changed, 78 insertions, 58 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 0e4904733..9d6cef6e8 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -239,6 +239,15 @@ void SetXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs | |||
| 239 | } | 239 | } |
| 240 | } // Anonymous namespace | 240 | } // Anonymous namespace |
| 241 | 241 | ||
| 242 | struct ShaderCache::Context { | ||
| 243 | explicit Context(Core::Frontend::EmuWindow& emu_window) | ||
| 244 | : gl_context{emu_window.CreateSharedContext()}, scoped{*gl_context} {} | ||
| 245 | |||
| 246 | std::unique_ptr<Core::Frontend::GraphicsContext> gl_context; | ||
| 247 | Core::Frontend::GraphicsContext::Scoped scoped; | ||
| 248 | ShaderPools pools; | ||
| 249 | }; | ||
| 250 | |||
| 242 | ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_, | 251 | ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_, |
| 243 | Tegra::Engines::Maxwell3D& maxwell3d_, | 252 | Tegra::Engines::Maxwell3D& maxwell3d_, |
| 244 | Tegra::Engines::KeplerCompute& kepler_compute_, | 253 | Tegra::Engines::KeplerCompute& kepler_compute_, |
| @@ -247,46 +256,49 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo | |||
| 247 | ProgramManager& program_manager_, StateTracker& state_tracker_) | 256 | ProgramManager& program_manager_, StateTracker& state_tracker_) |
| 248 | : VideoCommon::ShaderCache{rasterizer_, gpu_memory_, maxwell3d_, kepler_compute_}, | 257 | : VideoCommon::ShaderCache{rasterizer_, gpu_memory_, maxwell3d_, kepler_compute_}, |
| 249 | emu_window{emu_window_}, device{device_}, texture_cache{texture_cache_}, | 258 | emu_window{emu_window_}, device{device_}, texture_cache{texture_cache_}, |
| 250 | buffer_cache{buffer_cache_}, program_manager{program_manager_}, state_tracker{ | 259 | buffer_cache{buffer_cache_}, program_manager{program_manager_}, state_tracker{state_tracker_}, |
| 251 | state_tracker_} { | 260 | use_asynchronous_shaders{device.UseAsynchronousShaders()}, |
| 252 | profile = Shader::Profile{ | 261 | profile{ |
| 253 | .supported_spirv = 0x00010000, | 262 | .supported_spirv = 0x00010000, |
| 254 | 263 | ||
| 255 | .unified_descriptor_binding = false, | 264 | .unified_descriptor_binding = false, |
| 256 | .support_descriptor_aliasing = false, | 265 | .support_descriptor_aliasing = false, |
| 257 | .support_int8 = false, | 266 | .support_int8 = false, |
| 258 | .support_int16 = false, | 267 | .support_int16 = false, |
| 259 | .support_vertex_instance_id = true, | 268 | .support_vertex_instance_id = true, |
| 260 | .support_float_controls = false, | 269 | .support_float_controls = false, |
| 261 | .support_separate_denorm_behavior = false, | 270 | .support_separate_denorm_behavior = false, |
| 262 | .support_separate_rounding_mode = false, | 271 | .support_separate_rounding_mode = false, |
| 263 | .support_fp16_denorm_preserve = false, | 272 | .support_fp16_denorm_preserve = false, |
| 264 | .support_fp32_denorm_preserve = false, | 273 | .support_fp32_denorm_preserve = false, |
| 265 | .support_fp16_denorm_flush = false, | 274 | .support_fp16_denorm_flush = false, |
| 266 | .support_fp32_denorm_flush = false, | 275 | .support_fp32_denorm_flush = false, |
| 267 | .support_fp16_signed_zero_nan_preserve = false, | 276 | .support_fp16_signed_zero_nan_preserve = false, |
| 268 | .support_fp32_signed_zero_nan_preserve = false, | 277 | .support_fp32_signed_zero_nan_preserve = false, |
| 269 | .support_fp64_signed_zero_nan_preserve = false, | 278 | .support_fp64_signed_zero_nan_preserve = false, |
| 270 | .support_explicit_workgroup_layout = false, | 279 | .support_explicit_workgroup_layout = false, |
| 271 | .support_vote = true, | 280 | .support_vote = true, |
| 272 | .support_viewport_index_layer_non_geometry = | 281 | .support_viewport_index_layer_non_geometry = |
| 273 | device.HasNvViewportArray2() || device.HasVertexViewportLayer(), | 282 | device.HasNvViewportArray2() || device.HasVertexViewportLayer(), |
| 274 | .support_viewport_mask = device.HasNvViewportArray2(), | 283 | .support_viewport_mask = device.HasNvViewportArray2(), |
| 275 | .support_typeless_image_loads = device.HasImageLoadFormatted(), | 284 | .support_typeless_image_loads = device.HasImageLoadFormatted(), |
| 276 | .support_demote_to_helper_invocation = false, | 285 | .support_demote_to_helper_invocation = false, |
| 277 | .support_int64_atomics = false, | 286 | .support_int64_atomics = false, |
| 278 | .support_derivative_control = device.HasDerivativeControl(), | 287 | .support_derivative_control = device.HasDerivativeControl(), |
| 279 | 288 | ||
| 280 | .warp_size_potentially_larger_than_guest = true, | 289 | .warp_size_potentially_larger_than_guest = true, |
| 281 | 290 | ||
| 282 | .lower_left_origin_mode = true, | 291 | .lower_left_origin_mode = true, |
| 283 | .need_declared_frag_colors = true, | 292 | .need_declared_frag_colors = true, |
| 284 | 293 | ||
| 285 | .has_broken_spirv_clamp = true, | 294 | .has_broken_spirv_clamp = true, |
| 286 | .has_broken_unsigned_image_offsets = true, | 295 | .has_broken_unsigned_image_offsets = true, |
| 287 | .has_broken_signed_operations = true, | 296 | .has_broken_signed_operations = true, |
| 288 | .ignore_nan_fp_comparisons = true, | 297 | .ignore_nan_fp_comparisons = true, |
| 289 | }; | 298 | } { |
| 299 | if (use_asynchronous_shaders) { | ||
| 300 | workers = CreateWorkers(); | ||
| 301 | } | ||
| 290 | } | 302 | } |
| 291 | 303 | ||
| 292 | ShaderCache::~ShaderCache() = default; | 304 | ShaderCache::~ShaderCache() = default; |
| @@ -307,29 +319,20 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | |||
| 307 | } | 319 | } |
| 308 | shader_cache_filename = transferable_dir / fmt::format("{:016x}.bin", title_id); | 320 | shader_cache_filename = transferable_dir / fmt::format("{:016x}.bin", title_id); |
| 309 | 321 | ||
| 310 | struct Context { | 322 | if (!workers) { |
| 311 | explicit Context(Core::Frontend::EmuWindow& emu_window) | 323 | workers = CreateWorkers(); |
| 312 | : gl_context{emu_window.CreateSharedContext()}, scoped{*gl_context} {} | 324 | } |
| 313 | |||
| 314 | std::unique_ptr<Core::Frontend::GraphicsContext> gl_context; | ||
| 315 | Core::Frontend::GraphicsContext::Scoped scoped; | ||
| 316 | ShaderPools pools; | ||
| 317 | }; | ||
| 318 | Common::StatefulThreadWorker<Context> workers( | ||
| 319 | std::max(std::thread::hardware_concurrency(), 2U) - 1, "yuzu:ShaderBuilder", | ||
| 320 | [this] { return Context{emu_window}; }); | ||
| 321 | |||
| 322 | struct { | 325 | struct { |
| 323 | std::mutex mutex; | 326 | std::mutex mutex; |
| 324 | size_t total{0}; | 327 | size_t total{}; |
| 325 | size_t built{0}; | 328 | size_t built{}; |
| 326 | bool has_loaded{false}; | 329 | bool has_loaded{}; |
| 327 | } state; | 330 | } state; |
| 328 | 331 | ||
| 329 | const auto load_compute{[&](std::ifstream& file, FileEnvironment env) { | 332 | const auto load_compute{[&](std::ifstream& file, FileEnvironment env) { |
| 330 | ComputePipelineKey key; | 333 | ComputePipelineKey key; |
| 331 | file.read(reinterpret_cast<char*>(&key), sizeof(key)); | 334 | file.read(reinterpret_cast<char*>(&key), sizeof(key)); |
| 332 | workers.QueueWork( | 335 | workers->QueueWork( |
| 333 | [this, key, env = std::move(env), &state, &callback](Context* ctx) mutable { | 336 | [this, key, env = std::move(env), &state, &callback](Context* ctx) mutable { |
| 334 | ctx->pools.ReleaseContents(); | 337 | ctx->pools.ReleaseContents(); |
| 335 | auto pipeline{CreateComputePipeline(ctx->pools, key, env)}; | 338 | auto pipeline{CreateComputePipeline(ctx->pools, key, env)}; |
| @@ -347,7 +350,7 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | |||
| 347 | const auto load_graphics{[&](std::ifstream& file, std::vector<FileEnvironment> envs) { | 350 | const auto load_graphics{[&](std::ifstream& file, std::vector<FileEnvironment> envs) { |
| 348 | GraphicsPipelineKey key; | 351 | GraphicsPipelineKey key; |
| 349 | file.read(reinterpret_cast<char*>(&key), sizeof(key)); | 352 | file.read(reinterpret_cast<char*>(&key), sizeof(key)); |
| 350 | workers.QueueWork( | 353 | workers->QueueWork( |
| 351 | [this, key, envs = std::move(envs), &state, &callback](Context* ctx) mutable { | 354 | [this, key, envs = std::move(envs), &state, &callback](Context* ctx) mutable { |
| 352 | boost::container::static_vector<Shader::Environment*, 5> env_ptrs; | 355 | boost::container::static_vector<Shader::Environment*, 5> env_ptrs; |
| 353 | for (auto& env : envs) { | 356 | for (auto& env : envs) { |
| @@ -373,7 +376,10 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | |||
| 373 | state.has_loaded = true; | 376 | state.has_loaded = true; |
| 374 | lock.unlock(); | 377 | lock.unlock(); |
| 375 | 378 | ||
| 376 | workers.WaitForRequests(); | 379 | workers->WaitForRequests(); |
| 380 | if (!use_asynchronous_shaders) { | ||
| 381 | workers.reset(); | ||
| 382 | } | ||
| 377 | } | 383 | } |
| 378 | 384 | ||
| 379 | GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() { | 385 | GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() { |
| @@ -570,4 +576,11 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(ShaderPools& | |||
| 570 | return nullptr; | 576 | return nullptr; |
| 571 | } | 577 | } |
| 572 | 578 | ||
| 579 | std::unique_ptr<Common::StatefulThreadWorker<ShaderCache::Context>> ShaderCache::CreateWorkers() | ||
| 580 | const { | ||
| 581 | return std::make_unique<Common::StatefulThreadWorker<Context>>( | ||
| 582 | std::max(std::thread::hardware_concurrency(), 2U) - 1, "yuzu:ShaderBuilder", | ||
| 583 | [this] { return Context{emu_window}; }); | ||
| 584 | } | ||
| 585 | |||
| 573 | } // namespace OpenGL | 586 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index cf74d34e4..e0c5a06d8 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <glad/glad.h> | 12 | #include <glad/glad.h> |
| 13 | 13 | ||
| 14 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 15 | #include "common/thread_worker.h" | ||
| 15 | #include "shader_recompiler/frontend/ir/basic_block.h" | 16 | #include "shader_recompiler/frontend/ir/basic_block.h" |
| 16 | #include "shader_recompiler/frontend/ir/value.h" | 17 | #include "shader_recompiler/frontend/ir/value.h" |
| 17 | #include "shader_recompiler/frontend/maxwell/control_flow.h" | 18 | #include "shader_recompiler/frontend/maxwell/control_flow.h" |
| @@ -44,6 +45,8 @@ struct ShaderPools { | |||
| 44 | }; | 45 | }; |
| 45 | 46 | ||
| 46 | class ShaderCache : public VideoCommon::ShaderCache { | 47 | class ShaderCache : public VideoCommon::ShaderCache { |
| 48 | struct Context; | ||
| 49 | |||
| 47 | public: | 50 | public: |
| 48 | explicit ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_, | 51 | explicit ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_, |
| 49 | Tegra::Engines::Maxwell3D& maxwell3d_, | 52 | Tegra::Engines::Maxwell3D& maxwell3d_, |
| @@ -74,6 +77,8 @@ private: | |||
| 74 | const ComputePipelineKey& key, | 77 | const ComputePipelineKey& key, |
| 75 | Shader::Environment& env); | 78 | Shader::Environment& env); |
| 76 | 79 | ||
| 80 | std::unique_ptr<Common::StatefulThreadWorker<Context>> CreateWorkers() const; | ||
| 81 | |||
| 77 | Core::Frontend::EmuWindow& emu_window; | 82 | Core::Frontend::EmuWindow& emu_window; |
| 78 | const Device& device; | 83 | const Device& device; |
| 79 | TextureCache& texture_cache; | 84 | TextureCache& texture_cache; |
| @@ -82,6 +87,7 @@ private: | |||
| 82 | StateTracker& state_tracker; | 87 | StateTracker& state_tracker; |
| 83 | 88 | ||
| 84 | GraphicsPipelineKey graphics_key{}; | 89 | GraphicsPipelineKey graphics_key{}; |
| 90 | const bool use_asynchronous_shaders; | ||
| 85 | 91 | ||
| 86 | ShaderPools main_pools; | 92 | ShaderPools main_pools; |
| 87 | std::unordered_map<GraphicsPipelineKey, std::unique_ptr<GraphicsPipeline>> graphics_cache; | 93 | std::unordered_map<GraphicsPipelineKey, std::unique_ptr<GraphicsPipeline>> graphics_cache; |
| @@ -89,6 +95,7 @@ private: | |||
| 89 | 95 | ||
| 90 | Shader::Profile profile; | 96 | Shader::Profile profile; |
| 91 | std::filesystem::path shader_cache_filename; | 97 | std::filesystem::path shader_cache_filename; |
| 98 | std::unique_ptr<Common::StatefulThreadWorker<Context>> workers; | ||
| 92 | }; | 99 | }; |
| 93 | 100 | ||
| 94 | } // namespace OpenGL | 101 | } // namespace OpenGL |