Fix T62178 Eevee: Texture Box mapping not matching Cycles if object is scaled
[blender.git] / source / blender / gpu / intern / gpu_shader_interface.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 shader interface (C --> GLSL)
24  */
25
26 #include "MEM_guardedalloc.h"
27 #include "BKE_global.h"
28
29 #include "GPU_shader_interface.h"
30
31 #include "gpu_batch_private.h"
32 #include "gpu_context_private.h"
33
34 #include <stdlib.h>
35 #include <stddef.h>
36 #include <string.h>
37
38 #define DEBUG_SHADER_INTERFACE 0
39 #define DEBUG_SHADER_UNIFORMS 0
40
41 #if DEBUG_SHADER_INTERFACE
42 #  include <stdio.h>
43 #endif
44
45 static const char *BuiltinUniform_name(GPUUniformBuiltin u)
46 {
47         static const char *names[] = {
48                 [GPU_UNIFORM_NONE] = NULL,
49
50                 [GPU_UNIFORM_MODEL] = "ModelMatrix",
51                 [GPU_UNIFORM_VIEW] = "ViewMatrix",
52                 [GPU_UNIFORM_MODELVIEW] = "ModelViewMatrix",
53                 [GPU_UNIFORM_PROJECTION] = "ProjectionMatrix",
54                 [GPU_UNIFORM_VIEWPROJECTION] = "ViewProjectionMatrix",
55                 [GPU_UNIFORM_MVP] = "ModelViewProjectionMatrix",
56
57                 [GPU_UNIFORM_MODEL_INV] = "ModelMatrixInverse",
58                 [GPU_UNIFORM_VIEW_INV] = "ViewMatrixInverse",
59                 [GPU_UNIFORM_MODELVIEW_INV] = "ModelViewMatrixInverse",
60                 [GPU_UNIFORM_PROJECTION_INV] = "ProjectionMatrixInverse",
61                 [GPU_UNIFORM_VIEWPROJECTION_INV] = "ViewProjectionMatrixInverse",
62
63                 [GPU_UNIFORM_NORMAL] = "NormalMatrix",
64                 [GPU_UNIFORM_NORMAL_INV] = "NormalMatrixInverse",
65                 [GPU_UNIFORM_WORLDNORMAL] = "WorldNormalMatrix",
66                 [GPU_UNIFORM_CAMERATEXCO] = "CameraTexCoFactors",
67                 [GPU_UNIFORM_ORCO] = "OrcoTexCoFactors",
68
69                 [GPU_UNIFORM_COLOR] = "color",
70                 [GPU_UNIFORM_EYE] = "eye",
71                 [GPU_UNIFORM_CALLID] = "callId",
72                 [GPU_UNIFORM_OBJECT_INFO] = "unfobjectinfo",
73
74                 [GPU_UNIFORM_CUSTOM] = NULL,
75                 [GPU_NUM_UNIFORMS] = NULL,
76         };
77
78         return names[u];
79 }
80
81 GPU_INLINE bool match(const char *a, const char *b)
82 {
83         return strcmp(a, b) == 0;
84 }
85
86 GPU_INLINE uint hash_string(const char *str)
87 {
88         uint i = 0, c;
89         while ((c = *str++)) {
90                 i = i * 37 + c;
91         }
92         return i;
93 }
94
95 GPU_INLINE void set_input_name(
96         GPUShaderInterface *shaderface, GPUShaderInput *input,
97         const char *name, uint32_t name_len)
98 {
99         input->name_offset = shaderface->name_buffer_offset;
100         input->name_hash = hash_string(name);
101         shaderface->name_buffer_offset += name_len + 1; /* include NULL terminator */
102 }
103
104 GPU_INLINE void shader_input_to_bucket(
105         GPUShaderInput *input,
106         GPUShaderInput *buckets[GPU_NUM_SHADERINTERFACE_BUCKETS])
107 {
108         const uint bucket_index = input->name_hash % GPU_NUM_SHADERINTERFACE_BUCKETS;
109         input->next = buckets[bucket_index];
110         buckets[bucket_index] = input;
111 }
112
113 GPU_INLINE const GPUShaderInput *buckets_lookup(
114         GPUShaderInput *const buckets[GPU_NUM_SHADERINTERFACE_BUCKETS],
115         const char *name_buffer, const char *name)
116 {
117         const uint name_hash = hash_string(name);
118         const uint bucket_index = name_hash % GPU_NUM_SHADERINTERFACE_BUCKETS;
119         const GPUShaderInput *input = buckets[bucket_index];
120         if (input == NULL) {
121                 /* Requested uniform is not found at all. */
122                 return NULL;
123         }
124         /* Optimization bit: if there is no hash collision detected when constructing shader interface
125          * it means we can only request the single possible uniform. Surely, it's possible we request
126          * uniform which causes hash collision, but that will be detected in debug builds. */
127         if (input->next == NULL) {
128                 if (name_hash == input->name_hash) {
129 #if TRUST_NO_ONE
130                         assert(match(name_buffer + input->name_offset, name));
131 #endif
132                         return input;
133                 }
134                 return NULL;
135         }
136         /* Work through possible collisions. */
137         const GPUShaderInput *next = input;
138         while (next != NULL) {
139                 input = next;
140                 next = input->next;
141                 if (input->name_hash != name_hash) {
142                         continue;
143                 }
144                 if (match(name_buffer + input->name_offset, name)) {
145                         return input;
146                 }
147         }
148         return NULL; /* not found */
149 }
150
151 GPU_INLINE void buckets_free(GPUShaderInput *buckets[GPU_NUM_SHADERINTERFACE_BUCKETS])
152 {
153         for (uint bucket_index = 0; bucket_index < GPU_NUM_SHADERINTERFACE_BUCKETS; ++bucket_index) {
154                 GPUShaderInput *input = buckets[bucket_index];
155                 while (input != NULL) {
156                         GPUShaderInput *input_next = input->next;
157                         MEM_freeN(input);
158                         input = input_next;
159                 }
160         }
161 }
162
163 static bool setup_builtin_uniform(GPUShaderInput *input, const char *name)
164 {
165         /* TODO: reject DOUBLE, IMAGE, ATOMIC_COUNTER gl_types */
166
167         /* detect built-in uniforms (name must match) */
168         for (GPUUniformBuiltin u = GPU_UNIFORM_NONE + 1; u < GPU_UNIFORM_CUSTOM; ++u) {
169                 const char *builtin_name = BuiltinUniform_name(u);
170                 if (match(name, builtin_name)) {
171                         input->builtin_type = u;
172                         return true;
173                 }
174         }
175         input->builtin_type = GPU_UNIFORM_CUSTOM;
176         return false;
177 }
178
179 static const GPUShaderInput *add_uniform(GPUShaderInterface *shaderface, const char *name)
180 {
181         GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Unif");
182
183         input->location = glGetUniformLocation(shaderface->program, name);
184
185         uint name_len = strlen(name);
186         shaderface->name_buffer = MEM_reallocN(shaderface->name_buffer, shaderface->name_buffer_offset + name_len + 1); /* include NULL terminator */
187         char *name_buffer = shaderface->name_buffer + shaderface->name_buffer_offset;
188         strcpy(name_buffer, name);
189
190         set_input_name(shaderface, input, name, name_len);
191         setup_builtin_uniform(input, name);
192
193         shader_input_to_bucket(input, shaderface->uniform_buckets);
194         if (input->builtin_type != GPU_UNIFORM_NONE &&
195             input->builtin_type != GPU_UNIFORM_CUSTOM)
196         {
197                 shaderface->builtin_uniforms[input->builtin_type] = input;
198         }
199 #if DEBUG_SHADER_INTERFACE
200         printf("GPUShaderInterface %p, program %d, uniform[] '%s' at location %d\n",
201                shaderface,
202                shaderface->program,
203                name,
204                input->location);
205 #endif
206         return input;
207 }
208
209 GPUShaderInterface *GPU_shaderinterface_create(int32_t program)
210 {
211         GPUShaderInterface *shaderface = MEM_callocN(sizeof(GPUShaderInterface), "GPUShaderInterface");
212         shaderface->program = program;
213
214 #if DEBUG_SHADER_INTERFACE
215         printf("%s {\n", __func__); /* enter function */
216         printf("GPUShaderInterface %p, program %d\n", shaderface, program);
217 #endif
218
219         GLint max_attr_name_len, attr_len;
220         glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attr_name_len);
221         glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attr_len);
222
223         GLint max_ubo_name_len, ubo_len;
224         glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_ubo_name_len);
225         glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &ubo_len);
226
227         const uint32_t name_buffer_len = attr_len * max_attr_name_len + ubo_len * max_ubo_name_len;
228         shaderface->name_buffer = MEM_mallocN(name_buffer_len, "name_buffer");
229
230         /* Attributes */
231         for (uint32_t i = 0; i < attr_len; ++i) {
232                 GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Attr");
233                 GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset;
234                 char *name = shaderface->name_buffer + shaderface->name_buffer_offset;
235                 GLsizei name_len = 0;
236
237                 glGetActiveAttrib(program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name);
238
239                 /* remove "[0]" from array name */
240                 if (name[name_len - 1] == ']') {
241                         name[name_len - 3] = '\0';
242                         name_len -= 3;
243                 }
244
245                 /* TODO: reject DOUBLE gl_types */
246
247                 input->location = glGetAttribLocation(program, name);
248
249                 set_input_name(shaderface, input, name, name_len);
250
251                 shader_input_to_bucket(input, shaderface->attr_buckets);
252
253 #if DEBUG_SHADER_INTERFACE
254                 printf("attr[%u] '%s' at location %d\n", i, name, input->location);
255 #endif
256         }
257         /* Uniform Blocks */
258         for (uint32_t i = 0; i < ubo_len; ++i) {
259                 GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput UBO");
260                 GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset;
261                 char *name = shaderface->name_buffer + shaderface->name_buffer_offset;
262                 GLsizei name_len = 0;
263
264                 glGetActiveUniformBlockName(program, i, remaining_buffer, &name_len, name);
265
266                 input->location = i;
267
268                 set_input_name(shaderface, input, name, name_len);
269
270                 shader_input_to_bucket(input, shaderface->ubo_buckets);
271
272 #if DEBUG_SHADER_INTERFACE
273                 printf("ubo '%s' at location %d\n", name, input->location);
274 #endif
275         }
276         /* Builtin Uniforms */
277         for (GPUUniformBuiltin u = GPU_UNIFORM_NONE + 1; u < GPU_UNIFORM_CUSTOM; ++u) {
278                 const char *builtin_name = BuiltinUniform_name(u);
279                 if (glGetUniformLocation(program, builtin_name) != -1) {
280                         add_uniform((GPUShaderInterface *)shaderface, builtin_name);
281                 }
282         }
283         /* Batches ref buffer */
284         shaderface->batches_len = GPU_SHADERINTERFACE_REF_ALLOC_COUNT;
285         shaderface->batches = MEM_callocN(shaderface->batches_len * sizeof(GPUBatch *), "GPUShaderInterface batches");
286
287         return shaderface;
288 }
289
290 void GPU_shaderinterface_discard(GPUShaderInterface *shaderface)
291 {
292         /* Free memory used by buckets and has entries. */
293         buckets_free(shaderface->uniform_buckets);
294         buckets_free(shaderface->attr_buckets);
295         buckets_free(shaderface->ubo_buckets);
296         /* Free memory used by name_buffer. */
297         MEM_freeN(shaderface->name_buffer);
298         /* Remove this interface from all linked Batches vao cache. */
299         for (int i = 0; i < shaderface->batches_len; ++i) {
300                 if (shaderface->batches[i] != NULL) {
301                         gpu_batch_remove_interface_ref(shaderface->batches[i], shaderface);
302                 }
303         }
304         MEM_freeN(shaderface->batches);
305         /* Free memory used by shader interface by its self. */
306         MEM_freeN(shaderface);
307 }
308
309 const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *shaderface, const char *name)
310 {
311         return buckets_lookup(shaderface->uniform_buckets, shaderface->name_buffer, name);
312 }
313
314 const GPUShaderInput *GPU_shaderinterface_uniform_ensure(const GPUShaderInterface *shaderface, const char *name)
315 {
316         const GPUShaderInput *input = GPU_shaderinterface_uniform(shaderface, name);
317         /* If input is not found add it so it's found next time. */
318         if (input == NULL) {
319                 input = add_uniform((GPUShaderInterface *)shaderface, name);
320
321                 if ((G.debug & G_DEBUG_GPU) && (input->location == -1)) {
322                         fprintf(stderr, "GPUShaderInterface: Warning: Uniform '%s' not found!\n", name);
323                 }
324         }
325
326 #if DEBUG_SHADER_UNIFORMS
327         if ((G.debug & G_DEBUG_GPU) &&
328             input->builtin_type != GPU_UNIFORM_NONE &&
329             input->builtin_type != GPU_UNIFORM_CUSTOM)
330         {
331                 /* Warn if we find a matching builtin, since these can be looked up much quicker. */
332                 fprintf(stderr, "GPUShaderInterface: Warning: Uniform '%s' is a builtin uniform but not queried as such!\n", name);
333         }
334 #endif
335         return (input->location != -1) ? input : NULL;
336 }
337
338 const GPUShaderInput *GPU_shaderinterface_uniform_builtin(
339             const GPUShaderInterface *shaderface, GPUUniformBuiltin builtin)
340 {
341 #if TRUST_NO_ONE
342         assert(builtin != GPU_UNIFORM_NONE);
343         assert(builtin != GPU_UNIFORM_CUSTOM);
344         assert(builtin != GPU_NUM_UNIFORMS);
345 #endif
346         return shaderface->builtin_uniforms[builtin];
347 }
348
349 const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *shaderface, const char *name)
350 {
351         return buckets_lookup(shaderface->ubo_buckets, shaderface->name_buffer, name);
352 }
353
354 const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *shaderface, const char *name)
355 {
356         return buckets_lookup(shaderface->attr_buckets, shaderface->name_buffer, name);
357 }
358
359 void GPU_shaderinterface_add_batch_ref(GPUShaderInterface *shaderface, GPUBatch *batch)
360 {
361         int i; /* find first unused slot */
362         for (i = 0; i < shaderface->batches_len; ++i) {
363                 if (shaderface->batches[i] == NULL) {
364                         break;
365                 }
366         }
367         if (i == shaderface->batches_len) {
368                 /* Not enough place, realloc the array. */
369                 i = shaderface->batches_len;
370                 shaderface->batches_len += GPU_SHADERINTERFACE_REF_ALLOC_COUNT;
371                 shaderface->batches = MEM_recallocN(shaderface->batches, sizeof(GPUBatch *) * shaderface->batches_len);
372         }
373         shaderface->batches[i] = batch;
374 }
375
376 void GPU_shaderinterface_remove_batch_ref(GPUShaderInterface *shaderface, GPUBatch *batch)
377 {
378         for (int i = 0; i < shaderface->batches_len; ++i) {
379                 if (shaderface->batches[i] == batch) {
380                         shaderface->batches[i] = NULL;
381                         break; /* cannot have duplicates */
382                 }
383         }
384 }