diff --git a/libopenage/renderer/opengl/context.cpp b/libopenage/renderer/opengl/context.cpp index e02992d25e..59f82339aa 100644 --- a/libopenage/renderer/opengl/context.cpp +++ b/libopenage/renderer/opengl/context.cpp @@ -1,4 +1,4 @@ -// Copyright 2015-2023 the openage authors. See copying.md for legal info. +// Copyright 2015-2024 the openage authors. See copying.md for legal info. #include #include @@ -74,6 +74,8 @@ gl_context_spec GlContext::find_spec() { caps.max_texture_slots = temp; glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &temp); caps.max_vertex_attributes = temp; + glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &temp); + caps.max_uniform_locations = temp; glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &temp); caps.max_uniform_buffer_bindings = temp; diff --git a/libopenage/renderer/opengl/context.h b/libopenage/renderer/opengl/context.h index 1b9cd936ff..d0a3f4352a 100644 --- a/libopenage/renderer/opengl/context.h +++ b/libopenage/renderer/opengl/context.h @@ -24,6 +24,8 @@ struct gl_context_spec { size_t max_texture_slots; /// The maximum size of a single dimension of a texture. size_t max_texture_size; + /// The maximum number of uniform locations per shader. + size_t max_uniform_locations; /// The maximum number of binding points for uniform blocks /// in a single shader. size_t max_uniform_buffer_bindings; diff --git a/libopenage/renderer/opengl/lookup.h b/libopenage/renderer/opengl/lookup.h index a137101482..9521369ef5 100644 --- a/libopenage/renderer/opengl/lookup.h +++ b/libopenage/renderer/opengl/lookup.h @@ -33,6 +33,10 @@ static constexpr auto GL_UNIFORM_TYPE_SIZE = datastructure::create_const_map #include #include @@ -22,6 +23,13 @@ struct GlUniform { * NOT the same as the uniform index. */ GLuint location; + + /** + * Only used for sampler uniforms. + * + * Texture unit to which the sampler is bound. + */ + std::optional tex_unit; }; /** diff --git a/libopenage/renderer/opengl/shader_program.cpp b/libopenage/renderer/opengl/shader_program.cpp index cf59be1edb..da24ac1596 100644 --- a/libopenage/renderer/opengl/shader_program.cpp +++ b/libopenage/renderer/opengl/shader_program.cpp @@ -179,7 +179,7 @@ GlShaderProgram::GlShaderProgram(const std::shared_ptr &context, block_binding})); } - GLuint tex_unit = 0; + GLuint tex_unit_id = 0; // Extract information about uniforms in the default block. @@ -204,26 +204,30 @@ GlShaderProgram::GlShaderProgram(const std::shared_ptr &context, GLuint loc = glGetUniformLocation(handle, name.data()); - this->uniforms.push_back({type, loc}); + this->uniforms.push_back({type, loc, std::nullopt}); this->uniforms_by_name.insert(std::make_pair( name.data(), unif_id)); if (type == GL_SAMPLER_2D) { - ENSURE(tex_unit < caps.max_texture_slots, + ENSURE(tex_unit_id < caps.max_texture_slots, "Tried to create an OpenGL shader that uses more texture sampler uniforms " << "than there are texture unit slots (" << caps.max_texture_slots << " available)."); - this->texunits_per_unifs.insert(std::make_pair(unif_id, tex_unit)); + this->uniforms[unif_id].tex_unit = tex_unit_id; - tex_unit += 1; + tex_unit_id += 1; } // Increment uniform ID unif_id += 1; } + // Resize the texture unit bindings + // to number of texture units used by the shader + this->textures_per_texunits.resize(tex_unit_id); + // Extract vertex attribute descriptions. for (GLuint i_attrib = 0; i_attrib < attrib_count; ++i_attrib) { GLint size; @@ -304,32 +308,39 @@ void GlShaderProgram::use() { std::static_pointer_cast( this->shared_from_this())); - for (auto const &pair : this->textures_per_texunits) { + for (size_t i = 0; i < this->textures_per_texunits.size(); ++i) { + auto &tex_unit = this->textures_per_texunits[i]; + if (not tex_unit) { + continue; + } + + if (not glIsTexture(*tex_unit)) { + // By the time we use the shader again, the texture may have been deleted + // but if it's fixed afterwards using update_uniforms, the render state + // will still be fine + // We can free the texture unit in this case + tex_unit = std::nullopt; + continue; + } + // We have to bind the texture to their texture units here because // the texture unit bindings are global to the context. Each time // the shader switches, it is possible that some other shader overwrote // these, and since we want the uniform values to persist across update_uniforms // calls, we have to set them more often than just on update_uniforms. - glActiveTexture(GL_TEXTURE0 + pair.first); - glBindTexture(GL_TEXTURE_2D, pair.second); - - // By the time we call bind, the texture may have been deleted, but if it's fixed - // afterwards using update_uniforms, the render state will still be fine, so we can ignore - // this error. - // TODO this will swallow actual errors elsewhere, and should be avoided. how? - // probably by holding the texture object as shared_ptr as long as it is bound - glGetError(); + glActiveTexture(GL_TEXTURE0 + i); + glBindTexture(GL_TEXTURE_2D, *tex_unit); } } bool GlShaderProgram::in_use() const { - return this->context->get_current_program().lock() == this->shared_from_this(); + return this->context->get_current_program().lock().get() == this; } void GlShaderProgram::update_uniforms(std::shared_ptr const &unif_in) { - ENSURE(unif_in->get_program() == this->shared_from_this(), "Uniform input passed to different shader than it was created with."); + ENSURE(unif_in->get_program().get() == this, "Uniform input passed to different shader than it was created with."); // TODO: use glProgramUniform when we're on OpenGL 4.1 // then we don't need to "use" and then call glUniform* @@ -338,10 +349,19 @@ void GlShaderProgram::update_uniforms(std::shared_ptr const &uni this->use(); } + const auto &update_offs = unif_in->update_offs; + const auto &used_uniforms = unif_in->used_uniforms; + const auto &uniforms = this->uniforms; uint8_t const *data = unif_in->update_data.data(); - for (auto const &pair : unif_in->update_offs) { - uint8_t const *ptr = data + pair.second; - const auto &unif = this->uniforms.at(pair.first); + + size_t unif_count = used_uniforms.size(); + for (size_t i = 0; i < unif_count; ++i) { + uniform_id_t unif_id = used_uniforms[i]; + + const auto &update_off = update_offs[unif_id]; + uint8_t const *ptr = data + update_off.offset; + + const auto &unif = uniforms[unif_id]; auto loc = unif.location; switch (unif.type) { @@ -395,13 +415,17 @@ void GlShaderProgram::update_uniforms(std::shared_ptr const &uni glUniformMatrix4fv(loc, 1, GLboolean(false), reinterpret_cast(ptr)); break; case GL_SAMPLER_2D: { - GLuint tex_unit = this->texunits_per_unifs.at(pair.first); + ENSURE(unif.tex_unit, + "Tried to access texture unit for uniform that has no texture unit assigned."); + GLuint tex_unit_id = *unif.tex_unit; + GLuint tex = *reinterpret_cast(ptr); - glActiveTexture(GL_TEXTURE0 + tex_unit); + glActiveTexture(GL_TEXTURE0 + tex_unit_id); glBindTexture(GL_TEXTURE_2D, tex); // TODO: maybe call this at a more appropriate position - glUniform1i(loc, tex_unit); - this->textures_per_texunits[tex_unit] = tex; + glUniform1i(loc, tex_unit_id); + auto &tex_value = *this->textures_per_texunits[tex_unit_id]; + tex_value = tex; break; } default: @@ -434,6 +458,14 @@ uniform_id_t GlShaderProgram::get_uniform_id(const char *name) { return this->uniforms_by_name.at(name); } +const std::vector &GlShaderProgram::get_uniforms() const { + return this->uniforms; +} + +const std::unordered_map &GlShaderProgram::get_uniform_blocks() const { + return this->uniform_blocks; +} + bool GlShaderProgram::has_uniform(const char *name) { return this->uniforms_by_name.contains(name); } @@ -455,202 +487,180 @@ void GlShaderProgram::bind_uniform_buffer(const char *block_name, std::shared_pt glUniformBlockBinding(*this->handle, block.index, block.binding_point); } -void GlShaderProgram::set_unif(std::shared_ptr const &in, +void GlShaderProgram::set_unif(UniformInput &in, const char *unif, void const *val, + size_t size, GLenum type) { - auto unif_in = std::dynamic_pointer_cast(in); - auto uniform_id = this->uniforms_by_name.find(unif); ENSURE(uniform_id != std::end(this->uniforms_by_name), "Tried to set uniform '" << unif << "' that does not exist in the shader program."); - auto const &unif_info = this->uniforms.at(uniform_id->second); - - ENSURE(type == unif_info.type, - "Tried to set uniform '" << unif << "' to a value of the wrong type."); - - size_t size = get_uniform_type_size(type); - - auto update_off = unif_in->update_offs.find(uniform_id->second); - if (update_off != std::end(unif_in->update_offs)) [[likely]] { // always used after the uniform value is written once - // already wrote to this uniform since last upload - size_t off = update_off->second; - memcpy(unif_in->update_data.data() + off, val, size); - } - else { - // first time writing to this uniform since last upload, so - // extend the buffer before storing the uniform value - size_t prev_size = unif_in->update_data.size(); - unif_in->update_data.resize(prev_size + size); - memcpy(unif_in->update_data.data() + prev_size, val, size); - unif_in->update_offs.emplace(uniform_id->second, prev_size); - } + this->set_unif(in, uniform_id->second, val, size, type); } -void GlShaderProgram::set_unif(std::shared_ptr const &in, - const uniform_id_t &unif_id, +void GlShaderProgram::set_unif(UniformInput &in, + uniform_id_t unif_id, void const *val, + size_t size, GLenum type) { - auto unif_in = std::dynamic_pointer_cast(in); + auto &unif_in = dynamic_cast(in); ENSURE(unif_id < this->uniforms.size(), "Tried to set uniform '" << unif_id << "' that does not exist in the shader program."); - auto const &unif_info = this->uniforms.at(unif_id); + ENSURE(unif_id < this->uniforms.size(), + "Tried to set uniform with invalid ID " << unif_id); + + auto const &unif_info = this->uniforms[unif_id]; ENSURE(type == unif_info.type, "Tried to set uniform '" << unif_id << "' to a value of the wrong type."); - size_t size = get_uniform_type_size(type); - - auto update_off = unif_in->update_offs.find(unif_id); - if (update_off != std::end(unif_in->update_offs)) [[likely]] { // always used after the uniform value is written once - // already wrote to this uniform since last upload - size_t off = update_off->second; - memcpy(unif_in->update_data.data() + off, val, size); - } - else { - // first time writing to this uniform since last upload, so - // extend the buffer before storing the uniform value - size_t prev_size = unif_in->update_data.size(); - unif_in->update_data.resize(prev_size + size); - memcpy(unif_in->update_data.data() + prev_size, val, size); - unif_in->update_offs.emplace(unif_id, prev_size); + auto &update_off = unif_in.update_offs[unif_id]; + auto offset = update_off.offset; + memcpy(unif_in.update_data.data() + offset, val, size); + if (not update_off.used) [[unlikely]] { // only true if the uniform value was not set before + auto lower_bound = std::lower_bound( + std::begin(unif_in.used_uniforms), + std::end(unif_in.used_uniforms), + unif_id); + unif_in.used_uniforms.insert(lower_bound, unif_id); + update_off.used = true; } } -void GlShaderProgram::set_i32(std::shared_ptr const &in, const char *unif, int32_t val) { - this->set_unif(in, unif, &val, GL_INT); +void GlShaderProgram::set_i32(UniformInput &in, const char *unif, int32_t val) { + this->set_unif(in, unif, &val, get_uniform_type_size(GL_INT), GL_INT); } -void GlShaderProgram::set_u32(std::shared_ptr const &in, const char *unif, uint32_t val) { - this->set_unif(in, unif, &val, GL_UNSIGNED_INT); +void GlShaderProgram::set_u32(UniformInput &in, const char *unif, uint32_t val) { + this->set_unif(in, unif, &val, get_uniform_type_size(GL_UNSIGNED_INT), GL_UNSIGNED_INT); } -void GlShaderProgram::set_f32(std::shared_ptr const &in, const char *unif, float val) { - this->set_unif(in, unif, &val, GL_FLOAT); +void GlShaderProgram::set_f32(UniformInput &in, const char *unif, float val) { + this->set_unif(in, unif, &val, get_uniform_type_size(GL_FLOAT), GL_FLOAT); } -void GlShaderProgram::set_f64(std::shared_ptr const &in, const char *unif, double val) { +void GlShaderProgram::set_f64(UniformInput &in, const char *unif, double val) { // TODO requires extension - this->set_unif(in, unif, &val, GL_DOUBLE); + this->set_unif(in, unif, &val, get_uniform_type_size(GL_DOUBLE), GL_DOUBLE); } -void GlShaderProgram::set_bool(std::shared_ptr const &in, const char *unif, bool val) { - this->set_unif(in, unif, &val, GL_BOOL); +void GlShaderProgram::set_bool(UniformInput &in, const char *unif, bool val) { + this->set_unif(in, unif, &val, get_uniform_type_size(GL_BOOL), GL_BOOL); } -void GlShaderProgram::set_v2f32(std::shared_ptr const &in, const char *unif, Eigen::Vector2f const &val) { - this->set_unif(in, unif, &val, GL_FLOAT_VEC2); +void GlShaderProgram::set_v2f32(UniformInput &in, const char *unif, Eigen::Vector2f const &val) { + this->set_unif(in, unif, &val, get_uniform_type_size(GL_FLOAT_VEC2), GL_FLOAT_VEC2); } -void GlShaderProgram::set_v3f32(std::shared_ptr const &in, const char *unif, Eigen::Vector3f const &val) { - this->set_unif(in, unif, &val, GL_FLOAT_VEC3); +void GlShaderProgram::set_v3f32(UniformInput &in, const char *unif, Eigen::Vector3f const &val) { + this->set_unif(in, unif, &val, get_uniform_type_size(GL_FLOAT_VEC3), GL_FLOAT_VEC3); } -void GlShaderProgram::set_v4f32(std::shared_ptr const &in, const char *unif, Eigen::Vector4f const &val) { - this->set_unif(in, unif, &val, GL_FLOAT_VEC4); +void GlShaderProgram::set_v4f32(UniformInput &in, const char *unif, Eigen::Vector4f const &val) { + this->set_unif(in, unif, &val, get_uniform_type_size(GL_FLOAT_VEC4), GL_FLOAT_VEC4); } -void GlShaderProgram::set_v2i32(std::shared_ptr const &in, const char *unif, Eigen::Vector2i const &val) { - this->set_unif(in, unif, &val, GL_INT_VEC2); +void GlShaderProgram::set_v2i32(UniformInput &in, const char *unif, Eigen::Vector2i const &val) { + this->set_unif(in, unif, &val, get_uniform_type_size(GL_INT_VEC2), GL_INT_VEC2); } -void GlShaderProgram::set_v3i32(std::shared_ptr const &in, const char *unif, Eigen::Vector3i const &val) { - this->set_unif(in, unif, &val, GL_INT_VEC3); +void GlShaderProgram::set_v3i32(UniformInput &in, const char *unif, Eigen::Vector3i const &val) { + this->set_unif(in, unif, &val, get_uniform_type_size(GL_INT_VEC3), GL_INT_VEC3); } -void GlShaderProgram::set_v4i32(std::shared_ptr const &in, const char *unif, Eigen::Vector4i const &val) { - this->set_unif(in, unif, &val, GL_INT_VEC4); +void GlShaderProgram::set_v4i32(UniformInput &in, const char *unif, Eigen::Vector4i const &val) { + this->set_unif(in, unif, &val, get_uniform_type_size(GL_INT_VEC4), GL_INT_VEC4); } -void GlShaderProgram::set_v2ui32(std::shared_ptr const &in, const char *unif, Eigen::Vector2 const &val) { - this->set_unif(in, unif, &val, GL_UNSIGNED_INT_VEC2); +void GlShaderProgram::set_v2ui32(UniformInput &in, const char *unif, Eigen::Vector2 const &val) { + this->set_unif(in, unif, &val, get_uniform_type_size(GL_UNSIGNED_INT_VEC2), GL_UNSIGNED_INT_VEC2); } -void GlShaderProgram::set_v3ui32(std::shared_ptr const &in, const char *unif, Eigen::Vector3 const &val) { - this->set_unif(in, unif, &val, GL_UNSIGNED_INT_VEC3); +void GlShaderProgram::set_v3ui32(UniformInput &in, const char *unif, Eigen::Vector3 const &val) { + this->set_unif(in, unif, &val, get_uniform_type_size(GL_UNSIGNED_INT_VEC3), GL_UNSIGNED_INT_VEC3); } -void GlShaderProgram::set_v4ui32(std::shared_ptr const &in, const char *unif, Eigen::Vector4 const &val) { - this->set_unif(in, unif, &val, GL_UNSIGNED_INT_VEC4); +void GlShaderProgram::set_v4ui32(UniformInput &in, const char *unif, Eigen::Vector4 const &val) { + this->set_unif(in, unif, &val, get_uniform_type_size(GL_UNSIGNED_INT_VEC4), GL_UNSIGNED_INT_VEC4); } -void GlShaderProgram::set_m4f32(std::shared_ptr const &in, const char *unif, Eigen::Matrix4f const &val) { - this->set_unif(in, unif, val.data(), GL_FLOAT_MAT4); +void GlShaderProgram::set_m4f32(UniformInput &in, const char *unif, Eigen::Matrix4f const &val) { + this->set_unif(in, unif, val.data(), get_uniform_type_size(GL_FLOAT_MAT4), GL_FLOAT_MAT4); } -void GlShaderProgram::set_tex(std::shared_ptr const &in, const char *unif, std::shared_ptr const &val) { +void GlShaderProgram::set_tex(UniformInput &in, const char *unif, std::shared_ptr const &val) { auto tex = std::dynamic_pointer_cast(val); GLuint handle = tex->get_handle(); - this->set_unif(in, unif, &handle, GL_SAMPLER_2D); + this->set_unif(in, unif, &handle, get_uniform_type_size(GL_SAMPLER_2D), GL_SAMPLER_2D); } -void GlShaderProgram::set_i32(std::shared_ptr const &in, const uniform_id_t &id, int32_t val) { - this->set_unif(in, id, &val, GL_INT); +void GlShaderProgram::set_i32(UniformInput &in, uniform_id_t id, int32_t val) { + this->set_unif(in, id, &val, get_uniform_type_size(GL_INT), GL_INT); } -void GlShaderProgram::set_u32(std::shared_ptr const &in, const uniform_id_t &id, uint32_t val) { - this->set_unif(in, id, &val, GL_UNSIGNED_INT); +void GlShaderProgram::set_u32(UniformInput &in, uniform_id_t id, uint32_t val) { + this->set_unif(in, id, &val, get_uniform_type_size(GL_UNSIGNED_INT), GL_UNSIGNED_INT); } -void GlShaderProgram::set_f32(std::shared_ptr const &in, const uniform_id_t &id, float val) { - this->set_unif(in, id, &val, GL_FLOAT); +void GlShaderProgram::set_f32(UniformInput &in, uniform_id_t id, float val) { + this->set_unif(in, id, &val, get_uniform_type_size(GL_FLOAT), GL_FLOAT); } -void GlShaderProgram::set_f64(std::shared_ptr const &in, const uniform_id_t &id, double val) { +void GlShaderProgram::set_f64(UniformInput &in, uniform_id_t id, double val) { // TODO requires extension - this->set_unif(in, id, &val, GL_DOUBLE); + this->set_unif(in, id, &val, get_uniform_type_size(GL_DOUBLE), GL_DOUBLE); } -void GlShaderProgram::set_bool(std::shared_ptr const &in, const uniform_id_t &id, bool val) { - this->set_unif(in, id, &val, GL_BOOL); +void GlShaderProgram::set_bool(UniformInput &in, uniform_id_t id, bool val) { + this->set_unif(in, id, &val, get_uniform_type_size(GL_BOOL), GL_BOOL); } -void GlShaderProgram::set_v2f32(std::shared_ptr const &in, const uniform_id_t &id, Eigen::Vector2f const &val) { - this->set_unif(in, id, &val, GL_FLOAT_VEC2); +void GlShaderProgram::set_v2f32(UniformInput &in, uniform_id_t id, Eigen::Vector2f const &val) { + this->set_unif(in, id, &val, get_uniform_type_size(GL_FLOAT_VEC2), GL_FLOAT_VEC2); } -void GlShaderProgram::set_v3f32(std::shared_ptr const &in, const uniform_id_t &id, Eigen::Vector3f const &val) { - this->set_unif(in, id, &val, GL_FLOAT_VEC3); +void GlShaderProgram::set_v3f32(UniformInput &in, uniform_id_t id, Eigen::Vector3f const &val) { + this->set_unif(in, id, &val, get_uniform_type_size(GL_FLOAT_VEC3), GL_FLOAT_VEC3); } -void GlShaderProgram::set_v4f32(std::shared_ptr const &in, const uniform_id_t &id, Eigen::Vector4f const &val) { - this->set_unif(in, id, &val, GL_FLOAT_VEC4); +void GlShaderProgram::set_v4f32(UniformInput &in, uniform_id_t id, Eigen::Vector4f const &val) { + this->set_unif(in, id, &val, get_uniform_type_size(GL_FLOAT_VEC4), GL_FLOAT_VEC4); } -void GlShaderProgram::set_v2i32(std::shared_ptr const &in, const uniform_id_t &id, Eigen::Vector2i const &val) { - this->set_unif(in, id, &val, GL_INT_VEC2); +void GlShaderProgram::set_v2i32(UniformInput &in, uniform_id_t id, Eigen::Vector2i const &val) { + this->set_unif(in, id, &val, get_uniform_type_size(GL_INT_VEC2), GL_INT_VEC2); } -void GlShaderProgram::set_v3i32(std::shared_ptr const &in, const uniform_id_t &id, Eigen::Vector3i const &val) { - this->set_unif(in, id, &val, GL_INT_VEC3); +void GlShaderProgram::set_v3i32(UniformInput &in, uniform_id_t id, Eigen::Vector3i const &val) { + this->set_unif(in, id, &val, get_uniform_type_size(GL_INT_VEC3), GL_INT_VEC3); } -void GlShaderProgram::set_v4i32(std::shared_ptr const &in, const uniform_id_t &id, Eigen::Vector4i const &val) { - this->set_unif(in, id, &val, GL_INT_VEC4); +void GlShaderProgram::set_v4i32(UniformInput &in, uniform_id_t id, Eigen::Vector4i const &val) { + this->set_unif(in, id, &val, get_uniform_type_size(GL_INT_VEC4), GL_INT_VEC4); } -void GlShaderProgram::set_v2ui32(std::shared_ptr const &in, const uniform_id_t &id, Eigen::Vector2 const &val) { - this->set_unif(in, id, &val, GL_UNSIGNED_INT_VEC2); +void GlShaderProgram::set_v2ui32(UniformInput &in, uniform_id_t id, Eigen::Vector2 const &val) { + this->set_unif(in, id, &val, get_uniform_type_size(GL_UNSIGNED_INT_VEC2), GL_UNSIGNED_INT_VEC2); } -void GlShaderProgram::set_v3ui32(std::shared_ptr const &in, const uniform_id_t &id, Eigen::Vector3 const &val) { - this->set_unif(in, id, &val, GL_UNSIGNED_INT_VEC3); +void GlShaderProgram::set_v3ui32(UniformInput &in, uniform_id_t id, Eigen::Vector3 const &val) { + this->set_unif(in, id, &val, get_uniform_type_size(GL_UNSIGNED_INT_VEC3), GL_UNSIGNED_INT_VEC3); } -void GlShaderProgram::set_v4ui32(std::shared_ptr const &in, const uniform_id_t &id, Eigen::Vector4 const &val) { - this->set_unif(in, id, &val, GL_UNSIGNED_INT_VEC4); +void GlShaderProgram::set_v4ui32(UniformInput &in, uniform_id_t id, Eigen::Vector4 const &val) { + this->set_unif(in, id, &val, get_uniform_type_size(GL_UNSIGNED_INT_VEC4), GL_UNSIGNED_INT_VEC4); } -void GlShaderProgram::set_m4f32(std::shared_ptr const &in, const uniform_id_t &id, Eigen::Matrix4f const &val) { - this->set_unif(in, id, val.data(), GL_FLOAT_MAT4); +void GlShaderProgram::set_m4f32(UniformInput &in, uniform_id_t id, Eigen::Matrix4f const &val) { + this->set_unif(in, id, val.data(), get_uniform_type_size(GL_FLOAT_MAT4), GL_FLOAT_MAT4); } -void GlShaderProgram::set_tex(std::shared_ptr const &in, const uniform_id_t &id, std::shared_ptr const &val) { +void GlShaderProgram::set_tex(UniformInput &in, uniform_id_t id, std::shared_ptr const &val) { auto tex = std::dynamic_pointer_cast(val); GLuint handle = tex->get_handle(); - this->set_unif(in, id, &handle, GL_SAMPLER_2D); + this->set_unif(in, id, &handle, get_uniform_type_size(GL_SAMPLER_2D), GL_SAMPLER_2D); } } // namespace openage::renderer::opengl diff --git a/libopenage/renderer/opengl/shader_program.h b/libopenage/renderer/opengl/shader_program.h index a49c8214a9..5d31f2a071 100644 --- a/libopenage/renderer/opengl/shader_program.h +++ b/libopenage/renderer/opengl/shader_program.h @@ -64,8 +64,37 @@ class GlShaderProgram final : public ShaderProgram */ const GlUniformBlock &get_uniform_block(const char *block_name) const; + /** + * Get the uniform ID for the given uniform name. + * + * @param name Name of the uniform in the shader code. + * + * @return ID of the uniform. + */ uniform_id_t get_uniform_id(const char *name) override; + /** + * Get the uniforms in the default block of the shader program. + * This does not include uniforms in blocks. + * + * @return Uniforms in the shader program. + */ + const std::vector &get_uniforms() const; + + /** + * Get the map of uniform blocks in the shader program. + * + * @return Uniform blocks in the shader program. + */ + const std::unordered_map &get_uniform_blocks() const; + + /** + * Check whether the shader program contains a uniform variable with the given name. + * + * @param name Name of the uniform in the shader code. + * + * @return true if the shader program contains the uniform, false otherwise. + */ bool has_uniform(const char *name) override; /** @@ -82,39 +111,39 @@ class GlShaderProgram final : public ShaderProgram protected: std::shared_ptr new_unif_in() override; - void set_i32(std::shared_ptr const &, const char *, int32_t) override; - void set_u32(std::shared_ptr const &, const char *, uint32_t) override; - void set_f32(std::shared_ptr const &, const char *, float) override; - void set_f64(std::shared_ptr const &, const char *, double) override; - void set_bool(std::shared_ptr const &, const char *, bool) override; - void set_v2f32(std::shared_ptr const &, const char *, Eigen::Vector2f const &) override; - void set_v3f32(std::shared_ptr const &, const char *, Eigen::Vector3f const &) override; - void set_v4f32(std::shared_ptr const &, const char *, Eigen::Vector4f const &) override; - void set_v2i32(std::shared_ptr const &, const char *, Eigen::Vector2i const &) override; - void set_v3i32(std::shared_ptr const &, const char *, Eigen::Vector3i const &) override; - void set_v4i32(std::shared_ptr const &, const char *, Eigen::Vector4i const &) override; - void set_v2ui32(std::shared_ptr const &, const char *, Eigen::Vector2 const &) override; - void set_v3ui32(std::shared_ptr const &, const char *, Eigen::Vector3 const &) override; - void set_v4ui32(std::shared_ptr const &, const char *, Eigen::Vector4 const &) override; - void set_m4f32(std::shared_ptr const &, const char *, Eigen::Matrix4f const &) override; - void set_tex(std::shared_ptr const &, const char *, std::shared_ptr const &) override; - - void set_i32(std::shared_ptr const &, const uniform_id_t &, int32_t) override; - void set_u32(std::shared_ptr const &, const uniform_id_t &, uint32_t) override; - void set_f32(std::shared_ptr const &, const uniform_id_t &, float) override; - void set_f64(std::shared_ptr const &, const uniform_id_t &, double) override; - void set_bool(std::shared_ptr const &, const uniform_id_t &, bool) override; - void set_v2f32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector2f const &) override; - void set_v3f32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector3f const &) override; - void set_v4f32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector4f const &) override; - void set_v2i32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector2i const &) override; - void set_v3i32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector3i const &) override; - void set_v4i32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector4i const &) override; - void set_v2ui32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector2 const &) override; - void set_v3ui32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector3 const &) override; - void set_v4ui32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector4 const &) override; - void set_m4f32(std::shared_ptr const &, const uniform_id_t &, Eigen::Matrix4f const &) override; - void set_tex(std::shared_ptr const &, const uniform_id_t &, std::shared_ptr const &) override; + void set_i32(UniformInput &in, const char *, int32_t) override; + void set_u32(UniformInput &in, const char *, uint32_t) override; + void set_f32(UniformInput &in, const char *, float) override; + void set_f64(UniformInput &in, const char *, double) override; + void set_bool(UniformInput &in, const char *, bool) override; + void set_v2f32(UniformInput &in, const char *, Eigen::Vector2f const &) override; + void set_v3f32(UniformInput &in, const char *, Eigen::Vector3f const &) override; + void set_v4f32(UniformInput &in, const char *, Eigen::Vector4f const &) override; + void set_v2i32(UniformInput &in, const char *, Eigen::Vector2i const &) override; + void set_v3i32(UniformInput &in, const char *, Eigen::Vector3i const &) override; + void set_v4i32(UniformInput &in, const char *, Eigen::Vector4i const &) override; + void set_v2ui32(UniformInput &in, const char *, Eigen::Vector2 const &) override; + void set_v3ui32(UniformInput &in, const char *, Eigen::Vector3 const &) override; + void set_v4ui32(UniformInput &in, const char *, Eigen::Vector4 const &) override; + void set_m4f32(UniformInput &in, const char *, Eigen::Matrix4f const &) override; + void set_tex(UniformInput &in, const char *, std::shared_ptr const &) override; + + void set_i32(UniformInput &in, uniform_id_t id, int32_t) override; + void set_u32(UniformInput &in, uniform_id_t id, uint32_t) override; + void set_f32(UniformInput &in, uniform_id_t id, float) override; + void set_f64(UniformInput &in, uniform_id_t id, double) override; + void set_bool(UniformInput &in, uniform_id_t id, bool) override; + void set_v2f32(UniformInput &in, uniform_id_t id, Eigen::Vector2f const &) override; + void set_v3f32(UniformInput &in, uniform_id_t id, Eigen::Vector3f const &) override; + void set_v4f32(UniformInput &in, uniform_id_t id, Eigen::Vector4f const &) override; + void set_v2i32(UniformInput &in, uniform_id_t id, Eigen::Vector2i const &) override; + void set_v3i32(UniformInput &in, uniform_id_t id, Eigen::Vector3i const &) override; + void set_v4i32(UniformInput &in, uniform_id_t id, Eigen::Vector4i const &) override; + void set_v2ui32(UniformInput &in, uniform_id_t id, Eigen::Vector2 const &) override; + void set_v3ui32(UniformInput &in, uniform_id_t id, Eigen::Vector3 const &) override; + void set_v4ui32(UniformInput &in, uniform_id_t id, Eigen::Vector4 const &) override; + void set_m4f32(UniformInput &in, uniform_id_t id, Eigen::Matrix4f const &) override; + void set_tex(UniformInput &in, uniform_id_t id, std::shared_ptr const &) override; private: /** @@ -125,22 +154,32 @@ class GlShaderProgram final : public ShaderProgram * If performance is important, use the alternative \p set_unif(..) implementation * that works on IDs instead. * - * @param unif_in Uniform input. + * @param in Uniform input. * @param name Name of the uniform. * @param value Value to set. + * @param size Size of the value (in bytes). * @param type Type of the value. */ - void set_unif(std::shared_ptr const &, const char *, void const *, GLenum); + void set_unif(UniformInput &in, + const char *name, + void const *value, + size_t size, + GLenum type); /** * Set the uniform value via uniform ID from a uniform input. * - * @param unif_in Uniform input. - * @param id ID of the uniform. + * @param in Uniform input. + * @param unif_id ID of the uniform. * @param value Value to set. + * @param size Size of the value (in bytes). * @param type Type of the value. */ - void set_unif(std::shared_ptr const &, const uniform_id_t &, void const *, GLenum); + void set_unif(UniformInput &in, + uniform_id_t unif_id, + void const *value, + size_t size, + GLenum type); /// Uniforms in the shader program. Contains only /// uniforms in the default block, i.e. not within named blocks. @@ -155,11 +194,8 @@ class GlShaderProgram final : public ShaderProgram /// Maps per-vertex attribute names to their descriptions. std::unordered_map attribs; - /// Maps sampler uniform names to their assigned texture units. - std::unordered_map texunits_per_unifs; - - /// Maps texture units to the texture handles that are currently bound to them. - std::unordered_map textures_per_texunits; + /// Store which texture handles are currently bound to the shader's texture units. + std::vector> textures_per_texunits; /// Whether this program has been validated. bool validated; diff --git a/libopenage/renderer/opengl/uniform_buffer.cpp b/libopenage/renderer/opengl/uniform_buffer.cpp index b84b17e6e1..661f9e3173 100644 --- a/libopenage/renderer/opengl/uniform_buffer.cpp +++ b/libopenage/renderer/opengl/uniform_buffer.cpp @@ -92,7 +92,9 @@ void GlUniformBuffer::set_unif(std::shared_ptr const &in, co ENSURE(type == unif_data.type, "Tried to set uniform " << unif << " to a value of the wrong type."); - size_t size = get_uniform_type_size(type); + size_t size = GL_UNIFORM_TYPE_SIZE.get(type); + ENSURE(size == unif_data.size, + "Tried to set uniform " << unif << " to a value of the wrong size."); auto update_off = unif_in->update_offs.find(unif); if (update_off != std::end(unif_in->update_offs)) [[likely]] { // always used after the uniform value is written once diff --git a/libopenage/renderer/opengl/uniform_input.cpp b/libopenage/renderer/opengl/uniform_input.cpp index d8c7eeaba8..111b33b879 100644 --- a/libopenage/renderer/opengl/uniform_input.cpp +++ b/libopenage/renderer/opengl/uniform_input.cpp @@ -1,11 +1,32 @@ -// Copyright 2019-2023 the openage authors. See copying.md for legal info. +// Copyright 2019-2024 the openage authors. See copying.md for legal info. #include "uniform_input.h" +#include "renderer/opengl/lookup.h" +#include "renderer/opengl/shader_program.h" +#include "renderer/opengl/util.h" + + namespace openage::renderer::opengl { -GlUniformInput::GlUniformInput(std::shared_ptr const &prog) : - UniformInput{prog} {} +GlUniformInput::GlUniformInput(const std::shared_ptr &prog) : + UniformInput{prog} { + auto glprog = std::dynamic_pointer_cast(prog); + + // Reserve space for the used uniforms. + this->used_uniforms.reserve(glprog->get_uniforms().size()); + + // Calculate the byte-wise offsets of all uniforms. + size_t offset = 0; + this->update_offs.reserve(glprog->get_uniforms().size()); + for (auto &uniform : glprog->get_uniforms()) { + this->update_offs.push_back({offset, false}); + offset += GL_UNIFORM_TYPE_SIZE.get(uniform.type); + } + + // Resize the update data buffer to the total size of all uniforms. + this->update_data.resize(offset); +} GlUniformBufferInput::GlUniformBufferInput(std::shared_ptr const &buffer) : UniformBufferInput{buffer} {} diff --git a/libopenage/renderer/opengl/uniform_input.h b/libopenage/renderer/opengl/uniform_input.h index 1bb54f3cd4..8ca3ff02dd 100644 --- a/libopenage/renderer/opengl/uniform_input.h +++ b/libopenage/renderer/opengl/uniform_input.h @@ -23,18 +23,29 @@ class GlShaderProgram; * Describes OpenGL-specific uniform valuations. */ class GlUniformInput final : public UniformInput { +private: + struct GlUniformOffset { + // Offset in the update_data buffer. + size_t offset; + /// Dtermine whether the uniform value has been set. + bool used; + }; + public: - GlUniformInput(std::shared_ptr const &); + GlUniformInput(const std::shared_ptr &prog); /** - * We store uniform updates lazily. They are only actually uploaded to GPU - * when a draw call is made. + * Store the IDs of the uniforms from the shader set by this uniform input. + */ + std::vector used_uniforms; + + /** + * Store offsets of uniforms in the update_data buffer and + * whether the uniform value has been set. * - * \p update_offs maps the uniform IDs to where their - * value is in \p update_data in terms of a byte-wise offset. This is only a partial - * valuation, so not all uniforms have to be present here. + * Index in the vector corresponds to the uniform ID in the shader. */ - std::unordered_map update_offs; + std::vector update_offs; /** * Buffer containing untyped uniform update data. diff --git a/libopenage/renderer/opengl/util.cpp b/libopenage/renderer/opengl/util.cpp index 7a8a6e2f91..81185b6d97 100644 --- a/libopenage/renderer/opengl/util.cpp +++ b/libopenage/renderer/opengl/util.cpp @@ -1,68 +1,7 @@ -// Copyright 2023-2023 the openage authors. See copying.md for legal info. +// Copyright 2023-2024 the openage authors. See copying.md for legal info. #include "util.h" -#include "error/error.h" - - namespace openage::renderer::opengl { -size_t get_uniform_type_size(GLenum type) { - switch (type) { - case GL_BOOL: - return 1; - break; - case GL_BOOL_VEC2: - return 2; - break; - case GL_BOOL_VEC3: - return 3; - break; - case GL_BOOL_VEC4: - case GL_FLOAT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_SAMPLER_1D: - case GL_SAMPLER_2D: - case GL_SAMPLER_2D_ARRAY: - case GL_SAMPLER_3D: - case GL_SAMPLER_CUBE: - return 4; - break; - - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - case GL_UNSIGNED_INT_VEC2: - return 8; - break; - - case GL_FLOAT_VEC3: - case GL_INT_VEC3: - case GL_UNSIGNED_INT_VEC3: - return 12; - break; - - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - case GL_UNSIGNED_INT_VEC4: - case GL_FLOAT_MAT2: - return 16; - break; - - case GL_FLOAT_MAT3: - return 36; - break; - - case GL_FLOAT_MAT4: - return 64; - break; - - default: - throw Error(MSG(err) << "Unknown GL uniform type: " << type); - break; - } - - return 0; -} - } // namespace openage::renderer::opengl diff --git a/libopenage/renderer/opengl/util.h b/libopenage/renderer/opengl/util.h index 3ad5b4626e..5ed01ed43c 100644 --- a/libopenage/renderer/opengl/util.h +++ b/libopenage/renderer/opengl/util.h @@ -1,4 +1,4 @@ -// Copyright 2023-2023 the openage authors. See copying.md for legal info. +// Copyright 2023-2024 the openage authors. See copying.md for legal info. #pragma once @@ -6,16 +6,22 @@ #include +#include "renderer/opengl/lookup.h" + namespace openage::renderer::opengl { /** * Get the sizes of a uniform value with a given uniform type. * + * Guaranteed to be a evaluated at compile time. + * * @param type Uniform type. * * @return Size of uniform value (in bytes). */ -size_t get_uniform_type_size(GLenum type); +consteval size_t get_uniform_type_size(GLenum type) { + return GL_UNIFORM_TYPE_SIZE.get(type); +} } // namespace openage::renderer::opengl diff --git a/libopenage/renderer/shader_program.h b/libopenage/renderer/shader_program.h index beb365b2a4..a0d27dc5b0 100644 --- a/libopenage/renderer/shader_program.h +++ b/libopenage/renderer/shader_program.h @@ -94,39 +94,39 @@ class ShaderProgram : public std::enable_shared_from_this { /** * Set a uniform input variable in the actual shader program. */ - virtual void set_i32(std::shared_ptr const &, const char *, int32_t) = 0; - virtual void set_u32(std::shared_ptr const &, const char *, uint32_t) = 0; - virtual void set_f32(std::shared_ptr const &, const char *, float) = 0; - virtual void set_f64(std::shared_ptr const &, const char *, double) = 0; - virtual void set_bool(std::shared_ptr const &, const char *, bool) = 0; - virtual void set_v2f32(std::shared_ptr const &, const char *, Eigen::Vector2f const &) = 0; - virtual void set_v3f32(std::shared_ptr const &, const char *, Eigen::Vector3f const &) = 0; - virtual void set_v4f32(std::shared_ptr const &, const char *, Eigen::Vector4f const &) = 0; - virtual void set_v2i32(std::shared_ptr const &, const char *, Eigen::Vector2i const &) = 0; - virtual void set_v3i32(std::shared_ptr const &, const char *, Eigen::Vector3i const &) = 0; - virtual void set_v4i32(std::shared_ptr const &, const char *, Eigen::Vector4i const &) = 0; - virtual void set_v2ui32(std::shared_ptr const &, const char *, Eigen::Vector2 const &) = 0; - virtual void set_v3ui32(std::shared_ptr const &, const char *, Eigen::Vector3 const &) = 0; - virtual void set_v4ui32(std::shared_ptr const &, const char *, Eigen::Vector4 const &) = 0; - virtual void set_m4f32(std::shared_ptr const &, const char *, Eigen::Matrix4f const &) = 0; - virtual void set_tex(std::shared_ptr const &, const char *, std::shared_ptr const &) = 0; - - virtual void set_i32(std::shared_ptr const &, const uniform_id_t &, int32_t) = 0; - virtual void set_u32(std::shared_ptr const &, const uniform_id_t &, uint32_t) = 0; - virtual void set_f32(std::shared_ptr const &, const uniform_id_t &, float) = 0; - virtual void set_f64(std::shared_ptr const &, const uniform_id_t &, double) = 0; - virtual void set_bool(std::shared_ptr const &, const uniform_id_t &, bool) = 0; - virtual void set_v2f32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector2f const &) = 0; - virtual void set_v3f32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector3f const &) = 0; - virtual void set_v4f32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector4f const &) = 0; - virtual void set_v2i32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector2i const &) = 0; - virtual void set_v3i32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector3i const &) = 0; - virtual void set_v4i32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector4i const &) = 0; - virtual void set_v2ui32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector2 const &) = 0; - virtual void set_v3ui32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector3 const &) = 0; - virtual void set_v4ui32(std::shared_ptr const &, const uniform_id_t &, Eigen::Vector4 const &) = 0; - virtual void set_m4f32(std::shared_ptr const &, const uniform_id_t &, Eigen::Matrix4f const &) = 0; - virtual void set_tex(std::shared_ptr const &, const uniform_id_t &, std::shared_ptr const &) = 0; + virtual void set_i32(UniformInput &in, const char *, int32_t) = 0; + virtual void set_u32(UniformInput &in, const char *, uint32_t) = 0; + virtual void set_f32(UniformInput &in, const char *, float) = 0; + virtual void set_f64(UniformInput &in, const char *, double) = 0; + virtual void set_bool(UniformInput &in, const char *, bool) = 0; + virtual void set_v2f32(UniformInput &in, const char *, Eigen::Vector2f const &) = 0; + virtual void set_v3f32(UniformInput &in, const char *, Eigen::Vector3f const &) = 0; + virtual void set_v4f32(UniformInput &in, const char *, Eigen::Vector4f const &) = 0; + virtual void set_v2i32(UniformInput &in, const char *, Eigen::Vector2i const &) = 0; + virtual void set_v3i32(UniformInput &in, const char *, Eigen::Vector3i const &) = 0; + virtual void set_v4i32(UniformInput &in, const char *, Eigen::Vector4i const &) = 0; + virtual void set_v2ui32(UniformInput &in, const char *, Eigen::Vector2 const &) = 0; + virtual void set_v3ui32(UniformInput &in, const char *, Eigen::Vector3 const &) = 0; + virtual void set_v4ui32(UniformInput &in, const char *, Eigen::Vector4 const &) = 0; + virtual void set_m4f32(UniformInput &in, const char *, Eigen::Matrix4f const &) = 0; + virtual void set_tex(UniformInput &in, const char *, std::shared_ptr const &) = 0; + + virtual void set_i32(UniformInput &in, uniform_id_t id, int32_t) = 0; + virtual void set_u32(UniformInput &in, uniform_id_t id, uint32_t) = 0; + virtual void set_f32(UniformInput &in, uniform_id_t id, float) = 0; + virtual void set_f64(UniformInput &in, uniform_id_t id, double) = 0; + virtual void set_bool(UniformInput &in, uniform_id_t id, bool) = 0; + virtual void set_v2f32(UniformInput &in, uniform_id_t id, Eigen::Vector2f const &) = 0; + virtual void set_v3f32(UniformInput &in, uniform_id_t id, Eigen::Vector3f const &) = 0; + virtual void set_v4f32(UniformInput &in, uniform_id_t id, Eigen::Vector4f const &) = 0; + virtual void set_v2i32(UniformInput &in, uniform_id_t id, Eigen::Vector2i const &) = 0; + virtual void set_v3i32(UniformInput &in, uniform_id_t id, Eigen::Vector3i const &) = 0; + virtual void set_v4i32(UniformInput &in, uniform_id_t id, Eigen::Vector4i const &) = 0; + virtual void set_v2ui32(UniformInput &in, uniform_id_t id, Eigen::Vector2 const &) = 0; + virtual void set_v3ui32(UniformInput &in, uniform_id_t id, Eigen::Vector3 const &) = 0; + virtual void set_v4ui32(UniformInput &in, uniform_id_t id, Eigen::Vector4 const &) = 0; + virtual void set_m4f32(UniformInput &in, uniform_id_t id, Eigen::Matrix4f const &) = 0; + virtual void set_tex(UniformInput &in, uniform_id_t id, std::shared_ptr const &) = 0; }; } // namespace renderer diff --git a/libopenage/renderer/uniform_input.cpp b/libopenage/renderer/uniform_input.cpp index 8ad865ca04..ee42202faf 100644 --- a/libopenage/renderer/uniform_input.cpp +++ b/libopenage/renderer/uniform_input.cpp @@ -1,4 +1,4 @@ -// Copyright 2019-2023 the openage authors. See copying.md for legal info. +// Copyright 2019-2024 the openage authors. See copying.md for legal info. #include "uniform_input.h" @@ -14,140 +14,140 @@ UniformInput::UniformInput(std::shared_ptr const &prog) : void UniformInput::update() {} void UniformInput::update(const char *unif, int32_t val) { - this->program->set_i32(this->shared_from_this(), unif, val); + this->program->set_i32(*this, unif, val); } void UniformInput::update(const char *unif, uint32_t val) { - this->program->set_u32(this->shared_from_this(), unif, val); + this->program->set_u32(*this, unif, val); } void UniformInput::update(const char *unif, float val) { - this->program->set_f32(this->shared_from_this(), unif, val); + this->program->set_f32(*this, unif, val); } void UniformInput::update(const char *unif, double val) { - this->program->set_f64(this->shared_from_this(), unif, val); + this->program->set_f64(*this, unif, val); } void UniformInput::update(const char *unif, bool val) { - this->program->set_bool(this->shared_from_this(), unif, val); + this->program->set_bool(*this, unif, val); } void UniformInput::update(const char *unif, Eigen::Vector2f const &val) { - this->program->set_v2f32(this->shared_from_this(), unif, val); + this->program->set_v2f32(*this, unif, val); } void UniformInput::update(const char *unif, Eigen::Vector3f const &val) { - this->program->set_v3f32(this->shared_from_this(), unif, val); + this->program->set_v3f32(*this, unif, val); } void UniformInput::update(const char *unif, Eigen::Vector4f const &val) { - this->program->set_v4f32(this->shared_from_this(), unif, val); + this->program->set_v4f32(*this, unif, val); } void UniformInput::update(const char *unif, Eigen::Vector2i const &val) { - this->program->set_v2i32(this->shared_from_this(), unif, val); + this->program->set_v2i32(*this, unif, val); } void UniformInput::update(const char *unif, Eigen::Vector3i const &val) { - this->program->set_v3i32(this->shared_from_this(), unif, val); + this->program->set_v3i32(*this, unif, val); } void UniformInput::update(const char *unif, Eigen::Vector4i const &val) { - this->program->set_v4i32(this->shared_from_this(), unif, val); + this->program->set_v4i32(*this, unif, val); } void UniformInput::update(const char *unif, Eigen::Vector2 const &val) { - this->program->set_v2ui32(this->shared_from_this(), unif, val); + this->program->set_v2ui32(*this, unif, val); } void UniformInput::update(const char *unif, Eigen::Vector3 const &val) { - this->program->set_v3ui32(this->shared_from_this(), unif, val); + this->program->set_v3ui32(*this, unif, val); } void UniformInput::update(const char *unif, Eigen::Vector4 const &val) { - this->program->set_v4ui32(this->shared_from_this(), unif, val); + this->program->set_v4ui32(*this, unif, val); } void UniformInput::update(const char *unif, std::shared_ptr const &val) { - this->program->set_tex(this->shared_from_this(), unif, val); + this->program->set_tex(*this, unif, val); } void UniformInput::update(const char *unif, std::shared_ptr &val) { - this->program->set_tex(this->shared_from_this(), unif, val); + this->program->set_tex(*this, unif, val); } void UniformInput::update(const char *unif, Eigen::Matrix4f const &val) { - this->program->set_m4f32(this->shared_from_this(), unif, val); + this->program->set_m4f32(*this, unif, val); } -void UniformInput::update(const uniform_id_t &id, int32_t val) { - this->program->set_i32(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, int32_t val) { + this->program->set_i32(*this, id, val); } -void UniformInput::update(const uniform_id_t &id, uint32_t val) { - this->program->set_u32(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, uint32_t val) { + this->program->set_u32(*this, id, val); } -void UniformInput::update(const uniform_id_t &id, float val) { - this->program->set_f32(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, float val) { + this->program->set_f32(*this, id, val); } -void UniformInput::update(const uniform_id_t &id, double val) { - this->program->set_f64(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, double val) { + this->program->set_f64(*this, id, val); } -void UniformInput::update(const uniform_id_t &id, bool val) { - this->program->set_bool(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, bool val) { + this->program->set_bool(*this, id, val); } -void UniformInput::update(const uniform_id_t &id, Eigen::Vector2f const &val) { - this->program->set_v2f32(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, Eigen::Vector2f const &val) { + this->program->set_v2f32(*this, id, val); } -void UniformInput::update(const uniform_id_t &id, Eigen::Vector3f const &val) { - this->program->set_v3f32(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, Eigen::Vector3f const &val) { + this->program->set_v3f32(*this, id, val); } -void UniformInput::update(const uniform_id_t &id, Eigen::Vector4f const &val) { - this->program->set_v4f32(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, Eigen::Vector4f const &val) { + this->program->set_v4f32(*this, id, val); } -void UniformInput::update(const uniform_id_t &id, Eigen::Vector2i const &val) { - this->program->set_v2i32(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, Eigen::Vector2i const &val) { + this->program->set_v2i32(*this, id, val); } -void UniformInput::update(const uniform_id_t &id, Eigen::Vector3i const &val) { - this->program->set_v3i32(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, Eigen::Vector3i const &val) { + this->program->set_v3i32(*this, id, val); } -void UniformInput::update(const uniform_id_t &id, Eigen::Vector4i const &val) { - this->program->set_v4i32(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, Eigen::Vector4i const &val) { + this->program->set_v4i32(*this, id, val); } -void UniformInput::update(const uniform_id_t &id, Eigen::Vector2 const &val) { - this->program->set_v2ui32(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, Eigen::Vector2 const &val) { + this->program->set_v2ui32(*this, id, val); } -void UniformInput::update(const uniform_id_t &id, Eigen::Vector3 const &val) { - this->program->set_v3ui32(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, Eigen::Vector3 const &val) { + this->program->set_v3ui32(*this, id, val); } -void UniformInput::update(const uniform_id_t &id, Eigen::Vector4 const &val) { - this->program->set_v4ui32(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, Eigen::Vector4 const &val) { + this->program->set_v4ui32(*this, id, val); } -void UniformInput::update(const uniform_id_t &id, std::shared_ptr const &val) { - this->program->set_tex(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, std::shared_ptr const &val) { + this->program->set_tex(*this, id, val); } -void UniformInput::update(const uniform_id_t &id, std::shared_ptr &val) { - this->program->set_tex(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, std::shared_ptr &val) { + this->program->set_tex(*this, id, val); } -void UniformInput::update(const uniform_id_t &id, Eigen::Matrix4f const &val) { - this->program->set_m4f32(this->shared_from_this(), id, val); +void UniformInput::update(uniform_id_t id, Eigen::Matrix4f const &val) { + this->program->set_m4f32(*this, id, val); } diff --git a/libopenage/renderer/uniform_input.h b/libopenage/renderer/uniform_input.h index 9e66b64712..6f2536459b 100644 --- a/libopenage/renderer/uniform_input.h +++ b/libopenage/renderer/uniform_input.h @@ -54,8 +54,7 @@ class DataInput { * Abstract base for uniform input. Besides the uniform values, it stores information about * which shader program the input was created for. */ -class UniformInput : public DataInput - , public std::enable_shared_from_this { +class UniformInput : public DataInput { protected: /** * Create a new uniform input for a given shader program. @@ -86,23 +85,23 @@ class UniformInput : public DataInput void update(const char *unif, std::shared_ptr &val) override; void update(const char *unif, Eigen::Matrix4f const &val) override; - void update(const uniform_id_t &id, int32_t val); - void update(const uniform_id_t &id, uint32_t val); - void update(const uniform_id_t &id, float val); - void update(const uniform_id_t &id, double val); - void update(const uniform_id_t &id, bool val); - void update(const uniform_id_t &id, Eigen::Vector2f const &val); - void update(const uniform_id_t &id, Eigen::Vector3f const &val); - void update(const uniform_id_t &id, Eigen::Vector4f const &val); - void update(const uniform_id_t &id, Eigen::Vector2i const &val); - void update(const uniform_id_t &id, Eigen::Vector3i const &val); - void update(const uniform_id_t &id, Eigen::Vector4i const &val); - void update(const uniform_id_t &id, Eigen::Vector2 const &val); - void update(const uniform_id_t &id, Eigen::Vector3 const &val); - void update(const uniform_id_t &id, Eigen::Vector4 const &val); - void update(const uniform_id_t &id, std::shared_ptr const &val); - void update(const uniform_id_t &id, std::shared_ptr &val); - void update(const uniform_id_t &id, Eigen::Matrix4f const &val); + void update(uniform_id_t id, int32_t val); + void update(uniform_id_t id, uint32_t val); + void update(uniform_id_t id, float val); + void update(uniform_id_t id, double val); + void update(uniform_id_t id, bool val); + void update(uniform_id_t id, Eigen::Vector2f const &val); + void update(uniform_id_t id, Eigen::Vector3f const &val); + void update(uniform_id_t id, Eigen::Vector4f const &val); + void update(uniform_id_t id, Eigen::Vector2i const &val); + void update(uniform_id_t id, Eigen::Vector3i const &val); + void update(uniform_id_t id, Eigen::Vector4i const &val); + void update(uniform_id_t id, Eigen::Vector2 const &val); + void update(uniform_id_t id, Eigen::Vector3 const &val); + void update(uniform_id_t id, Eigen::Vector4 const &val); + void update(uniform_id_t id, std::shared_ptr const &val); + void update(uniform_id_t id, std::shared_ptr &val); + void update(uniform_id_t id, Eigen::Matrix4f const &val); /** * Catch-all template in order to handle unsupported types and avoid infinite recursion.