Pārlūkot izejas kodu

Merge pull request #1740 from FernandoS27/shader_props

Implemented Shader Unique Identifiers
bunnei 7 gadi atpakaļ
vecāks
revīzija
5b5d0199fe

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

@@ -2,7 +2,9 @@
 // Licensed under GPLv2 or any later version
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 // Refer to the license.txt file included.
 
 
+#include <boost/functional/hash.hpp>
 #include "common/assert.h"
 #include "common/assert.h"
+#include "common/hash.h"
 #include "core/core.h"
 #include "core/core.h"
 #include "core/memory.h"
 #include "core/memory.h"
 #include "video_core/engines/maxwell_3d.h"
 #include "video_core/engines/maxwell_3d.h"
@@ -66,14 +68,17 @@ CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type)
         // stage here.
         // stage here.
         setup.SetProgramB(GetShaderCode(GetShaderAddress(Maxwell::ShaderProgram::VertexB)));
         setup.SetProgramB(GetShaderCode(GetShaderAddress(Maxwell::ShaderProgram::VertexB)));
     case Maxwell::ShaderProgram::VertexB:
     case Maxwell::ShaderProgram::VertexB:
+        CalculateProperties();
         program_result = GLShader::GenerateVertexShader(setup);
         program_result = GLShader::GenerateVertexShader(setup);
         gl_type = GL_VERTEX_SHADER;
         gl_type = GL_VERTEX_SHADER;
         break;
         break;
     case Maxwell::ShaderProgram::Geometry:
     case Maxwell::ShaderProgram::Geometry:
+        CalculateProperties();
         program_result = GLShader::GenerateGeometryShader(setup);
         program_result = GLShader::GenerateGeometryShader(setup);
         gl_type = GL_GEOMETRY_SHADER;
         gl_type = GL_GEOMETRY_SHADER;
         break;
         break;
     case Maxwell::ShaderProgram::Fragment:
     case Maxwell::ShaderProgram::Fragment:
+        CalculateProperties();
         program_result = GLShader::GenerateFragmentShader(setup);
         program_result = GLShader::GenerateFragmentShader(setup);
         gl_type = GL_FRAGMENT_SHADER;
         gl_type = GL_FRAGMENT_SHADER;
         break;
         break;
@@ -140,6 +145,46 @@ GLuint CachedShader::LazyGeometryProgram(OGLProgram& target_program,
     return target_program.handle;
     return target_program.handle;
 };
 };
 
 
+static bool IsSchedInstruction(u32 offset, u32 main_offset) {
+    // sched instructions appear once every 4 instructions.
+    static constexpr std::size_t SchedPeriod = 4;
+    const std::size_t absolute_offset = offset - main_offset;
+    return (absolute_offset % SchedPeriod) == 0;
+}
+
+static std::size_t CalculateProgramSize(const GLShader::ProgramCode& program) {
+    const std::size_t start_offset = 10;
+    std::size_t offset = start_offset;
+    std::size_t size = start_offset * sizeof(u64);
+    while (offset < program.size()) {
+        const u64 inst = program[offset];
+        if (!IsSchedInstruction(offset, start_offset)) {
+            if (inst == 0 || (inst >> 52) == 0x50b) {
+                break;
+            }
+        }
+        size += 8;
+        offset++;
+    }
+    return size;
+}
+
+void CachedShader::CalculateProperties() {
+    setup.program.real_size = CalculateProgramSize(setup.program.code);
+    setup.program.real_size_b = 0;
+    setup.program.unique_identifier = Common::CityHash64(
+        reinterpret_cast<const char*>(setup.program.code.data()), setup.program.real_size);
+    if (program_type == Maxwell::ShaderProgram::VertexA) {
+        std::size_t seed = 0;
+        boost::hash_combine(seed, setup.program.unique_identifier);
+        setup.program.real_size_b = CalculateProgramSize(setup.program.code_b);
+        const u64 identifier_b = Common::CityHash64(
+            reinterpret_cast<const char*>(setup.program.code_b.data()), setup.program.real_size_b);
+        boost::hash_combine(seed, identifier_b);
+        setup.program.unique_identifier = static_cast<u64>(seed);
+    }
+}
+
 ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer) : RasterizerCache{rasterizer} {}
 ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer) : RasterizerCache{rasterizer} {}
 
 
 Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {
 Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {

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

@@ -81,6 +81,8 @@ private:
     GLuint LazyGeometryProgram(OGLProgram& target_program, const std::string& glsl_topology,
     GLuint LazyGeometryProgram(OGLProgram& target_program, const std::string& glsl_topology,
                                u32 max_vertices, const std::string& debug_name);
                                u32 max_vertices, const std::string& debug_name);
 
 
+    void CalculateProperties();
+
     VAddr addr;
     VAddr addr;
     std::size_t shader_length;
     std::size_t shader_length;
     Maxwell::ShaderProgram program_type;
     Maxwell::ShaderProgram program_type;

+ 7 - 0
src/video_core/renderer_opengl/gl_shader_gen.cpp

@@ -2,6 +2,7 @@
 // Licensed under GPLv2 or any later version
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 // Refer to the license.txt file included.
 
 
+#include <fmt/format.h>
 #include "common/assert.h"
 #include "common/assert.h"
 #include "video_core/engines/maxwell_3d.h"
 #include "video_core/engines/maxwell_3d.h"
 #include "video_core/renderer_opengl/gl_shader_decompiler.h"
 #include "video_core/renderer_opengl/gl_shader_decompiler.h"
@@ -16,6 +17,8 @@ static constexpr u32 PROGRAM_OFFSET{10};
 ProgramResult GenerateVertexShader(const ShaderSetup& setup) {
 ProgramResult GenerateVertexShader(const ShaderSetup& setup) {
     std::string out = "#version 430 core\n";
     std::string out = "#version 430 core\n";
     out += "#extension GL_ARB_separate_shader_objects : enable\n\n";
     out += "#extension GL_ARB_separate_shader_objects : enable\n\n";
+    const std::string id = fmt::format("{:016x}", setup.program.unique_identifier);
+    out += "// Shader Unique Id: VS" + id + "\n\n";
     out += Decompiler::GetCommonDeclarations();
     out += Decompiler::GetCommonDeclarations();
 
 
     out += R"(
     out += R"(
@@ -84,6 +87,8 @@ void main() {
 ProgramResult GenerateGeometryShader(const ShaderSetup& setup) {
 ProgramResult GenerateGeometryShader(const ShaderSetup& setup) {
     // Version is intentionally skipped in shader generation, it's added by the lazy compilation.
     // Version is intentionally skipped in shader generation, it's added by the lazy compilation.
     std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n";
     std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n";
+    const std::string id = fmt::format("{:016x}", setup.program.unique_identifier);
+    out += "// Shader Unique Id: GS" + id + "\n\n";
     out += Decompiler::GetCommonDeclarations();
     out += Decompiler::GetCommonDeclarations();
     out += "bool exec_geometry();\n";
     out += "bool exec_geometry();\n";
 
 
@@ -117,6 +122,8 @@ void main() {
 ProgramResult GenerateFragmentShader(const ShaderSetup& setup) {
 ProgramResult GenerateFragmentShader(const ShaderSetup& setup) {
     std::string out = "#version 430 core\n";
     std::string out = "#version 430 core\n";
     out += "#extension GL_ARB_separate_shader_objects : enable\n\n";
     out += "#extension GL_ARB_separate_shader_objects : enable\n\n";
+    const std::string id = fmt::format("{:016x}", setup.program.unique_identifier);
+    out += "// Shader Unique Id: FS" + id + "\n\n";
     out += Decompiler::GetCommonDeclarations();
     out += Decompiler::GetCommonDeclarations();
     out += "bool exec_fragment();\n";
     out += "bool exec_fragment();\n";
 
 

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

@@ -177,6 +177,9 @@ struct ShaderSetup {
     struct {
     struct {
         ProgramCode code;
         ProgramCode code;
         ProgramCode code_b; // Used for dual vertex shaders
         ProgramCode code_b; // Used for dual vertex shaders
+        u64 unique_identifier;
+        std::size_t real_size;
+        std::size_t real_size_b;
     } program;
     } program;
 
 
     /// Used in scenarios where we have a dual vertex shaders
     /// Used in scenarios where we have a dual vertex shaders