OpenGL: manage built-in shaders better
[blender.git] / source / blender / gpu / intern / gpu_shader.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Brecht Van Lommel.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include "MEM_guardedalloc.h"
29
30 #include "BLI_utildefines.h"
31 #include "BLI_math_base.h"
32 #include "BLI_math_vector.h"
33
34 #include "BKE_global.h"
35
36 #include "GPU_compositing.h"
37 #include "GPU_debug.h"
38 #include "GPU_extensions.h"
39 #include "GPU_shader.h"
40 #include "GPU_texture.h"
41
42 #include "gpu_shader_private.h"
43
44 /* TODO(sergey): Find better default values for this constants. */
45 #define MAX_DEFINE_LENGTH 1024
46 #define MAX_EXT_DEFINE_LENGTH 1024
47
48 /* Non-generated shaders */
49 extern char datatoc_gpu_shader_depth_only_frag_glsl[];
50 extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
51 extern char datatoc_gpu_shader_flat_color_frag_glsl[];
52 extern char datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl[];
53 extern char datatoc_gpu_shader_2D_vert_glsl[];
54 extern char datatoc_gpu_shader_2D_flat_color_vert_glsl[];
55 extern char datatoc_gpu_shader_2D_smooth_color_vert_glsl[];
56 extern char datatoc_gpu_shader_2D_smooth_color_frag_glsl[];
57 extern char datatoc_gpu_shader_3D_image_vert_glsl[];
58 extern char datatoc_gpu_shader_image_mask_uniform_color_frag_glsl[];
59 extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[];
60 extern char datatoc_gpu_shader_image_rect_modulate_alpha_frag_glsl[];
61 extern char datatoc_gpu_shader_image_depth_linear_frag_glsl[];
62 extern char datatoc_gpu_shader_3D_vert_glsl[];
63 extern char datatoc_gpu_shader_3D_flat_color_vert_glsl[];
64 extern char datatoc_gpu_shader_3D_smooth_color_vert_glsl[];
65 extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
66
67 extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[];
68 extern char datatoc_gpu_shader_point_uniform_color_smooth_frag_glsl[];
69 extern char datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl[];
70 extern char datatoc_gpu_shader_point_varying_color_outline_smooth_frag_glsl[];
71 extern char datatoc_gpu_shader_point_varying_color_frag_glsl[];
72 extern char datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl[];
73 extern char datatoc_gpu_shader_3D_point_varying_size_vert_glsl[];
74 extern char datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl[];
75 extern char datatoc_gpu_shader_3D_point_uniform_size_smooth_vert_glsl[];
76 extern char datatoc_gpu_shader_3D_point_uniform_size_outline_smooth_vert_glsl[];
77 extern char datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl[];
78 extern char datatoc_gpu_shader_2D_point_uniform_size_smooth_vert_glsl[];
79 extern char datatoc_gpu_shader_2D_point_uniform_size_outline_smooth_vert_glsl[];
80 extern char datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert_glsl[];
81
82 extern char datatoc_gpu_shader_edges_front_back_persp_vert_glsl[];
83 extern char datatoc_gpu_shader_edges_front_back_persp_geom_glsl[];
84 extern char datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl[];
85 extern char datatoc_gpu_shader_edges_front_back_ortho_vert_glsl[];
86 extern char datatoc_gpu_shader_edges_overlay_vert_glsl[];
87 extern char datatoc_gpu_shader_edges_overlay_geom_glsl[];
88 extern char datatoc_gpu_shader_edges_overlay_simple_geom_glsl[];
89 extern char datatoc_gpu_shader_edges_overlay_frag_glsl[];
90 extern char datatoc_gpu_shader_text_vert_glsl[];
91 extern char datatoc_gpu_shader_text_frag_glsl[];
92
93 extern char datatoc_gpu_shader_fire_frag_glsl[];
94 extern char datatoc_gpu_shader_smoke_vert_glsl[];
95 extern char datatoc_gpu_shader_smoke_frag_glsl[];
96 extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
97 extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
98 extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
99 extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[];
100 extern char datatoc_gpu_shader_fx_vert_glsl[];
101 extern char datatoc_gpu_shader_fx_ssao_frag_glsl[];
102 extern char datatoc_gpu_shader_fx_dof_frag_glsl[];
103 extern char datatoc_gpu_shader_fx_dof_vert_glsl[];
104 extern char datatoc_gpu_shader_fx_dof_hq_frag_glsl[];
105 extern char datatoc_gpu_shader_fx_dof_hq_vert_glsl[];
106 extern char datatoc_gpu_shader_fx_dof_hq_geo_glsl[];
107 extern char datatoc_gpu_shader_fx_depth_resolve_glsl[];
108 extern char datatoc_gpu_shader_fx_lib_glsl[];
109
110 /* cache of built-in shaders (each is created on first use) */
111 static GPUShader *builtin_shaders[GPU_NUM_BUILTIN_SHADERS] = { NULL };
112
113 /* cache for shader fx. Those can exist in combinations so store them here */
114 static GPUShader *fx_shaders[MAX_FX_SHADERS * 2] = { NULL };
115
116 typedef struct {
117         const char *vert;
118         const char *frag;
119         const char *geom; /* geometry stage runs between vert & frag, but is less common, so it goes last */
120 } GPUShaderStages;
121
122 static void shader_print_errors(const char *task, const char *log, const char **code, int totcode)
123 {
124         int line = 1;
125
126         fprintf(stderr, "GPUShader: %s error:\n", task);
127
128         for (int i = 0; i < totcode; i++) {
129                 const char *c, *pos, *end = code[i] + strlen(code[i]);
130
131                 if (G.debug & G_DEBUG) {
132                         fprintf(stderr, "===== shader string %d ====\n", i + 1);
133
134                         c = code[i];
135                         while ((c < end) && (pos = strchr(c, '\n'))) {
136                                 fprintf(stderr, "%2d  ", line);
137                                 fwrite(c, (pos + 1) - c, 1, stderr);
138                                 c = pos + 1;
139                                 line++;
140                         }
141                         
142                         fprintf(stderr, "%s", c);
143                 }
144         }
145         
146         fprintf(stderr, "%s\n", log);
147 }
148
149 static const char *gpu_shader_version(void)
150 {
151         if (GLEW_VERSION_3_3) {
152                 if (GPU_legacy_support()) {
153                         return "#version 330 compatibility\n";
154                         /* highest version that is widely supported
155                          * gives us native geometry shaders!
156                          * use compatibility profile so we can continue using builtin shader input/output names
157                          */
158                 }
159                 else {
160                         return "#version 130\n";
161                         /* latest version that is compatible with existing shaders */
162                 }
163         }
164         else if (GLEW_VERSION_3_0) {
165                 return "#version 130\n";
166                 /* GLSL 1.3 has modern syntax/keywords/datatypes so use if available
167                  * older features are deprecated but still available without compatibility extension or profile
168                  */
169         }
170         else {
171                 return "#version 120\n";
172                 /* minimum supported */
173         }
174 }
175
176
177 static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH], bool use_geometry_shader)
178 {
179         /* enable extensions for features that are not part of our base GLSL version
180          * don't use an extension for something already available!
181          */
182
183         if (GLEW_ARB_texture_query_lod) {
184                 /* a #version 400 feature, but we use #version 150 maximum so use extension */
185                 strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n");
186         }
187
188         if (use_geometry_shader && GPU_geometry_shader_support_via_extension()) {
189                 strcat(defines, "#extension GL_EXT_geometry_shader4: enable\n");
190         }
191
192         if (GLEW_VERSION_3_1 && !GLEW_VERSION_3_2 && GLEW_ARB_compatibility) {
193                 strcat(defines, "#extension GL_ARB_compatibility: enable\n");
194         }
195
196         if (!GLEW_VERSION_3_1) {
197                 if (GLEW_ARB_draw_instanced) {
198                         strcat(defines, "#extension GL_ARB_draw_instanced: enable\n");
199                 }
200
201                 if (!GLEW_VERSION_3_0) {
202                         strcat(defines, "#extension GL_EXT_gpu_shader4: require\n");
203                 }
204         }
205 }
206
207 static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH],
208                                         bool use_opensubdiv,
209                                         bool use_new_shading)
210 {
211         /* some useful defines to detect GPU type */
212         if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
213                 strcat(defines, "#define GPU_ATI\n");
214                 if (GLEW_VERSION_3_0) {
215                         /* TODO(merwin): revisit this version check; GLEW_VERSION_3_0 means GL 3.0 or newer */
216                         strcat(defines, "#define CLIP_WORKAROUND\n");
217                 }
218         }
219         else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY))
220                 strcat(defines, "#define GPU_NVIDIA\n");
221         else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY))
222                 strcat(defines, "#define GPU_INTEL\n");
223
224         if (GPU_bicubic_bump_support())
225                 strcat(defines, "#define BUMP_BICUBIC\n");
226
227         if (GLEW_VERSION_3_0) {
228                 strcat(defines, "#define BIT_OPERATIONS\n");
229         }
230
231 #ifdef WITH_OPENSUBDIV
232         /* TODO(sergey): Check whether we actually compiling shader for
233          * the OpenSubdiv mesh.
234          */
235         if (use_opensubdiv) {
236                 strcat(defines, "#define USE_OPENSUBDIV\n");
237
238                 /* TODO(sergey): not strictly speaking a define, but this is
239                  * a global typedef which we don't have better place to define
240                  * in yet.
241                  */
242                 strcat(defines, "struct VertexData {\n"
243                                 "  vec4 position;\n"
244                                 "  vec3 normal;\n"
245                                 "  vec2 uv;"
246                                 "};\n");
247         }
248 #else
249         UNUSED_VARS(use_opensubdiv);
250 #endif
251
252         if (use_new_shading) {
253                 strcat(defines, "#define USE_NEW_SHADING\n");
254         }
255
256         return;
257 }
258
259 GPUShader *GPU_shader_create(const char *vertexcode,
260                              const char *fragcode,
261                              const char *geocode,
262                              const char *libcode,
263                              const char *defines,
264                              int input,
265                              int output,
266                              int number)
267 {
268         return GPU_shader_create_ex(vertexcode,
269                                     fragcode,
270                                     geocode,
271                                     libcode,
272                                     defines,
273                                     input,
274                                     output,
275                                     number,
276                                     GPU_SHADER_FLAGS_NONE);
277 }
278
279 GPUShader *GPU_shader_create_ex(const char *vertexcode,
280                                 const char *fragcode,
281                                 const char *geocode,
282                                 const char *libcode,
283                                 const char *defines,
284                                 int input,
285                                 int output,
286                                 int number,
287                                 const int flags)
288 {
289 #ifdef WITH_OPENSUBDIV
290         /* TODO(sergey): used to add #version 150 to the geometry shader.
291          * Could safely be renamed to "use_geometry_code" since it's very
292          * likely any of geometry code will want to use GLSL 1.5.
293          */
294         bool use_opensubdiv = (flags & GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV) != 0;
295 #else
296         UNUSED_VARS(flags);
297         bool use_opensubdiv = false;
298 #endif
299         GLint status;
300         GLchar log[5000];
301         GLsizei length = 0;
302         GPUShader *shader;
303         char standard_defines[MAX_DEFINE_LENGTH] = "";
304         char standard_extensions[MAX_EXT_DEFINE_LENGTH] = "";
305
306         if (geocode && !GPU_geometry_shader_support())
307                 return NULL;
308
309         shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
310
311         if (vertexcode)
312                 shader->vertex = glCreateShader(GL_VERTEX_SHADER);
313         if (fragcode)
314                 shader->fragment = glCreateShader(GL_FRAGMENT_SHADER);
315         if (geocode)
316                 shader->geometry = glCreateShader(GL_GEOMETRY_SHADER_EXT);
317
318         shader->program = glCreateProgram();
319
320         if (!shader->program ||
321             (vertexcode && !shader->vertex) ||
322             (fragcode && !shader->fragment) ||
323             (geocode && !shader->geometry))
324         {
325                 fprintf(stderr, "GPUShader, object creation failed.\n");
326                 GPU_shader_free(shader);
327                 return NULL;
328         }
329
330         gpu_shader_standard_defines(standard_defines,
331                                     use_opensubdiv,
332                                     (flags & GPU_SHADER_FLAGS_NEW_SHADING) != 0);
333         gpu_shader_standard_extensions(standard_extensions, geocode != NULL);
334
335         if (vertexcode) {
336                 const char *source[5];
337                 /* custom limit, may be too small, beware */
338                 int num_source = 0;
339
340                 source[num_source++] = gpu_shader_version();
341                 source[num_source++] = standard_extensions;
342                 source[num_source++] = standard_defines;
343
344                 if (defines) source[num_source++] = defines;
345                 source[num_source++] = vertexcode;
346
347                 glAttachShader(shader->program, shader->vertex);
348                 glShaderSource(shader->vertex, num_source, source, NULL);
349
350                 glCompileShader(shader->vertex);
351                 glGetShaderiv(shader->vertex, GL_COMPILE_STATUS, &status);
352
353                 if (!status) {
354                         glGetShaderInfoLog(shader->vertex, sizeof(log), &length, log);
355                         shader_print_errors("compile", log, source, num_source);
356
357                         GPU_shader_free(shader);
358                         return NULL;
359                 }
360         }
361
362         if (fragcode) {
363                 const char *source[7];
364                 int num_source = 0;
365
366                 source[num_source++] = gpu_shader_version();
367                 source[num_source++] = standard_extensions;
368                 source[num_source++] = standard_defines;
369
370 #ifdef WITH_OPENSUBDIV
371                 /* TODO(sergey): Move to fragment shader source code generation. */
372                 if (use_opensubdiv) {
373                         source[num_source++] =
374                                 "#ifdef USE_OPENSUBDIV\n"
375                                 "in block {\n"
376                                 "       VertexData v;\n"
377                                 "} inpt;\n"
378                                 "#endif\n";
379                 }
380 #endif
381
382                 if (defines) source[num_source++] = defines;
383                 if (libcode) source[num_source++] = libcode;
384                 source[num_source++] = fragcode;
385
386                 glAttachShader(shader->program, shader->fragment);
387                 glShaderSource(shader->fragment, num_source, source, NULL);
388
389                 glCompileShader(shader->fragment);
390                 glGetShaderiv(shader->fragment, GL_COMPILE_STATUS, &status);
391
392                 if (!status) {
393                         glGetShaderInfoLog(shader->fragment, sizeof(log), &length, log);
394                         shader_print_errors("compile", log, source, num_source);
395
396                         GPU_shader_free(shader);
397                         return NULL;
398                 }
399         }
400
401         if (geocode) {
402                 const char *source[6];
403                 int num_source = 0;
404
405                 source[num_source++] = gpu_shader_version();
406                 source[num_source++] = standard_extensions;
407                 source[num_source++] = standard_defines;
408
409                 if (defines) source[num_source++] = defines;
410                 source[num_source++] = geocode;
411
412                 glAttachShader(shader->program, shader->geometry);
413                 glShaderSource(shader->geometry, num_source, source, NULL);
414
415                 glCompileShader(shader->geometry);
416                 glGetShaderiv(shader->geometry, GL_COMPILE_STATUS, &status);
417
418                 if (!status) {
419                         glGetShaderInfoLog(shader->geometry, sizeof(log), &length, log);
420                         shader_print_errors("compile", log, source, num_source);
421
422                         GPU_shader_free(shader);
423                         return NULL;
424                 }
425                 
426                 if (!use_opensubdiv) {
427                         GPU_shader_geometry_stage_primitive_io(shader, input, output, number);
428                 }
429         }
430
431 #ifdef WITH_OPENSUBDIV
432         if (use_opensubdiv) {
433                 glBindAttribLocation(shader->program, 0, "position");
434                 glBindAttribLocation(shader->program, 1, "normal");
435                 GPU_shader_geometry_stage_primitive_io(shader,
436                                                        GL_LINES_ADJACENCY_EXT,
437                                                        GL_TRIANGLE_STRIP,
438                                                        4);
439         }
440 #endif
441
442         glLinkProgram(shader->program);
443         glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
444         if (!status) {
445                 glGetProgramInfoLog(shader->program, sizeof(log), &length, log);
446                 /* print attached shaders in pipeline order */
447                 if (vertexcode) shader_print_errors("linking", log, &vertexcode, 1);
448                 if (geocode) shader_print_errors("linking", log, &geocode, 1);
449                 if (libcode) shader_print_errors("linking", log, &libcode, 1);
450                 if (fragcode) shader_print_errors("linking", log, &fragcode, 1);
451
452                 GPU_shader_free(shader);
453                 return NULL;
454         }
455
456 #ifdef WITH_OPENSUBDIV
457         /* TODO(sergey): Find a better place for this. */
458         if (use_opensubdiv && GLEW_VERSION_4_1) {
459                 glProgramUniform1i(shader->program,
460                                    glGetUniformLocation(shader->program, "FVarDataOffsetBuffer"),
461                                    30);  /* GL_TEXTURE30 */
462
463                 glProgramUniform1i(shader->program,
464                                    glGetUniformLocation(shader->program, "FVarDataBuffer"),
465                                    31);  /* GL_TEXTURE31 */
466         }
467 #endif
468
469         return shader;
470 }
471
472 void GPU_shader_bind(GPUShader *shader)
473 {
474         BLI_assert(shader && shader->program);
475
476         glUseProgram(shader->program);
477 }
478
479 void GPU_shader_unbind(void)
480 {
481         glUseProgram(0);
482 }
483
484 void GPU_shader_free(GPUShader *shader)
485 {
486         BLI_assert(shader);
487
488         if (shader->vertex)
489                 glDeleteShader(shader->vertex);
490         if (shader->geometry)
491                 glDeleteShader(shader->geometry);
492         if (shader->fragment)
493                 glDeleteShader(shader->fragment);
494         if (shader->program)
495                 glDeleteProgram(shader->program);
496
497         if (shader->uniform_interface)
498                 MEM_freeN(shader->uniform_interface);
499
500         MEM_freeN(shader);
501 }
502
503 int GPU_shader_get_uniform(GPUShader *shader, const char *name)
504 {
505         BLI_assert(shader && shader->program);
506
507         return glGetUniformLocation(shader->program, name);
508 }
509
510 void *GPU_shader_get_interface(GPUShader *shader)
511 {
512         return shader->uniform_interface;
513 }
514
515 void GPU_shader_set_interface(GPUShader *shader, void *interface)
516 {
517         shader->uniform_interface = interface;
518 }
519
520 void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
521 {
522         if (location == -1 || value == NULL)
523                 return;
524
525         if (length == 1) glUniform1fv(location, arraysize, value);
526         else if (length == 2) glUniform2fv(location, arraysize, value);
527         else if (length == 3) glUniform3fv(location, arraysize, value);
528         else if (length == 4) glUniform4fv(location, arraysize, value);
529         else if (length == 9) glUniformMatrix3fv(location, arraysize, 0, value);
530         else if (length == 16) glUniformMatrix4fv(location, arraysize, 0, value);
531 }
532
533 void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int length, int arraysize, const int *value)
534 {
535         if (location == -1)
536                 return;
537
538         if (length == 1) glUniform1iv(location, arraysize, value);
539         else if (length == 2) glUniform2iv(location, arraysize, value);
540         else if (length == 3) glUniform3iv(location, arraysize, value);
541         else if (length == 4) glUniform4iv(location, arraysize, value);
542 }
543
544 void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
545 {
546         if (location == -1)
547                 return;
548
549         glUniform1i(location, value);
550 }
551
552 void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number)
553 {
554         if (GPU_geometry_shader_support_via_extension()) {
555                 /* geometry shaders must provide this info themselves for #version 150 and up */
556                 glProgramParameteriEXT(shader->program, GL_GEOMETRY_INPUT_TYPE_EXT, input);
557                 glProgramParameteriEXT(shader->program, GL_GEOMETRY_OUTPUT_TYPE_EXT, output);
558                 glProgramParameteriEXT(shader->program, GL_GEOMETRY_VERTICES_OUT_EXT, number);
559         }
560 }
561
562 void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
563 {
564         int number = GPU_texture_bound_number(tex);
565         int bindcode = GPU_texture_opengl_bindcode(tex);
566         int target = GPU_texture_target(tex);
567
568         if (number >= GPU_max_textures()) {
569                 fprintf(stderr, "Not enough texture slots.\n");
570                 return;
571         }
572                 
573         if (number == -1)
574                 return;
575
576         if (location == -1)
577                 return;
578
579         if (number != 0)
580                 glActiveTexture(GL_TEXTURE0 + number);
581
582         if (bindcode != 0)
583                 glBindTexture(target, bindcode);
584         else
585                 GPU_invalid_tex_bind(target);
586
587         glUniform1i(location, number);
588
589         if (number != 0)
590                 glActiveTexture(GL_TEXTURE0);
591 }
592
593 int GPU_shader_get_attribute(GPUShader *shader, const char *name)
594 {
595         BLI_assert(shader && shader->program);
596
597         return glGetAttribLocation(shader->program, name);
598 }
599
600 GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
601 {
602         BLI_assert(shader != GPU_NUM_BUILTIN_SHADERS); /* don't be a troll */
603
604         static const GPUShaderStages builtin_shader_stages[GPU_NUM_BUILTIN_SHADERS] = {
605                 [GPU_SHADER_VSM_STORE] = { datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl },
606                 [GPU_SHADER_SEP_GAUSSIAN_BLUR] = { datatoc_gpu_shader_sep_gaussian_blur_vert_glsl,
607                                                    datatoc_gpu_shader_sep_gaussian_blur_frag_glsl },
608                 [GPU_SHADER_SMOKE] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl },
609                 [GPU_SHADER_SMOKE_FIRE] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl },
610                 [GPU_SHADER_SMOKE_COBA] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl },
611
612                 [GPU_SHADER_TEXT] = { datatoc_gpu_shader_text_vert_glsl, datatoc_gpu_shader_text_frag_glsl },
613                 [GPU_SHADER_EDGES_FRONT_BACK_PERSP] = { datatoc_gpu_shader_edges_front_back_persp_vert_glsl,
614                         /*  this version is     */      datatoc_gpu_shader_flat_color_frag_glsl,
615                        /*  magical but slooow  */       datatoc_gpu_shader_edges_front_back_persp_geom_glsl },
616                 [GPU_SHADER_EDGES_FRONT_BACK_ORTHO] = { datatoc_gpu_shader_edges_front_back_ortho_vert_glsl,
617                                                         datatoc_gpu_shader_flat_color_frag_glsl },
618                 [GPU_SHADER_EDGES_OVERLAY_SIMPLE] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_edges_overlay_frag_glsl,
619                                                       datatoc_gpu_shader_edges_overlay_simple_geom_glsl },
620                 [GPU_SHADER_EDGES_OVERLAY] = { datatoc_gpu_shader_edges_overlay_vert_glsl,
621                                                datatoc_gpu_shader_edges_overlay_frag_glsl,
622                                                datatoc_gpu_shader_edges_overlay_geom_glsl },
623
624                 [GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_image_vert_glsl,
625                                                              datatoc_gpu_shader_image_mask_uniform_color_frag_glsl },
626                 [GPU_SHADER_3D_IMAGE_MODULATE_ALPHA] = { datatoc_gpu_shader_3D_image_vert_glsl,
627                                                          datatoc_gpu_shader_image_modulate_alpha_frag_glsl },
628                 [GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA] = { datatoc_gpu_shader_3D_image_vert_glsl,
629                                                               datatoc_gpu_shader_image_rect_modulate_alpha_frag_glsl },
630                 [GPU_SHADER_3D_IMAGE_DEPTH] = { datatoc_gpu_shader_3D_image_vert_glsl,
631                                                 datatoc_gpu_shader_image_depth_linear_frag_glsl },
632
633                 [GPU_SHADER_2D_UNIFORM_COLOR] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
634                 [GPU_SHADER_2D_FLAT_COLOR] = { datatoc_gpu_shader_2D_flat_color_vert_glsl,
635                                                datatoc_gpu_shader_flat_color_frag_glsl },
636                 [GPU_SHADER_2D_SMOOTH_COLOR] = { datatoc_gpu_shader_2D_smooth_color_vert_glsl,
637                                                  datatoc_gpu_shader_2D_smooth_color_frag_glsl },
638                 [GPU_SHADER_3D_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
639                 [GPU_SHADER_3D_FLAT_COLOR] = { datatoc_gpu_shader_3D_flat_color_vert_glsl,
640                                                datatoc_gpu_shader_flat_color_frag_glsl },
641                 [GPU_SHADER_3D_SMOOTH_COLOR] = { datatoc_gpu_shader_3D_smooth_color_vert_glsl,
642                                                  datatoc_gpu_shader_3D_smooth_color_frag_glsl },
643                 [GPU_SHADER_3D_DEPTH_ONLY] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_depth_only_frag_glsl },
644
645                 [GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR] =
646                         { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl },
647                 [GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR] =
648                         { datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl,
649                           datatoc_gpu_shader_point_varying_color_frag_glsl },
650                 [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH] =
651                         { datatoc_gpu_shader_2D_point_uniform_size_smooth_vert_glsl,
652                           datatoc_gpu_shader_point_uniform_color_smooth_frag_glsl },
653                 [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH] =
654                         { datatoc_gpu_shader_2D_point_uniform_size_outline_smooth_vert_glsl,
655                           datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl },
656                 [GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_SMOOTH] =
657                         { datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert_glsl,
658                           datatoc_gpu_shader_point_varying_color_outline_smooth_frag_glsl },
659                 [GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl,
660                                                                    datatoc_gpu_shader_point_uniform_color_frag_glsl },
661                 [GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR] = { datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl,
662                                                                    datatoc_gpu_shader_point_varying_color_frag_glsl },
663                 [GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_point_varying_size_vert_glsl,
664                                                                      datatoc_gpu_shader_point_uniform_color_frag_glsl },
665                 [GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR] =
666                         { datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl,
667                           datatoc_gpu_shader_point_varying_color_frag_glsl },
668                 [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH] =
669                         { datatoc_gpu_shader_3D_point_uniform_size_smooth_vert_glsl,
670                           datatoc_gpu_shader_point_uniform_color_smooth_frag_glsl },
671                 [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH] =
672                         { datatoc_gpu_shader_3D_point_uniform_size_outline_smooth_vert_glsl,
673                           datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl },
674         };
675
676         if (builtin_shaders[shader] == NULL) {
677                 /* just a few special cases */
678                 const char *defines = (shader == GPU_SHADER_SMOKE_COBA) ? "#define USE_COBA;\n" : NULL;
679
680                 const GPUShaderStages *stages = builtin_shader_stages + shader;
681
682                 if (shader == GPU_SHADER_EDGES_FRONT_BACK_PERSP && !GLEW_VERSION_3_2) {
683                         /* TODO: remove after switch to core profile (maybe) */
684                         static const GPUShaderStages legacy_fancy_edges =
685                                 { datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl,
686                                   datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl };
687                         stages = &legacy_fancy_edges;
688                 }
689
690                 /* common case */
691                 builtin_shaders[shader] = GPU_shader_create(stages->vert, stages->frag, stages->geom,
692                                                             NULL, defines, 0, 0, 0);
693         }
694
695         return builtin_shaders[shader];
696 }
697
698 #define MAX_DEFINES 100
699
700 GPUShader *GPU_shader_get_builtin_fx_shader(int effect, bool persp)
701 {
702         int offset;
703         char defines[MAX_DEFINES] = "";
704         /* avoid shaders out of range */
705         if (effect >= MAX_FX_SHADERS)
706                 return NULL;
707
708         offset = 2 * effect;
709
710         if (persp) {
711                 offset += 1;
712                 strcat(defines, "#define PERSP_MATRIX\n");
713         }
714
715         if (!fx_shaders[offset]) {
716                 GPUShader *shader = NULL;
717
718                 switch (effect) {
719                         case GPU_SHADER_FX_SSAO:
720                                 shader = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
721                                 break;
722
723                         case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
724                                 strcat(defines, "#define FIRST_PASS\n");
725                                 shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
726                                 break;
727
728                         case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
729                                 strcat(defines, "#define SECOND_PASS\n");
730                                 shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
731                                 break;
732
733                         case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
734                                 strcat(defines, "#define THIRD_PASS\n");
735                                 shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
736                                 break;
737
738                         case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
739                                 strcat(defines, "#define FOURTH_PASS\n");
740                                 shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
741                                 break;
742
743                         case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
744                                 strcat(defines, "#define FIFTH_PASS\n");
745                                 shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
746                                 break;
747
748                         case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
749                                 strcat(defines, "#define FIRST_PASS\n");
750                                 shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
751                                 break;
752
753                         case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
754                                 strcat(defines, "#define SECOND_PASS\n");
755                                 shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl,
756                                                            defines, GL_POINTS, GL_TRIANGLE_STRIP, 4);
757                                 break;
758
759                         case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
760                                 strcat(defines, "#define THIRD_PASS\n");
761                                 shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
762                                 break;
763
764                         case GPU_SHADER_FX_DEPTH_RESOLVE:
765                                 shader = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0);
766                                 break;
767                 }
768
769                 fx_shaders[offset] = shader;
770                 GPU_fx_shader_init_interface(shader, effect);
771         }
772
773         return fx_shaders[offset];
774 }
775
776
777 void GPU_shader_free_builtin_shaders(void)
778 {
779         for (int i = 0; i < GPU_NUM_BUILTIN_SHADERS; ++i) {
780                 if (builtin_shaders[i]) {
781                         GPU_shader_free(builtin_shaders[i]);
782                         builtin_shaders[i] = NULL;
783                 }
784         }
785
786         for (int i = 0; i < 2 * MAX_FX_SHADERS; ++i) {
787                 if (fx_shaders[i]) {
788                         GPU_shader_free(fx_shaders[i]);
789                         fx_shaders[i] = NULL;
790                 }
791         }
792 }