Skip to content

Commit 34c13d2

Browse files
committed
renderer: Make fetching from render entity more reliable.
1 parent 71353f2 commit 34c13d2

File tree

13 files changed

+90
-98
lines changed

13 files changed

+90
-98
lines changed

libopenage/curve/keyframe_container.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -607,18 +607,18 @@ template <typename T>
607607
typename KeyframeContainer<T>::elem_ptr
608608
KeyframeContainer<T>::sync(const KeyframeContainer<T> &other,
609609
const time::time_t &start) {
610-
// Delete elements after start time
610+
// Delete elements from this container after start time
611611
elem_ptr at = this->last_before(start, this->container.size());
612612
at = this->erase_after(at);
613613

614-
auto at_other = 1; // always skip the first element (because it's the default value)
614+
// Find the last element before the start time in the other container
615+
elem_ptr at_other = other.last_before(start, other.size());
616+
++at_other; // move one element forward so that at_other.time() >= start
615617

616618
// Copy all elements from other with time >= start
617-
for (size_t i = at_other; i < other.size(); i++) {
618-
if (other.get(i).time() >= start) {
619-
at = this->insert_after(other.get(i), at);
620-
}
621-
}
619+
this->container.insert(this->container.end(),
620+
other.container.begin() + at_other,
621+
other.container.end());
622622

623623
return this->container.size();
624624
}
@@ -634,13 +634,14 @@ KeyframeContainer<T>::sync(const KeyframeContainer<O> &other,
634634
elem_ptr at = this->last_before(start, this->container.size());
635635
at = this->erase_after(at);
636636

637-
auto at_other = 1; // always skip the first element (because it's the default value)
637+
// Find the last element before the start time in the other container
638+
elem_ptr at_other = other.last_before(start, other.size());
639+
++at_other; // move one element forward so that at_other.time() >= start
638640

639641
// Copy all elements from other with time >= start
640642
for (size_t i = at_other; i < other.size(); i++) {
641-
if (other.get(i).time() >= start) {
642-
at = this->insert_after(keyframe_t(other.get(i).time(), converter(other.get(i).val())), at);
643-
}
643+
auto &elem = other.get(i);
644+
this->container.emplace_back(elem.time(), converter(elem.val()));
644645
}
645646

646647
return this->container.size();

libopenage/gamestate/system/idle.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2023-2023 the openage authors. See copying.md for legal info.
1+
// Copyright 2023-2024 the openage authors. See copying.md for legal info.
22

33
#include "idle.h"
44

libopenage/renderer/stages/hud/object.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,17 @@ void HudDragObject::fetch_updates(const time::time_t &time) {
3636
return;
3737
}
3838

39-
// Get data from render entity
40-
this->drag_start = this->render_entity->get_drag_start();
41-
4239
// Thread-safe access to curves needs a lock on the render entity's mutex
4340
auto read_lock = this->render_entity->get_read_lock();
4441

45-
this->drag_pos.sync(this->render_entity->get_drag_pos() /* , this->last_update */);
42+
// Get data from render entity
43+
this->drag_start = this->render_entity->get_drag_start();
4644

47-
// Unlock the render entity mutex
48-
read_lock.unlock();
45+
this->drag_pos.sync(this->render_entity->get_drag_pos() /* , this->last_update */);
4946

5047
// Set self to changed so that world renderer can update the renderable
5148
this->changed = true;
52-
this->render_entity->clear_changed_flag();
49+
this->render_entity->fetch_done();
5350
this->last_update = time;
5451
}
5552

libopenage/renderer/stages/hud/render_entity.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,15 @@ void DragRenderEntity::update(const coord::input drag_pos,
2020
this->drag_pos.set_insert(time, drag_pos);
2121

2222
this->last_update = time;
23+
this->fetch_time = time;
2324
this->changed = true;
2425
}
2526

2627
const curve::Continuous<coord::input> &DragRenderEntity::get_drag_pos() {
27-
std::shared_lock lock{this->mutex};
28-
2928
return this->drag_pos;
3029
}
3130

3231
const coord::input DragRenderEntity::get_drag_start() {
33-
std::shared_lock lock{this->mutex};
34-
3532
return this->drag_start;
3633
}
3734

libopenage/renderer/stages/hud/render_entity.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,13 @@ class DragRenderEntity final : public renderer::RenderEntity {
3939
/**
4040
* Get the position of the dragged corner.
4141
*
42-
* Accessing the drag position curve REQUIRES a read lock on the render entity
43-
* (using \p get_read_lock()) to ensure thread safety.
44-
*
4542
* @return Coordinates of the dragged corner.
4643
*/
4744
const curve::Continuous<coord::input> &get_drag_pos();
4845

4946
/**
5047
* Get the position of the start corner.
5148
*
52-
* Accessing the drag start is thread-safe.
53-
*
5449
* @return Coordinates of the start corner.
5550
*/
5651
const coord::input get_drag_start();

libopenage/renderer/stages/render_entity.cpp

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,17 @@
22

33
#include "render_entity.h"
44

5-
#include <mutex>
6-
75

86
namespace openage::renderer {
97

108
RenderEntity::RenderEntity() :
119
changed{false},
12-
last_update{time::time_t::zero()} {
10+
last_update{time::TIME_ZERO},
11+
fetch_time{time::TIME_MAX} {
1312
}
1413

15-
time::time_t RenderEntity::get_update_time() {
16-
std::shared_lock lock{this->mutex};
17-
18-
return this->last_update;
14+
time::time_t RenderEntity::get_fetch_time() {
15+
return this->fetch_time;
1916
}
2017

2118
bool RenderEntity::is_changed() {
@@ -24,14 +21,13 @@ bool RenderEntity::is_changed() {
2421
return this->changed;
2522
}
2623

27-
void RenderEntity::clear_changed_flag() {
28-
std::unique_lock lock{this->mutex};
29-
24+
void RenderEntity::fetch_done() {
3025
this->changed = false;
26+
this->fetch_time = time::TIME_MAX;
3127
}
3228

33-
std::shared_lock<std::shared_mutex> RenderEntity::get_read_lock() {
34-
return std::shared_lock{this->mutex};
29+
std::unique_lock<std::shared_mutex> RenderEntity::get_read_lock() {
30+
return std::unique_lock{this->mutex};
3531
}
3632

3733
} // namespace openage::renderer

libopenage/renderer/stages/render_entity.h

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,47 @@ namespace openage::renderer {
1515
/**
1616
* Interface for render entities that allow pushing updates from game simulation
1717
* to renderer.
18+
*
19+
* Accessing the render entity from the renderer thread REQUIRES a
20+
* read lock on the render entity (using \p get_read_lock()) to ensure
21+
* thread safety.
1822
*/
1923
class RenderEntity {
2024
public:
2125
~RenderEntity() = default;
2226

2327
/**
24-
* Get the time of the last update.
28+
* Get the earliest time for which updates are available.
29+
*
30+
* Render objects should synchronize their state with the render entity
31+
* from this time onwards.
2532
*
2633
* Accessing the update time is thread-safe.
2734
*
2835
* @return Time of last update.
2936
*/
30-
time::time_t get_update_time();
37+
time::time_t get_fetch_time();
3138

3239
/**
3340
* Check whether the render entity has received new updates from the
3441
* gamestate.
3542
*
43+
* Accessing the change flag is thread-safe.
44+
*
3645
* @return true if updates have been received, else false.
3746
*/
3847
bool is_changed();
3948

4049
/**
41-
* Clear the update flag by setting it to false.
50+
* Indicate to this entity that its updates have been processed and transfered to the
51+
* render object.
52+
*
53+
* - Clear the update flag by setting it to false.
54+
* - Sets the fetch time to \p time::MAX_TIME.
55+
*
56+
* Accessing this method is thread-safe.
4257
*/
43-
void clear_changed_flag();
58+
void fetch_done();
4459

4560
/**
4661
* Get a shared lock for thread-safe reading from the render entity.
@@ -49,7 +64,7 @@ class RenderEntity {
4964
*
5065
* @return Lock for the render entity.
5166
*/
52-
std::shared_lock<std::shared_mutex> get_read_lock();
67+
std::unique_lock<std::shared_mutex> get_read_lock();
5368

5469
protected:
5570
/**
@@ -71,10 +86,17 @@ class RenderEntity {
7186
bool changed;
7287

7388
/**
74-
* Time of the last update call.
89+
* Time of the last update.
7590
*/
7691
time::time_t last_update;
7792

93+
/**
94+
* Earliest time for which updates have been received.
95+
*
96+
* \p time::TIME_MAX indicates that no updates are available.
97+
*/
98+
time::time_t fetch_time;
99+
78100
/**
79101
* Mutex for protecting threaded access.
80102
*/

libopenage/renderer/stages/terrain/chunk.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ void TerrainChunk::fetch_updates(const time::time_t & /* time */) {
3232
return;
3333
}
3434

35+
// Thread-safe access to data needs a lock on the render entity's mutex
36+
auto read_lock = this->render_entity->get_read_lock();
37+
3538
// Get the terrain data from the render entity
3639
auto terrain_size = this->render_entity->get_size();
3740
auto terrain_paths = this->render_entity->get_terrain_paths();
@@ -54,7 +57,7 @@ void TerrainChunk::fetch_updates(const time::time_t & /* time */) {
5457
// this->meshes.push_back(new_mesh);
5558

5659
// Indicate to the render entity that its updates have been processed.
57-
this->render_entity->clear_changed_flag();
60+
this->render_entity->fetch_done();
5861
}
5962

6063
void TerrainChunk::update_uniforms(const time::time_t &time) {

libopenage/renderer/stages/terrain/render_entity.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ void RenderEntity::update_tile(const util::Vector2s size,
4242

4343
// update the last update time
4444
this->last_update = time;
45+
this->fetch_time = time;
4546

4647
// update the terrain paths
4748
this->terrain_paths.insert(terrain_path);
@@ -94,7 +95,7 @@ void RenderEntity::update(const util::Vector2s size,
9495
this->tiles = tiles;
9596

9697
// update the last update time
97-
this->last_update = time;
98+
this->fetch_time = time;
9899

99100
// update the terrain paths
100101
this->terrain_paths.clear();
@@ -106,26 +107,18 @@ void RenderEntity::update(const util::Vector2s size,
106107
}
107108

108109
const std::vector<coord::scene3> RenderEntity::get_vertices() {
109-
std::shared_lock lock{this->mutex};
110-
111110
return this->vertices;
112111
}
113112

114113
const RenderEntity::tiles_t RenderEntity::get_tiles() {
115-
std::shared_lock lock{this->mutex};
116-
117114
return this->tiles;
118115
}
119116

120117
const std::unordered_set<std::string> RenderEntity::get_terrain_paths() {
121-
std::shared_lock lock{this->mutex};
122-
123118
return this->terrain_paths;
124119
}
125120

126121
const util::Vector2s RenderEntity::get_size() {
127-
std::shared_lock lock{this->mutex};
128-
129122
return this->size;
130123
}
131124

libopenage/renderer/stages/terrain/render_entity.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,36 +61,28 @@ class RenderEntity final : public renderer::RenderEntity {
6161
/**
6262
* Get the vertices of the terrain.
6363
*
64-
* Accessing the terrain vertices is thread-safe.
65-
*
6664
* @return Vector of vertex coordinates.
6765
*/
6866
const std::vector<coord::scene3> get_vertices();
6967

7068
/**
7169
* Get the tiles of the terrain.
7270
*
73-
* Accessing the terrain tiles is thread-safe.
74-
*
7571
* @return Terrain tiles.
7672
*/
7773
const tiles_t get_tiles();
7874

7975
/**
8076
* Get the terrain paths used in the terrain.
8177
*
82-
* Accessing the terrain paths is thread-safe.
83-
*
8478
* @return Terrain paths.
8579
*/
8680
const std::unordered_set<std::string> get_terrain_paths();
8781

8882
/**
8983
* Get the number of vertices on each side of the terrain.
9084
*
91-
* Accessing the vertices size is thread-safe.
92-
*
93-
* @return Vector with width as first element and height as second element.
85+
* @return Number of vertices on each side (width x height).
9486
*/
9587
const util::Vector2s get_size();
9688

0 commit comments

Comments
 (0)