Fix build errors
[blender.git] / source / blender / gpu / intern / gpu_vertex_format.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2016 by Mike Erwin.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup gpu
22  *
23  * GPU vertex format
24  */
25
26 #include "GPU_shader_interface.h"
27
28 #include "GPU_vertex_format.h"
29 #include "gpu_vertex_format_private.h"
30 #include <stddef.h>
31 #include <string.h>
32
33 #include "BLI_utildefines.h"
34
35 #define PACK_DEBUG 0
36
37 #if PACK_DEBUG
38 #  include <stdio.h>
39 #endif
40
41 void GPU_vertformat_clear(GPUVertFormat *format)
42 {
43 #if TRUST_NO_ONE
44         memset(format, 0, sizeof(GPUVertFormat));
45 #else
46         format->attr_len = 0;
47         format->packed = false;
48         format->name_offset = 0;
49         format->name_len = 0;
50
51         for (uint i = 0; i < GPU_VERT_ATTR_MAX_LEN; i++) {
52                 format->attrs[i].name_len = 0;
53         }
54 #endif
55 }
56
57 void GPU_vertformat_copy(GPUVertFormat *dest, const GPUVertFormat *src)
58 {
59         /* copy regular struct fields */
60         memcpy(dest, src, sizeof(GPUVertFormat));
61
62         for (uint i = 0; i < dest->attr_len; i++) {
63                 for (uint j = 0; j < dest->attrs[i].name_len; j++) {
64                         dest->attrs[i].name[j] = (char *)dest + (src->attrs[i].name[j] - ((char *)src));
65                 }
66         }
67 }
68
69 static GLenum convert_comp_type_to_gl(GPUVertCompType type)
70 {
71         static const GLenum table[] = {
72                 [GPU_COMP_I8] = GL_BYTE,
73                 [GPU_COMP_U8] = GL_UNSIGNED_BYTE,
74                 [GPU_COMP_I16] = GL_SHORT,
75                 [GPU_COMP_U16] = GL_UNSIGNED_SHORT,
76                 [GPU_COMP_I32] = GL_INT,
77                 [GPU_COMP_U32] = GL_UNSIGNED_INT,
78
79                 [GPU_COMP_F32] = GL_FLOAT,
80
81                 [GPU_COMP_I10] = GL_INT_2_10_10_10_REV,
82         };
83         return table[type];
84 }
85
86 static uint comp_sz(GPUVertCompType type)
87 {
88 #if TRUST_NO_ONE
89         assert(type <= GPU_COMP_F32); /* other types have irregular sizes (not bytes) */
90 #endif
91         const GLubyte sizes[] = {1, 1, 2, 2, 4, 4, 4};
92         return sizes[type];
93 }
94
95 static uint attr_sz(const GPUVertAttr *a)
96 {
97         if (a->comp_type == GPU_COMP_I10) {
98                 return 4; /* always packed as 10_10_10_2 */
99         }
100         return a->comp_len * comp_sz(a->comp_type);
101 }
102
103 static uint attr_align(const GPUVertAttr *a)
104 {
105         if (a->comp_type == GPU_COMP_I10) {
106                 return 4; /* always packed as 10_10_10_2 */
107         }
108         uint c = comp_sz(a->comp_type);
109         if (a->comp_len == 3 && c <= 2) {
110                 return 4 * c; /* AMD HW can't fetch these well, so pad it out (other vendors too?) */
111         }
112         else {
113                 return c; /* most fetches are ok if components are naturally aligned */
114         }
115 }
116
117 uint vertex_buffer_size(const GPUVertFormat *format, uint vertex_len)
118 {
119 #if TRUST_NO_ONE
120         assert(format->packed && format->stride > 0);
121 #endif
122         return format->stride * vertex_len;
123 }
124
125 static const char *copy_attr_name(GPUVertFormat *format, const char *name, const char *suffix)
126 {
127         /* strncpy does 110% of what we need; let's do exactly 100% */
128         char *name_copy = format->names + format->name_offset;
129         uint available = GPU_VERT_ATTR_NAMES_BUF_LEN - format->name_offset;
130         bool terminated = false;
131
132         for (uint i = 0; i < available; ++i) {
133                 const char c = name[i];
134                 name_copy[i] = c;
135                 if (c == '\0') {
136                         if (suffix) {
137                                 for (uint j = 0; j < available; ++j) {
138                                         const char s = suffix[j];
139                                         name_copy[i + j] = s;
140                                         if (s == '\0') {
141                                                 terminated = true;
142                                                 format->name_offset += (i + j + 1);
143                                                 break;
144                                         }
145                                 }
146                         }
147                         else {
148                                 terminated = true;
149                                 format->name_offset += (i + 1);
150                         }
151                         break;
152                 }
153         }
154 #if TRUST_NO_ONE
155         assert(terminated);
156         assert(format->name_offset <= GPU_VERT_ATTR_NAMES_BUF_LEN);
157 #else
158         (void)terminated;
159 #endif
160         return name_copy;
161 }
162
163 uint GPU_vertformat_attr_add(
164         GPUVertFormat *format, const char *name,
165         GPUVertCompType comp_type, uint comp_len, GPUVertFetchMode fetch_mode)
166 {
167 #if TRUST_NO_ONE
168         assert(format->name_len < GPU_VERT_ATTR_MAX_LEN); /* there's room for more */
169         assert(format->attr_len < GPU_VERT_ATTR_MAX_LEN); /* there's room for more */
170         assert(!format->packed); /* packed means frozen/locked */
171         assert((comp_len >= 1 && comp_len <= 4) || comp_len == 8 || comp_len == 12 || comp_len == 16);
172
173         switch (comp_type) {
174                 case GPU_COMP_F32:
175                         /* float type can only kept as float */
176                         assert(fetch_mode == GPU_FETCH_FLOAT);
177                         break;
178                 case GPU_COMP_I10:
179                         /* 10_10_10 format intended for normals (xyz) or colors (rgb)
180                          * extra component packed.w can be manually set to { -2, -1, 0, 1 } */
181                         assert(comp_len == 3 || comp_len == 4);
182                         assert(fetch_mode == GPU_FETCH_INT_TO_FLOAT_UNIT); /* not strictly required, may relax later */
183                         break;
184                 default:
185                         /* integer types can be kept as int or converted/normalized to float */
186                         assert(fetch_mode != GPU_FETCH_FLOAT);
187                         /* only support float matrices (see Batch_update_program_bindings) */
188                         assert(comp_len != 8 && comp_len != 12 && comp_len != 16);
189         }
190 #endif
191         format->name_len++; /* multiname support */
192
193         const uint attr_id = format->attr_len++;
194         GPUVertAttr *attr = &format->attrs[attr_id];
195
196         attr->name[attr->name_len++] = copy_attr_name(format, name, NULL);
197         attr->comp_type = comp_type;
198         attr->gl_comp_type = convert_comp_type_to_gl(comp_type);
199         attr->comp_len = (comp_type == GPU_COMP_I10) ? 4 : comp_len; /* system needs 10_10_10_2 to be 4 or BGRA */
200         attr->sz = attr_sz(attr);
201         attr->offset = 0; /* offsets & stride are calculated later (during pack) */
202         attr->fetch_mode = fetch_mode;
203
204         return attr_id;
205 }
206
207 void GPU_vertformat_alias_add(GPUVertFormat *format, const char *alias)
208 {
209         GPUVertAttr *attr = &format->attrs[format->attr_len - 1];
210 #if TRUST_NO_ONE
211         assert(format->name_len < GPU_VERT_ATTR_MAX_LEN); /* there's room for more */
212         assert(attr->name_len < GPU_VERT_ATTR_MAX_NAMES);
213 #endif
214         format->name_len++; /* multiname support */
215         attr->name[attr->name_len++] = copy_attr_name(format, alias, NULL);
216 }
217
218 int GPU_vertformat_attr_id_get(const GPUVertFormat *format, const char *name)
219 {
220         for (int i = 0; i < format->attr_len; i++) {
221                 const GPUVertAttr *attr = &format->attrs[i];
222                 for (int j = 0; j < attr->name_len; j++) {
223                         if (STREQ(name, attr->name[j])) {
224                                 return i;
225                         }
226                 }
227         }
228         return -1;
229 }
230
231 void GPU_vertformat_triple_load(GPUVertFormat *format)
232 {
233 #if TRUST_NO_ONE
234         assert(!format->packed);
235         assert(format->attr_len * 3 < GPU_VERT_ATTR_MAX_LEN);
236         assert(format->name_len + format->attr_len * 3 < GPU_VERT_ATTR_MAX_LEN);
237 #endif
238
239         VertexFormat_pack(format);
240
241         uint old_attr_len = format->attr_len;
242         for (uint a_idx = 0; a_idx < old_attr_len; ++a_idx) {
243                 GPUVertAttr *attr = &format->attrs[a_idx];
244                 /* Duplicate attr twice */
245                 for (int i = 1; i < 3; ++i) {
246                         GPUVertAttr *dst_attr = &format->attrs[format->attr_len];
247                         memcpy(dst_attr, attr, sizeof(GPUVertAttr));
248                         /* Increase offset to the next vertex. */
249                         dst_attr->offset += format->stride * i;
250                         /* Only copy first name for now. */
251                         dst_attr->name_len = 0;
252                         dst_attr->name[dst_attr->name_len++] = copy_attr_name(format, attr->name[0], (i == 1) ? "1" : "2");
253                         format->attr_len++;
254                 }
255
256 #if TRUST_NO_ONE
257                 assert(attr->name_len < GPU_VERT_ATTR_MAX_NAMES);
258 #endif
259                 /* Add alias to first attr. */
260                 format->name_len++;
261                 attr->name[attr->name_len++] = copy_attr_name(format, attr->name[0], "0");
262         }
263 }
264
265 uint padding(uint offset, uint alignment)
266 {
267         const uint mod = offset % alignment;
268         return (mod == 0) ? 0 : (alignment - mod);
269 }
270
271 #if PACK_DEBUG
272 static void show_pack(uint a_idx, uint sz, uint pad)
273 {
274         const char c = 'A' + a_idx;
275         for (uint i = 0; i < pad; ++i) {
276                 putchar('-');
277         }
278         for (uint i = 0; i < sz; ++i) {
279                 putchar(c);
280         }
281 }
282 #endif
283
284 void VertexFormat_pack(GPUVertFormat *format)
285 {
286         /* For now, attributes are packed in the order they were added,
287          * making sure each attribute is naturally aligned (add padding where necessary)
288          * Later we can implement more efficient packing w/ reordering
289          * (keep attribute ID order, adjust their offsets to reorder in buffer). */
290
291         /* TODO: realloc just enough to hold the final combo string. And just enough to
292          * hold used attributes, not all 16. */
293
294         GPUVertAttr *a0 = &format->attrs[0];
295         a0->offset = 0;
296         uint offset = a0->sz;
297
298 #if PACK_DEBUG
299         show_pack(0, a0->sz, 0);
300 #endif
301
302         for (uint a_idx = 1; a_idx < format->attr_len; ++a_idx) {
303                 GPUVertAttr *a = &format->attrs[a_idx];
304                 uint mid_padding = padding(offset, attr_align(a));
305                 offset += mid_padding;
306                 a->offset = offset;
307                 offset += a->sz;
308
309 #if PACK_DEBUG
310                 show_pack(a_idx, a->sz, mid_padding);
311 #endif
312         }
313
314         uint end_padding = padding(offset, attr_align(a0));
315
316 #if PACK_DEBUG
317         show_pack(0, 0, end_padding);
318         putchar('\n');
319 #endif
320         format->stride = offset + end_padding;
321         format->packed = true;
322 }
323
324 static uint calc_input_component_size(const GPUShaderInput *input)
325 {
326         int size = input->size;
327         switch (input->gl_type) {
328                 case GL_FLOAT_VEC2:
329                 case GL_INT_VEC2:
330                 case GL_UNSIGNED_INT_VEC2:
331                         return size * 2;
332                 case GL_FLOAT_VEC3:
333                 case GL_INT_VEC3:
334                 case GL_UNSIGNED_INT_VEC3:
335                         return size * 3;
336                 case GL_FLOAT_VEC4:
337                 case GL_FLOAT_MAT2:
338                 case GL_INT_VEC4:
339                 case GL_UNSIGNED_INT_VEC4:
340                         return size * 4;
341                 case GL_FLOAT_MAT3:
342                         return size * 9;
343                 case GL_FLOAT_MAT4:
344                         return size * 16;
345                 case GL_FLOAT_MAT2x3:
346                 case GL_FLOAT_MAT3x2:
347                         return size * 6;
348                 case GL_FLOAT_MAT2x4:
349                 case GL_FLOAT_MAT4x2:
350                         return size * 8;
351                 case GL_FLOAT_MAT3x4:
352                 case GL_FLOAT_MAT4x3:
353                         return size * 12;
354                 default:
355                         return size;
356         }
357 }
358
359 static void get_fetch_mode_and_comp_type(
360         int gl_type,
361         GPUVertCompType *r_comp_type,
362         uint *r_gl_comp_type,
363         GPUVertFetchMode *r_fetch_mode)
364 {
365         switch (gl_type) {
366                 case GL_FLOAT:
367                 case GL_FLOAT_VEC2:
368                 case GL_FLOAT_VEC3:
369                 case GL_FLOAT_VEC4:
370                 case GL_FLOAT_MAT2:
371                 case GL_FLOAT_MAT3:
372                 case GL_FLOAT_MAT4:
373                 case GL_FLOAT_MAT2x3:
374                 case GL_FLOAT_MAT2x4:
375                 case GL_FLOAT_MAT3x2:
376                 case GL_FLOAT_MAT3x4:
377                 case GL_FLOAT_MAT4x2:
378                 case GL_FLOAT_MAT4x3:
379                         *r_comp_type = GPU_COMP_F32;
380                         *r_gl_comp_type = GL_FLOAT;
381                         *r_fetch_mode = GPU_FETCH_FLOAT;
382                         break;
383                 case GL_INT:
384                 case GL_INT_VEC2:
385                 case GL_INT_VEC3:
386                 case GL_INT_VEC4:
387                         *r_comp_type = GPU_COMP_I32;
388                         *r_gl_comp_type = GL_INT;
389                         *r_fetch_mode = GPU_FETCH_INT;
390                         break;
391                 case GL_UNSIGNED_INT:
392                 case GL_UNSIGNED_INT_VEC2:
393                 case GL_UNSIGNED_INT_VEC3:
394                 case GL_UNSIGNED_INT_VEC4:
395                         *r_comp_type = GPU_COMP_U32;
396                         *r_gl_comp_type = GL_UNSIGNED_INT;
397                         *r_fetch_mode = GPU_FETCH_INT;
398                         break;
399                 default:
400                         BLI_assert(0);
401         }
402 }
403
404 void GPU_vertformat_from_interface(GPUVertFormat *format, const GPUShaderInterface *shaderface)
405 {
406         const char *name_buffer = shaderface->name_buffer;
407
408         for (int i = 0; i < GPU_NUM_SHADERINTERFACE_BUCKETS; i++) {
409                 const GPUShaderInput *input = shaderface->attr_buckets[i];
410                 if (input == NULL) {
411                         continue;
412                 }
413
414                 const GPUShaderInput *next = input;
415                 while (next != NULL) {
416                         input = next;
417                         next = input->next;
418
419                         format->name_len++; /* multiname support */
420                         format->attr_len++;
421
422                         GPUVertAttr *attr = &format->attrs[input->location];
423
424                         attr->name[attr->name_len++] = copy_attr_name(format, name_buffer + input->name_offset, NULL);
425                         attr->offset = 0; /* offsets & stride are calculated later (during pack) */
426                         attr->comp_len = calc_input_component_size(input);
427                         attr->sz = attr->comp_len * 4;
428                         get_fetch_mode_and_comp_type(input->gl_type, &attr->comp_type, &attr->gl_comp_type, &attr->fetch_mode);
429                 }
430         }
431 }
432
433
434 /* OpenGL ES packs in a different order as desktop GL but component conversion is the same.
435  * Of the code here, only struct GPUPackedNormal needs to change. */
436
437 #define SIGNED_INT_10_MAX  511
438 #define SIGNED_INT_10_MIN -512
439
440 static int clampi(int x, int min_allowed, int max_allowed)
441 {
442 #if TRUST_NO_ONE
443         assert(min_allowed <= max_allowed);
444 #endif
445         if (x < min_allowed) {
446                 return min_allowed;
447         }
448         else if (x > max_allowed) {
449                 return max_allowed;
450         }
451         else {
452                 return x;
453         }
454 }
455
456 static int quantize(float x)
457 {
458         int qx = x * 511.0f;
459         return clampi(qx, SIGNED_INT_10_MIN, SIGNED_INT_10_MAX);
460 }
461
462 static int convert_i16(short x)
463 {
464         /* 16-bit signed --> 10-bit signed */
465         /* TODO: round? */
466         return x >> 6;
467 }
468
469 GPUPackedNormal GPU_normal_convert_i10_v3(const float data[3])
470 {
471         GPUPackedNormal n = { .x = quantize(data[0]), .y = quantize(data[1]), .z = quantize(data[2]), };
472         return n;
473 }
474
475 GPUPackedNormal GPU_normal_convert_i10_s3(const short data[3])
476 {
477         GPUPackedNormal n = { .x = convert_i16(data[0]), .y = convert_i16(data[1]), .z = convert_i16(data[2]), };
478         return n;
479 }