summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gfx/src/render/buffer.c44
-rw-r--r--gfx/src/render/buffer.h3
-rw-r--r--gfx/src/render/geometry.c183
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
9static size_t get_buffer_size_bytes( 9static 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
31static GLenum get_buffer_usage(BufferUsage usage) { 14static 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
25size_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
42bool gfx_init_buffer(Buffer* buffer, const BufferDesc* desc) { 46bool 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
64void gfx_update_buffer( 68void 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.
20size_t gfx_get_buffer_type_size_bytes(BufferType);
21
19/// Create a buffer from raw data. 22/// Create a buffer from raw data.
20bool gfx_init_buffer(Buffer*, const BufferDesc*); 23bool 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) \ 31void 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.
43static bool configure_buffer( 48static 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
77static bool configure_vertex_attributes( 80static 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)});