From 1fd979f50a9f4c21fa8cafba7268d959e3076924 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 22 Aug 2018 15:43:52 -0400 Subject: [PATCH] gl_shader_gen: Use a std::vector to represent program code instead of std::array While convenient as a std::array, it's also quite a large set of data as well (32KB). It being an array also means data cannot be std::moved. Any situation where the code is being set or relocated means that a full copy of that 32KB data must be done. If we use a std::vector we do need to allocate on the heap, however, it does allow us to std::move the data we have within the std::vector into another std::vector instance, eliminating the need to always copy the program data (as std::move in this case would just transfer the pointers and bare necessities over to the new vector instance). --- .../renderer_opengl/gl_rasterizer.cpp | 2 +- .../renderer_opengl/gl_shader_gen.h | 25 +++++++++++-------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 35056d9bd..3e5142bb1 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -179,7 +179,7 @@ static GLShader::ProgramCode GetShaderProgramCode(Maxwell::ShaderProgram program auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); // Fetch program code from memory - GLShader::ProgramCode program_code; + GLShader::ProgramCode program_code(GLShader::MAX_PROGRAM_CODE_LENGTH); auto& shader_config = gpu.regs.shader_config[static_cast(program)]; const u64 gpu_address{gpu.regs.code_address.CodeAddress() + shader_config.offset}; const boost::optional cpu_address{gpu.memory_manager.GpuToCpuAddress(gpu_address)}; diff --git a/src/video_core/renderer_opengl/gl_shader_gen.h b/src/video_core/renderer_opengl/gl_shader_gen.h index 4729ce0fc..6a1dab0e5 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.h +++ b/src/video_core/renderer_opengl/gl_shader_gen.h @@ -9,14 +9,14 @@ #include #include #include +#include #include "common/common_types.h" #include "common/hash.h" namespace GLShader { constexpr size_t MAX_PROGRAM_CODE_LENGTH{0x1000}; - -using ProgramCode = std::array; +using ProgramCode = std::vector; class ConstBufferEntry { using Maxwell = Tegra::Engines::Maxwell3D::Regs; @@ -115,8 +115,8 @@ struct ShaderEntries { using ProgramResult = std::pair; struct ShaderSetup { - ShaderSetup(const ProgramCode& program_code) { - program.code = program_code; + ShaderSetup(ProgramCode program_code) { + program.code = std::move(program_code); } struct { @@ -135,8 +135,8 @@ struct ShaderSetup { } /// Used in scenarios where we have a dual vertex shaders - void SetProgramB(const ProgramCode& program_b) { - program.code_b = program_b; + void SetProgramB(ProgramCode program_b) { + program.code_b = std::move(program_b); has_program_b = true; } @@ -146,13 +146,18 @@ struct ShaderSetup { private: u64 GetNewHash() const { + size_t hash = 0; + + const u64 hash_a = Common::ComputeHash64(program.code.data(), program.code.size()); + boost::hash_combine(hash, hash_a); + if (has_program_b) { // Compute hash over dual shader programs - return Common::ComputeHash64(&program, sizeof(program)); - } else { - // Compute hash over a single shader program - return Common::ComputeHash64(&program.code, program.code.size()); + const u64 hash_b = Common::ComputeHash64(program.code_b.data(), program.code_b.size()); + boost::hash_combine(hash, hash_b); } + + return hash; } u64 program_code_hash{};