diff --git a/libopenage/renderer/opengl/renderer.cpp b/libopenage/renderer/opengl/renderer.cpp index 48639dc368..33b734790f 100644 --- a/libopenage/renderer/opengl/renderer.cpp +++ b/libopenage/renderer/opengl/renderer.cpp @@ -86,7 +86,7 @@ std::shared_ptr GlRenderer::get_display_target() { std::shared_ptr GlRenderer::add_uniform_buffer(resources::UniformBufferInfo const &info) { auto inputs = info.get_inputs(); - std::unordered_map uniforms{}; + std::vector uniforms{}; size_t offset = 0; for (auto const &input : inputs) { auto type = GL_UBO_INPUT_TYPE.get(input.type); @@ -94,14 +94,13 @@ std::shared_ptr GlRenderer::add_uniform_buffer(resources::Uniform // align offset to the size of the type offset += offset % size; - - uniforms.emplace( - std::make_pair(input.name, - GlInBlockUniform{type, - offset, - resources::UniformBufferInfo::get_size(input, info.get_layout()), - resources::UniformBufferInfo::get_stride_size(input.type, info.get_layout()), - input.count})); + uniforms.push_back( + GlInBlockUniform{type, + offset, + resources::UniformBufferInfo::get_size(input, info.get_layout()), + resources::UniformBufferInfo::get_stride_size(input.type, info.get_layout()), + input.count, + input.name}); offset += size; } diff --git a/libopenage/renderer/opengl/shader_data.h b/libopenage/renderer/opengl/shader_data.h index 7b987fb6a7..d60d16cb85 100644 --- a/libopenage/renderer/opengl/shader_data.h +++ b/libopenage/renderer/opengl/shader_data.h @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -61,6 +62,11 @@ struct GlInBlockUniform { * Only relevant for arrays. The number of elements in the array. */ size_t count; + + /** + * Name of the block uniform. + */ + std::string name; }; /** @@ -78,7 +84,7 @@ struct GlUniformBlock { /** * Maps uniform names within this block to their descriptions. */ - std::unordered_map uniforms; + std::vector uniforms; /** * The binding point assigned to this block. diff --git a/libopenage/renderer/opengl/shader_program.cpp b/libopenage/renderer/opengl/shader_program.cpp index da24ac1596..395ee395c2 100644 --- a/libopenage/renderer/opengl/shader_program.cpp +++ b/libopenage/renderer/opengl/shader_program.cpp @@ -125,7 +125,7 @@ GlShaderProgram::GlShaderProgram(const std::shared_ptr &context, std::vector uniform_indices(val); glGetActiveUniformBlockiv(handle, i_unif_block, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, uniform_indices.data()); - std::unordered_map uniforms; + std::vector uniforms; for (GLuint const i_unif : uniform_indices) { in_block_unifs.insert(i_unif); @@ -152,14 +152,14 @@ GlShaderProgram::GlShaderProgram(const std::shared_ptr &context, // We do not need to handle sampler types here like in the uniform loop below, // because named blocks cannot contain samplers. - uniforms.insert(std::make_pair( - name.data(), + uniforms.push_back( GlInBlockUniform{ type, size_t(offset), size_t(count) * GL_UNIFORM_TYPE_SIZE.get(type), size_t(stride), - size_t(count)})); + size_t(count), + std::string(name.data())}); } // ENSURE(block_binding < caps.max_uniform_buffer_bindings, @@ -257,10 +257,10 @@ GlShaderProgram::GlShaderProgram(const std::shared_ptr &context, for (auto const &pair : this->uniform_blocks) { log::log(MSG(dbg) << "(" << pair.second.index << ") " << pair.first << " (size: " << pair.second.data_size << ") {"); - for (auto const &unif_pair : pair.second.uniforms) { - log::log(MSG(dbg) << "\t+" << unif_pair.second.offset - << " " << unif_pair.first << ": " - << GLSL_TYPE_NAME.get(unif_pair.second.type)); + for (auto const &unif : pair.second.uniforms) { + log::log(MSG(dbg) << "\t+" << unif.offset + << " " << unif.name << ": " + << GLSL_TYPE_NAME.get(unif.type)); } log::log(MSG(dbg) << "}"); } @@ -478,9 +478,9 @@ void GlShaderProgram::bind_uniform_buffer(const char *block_name, std::shared_pt auto &block = this->uniform_blocks[block_name]; // Check if the uniform buffer matches the block definition - for (auto const &pair : block.uniforms) { - ENSURE(gl_buffer->has_uniform(pair.first.c_str()), - "Uniform buffer does not contain uniform '" << pair.first << "' required by block " << block_name); + for (auto const &unif : block.uniforms) { + ENSURE(gl_buffer->has_uniform(unif.name.c_str()), + "Uniform buffer does not contain uniform '" << unif.name << "' required by block " << block_name); } block.binding_point = gl_buffer->get_binding_point(); diff --git a/libopenage/renderer/opengl/uniform_buffer.cpp b/libopenage/renderer/opengl/uniform_buffer.cpp index c153d1e080..cc3aa3d3dc 100644 --- a/libopenage/renderer/opengl/uniform_buffer.cpp +++ b/libopenage/renderer/opengl/uniform_buffer.cpp @@ -16,7 +16,7 @@ namespace openage::renderer::opengl { GlUniformBuffer::GlUniformBuffer(const std::shared_ptr &context, size_t size, - std::unordered_map uniforms, + std::vector uniforms, GLuint binding_point, GLenum usage) : GlSimpleObject(context, @@ -35,7 +35,7 @@ GlUniformBuffer::GlUniformBuffer(const std::shared_ptr &context, uniform_id_t unif_id = 0; for (auto &uniform : uniforms) { - this->uniforms_by_name.insert(std::make_pair(uniform.first, unif_id)); + this->uniforms_by_name.insert(std::make_pair(uniform.name, unif_id)); unif_id += 1; } @@ -62,25 +62,30 @@ void GlUniformBuffer::update_uniforms(std::shared_ptr const this->bind(); const auto &update_offs = glunif_in->update_offs; + const auto &used_uniforms = glunif_in->used_uniforms; + const auto &uniforms = this->uniforms; uint8_t const *data = glunif_in->update_data.data(); - for (auto const &pair : this->uniforms_by_name) { - auto id = pair.second; - auto offset = update_offs[id]; + + size_t unif_count = used_uniforms.size(); + for (size_t i = 0; i < unif_count; ++i) { + uniform_id_t unif_id = used_uniforms[i]; + auto offset = update_offs[unif_id]; + uint8_t const *ptr = data + offset.offset; - auto unif_def = this->uniforms.find(pair.first)->second; - auto loc = unif_def.offset; - auto size = unif_def.size; + auto &unif = uniforms[unif_id]; + auto loc = unif.offset; + auto size = unif.size; glBufferSubData(GL_UNIFORM_BUFFER, loc, size, ptr); } } -const std::unordered_map &GlUniformBuffer::get_uniforms() const { +const std::vector &GlUniformBuffer::get_uniforms() const { return this->uniforms; } -bool GlUniformBuffer::has_uniform(const char *unif) { - return this->uniforms.count(unif) != 0; +bool GlUniformBuffer::has_uniform(const char *name) { + return this->uniforms_by_name.contains(name); } void GlUniformBuffer::bind() const { @@ -100,11 +105,7 @@ void GlUniformBuffer::set_unif(UniformBufferInput &in, const char *unif, void co ENSURE(unif_id < this->uniforms.size(), "Tried to set uniform with invalid ID " << unif_id); - auto uniform = this->uniforms.find(unif); - ENSURE(uniform != std::end(this->uniforms), - "Tried to set uniform " << unif << " that does not exist in the shader program."); - - auto const &unif_data = uniform->second; + auto const &unif_data = this->uniforms[unif_id]; ENSURE(type == unif_data.type, "Tried to set uniform " << unif << " to a value of the wrong type."); diff --git a/libopenage/renderer/opengl/uniform_buffer.h b/libopenage/renderer/opengl/uniform_buffer.h index 0fdfc7309d..24fd1e23a2 100644 --- a/libopenage/renderer/opengl/uniform_buffer.h +++ b/libopenage/renderer/opengl/uniform_buffer.h @@ -22,7 +22,7 @@ class GlUniformBuffer final : public UniformBuffer public: GlUniformBuffer(const std::shared_ptr &context, size_t size, - std::unordered_map uniforms, + std::vector uniforms, GLuint binding_point = 0, GLenum usage = GL_DYNAMIC_DRAW); @@ -38,7 +38,7 @@ class GlUniformBuffer final : public UniformBuffer * * @return Uniforms in the shader program. */ - const std::unordered_map &get_uniforms() const; + const std::vector &get_uniforms() const; /** * Set the binding point of the buffer. @@ -95,7 +95,7 @@ class GlUniformBuffer final : public UniformBuffer /** * Uniform definitions inside the buffer. */ - std::unordered_map uniforms; + std::vector uniforms; /** * Maps uniform names to their ID (the index in the uniform vector). diff --git a/libopenage/renderer/opengl/uniform_input.cpp b/libopenage/renderer/opengl/uniform_input.cpp index 0121cc751a..38c63f2d66 100644 --- a/libopenage/renderer/opengl/uniform_input.cpp +++ b/libopenage/renderer/opengl/uniform_input.cpp @@ -42,8 +42,8 @@ GlUniformBufferInput::GlUniformBufferInput(const std::shared_ptr size_t offset = 0; this->update_offs.reserve(uniforms.size()); for (auto &uniform : uniforms) { - this->update_offs.push_back({uniform.second.offset, false}); - offset += GL_UNIFORM_TYPE_SIZE.get(uniform.second.type); + this->update_offs.push_back({uniform.offset, false}); + offset += GL_UNIFORM_TYPE_SIZE.get(uniform.type); } // Resize the update data buffer to the total size of all uniforms.