Hash uniform name strings

This commit is contained in:
Attila Uygun 2023-07-12 02:32:22 +02:00
parent e509588f61
commit c5171ffc03
5 changed files with 36 additions and 23 deletions

View File

@ -6,17 +6,15 @@
namespace base { namespace base {
// Compile-time string hashing function.
template <size_t N> template <size_t N>
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; size_t hash_value = 0;
for (int i = 0; str[i] != '\0'; ++i) for (int i = 0; str[i] != '\0'; ++i)
hash_value = str[i] + 31 * hash_value; hash_value = str[i] + 31 * hash_value;
return hash_value; return hash_value;
} }
// The same hashing function for run-time. inline size_t KR2Hash(const std::string& str) {
inline size_t Hash(const std::string& str) {
size_t hash_value = 0; size_t hash_value = 0;
for (std::string::value_type c : str) for (std::string::value_type c : str)
hash_value = c + 31 * hash_value; hash_value = c + 31 * hash_value;

View File

@ -5,6 +5,7 @@
#include <sstream> #include <sstream>
#include <unordered_set> #include <unordered_set>
#include "base/hash.h"
#include "base/log.h" #include "base/log.h"
#include "base/vecmath.h" #include "base/vecmath.h"
#include "engine/asset/image.h" #include "engine/asset/image.h"
@ -615,10 +616,11 @@ bool RendererOpenGL::BindAttributeLocation(GLuint id,
GLint RendererOpenGL::GetUniformLocation( GLint RendererOpenGL::GetUniformLocation(
GLuint id, GLuint id,
const std::string& name, const std::string& name,
std::vector<std::pair<std::string, GLuint>>& uniforms) { std::vector<std::pair<size_t, GLuint>>& uniforms) {
// Check if we've encountered this uniform before. // Check if we've encountered this uniform before.
auto hash = KR2Hash(name);
auto it = std::find_if(uniforms.begin(), uniforms.end(), 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; GLint index;
if (it != uniforms.end()) { if (it != uniforms.end()) {
// Yes, we already have the mapping. // Yes, we already have the mapping.
@ -626,11 +628,16 @@ GLint RendererOpenGL::GetUniformLocation(
} else { } else {
// No, ask the driver for the mapping and save it. // No, ask the driver for the mapping and save it.
index = glGetUniformLocation(id, name.c_str()); index = glGetUniformLocation(id, name.c_str());
if (index >= 0) if (index >= 0) {
uniforms.emplace_back(std::make_pair(name, index)); DCHECK(std::find_if(uniforms.begin(), uniforms.end(),
else [&](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 LOG(0) << "Cannot find uniform " << name.c_str() << " (shader: " << id
<< ")"; << ")";
}
} }
return index; return index;
} }

View File

@ -95,7 +95,10 @@ class RendererOpenGL final : public Renderer {
struct ShaderOpenGL { struct ShaderOpenGL {
GLuint id = 0; GLuint id = 0;
std::vector<std::pair<std::string, GLuint>> uniforms; std::vector<std::pair<size_t, // Uniform name hash
GLuint // Uniform index
>>
uniforms;
bool enable_depth_test = false; bool enable_depth_test = false;
}; };
@ -139,10 +142,9 @@ class RendererOpenGL final : public Renderer {
std::vector<GeometryOpenGL::Element>& vertex_layout); std::vector<GeometryOpenGL::Element>& vertex_layout);
GLuint CreateShader(const char* source, GLenum type); GLuint CreateShader(const char* source, GLenum type);
bool BindAttributeLocation(GLuint id, const VertexDescription& vd); bool BindAttributeLocation(GLuint id, const VertexDescription& vd);
GLint GetUniformLocation( GLint GetUniformLocation(GLuint id,
GLuint id, const std::string& name,
const std::string& name, std::vector<std::pair<size_t, GLuint>>& uniforms);
std::vector<std::pair<std::string, GLuint>>& uniforms);
}; };
} // namespace eng } // namespace eng

View File

@ -5,6 +5,7 @@
#include <sstream> #include <sstream>
#include <utility> #include <utility>
#include "base/hash.h"
#include "base/log.h" #include "base/log.h"
#include "base/vecmath.h" #include "base/vecmath.h"
#include "engine/asset/image.h" #include "engine/asset/image.h"
@ -1876,12 +1877,12 @@ bool RendererVulkan::CreatePipelineLayout(
size_t offset = 0; size_t offset = 0;
for (uint32_t j = 0; j < pconstants_vertex[0]->member_count; j++) { for (uint32_t j = 0; j < pconstants_vertex[0]->member_count; j++) {
DCHECK(std::find_if(shader.variables.begin(), shader.variables.end(), DCHECK(std::find_if(
[&](auto& r) { shader.variables.begin(), shader.variables.end(),
return pconstants_vertex[0]->members[j].name == [hash = KR2Hash(pconstants_vertex[0]->members[j].name)](
std::get<0>(r); auto& r) { return hash == std::get<0>(r); }) ==
}) == shader.variables.end()) shader.variables.end())
<< "Duplicate uniform name"; << "Hash collision";
DLOG(0) << __func__ DLOG(0) << __func__
<< " name: " << pconstants_vertex[0]->members[j].name << " name: " << pconstants_vertex[0]->members[j].name
@ -1890,7 +1891,7 @@ bool RendererVulkan::CreatePipelineLayout(
<< pconstants_vertex[0]->members[j].padded_size; << pconstants_vertex[0]->members[j].padded_size;
shader.variables.emplace_back( 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)); pconstants_vertex[0]->members[j].size, offset));
offset += pconstants_vertex[0]->members[j].padded_size; offset += pconstants_vertex[0]->members[j].padded_size;
} }
@ -2040,8 +2041,9 @@ template <typename T>
bool RendererVulkan::SetUniformInternal(ShaderVulkan& shader, bool RendererVulkan::SetUniformInternal(ShaderVulkan& shader,
const std::string& name, const std::string& name,
T val) { T val) {
auto hash = KR2Hash(name);
auto it = std::find_if(shader.variables.begin(), shader.variables.end(), 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()) { if (it == shader.variables.end()) {
DLOG(0) << "No variable found with name " << name; DLOG(0) << "No variable found with name " << name;
return false; return false;

View File

@ -106,7 +106,11 @@ class RendererVulkan final : public Renderer {
}; };
struct ShaderVulkan { struct ShaderVulkan {
std::vector<std::tuple<std::string, size_t, size_t>> variables; std::vector<std::tuple<size_t, // Variable name hash
size_t, // Variable size
size_t // Push constant offset
>>
variables;
std::unique_ptr<char[]> push_constants; std::unique_ptr<char[]> push_constants;
size_t push_constants_size = 0; size_t push_constants_size = 0;
std::vector<std::string> sampler_uniform_names; std::vector<std::string> sampler_uniform_names;