diff options
| author | 2020-04-24 01:44:14 -0300 | |
|---|---|---|
| committer | 2020-04-26 01:38:51 -0300 | |
| commit | ddd82ef42b7bb7bea4c80edeb96bca8512580df3 (patch) | |
| tree | b2b09f597fe519128d065f034d51103f478e6776 /src/video_core/renderer_opengl | |
| parent | Merge pull request #3768 from H27CK/cmd-title-fmt (diff) | |
| download | yuzu-ddd82ef42b7bb7bea4c80edeb96bca8512580df3.tar.gz yuzu-ddd82ef42b7bb7bea4c80edeb96bca8512580df3.tar.xz yuzu-ddd82ef42b7bb7bea4c80edeb96bca8512580df3.zip | |
shader/memory_util: Deduplicate code
Deduplicate code shared between vk_pipeline_cache and gl_shader_cache as
well as shader decoder code.
While we are at it, fix a bug in gl_shader_cache where compute shaders
had an start offset of a stage shader.
Diffstat (limited to 'src/video_core/renderer_opengl')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 82 |
1 files changed, 10 insertions, 72 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index f63156b8d..9759a7078 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -10,8 +10,6 @@ | |||
| 10 | #include <thread> | 10 | #include <thread> |
| 11 | #include <unordered_set> | 11 | #include <unordered_set> |
| 12 | 12 | ||
| 13 | #include <boost/functional/hash.hpp> | ||
| 14 | |||
| 15 | #include "common/alignment.h" | 13 | #include "common/alignment.h" |
| 16 | #include "common/assert.h" | 14 | #include "common/assert.h" |
| 17 | #include "common/logging/log.h" | 15 | #include "common/logging/log.h" |
| @@ -28,76 +26,26 @@ | |||
| 28 | #include "video_core/renderer_opengl/gl_shader_disk_cache.h" | 26 | #include "video_core/renderer_opengl/gl_shader_disk_cache.h" |
| 29 | #include "video_core/renderer_opengl/gl_state_tracker.h" | 27 | #include "video_core/renderer_opengl/gl_state_tracker.h" |
| 30 | #include "video_core/renderer_opengl/utils.h" | 28 | #include "video_core/renderer_opengl/utils.h" |
| 29 | #include "video_core/shader/memory_util.h" | ||
| 31 | #include "video_core/shader/registry.h" | 30 | #include "video_core/shader/registry.h" |
| 32 | #include "video_core/shader/shader_ir.h" | 31 | #include "video_core/shader/shader_ir.h" |
| 33 | 32 | ||
| 34 | namespace OpenGL { | 33 | namespace OpenGL { |
| 35 | 34 | ||
| 36 | using Tegra::Engines::ShaderType; | 35 | using Tegra::Engines::ShaderType; |
| 36 | using VideoCommon::Shader::GetShaderAddress; | ||
| 37 | using VideoCommon::Shader::GetShaderCode; | ||
| 38 | using VideoCommon::Shader::GetUniqueIdentifier; | ||
| 39 | using VideoCommon::Shader::KERNEL_MAIN_OFFSET; | ||
| 37 | using VideoCommon::Shader::ProgramCode; | 40 | using VideoCommon::Shader::ProgramCode; |
| 38 | using VideoCommon::Shader::Registry; | 41 | using VideoCommon::Shader::Registry; |
| 39 | using VideoCommon::Shader::ShaderIR; | 42 | using VideoCommon::Shader::ShaderIR; |
| 43 | using VideoCommon::Shader::STAGE_MAIN_OFFSET; | ||
| 40 | 44 | ||
| 41 | namespace { | 45 | namespace { |
| 42 | 46 | ||
| 43 | constexpr u32 STAGE_MAIN_OFFSET = 10; | ||
| 44 | constexpr u32 KERNEL_MAIN_OFFSET = 0; | ||
| 45 | |||
| 46 | constexpr VideoCommon::Shader::CompilerSettings COMPILER_SETTINGS{}; | 47 | constexpr VideoCommon::Shader::CompilerSettings COMPILER_SETTINGS{}; |
| 47 | 48 | ||
| 48 | /// Gets the address for the specified shader stage program | ||
| 49 | GPUVAddr GetShaderAddress(Core::System& system, Maxwell::ShaderProgram program) { | ||
| 50 | const auto& gpu{system.GPU().Maxwell3D()}; | ||
| 51 | const auto& shader_config{gpu.regs.shader_config[static_cast<std::size_t>(program)]}; | ||
| 52 | return gpu.regs.code_address.CodeAddress() + shader_config.offset; | ||
| 53 | } | ||
| 54 | |||
| 55 | /// Gets if the current instruction offset is a scheduler instruction | ||
| 56 | constexpr bool IsSchedInstruction(std::size_t offset, std::size_t main_offset) { | ||
| 57 | // Sched instructions appear once every 4 instructions. | ||
| 58 | constexpr std::size_t SchedPeriod = 4; | ||
| 59 | const std::size_t absolute_offset = offset - main_offset; | ||
| 60 | return (absolute_offset % SchedPeriod) == 0; | ||
| 61 | } | ||
| 62 | |||
| 63 | /// Calculates the size of a program stream | ||
| 64 | std::size_t CalculateProgramSize(const ProgramCode& program) { | ||
| 65 | constexpr std::size_t start_offset = 10; | ||
| 66 | // This is the encoded version of BRA that jumps to itself. All Nvidia | ||
| 67 | // shaders end with one. | ||
| 68 | constexpr u64 self_jumping_branch = 0xE2400FFFFF07000FULL; | ||
| 69 | constexpr u64 mask = 0xFFFFFFFFFF7FFFFFULL; | ||
| 70 | std::size_t offset = start_offset; | ||
| 71 | while (offset < program.size()) { | ||
| 72 | const u64 instruction = program[offset]; | ||
| 73 | if (!IsSchedInstruction(offset, start_offset)) { | ||
| 74 | if ((instruction & mask) == self_jumping_branch) { | ||
| 75 | // End on Maxwell's "nop" instruction | ||
| 76 | break; | ||
| 77 | } | ||
| 78 | if (instruction == 0) { | ||
| 79 | break; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | offset++; | ||
| 83 | } | ||
| 84 | // The last instruction is included in the program size | ||
| 85 | return std::min(offset + 1, program.size()); | ||
| 86 | } | ||
| 87 | |||
| 88 | /// Gets the shader program code from memory for the specified address | ||
| 89 | ProgramCode GetShaderCode(Tegra::MemoryManager& memory_manager, const GPUVAddr gpu_addr, | ||
| 90 | const u8* host_ptr) { | ||
| 91 | ProgramCode code(VideoCommon::Shader::MAX_PROGRAM_LENGTH); | ||
| 92 | ASSERT_OR_EXECUTE(host_ptr != nullptr, { | ||
| 93 | std::fill(code.begin(), code.end(), 0); | ||
| 94 | return code; | ||
| 95 | }); | ||
| 96 | memory_manager.ReadBlockUnsafe(gpu_addr, code.data(), code.size() * sizeof(u64)); | ||
| 97 | code.resize(CalculateProgramSize(code)); | ||
| 98 | return code; | ||
| 99 | } | ||
| 100 | |||
| 101 | /// Gets the shader type from a Maxwell program type | 49 | /// Gets the shader type from a Maxwell program type |
| 102 | constexpr GLenum GetGLShaderType(ShaderType shader_type) { | 50 | constexpr GLenum GetGLShaderType(ShaderType shader_type) { |
| 103 | switch (shader_type) { | 51 | switch (shader_type) { |
| @@ -114,17 +62,6 @@ constexpr GLenum GetGLShaderType(ShaderType shader_type) { | |||
| 114 | } | 62 | } |
| 115 | } | 63 | } |
| 116 | 64 | ||
| 117 | /// Hashes one (or two) program streams | ||
| 118 | u64 GetUniqueIdentifier(ShaderType shader_type, bool is_a, const ProgramCode& code, | ||
| 119 | const ProgramCode& code_b = {}) { | ||
| 120 | u64 unique_identifier = boost::hash_value(code); | ||
| 121 | if (is_a) { | ||
| 122 | // VertexA programs include two programs | ||
| 123 | boost::hash_combine(unique_identifier, boost::hash_value(code_b)); | ||
| 124 | } | ||
| 125 | return unique_identifier; | ||
| 126 | } | ||
| 127 | |||
| 128 | constexpr const char* GetShaderTypeName(ShaderType shader_type) { | 65 | constexpr const char* GetShaderTypeName(ShaderType shader_type) { |
| 129 | switch (shader_type) { | 66 | switch (shader_type) { |
| 130 | case ShaderType::Vertex: | 67 | case ShaderType::Vertex: |
| @@ -456,11 +393,12 @@ Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) { | |||
| 456 | const auto host_ptr{memory_manager.GetPointer(address)}; | 393 | const auto host_ptr{memory_manager.GetPointer(address)}; |
| 457 | 394 | ||
| 458 | // No shader found - create a new one | 395 | // No shader found - create a new one |
| 459 | ProgramCode code{GetShaderCode(memory_manager, address, host_ptr)}; | 396 | ProgramCode code{GetShaderCode(memory_manager, address, host_ptr, false)}; |
| 460 | ProgramCode code_b; | 397 | ProgramCode code_b; |
| 461 | if (program == Maxwell::ShaderProgram::VertexA) { | 398 | if (program == Maxwell::ShaderProgram::VertexA) { |
| 462 | const GPUVAddr address_b{GetShaderAddress(system, Maxwell::ShaderProgram::VertexB)}; | 399 | const GPUVAddr address_b{GetShaderAddress(system, Maxwell::ShaderProgram::VertexB)}; |
| 463 | code_b = GetShaderCode(memory_manager, address_b, memory_manager.GetPointer(address_b)); | 400 | const u8* host_ptr_b = memory_manager.GetPointer(address_b); |
| 401 | code_b = GetShaderCode(memory_manager, address_b, host_ptr_b, false); | ||
| 464 | } | 402 | } |
| 465 | 403 | ||
| 466 | const auto unique_identifier = GetUniqueIdentifier( | 404 | const auto unique_identifier = GetUniqueIdentifier( |
| @@ -498,7 +436,7 @@ Shader ShaderCacheOpenGL::GetComputeKernel(GPUVAddr code_addr) { | |||
| 498 | 436 | ||
| 499 | const auto host_ptr{memory_manager.GetPointer(code_addr)}; | 437 | const auto host_ptr{memory_manager.GetPointer(code_addr)}; |
| 500 | // No kernel found, create a new one | 438 | // No kernel found, create a new one |
| 501 | auto code{GetShaderCode(memory_manager, code_addr, host_ptr)}; | 439 | auto code{GetShaderCode(memory_manager, code_addr, host_ptr, true)}; |
| 502 | const auto unique_identifier{GetUniqueIdentifier(ShaderType::Compute, false, code)}; | 440 | const auto unique_identifier{GetUniqueIdentifier(ShaderType::Compute, false, code)}; |
| 503 | 441 | ||
| 504 | const ShaderParameters params{system, disk_cache, device, | 442 | const ShaderParameters params{system, disk_cache, device, |