summaryrefslogtreecommitdiff
path: root/src/video_core/renderer_opengl
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2020-04-24 01:44:14 -0300
committerGravatar ReinUsesLisp2020-04-26 01:38:51 -0300
commitddd82ef42b7bb7bea4c80edeb96bca8512580df3 (patch)
treeb2b09f597fe519128d065f034d51103f478e6776 /src/video_core/renderer_opengl
parentMerge pull request #3768 from H27CK/cmd-title-fmt (diff)
downloadyuzu-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.cpp82
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
34namespace OpenGL { 33namespace OpenGL {
35 34
36using Tegra::Engines::ShaderType; 35using Tegra::Engines::ShaderType;
36using VideoCommon::Shader::GetShaderAddress;
37using VideoCommon::Shader::GetShaderCode;
38using VideoCommon::Shader::GetUniqueIdentifier;
39using VideoCommon::Shader::KERNEL_MAIN_OFFSET;
37using VideoCommon::Shader::ProgramCode; 40using VideoCommon::Shader::ProgramCode;
38using VideoCommon::Shader::Registry; 41using VideoCommon::Shader::Registry;
39using VideoCommon::Shader::ShaderIR; 42using VideoCommon::Shader::ShaderIR;
43using VideoCommon::Shader::STAGE_MAIN_OFFSET;
40 44
41namespace { 45namespace {
42 46
43constexpr u32 STAGE_MAIN_OFFSET = 10;
44constexpr u32 KERNEL_MAIN_OFFSET = 0;
45
46constexpr VideoCommon::Shader::CompilerSettings COMPILER_SETTINGS{}; 47constexpr VideoCommon::Shader::CompilerSettings COMPILER_SETTINGS{};
47 48
48/// Gets the address for the specified shader stage program
49GPUVAddr 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
56constexpr 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
64std::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
89ProgramCode 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
102constexpr GLenum GetGLShaderType(ShaderType shader_type) { 50constexpr 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
118u64 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
128constexpr const char* GetShaderTypeName(ShaderType shader_type) { 65constexpr 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,