diff --git a/copying.md b/copying.md index fb6501bab0..1002c8321a 100644 --- a/copying.md +++ b/copying.md @@ -154,6 +154,7 @@ _the openage authors_ are: | Haoyang Bi | AyiStar | ayistar à outlook dawt com | | Michael Seibt | RoboSchmied | github à roboschmie dawt de | | Nikhil Ghosh | NikhilGhosh75 | nghosh606 à gmail dawt com | +| Edvin Lindholm | EdvinLndh | edvinlndh à gmail dawt com | If you're a first-time committer, add yourself to the above list. This is not just for legal reasons, but also to keep an overview of all those nicknames. diff --git a/libopenage/gamestate/game_entity.cpp b/libopenage/gamestate/game_entity.cpp index a4e18a29e3..421c2847e7 100644 --- a/libopenage/gamestate/game_entity.cpp +++ b/libopenage/gamestate/game_entity.cpp @@ -1,4 +1,4 @@ -// Copyright 2022-2023 the openage authors. See copying.md for legal info. +// Copyright 2022-2024 the openage authors. See copying.md for legal info. #include "game_entity.h" @@ -30,7 +30,7 @@ entity_id_t GameEntity::get_id() const { return this->id; } -void GameEntity::set_render_entity(const std::shared_ptr &entity) { +void GameEntity::set_render_entity(const std::shared_ptr &entity) { // TODO: Transfer state from old render entity to new one? this->render_entity = entity; diff --git a/libopenage/gamestate/game_entity.h b/libopenage/gamestate/game_entity.h index 9b30e8ec76..923aed2eab 100644 --- a/libopenage/gamestate/game_entity.h +++ b/libopenage/gamestate/game_entity.h @@ -14,7 +14,7 @@ namespace openage { namespace renderer::world { -class WorldRenderEntity; +class RenderEntity; } namespace gamestate { @@ -62,7 +62,7 @@ class GameEntity { * * @param entity New render entity. */ - void set_render_entity(const std::shared_ptr &entity); + void set_render_entity(const std::shared_ptr &entity); /** * Set the event manager of this entity. @@ -142,7 +142,7 @@ class GameEntity { /** * Render entity for pushing updates to the renderer. Can be \p nullptr. */ - std::shared_ptr render_entity; + std::shared_ptr render_entity; /** * Event manager. diff --git a/libopenage/gamestate/terrain_chunk.cpp b/libopenage/gamestate/terrain_chunk.cpp index d863db9f67..3c624ff700 100644 --- a/libopenage/gamestate/terrain_chunk.cpp +++ b/libopenage/gamestate/terrain_chunk.cpp @@ -18,7 +18,7 @@ TerrainChunk::TerrainChunk(const util::Vector2s size, } } -void TerrainChunk::set_render_entity(const std::shared_ptr &entity) { +void TerrainChunk::set_render_entity(const std::shared_ptr &entity) { this->render_entity = entity; } diff --git a/libopenage/gamestate/terrain_chunk.h b/libopenage/gamestate/terrain_chunk.h index 574e63da4d..68d0a2e6f2 100644 --- a/libopenage/gamestate/terrain_chunk.h +++ b/libopenage/gamestate/terrain_chunk.h @@ -32,7 +32,7 @@ class TerrainChunk { * * @param entity New render entity. */ - void set_render_entity(const std::shared_ptr &entity); + void set_render_entity(const std::shared_ptr &entity); /** * Get the size of this terrain chunk. @@ -103,7 +103,7 @@ class TerrainChunk { /** * Render entity for pushing updates to the renderer. Can be \p nullptr. */ - std::shared_ptr render_entity; + std::shared_ptr render_entity; }; } // namespace openage::gamestate diff --git a/libopenage/input/controller/hud/controller.cpp b/libopenage/input/controller/hud/controller.cpp index b423ef79ae..af89923d1b 100644 --- a/libopenage/input/controller/hud/controller.cpp +++ b/libopenage/input/controller/hud/controller.cpp @@ -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. #include "controller.h" @@ -27,11 +27,11 @@ bool Controller::process(const event_arguments &ev_args, return true; } -void Controller::set_drag_entity(const std::shared_ptr &entity) { +void Controller::set_drag_entity(const std::shared_ptr &entity) { this->drag_entity = entity; } -const std::shared_ptr &Controller::get_drag_entity() const { +const std::shared_ptr &Controller::get_drag_entity() const { return this->drag_entity; } @@ -39,7 +39,7 @@ void setup_defaults(const std::shared_ptr &ctx, const std::shared_ptr &hud_renderer) { binding_func_t drag_selection_init{[&](const event_arguments &args, const std::shared_ptr controller) { - auto render_entity = std::make_shared(args.mouse); + auto render_entity = std::make_shared(args.mouse); hud_renderer->add_drag_entity(render_entity); controller->set_drag_entity(render_entity); }}; diff --git a/libopenage/input/controller/hud/controller.h b/libopenage/input/controller/hud/controller.h index 60e9ff2bb8..44d64ee833 100644 --- a/libopenage/input/controller/hud/controller.h +++ b/libopenage/input/controller/hud/controller.h @@ -10,7 +10,7 @@ namespace openage { namespace renderer::hud { -class HudDragRenderEntity; +class DragRenderEntity; class HudRenderStage; } // namespace renderer::hud @@ -42,20 +42,20 @@ class Controller : public std::enable_shared_from_this { * * @param entity New render entity. */ - void set_drag_entity(const std::shared_ptr &entity); + void set_drag_entity(const std::shared_ptr &entity); /** * Get the render entity for the selection box. * * @return Render entity for the selection box. */ - const std::shared_ptr &get_drag_entity() const; + const std::shared_ptr &get_drag_entity() const; private: /** * Render entity for the selection box. */ - std::shared_ptr drag_entity; + std::shared_ptr drag_entity; }; /** diff --git a/libopenage/renderer/demo/demo_3.cpp b/libopenage/renderer/demo/demo_3.cpp index 408e699196..9c294285f9 100644 --- a/libopenage/renderer/demo/demo_3.cpp +++ b/libopenage/renderer/demo/demo_3.cpp @@ -123,7 +123,7 @@ void renderer_demo_3(const util::Path &path) { // Fill a 10x10 terrain grid with height values auto terrain_size = util::Vector2s{10, 10}; - std::vector> tiles{}; + std::vector> tiles{}; tiles.reserve(terrain_size[0] * terrain_size[1]); for (size_t i = 0; i < terrain_size[0] * terrain_size[1]; ++i) { tiles.emplace_back(0.0f, "./textures/test_terrain.terrain"); diff --git a/libopenage/renderer/demo/stresstest_0.cpp b/libopenage/renderer/demo/stresstest_0.cpp index 76c53d7b21..eae208c5d3 100644 --- a/libopenage/renderer/demo/stresstest_0.cpp +++ b/libopenage/renderer/demo/stresstest_0.cpp @@ -133,7 +133,7 @@ void renderer_stresstest_0(const util::Path &path) { // Fill a 10x10 terrain grid with height values auto terrain_size = util::Vector2s{10, 10}; - std::vector> tiles{}; + std::vector> tiles{}; tiles.reserve(terrain_size[0] * terrain_size[1]); for (size_t i = 0; i < terrain_size[0] * terrain_size[1]; ++i) { tiles.emplace_back(0.0f, "./textures/test_terrain.terrain"); @@ -147,7 +147,7 @@ void renderer_stresstest_0(const util::Path &path) { terrain0->update(terrain_size, tiles); // World entities - std::vector> render_entities{}; + std::vector> render_entities{}; auto add_world_entity = [&](const coord::phys3 initial_pos, const time::time_t time) { const auto animation_path = "./textures/test_tank_mirrored.sprite"; diff --git a/libopenage/renderer/demo/stresstest_1.cpp b/libopenage/renderer/demo/stresstest_1.cpp index ac6177f819..9d2d43968b 100644 --- a/libopenage/renderer/demo/stresstest_1.cpp +++ b/libopenage/renderer/demo/stresstest_1.cpp @@ -138,7 +138,7 @@ void renderer_stresstest_1(const util::Path &path) { // Fill a 10x10 terrain grid with height values auto terrain_size = util::Vector2s{10, 10}; - std::vector> tiles{}; + std::vector> tiles{}; tiles.reserve(terrain_size[0] * terrain_size[1]); for (size_t i = 0; i < terrain_size[0] * terrain_size[1]; ++i) { tiles.emplace_back(0.0f, "./textures/test_terrain.terrain"); @@ -151,7 +151,7 @@ void renderer_stresstest_1(const util::Path &path) { // send the terrain data to the terrain renderer terrain0->update(terrain_size, tiles); - std::vector> render_entities{}; + std::vector> render_entities{}; auto add_world_entity = [&](const coord::phys3 initial_pos, const time::time_t time) { const auto animation_path = "./textures/test_tank_mirrored.sprite"; 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 661f9e3173..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, @@ -33,6 +33,12 @@ GlUniformBuffer::GlUniformBuffer(const std::shared_ptr &context, this->bind(); glBufferData(GL_UNIFORM_BUFFER, this->data_size, NULL, usage); + uniform_id_t unif_id = 0; + for (auto &uniform : uniforms) { + this->uniforms_by_name.insert(std::make_pair(uniform.name, unif_id)); + unif_id += 1; + } + glBindBufferRange(GL_UNIFORM_BUFFER, this->binding_point, *this->handle, 0, this->data_size); log::log(MSG(dbg) << "Created OpenGL uniform buffer (size: " @@ -51,23 +57,35 @@ void GlUniformBuffer::set_binding_point(GLuint binding_point) { void GlUniformBuffer::update_uniforms(std::shared_ptr const &unif_in) { auto glunif_in = std::dynamic_pointer_cast(unif_in); - ENSURE(glunif_in->get_buffer() == this->shared_from_this(), "Uniform input passed to different buffer than it was created with."); + ENSURE(glunif_in->get_buffer().get() == this, "Uniform input passed to different buffer than it was created with."); 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 : glunif_in->update_offs) { - uint8_t const *ptr = data + pair.second; - auto unif_def = this->uniforms[pair.first]; - auto loc = unif_def.offset; - auto size = unif_def.size; + + 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 = uniforms[unif_id]; + auto loc = unif.offset; + auto size = unif.size; glBufferSubData(GL_UNIFORM_BUFFER, loc, size, ptr); } } -bool GlUniformBuffer::has_uniform(const char *unif) { - return this->uniforms.count(unif) != 0; +const std::vector &GlUniformBuffer::get_uniforms() const { + return this->uniforms; +} + +bool GlUniformBuffer::has_uniform(const char *name) { + return this->uniforms_by_name.contains(name); } void GlUniformBuffer::bind() const { @@ -80,14 +98,14 @@ std::shared_ptr GlUniformBuffer::new_unif_in() { return in; } -void GlUniformBuffer::set_unif(std::shared_ptr const &in, const char *unif, void const *val, GLenum type) { - auto unif_in = std::dynamic_pointer_cast(in); +void GlUniformBuffer::set_unif(UniformBufferInput &in, const char *unif, void const *val, GLenum type) { + auto &unif_in = dynamic_cast(in); - 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 unif_id = this->uniforms_by_name.find(unif)->second; + ENSURE(unif_id < this->uniforms.size(), + "Tried to set uniform with invalid ID " << unif_id); - 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."); @@ -96,83 +114,80 @@ void GlUniformBuffer::set_unif(std::shared_ptr const &in, co 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 - // 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, 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 GlUniformBuffer::set_i32(std::shared_ptr const &in, const char *unif, int32_t val) { +void GlUniformBuffer::set_i32(UniformBufferInput &in, const char *unif, int32_t val) { this->set_unif(in, unif, &val, GL_INT); } -void GlUniformBuffer::set_u32(std::shared_ptr const &in, const char *unif, uint32_t val) { +void GlUniformBuffer::set_u32(UniformBufferInput &in, const char *unif, uint32_t val) { this->set_unif(in, unif, &val, GL_UNSIGNED_INT); } -void GlUniformBuffer::set_f32(std::shared_ptr const &in, const char *unif, float val) { +void GlUniformBuffer::set_f32(UniformBufferInput &in, const char *unif, float val) { this->set_unif(in, unif, &val, GL_FLOAT); } -void GlUniformBuffer::set_f64(std::shared_ptr const &in, const char *unif, double val) { +void GlUniformBuffer::set_f64(UniformBufferInput &in, const char *unif, double val) { this->set_unif(in, unif, &val, GL_DOUBLE); } -void GlUniformBuffer::set_bool(std::shared_ptr const &in, const char *unif, bool val) { +void GlUniformBuffer::set_bool(UniformBufferInput &in, const char *unif, bool val) { this->set_unif(in, unif, &val, GL_BOOL); } -void GlUniformBuffer::set_v2f32(std::shared_ptr const &in, const char *unif, Eigen::Vector2f const &val) { +void GlUniformBuffer::set_v2f32(UniformBufferInput &in, const char *unif, Eigen::Vector2f const &val) { this->set_unif(in, unif, val.data(), GL_FLOAT_VEC2); } -void GlUniformBuffer::set_v3f32(std::shared_ptr const &in, const char *unif, Eigen::Vector3f const &val) { +void GlUniformBuffer::set_v3f32(UniformBufferInput &in, const char *unif, Eigen::Vector3f const &val) { this->set_unif(in, unif, val.data(), GL_FLOAT_VEC3); } -void GlUniformBuffer::set_v4f32(std::shared_ptr const &in, const char *unif, Eigen::Vector4f const &val) { +void GlUniformBuffer::set_v4f32(UniformBufferInput &in, const char *unif, Eigen::Vector4f const &val) { this->set_unif(in, unif, val.data(), GL_FLOAT_VEC4); } -void GlUniformBuffer::set_v2i32(std::shared_ptr const &in, const char *unif, Eigen::Vector2i const &val) { +void GlUniformBuffer::set_v2i32(UniformBufferInput &in, const char *unif, Eigen::Vector2i const &val) { this->set_unif(in, unif, val.data(), GL_INT_VEC2); } -void GlUniformBuffer::set_v3i32(std::shared_ptr const &in, const char *unif, Eigen::Vector3i const &val) { +void GlUniformBuffer::set_v3i32(UniformBufferInput &in, const char *unif, Eigen::Vector3i const &val) { this->set_unif(in, unif, val.data(), GL_INT_VEC3); } -void GlUniformBuffer::set_v4i32(std::shared_ptr const &in, const char *unif, Eigen::Vector4i const &val) { +void GlUniformBuffer::set_v4i32(UniformBufferInput &in, const char *unif, Eigen::Vector4i const &val) { this->set_unif(in, unif, val.data(), GL_INT_VEC4); } -void GlUniformBuffer::set_v2ui32(std::shared_ptr const &in, const char *unif, Eigen::Vector2 const &val) { +void GlUniformBuffer::set_v2ui32(UniformBufferInput &in, const char *unif, Eigen::Vector2 const &val) { this->set_unif(in, unif, val.data(), GL_UNSIGNED_INT_VEC2); } -void GlUniformBuffer::set_v3ui32(std::shared_ptr const &in, const char *unif, Eigen::Vector3 const &val) { +void GlUniformBuffer::set_v3ui32(UniformBufferInput &in, const char *unif, Eigen::Vector3 const &val) { this->set_unif(in, unif, val.data(), GL_UNSIGNED_INT_VEC3); } -void GlUniformBuffer::set_v4ui32(std::shared_ptr const &in, const char *unif, Eigen::Vector4 const &val) { +void GlUniformBuffer::set_v4ui32(UniformBufferInput &in, const char *unif, Eigen::Vector4 const &val) { this->set_unif(in, unif, val.data(), GL_UNSIGNED_INT_VEC4); } -void GlUniformBuffer::set_m4f32(std::shared_ptr const &in, const char *unif, Eigen::Matrix4f const &val) { +void GlUniformBuffer::set_m4f32(UniformBufferInput &in, const char *unif, Eigen::Matrix4f const &val) { this->set_unif(in, unif, val.data(), GL_FLOAT_MAT4); } -void GlUniformBuffer::set_tex(std::shared_ptr const &in, const char *unif, std::shared_ptr const &val) { +void GlUniformBuffer::set_tex(UniformBufferInput &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); diff --git a/libopenage/renderer/opengl/uniform_buffer.h b/libopenage/renderer/opengl/uniform_buffer.h index 6c7ca3d869..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); @@ -33,6 +33,13 @@ class GlUniformBuffer final : public UniformBuffer */ GLuint get_binding_point() const; + /** + * Get the uniform buffers uniforms. + * + * @return Uniforms in the shader program. + */ + const std::vector &get_uniforms() const; + /** * Set the binding point of the buffer. * @@ -51,22 +58,22 @@ class GlUniformBuffer final : public UniformBuffer 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(UniformBufferInput &in, const char *, int32_t) override; + void set_u32(UniformBufferInput &in, const char *, uint32_t) override; + void set_f32(UniformBufferInput &in, const char *, float) override; + void set_f64(UniformBufferInput &in, const char *, double) override; + void set_bool(UniformBufferInput &in, const char *, bool) override; + void set_v2f32(UniformBufferInput &in, const char *, Eigen::Vector2f const &) override; + void set_v3f32(UniformBufferInput &in, const char *, Eigen::Vector3f const &) override; + void set_v4f32(UniformBufferInput &in, const char *, Eigen::Vector4f const &) override; + void set_v2i32(UniformBufferInput &in, const char *, Eigen::Vector2i const &) override; + void set_v3i32(UniformBufferInput &in, const char *, Eigen::Vector3i const &) override; + void set_v4i32(UniformBufferInput &in, const char *, Eigen::Vector4i const &) override; + void set_v2ui32(UniformBufferInput &in, const char *, Eigen::Vector2 const &) override; + void set_v3ui32(UniformBufferInput &in, const char *, Eigen::Vector3 const &) override; + void set_v4ui32(UniformBufferInput &in, const char *, Eigen::Vector4 const &) override; + void set_m4f32(UniformBufferInput &in, const char *, Eigen::Matrix4f const &) override; + void set_tex(UniformBufferInput &in, const char *, std::shared_ptr const &) override; private: /** @@ -80,7 +87,7 @@ class GlUniformBuffer final : public UniformBuffer * @param val Pointer to the value to update the uniform with. * @param type Type of the uniform. */ - void set_unif(std::shared_ptr const &in, + void set_unif(UniformBufferInput &in, const char *name, void const *val, GLenum type); @@ -88,7 +95,12 @@ 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). + */ + std::unordered_map uniforms_by_name; /** * Size of the buffer (in bytes). diff --git a/libopenage/renderer/opengl/uniform_input.cpp b/libopenage/renderer/opengl/uniform_input.cpp index 111b33b879..38c63f2d66 100644 --- a/libopenage/renderer/opengl/uniform_input.cpp +++ b/libopenage/renderer/opengl/uniform_input.cpp @@ -4,6 +4,7 @@ #include "renderer/opengl/lookup.h" #include "renderer/opengl/shader_program.h" +#include "renderer/opengl/uniform_buffer.h" #include "renderer/opengl/util.h" @@ -28,7 +29,25 @@ GlUniformInput::GlUniformInput(const std::shared_ptr &prog) : this->update_data.resize(offset); } -GlUniformBufferInput::GlUniformBufferInput(std::shared_ptr const &buffer) : - UniformBufferInput{buffer} {} +GlUniformBufferInput::GlUniformBufferInput(const std::shared_ptr &buffer) : + UniformBufferInput{buffer} { + auto glBuf = std::dynamic_pointer_cast(buffer); + + auto uniforms = glBuf->get_uniforms(); + + // Reserve space for the used uniforms. + this->used_uniforms.reserve(uniforms.size()); + + // Calculate the byte-wise offsets of all uniforms. + size_t offset = 0; + this->update_offs.reserve(uniforms.size()); + for (auto &uniform : uniforms) { + 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. + this->update_data.resize(offset); +} } // namespace openage::renderer::opengl diff --git a/libopenage/renderer/opengl/uniform_input.h b/libopenage/renderer/opengl/uniform_input.h index 8ca3ff02dd..961e12a2a5 100644 --- a/libopenage/renderer/opengl/uniform_input.h +++ b/libopenage/renderer/opengl/uniform_input.h @@ -18,6 +18,7 @@ class UniformBuffer; namespace opengl { class GlShaderProgram; +class GlUniformBuffer; /** * Describes OpenGL-specific uniform valuations. @@ -57,18 +58,28 @@ class GlUniformInput final : public UniformInput { * Describes OpenGL-specific uniform buffer valuations. */ class GlUniformBufferInput final : public UniformBufferInput { +private: + struct GlUniformOffset { + // Offset in the update_data buffer. + size_t offset; + /// Dtermine whether the uniform value has been set. + bool used; + }; + + public: - GlUniformBufferInput(std::shared_ptr const &); + GlUniformBufferInput(const std::shared_ptr &buffer); /** - * We store uniform updates lazily. They are only actually uploaded to GPU - * when a draw call is made. - * - * \p update_offs maps the uniform names 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. + * Store the IDs of the uniforms from the shader set by this uniform input. */ - std::unordered_map update_offs; + std::vector used_uniforms; + + /** + * Store offsets of uniforms in the update_data buffer and + * whether the uniform value has been set. + */ + std::vector update_offs; /** * Buffer containing untyped uniform update data. diff --git a/libopenage/renderer/render_factory.cpp b/libopenage/renderer/render_factory.cpp index 6d5e276479..3dee6dd6ae 100644 --- a/libopenage/renderer/render_factory.cpp +++ b/libopenage/renderer/render_factory.cpp @@ -1,4 +1,4 @@ -// Copyright 2022-2023 the openage authors. See copying.md for legal info. +// Copyright 2022-2024 the openage authors. See copying.md for legal info. #include "render_factory.h" @@ -15,16 +15,16 @@ RenderFactory::RenderFactory(const std::shared_ptr world_renderer{world_renderer} { } -std::shared_ptr RenderFactory::add_terrain_render_entity(const util::Vector2s chunk_size, - const coord::tile_delta chunk_offset) { - auto entity = std::make_shared(); +std::shared_ptr RenderFactory::add_terrain_render_entity(const util::Vector2s chunk_size, + const coord::tile_delta chunk_offset) { + auto entity = std::make_shared(); this->terrain_renderer->add_render_entity(entity, chunk_size, chunk_offset.to_phys2().to_scene2()); return entity; } -std::shared_ptr RenderFactory::add_world_render_entity() { - auto entity = std::make_shared(); +std::shared_ptr RenderFactory::add_world_render_entity() { + auto entity = std::make_shared(); this->world_renderer->add_render_entity(entity); return entity; diff --git a/libopenage/renderer/render_factory.h b/libopenage/renderer/render_factory.h index 26601bcf7f..a211e3edf4 100644 --- a/libopenage/renderer/render_factory.h +++ b/libopenage/renderer/render_factory.h @@ -11,12 +11,12 @@ namespace openage::renderer { namespace terrain { class TerrainRenderStage; -class TerrainRenderEntity; +class RenderEntity; } // namespace terrain namespace world { class WorldRenderStage; -class WorldRenderEntity; +class RenderEntity; } // namespace world /** @@ -47,15 +47,15 @@ class RenderFactory { * * @return Render entity for pushing terrain updates. */ - std::shared_ptr add_terrain_render_entity(const util::Vector2s chunk_size, - const coord::tile_delta chunk_offset); + std::shared_ptr add_terrain_render_entity(const util::Vector2s chunk_size, + const coord::tile_delta chunk_offset); /** * Create a new world render entity and register it at the world renderer. * * @return Render entity for pushing terrain updates. */ - std::shared_ptr add_world_render_entity(); + std::shared_ptr add_world_render_entity(); private: /** diff --git a/libopenage/renderer/stages/CMakeLists.txt b/libopenage/renderer/stages/CMakeLists.txt index c2ae5bf781..77d6faa091 100644 --- a/libopenage/renderer/stages/CMakeLists.txt +++ b/libopenage/renderer/stages/CMakeLists.txt @@ -1,3 +1,7 @@ +add_sources(libopenage + render_entity.cpp +) + add_subdirectory(camera/) add_subdirectory(hud/) add_subdirectory(screen/) diff --git a/libopenage/renderer/stages/hud/object.cpp b/libopenage/renderer/stages/hud/object.cpp index 2b53bd1b3b..6e23b6663a 100644 --- a/libopenage/renderer/stages/hud/object.cpp +++ b/libopenage/renderer/stages/hud/object.cpp @@ -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. #include "object.h" @@ -21,7 +21,7 @@ HudDragObject::HudDragObject(const std::shared_ptr &entity) { +void HudDragObject::set_render_entity(const std::shared_ptr &entity) { this->render_entity = entity; this->fetch_updates(); } @@ -38,8 +38,15 @@ void HudDragObject::fetch_updates(const time::time_t &time) { // Get data from render entity this->drag_start = this->render_entity->get_drag_start(); + + // Thread-safe access to curves needs a lock on the render entity's mutex + auto read_lock = this->render_entity->get_read_lock(); + this->drag_pos.sync(this->render_entity->get_drag_pos() /* , this->last_update */); + // Unlock the render entity mutex + read_lock.unlock(); + // Set self to changed so that world renderer can update the renderable this->changed = true; this->render_entity->clear_changed_flag(); diff --git a/libopenage/renderer/stages/hud/object.h b/libopenage/renderer/stages/hud/object.h index fac062f18d..d81e51ed8d 100644 --- a/libopenage/renderer/stages/hud/object.h +++ b/libopenage/renderer/stages/hud/object.h @@ -26,7 +26,7 @@ class Animation2dInfo; } // namespace resources namespace hud { -class HudDragRenderEntity; +class DragRenderEntity; /** * Stores the state of a renderable object in the HUD render stage. @@ -46,7 +46,7 @@ class HudDragObject { * * @param entity New world render entity. */ - void set_render_entity(const std::shared_ptr &entity); + void set_render_entity(const std::shared_ptr &entity); /** * Set the current camera of the scene. @@ -147,7 +147,7 @@ class HudDragObject { /** * Source for positional and texture data. */ - std::shared_ptr render_entity; + std::shared_ptr render_entity; /** * Position of the dragged corner. diff --git a/libopenage/renderer/stages/hud/render_entity.cpp b/libopenage/renderer/stages/hud/render_entity.cpp index f8cf19e692..2ff3f75649 100644 --- a/libopenage/renderer/stages/hud/render_entity.cpp +++ b/libopenage/renderer/stages/hud/render_entity.cpp @@ -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. #include "render_entity.h" @@ -7,15 +7,14 @@ namespace openage::renderer::hud { -HudDragRenderEntity::HudDragRenderEntity(const coord::input drag_start) : - changed{false}, - last_update{0.0}, +DragRenderEntity::DragRenderEntity(const coord::input drag_start) : + renderer::RenderEntity{}, drag_pos{nullptr, 0, "", nullptr, drag_start}, drag_start{drag_start} { } -void HudDragRenderEntity::update(const coord::input drag_pos, - const time::time_t time) { +void DragRenderEntity::update(const coord::input drag_pos, + const time::time_t time) { std::unique_lock lock{this->mutex}; this->drag_pos.set_insert(time, drag_pos); @@ -24,30 +23,16 @@ void HudDragRenderEntity::update(const coord::input drag_pos, this->changed = true; } -time::time_t HudDragRenderEntity::get_update_time() { +const curve::Continuous &DragRenderEntity::get_drag_pos() { std::shared_lock lock{this->mutex}; - return this->last_update; -} - -const curve::Continuous &HudDragRenderEntity::get_drag_pos() { return this->drag_pos; } -const coord::input &HudDragRenderEntity::get_drag_start() { - return this->drag_start; -} - -bool HudDragRenderEntity::is_changed() { +const coord::input DragRenderEntity::get_drag_start() { std::shared_lock lock{this->mutex}; - return this->changed; -} - -void HudDragRenderEntity::clear_changed_flag() { - std::unique_lock lock{this->mutex}; - - this->changed = false; + return this->drag_start; } } // namespace openage::renderer::hud diff --git a/libopenage/renderer/stages/hud/render_entity.h b/libopenage/renderer/stages/hud/render_entity.h index e2e2da65fa..9d15204386 100644 --- a/libopenage/renderer/stages/hud/render_entity.h +++ b/libopenage/renderer/stages/hud/render_entity.h @@ -3,12 +3,10 @@ #pragma once #include -#include -#include #include "coord/pixel.h" #include "curve/continuous.h" -#include "time/time.h" +#include "renderer/stages/render_entity.h" namespace openage::renderer::hud { @@ -16,36 +14,34 @@ namespace openage::renderer::hud { /** * Render entity for pushing drag selection updates to the HUD renderer. */ -class HudDragRenderEntity { +class DragRenderEntity final : public renderer::RenderEntity { public: /** * Create a new render entity for drag selection in the HUD. * * @param drag_start Position of the start corner. */ - HudDragRenderEntity(const coord::input drag_start); - ~HudDragRenderEntity() = default; + DragRenderEntity(const coord::input drag_start); + ~DragRenderEntity() = default; /** * Update the render entity with information from the gamestate * or input system. * + * Updating the render entity with this method is thread-safe. + * * @param drag_pos Position of the dragged corner. * @param time Current simulation time. */ void update(const coord::input drag_pos, const time::time_t time = 0.0); - /** - * Get the time of the last update. - * - * @return Time of last update. - */ - time::time_t get_update_time(); - /** * Get the position of the dragged corner. * + * Accessing the drag position curve REQUIRES a read lock on the render entity + * (using \p get_read_lock()) to ensure thread safety. + * * @return Coordinates of the dragged corner. */ const curve::Continuous &get_drag_pos(); @@ -53,35 +49,13 @@ class HudDragRenderEntity { /** * Get the position of the start corner. * - * @return Coordinates of the start corner. - */ - const coord::input &get_drag_start(); - - /** - * Check whether the render entity has received new updates. + * Accessing the drag start is thread-safe. * - * @return true if updates have been received, else false. - */ - bool is_changed(); - - /** - * Clear the update flag by setting it to false. + * @return Coordinates of the start corner. */ - void clear_changed_flag(); + const coord::input get_drag_start(); private: - /** - * Flag for determining if the render entity has been updated by the - * corresponding gamestate entity. Set to true every time \p update() - * is called. - */ - bool changed; - - /** - * Time of the last update call. - */ - time::time_t last_update; - /** * Position of the dragged corner. */ @@ -91,10 +65,5 @@ class HudDragRenderEntity { * Position of the start corner. */ coord::input drag_start; - - /** - * Mutex for protecting threaded access. - */ - std::shared_mutex mutex; }; } // namespace openage::renderer::hud diff --git a/libopenage/renderer/stages/hud/render_stage.cpp b/libopenage/renderer/stages/hud/render_stage.cpp index a55751ec5f..d5d7c5b83f 100644 --- a/libopenage/renderer/stages/hud/render_stage.cpp +++ b/libopenage/renderer/stages/hud/render_stage.cpp @@ -45,7 +45,7 @@ std::shared_ptr HudRenderStage::get_render_pass() { return this->render_pass; } -void HudRenderStage::add_drag_entity(const std::shared_ptr entity) { +void HudRenderStage::add_drag_entity(const std::shared_ptr entity) { std::unique_lock lock{this->mutex}; auto hud_object = std::make_shared(this->asset_manager); diff --git a/libopenage/renderer/stages/hud/render_stage.h b/libopenage/renderer/stages/hud/render_stage.h index f63662aa40..047aac6349 100644 --- a/libopenage/renderer/stages/hud/render_stage.h +++ b/libopenage/renderer/stages/hud/render_stage.h @@ -31,7 +31,7 @@ class AssetManager; namespace hud { class HudDragObject; -class HudDragRenderEntity; +class DragRenderEntity; /** * Renderer for the "Heads-Up Display" (HUD). @@ -71,7 +71,7 @@ class HudRenderStage { * * @param render_entity New render entity. */ - void add_drag_entity(const std::shared_ptr entity); + void add_drag_entity(const std::shared_ptr entity); /** * Remove the render object for drag selection. diff --git a/libopenage/renderer/stages/render_entity.cpp b/libopenage/renderer/stages/render_entity.cpp new file mode 100644 index 0000000000..dc95de9a6d --- /dev/null +++ b/libopenage/renderer/stages/render_entity.cpp @@ -0,0 +1,37 @@ +// Copyright 2024-2024 the openage authors. See copying.md for legal info. + +#include "render_entity.h" + +#include + + +namespace openage::renderer { + +RenderEntity::RenderEntity() : + changed{false}, + last_update{time::time_t::zero()} { +} + +time::time_t RenderEntity::get_update_time() { + std::shared_lock lock{this->mutex}; + + return this->last_update; +} + +bool RenderEntity::is_changed() { + std::shared_lock lock{this->mutex}; + + return this->changed; +} + +void RenderEntity::clear_changed_flag() { + std::unique_lock lock{this->mutex}; + + this->changed = false; +} + +std::shared_lock RenderEntity::get_read_lock() { + return std::shared_lock{this->mutex}; +} + +} // namespace openage::renderer diff --git a/libopenage/renderer/stages/render_entity.h b/libopenage/renderer/stages/render_entity.h new file mode 100644 index 0000000000..f441452968 --- /dev/null +++ b/libopenage/renderer/stages/render_entity.h @@ -0,0 +1,83 @@ +// Copyright 2024-2024 the openage authors. See copying.md for legal info. + +#pragma once + +#include +#include + +#include + +#include "time/time.h" + + +namespace openage::renderer { + +/** + * Interface for render entities that allow pushing updates from game simulation + * to renderer. + */ +class RenderEntity { +public: + ~RenderEntity() = default; + + /** + * Get the time of the last update. + * + * Accessing the update time is thread-safe. + * + * @return Time of last update. + */ + time::time_t get_update_time(); + + /** + * Check whether the render entity has received new updates from the + * gamestate. + * + * @return true if updates have been received, else false. + */ + bool is_changed(); + + /** + * Clear the update flag by setting it to false. + */ + void clear_changed_flag(); + + /** + * Get a shared lock for thread-safe reading from the render entity. + * + * The caller is responsible for unlocking the mutex after reading. + * + * @return Lock for the render entity. + */ + std::shared_lock get_read_lock(); + +protected: + /** + * Create a new render entity. + * + * Members are initialized to these values by default: + * - \p changed: false + * - \p last_update: time::time_t::zero() + * + * Declared as protected to prevent direct instantiation of this class. + */ + RenderEntity(); + + /** + * Flag for determining if the render entity has been updated by the + * corresponding gamestate entity. Set to true every time \p update() + * is called. + */ + bool changed; + + /** + * Time of the last update call. + */ + time::time_t last_update; + + /** + * Mutex for protecting threaded access. + */ + std::shared_mutex mutex; +}; +} // namespace openage::renderer diff --git a/libopenage/renderer/stages/terrain/chunk.cpp b/libopenage/renderer/stages/terrain/chunk.cpp index 12b207bdc9..58a95d2a95 100644 --- a/libopenage/renderer/stages/terrain/chunk.cpp +++ b/libopenage/renderer/stages/terrain/chunk.cpp @@ -17,7 +17,7 @@ TerrainChunk::TerrainChunk(const std::shared_ptr &entity) { +void TerrainChunk::set_render_entity(const std::shared_ptr &entity) { this->render_entity = entity; } @@ -31,11 +31,19 @@ void TerrainChunk::fetch_updates(const time::time_t & /* time */) { if (not this->render_entity->is_changed()) { return; } + + // Get the terrain data from the render entity + auto terrain_size = this->render_entity->get_size(); + auto terrain_paths = this->render_entity->get_terrain_paths(); + auto tiles = this->render_entity->get_tiles(); + auto heightmap_verts = this->render_entity->get_vertices(); + + // Recreate the mesh data // TODO: Change mesh instead of recreating it // TODO: Multiple meshes this->meshes.clear(); - for (const auto &terrain_path : this->render_entity->get_terrain_paths()) { - auto new_mesh = this->create_mesh(terrain_path); + for (const auto &terrain_path : terrain_paths) { + auto new_mesh = this->create_mesh(terrain_size, tiles, heightmap_verts, terrain_path); new_mesh->create_model_matrix(this->offset); this->meshes.push_back(new_mesh); } @@ -59,13 +67,12 @@ const std::vector> &TerrainChunk::get_meshes( return this->meshes; } -std::shared_ptr TerrainChunk::create_mesh(const std::string &texture_path) { - auto size = this->render_entity->get_size(); - auto v_width = size[0]; - auto v_height = size[1]; - - auto tiles = this->render_entity->get_tiles(); - auto heightmap_verts = this->render_entity->get_vertices(); +std::shared_ptr TerrainChunk::create_mesh(const util::Vector2s vert_size, + const RenderEntity::tiles_t &tiles, + const std::vector &heightmap_verts, + const std::string &texture_path) { + auto v_width = vert_size[0]; + auto v_height = vert_size[1]; // vertex data for the mesh std::vector mesh_verts{}; diff --git a/libopenage/renderer/stages/terrain/chunk.h b/libopenage/renderer/stages/terrain/chunk.h index b64133e5b6..7d3d9fcc70 100644 --- a/libopenage/renderer/stages/terrain/chunk.h +++ b/libopenage/renderer/stages/terrain/chunk.h @@ -7,6 +7,7 @@ #include #include "coord/scene.h" +#include "renderer/stages/terrain/render_entity.h" #include "time/time.h" #include "util/vector.h" @@ -19,7 +20,6 @@ class AssetManager; namespace terrain { class TerrainRenderMesh; -class TerrainRenderEntity; /** * Stores the state of a terrain chunk in the terrain render stage. @@ -44,7 +44,7 @@ class TerrainChunk { * @param size Size of the chunk in tiles. * @param offset Offset of the chunk from origin in tiles. */ - void set_render_entity(const std::shared_ptr &entity); + void set_render_entity(const std::shared_ptr &entity); /** * Fetch updates from the render entity. @@ -85,9 +85,17 @@ class TerrainChunk { /** * Create a terrain mesh from the data provided by the render entity. * + * @param vert_size Size of the terrain in vertices. + * @param tiles Data for each tile (elevation, terrain path). + * @param heightmap_verts Position of each vertex in the chunk. + * @param texture_path Path to the texture for the terrain. + * * @return New terrain mesh. */ - std::shared_ptr create_mesh(const std::string &texture_path); + std::shared_ptr create_mesh(const util::Vector2s vert_size, + const RenderEntity::tiles_t &tiles, + const std::vector &heightmap_verts, + const std::string &texture_path); /** * Size of the chunk in tiles (width x height). @@ -114,7 +122,7 @@ class TerrainChunk { * Source for ingame terrain coordinates. These coordinates are translated into * our render vertex mesh when \p update() is called. */ - std::shared_ptr render_entity; + std::shared_ptr render_entity; }; diff --git a/libopenage/renderer/stages/terrain/model.cpp b/libopenage/renderer/stages/terrain/model.cpp index 8d8cc4c727..30e235c1bd 100644 --- a/libopenage/renderer/stages/terrain/model.cpp +++ b/libopenage/renderer/stages/terrain/model.cpp @@ -1,4 +1,4 @@ -// Copyright 2022-2023 the openage authors. See copying.md for legal info. +// Copyright 2022-2024 the openage authors. See copying.md for legal info. #include "model.h" @@ -26,7 +26,7 @@ TerrainRenderModel::TerrainRenderModel(const std::shared_ptr &entity, +void TerrainRenderModel::add_chunk(const std::shared_ptr &entity, const util::Vector2s size, const coord::scene2_delta offset) { auto chunk = std::make_shared(this->asset_manager, size, offset); diff --git a/libopenage/renderer/stages/terrain/model.h b/libopenage/renderer/stages/terrain/model.h index c06ea351c0..951599855d 100644 --- a/libopenage/renderer/stages/terrain/model.h +++ b/libopenage/renderer/stages/terrain/model.h @@ -21,7 +21,7 @@ class AssetManager; } namespace terrain { -class TerrainRenderEntity; +class RenderEntity; class TerrainRenderMesh; class TerrainChunk; @@ -46,7 +46,7 @@ class TerrainRenderModel { * @param chunk_size Size of the chunk in tiles. * @param chunk_offset Offset of the chunk from origin in tiles. */ - void add_chunk(const std::shared_ptr &entity, + void add_chunk(const std::shared_ptr &entity, const util::Vector2s chunk_size, const coord::scene2_delta chunk_offset); diff --git a/libopenage/renderer/stages/terrain/render_entity.cpp b/libopenage/renderer/stages/terrain/render_entity.cpp index 7f2e6d825e..2316f5dab7 100644 --- a/libopenage/renderer/stages/terrain/render_entity.cpp +++ b/libopenage/renderer/stages/terrain/render_entity.cpp @@ -9,22 +9,19 @@ namespace openage::renderer::terrain { -TerrainRenderEntity::TerrainRenderEntity() : - changed{false}, +RenderEntity::RenderEntity() : + renderer::RenderEntity{}, size{0, 0}, tiles{}, - last_update{0.0}, terrain_paths{}, - vertices{} -// terrain_path{nullptr, 0}, -{ + vertices{} { } -void TerrainRenderEntity::update_tile(const util::Vector2s size, - const coord::tile &pos, - const terrain_elevation_t elevation, - const std::string terrain_path, - const time::time_t time) { +void RenderEntity::update_tile(const util::Vector2s size, + const coord::tile &pos, + const terrain_elevation_t elevation, + const std::string terrain_path, + const time::time_t time) { std::unique_lock lock{this->mutex}; if (this->vertices.empty()) { @@ -52,9 +49,9 @@ void TerrainRenderEntity::update_tile(const util::Vector2s size, this->changed = true; } -void TerrainRenderEntity::update(const util::Vector2s size, - const tiles_t tiles, - const time::time_t time) { +void RenderEntity::update(const util::Vector2s size, + const tiles_t tiles, + const time::time_t time) { std::unique_lock lock{this->mutex}; // increase by 1 in every dimension because tiles @@ -108,40 +105,28 @@ void TerrainRenderEntity::update(const util::Vector2s size, this->changed = true; } -const std::vector &TerrainRenderEntity::get_vertices() { +const std::vector RenderEntity::get_vertices() { std::shared_lock lock{this->mutex}; return this->vertices; } -const TerrainRenderEntity::tiles_t &TerrainRenderEntity::get_tiles() { +const RenderEntity::tiles_t RenderEntity::get_tiles() { std::shared_lock lock{this->mutex}; return this->tiles; } -const std::unordered_set &TerrainRenderEntity::get_terrain_paths() { +const std::unordered_set RenderEntity::get_terrain_paths() { std::shared_lock lock{this->mutex}; return this->terrain_paths; } -const util::Vector2s &TerrainRenderEntity::get_size() { +const util::Vector2s RenderEntity::get_size() { std::shared_lock lock{this->mutex}; return this->size; } -bool TerrainRenderEntity::is_changed() { - std::shared_lock lock{this->mutex}; - - return this->changed; -} - -void TerrainRenderEntity::clear_changed_flag() { - std::unique_lock lock{this->mutex}; - - this->changed = false; -} - } // namespace openage::renderer::terrain diff --git a/libopenage/renderer/stages/terrain/render_entity.h b/libopenage/renderer/stages/terrain/render_entity.h index 4136c7c81a..0f726a2351 100644 --- a/libopenage/renderer/stages/terrain/render_entity.h +++ b/libopenage/renderer/stages/terrain/render_entity.h @@ -2,8 +2,6 @@ #pragma once -#include -#include #include #include #include @@ -11,7 +9,7 @@ #include "coord/scene.h" #include "coord/tile.h" #include "curve/discrete.h" -#include "time/time.h" +#include "renderer/stages/render_entity.h" #include "util/vector.h" @@ -20,10 +18,10 @@ namespace openage::renderer::terrain { /** * Render entity for pushing updates to the Terrain renderer. */ -class TerrainRenderEntity { +class RenderEntity final : public renderer::RenderEntity { public: - TerrainRenderEntity(); - ~TerrainRenderEntity() = default; + RenderEntity(); + ~RenderEntity() = default; using terrain_elevation_t = util::FixedPoint; using tiles_t = std::vector>; @@ -32,6 +30,8 @@ class TerrainRenderEntity { * Update a single tile of the displayed terrain (chunk) with information from the * gamestate. * + * Updating the render entity with this method is thread-safe. + * * @param size Size of the terrain in tiles (width x length) * @param pos Position of the tile in the chunk. * @param elevation Height of terrain tile. @@ -48,6 +48,8 @@ class TerrainRenderEntity { * Update the full grid of the displayed terrain (chunk) with information from the * gamestate. * + * Updating the render entity with this method is thread-safe. + * * @param size Size of the terrain in tiles (width x length) * @param tiles Animation data for each tile (elevation, terrain path). * @param time Simulation time of the update. @@ -59,52 +61,40 @@ class TerrainRenderEntity { /** * Get the vertices of the terrain. * + * Accessing the terrain vertices is thread-safe. + * * @return Vector of vertex coordinates. */ - const std::vector &get_vertices(); + const std::vector get_vertices(); /** * Get the tiles of the terrain. * + * Accessing the terrain tiles is thread-safe. + * * @return Terrain tiles. */ - const tiles_t &get_tiles(); + const tiles_t get_tiles(); /** * Get the terrain paths used in the terrain. * + * Accessing the terrain paths is thread-safe. + * * @return Terrain paths. */ - const std::unordered_set &get_terrain_paths(); + const std::unordered_set get_terrain_paths(); /** * Get the number of vertices on each side of the terrain. * - * @return Vector with width as first element and height as second element. - */ - const util::Vector2s &get_size(); - - /** - * Check whether the render entity has received new updates from the - * gamestate. + * Accessing the vertices size is thread-safe. * - * @return true if updates have been received, else false. - */ - bool is_changed(); - - /** - * Clear the update flag by setting it to false. + * @return Vector with width as first element and height as second element. */ - void clear_changed_flag(); + const util::Vector2s get_size(); private: - /** - * Flag for determining if the render entity has been updated by the - * corresponding gamestate entity. Set to true every time \p update() - * is called. - */ - bool changed; - /** * Chunk dimensions (width x height). */ @@ -115,11 +105,6 @@ class TerrainRenderEntity { */ tiles_t tiles; - /** - * Time of the last update call. - */ - time::time_t last_update; - /** * Terrain texture paths used in \p tiles . */ @@ -129,10 +114,5 @@ class TerrainRenderEntity { * Terrain vertices (ingame coordinates). */ std::vector vertices; - - /** - * Mutex for protecting threaded access. - */ - std::shared_mutex mutex; }; } // namespace openage::renderer::terrain diff --git a/libopenage/renderer/stages/terrain/render_stage.cpp b/libopenage/renderer/stages/terrain/render_stage.cpp index 740fe260f6..01376d886b 100644 --- a/libopenage/renderer/stages/terrain/render_stage.cpp +++ b/libopenage/renderer/stages/terrain/render_stage.cpp @@ -48,7 +48,7 @@ std::shared_ptr TerrainRenderStage::get_render_pass() { return this->render_pass; } -void TerrainRenderStage::add_render_entity(const std::shared_ptr entity, +void TerrainRenderStage::add_render_entity(const std::shared_ptr entity, const util::Vector2s chunk_size, const coord::scene2_delta chunk_offset) { std::unique_lock lock{this->mutex}; diff --git a/libopenage/renderer/stages/terrain/render_stage.h b/libopenage/renderer/stages/terrain/render_stage.h index 40caf2b309..6066dc90aa 100644 --- a/libopenage/renderer/stages/terrain/render_stage.h +++ b/libopenage/renderer/stages/terrain/render_stage.h @@ -32,7 +32,7 @@ class AssetManager; } namespace terrain { -class TerrainRenderEntity; +class RenderEntity; class TerrainRenderMesh; class TerrainRenderModel; @@ -73,7 +73,7 @@ class TerrainRenderStage { * * @param render_entity New render entity. */ - void add_render_entity(const std::shared_ptr entity, + void add_render_entity(const std::shared_ptr entity, const util::Vector2s chunk_size, const coord::scene2_delta chunk_offset); @@ -119,7 +119,7 @@ class TerrainRenderStage { /** * Engine interface for updating terrain draw information. */ - std::shared_ptr render_entity; + std::shared_ptr render_entity; /** * 3D model of the terrain. diff --git a/libopenage/renderer/stages/world/object.cpp b/libopenage/renderer/stages/world/object.cpp index 0a707807ca..2396c94ed2 100644 --- a/libopenage/renderer/stages/world/object.cpp +++ b/libopenage/renderer/stages/world/object.cpp @@ -43,7 +43,7 @@ WorldObject::WorldObject(const std::shared_ptr &entity) { +void WorldObject::set_render_entity(const std::shared_ptr &entity) { this->render_entity = entity; this->fetch_updates(); } @@ -63,6 +63,9 @@ void WorldObject::fetch_updates(const time::time_t &time) { // Get data from render entity this->ref_id = this->render_entity->get_id(); + + // Thread-safe access to curves needs a lock on the render entity's mutex + auto read_lock = this->render_entity->get_read_lock(); this->position.sync(this->render_entity->get_position()); this->animation_info.sync(this->render_entity->get_animation_path(), std::function(const std::string &)>( @@ -79,6 +82,9 @@ void WorldObject::fetch_updates(const time::time_t &time) { this->last_update); this->angle.sync(this->render_entity->get_angle(), this->last_update); + // Unlock mutex of the render entity + read_lock.unlock(); + // Set self to changed so that world renderer can update the renderable this->changed = true; this->render_entity->clear_changed_flag(); diff --git a/libopenage/renderer/stages/world/object.h b/libopenage/renderer/stages/world/object.h index 1302733954..c5579f62a0 100644 --- a/libopenage/renderer/stages/world/object.h +++ b/libopenage/renderer/stages/world/object.h @@ -29,7 +29,7 @@ class Animation2dInfo; } // namespace resources namespace world { -class WorldRenderEntity; +class RenderEntity; /** * Stores the state of a renderable object in the World render stage. @@ -49,7 +49,7 @@ class WorldObject { * * @param entity New world render entity. */ - void set_render_entity(const std::shared_ptr &entity); + void set_render_entity(const std::shared_ptr &entity); /** * Fetch updates from the render entity. @@ -177,7 +177,7 @@ class WorldObject { * Entity that gets updates from the gamestate, e.g. the position and * requested animation data. */ - std::shared_ptr render_entity; + std::shared_ptr render_entity; /** * Reference ID for passing interaction with the graphic (e.g. mouse clicks) back to diff --git a/libopenage/renderer/stages/world/render_entity.cpp b/libopenage/renderer/stages/world/render_entity.cpp index 6909a6554a..7a8e145741 100644 --- a/libopenage/renderer/stages/world/render_entity.cpp +++ b/libopenage/renderer/stages/world/render_entity.cpp @@ -1,4 +1,4 @@ -// Copyright 2022-2023 the openage authors. See copying.md for legal info. +// Copyright 2022-2024 the openage authors. See copying.md for legal info. #include "render_entity.h" @@ -10,20 +10,19 @@ namespace openage::renderer::world { -WorldRenderEntity::WorldRenderEntity() : - changed{false}, +RenderEntity::RenderEntity() : + renderer::RenderEntity{}, ref_id{0}, position{nullptr, 0, "", nullptr, SCENE_ORIGIN}, angle{nullptr, 0, "", nullptr, 0}, - animation_path{nullptr, 0}, - last_update{0.0} { + animation_path{nullptr, 0} { } -void WorldRenderEntity::update(const uint32_t ref_id, - const curve::Continuous &position, - const curve::Segmented &angle, - const std::string animation_path, - const time::time_t time) { +void RenderEntity::update(const uint32_t ref_id, + const curve::Continuous &position, + const curve::Segmented &angle, + const std::string animation_path, + const time::time_t time) { std::unique_lock lock{this->mutex}; this->ref_id = ref_id; @@ -41,10 +40,10 @@ void WorldRenderEntity::update(const uint32_t ref_id, this->last_update = time; } -void WorldRenderEntity::update(const uint32_t ref_id, - const coord::phys3 position, - const std::string animation_path, - const time::time_t time) { +void RenderEntity::update(const uint32_t ref_id, + const coord::phys3 position, + const std::string animation_path, + const time::time_t time) { std::unique_lock lock{this->mutex}; this->ref_id = ref_id; @@ -54,46 +53,28 @@ void WorldRenderEntity::update(const uint32_t ref_id, this->last_update = time; } -uint32_t WorldRenderEntity::get_id() { +uint32_t RenderEntity::get_id() { std::shared_lock lock{this->mutex}; return this->ref_id; } -const curve::Continuous &WorldRenderEntity::get_position() { +const curve::Continuous &RenderEntity::get_position() { std::shared_lock lock{this->mutex}; return this->position; } -const curve::Segmented &WorldRenderEntity::get_angle() { +const curve::Segmented &RenderEntity::get_angle() { std::shared_lock lock{this->mutex}; return this->angle; } -const curve::Discrete &WorldRenderEntity::get_animation_path() { +const curve::Discrete &RenderEntity::get_animation_path() { std::shared_lock lock{this->mutex}; return this->animation_path; } -time::time_t WorldRenderEntity::get_update_time() { - std::shared_lock lock{this->mutex}; - - return this->last_update; -} - -bool WorldRenderEntity::is_changed() { - std::shared_lock lock{this->mutex}; - - return this->changed; -} - -void WorldRenderEntity::clear_changed_flag() { - std::unique_lock lock{this->mutex}; - - this->changed = false; -} - } // namespace openage::renderer::world diff --git a/libopenage/renderer/stages/world/render_entity.h b/libopenage/renderer/stages/world/render_entity.h index 7c56635f89..ed9011b8a4 100644 --- a/libopenage/renderer/stages/world/render_entity.h +++ b/libopenage/renderer/stages/world/render_entity.h @@ -3,18 +3,14 @@ #pragma once #include -#include -#include #include -#include - #include "coord/phys.h" #include "coord/scene.h" #include "curve/continuous.h" #include "curve/discrete.h" #include "curve/segmented.h" -#include "time/time.h" +#include "renderer/stages/render_entity.h" namespace openage::renderer::world { @@ -22,14 +18,16 @@ namespace openage::renderer::world { /** * Render entity for pushing updates to the World renderer. */ -class WorldRenderEntity { +class RenderEntity final : public renderer::RenderEntity { public: - WorldRenderEntity(); - ~WorldRenderEntity() = default; + RenderEntity(); + ~RenderEntity() = default; /** * Update the render entity with information from the gamestate. * + * Updating the render entity with this method is thread-safe. + * * @param ref_id Game entity ID. * @param position Position of the game entity inside the game world. * @param angle Angle of the game entity inside the game world. @@ -47,6 +45,8 @@ class WorldRenderEntity { * * Update the render entity with information from the gamestate. * + * Updating the render entity with this method is thread-safe. + * * @param ref_id Game entity ID. * @param position Position of the game entity inside the game world. * @param animation_path Path to the animation definition. @@ -60,6 +60,8 @@ class WorldRenderEntity { /** * Get the ID of the corresponding game entity. * + * Accessing the game entity ID is thread-safe. + * * @return Game entity ID. */ uint32_t get_id(); @@ -67,6 +69,9 @@ class WorldRenderEntity { /** * Get the position of the entity inside the game world. * + * Accessing the position curve REQUIRES a read lock on the render entity + * (using \p get_read_lock()) to ensure thread safety. + * * @return Position curve of the entity. */ const curve::Continuous &get_position(); @@ -74,6 +79,9 @@ class WorldRenderEntity { /** * Get the angle of the entity inside the game world. * + * Accessing the angle curve REQUIRES a read lock on the render entity + * (using \p get_read_lock()) to ensure thread safety. + * * @return Angle curve of the entity. */ const curve::Segmented &get_angle(); @@ -81,38 +89,14 @@ class WorldRenderEntity { /** * Get the animation definition path. * + * Accessing the animation path curve requires a read lock on the render entity + * (using \p get_read_lock()) to ensure thread safety. + * * @return Path to the animation definition file. */ const curve::Discrete &get_animation_path(); - /** - * Get the time of the last update. - * - * @return Time of last update. - */ - time::time_t get_update_time(); - - /** - * Check whether the render entity has received new updates from the - * gamestate. - * - * @return true if updates have been received, else false. - */ - bool is_changed(); - - /** - * Clear the update flag by setting it to false. - */ - void clear_changed_flag(); - private: - /** - * Flag for determining if the render entity has been updated by the - * corresponding gamestate entity. Set to true every time \p update() - * is called. - */ - bool changed; - /** * ID of the game entity in the gamestate. */ @@ -132,15 +116,5 @@ class WorldRenderEntity { * Path to the animation definition file. */ curve::Discrete animation_path; - - /** - * Time of the last update call. - */ - time::time_t last_update; - - /** - * Mutex for protecting threaded access. - */ - std::shared_mutex mutex; }; } // namespace openage::renderer::world diff --git a/libopenage/renderer/stages/world/render_stage.cpp b/libopenage/renderer/stages/world/render_stage.cpp index 0434f3cf07..d8d93279af 100644 --- a/libopenage/renderer/stages/world/render_stage.cpp +++ b/libopenage/renderer/stages/world/render_stage.cpp @@ -50,7 +50,7 @@ std::shared_ptr WorldRenderStage::get_render_pass() { return this->render_pass; } -void WorldRenderStage::add_render_entity(const std::shared_ptr entity) { +void WorldRenderStage::add_render_entity(const std::shared_ptr entity) { std::unique_lock lock{this->mutex}; auto world_object = std::make_shared(this->asset_manager); diff --git a/libopenage/renderer/stages/world/render_stage.h b/libopenage/renderer/stages/world/render_stage.h index e6ae39c094..f1256f3b57 100644 --- a/libopenage/renderer/stages/world/render_stage.h +++ b/libopenage/renderer/stages/world/render_stage.h @@ -31,7 +31,7 @@ class AssetManager; } namespace world { -class WorldRenderEntity; +class RenderEntity; class WorldObject; /** @@ -74,7 +74,7 @@ class WorldRenderStage { * * @param render_entity New render entity. */ - void add_render_entity(const std::shared_ptr entity); + void add_render_entity(const std::shared_ptr entity); /** * Update the render entities and render positions. diff --git a/libopenage/renderer/uniform_buffer.h b/libopenage/renderer/uniform_buffer.h index 85040a4976..c91edf1132 100644 --- a/libopenage/renderer/uniform_buffer.h +++ b/libopenage/renderer/uniform_buffer.h @@ -50,22 +50,22 @@ class UniformBuffer : public std::enable_shared_from_this { protected: virtual std::shared_ptr new_unif_in() = 0; - 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(UniformBufferInput &in, const char *, int32_t) = 0; + virtual void set_u32(UniformBufferInput &in, const char *, uint32_t) = 0; + virtual void set_f32(UniformBufferInput &in, const char *, float) = 0; + virtual void set_f64(UniformBufferInput &in, const char *, double) = 0; + virtual void set_bool(UniformBufferInput &in, const char *, bool) = 0; + virtual void set_v2f32(UniformBufferInput &in, const char *, Eigen::Vector2f const &) = 0; + virtual void set_v3f32(UniformBufferInput &in, const char *, Eigen::Vector3f const &) = 0; + virtual void set_v4f32(UniformBufferInput &in, const char *, Eigen::Vector4f const &) = 0; + virtual void set_v2i32(UniformBufferInput &in, const char *, Eigen::Vector2i const &) = 0; + virtual void set_v3i32(UniformBufferInput &in, const char *, Eigen::Vector3i const &) = 0; + virtual void set_v4i32(UniformBufferInput &in, const char *, Eigen::Vector4i const &) = 0; + virtual void set_v2ui32(UniformBufferInput &in, const char *, Eigen::Vector2 const &) = 0; + virtual void set_v3ui32(UniformBufferInput &in, const char *, Eigen::Vector3 const &) = 0; + virtual void set_v4ui32(UniformBufferInput &in, const char *, Eigen::Vector4 const &) = 0; + virtual void set_m4f32(UniformBufferInput &in, const char *, Eigen::Matrix4f const &) = 0; + virtual void set_tex(UniformBufferInput &in, const char *, std::shared_ptr const &) = 0; }; } // namespace openage::renderer diff --git a/libopenage/renderer/uniform_input.cpp b/libopenage/renderer/uniform_input.cpp index ee42202faf..b3abbe7ba8 100644 --- a/libopenage/renderer/uniform_input.cpp +++ b/libopenage/renderer/uniform_input.cpp @@ -157,71 +157,71 @@ UniformBufferInput::UniformBufferInput(std::shared_ptr const &buf void UniformBufferInput::update() {} void UniformBufferInput::update(const char *unif, int32_t val) { - this->buffer->set_i32(this->shared_from_this(), unif, val); + this->buffer->set_i32(*this, unif, val); } void UniformBufferInput::update(const char *unif, uint32_t val) { - this->buffer->set_u32(this->shared_from_this(), unif, val); + this->buffer->set_u32(*this, unif, val); } void UniformBufferInput::update(const char *unif, float val) { - this->buffer->set_f32(this->shared_from_this(), unif, val); + this->buffer->set_f32(*this, unif, val); } void UniformBufferInput::update(const char *unif, double val) { - this->buffer->set_f64(this->shared_from_this(), unif, val); + this->buffer->set_f64(*this, unif, val); } void UniformBufferInput::update(const char *unif, bool val) { - this->buffer->set_bool(this->shared_from_this(), unif, val); + this->buffer->set_bool(*this, unif, val); } void UniformBufferInput::update(const char *unif, Eigen::Vector2f const &val) { - this->buffer->set_v2f32(this->shared_from_this(), unif, val); + this->buffer->set_v2f32(*this, unif, val); } void UniformBufferInput::update(const char *unif, Eigen::Vector3f const &val) { - this->buffer->set_v3f32(this->shared_from_this(), unif, val); + this->buffer->set_v3f32(*this, unif, val); } void UniformBufferInput::update(const char *unif, Eigen::Vector4f const &val) { - this->buffer->set_v4f32(this->shared_from_this(), unif, val); + this->buffer->set_v4f32(*this, unif, val); } void UniformBufferInput::update(const char *unif, Eigen::Vector2i const &val) { - this->buffer->set_v2i32(this->shared_from_this(), unif, val); + this->buffer->set_v2i32(*this, unif, val); } void UniformBufferInput::update(const char *unif, Eigen::Vector3i const &val) { - this->buffer->set_v3i32(this->shared_from_this(), unif, val); + this->buffer->set_v3i32(*this, unif, val); } void UniformBufferInput::update(const char *unif, Eigen::Vector4i const &val) { - this->buffer->set_v4i32(this->shared_from_this(), unif, val); + this->buffer->set_v4i32(*this, unif, val); } void UniformBufferInput::update(const char *unif, Eigen::Vector2 const &val) { - this->buffer->set_v2ui32(this->shared_from_this(), unif, val); + this->buffer->set_v2ui32(*this, unif, val); } void UniformBufferInput::update(const char *unif, Eigen::Vector3 const &val) { - this->buffer->set_v3ui32(this->shared_from_this(), unif, val); + this->buffer->set_v3ui32(*this, unif, val); } void UniformBufferInput::update(const char *unif, Eigen::Vector4 const &val) { - this->buffer->set_v4ui32(this->shared_from_this(), unif, val); + this->buffer->set_v4ui32(*this, unif, val); } void UniformBufferInput::update(const char *unif, std::shared_ptr const &val) { - this->buffer->set_tex(this->shared_from_this(), unif, val); + this->buffer->set_tex(*this, unif, val); } void UniformBufferInput::update(const char *unif, std::shared_ptr &val) { - this->buffer->set_tex(this->shared_from_this(), unif, val); + this->buffer->set_tex(*this, unif, val); } void UniformBufferInput::update(const char *unif, Eigen::Matrix4f const &val) { - this->buffer->set_m4f32(this->shared_from_this(), unif, val); + this->buffer->set_m4f32(*this, unif, val); } } // namespace openage::renderer