Kaynağa Gözat

shader_cache: Only lock covered instructions.

Markus Wick 7 yıl önce
ebeveyn
işleme
cfbae58b2b

+ 1 - 0
src/video_core/renderer_opengl/gl_shader_cache.cpp

@@ -84,6 +84,7 @@ CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type)
     }
 
     entries = program_result.second;
+    shader_length = entries.shader_length;
 
     if (program_type != Maxwell::ShaderProgram::Geometry) {
         OGLShader shader;

+ 2 - 1
src/video_core/renderer_opengl/gl_shader_cache.h

@@ -30,7 +30,7 @@ public:
     }
 
     std::size_t GetSizeInBytes() const override {
-        return GLShader::MAX_PROGRAM_CODE_LENGTH * sizeof(u64);
+        return shader_length;
     }
 
     // We do not have to flush this cache as things in it are never modified by us.
@@ -82,6 +82,7 @@ private:
                                u32 max_vertices, const std::string& debug_name);
 
     VAddr addr;
+    std::size_t shader_length;
     Maxwell::ShaderProgram program_type;
     GLShader::ShaderSetup setup;
     GLShader::ShaderEntries entries;

+ 20 - 7
src/video_core/renderer_opengl/gl_shader_decompiler.cpp

@@ -85,7 +85,8 @@ struct Subroutine {
 class ControlFlowAnalyzer {
 public:
     ControlFlowAnalyzer(const ProgramCode& program_code, u32 main_offset, const std::string& suffix)
-        : program_code(program_code) {
+        : program_code(program_code), shader_coverage_begin(main_offset),
+          shader_coverage_end(main_offset + 1) {
 
         // Recursively finds all subroutines.
         const Subroutine& program_main = AddSubroutine(main_offset, PROGRAM_END, suffix);
@@ -97,10 +98,16 @@ public:
         return std::move(subroutines);
     }
 
+    std::size_t GetShaderLength() const {
+        return shader_coverage_end * sizeof(u64);
+    }
+
 private:
     const ProgramCode& program_code;
     std::set<Subroutine> subroutines;
     std::map<std::pair<u32, u32>, ExitMethod> exit_method_map;
+    u32 shader_coverage_begin;
+    u32 shader_coverage_end;
 
     /// Adds and analyzes a new subroutine if it is not added yet.
     const Subroutine& AddSubroutine(u32 begin, u32 end, const std::string& suffix) {
@@ -142,6 +149,9 @@ private:
             return exit_method;
 
         for (u32 offset = begin; offset != end && offset != PROGRAM_END; ++offset) {
+            shader_coverage_begin = std::min(shader_coverage_begin, offset);
+            shader_coverage_end = std::max(shader_coverage_end, offset + 1);
+
             const Instruction instr = {program_code[offset]};
             if (const auto opcode = OpCode::Decode(instr)) {
                 switch (opcode->get().GetId()) {
@@ -951,9 +961,10 @@ private:
 class GLSLGenerator {
 public:
     GLSLGenerator(const std::set<Subroutine>& subroutines, const ProgramCode& program_code,
-                  u32 main_offset, Maxwell3D::Regs::ShaderStage stage, const std::string& suffix)
+                  u32 main_offset, Maxwell3D::Regs::ShaderStage stage, const std::string& suffix,
+                  std::size_t shader_length)
         : subroutines(subroutines), program_code(program_code), main_offset(main_offset),
-          stage(stage), suffix(suffix) {
+          stage(stage), suffix(suffix), shader_length(shader_length) {
         std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header));
         local_memory_size = header.GetLocalMemorySize();
         regs.SetLocalMemory(local_memory_size);
@@ -966,7 +977,7 @@ public:
 
     /// Returns entries in the shader that are useful for external functions
     ShaderEntries GetEntries() const {
-        return {regs.GetConstBuffersDeclarations(), regs.GetSamplers()};
+        return {regs.GetConstBuffersDeclarations(), regs.GetSamplers(), shader_length};
     }
 
 private:
@@ -3827,6 +3838,7 @@ private:
     Maxwell3D::Regs::ShaderStage stage;
     const std::string& suffix;
     u64 local_memory_size;
+    std::size_t shader_length;
 
     ShaderWriter shader;
     ShaderWriter declarations;
@@ -3845,9 +3857,10 @@ std::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u
                                               Maxwell3D::Regs::ShaderStage stage,
                                               const std::string& suffix) {
     try {
-        const auto subroutines =
-            ControlFlowAnalyzer(program_code, main_offset, suffix).GetSubroutines();
-        GLSLGenerator generator(subroutines, program_code, main_offset, stage, suffix);
+        ControlFlowAnalyzer analyzer(program_code, main_offset, suffix);
+        const auto subroutines = analyzer.GetSubroutines();
+        GLSLGenerator generator(subroutines, program_code, main_offset, stage, suffix,
+                                analyzer.GetShaderLength());
         return ProgramResult{generator.GetShaderCode(), generator.GetEntries()};
     } catch (const DecompileFail& exception) {
         LOG_ERROR(HW_GPU, "Shader decompilation failed: {}", exception.what());

+ 1 - 0
src/video_core/renderer_opengl/gl_shader_gen.h

@@ -163,6 +163,7 @@ private:
 struct ShaderEntries {
     std::vector<ConstBufferEntry> const_buffer_entries;
     std::vector<SamplerEntry> texture_samplers;
+    std::size_t shader_length;
 };
 
 using ProgramResult = std::pair<std::string, ShaderEntries>;