Skip to content

Commit d9b6c43

Browse files
committed
FIX: OpenGL crashes under specific build flags
1 parent 567f2d0 commit d9b6c43

16 files changed

+158
-99
lines changed

doc/source/doxygen-docs/changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# Version 2.14.14: UNRELEASED
44
- BUG FIXES:
55
- Fix missing backported fix to build mrpt::lockHelper() on modern gcc
6+
- Fix OpenGL crashes under specific build flags: OpenGL Buffers and VBO changed so they are initialized after constructor.
67

78
# Version 2.14.13: Released Sep 27th, 2025
89
- Changes in libraries:

libs/containers/include/mrpt/containers/NonCopiableData.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,20 @@ class NonCopiableData
3030

3131
T data;
3232

33+
NonCopiableData& operator=(const T& value)
34+
{
35+
data = value;
36+
return *this;
37+
}
38+
39+
NonCopiableData(T&& value) : data(std::move(value)) {}
40+
NonCopiableData(const T& value) : data(value) {}
41+
42+
T& operator*() { return data; }
43+
const T& operator*() const { return data; }
44+
T* operator->() { return &data; }
45+
const T* operator->() const { return &data; }
46+
3347
NonCopiableData(const NonCopiableData&) {}
3448
NonCopiableData& operator=(const NonCopiableData&) { return *this; }
3549

libs/core/include/mrpt/core/lock_helper.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class LockHelper
2222
using Tnc = std::remove_const_t<T>;
2323

2424
public:
25-
LockHelper(const Tnc* l) : l_{const_cast<Tnc*>(l_)} { l_->lock(); }
25+
LockHelper(const Tnc* l) : l_{const_cast<Tnc*>(l)} { l_->lock(); }
2626
~LockHelper()
2727
{
2828
if (l_) l_->unlock();

libs/nav/include/mrpt/nav/planners/impl_renderMoveTree.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ void PlannerTPS_VirtualBase::renderMoveTree(
136136
// The starting pose vehicle shape must be inserted independently, because
137137
// the rest are edges and we draw the END pose of each edge:
138138
{
139-
mrpt::opengl::CSetOfLines::Ptr vehShape(new mrpt::opengl::CSetOfLines(*gl_veh_shape));
139+
auto vehShape = std::make_shared<mrpt::opengl::CSetOfLines>(*gl_veh_shape);
140140
mrpt::poses::CPose3D shapePose(mrpt::math::TPose3D(pi.start_pose));
141141
shapePose.z_incr(options.vehicle_shape_z);
142142
vehShape->setPose(shapePose);

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

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,13 @@ class CRenderizableShaderPoints : public virtual CRenderizable
4040
DEFINE_VIRTUAL_SERIALIZABLE(CRenderizableShaderPoints, mrpt::opengl)
4141

4242
public:
43-
CRenderizableShaderPoints() = default;
43+
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>();
48+
}
49+
4450
virtual ~CRenderizableShaderPoints() override;
4551

4652
virtual shader_list_t requiredShaders() const override { return {DefaultShaderID::POINTS}; }
@@ -70,9 +76,9 @@ class CRenderizableShaderPoints : public virtual CRenderizable
7076
// See base docs
7177
void freeOpenGLResources() override
7278
{
73-
m_vertexBuffer.destroy();
74-
m_colorBuffer.destroy();
75-
m_vao.destroy();
79+
(*m_vertexBuffer)->destroy();
80+
(*m_colorBuffer)->destroy();
81+
(*m_vao)->destroy();
7682
}
7783

7884
/** @name Raw access to point shader buffer data
@@ -101,8 +107,9 @@ class CRenderizableShaderPoints : public virtual CRenderizable
101107
void params_deserialize(mrpt::serialization::CArchive& in);
102108

103109
private:
104-
mutable Buffer m_vertexBuffer, m_colorBuffer;
105-
mutable VertexArrayObject m_vao;
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;
106113
};
107114

108115
} // namespace mrpt::opengl

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

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,14 @@ class CRenderizableShaderText : public virtual CRenderizable
2929
DEFINE_VIRTUAL_SERIALIZABLE(CRenderizableShaderText, mrpt::opengl)
3030

3131
public:
32-
CRenderizableShaderText() = default;
32+
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>();
39+
}
3340
virtual ~CRenderizableShaderText() override;
3441

3542
virtual shader_list_t requiredShaders() const override { return {DefaultShaderID::TEXT}; }
@@ -43,11 +50,10 @@ class CRenderizableShaderText : public virtual CRenderizable
4350
// See base docs
4451
void freeOpenGLResources() override
4552
{
46-
m_trianglesBuffer.destroy();
47-
m_trianglesColorBuffer.destroy();
48-
m_linesVertexBuffer.destroy();
49-
m_linesColorBuffer.destroy();
50-
m_vao.destroy();
53+
(*m_trianglesBuffer)->destroy();
54+
(*m_linesVertexBuffer)->destroy();
55+
(*m_linesColorBuffer)->destroy();
56+
(*m_vao)->destroy();
5157
}
5258

5359
protected:
@@ -60,9 +66,10 @@ class CRenderizableShaderText : public virtual CRenderizable
6066
mutable mrpt::containers::NonCopiableData<std::shared_mutex> m_textDataMtx;
6167

6268
private:
63-
mutable Buffer m_trianglesBuffer, m_trianglesColorBuffer;
64-
mutable Buffer m_linesVertexBuffer, m_linesColorBuffer;
65-
mutable VertexArrayObject m_vao;
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;
6673
};
6774

6875
} // namespace mrpt::opengl

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ class CRenderizableShaderTexturedTriangles : public virtual CRenderizable
3030
DEFINE_VIRTUAL_SERIALIZABLE(CRenderizableShaderTexturedTriangles, mrpt::opengl)
3131

3232
public:
33-
CRenderizableShaderTexturedTriangles() = default;
33+
CRenderizableShaderTexturedTriangles()
34+
{
35+
m_vbo.data = std::make_unique<Buffer>();
36+
m_vao.data = std::make_unique<VertexArrayObject>();
37+
}
3438
virtual ~CRenderizableShaderTexturedTriangles() override;
3539

3640
virtual shader_list_t requiredShaders() const override
@@ -49,8 +53,8 @@ class CRenderizableShaderTexturedTriangles : public virtual CRenderizable
4953
// See base docs
5054
void freeOpenGLResources() override
5155
{
52-
m_vbo.destroy();
53-
m_vao.destroy();
56+
(*m_vbo)->destroy();
57+
(*m_vao)->destroy();
5458
}
5559

5660
/** Assigns a texture and a transparency image, and enables transparency (If
@@ -134,8 +138,8 @@ class CRenderizableShaderTexturedTriangles : public virtual CRenderizable
134138
bool m_textureInterpolate = false;
135139
bool m_textureUseMipMaps = true;
136140

137-
mutable Buffer m_vbo;
138-
mutable VertexArrayObject m_vao;
141+
mutable mrpt::containers::NonCopiableData<std::unique_ptr<Buffer>> m_vbo;
142+
mutable mrpt::containers::NonCopiableData<std::unique_ptr<VertexArrayObject>> m_vao;
139143
};
140144

141145
} // namespace mrpt::opengl

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ class CRenderizableShaderTriangles : public virtual CRenderizable
2929
DEFINE_VIRTUAL_SERIALIZABLE(CRenderizableShaderTriangles, mrpt::opengl)
3030

3131
public:
32-
CRenderizableShaderTriangles() = default;
32+
CRenderizableShaderTriangles()
33+
{
34+
m_trianglesBuffer.data = std::make_unique<Buffer>();
35+
m_vao.data = std::make_unique<VertexArrayObject>();
36+
}
37+
3338
virtual ~CRenderizableShaderTriangles() override;
3439

3540
virtual shader_list_t requiredShaders() const override
@@ -46,8 +51,8 @@ class CRenderizableShaderTriangles : public virtual CRenderizable
4651
// See base docs
4752
void freeOpenGLResources() override
4853
{
49-
m_trianglesBuffer.destroy();
50-
m_vao.destroy();
54+
(*m_trianglesBuffer)->destroy();
55+
(*m_vao)->destroy();
5156
}
5257

5358
bool isLightEnabled() const { return m_enableLight; }
@@ -79,8 +84,8 @@ class CRenderizableShaderTriangles : public virtual CRenderizable
7984
void params_deserialize(mrpt::serialization::CArchive& in);
8085

8186
private:
82-
mutable Buffer m_trianglesBuffer;
83-
mutable VertexArrayObject m_vao;
87+
mutable mrpt::containers::NonCopiableData<std::unique_ptr<Buffer>> m_trianglesBuffer;
88+
mutable mrpt::containers::NonCopiableData<std::unique_ptr<VertexArrayObject>> m_vao;
8489

8590
bool m_enableLight = true;
8691
TCullFace m_cullface = TCullFace::NONE;

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,14 @@ class CRenderizableShaderWireFrame : public virtual CRenderizable
2828
DEFINE_VIRTUAL_SERIALIZABLE(CRenderizableShaderWireFrame, mrpt::opengl)
2929

3030
public:
31-
CRenderizableShaderWireFrame() = default;
31+
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>();
37+
}
38+
3239
virtual ~CRenderizableShaderWireFrame();
3340

3441
virtual shader_list_t requiredShaders() const override { return {DefaultShaderID::WIREFRAME}; }
@@ -55,9 +62,9 @@ class CRenderizableShaderWireFrame : public virtual CRenderizable
5562
// See base docs
5663
void freeOpenGLResources() override
5764
{
58-
m_vertexBuffer.destroy();
59-
m_colorBuffer.destroy();
60-
m_vao.destroy();
65+
(*m_vertexBuffer)->destroy();
66+
(*m_colorBuffer)->destroy();
67+
(*m_vao)->destroy();
6168
}
6269

6370
/** @name Raw access to wireframe shader buffer data
@@ -81,8 +88,9 @@ class CRenderizableShaderWireFrame : public virtual CRenderizable
8188
const mrpt::math::TBoundingBox wireframeVerticesBoundingBox() const;
8289

8390
private:
84-
mutable Buffer m_vertexBuffer, m_colorBuffer;
85-
mutable VertexArrayObject m_vao;
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;
8694
};
8795

8896
} // namespace mrpt::opengl

libs/opengl/include/mrpt/opengl/CSkyBox.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@ class CSkyBox : public CRenderizable
3333
DEFINE_SERIALIZABLE(CSkyBox, mrpt::opengl)
3434

3535
public:
36-
CSkyBox() = default;
36+
CSkyBox()
37+
{
38+
m_vbo.data = std::make_unique<Buffer>();
39+
m_vao.data = std::make_unique<VertexArrayObject>();
40+
}
3741
virtual ~CSkyBox() override;
3842

3943
/** @name Renderizable shader API virtual methods
@@ -65,8 +69,8 @@ class CSkyBox : public CRenderizable
6569
mutable Texture m_cubeTexture;
6670
std::array<mrpt::img::CImage, 6> m_textureImages;
6771

68-
mutable Buffer m_vbo;
69-
mutable VertexArrayObject m_vao;
72+
mutable mrpt::containers::NonCopiableData<std::unique_ptr<Buffer>> m_vbo;
73+
mutable mrpt::containers::NonCopiableData<std::unique_ptr<VertexArrayObject>> m_vao;
7074
};
7175

7276
} // namespace mrpt::opengl

0 commit comments

Comments
 (0)