summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/CMakeLists.txt1
-rw-r--r--src/video_core/renderer_opengl/gl_graphics_pipeline.cpp123
-rw-r--r--src/video_core/renderer_opengl/gl_graphics_pipeline.h14
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp54
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.h34
-rw-r--r--src/video_core/renderer_opengl/gl_shader_context.h33
7 files changed, 154 insertions, 107 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 1ef3a6189..007ecc13e 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -83,6 +83,7 @@ add_library(video_core STATIC
83 renderer_opengl/gl_shader_cache.h 83 renderer_opengl/gl_shader_cache.h
84 renderer_opengl/gl_shader_manager.cpp 84 renderer_opengl/gl_shader_manager.cpp
85 renderer_opengl/gl_shader_manager.h 85 renderer_opengl/gl_shader_manager.h
86 renderer_opengl/gl_shader_context.h
86 renderer_opengl/gl_shader_util.cpp 87 renderer_opengl/gl_shader_util.cpp
87 renderer_opengl/gl_shader_util.h 88 renderer_opengl/gl_shader_util.h
88 renderer_opengl/gl_state_tracker.cpp 89 renderer_opengl/gl_state_tracker.cpp
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
index d64723d6b..d27a3cf46 100644
--- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
+++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
@@ -6,11 +6,13 @@
6#include <cstring> 6#include <cstring>
7 7
8#include "common/cityhash.h" 8#include "common/cityhash.h"
9#include "common/thread_worker.h"
9#include "shader_recompiler/shader_info.h" 10#include "shader_recompiler/shader_info.h"
10#include "video_core/renderer_opengl/gl_graphics_pipeline.h" 11#include "video_core/renderer_opengl/gl_graphics_pipeline.h"
11#include "video_core/renderer_opengl/gl_shader_manager.h" 12#include "video_core/renderer_opengl/gl_shader_manager.h"
12#include "video_core/renderer_opengl/gl_shader_util.h" 13#include "video_core/renderer_opengl/gl_shader_util.h"
13#include "video_core/renderer_opengl/gl_state_tracker.h" 14#include "video_core/renderer_opengl/gl_state_tracker.h"
15#include "video_core/shader_notify.h"
14#include "video_core/texture_cache/texture_cache.h" 16#include "video_core/texture_cache/texture_cache.h"
15 17
16namespace OpenGL { 18namespace OpenGL {
@@ -117,74 +119,91 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c
117 BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_, 119 BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_,
118 Tegra::Engines::Maxwell3D& maxwell3d_, 120 Tegra::Engines::Maxwell3D& maxwell3d_,
119 ProgramManager& program_manager_, StateTracker& state_tracker_, 121 ProgramManager& program_manager_, StateTracker& state_tracker_,
120 std::array<std::string, 5> assembly_sources, 122 ShaderWorker* thread_worker,
121 std::array<std::string, 5> glsl_sources, 123 VideoCore::ShaderNotify* shader_notify,
124 std::array<std::string, 5> sources,
122 const std::array<const Shader::Info*, 5>& infos, 125 const std::array<const Shader::Info*, 5>& infos,
123 const VideoCommon::TransformFeedbackState* xfb_state) 126 const VideoCommon::TransformFeedbackState* xfb_state)
124 : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, gpu_memory{gpu_memory_}, 127 : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, gpu_memory{gpu_memory_},
125 maxwell3d{maxwell3d_}, program_manager{program_manager_}, state_tracker{state_tracker_} { 128 maxwell3d{maxwell3d_}, program_manager{program_manager_}, state_tracker{state_tracker_} {
129 if (shader_notify) {
130 shader_notify->MarkShaderBuilding();
131 }
126 std::ranges::transform(infos, stage_infos.begin(), 132 std::ranges::transform(infos, stage_infos.begin(),
127 [](const Shader::Info* info) { return info ? *info : Shader::Info{}; }); 133 [](const Shader::Info* info) { return info ? *info : Shader::Info{}; });
128 if (device.UseAssemblyShaders()) { 134 auto func{[this, device, sources, shader_notify, xfb_state](ShaderContext::Context*) mutable {
129 for (size_t stage = 0; stage < 5; ++stage) { 135 if (device.UseAssemblyShaders()) {
130 const auto code{assembly_sources[stage]}; 136 for (size_t stage = 0; stage < 5; ++stage) {
131 if (code.empty()) { 137 const auto code{sources[stage]};
132 continue; 138 if (code.empty()) {
139 continue;
140 }
141 assembly_programs[stage] = CompileProgram(code, AssemblyStage(stage));
142 enabled_stages_mask |= (assembly_programs[stage].handle != 0 ? 1 : 0) << stage;
133 } 143 }
134 assembly_programs[stage] = CompileProgram(code, AssemblyStage(stage)); 144 } else {
135 enabled_stages_mask |= (assembly_programs[stage].handle != 0 ? 1 : 0) << stage; 145 program.handle = glCreateProgram();
136 } 146 for (size_t stage = 0; stage < 5; ++stage) {
137 } else { 147 const auto code{sources[stage]};
138 program.handle = glCreateProgram(); 148 if (code.empty()) {
139 for (size_t stage = 0; stage < 5; ++stage) { 149 continue;
140 const auto code{glsl_sources[stage]}; 150 }
141 if (code.empty()) { 151 AttachShader(Stage(stage), program.handle, code);
142 continue;
143 } 152 }
144 AttachShader(Stage(stage), program.handle, code); 153 LinkProgram(program.handle);
145 } 154 }
146 LinkProgram(program.handle); 155 if (shader_notify) {
147 } 156 shader_notify->MarkShaderComplete();
148 u32 num_textures{};
149 u32 num_images{};
150 u32 num_storage_buffers{};
151 for (size_t stage = 0; stage < base_uniform_bindings.size(); ++stage) {
152 const auto& info{stage_infos[stage]};
153 if (stage < 4) {
154 base_uniform_bindings[stage + 1] = base_uniform_bindings[stage];
155 base_storage_bindings[stage + 1] = base_storage_bindings[stage];
156
157 base_uniform_bindings[stage + 1] += AccumulateCount(info.constant_buffer_descriptors);
158 base_storage_bindings[stage + 1] += AccumulateCount(info.storage_buffers_descriptors);
159 } 157 }
160 enabled_uniform_buffer_masks[stage] = info.constant_buffer_mask; 158 u32 num_textures{};
161 std::ranges::copy(info.constant_buffer_used_sizes, uniform_buffer_sizes[stage].begin()); 159 u32 num_images{};
160 u32 num_storage_buffers{};
161 for (size_t stage = 0; stage < base_uniform_bindings.size(); ++stage) {
162 const auto& info{stage_infos[stage]};
163 if (stage < 4) {
164 base_uniform_bindings[stage + 1] = base_uniform_bindings[stage];
165 base_storage_bindings[stage + 1] = base_storage_bindings[stage];
166
167 base_uniform_bindings[stage + 1] +=
168 AccumulateCount(info.constant_buffer_descriptors);
169 base_storage_bindings[stage + 1] +=
170 AccumulateCount(info.storage_buffers_descriptors);
171 }
172 enabled_uniform_buffer_masks[stage] = info.constant_buffer_mask;
173 std::ranges::copy(info.constant_buffer_used_sizes, uniform_buffer_sizes[stage].begin());
162 174
163 const u32 num_tex_buffer_bindings{AccumulateCount(info.texture_buffer_descriptors)}; 175 const u32 num_tex_buffer_bindings{AccumulateCount(info.texture_buffer_descriptors)};
164 num_texture_buffers[stage] += num_tex_buffer_bindings; 176 num_texture_buffers[stage] += num_tex_buffer_bindings;
165 num_textures += num_tex_buffer_bindings; 177 num_textures += num_tex_buffer_bindings;
166 178
167 const u32 num_img_buffers_bindings{AccumulateCount(info.image_buffer_descriptors)}; 179 const u32 num_img_buffers_bindings{AccumulateCount(info.image_buffer_descriptors)};
168 num_image_buffers[stage] += num_img_buffers_bindings; 180 num_image_buffers[stage] += num_img_buffers_bindings;
169 num_images += num_img_buffers_bindings; 181 num_images += num_img_buffers_bindings;
170 182
171 num_textures += AccumulateCount(info.texture_descriptors); 183 num_textures += AccumulateCount(info.texture_descriptors);
172 num_images += AccumulateCount(info.image_descriptors); 184 num_images += AccumulateCount(info.image_descriptors);
173 num_storage_buffers += AccumulateCount(info.storage_buffers_descriptors); 185 num_storage_buffers += AccumulateCount(info.storage_buffers_descriptors);
174 186
175 writes_global_memory |= std::ranges::any_of( 187 writes_global_memory |= std::ranges::any_of(
176 info.storage_buffers_descriptors, [](const auto& desc) { return desc.is_written; }); 188 info.storage_buffers_descriptors, [](const auto& desc) { return desc.is_written; });
177 } 189 }
178 ASSERT(num_textures <= MAX_TEXTURES); 190 ASSERT(num_textures <= MAX_TEXTURES);
179 ASSERT(num_images <= MAX_IMAGES); 191 ASSERT(num_images <= MAX_IMAGES);
180 192
181 const bool assembly_shaders{assembly_programs[0].handle != 0}; 193 const bool assembly_shaders{assembly_programs[0].handle != 0};
182 use_storage_buffers = 194 use_storage_buffers =
183 !assembly_shaders || num_storage_buffers <= device.GetMaxGLASMStorageBufferBlocks(); 195 !assembly_shaders || num_storage_buffers <= device.GetMaxGLASMStorageBufferBlocks();
184 writes_global_memory &= !use_storage_buffers; 196 writes_global_memory &= !use_storage_buffers;
185 197
186 if (assembly_shaders && xfb_state) { 198 if (assembly_shaders && xfb_state) {
187 GenerateTransformFeedbackState(*xfb_state); 199 GenerateTransformFeedbackState(*xfb_state);
200 }
201 is_built.store(true, std::memory_order_relaxed);
202 }};
203 if (thread_worker) {
204 thread_worker->QueueWork(std::move(func));
205 } else {
206 func(nullptr);
188 } 207 }
189} 208}
190 209
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.h b/src/video_core/renderer_opengl/gl_graphics_pipeline.h
index dc791be53..58deafd3c 100644
--- a/src/video_core/renderer_opengl/gl_graphics_pipeline.h
+++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.h
@@ -20,10 +20,15 @@
20 20
21namespace OpenGL { 21namespace OpenGL {
22 22
23namespace ShaderContext {
24struct Context;
25}
26
23class Device; 27class Device;
24class ProgramManager; 28class ProgramManager;
25 29
26using Maxwell = Tegra::Engines::Maxwell3D::Regs; 30using Maxwell = Tegra::Engines::Maxwell3D::Regs;
31using ShaderWorker = Common::StatefulThreadWorker<ShaderContext::Context>;
27 32
28struct GraphicsPipelineKey { 33struct GraphicsPipelineKey {
29 std::array<u64, 6> unique_hashes; 34 std::array<u64, 6> unique_hashes;
@@ -65,8 +70,8 @@ public:
65 BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_, 70 BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_,
66 Tegra::Engines::Maxwell3D& maxwell3d_, 71 Tegra::Engines::Maxwell3D& maxwell3d_,
67 ProgramManager& program_manager_, StateTracker& state_tracker_, 72 ProgramManager& program_manager_, StateTracker& state_tracker_,
68 std::array<std::string, 5> assembly_sources, 73 ShaderWorker* thread_worker, VideoCore::ShaderNotify* shader_notify,
69 std::array<std::string, 5> glsl_sources, 74 std::array<std::string, 5> sources,
70 const std::array<const Shader::Info*, 5>& infos, 75 const std::array<const Shader::Info*, 5>& infos,
71 const VideoCommon::TransformFeedbackState* xfb_state); 76 const VideoCommon::TransformFeedbackState* xfb_state);
72 77
@@ -82,6 +87,10 @@ public:
82 return writes_global_memory; 87 return writes_global_memory;
83 } 88 }
84 89
90 [[nodiscard]] bool IsBuilt() const noexcept {
91 return is_built.load(std::memory_order::relaxed);
92 }
93
85private: 94private:
86 void GenerateTransformFeedbackState(const VideoCommon::TransformFeedbackState& xfb_state); 95 void GenerateTransformFeedbackState(const VideoCommon::TransformFeedbackState& xfb_state);
87 96
@@ -108,6 +117,7 @@ private:
108 117
109 bool use_storage_buffers{}; 118 bool use_storage_buffers{};
110 bool writes_global_memory{}; 119 bool writes_global_memory{};
120 std::atomic_bool is_built{false};
111 121
112 static constexpr std::size_t XFB_ENTRY_STRIDE = 3; 122 static constexpr std::size_t XFB_ENTRY_STRIDE = 3;
113 GLsizei num_xfb_attribs{}; 123 GLsizei num_xfb_attribs{};
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 7513bd071..e3d336f86 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -70,7 +70,7 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra
70 buffer_cache_runtime(device), 70 buffer_cache_runtime(device),
71 buffer_cache(*this, maxwell3d, kepler_compute, gpu_memory, cpu_memory_, buffer_cache_runtime), 71 buffer_cache(*this, maxwell3d, kepler_compute, gpu_memory, cpu_memory_, buffer_cache_runtime),
72 shader_cache(*this, emu_window_, maxwell3d, kepler_compute, gpu_memory, device, texture_cache, 72 shader_cache(*this, emu_window_, maxwell3d, kepler_compute, gpu_memory, device, texture_cache,
73 buffer_cache, program_manager, state_tracker), 73 buffer_cache, program_manager, state_tracker, gpu.ShaderNotify()),
74 query_cache(*this, maxwell3d, gpu_memory), accelerate_dma(buffer_cache), 74 query_cache(*this, maxwell3d, gpu_memory), accelerate_dma(buffer_cache),
75 fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache) {} 75 fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache) {}
76 76
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 3d59d34d7..d082b9f73 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -17,7 +17,6 @@
17#include "common/scope_exit.h" 17#include "common/scope_exit.h"
18#include "common/thread_worker.h" 18#include "common/thread_worker.h"
19#include "core/core.h" 19#include "core/core.h"
20#include "core/frontend/emu_window.h"
21#include "shader_recompiler/backend/glasm/emit_glasm.h" 20#include "shader_recompiler/backend/glasm/emit_glasm.h"
22#include "shader_recompiler/backend/glsl/emit_glsl.h" 21#include "shader_recompiler/backend/glsl/emit_glsl.h"
23#include "shader_recompiler/backend/spirv/emit_spirv.h" 22#include "shader_recompiler/backend/spirv/emit_spirv.h"
@@ -50,6 +49,7 @@ using VideoCommon::FileEnvironment;
50using VideoCommon::GenericEnvironment; 49using VideoCommon::GenericEnvironment;
51using VideoCommon::GraphicsEnvironment; 50using VideoCommon::GraphicsEnvironment;
52using VideoCommon::SerializePipeline; 51using VideoCommon::SerializePipeline;
52using Context = ShaderContext::Context;
53 53
54template <typename Container> 54template <typename Container>
55auto MakeSpan(Container& container) { 55auto MakeSpan(Container& container) {
@@ -143,25 +143,17 @@ void SetXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs
143} 143}
144} // Anonymous namespace 144} // Anonymous namespace
145 145
146struct ShaderCache::Context {
147 explicit Context(Core::Frontend::EmuWindow& emu_window)
148 : gl_context{emu_window.CreateSharedContext()}, scoped{*gl_context} {}
149
150 std::unique_ptr<Core::Frontend::GraphicsContext> gl_context;
151 Core::Frontend::GraphicsContext::Scoped scoped;
152 ShaderPools pools;
153};
154
155ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_, 146ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_,
156 Tegra::Engines::Maxwell3D& maxwell3d_, 147 Tegra::Engines::Maxwell3D& maxwell3d_,
157 Tegra::Engines::KeplerCompute& kepler_compute_, 148 Tegra::Engines::KeplerCompute& kepler_compute_,
158 Tegra::MemoryManager& gpu_memory_, const Device& device_, 149 Tegra::MemoryManager& gpu_memory_, const Device& device_,
159 TextureCache& texture_cache_, BufferCache& buffer_cache_, 150 TextureCache& texture_cache_, BufferCache& buffer_cache_,
160 ProgramManager& program_manager_, StateTracker& state_tracker_) 151 ProgramManager& program_manager_, StateTracker& state_tracker_,
152 VideoCore::ShaderNotify& shader_notify_)
161 : VideoCommon::ShaderCache{rasterizer_, gpu_memory_, maxwell3d_, kepler_compute_}, 153 : VideoCommon::ShaderCache{rasterizer_, gpu_memory_, maxwell3d_, kepler_compute_},
162 emu_window{emu_window_}, device{device_}, texture_cache{texture_cache_}, 154 emu_window{emu_window_}, device{device_}, texture_cache{texture_cache_},
163 buffer_cache{buffer_cache_}, program_manager{program_manager_}, state_tracker{state_tracker_}, 155 buffer_cache{buffer_cache_}, program_manager{program_manager_}, state_tracker{state_tracker_},
164 use_asynchronous_shaders{device.UseAsynchronousShaders()}, 156 shader_notify{shader_notify_}, use_asynchronous_shaders{device.UseAsynchronousShaders()},
165 profile{ 157 profile{
166 .supported_spirv = 0x00010000, 158 .supported_spirv = 0x00010000,
167 159
@@ -264,7 +256,7 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
264 env_ptrs.push_back(&env); 256 env_ptrs.push_back(&env);
265 } 257 }
266 ctx->pools.ReleaseContents(); 258 ctx->pools.ReleaseContents();
267 auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs))}; 259 auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs), false)};
268 std::lock_guard lock{state.mutex}; 260 std::lock_guard lock{state.mutex};
269 if (pipeline) { 261 if (pipeline) {
270 graphics_cache.emplace(key, std::move(pipeline)); 262 graphics_cache.emplace(key, std::move(pipeline));
@@ -311,6 +303,9 @@ GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() {
311 if (is_new) { 303 if (is_new) {
312 program = CreateGraphicsPipeline(); 304 program = CreateGraphicsPipeline();
313 } 305 }
306 if (!program || !program->IsBuilt()) {
307 return nullptr;
308 }
314 return program.get(); 309 return program.get();
315} 310}
316 311
@@ -339,7 +334,8 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline() {
339 GetGraphicsEnvironments(environments, graphics_key.unique_hashes); 334 GetGraphicsEnvironments(environments, graphics_key.unique_hashes);
340 335
341 main_pools.ReleaseContents(); 336 main_pools.ReleaseContents();
342 auto pipeline{CreateGraphicsPipeline(main_pools, graphics_key, environments.Span())}; 337 auto pipeline{CreateGraphicsPipeline(main_pools, graphics_key, environments.Span(),
338 use_asynchronous_shaders)};
343 if (!pipeline || shader_cache_filename.empty()) { 339 if (!pipeline || shader_cache_filename.empty()) {
344 return pipeline; 340 return pipeline;
345 } 341 }
@@ -354,8 +350,8 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline() {
354} 350}
355 351
356std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( 352std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
357 ShaderPools& pools, const GraphicsPipelineKey& key, 353 ShaderContext::ShaderPools& pools, const GraphicsPipelineKey& key,
358 std::span<Shader::Environment* const> envs) try { 354 std::span<Shader::Environment* const> envs, bool build_in_parallel) try {
359 LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); 355 LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash());
360 size_t env_index{}; 356 size_t env_index{};
361 u32 total_storage_buffers{}; 357 u32 total_storage_buffers{};
@@ -394,8 +390,7 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
394 std::array<const Shader::Info*, Maxwell::MaxShaderStage> infos{}; 390 std::array<const Shader::Info*, Maxwell::MaxShaderStage> infos{};
395 391
396 OGLProgram source_program; 392 OGLProgram source_program;
397 std::array<std::string, 5> assembly_sources; 393 std::array<std::string, 5> sources;
398 std::array<std::string, 5> glsl_sources;
399 Shader::Backend::Bindings binding; 394 Shader::Backend::Bindings binding;
400 const bool use_glasm{device.UseAssemblyShaders()}; 395 const bool use_glasm{device.UseAssemblyShaders()};
401 const size_t first_index = uses_vertex_a && uses_vertex_b ? 1 : 0; 396 const size_t first_index = uses_vertex_a && uses_vertex_b ? 1 : 0;
@@ -412,14 +407,16 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
412 const auto runtime_info{ 407 const auto runtime_info{
413 MakeRuntimeInfo(key, program, glasm_use_storage_buffers, use_glasm)}; 408 MakeRuntimeInfo(key, program, glasm_use_storage_buffers, use_glasm)};
414 if (use_glasm) { 409 if (use_glasm) {
415 assembly_sources[stage_index] = EmitGLASM(profile, runtime_info, program, binding); 410 sources[stage_index] = EmitGLASM(profile, runtime_info, program, binding);
416 } else { 411 } else {
417 glsl_sources[stage_index] = EmitGLSL(profile, runtime_info, program, binding); 412 sources[stage_index] = EmitGLSL(profile, runtime_info, program, binding);
418 } 413 }
419 } 414 }
415 auto* const thread_worker{build_in_parallel ? workers.get() : nullptr};
416 VideoCore::ShaderNotify* const notify{build_in_parallel ? &shader_notify : nullptr};
420 return std::make_unique<GraphicsPipeline>( 417 return std::make_unique<GraphicsPipeline>(
421 device, texture_cache, buffer_cache, gpu_memory, maxwell3d, program_manager, state_tracker, 418 device, texture_cache, buffer_cache, gpu_memory, maxwell3d, program_manager, state_tracker,
422 assembly_sources, glsl_sources, infos, key.xfb_enabled != 0 ? &key.xfb_state : nullptr); 419 thread_worker, notify, sources, infos, key.xfb_enabled != 0 ? &key.xfb_state : nullptr);
423 420
424} catch (Shader::Exception& exception) { 421} catch (Shader::Exception& exception) {
425 LOG_ERROR(Render_OpenGL, "{}", exception.what()); 422 LOG_ERROR(Render_OpenGL, "{}", exception.what());
@@ -442,9 +439,9 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(
442 return pipeline; 439 return pipeline;
443} 440}
444 441
445std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(ShaderPools& pools, 442std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(
446 const ComputePipelineKey& key, 443 ShaderContext::ShaderPools& pools, const ComputePipelineKey& key,
447 Shader::Environment& env) try { 444 Shader::Environment& env) try {
448 LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); 445 LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash());
449 446
450 Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; 447 Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()};
@@ -465,11 +462,10 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(ShaderPools&
465 return nullptr; 462 return nullptr;
466} 463}
467 464
468std::unique_ptr<Common::StatefulThreadWorker<ShaderCache::Context>> ShaderCache::CreateWorkers() 465std::unique_ptr<ShaderWorker> ShaderCache::CreateWorkers() const {
469 const { 466 return std::make_unique<ShaderWorker>(std::max(std::thread::hardware_concurrency(), 2U) - 1,
470 return std::make_unique<Common::StatefulThreadWorker<Context>>( 467 "yuzu:ShaderBuilder",
471 std::max(std::thread::hardware_concurrency(), 2U) - 1, "yuzu:ShaderBuilder", 468 [this] { return Context{emu_window}; });
472 [this] { return Context{emu_window}; });
473} 469}
474 470
475} // namespace OpenGL 471} // 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 e0c5a06d8..d24b54d90 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_cache.h
@@ -13,13 +13,12 @@
13 13
14#include "common/common_types.h" 14#include "common/common_types.h"
15#include "common/thread_worker.h" 15#include "common/thread_worker.h"
16#include "shader_recompiler/frontend/ir/basic_block.h"
17#include "shader_recompiler/frontend/ir/value.h" 16#include "shader_recompiler/frontend/ir/value.h"
18#include "shader_recompiler/frontend/maxwell/control_flow.h"
19#include "shader_recompiler/object_pool.h" 17#include "shader_recompiler/object_pool.h"
20#include "video_core/engines/shader_type.h" 18#include "video_core/engines/shader_type.h"
21#include "video_core/renderer_opengl/gl_compute_pipeline.h" 19#include "video_core/renderer_opengl/gl_compute_pipeline.h"
22#include "video_core/renderer_opengl/gl_graphics_pipeline.h" 20#include "video_core/renderer_opengl/gl_graphics_pipeline.h"
21#include "video_core/renderer_opengl/gl_shader_context.h"
23#include "video_core/shader_cache.h" 22#include "video_core/shader_cache.h"
24 23
25namespace Tegra { 24namespace Tegra {
@@ -31,29 +30,17 @@ namespace OpenGL {
31class Device; 30class Device;
32class ProgramManager; 31class ProgramManager;
33class RasterizerOpenGL; 32class RasterizerOpenGL;
34 33using ShaderWorker = Common::StatefulThreadWorker<ShaderContext::Context>;
35struct ShaderPools {
36 void ReleaseContents() {
37 flow_block.ReleaseContents();
38 block.ReleaseContents();
39 inst.ReleaseContents();
40 }
41
42 Shader::ObjectPool<Shader::IR::Inst> inst;
43 Shader::ObjectPool<Shader::IR::Block> block;
44 Shader::ObjectPool<Shader::Maxwell::Flow::Block> flow_block;
45};
46 34
47class ShaderCache : public VideoCommon::ShaderCache { 35class ShaderCache : public VideoCommon::ShaderCache {
48 struct Context;
49
50public: 36public:
51 explicit ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_, 37 explicit ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_,
52 Tegra::Engines::Maxwell3D& maxwell3d_, 38 Tegra::Engines::Maxwell3D& maxwell3d_,
53 Tegra::Engines::KeplerCompute& kepler_compute_, 39 Tegra::Engines::KeplerCompute& kepler_compute_,
54 Tegra::MemoryManager& gpu_memory_, const Device& device_, 40 Tegra::MemoryManager& gpu_memory_, const Device& device_,
55 TextureCache& texture_cache_, BufferCache& buffer_cache_, 41 TextureCache& texture_cache_, BufferCache& buffer_cache_,
56 ProgramManager& program_manager_, StateTracker& state_tracker_); 42 ProgramManager& program_manager_, StateTracker& state_tracker_,
43 VideoCore::ShaderNotify& shader_notify_);
57 ~ShaderCache(); 44 ~ShaderCache();
58 45
59 void LoadDiskResources(u64 title_id, std::stop_token stop_loading, 46 void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
@@ -67,17 +54,17 @@ private:
67 std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline(); 54 std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline();
68 55
69 std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline( 56 std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline(
70 ShaderPools& pools, const GraphicsPipelineKey& key, 57 ShaderContext::ShaderPools& pools, const GraphicsPipelineKey& key,
71 std::span<Shader::Environment* const> envs); 58 std::span<Shader::Environment* const> envs, bool build_in_parallel);
72 59
73 std::unique_ptr<ComputePipeline> CreateComputePipeline(const ComputePipelineKey& key, 60 std::unique_ptr<ComputePipeline> CreateComputePipeline(const ComputePipelineKey& key,
74 const VideoCommon::ShaderInfo* shader); 61 const VideoCommon::ShaderInfo* shader);
75 62
76 std::unique_ptr<ComputePipeline> CreateComputePipeline(ShaderPools& pools, 63 std::unique_ptr<ComputePipeline> CreateComputePipeline(ShaderContext::ShaderPools& pools,
77 const ComputePipelineKey& key, 64 const ComputePipelineKey& key,
78 Shader::Environment& env); 65 Shader::Environment& env);
79 66
80 std::unique_ptr<Common::StatefulThreadWorker<Context>> CreateWorkers() const; 67 std::unique_ptr<ShaderWorker> CreateWorkers() const;
81 68
82 Core::Frontend::EmuWindow& emu_window; 69 Core::Frontend::EmuWindow& emu_window;
83 const Device& device; 70 const Device& device;
@@ -85,17 +72,18 @@ private:
85 BufferCache& buffer_cache; 72 BufferCache& buffer_cache;
86 ProgramManager& program_manager; 73 ProgramManager& program_manager;
87 StateTracker& state_tracker; 74 StateTracker& state_tracker;
75 VideoCore::ShaderNotify& shader_notify;
88 76
89 GraphicsPipelineKey graphics_key{}; 77 GraphicsPipelineKey graphics_key{};
90 const bool use_asynchronous_shaders; 78 const bool use_asynchronous_shaders;
91 79
92 ShaderPools main_pools; 80 ShaderContext::ShaderPools main_pools;
93 std::unordered_map<GraphicsPipelineKey, std::unique_ptr<GraphicsPipeline>> graphics_cache; 81 std::unordered_map<GraphicsPipelineKey, std::unique_ptr<GraphicsPipeline>> graphics_cache;
94 std::unordered_map<ComputePipelineKey, std::unique_ptr<ComputePipeline>> compute_cache; 82 std::unordered_map<ComputePipelineKey, std::unique_ptr<ComputePipeline>> compute_cache;
95 83
96 Shader::Profile profile; 84 Shader::Profile profile;
97 std::filesystem::path shader_cache_filename; 85 std::filesystem::path shader_cache_filename;
98 std::unique_ptr<Common::StatefulThreadWorker<Context>> workers; 86 std::unique_ptr<ShaderWorker> workers;
99}; 87};
100 88
101} // namespace OpenGL 89} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_shader_context.h b/src/video_core/renderer_opengl/gl_shader_context.h
new file mode 100644
index 000000000..6ff34e5d6
--- /dev/null
+++ b/src/video_core/renderer_opengl/gl_shader_context.h
@@ -0,0 +1,33 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/frontend/emu_window.h"
8#include "shader_recompiler/frontend/ir/basic_block.h"
9#include "shader_recompiler/frontend/maxwell/control_flow.h"
10
11namespace OpenGL::ShaderContext {
12struct ShaderPools {
13 void ReleaseContents() {
14 flow_block.ReleaseContents();
15 block.ReleaseContents();
16 inst.ReleaseContents();
17 }
18
19 Shader::ObjectPool<Shader::IR::Inst> inst;
20 Shader::ObjectPool<Shader::IR::Block> block;
21 Shader::ObjectPool<Shader::Maxwell::Flow::Block> flow_block;
22};
23
24struct Context {
25 explicit Context(Core::Frontend::EmuWindow& emu_window)
26 : gl_context{emu_window.CreateSharedContext()}, scoped{*gl_context} {}
27
28 std::unique_ptr<Core::Frontend::GraphicsContext> gl_context;
29 Core::Frontend::GraphicsContext::Scoped scoped;
30 ShaderPools pools;
31};
32
33} // namespace OpenGL::ShaderContext