Merge pull request #1740 from FernandoS27/shader_props
Implemented Shader Unique Identifiers
This commit is contained in:
		@@ -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) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user