diff --git a/src/common/hash.h b/src/common/hash.h index 5567725742..cc3cece682 100644 --- a/src/common/hash.h +++ b/src/common/hash.h @@ -20,4 +20,17 @@ static inline u64 ComputeHash64(const void* data, size_t len) { return CityHash64(static_cast(data), len); } +/** + * Computes a 64-bit hash of a struct. In addition to being POD (trivially copyable and having + * standard layout), it is also critical that either the struct includes no padding, or that any + * padding is initialized to a known value by memsetting the struct to 0 before filling it in. + */ +template +static inline u64 ComputeStructHash64(const T& data) { + static_assert( + std::is_trivially_copyable::value && std::is_standard_layout::value, + "Type passed to ComputeStructHash64 must be trivially copyable and standard layout"); + return ComputeHash64(&data, sizeof(data)); +} + } // namespace Common diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 9a61c0cfc2..3053b00387 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -65,6 +65,7 @@ PicaShaderConfig PicaShaderConfig::BuildFromRegs(const Pica::Regs& regs) { PicaShaderConfig res; auto& state = res.state; + // Memset structure to zero padding bits, so that they will be deterministic when hashing std::memset(&state, 0, sizeof(PicaShaderConfig::State)); state.scissor_test_mode = regs.rasterizer.scissor_test.mode; diff --git a/src/video_core/renderer_opengl/gl_shader_gen.h b/src/video_core/renderer_opengl/gl_shader_gen.h index 2302ae4533..c67ceb54dc 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.h +++ b/src/video_core/renderer_opengl/gl_shader_gen.h @@ -131,10 +131,6 @@ union PicaShaderConfig { } state; }; -#if (__GNUC__ >= 5) || defined(__clang__) || defined(_MSC_VER) -static_assert(std::is_trivially_copyable::value, - "PicaShaderConfig::State must be trivially copyable"); -#endif /** * Generates the GLSL vertex shader program source code for the current Pica state @@ -156,7 +152,7 @@ namespace std { template <> struct hash { size_t operator()(const GLShader::PicaShaderConfig& k) const { - return Common::ComputeHash64(&k.state, sizeof(GLShader::PicaShaderConfig::State)); + return Common::ComputeStructHash64(k.state); } }; } // namespace std