Skip to content

Commit 1b63182

Browse files
committed
Merge branch 'develop'
2 parents 5232451 + 01aadc6 commit 1b63182

12 files changed

+204
-122
lines changed

doc/source/doxygen-docs/changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
\page changelog Change Log
22

3+
# Version 2.14.15: Released Sep 29th, 2025
4+
- BUG FIXES:
5+
- Fix regression in OpenGL application crashing after last update.
6+
37
# Version 2.14.14: Released Sep 27th, 2025
48
- BUG FIXES:
59
- Fix missing backported fix to build mrpt::lockHelper() on modern gcc

libs/opengl/include/mrpt/opengl/CRenderizableShaderPoints.h

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,8 @@ class CRenderizableShaderPoints : public virtual CRenderizable
4141

4242
public:
4343
CRenderizableShaderPoints()
44-
{
45-
m_vertexBuffer.data = std::make_unique<Buffer>();
46-
m_colorBuffer.data = std::make_unique<Buffer>();
47-
m_vao.data = std::make_unique<VertexArrayObject>();
44+
{ // Initialize GlState
45+
auto gh = gls();
4846
}
4947

5048
virtual ~CRenderizableShaderPoints() override;
@@ -76,9 +74,10 @@ class CRenderizableShaderPoints : public virtual CRenderizable
7674
// See base docs
7775
void freeOpenGLResources() override
7876
{
79-
(*m_vertexBuffer)->destroy();
80-
(*m_colorBuffer)->destroy();
81-
(*m_vao)->destroy();
77+
auto gh = gls();
78+
gh.state.vertexBuffer->destroy();
79+
gh.state.colorBuffer->destroy();
80+
gh.state.vao->destroy();
8281
}
8382

8483
/** @name Raw access to point shader buffer data
@@ -107,9 +106,25 @@ class CRenderizableShaderPoints : public virtual CRenderizable
107106
void params_deserialize(mrpt::serialization::CArchive& in);
108107

109108
private:
110-
mutable mrpt::containers::NonCopiableData<std::unique_ptr<Buffer>> m_vertexBuffer;
111-
mutable mrpt::containers::NonCopiableData<std::unique_ptr<Buffer>> m_colorBuffer;
112-
mutable mrpt::containers::NonCopiableData<std::unique_ptr<VertexArrayObject>> m_vao;
109+
struct GlState
110+
{
111+
std::unique_ptr<Buffer> vertexBuffer = std::make_unique<Buffer>();
112+
std::unique_ptr<Buffer> colorBuffer = std::make_unique<Buffer>();
113+
std::unique_ptr<VertexArrayObject> vao = std::make_unique<VertexArrayObject>();
114+
};
115+
mutable mrpt::containers::NonCopiableData<GlState> m_gls;
116+
mutable mrpt::containers::NonCopiableData<std::mutex> m_glsMtx;
117+
struct GlsHandle
118+
{
119+
GlState& state;
120+
std::unique_lock<std::mutex> lock;
121+
};
122+
123+
[[nodiscard]] GlsHandle gls() const
124+
{
125+
std::unique_lock<std::mutex> lock(m_glsMtx.data);
126+
return {m_gls.data, std::move(lock)};
127+
}
113128
};
114129

115130
} // namespace mrpt::opengl

libs/opengl/include/mrpt/opengl/CRenderizableShaderText.h

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,10 @@ class CRenderizableShaderText : public virtual CRenderizable
3030

3131
public:
3232
CRenderizableShaderText()
33-
{
34-
// This ensures the object's vptrs are safely established.
35-
m_trianglesBuffer.data = std::make_unique<mrpt::opengl::Buffer>();
36-
m_linesVertexBuffer.data = std::make_unique<mrpt::opengl::Buffer>();
37-
m_linesColorBuffer.data = std::make_unique<mrpt::opengl::Buffer>();
38-
m_vao.data = std::make_unique<mrpt::opengl::VertexArrayObject>();
33+
{ // Initialize GlState
34+
auto gh = gls();
3935
}
36+
4037
virtual ~CRenderizableShaderText() override;
4138

4239
virtual shader_list_t requiredShaders() const override { return {DefaultShaderID::TEXT}; }
@@ -50,10 +47,11 @@ class CRenderizableShaderText : public virtual CRenderizable
5047
// See base docs
5148
void freeOpenGLResources() override
5249
{
53-
(*m_trianglesBuffer)->destroy();
54-
(*m_linesVertexBuffer)->destroy();
55-
(*m_linesColorBuffer)->destroy();
56-
(*m_vao)->destroy();
50+
auto gh = gls();
51+
gh.state.trianglesBuffer->destroy();
52+
gh.state.linesVertexBuffer->destroy();
53+
gh.state.linesColorBuffer->destroy();
54+
gh.state.vao->destroy();
5755
}
5856

5957
protected:
@@ -66,10 +64,26 @@ class CRenderizableShaderText : public virtual CRenderizable
6664
mutable mrpt::containers::NonCopiableData<std::shared_mutex> m_textDataMtx;
6765

6866
private:
69-
mutable mrpt::containers::NonCopiableData<std::unique_ptr<Buffer>> m_trianglesBuffer;
70-
mutable mrpt::containers::NonCopiableData<std::unique_ptr<Buffer>> m_linesVertexBuffer;
71-
mutable mrpt::containers::NonCopiableData<std::unique_ptr<Buffer>> m_linesColorBuffer;
72-
mutable mrpt::containers::NonCopiableData<std::unique_ptr<VertexArrayObject>> m_vao;
67+
struct GlState
68+
{
69+
std::unique_ptr<Buffer> trianglesBuffer = std::make_unique<Buffer>();
70+
std::unique_ptr<Buffer> linesVertexBuffer = std::make_unique<Buffer>();
71+
std::unique_ptr<Buffer> linesColorBuffer = std::make_unique<Buffer>();
72+
std::unique_ptr<VertexArrayObject> vao = std::make_unique<VertexArrayObject>();
73+
};
74+
mutable mrpt::containers::NonCopiableData<GlState> m_gls;
75+
mutable mrpt::containers::NonCopiableData<std::mutex> m_glsMtx;
76+
struct GlsHandle
77+
{
78+
GlState& state;
79+
std::unique_lock<std::mutex> lock;
80+
};
81+
82+
[[nodiscard]] GlsHandle gls() const
83+
{
84+
std::unique_lock<std::mutex> lock(m_glsMtx.data);
85+
return {m_gls.data, std::move(lock)};
86+
}
7387
};
7488

7589
} // namespace mrpt::opengl

libs/opengl/include/mrpt/opengl/CRenderizableShaderTexturedTriangles.h

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ class CRenderizableShaderTexturedTriangles : public virtual CRenderizable
3131

3232
public:
3333
CRenderizableShaderTexturedTriangles()
34-
{
35-
m_vbo.data = std::make_unique<Buffer>();
36-
m_vao.data = std::make_unique<VertexArrayObject>();
34+
{ // Initialize GlState
35+
auto gh = gls();
3736
}
37+
3838
virtual ~CRenderizableShaderTexturedTriangles() override;
3939

4040
virtual shader_list_t requiredShaders() const override
@@ -53,8 +53,9 @@ class CRenderizableShaderTexturedTriangles : public virtual CRenderizable
5353
// See base docs
5454
void freeOpenGLResources() override
5555
{
56-
(*m_vbo)->destroy();
57-
(*m_vao)->destroy();
56+
auto gh = gls();
57+
gh.state.vbo->destroy();
58+
gh.state.vao->destroy();
5859
}
5960

6061
/** Assigns a texture and a transparency image, and enables transparency (If
@@ -138,8 +139,24 @@ class CRenderizableShaderTexturedTriangles : public virtual CRenderizable
138139
bool m_textureInterpolate = false;
139140
bool m_textureUseMipMaps = true;
140141

141-
mutable mrpt::containers::NonCopiableData<std::unique_ptr<Buffer>> m_vbo;
142-
mutable mrpt::containers::NonCopiableData<std::unique_ptr<VertexArrayObject>> m_vao;
142+
struct GlState
143+
{
144+
std::unique_ptr<Buffer> vbo = std::make_unique<Buffer>();
145+
std::unique_ptr<VertexArrayObject> vao = std::make_unique<VertexArrayObject>();
146+
};
147+
mutable mrpt::containers::NonCopiableData<GlState> m_gls;
148+
mutable mrpt::containers::NonCopiableData<std::mutex> m_glsMtx;
149+
struct GlsHandle
150+
{
151+
GlState& state;
152+
std::unique_lock<std::mutex> lock;
153+
};
154+
155+
[[nodiscard]] GlsHandle gls() const
156+
{
157+
std::unique_lock<std::mutex> lock(m_glsMtx.data);
158+
return {m_gls.data, std::move(lock)};
159+
}
143160
};
144161

145162
} // namespace mrpt::opengl

libs/opengl/include/mrpt/opengl/CRenderizableShaderTriangles.h

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,8 @@ class CRenderizableShaderTriangles : public virtual CRenderizable
3030

3131
public:
3232
CRenderizableShaderTriangles()
33-
{
34-
m_trianglesBuffer.data = std::make_unique<Buffer>();
35-
m_vao.data = std::make_unique<VertexArrayObject>();
33+
{ // Initialize GlState
34+
auto gh = gls();
3635
}
3736

3837
virtual ~CRenderizableShaderTriangles() override;
@@ -51,8 +50,9 @@ class CRenderizableShaderTriangles : public virtual CRenderizable
5150
// See base docs
5251
void freeOpenGLResources() override
5352
{
54-
(*m_trianglesBuffer)->destroy();
55-
(*m_vao)->destroy();
53+
auto gh = gls();
54+
gh.state.trianglesBuffer->destroy();
55+
gh.state.vao->destroy();
5656
}
5757

5858
bool isLightEnabled() const { return m_enableLight; }
@@ -84,11 +84,27 @@ class CRenderizableShaderTriangles : public virtual CRenderizable
8484
void params_deserialize(mrpt::serialization::CArchive& in);
8585

8686
private:
87-
mutable mrpt::containers::NonCopiableData<std::unique_ptr<Buffer>> m_trianglesBuffer;
88-
mutable mrpt::containers::NonCopiableData<std::unique_ptr<VertexArrayObject>> m_vao;
89-
9087
bool m_enableLight = true;
9188
TCullFace m_cullface = TCullFace::NONE;
89+
90+
struct GlState
91+
{
92+
std::unique_ptr<Buffer> trianglesBuffer = std::make_unique<Buffer>();
93+
std::unique_ptr<VertexArrayObject> vao = std::make_unique<VertexArrayObject>();
94+
};
95+
mutable mrpt::containers::NonCopiableData<GlState> m_gls;
96+
mutable mrpt::containers::NonCopiableData<std::mutex> m_glsMtx;
97+
struct GlsHandle
98+
{
99+
GlState& state;
100+
std::unique_lock<std::mutex> lock;
101+
};
102+
103+
[[nodiscard]] GlsHandle gls() const
104+
{
105+
std::unique_lock<std::mutex> lock(m_glsMtx.data);
106+
return {m_gls.data, std::move(lock)};
107+
}
92108
};
93109

94110
} // namespace mrpt::opengl

libs/opengl/include/mrpt/opengl/CRenderizableShaderWireFrame.h

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,13 @@ class CRenderizableShaderWireFrame : public virtual CRenderizable
2929

3030
public:
3131
CRenderizableShaderWireFrame()
32-
{
33-
// The base class vptrs are now safely initialized! (prevents memory layout bug)
34-
m_vertexBuffer.data = std::make_unique<Buffer>();
35-
m_colorBuffer.data = std::make_unique<Buffer>();
36-
m_vao.data = std::make_unique<VertexArrayObject>();
32+
{ // Initialize GlState
33+
auto gh = gls();
3734
}
3835

39-
virtual ~CRenderizableShaderWireFrame();
36+
~CRenderizableShaderWireFrame() override;
4037

41-
virtual shader_list_t requiredShaders() const override { return {DefaultShaderID::WIREFRAME}; }
38+
shader_list_t requiredShaders() const override { return {DefaultShaderID::WIREFRAME}; }
4239
void render(const RenderContext& rc) const override;
4340
void renderUpdateBuffers() const override;
4441

@@ -62,9 +59,10 @@ class CRenderizableShaderWireFrame : public virtual CRenderizable
6259
// See base docs
6360
void freeOpenGLResources() override
6461
{
65-
(*m_vertexBuffer)->destroy();
66-
(*m_colorBuffer)->destroy();
67-
(*m_vao)->destroy();
62+
auto gh = gls();
63+
gh.state.vertexBuffer->destroy();
64+
gh.state.colorBuffer->destroy();
65+
gh.state.vao->destroy();
6866
}
6967

7068
/** @name Raw access to wireframe shader buffer data
@@ -88,9 +86,25 @@ class CRenderizableShaderWireFrame : public virtual CRenderizable
8886
const mrpt::math::TBoundingBox wireframeVerticesBoundingBox() const;
8987

9088
private:
91-
mutable mrpt::containers::NonCopiableData<std::unique_ptr<Buffer>> m_vertexBuffer;
92-
mutable mrpt::containers::NonCopiableData<std::unique_ptr<Buffer>> m_colorBuffer;
93-
mutable mrpt::containers::NonCopiableData<std::unique_ptr<VertexArrayObject>> m_vao;
89+
struct GlState
90+
{
91+
std::unique_ptr<Buffer> vertexBuffer = std::make_unique<Buffer>();
92+
std::unique_ptr<Buffer> colorBuffer = std::make_unique<Buffer>();
93+
std::unique_ptr<VertexArrayObject> vao = std::make_unique<VertexArrayObject>();
94+
};
95+
mutable mrpt::containers::NonCopiableData<GlState> m_gls;
96+
mutable mrpt::containers::NonCopiableData<std::mutex> m_glsMtx;
97+
struct GlsHandle
98+
{
99+
GlState& state;
100+
std::unique_lock<std::mutex> lock;
101+
};
102+
103+
[[nodiscard]] GlsHandle gls() const
104+
{
105+
std::unique_lock<std::mutex> lock(m_glsMtx.data);
106+
return {m_gls.data, std::move(lock)};
107+
}
94108
};
95109

96110
} // namespace mrpt::opengl

libs/opengl/src/CRenderizableShaderPoints.cpp

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,22 @@ void CRenderizableShaderPoints::renderUpdateBuffers() const
3030
const_cast<CRenderizableShaderPoints&>(*this).onUpdateBuffers_Points();
3131

3232
std::shared_lock<std::shared_mutex> wfReadLock(CRenderizableShaderPoints::m_pointsMtx.data);
33+
auto gh = gls();
3334

3435
// Define OpenGL buffers:
35-
(*m_vertexBuffer)->createOnce();
36-
(*m_vertexBuffer)->bind();
37-
(*m_vertexBuffer)
38-
->allocate(
39-
m_vertex_buffer_data.data(),
40-
sizeof(m_vertex_buffer_data[0]) * m_vertex_buffer_data.size());
36+
gh.state.vertexBuffer->createOnce();
37+
gh.state.vertexBuffer->bind();
38+
gh.state.vertexBuffer->allocate(
39+
m_vertex_buffer_data.data(), sizeof(m_vertex_buffer_data[0]) * m_vertex_buffer_data.size());
4140

4241
// color buffer:
43-
(*m_colorBuffer)->createOnce();
44-
(*m_colorBuffer)->bind();
45-
(*m_colorBuffer)
46-
->allocate(
47-
m_color_buffer_data.data(), sizeof(m_color_buffer_data[0]) * m_color_buffer_data.size());
42+
gh.state.colorBuffer->createOnce();
43+
gh.state.colorBuffer->bind();
44+
gh.state.colorBuffer->allocate(
45+
m_color_buffer_data.data(), sizeof(m_color_buffer_data[0]) * m_color_buffer_data.size());
4846

4947
// VAO: required to use glEnableVertexAttribArray()
50-
(*m_vao)->createOnce();
48+
gh.state.vao->createOnce();
5149
#endif
5250
}
5351

@@ -59,6 +57,7 @@ void CRenderizableShaderPoints::render(const RenderContext& rc) const
5957
if (rc.state->is1stShadowMapPass) return;
6058

6159
std::shared_lock<std::shared_mutex> wfReadLock(CRenderizableShaderPoints::m_pointsMtx.data);
60+
auto gh = gls();
6261

6362
// Point size as uniform:
6463
glUniform1f(rc.shader->uniformId("vertexPointSize"), m_pointSize);
@@ -74,9 +73,9 @@ void CRenderizableShaderPoints::render(const RenderContext& rc) const
7473
if (rc.shader->hasAttribute("position"))
7574
{
7675
attr_position = rc.shader->attributeId("position");
77-
(*m_vao)->bind();
76+
gh.state.vao->bind();
7877
glEnableVertexAttribArray(*attr_position);
79-
(*m_vertexBuffer)->bind();
78+
gh.state.vertexBuffer->bind();
8079
glVertexAttribPointer(
8180
*attr_position, /* attribute */
8281
3, /* size */
@@ -94,7 +93,7 @@ void CRenderizableShaderPoints::render(const RenderContext& rc) const
9493
{
9594
attr_color = rc.shader->attributeId("vertexColor");
9695
glEnableVertexAttribArray(*attr_color);
97-
(*m_colorBuffer)->bind();
96+
gh.state.colorBuffer->bind();
9897
glVertexAttribPointer(
9998
*attr_color, /* attribute */
10099
4, /* size */

0 commit comments

Comments
 (0)