diff --git a/src/base/hash.h b/src/base/hash.h index 0cd4432..2cf1992 100644 --- a/src/base/hash.h +++ b/src/base/hash.h @@ -6,17 +6,15 @@ namespace base { -// Compile-time string hashing function. template -constexpr inline size_t Hash(const char (&str)[N], size_t Len = N - 1) { +constexpr inline size_t KR2Hash(const char (&str)[N], size_t Len = N - 1) { size_t hash_value = 0; for (int i = 0; str[i] != '\0'; ++i) hash_value = str[i] + 31 * hash_value; return hash_value; } -// The same hashing function for run-time. -inline size_t Hash(const std::string& str) { +inline size_t KR2Hash(const std::string& str) { size_t hash_value = 0; for (std::string::value_type c : str) hash_value = c + 31 * hash_value; diff --git a/src/engine/renderer/opengl/renderer_opengl.cc b/src/engine/renderer/opengl/renderer_opengl.cc index 045d8f0..cb4562d 100644 --- a/src/engine/renderer/opengl/renderer_opengl.cc +++ b/src/engine/renderer/opengl/renderer_opengl.cc @@ -5,6 +5,7 @@ #include #include +#include "base/hash.h" #include "base/log.h" #include "base/vecmath.h" #include "engine/asset/image.h" @@ -615,10 +616,11 @@ bool RendererOpenGL::BindAttributeLocation(GLuint id, GLint RendererOpenGL::GetUniformLocation( GLuint id, const std::string& name, - std::vector>& uniforms) { + std::vector>& uniforms) { // Check if we've encountered this uniform before. + auto hash = KR2Hash(name); auto it = std::find_if(uniforms.begin(), uniforms.end(), - [&](auto& r) { return name == std::get<0>(r); }); + [&](auto& r) { return hash == std::get<0>(r); }); GLint index; if (it != uniforms.end()) { // Yes, we already have the mapping. @@ -626,11 +628,16 @@ GLint RendererOpenGL::GetUniformLocation( } else { // No, ask the driver for the mapping and save it. index = glGetUniformLocation(id, name.c_str()); - if (index >= 0) - uniforms.emplace_back(std::make_pair(name, index)); - else + if (index >= 0) { + DCHECK(std::find_if(uniforms.begin(), uniforms.end(), + [&](auto& r) { return hash == std::get<0>(r); }) == + uniforms.end()) + << "Hash collision"; + uniforms.emplace_back(std::make_pair(hash, index)); + } else { LOG(0) << "Cannot find uniform " << name.c_str() << " (shader: " << id << ")"; + } } return index; } diff --git a/src/engine/renderer/opengl/renderer_opengl.h b/src/engine/renderer/opengl/renderer_opengl.h index b9eb05e..02676ad 100644 --- a/src/engine/renderer/opengl/renderer_opengl.h +++ b/src/engine/renderer/opengl/renderer_opengl.h @@ -95,7 +95,10 @@ class RendererOpenGL final : public Renderer { struct ShaderOpenGL { GLuint id = 0; - std::vector> uniforms; + std::vector> + uniforms; bool enable_depth_test = false; }; @@ -139,10 +142,9 @@ class RendererOpenGL final : public Renderer { std::vector& vertex_layout); GLuint CreateShader(const char* source, GLenum type); bool BindAttributeLocation(GLuint id, const VertexDescription& vd); - GLint GetUniformLocation( - GLuint id, - const std::string& name, - std::vector>& uniforms); + GLint GetUniformLocation(GLuint id, + const std::string& name, + std::vector>& uniforms); }; } // namespace eng diff --git a/src/engine/renderer/vulkan/renderer_vulkan.cc b/src/engine/renderer/vulkan/renderer_vulkan.cc index 0ad5413..999f747 100644 --- a/src/engine/renderer/vulkan/renderer_vulkan.cc +++ b/src/engine/renderer/vulkan/renderer_vulkan.cc @@ -5,6 +5,7 @@ #include #include +#include "base/hash.h" #include "base/log.h" #include "base/vecmath.h" #include "engine/asset/image.h" @@ -1876,12 +1877,12 @@ bool RendererVulkan::CreatePipelineLayout( size_t offset = 0; for (uint32_t j = 0; j < pconstants_vertex[0]->member_count; j++) { - DCHECK(std::find_if(shader.variables.begin(), shader.variables.end(), - [&](auto& r) { - return pconstants_vertex[0]->members[j].name == - std::get<0>(r); - }) == shader.variables.end()) - << "Duplicate uniform name"; + DCHECK(std::find_if( + shader.variables.begin(), shader.variables.end(), + [hash = KR2Hash(pconstants_vertex[0]->members[j].name)]( + auto& r) { return hash == std::get<0>(r); }) == + shader.variables.end()) + << "Hash collision"; DLOG(0) << __func__ << " name: " << pconstants_vertex[0]->members[j].name @@ -1890,7 +1891,7 @@ bool RendererVulkan::CreatePipelineLayout( << pconstants_vertex[0]->members[j].padded_size; shader.variables.emplace_back( - std::make_tuple(pconstants_vertex[0]->members[j].name, + std::make_tuple(KR2Hash(pconstants_vertex[0]->members[j].name), pconstants_vertex[0]->members[j].size, offset)); offset += pconstants_vertex[0]->members[j].padded_size; } @@ -2040,8 +2041,9 @@ template bool RendererVulkan::SetUniformInternal(ShaderVulkan& shader, const std::string& name, T val) { + auto hash = KR2Hash(name); auto it = std::find_if(shader.variables.begin(), shader.variables.end(), - [&](auto& r) { return name == std::get<0>(r); }); + [&](auto& r) { return hash == std::get<0>(r); }); if (it == shader.variables.end()) { DLOG(0) << "No variable found with name " << name; return false; diff --git a/src/engine/renderer/vulkan/renderer_vulkan.h b/src/engine/renderer/vulkan/renderer_vulkan.h index 5693911..df07dc5 100644 --- a/src/engine/renderer/vulkan/renderer_vulkan.h +++ b/src/engine/renderer/vulkan/renderer_vulkan.h @@ -106,7 +106,11 @@ class RendererVulkan final : public Renderer { }; struct ShaderVulkan { - std::vector> variables; + std::vector> + variables; std::unique_ptr push_constants; size_t push_constants_size = 0; std::vector sampler_uniform_names;