diff options
| author | 2021-06-22 01:12:11 -0400 | |
|---|---|---|
| committer | 2021-07-22 21:51:39 -0400 | |
| commit | fb9b1787f86d069db27fe0af44ded042c6d8de39 (patch) | |
| tree | ac1e1056f0ce34be34063dc5ce38c34faceaf946 /src | |
| parent | general: Add setting shader_backend (diff) | |
| download | yuzu-fb9b1787f86d069db27fe0af44ded042c6d8de39.tar.gz yuzu-fb9b1787f86d069db27fe0af44ded042c6d8de39.tar.xz yuzu-fb9b1787f86d069db27fe0af44ded042c6d8de39.zip | |
video_core: Enable GL SPIR-V shaders
Diffstat (limited to 'src')
7 files changed, 105 insertions, 38 deletions
diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp index 2d6442d74..c63e87a56 100644 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <cstring> | 5 | #include <cstring> |
| 6 | 6 | ||
| 7 | #include "common/cityhash.h" | 7 | #include "common/cityhash.h" |
| 8 | #include "common/settings.h" // for enum class Settings::ShaderBackend | ||
| 8 | #include "video_core/renderer_opengl/gl_compute_pipeline.h" | 9 | #include "video_core/renderer_opengl/gl_compute_pipeline.h" |
| 9 | #include "video_core/renderer_opengl/gl_shader_manager.h" | 10 | #include "video_core/renderer_opengl/gl_shader_manager.h" |
| 10 | #include "video_core/renderer_opengl/gl_shader_util.h" | 11 | #include "video_core/renderer_opengl/gl_shader_util.h" |
| @@ -40,15 +41,23 @@ ComputePipeline::ComputePipeline(const Device& device, TextureCache& texture_cac | |||
| 40 | BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_, | 41 | BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_, |
| 41 | Tegra::Engines::KeplerCompute& kepler_compute_, | 42 | Tegra::Engines::KeplerCompute& kepler_compute_, |
| 42 | ProgramManager& program_manager_, const Shader::Info& info_, | 43 | ProgramManager& program_manager_, const Shader::Info& info_, |
| 43 | std::string code) | 44 | std::string code, std::vector<u32> code_v) |
| 44 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, gpu_memory{gpu_memory_}, | 45 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, gpu_memory{gpu_memory_}, |
| 45 | kepler_compute{kepler_compute_}, program_manager{program_manager_}, info{info_} { | 46 | kepler_compute{kepler_compute_}, program_manager{program_manager_}, info{info_} { |
| 46 | if (device.UseAssemblyShaders()) { | 47 | switch (device.GetShaderBackend()) { |
| 47 | assembly_program = CompileProgram(code, GL_COMPUTE_PROGRAM_NV); | 48 | case Settings::ShaderBackend::GLSL: |
| 48 | } else { | ||
| 49 | source_program.handle = glCreateProgram(); | 49 | source_program.handle = glCreateProgram(); |
| 50 | AttachShader(GL_COMPUTE_SHADER, source_program.handle, code); | 50 | AttachShader(GL_COMPUTE_SHADER, source_program.handle, code); |
| 51 | LinkProgram(source_program.handle); | 51 | LinkProgram(source_program.handle); |
| 52 | break; | ||
| 53 | case Settings::ShaderBackend::GLASM: | ||
| 54 | assembly_program = CompileProgram(code, GL_COMPUTE_PROGRAM_NV); | ||
| 55 | break; | ||
| 56 | case Settings::ShaderBackend::SPIRV: | ||
| 57 | source_program.handle = glCreateProgram(); | ||
| 58 | AttachShader(GL_COMPUTE_SHADER, source_program.handle, code_v); | ||
| 59 | LinkProgram(source_program.handle); | ||
| 60 | break; | ||
| 52 | } | 61 | } |
| 53 | std::copy_n(info.constant_buffer_used_sizes.begin(), uniform_buffer_sizes.size(), | 62 | std::copy_n(info.constant_buffer_used_sizes.begin(), uniform_buffer_sizes.size(), |
| 54 | uniform_buffer_sizes.begin()); | 63 | uniform_buffer_sizes.begin()); |
diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.h b/src/video_core/renderer_opengl/gl_compute_pipeline.h index b5fc45f26..50c676365 100644 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.h +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.h | |||
| @@ -54,7 +54,7 @@ public: | |||
| 54 | BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_, | 54 | BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_, |
| 55 | Tegra::Engines::KeplerCompute& kepler_compute_, | 55 | Tegra::Engines::KeplerCompute& kepler_compute_, |
| 56 | ProgramManager& program_manager_, const Shader::Info& info_, | 56 | ProgramManager& program_manager_, const Shader::Info& info_, |
| 57 | std::string code); | 57 | std::string code, std::vector<u32> code_v); |
| 58 | 58 | ||
| 59 | void Configure(); | 59 | void Configure(); |
| 60 | 60 | ||
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index c4eeed53b..99f8769fc 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -177,6 +177,11 @@ Device::Device() { | |||
| 177 | GLAD_GL_NV_gpu_program5 && GLAD_GL_NV_compute_program5 && GLAD_GL_NV_transform_feedback && | 177 | GLAD_GL_NV_gpu_program5 && GLAD_GL_NV_compute_program5 && GLAD_GL_NV_transform_feedback && |
| 178 | GLAD_GL_NV_transform_feedback2; | 178 | GLAD_GL_NV_transform_feedback2; |
| 179 | 179 | ||
| 180 | shader_backend = (Settings::values.shader_backend.GetValue() == | ||
| 181 | Settings::ShaderBackend::GLASM) == use_assembly_shaders | ||
| 182 | ? Settings::values.shader_backend.GetValue() | ||
| 183 | : Settings::ShaderBackend::GLSL; | ||
| 184 | |||
| 180 | // Blocks AMD and Intel OpenGL drivers on Windows from using asynchronous shader compilation. | 185 | // Blocks AMD and Intel OpenGL drivers on Windows from using asynchronous shader compilation. |
| 181 | use_asynchronous_shaders = Settings::values.use_asynchronous_shaders.GetValue() && | 186 | use_asynchronous_shaders = Settings::values.use_asynchronous_shaders.GetValue() && |
| 182 | !(is_amd || (is_intel && !is_linux)); | 187 | !(is_amd || (is_intel && !is_linux)); |
| @@ -188,8 +193,7 @@ Device::Device() { | |||
| 188 | LOG_INFO(Render_OpenGL, "Renderer_BrokenTextureViewFormats: {}", | 193 | LOG_INFO(Render_OpenGL, "Renderer_BrokenTextureViewFormats: {}", |
| 189 | has_broken_texture_view_formats); | 194 | has_broken_texture_view_formats); |
| 190 | 195 | ||
| 191 | if (Settings::values.shader_backend.GetValue() == Settings::ShaderBackend::GLASM && | 196 | if (shader_backend == Settings::ShaderBackend::GLASM && !use_assembly_shaders) { |
| 192 | !use_assembly_shaders) { | ||
| 193 | LOG_ERROR(Render_OpenGL, "Assembly shaders enabled but not supported"); | 197 | LOG_ERROR(Render_OpenGL, "Assembly shaders enabled but not supported"); |
| 194 | } | 198 | } |
| 195 | 199 | ||
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index 45ddf5e01..ee992aed4 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h | |||
| @@ -8,6 +8,10 @@ | |||
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | #include "shader_recompiler/stage.h" | 9 | #include "shader_recompiler/stage.h" |
| 10 | 10 | ||
| 11 | namespace Settings { | ||
| 12 | enum class ShaderBackend : u32; | ||
| 13 | }; | ||
| 14 | |||
| 11 | namespace OpenGL { | 15 | namespace OpenGL { |
| 12 | 16 | ||
| 13 | class Device { | 17 | class Device { |
| @@ -148,6 +152,10 @@ public: | |||
| 148 | return need_fastmath_off; | 152 | return need_fastmath_off; |
| 149 | } | 153 | } |
| 150 | 154 | ||
| 155 | Settings::ShaderBackend GetShaderBackend() const { | ||
| 156 | return shader_backend; | ||
| 157 | } | ||
| 158 | |||
| 151 | private: | 159 | private: |
| 152 | static bool TestVariableAoffi(); | 160 | static bool TestVariableAoffi(); |
| 153 | static bool TestPreciseBug(); | 161 | static bool TestPreciseBug(); |
| @@ -159,6 +167,9 @@ private: | |||
| 159 | u32 max_varyings{}; | 167 | u32 max_varyings{}; |
| 160 | u32 max_compute_shared_memory_size{}; | 168 | u32 max_compute_shared_memory_size{}; |
| 161 | u32 max_glasm_storage_buffer_blocks{}; | 169 | u32 max_glasm_storage_buffer_blocks{}; |
| 170 | |||
| 171 | Settings::ShaderBackend shader_backend{}; | ||
| 172 | |||
| 162 | bool has_warp_intrinsics{}; | 173 | bool has_warp_intrinsics{}; |
| 163 | bool has_shader_ballot{}; | 174 | bool has_shader_ballot{}; |
| 164 | bool has_vertex_viewport_layer{}; | 175 | bool has_vertex_viewport_layer{}; |
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index a93b03cf7..1f19b5825 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp | |||
| @@ -3,7 +3,11 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <array> | ||
| 7 | #include <string> | ||
| 8 | #include <vector> | ||
| 6 | 9 | ||
| 10 | #include "common/settings.h" // for enum class Settings::ShaderBackend | ||
| 7 | #include "common/thread_worker.h" | 11 | #include "common/thread_worker.h" |
| 8 | #include "shader_recompiler/shader_info.h" | 12 | #include "shader_recompiler/shader_info.h" |
| 9 | #include "video_core/renderer_opengl/gl_graphics_pipeline.h" | 13 | #include "video_core/renderer_opengl/gl_graphics_pipeline.h" |
| @@ -179,7 +183,8 @@ GraphicsPipeline::GraphicsPipeline( | |||
| 179 | Tegra::MemoryManager& gpu_memory_, Tegra::Engines::Maxwell3D& maxwell3d_, | 183 | Tegra::MemoryManager& gpu_memory_, Tegra::Engines::Maxwell3D& maxwell3d_, |
| 180 | ProgramManager& program_manager_, StateTracker& state_tracker_, ShaderWorker* thread_worker, | 184 | ProgramManager& program_manager_, StateTracker& state_tracker_, ShaderWorker* thread_worker, |
| 181 | VideoCore::ShaderNotify* shader_notify, std::array<std::string, 5> sources, | 185 | VideoCore::ShaderNotify* shader_notify, std::array<std::string, 5> sources, |
| 182 | const std::array<const Shader::Info*, 5>& infos, const GraphicsPipelineKey& key_) | 186 | std::array<std::vector<u32>, 5> sources_spirv, const std::array<const Shader::Info*, 5>& infos, |
| 187 | const GraphicsPipelineKey& key_) | ||
| 183 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, | 188 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, |
| 184 | gpu_memory{gpu_memory_}, maxwell3d{maxwell3d_}, program_manager{program_manager_}, | 189 | gpu_memory{gpu_memory_}, maxwell3d{maxwell3d_}, program_manager{program_manager_}, |
| 185 | state_tracker{state_tracker_}, key{key_} { | 190 | state_tracker{state_tracker_}, key{key_} { |
| @@ -232,29 +237,44 @@ GraphicsPipeline::GraphicsPipeline( | |||
| 232 | if (key.xfb_enabled && device.UseAssemblyShaders()) { | 237 | if (key.xfb_enabled && device.UseAssemblyShaders()) { |
| 233 | GenerateTransformFeedbackState(); | 238 | GenerateTransformFeedbackState(); |
| 234 | } | 239 | } |
| 235 | auto func{[this, device, sources, shader_notify](ShaderContext::Context*) mutable { | 240 | auto func{ |
| 236 | if (!device.UseAssemblyShaders()) { | 241 | [this, device, sources, sources_spirv, shader_notify](ShaderContext::Context*) mutable { |
| 237 | program.handle = glCreateProgram(); | 242 | if (!device.UseAssemblyShaders()) { |
| 238 | } | 243 | program.handle = glCreateProgram(); |
| 239 | for (size_t stage = 0; stage < 5; ++stage) { | ||
| 240 | const auto code{sources[stage]}; | ||
| 241 | if (code.empty()) { | ||
| 242 | continue; | ||
| 243 | } | 244 | } |
| 244 | if (device.UseAssemblyShaders()) { | 245 | for (size_t stage = 0; stage < 5; ++stage) { |
| 245 | assembly_programs[stage] = CompileProgram(code, AssemblyStage(stage)); | 246 | switch (device.GetShaderBackend()) { |
| 246 | } else { | 247 | case Settings::ShaderBackend::GLSL: { |
| 247 | AttachShader(Stage(stage), program.handle, code); | 248 | const auto code{sources[stage]}; |
| 249 | if (code.empty()) { | ||
| 250 | continue; | ||
| 251 | } | ||
| 252 | AttachShader(Stage(stage), program.handle, code); | ||
| 253 | } break; | ||
| 254 | case Settings::ShaderBackend::GLASM: { | ||
| 255 | const auto code{sources[stage]}; | ||
| 256 | if (code.empty()) { | ||
| 257 | continue; | ||
| 258 | } | ||
| 259 | assembly_programs[stage] = CompileProgram(code, AssemblyStage(stage)); | ||
| 260 | } break; | ||
| 261 | case Settings::ShaderBackend::SPIRV: { | ||
| 262 | const auto code{sources_spirv[stage]}; | ||
| 263 | if (code.empty()) { | ||
| 264 | continue; | ||
| 265 | } | ||
| 266 | AttachShader(Stage(stage), program.handle, code); | ||
| 267 | } break; | ||
| 268 | } | ||
| 248 | } | 269 | } |
| 249 | } | 270 | if (!device.UseAssemblyShaders()) { |
| 250 | if (!device.UseAssemblyShaders()) { | 271 | LinkProgram(program.handle); |
| 251 | LinkProgram(program.handle); | 272 | } |
| 252 | } | 273 | if (shader_notify) { |
| 253 | if (shader_notify) { | 274 | shader_notify->MarkShaderComplete(); |
| 254 | shader_notify->MarkShaderComplete(); | 275 | } |
| 255 | } | 276 | is_built.store(true, std::memory_order_relaxed); |
| 256 | is_built.store(true, std::memory_order_relaxed); | 277 | }}; |
| 257 | }}; | ||
| 258 | if (thread_worker) { | 278 | if (thread_worker) { |
| 259 | thread_worker->QueueWork(std::move(func)); | 279 | thread_worker->QueueWork(std::move(func)); |
| 260 | } else { | 280 | } else { |
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.h b/src/video_core/renderer_opengl/gl_graphics_pipeline.h index f82d712f8..5f5d57385 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.h +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.h | |||
| @@ -78,6 +78,7 @@ public: | |||
| 78 | ProgramManager& program_manager_, StateTracker& state_tracker_, | 78 | ProgramManager& program_manager_, StateTracker& state_tracker_, |
| 79 | ShaderWorker* thread_worker, VideoCore::ShaderNotify* shader_notify, | 79 | ShaderWorker* thread_worker, VideoCore::ShaderNotify* shader_notify, |
| 80 | std::array<std::string, 5> sources, | 80 | std::array<std::string, 5> sources, |
| 81 | std::array<std::vector<u32>, 5> sources_spirv, | ||
| 81 | const std::array<const Shader::Info*, 5>& infos, | 82 | const std::array<const Shader::Info*, 5>& infos, |
| 82 | const GraphicsPipelineKey& key_); | 83 | const GraphicsPipelineKey& key_); |
| 83 | 84 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index af8e9f44d..cde0f54c9 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include "common/fs/path_util.h" | 15 | #include "common/fs/path_util.h" |
| 16 | #include "common/logging/log.h" | 16 | #include "common/logging/log.h" |
| 17 | #include "common/scope_exit.h" | 17 | #include "common/scope_exit.h" |
| 18 | #include "common/settings.h" | ||
| 18 | #include "common/thread_worker.h" | 19 | #include "common/thread_worker.h" |
| 19 | #include "core/core.h" | 20 | #include "core/core.h" |
| 20 | #include "shader_recompiler/backend/glasm/emit_glasm.h" | 21 | #include "shader_recompiler/backend/glasm/emit_glasm.h" |
| @@ -415,6 +416,7 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 415 | 416 | ||
| 416 | OGLProgram source_program; | 417 | OGLProgram source_program; |
| 417 | std::array<std::string, 5> sources; | 418 | std::array<std::string, 5> sources; |
| 419 | std::array<std::vector<u32>, 5> sources_spirv; | ||
| 418 | Shader::Backend::Bindings binding; | 420 | Shader::Backend::Bindings binding; |
| 419 | Shader::IR::Program* previous_program{}; | 421 | Shader::IR::Program* previous_program{}; |
| 420 | const bool use_glasm{device.UseAssemblyShaders()}; | 422 | const bool use_glasm{device.UseAssemblyShaders()}; |
| @@ -431,17 +433,23 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 431 | 433 | ||
| 432 | const auto runtime_info{ | 434 | const auto runtime_info{ |
| 433 | MakeRuntimeInfo(key, program, previous_program, glasm_use_storage_buffers, use_glasm)}; | 435 | MakeRuntimeInfo(key, program, previous_program, glasm_use_storage_buffers, use_glasm)}; |
| 434 | if (use_glasm) { | 436 | switch (device.GetShaderBackend()) { |
| 435 | sources[stage_index] = EmitGLASM(profile, runtime_info, program, binding); | 437 | case Settings::ShaderBackend::GLSL: |
| 436 | } else { | ||
| 437 | sources[stage_index] = EmitGLSL(profile, runtime_info, program, binding); | 438 | sources[stage_index] = EmitGLSL(profile, runtime_info, program, binding); |
| 439 | break; | ||
| 440 | case Settings::ShaderBackend::GLASM: | ||
| 441 | sources[stage_index] = EmitGLASM(profile, runtime_info, program, binding); | ||
| 442 | break; | ||
| 443 | case Settings::ShaderBackend::SPIRV: | ||
| 444 | sources_spirv[stage_index] = EmitSPIRV(profile, runtime_info, program, binding); | ||
| 445 | break; | ||
| 438 | } | 446 | } |
| 439 | previous_program = &program; | 447 | previous_program = &program; |
| 440 | } | 448 | } |
| 441 | auto* const thread_worker{build_in_parallel ? workers.get() : nullptr}; | 449 | auto* const thread_worker{build_in_parallel ? workers.get() : nullptr}; |
| 442 | return std::make_unique<GraphicsPipeline>(device, texture_cache, buffer_cache, gpu_memory, | 450 | return std::make_unique<GraphicsPipeline>( |
| 443 | maxwell3d, program_manager, state_tracker, | 451 | device, texture_cache, buffer_cache, gpu_memory, maxwell3d, program_manager, state_tracker, |
| 444 | thread_worker, &shader_notify, sources, infos, key); | 452 | thread_worker, &shader_notify, sources, sources_spirv, infos, key); |
| 445 | 453 | ||
| 446 | } catch (Shader::Exception& exception) { | 454 | } catch (Shader::Exception& exception) { |
| 447 | LOG_ERROR(Render_OpenGL, "{}", exception.what()); | 455 | LOG_ERROR(Render_OpenGL, "{}", exception.what()); |
| @@ -478,10 +486,24 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( | |||
| 478 | } | 486 | } |
| 479 | Shader::RuntimeInfo info; | 487 | Shader::RuntimeInfo info; |
| 480 | info.glasm_use_storage_buffers = num_storage_buffers <= device.GetMaxGLASMStorageBufferBlocks(); | 488 | info.glasm_use_storage_buffers = num_storage_buffers <= device.GetMaxGLASMStorageBufferBlocks(); |
| 481 | const std::string code{device.UseAssemblyShaders() ? EmitGLASM(profile, info, program) | 489 | |
| 482 | : EmitGLSL(profile, program)}; | 490 | std::string code{}; |
| 491 | std::vector<u32> code_spirv; | ||
| 492 | switch (device.GetShaderBackend()) { | ||
| 493 | case Settings::ShaderBackend::GLSL: | ||
| 494 | code = EmitGLSL(profile, program); | ||
| 495 | break; | ||
| 496 | case Settings::ShaderBackend::GLASM: | ||
| 497 | code = EmitGLASM(profile, info, program); | ||
| 498 | break; | ||
| 499 | case Settings::ShaderBackend::SPIRV: | ||
| 500 | code_spirv = EmitSPIRV(profile, program); | ||
| 501 | break; | ||
| 502 | } | ||
| 503 | |||
| 483 | return std::make_unique<ComputePipeline>(device, texture_cache, buffer_cache, gpu_memory, | 504 | return std::make_unique<ComputePipeline>(device, texture_cache, buffer_cache, gpu_memory, |
| 484 | kepler_compute, program_manager, program.info, code); | 505 | kepler_compute, program_manager, program.info, code, |
| 506 | code_spirv); | ||
| 485 | } catch (Shader::Exception& exception) { | 507 | } catch (Shader::Exception& exception) { |
| 486 | LOG_ERROR(Render_OpenGL, "{}", exception.what()); | 508 | LOG_ERROR(Render_OpenGL, "{}", exception.what()); |
| 487 | return nullptr; | 509 | return nullptr; |