diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_graphics_pipeline.cpp | 123 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_graphics_pipeline.h | 14 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 54 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.h | 34 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_context.h | 33 |
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 | ||
| 16 | namespace OpenGL { | 18 | namespace 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 | ||
| 21 | namespace OpenGL { | 21 | namespace OpenGL { |
| 22 | 22 | ||
| 23 | namespace ShaderContext { | ||
| 24 | struct Context; | ||
| 25 | } | ||
| 26 | |||
| 23 | class Device; | 27 | class Device; |
| 24 | class ProgramManager; | 28 | class ProgramManager; |
| 25 | 29 | ||
| 26 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 30 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 31 | using ShaderWorker = Common::StatefulThreadWorker<ShaderContext::Context>; | ||
| 27 | 32 | ||
| 28 | struct GraphicsPipelineKey { | 33 | struct 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 | |||
| 85 | private: | 94 | private: |
| 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; | |||
| 50 | using VideoCommon::GenericEnvironment; | 49 | using VideoCommon::GenericEnvironment; |
| 51 | using VideoCommon::GraphicsEnvironment; | 50 | using VideoCommon::GraphicsEnvironment; |
| 52 | using VideoCommon::SerializePipeline; | 51 | using VideoCommon::SerializePipeline; |
| 52 | using Context = ShaderContext::Context; | ||
| 53 | 53 | ||
| 54 | template <typename Container> | 54 | template <typename Container> |
| 55 | auto MakeSpan(Container& container) { | 55 | auto 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 | ||
| 146 | struct 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 | |||
| 155 | ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_, | 146 | ShaderCache::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 | ||
| 356 | std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | 352 | std::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 | ||
| 445 | std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(ShaderPools& pools, | 442 | std::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 | ||
| 468 | std::unique_ptr<Common::StatefulThreadWorker<ShaderCache::Context>> ShaderCache::CreateWorkers() | 465 | std::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 | ||
| 25 | namespace Tegra { | 24 | namespace Tegra { |
| @@ -31,29 +30,17 @@ namespace OpenGL { | |||
| 31 | class Device; | 30 | class Device; |
| 32 | class ProgramManager; | 31 | class ProgramManager; |
| 33 | class RasterizerOpenGL; | 32 | class RasterizerOpenGL; |
| 34 | 33 | using ShaderWorker = Common::StatefulThreadWorker<ShaderContext::Context>; | |
| 35 | struct 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 | ||
| 47 | class ShaderCache : public VideoCommon::ShaderCache { | 35 | class ShaderCache : public VideoCommon::ShaderCache { |
| 48 | struct Context; | ||
| 49 | |||
| 50 | public: | 36 | public: |
| 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 | |||
| 11 | namespace OpenGL::ShaderContext { | ||
| 12 | struct 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 | |||
| 24 | struct 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 | ||