diff options
author | 3gg <3gg@shellblade.net> | 2023-06-21 08:56:34 -0700 |
---|---|---|
committer | 3gg <3gg@shellblade.net> | 2023-06-21 08:56:34 -0700 |
commit | a6767082a78e8b090fcce8c386fcbd359da8ecee (patch) | |
tree | 19785d8f5d36b1980230f4d0a27aa5212882eaf3 | |
parent | b03a00b89fd53874b22292cd94ae540451ebb242 (diff) |
Fix bug in Geometry that would over-allocate buffers.
-rw-r--r-- | gfx/src/render/buffer.c | 44 | ||||
-rw-r--r-- | gfx/src/render/buffer.h | 3 | ||||
-rw-r--r-- | gfx/src/render/geometry.c | 183 |
3 files changed, 124 insertions, 106 deletions
diff --git a/gfx/src/render/buffer.c b/gfx/src/render/buffer.c index 3c0c794..55c68cc 100644 --- a/gfx/src/render/buffer.c +++ b/gfx/src/render/buffer.c | |||
@@ -8,24 +8,7 @@ | |||
8 | 8 | ||
9 | static size_t get_buffer_size_bytes( | 9 | static size_t get_buffer_size_bytes( |
10 | BufferType type, const BufferDataDesc* desc) { | 10 | BufferType type, const BufferDataDesc* desc) { |
11 | switch (type) { | 11 | return desc->count * gfx_get_buffer_type_size_bytes(type); |
12 | case BufferUntyped: | ||
13 | return desc->count; | ||
14 | case Buffer2d: | ||
15 | return desc->count * sizeof(vec2); | ||
16 | case Buffer3d: | ||
17 | return desc->count * sizeof(vec3); | ||
18 | case Buffer4d: | ||
19 | return desc->count * sizeof(vec4); | ||
20 | case BufferFloat: | ||
21 | return desc->count * sizeof(float); | ||
22 | case BufferU8: | ||
23 | return desc->count * sizeof(uint8_t); | ||
24 | case BufferU16: | ||
25 | return desc->count * sizeof(uint16_t); | ||
26 | } | ||
27 | assert(false); | ||
28 | return 0; | ||
29 | } | 12 | } |
30 | 13 | ||
31 | static GLenum get_buffer_usage(BufferUsage usage) { | 14 | static GLenum get_buffer_usage(BufferUsage usage) { |
@@ -39,6 +22,27 @@ static GLenum get_buffer_usage(BufferUsage usage) { | |||
39 | return GL_STATIC_DRAW; | 22 | return GL_STATIC_DRAW; |
40 | } | 23 | } |
41 | 24 | ||
25 | size_t gfx_get_buffer_type_size_bytes(BufferType type) { | ||
26 | switch (type) { | ||
27 | case BufferUntyped: | ||
28 | return 1; | ||
29 | case Buffer2d: | ||
30 | return sizeof(vec2); | ||
31 | case Buffer3d: | ||
32 | return sizeof(vec3); | ||
33 | case Buffer4d: | ||
34 | return sizeof(vec4); | ||
35 | case BufferFloat: | ||
36 | return sizeof(float); | ||
37 | case BufferU8: | ||
38 | return sizeof(uint8_t); | ||
39 | case BufferU16: | ||
40 | return sizeof(uint16_t); | ||
41 | } | ||
42 | assert(false); | ||
43 | return 0; | ||
44 | } | ||
45 | |||
42 | bool gfx_init_buffer(Buffer* buffer, const BufferDesc* desc) { | 46 | bool gfx_init_buffer(Buffer* buffer, const BufferDesc* desc) { |
43 | assert(buffer); | 47 | assert(buffer); |
44 | buffer->type = desc->type; | 48 | buffer->type = desc->type; |
@@ -61,9 +65,7 @@ void gfx_del_buffer(Buffer* buffer) { | |||
61 | } | 65 | } |
62 | } | 66 | } |
63 | 67 | ||
64 | void gfx_update_buffer( | 68 | void gfx_update_buffer(Buffer* buffer, const BufferDataDesc* desc) { |
65 | RenderBackend* render_backend, Buffer* buffer, const BufferDataDesc* desc) { | ||
66 | assert(render_backend); | ||
67 | assert(buffer); | 69 | assert(buffer); |
68 | assert(desc); | 70 | assert(desc); |
69 | // OpenGL allows updating static buffers, but it is not optimal for | 71 | // OpenGL allows updating static buffers, but it is not optimal for |
diff --git a/gfx/src/render/buffer.h b/gfx/src/render/buffer.h index 0c81e7b..3adfd8e 100644 --- a/gfx/src/render/buffer.h +++ b/gfx/src/render/buffer.h | |||
@@ -16,6 +16,9 @@ typedef struct Buffer { | |||
16 | size_t size_bytes; | 16 | size_t size_bytes; |
17 | } Buffer; | 17 | } Buffer; |
18 | 18 | ||
19 | /// Return the buffer type size in bytes. | ||
20 | size_t gfx_get_buffer_type_size_bytes(BufferType); | ||
21 | |||
19 | /// Create a buffer from raw data. | 22 | /// Create a buffer from raw data. |
20 | bool gfx_init_buffer(Buffer*, const BufferDesc*); | 23 | bool gfx_init_buffer(Buffer*, const BufferDesc*); |
21 | 24 | ||
diff --git a/gfx/src/render/geometry.c b/gfx/src/render/geometry.c index e9d3ae5..44bfd04 100644 --- a/gfx/src/render/geometry.c +++ b/gfx/src/render/geometry.c | |||
@@ -26,21 +26,26 @@ static GLenum primitive_type_to_gl(PrimitiveType type) { | |||
26 | } | 26 | } |
27 | } | 27 | } |
28 | 28 | ||
29 | /// Create a buffer for the buffer view if the view does not already point to | 29 | /// Create a typed buffer for the buffer view if the view does not already point |
30 | /// a buffer. | 30 | /// to a buffer. |
31 | #define INIT_VIEW_BUFFER(render_backend, view, buffer_type, buffer_usage) \ | 31 | void init_view_buffer( |
32 | if (!view.buffer) { \ | 32 | RenderBackend* render_backend, BufferView* view, BufferType buffer_type, |
33 | view.buffer = (__typeof__(view.buffer))gfx_make_buffer( \ | 33 | BufferUsage buffer_usage) { |
34 | render_backend, &(BufferDesc){ \ | 34 | if (!view->buffer) { |
35 | .usage = buffer_usage, \ | 35 | view->buffer = gfx_make_buffer( |
36 | .type = buffer_type, \ | 36 | render_backend, |
37 | .data.data = view.data, \ | 37 | &(BufferDesc){ |
38 | .data.count = view.size_bytes}); \ | 38 | .usage = buffer_usage, |
39 | } \ | 39 | .type = buffer_type, |
40 | assert(view.size_bytes <= view.buffer->size_bytes); | 40 | .data.data = view->data, |
41 | .data.count = view->size_bytes / | ||
42 | gfx_get_buffer_type_size_bytes(buffer_type)}); | ||
43 | } | ||
44 | assert(view->size_bytes <= view->buffer->size_bytes); | ||
45 | } | ||
41 | 46 | ||
42 | /// Create a buffer for the view, then configure it in the VAO. | 47 | /// Configure the buffer in teh VAO. |
43 | static bool configure_buffer( | 48 | static void configure_buffer( |
44 | RenderBackend* render_backend, const GeometryDesc* desc, BufferView* view, | 49 | RenderBackend* render_backend, const GeometryDesc* desc, BufferView* view, |
45 | size_t num_components, size_t component_size_bytes, GLenum component_type, | 50 | size_t num_components, size_t component_size_bytes, GLenum component_type, |
46 | GLboolean normalized, GLuint channel) { | 51 | GLboolean normalized, GLuint channel) { |
@@ -70,8 +75,6 @@ static bool configure_buffer( | |||
70 | (const void*)view->offset_bytes); | 75 | (const void*)view->offset_bytes); |
71 | } | 76 | } |
72 | glBindBuffer(GL_ARRAY_BUFFER, 0); | 77 | glBindBuffer(GL_ARRAY_BUFFER, 0); |
73 | |||
74 | return true; | ||
75 | } | 78 | } |
76 | 79 | ||
77 | static bool configure_vertex_attributes( | 80 | static bool configure_vertex_attributes( |
@@ -80,105 +83,113 @@ static bool configure_vertex_attributes( | |||
80 | assert(desc); | 83 | assert(desc); |
81 | 84 | ||
82 | if (view_is_populated(desc->positions3d)) { | 85 | if (view_is_populated(desc->positions3d)) { |
83 | INIT_VIEW_BUFFER( | 86 | init_view_buffer( |
84 | render_backend, desc->positions3d, Buffer3d, desc->buffer_usage); | 87 | render_backend, (BufferView*)&desc->positions3d, Buffer3d, |
85 | if (!desc->positions3d.buffer || | 88 | desc->buffer_usage); |
86 | !configure_buffer( | 89 | if (!desc->positions3d.buffer) { |
87 | render_backend, desc, (BufferView*)&desc->positions3d, 3, | ||
88 | sizeof(float), GL_FLOAT, GL_FALSE, GFX_POSITION_CHANNEL)) { | ||
89 | return false; | 90 | return false; |
90 | } | 91 | } |
92 | configure_buffer( | ||
93 | render_backend, desc, (BufferView*)&desc->positions3d, 3, sizeof(float), | ||
94 | GL_FLOAT, GL_FALSE, GFX_POSITION_CHANNEL); | ||
91 | } else if (view_is_populated(desc->positions2d)) { | 95 | } else if (view_is_populated(desc->positions2d)) { |
92 | INIT_VIEW_BUFFER( | 96 | init_view_buffer( |
93 | render_backend, desc->positions2d, Buffer2d, desc->buffer_usage); | 97 | render_backend, (BufferView*)&desc->positions2d, Buffer2d, |
94 | if (!desc->positions2d.buffer || | 98 | desc->buffer_usage); |
95 | !configure_buffer( | 99 | if (!desc->positions2d.buffer) { |
96 | render_backend, desc, (BufferView*)&desc->positions2d, 2, | ||
97 | sizeof(float), GL_FLOAT, GL_FALSE, GFX_POSITION_CHANNEL)) { | ||
98 | return false; | 100 | return false; |
99 | } | 101 | } |
102 | configure_buffer( | ||
103 | render_backend, desc, (BufferView*)&desc->positions2d, 2, sizeof(float), | ||
104 | GL_FLOAT, GL_FALSE, GFX_POSITION_CHANNEL); | ||
100 | } | 105 | } |
101 | if (view_is_populated(desc->normals)) { | 106 | if (view_is_populated(desc->normals)) { |
102 | INIT_VIEW_BUFFER( | 107 | init_view_buffer( |
103 | render_backend, desc->normals, Buffer3d, desc->buffer_usage); | 108 | render_backend, (BufferView*)&desc->normals, Buffer3d, |
104 | if (!desc->normals.buffer || | 109 | desc->buffer_usage); |
105 | !configure_buffer( | 110 | if (!desc->normals.buffer) { |
106 | render_backend, desc, (BufferView*)&desc->normals, 3, sizeof(float), | ||
107 | GL_FLOAT, GL_FALSE, GFX_NORMAL_CHANNEL)) { | ||
108 | return false; | 111 | return false; |
109 | } | 112 | } |
113 | configure_buffer( | ||
114 | render_backend, desc, (BufferView*)&desc->normals, 3, sizeof(float), | ||
115 | GL_FLOAT, GL_FALSE, GFX_NORMAL_CHANNEL); | ||
110 | } | 116 | } |
111 | if (view_is_populated(desc->tangents)) { | 117 | if (view_is_populated(desc->tangents)) { |
112 | INIT_VIEW_BUFFER( | 118 | init_view_buffer( |
113 | render_backend, desc->tangents, Buffer4d, desc->buffer_usage); | 119 | render_backend, (BufferView*)&desc->tangents, Buffer4d, |
114 | if (!desc->tangents.buffer || | 120 | desc->buffer_usage); |
115 | !configure_buffer( | 121 | if (!desc->tangents.buffer) { |
116 | render_backend, desc, (BufferView*)&desc->tangents, 4, | ||
117 | sizeof(float), GL_FLOAT, GL_FALSE, GFX_TANGENT_CHANNEL)) { | ||
118 | return false; | 122 | return false; |
119 | } | 123 | } |
124 | configure_buffer( | ||
125 | render_backend, desc, (BufferView*)&desc->tangents, 4, sizeof(float), | ||
126 | GL_FLOAT, GL_FALSE, GFX_TANGENT_CHANNEL); | ||
120 | } | 127 | } |
121 | if (view_is_populated(desc->texcoords)) { | 128 | if (view_is_populated(desc->texcoords)) { |
122 | INIT_VIEW_BUFFER( | 129 | init_view_buffer( |
123 | render_backend, desc->texcoords, Buffer2d, desc->buffer_usage); | 130 | render_backend, (BufferView*)&desc->texcoords, Buffer2d, |
124 | if (!desc->texcoords.buffer || | 131 | desc->buffer_usage); |
125 | !configure_buffer( | 132 | if (!desc->texcoords.buffer) { |
126 | render_backend, desc, (BufferView*)&desc->texcoords, 2, | ||
127 | sizeof(float), GL_FLOAT, GL_FALSE, GFX_TEXCOORDS_CHANNEL)) { | ||
128 | return false; | 133 | return false; |
129 | } | 134 | } |
135 | configure_buffer( | ||
136 | render_backend, desc, (BufferView*)&desc->texcoords, 2, sizeof(float), | ||
137 | GL_FLOAT, GL_FALSE, GFX_TEXCOORDS_CHANNEL); | ||
130 | } | 138 | } |
131 | if (view_is_populated(desc->joints.u8)) { | 139 | if (view_is_populated(desc->joints.u8)) { |
132 | INIT_VIEW_BUFFER( | 140 | init_view_buffer( |
133 | render_backend, desc->joints.u8, BufferU8, desc->buffer_usage); | 141 | render_backend, (BufferView*)&desc->joints.u8, BufferU8, |
134 | if (!desc->joints.u8.buffer || | 142 | desc->buffer_usage); |
135 | !configure_buffer( | 143 | if (!desc->joints.u8.buffer) { |
136 | render_backend, desc, (BufferView*)&desc->joints.u8, 4, | ||
137 | sizeof(uint8_t), GL_UNSIGNED_BYTE, GL_FALSE, GFX_JOINTS_CHANNEL)) { | ||
138 | return false; | 144 | return false; |
139 | } | 145 | } |
146 | configure_buffer( | ||
147 | render_backend, desc, (BufferView*)&desc->joints.u8, 4, sizeof(uint8_t), | ||
148 | GL_UNSIGNED_BYTE, GL_FALSE, GFX_JOINTS_CHANNEL); | ||
140 | } else if (view_is_populated(desc->joints.u16)) { | 149 | } else if (view_is_populated(desc->joints.u16)) { |
141 | INIT_VIEW_BUFFER( | 150 | init_view_buffer( |
142 | render_backend, desc->joints.u16, BufferU16, desc->buffer_usage); | 151 | render_backend, (BufferView*)&desc->joints.u16, BufferU16, |
143 | if (!desc->joints.u16.buffer || | 152 | desc->buffer_usage); |
144 | !configure_buffer( | 153 | if (!desc->joints.u16.buffer) { |
145 | render_backend, desc, (BufferView*)&desc->joints.u16, 4, | ||
146 | sizeof(uint16_t), GL_UNSIGNED_SHORT, GL_FALSE, | ||
147 | GFX_JOINTS_CHANNEL)) { | ||
148 | return false; | 154 | return false; |
149 | } | 155 | } |
156 | configure_buffer( | ||
157 | render_backend, desc, (BufferView*)&desc->joints.u16, 4, | ||
158 | sizeof(uint16_t), GL_UNSIGNED_SHORT, GL_FALSE, GFX_JOINTS_CHANNEL); | ||
150 | } | 159 | } |
151 | 160 | ||
152 | // If weights are given as unsigned integers, then they are normalized when | 161 | // If weights are given as unsigned integers, then they are normalized |
153 | // read by the shader. | 162 | // when read by the shader. |
154 | if (view_is_populated(desc->weights.u8)) { | 163 | if (view_is_populated(desc->weights.u8)) { |
155 | INIT_VIEW_BUFFER( | 164 | init_view_buffer( |
156 | render_backend, desc->weights.u8, BufferU8, desc->buffer_usage); | 165 | render_backend, (BufferView*)&desc->weights.u8, BufferU8, |
157 | if (!desc->weights.u8.buffer || | 166 | desc->buffer_usage); |
158 | !configure_buffer( | 167 | if (!desc->weights.u8.buffer) { |
159 | render_backend, desc, (BufferView*)&desc->weights.u8, 4, | ||
160 | sizeof(uint8_t), GL_UNSIGNED_BYTE, GL_TRUE, GFX_WEIGHTS_CHANNEL)) { | ||
161 | return false; | 168 | return false; |
162 | } | 169 | } |
170 | configure_buffer( | ||
171 | render_backend, desc, (BufferView*)&desc->weights.u8, 4, | ||
172 | sizeof(uint8_t), GL_UNSIGNED_BYTE, GL_TRUE, GFX_WEIGHTS_CHANNEL); | ||
163 | } else if (view_is_populated(desc->weights.u16)) { | 173 | } else if (view_is_populated(desc->weights.u16)) { |
164 | INIT_VIEW_BUFFER( | 174 | init_view_buffer( |
165 | render_backend, desc->weights.u16, BufferU16, desc->buffer_usage); | 175 | render_backend, (BufferView*)&desc->weights.u16, BufferU16, |
166 | if (!desc->weights.u16.buffer || | 176 | desc->buffer_usage); |
167 | !configure_buffer( | 177 | if (!desc->weights.u16.buffer) { |
168 | render_backend, desc, (BufferView*)&desc->weights.u16, 4, | ||
169 | sizeof(uint16_t), GL_UNSIGNED_SHORT, GL_TRUE, | ||
170 | GFX_WEIGHTS_CHANNEL)) { | ||
171 | return false; | 178 | return false; |
172 | } | 179 | } |
180 | configure_buffer( | ||
181 | render_backend, desc, (BufferView*)&desc->weights.u16, 4, | ||
182 | sizeof(uint16_t), GL_UNSIGNED_SHORT, GL_TRUE, GFX_WEIGHTS_CHANNEL); | ||
173 | } else if (view_is_populated(desc->weights.floats)) { | 183 | } else if (view_is_populated(desc->weights.floats)) { |
174 | INIT_VIEW_BUFFER( | 184 | init_view_buffer( |
175 | render_backend, desc->weights.floats, BufferFloat, desc->buffer_usage); | 185 | render_backend, (BufferView*)&desc->weights.floats, BufferFloat, |
176 | if (!desc->weights.floats.buffer || | 186 | desc->buffer_usage); |
177 | !configure_buffer( | 187 | if (!desc->weights.floats.buffer) { |
178 | render_backend, desc, (BufferView*)&desc->weights.floats, 4, | ||
179 | sizeof(float), GL_FLOAT, GL_FALSE, GFX_WEIGHTS_CHANNEL)) { | ||
180 | return false; | 188 | return false; |
181 | } | 189 | } |
190 | configure_buffer( | ||
191 | render_backend, desc, (BufferView*)&desc->weights.floats, 4, | ||
192 | sizeof(float), GL_FLOAT, GL_FALSE, GFX_WEIGHTS_CHANNEL); | ||
182 | } | 193 | } |
183 | 194 | ||
184 | return true; | 195 | return true; |
@@ -193,8 +204,9 @@ static bool configure_indices( | |||
193 | assert(desc->num_indices > 0); | 204 | assert(desc->num_indices > 0); |
194 | assert( | 205 | assert( |
195 | desc->num_indices <= desc->indices8.size_bytes / sizeof(VertexIndex8)); | 206 | desc->num_indices <= desc->indices8.size_bytes / sizeof(VertexIndex8)); |
196 | INIT_VIEW_BUFFER( | 207 | init_view_buffer( |
197 | render_backend, desc->indices8, BufferU8, desc->buffer_usage); | 208 | render_backend, (BufferView*)&desc->indices8, BufferU8, |
209 | desc->buffer_usage); | ||
198 | if (!desc->indices8.buffer) { | 210 | if (!desc->indices8.buffer) { |
199 | return false; | 211 | return false; |
200 | } | 212 | } |
@@ -203,8 +215,9 @@ static bool configure_indices( | |||
203 | assert( | 215 | assert( |
204 | desc->num_indices <= | 216 | desc->num_indices <= |
205 | desc->indices16.size_bytes / sizeof(VertexIndex16)); | 217 | desc->indices16.size_bytes / sizeof(VertexIndex16)); |
206 | INIT_VIEW_BUFFER( | 218 | init_view_buffer( |
207 | render_backend, desc->indices16, BufferU16, desc->buffer_usage); | 219 | render_backend, (BufferView*)&desc->indices16, BufferU16, |
220 | desc->buffer_usage); | ||
208 | if (!desc->indices16.buffer) { | 221 | if (!desc->indices16.buffer) { |
209 | return false; | 222 | return false; |
210 | } | 223 | } |
@@ -280,7 +293,7 @@ void gfx_update_geometry(Geometry* geometry, const GeometryDesc* desc) { | |||
280 | // The geometry must already have an underlying GPU buffer. | 293 | // The geometry must already have an underlying GPU buffer. |
281 | assert(geometry->desc.positions3d.buffer); | 294 | assert(geometry->desc.positions3d.buffer); |
282 | gfx_update_buffer( | 295 | gfx_update_buffer( |
283 | geometry->render_backend, geometry->desc.positions3d.buffer, | 296 | geometry->desc.positions3d.buffer, |
284 | &(BufferDataDesc){ | 297 | &(BufferDataDesc){ |
285 | .vec3s = desc->positions3d.data, | 298 | .vec3s = desc->positions3d.data, |
286 | .count = desc->positions3d.size_bytes / sizeof(vec3)}); | 299 | .count = desc->positions3d.size_bytes / sizeof(vec3)}); |