Use a vector instead of unordered_map for shader variables

This commit is contained in:
Attila Uygun 2023-07-10 15:49:02 +02:00
parent cccc6ca8c3
commit 6bad0ac9c0
4 changed files with 30 additions and 16 deletions

View File

@ -615,18 +615,19 @@ bool RendererOpenGL::BindAttributeLocation(GLuint id,
GLint RendererOpenGL::GetUniformLocation( GLint RendererOpenGL::GetUniformLocation(
GLuint id, GLuint id,
const std::string& name, const std::string& name,
std::unordered_map<std::string, GLuint>& uniforms) { std::vector<std::pair<std::string, GLuint>>& uniforms) {
// Check if we've encountered this uniform before. // Check if we've encountered this uniform before.
auto i = uniforms.find(name); auto it = std::find_if(uniforms.begin(), uniforms.end(),
[&](auto& r) { return name == std::get<0>(r); });
GLint index; GLint index;
if (i != uniforms.end()) { if (it != uniforms.end()) {
// Yes, we already have the mapping. // Yes, we already have the mapping.
index = i->second; index = std::get<1>(*it);
} 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[name] = index; uniforms.emplace_back(std::make_pair(name, index));
else else
LOG(0) << "Cannot find uniform " << name.c_str() << " (shader: " << id LOG(0) << "Cannot find uniform " << name.c_str() << " (shader: " << id
<< ")"; << ")";

View File

@ -4,6 +4,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <utility>
#include <vector> #include <vector>
#include "engine/renderer/opengl/opengl.h" #include "engine/renderer/opengl/opengl.h"
@ -94,7 +95,7 @@ class RendererOpenGL final : public Renderer {
struct ShaderOpenGL { struct ShaderOpenGL {
GLuint id = 0; GLuint id = 0;
std::unordered_map<std::string, GLuint> uniforms; std::vector<std::pair<std::string, GLuint>> uniforms;
bool enable_depth_test = false; bool enable_depth_test = false;
}; };
@ -138,9 +139,10 @@ 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(GLuint id, GLint GetUniformLocation(
const std::string& name, GLuint id,
std::unordered_map<std::string, GLuint>& uniforms); const std::string& name,
std::vector<std::pair<std::string, GLuint>>& uniforms);
}; };
} // namespace eng } // namespace eng

View File

@ -1876,19 +1876,27 @@ 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(),
[&](auto& r) {
return pconstants_vertex[0]->members[j].name ==
std::get<0>(r);
}) == shader.variables.end())
<< "Duplicate uniform name";
DLOG(0) << __func__ DLOG(0) << __func__
<< " name: " << pconstants_vertex[0]->members[j].name << " name: " << pconstants_vertex[0]->members[j].name
<< " size: " << pconstants_vertex[0]->members[j].size << " size: " << pconstants_vertex[0]->members[j].size
<< " padded_size: " << " padded_size: "
<< pconstants_vertex[0]->members[j].padded_size; << pconstants_vertex[0]->members[j].padded_size;
shader.variables[pconstants_vertex[0]->members[j].name] = { shader.variables.emplace_back(
pconstants_vertex[0]->members[j].size, offset}; std::make_tuple(pconstants_vertex[0]->members[j].name,
pconstants_vertex[0]->members[j].size, offset));
offset += pconstants_vertex[0]->members[j].padded_size; offset += pconstants_vertex[0]->members[j].padded_size;
} }
} }
// Use the same layout for all decriptor sets. // Use the same layout for all descriptor sets.
std::vector<VkDescriptorSetLayout> desc_set_layouts; std::vector<VkDescriptorSetLayout> desc_set_layouts;
for (size_t i = 0; i < binding_count; ++i) for (size_t i = 0; i < binding_count; ++i)
desc_set_layouts.push_back(descriptor_set_layout_); desc_set_layouts.push_back(descriptor_set_layout_);
@ -2032,17 +2040,20 @@ 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 it = shader.variables.find(name); auto it = std::find_if(shader.variables.begin(), shader.variables.end(),
[&](auto& r) { return name == 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;
} }
if (it->second[0] != sizeof(val)) {
if (std::get<1>(*it) != sizeof(val)) {
DLOG(0) << "Size mismatch for variable " << name; DLOG(0) << "Size mismatch for variable " << name;
return false; return false;
} }
auto* dst = reinterpret_cast<T*>(shader.push_constants.get() + it->second[1]); auto* dst =
reinterpret_cast<T*>(shader.push_constants.get() + std::get<2>(*it));
*dst = val; *dst = val;
return true; return true;
} }

View File

@ -106,7 +106,7 @@ class RendererVulkan final : public Renderer {
}; };
struct ShaderVulkan { struct ShaderVulkan {
std::unordered_map<std::string, std::array<size_t, 2>> variables; std::vector<std::tuple<std::string, size_t, size_t>> 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;