Fix crash cause by SSS referencing Material Nodetree data.
[blender.git] / source / blender / gpu / intern / gpu_material.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) 2006 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 /** \file blender/gpu/intern/gpu_material.c
29  *  \ingroup gpu
30  *
31  * Manages materials, lights and textures.
32  */
33
34 #include <math.h>
35 #include <string.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "DNA_lamp_types.h"
40 #include "DNA_material_types.h"
41 #include "DNA_object_types.h"
42 #include "DNA_scene_types.h"
43 #include "DNA_world_types.h"
44
45 #include "BLI_math.h"
46 #include "BLI_blenlib.h"
47 #include "BLI_utildefines.h"
48 #include "BLI_rand.h"
49
50 #include "BKE_anim.h"
51 #include "BKE_colorband.h"
52 #include "BKE_colortools.h"
53 #include "BKE_global.h"
54 #include "BKE_image.h"
55 #include "BKE_layer.h"
56 #include "BKE_main.h"
57 #include "BKE_node.h"
58 #include "BKE_scene.h"
59
60 #include "IMB_imbuf_types.h"
61
62 #include "GPU_extensions.h"
63 #include "GPU_framebuffer.h"
64 #include "GPU_material.h"
65 #include "GPU_shader.h"
66 #include "GPU_texture.h"
67 #include "GPU_uniformbuffer.h"
68
69 #include "DRW_engine.h"
70
71 #include "gpu_codegen.h"
72
73 #ifdef WITH_OPENSUBDIV
74 #  include "BKE_DerivedMesh.h"
75 #endif
76
77 /* Structs */
78
79 struct GPUMaterial {
80         Scene *scene; /* DEPRECATED was only usefull for lamps */
81         Material *ma;
82
83         /* material for mesh surface, worlds or something else.
84          * some code generation is done differently depending on the use case */
85         int type; /* DEPRECATED */
86         GPUMaterialStatus status;
87
88         const void *engine_type;   /* attached engine type */
89         int options;    /* to identify shader variations (shadow, probe, world background...) */
90
91         /* for creating the material */
92         ListBase nodes;
93         GPUNodeLink *outlink;
94
95         /* for binding the material */
96         GPUPass *pass;
97         ListBase inputs;  /* GPUInput */
98         GPUVertexAttribs attribs;
99         int builtins;
100         int alpha, obcolalpha;
101         int dynproperty;
102
103         /* for passing uniforms */
104         int viewmatloc, invviewmatloc;
105         int obmatloc, invobmatloc;
106         int localtoviewmatloc, invlocaltoviewmatloc;
107         int obcolloc, obautobumpscaleloc;
108         int cameratexcofacloc;
109
110         int partscalarpropsloc;
111         int partcoloc;
112         int partvel;
113         int partangvel;
114
115         int objectinfoloc;
116
117         bool is_opensubdiv;
118
119         /* XXX: Should be in Material. But it depends on the output node
120          * used and since the output selection is difference for GPUMaterial...
121          */
122         int domain;
123
124         /* Used by 2.8 pipeline */
125         GPUUniformBuffer *ubo; /* UBOs for shader uniforms. */
126
127         /* Eevee SSS */
128         GPUUniformBuffer *sss_profile; /* UBO containing SSS profile. */
129         GPUTexture *sss_tex_profile; /* Texture containing SSS profile. */
130         float sss_enabled;
131         float sss_radii[3];
132         int sss_samples;
133         short int sss_falloff;
134         float sss_sharpness;
135         bool sss_dirty;
136 };
137
138 enum {
139         GPU_DOMAIN_SURFACE    = (1 << 0),
140         GPU_DOMAIN_VOLUME     = (1 << 1),
141         GPU_DOMAIN_SSS        = (1 << 2)
142 };
143
144 /* Functions */
145
146 void GPU_material_free(ListBase *gpumaterial)
147 {
148         for (LinkData *link = gpumaterial->first; link; link = link->next) {
149                 GPUMaterial *material = link->data;
150
151                 /* Cancel / wait any pending lazy compilation. */
152                 DRW_deferred_shader_remove(material);
153
154                 GPU_pass_free_nodes(&material->nodes);
155                 GPU_inputs_free(&material->inputs);
156
157                 if (material->pass)
158                         GPU_pass_release(material->pass);
159
160                 if (material->ubo != NULL) {
161                         GPU_uniformbuffer_free(material->ubo);
162                 }
163
164                 if (material->sss_tex_profile != NULL) {
165                         GPU_texture_free(material->sss_tex_profile);
166                 }
167
168                 if (material->sss_profile != NULL) {
169                         GPU_uniformbuffer_free(material->sss_profile);
170                 }
171
172                 MEM_freeN(material);
173         }
174
175         BLI_freelistN(gpumaterial);
176 }
177
178 GPUBuiltin GPU_get_material_builtins(GPUMaterial *material)
179 {
180         return material->builtins;
181 }
182
183 Scene *GPU_material_scene(GPUMaterial *material)
184 {
185         return material->scene;
186 }
187
188 GPUMatType GPU_Material_get_type(GPUMaterial *material)
189 {
190         return material->type;
191 }
192
193 GPUPass *GPU_material_get_pass(GPUMaterial *material)
194 {
195         return material->pass;
196 }
197
198 ListBase *GPU_material_get_inputs(GPUMaterial *material)
199 {
200         return &material->inputs;
201 }
202
203 GPUUniformBuffer *GPU_material_get_uniform_buffer(GPUMaterial *material)
204 {
205         return material->ubo;
206 }
207
208 /**
209  * Create dynamic UBO from parameters
210  * \param ListBase of BLI_genericNodeN(GPUInput)
211  */
212 void GPU_material_create_uniform_buffer(GPUMaterial *material, ListBase *inputs)
213 {
214         material->ubo = GPU_uniformbuffer_dynamic_create(inputs, NULL);
215 }
216
217 void GPU_material_uniform_buffer_tag_dirty(ListBase *gpumaterials)
218 {
219         for (LinkData *link = gpumaterials->first; link; link = link->next) {
220                 GPUMaterial *material = link->data;
221                 if (material->ubo != NULL) {
222                         GPU_uniformbuffer_tag_dirty(material->ubo);
223                 }
224                 if (material->sss_profile != NULL) {
225                         material->sss_dirty = true;
226                 }
227         }
228 }
229
230 /* Eevee Subsurface scattering. */
231 /* Based on Separable SSS. by Jorge Jimenez and Diego Gutierrez */
232
233 #define SSS_SAMPLES 65
234 #define SSS_EXPONENT 2.0f /* Importance sampling exponent */
235
236 typedef struct GPUSssKernelData {
237         float kernel[SSS_SAMPLES][4];
238         float param[3], max_radius;
239         int samples;
240 } GPUSssKernelData;
241
242 static void sss_calculate_offsets(GPUSssKernelData *kd, int count, float exponent)
243 {
244         float step = 2.0f / (float)(count - 1);
245         for (int i = 0; i < count; i++) {
246                 float o = ((float)i) * step - 1.0f;
247                 float sign = (o < 0.0f) ? -1.0f : 1.0f;
248                 float ofs = sign * fabsf(powf(o, exponent));
249                 kd->kernel[i][3] = ofs;
250         }
251 }
252
253 #define GAUSS_TRUNCATE 12.46f
254 static float gaussian_profile(float r, float radius)
255 {
256         const float v = radius * radius * (0.25f * 0.25f);
257         const float Rm = sqrtf(v * GAUSS_TRUNCATE);
258
259         if (r >= Rm) {
260                 return 0.0f;
261         }
262         return expf(-r * r / (2.0f * v)) / (2.0f * M_PI * v);
263 }
264
265 #define BURLEY_TRUNCATE     16.0f
266 #define BURLEY_TRUNCATE_CDF 0.9963790093708328f // cdf(BURLEY_TRUNCATE)
267 static float burley_profile(float r, float d)
268 {
269         float exp_r_3_d = expf(-r / (3.0f * d));
270         float exp_r_d = exp_r_3_d * exp_r_3_d * exp_r_3_d;
271         return (exp_r_d + exp_r_3_d) / (4.0f * d);
272 }
273
274 static float cubic_profile(float r, float radius, float sharpness)
275 {
276         float Rm = radius * (1.0f + sharpness);
277
278         if (r >= Rm) {
279                 return 0.0f;
280         }
281         /* custom variation with extra sharpness, to match the previous code */
282         const float y = 1.0f / (1.0f + sharpness);
283         float Rmy, ry, ryinv;
284
285         Rmy = powf(Rm, y);
286         ry = powf(r, y);
287         ryinv = (r > 0.0f) ? powf(r, y - 1.0f) : 0.0f;
288
289         const float Rmy5 = (Rmy * Rmy) * (Rmy * Rmy) * Rmy;
290         const float f = Rmy - ry;
291         const float num = f * (f * f) * (y * ryinv);
292
293         return (10.0f * num) / (Rmy5 * M_PI);
294 }
295
296 static float eval_profile(float r, short falloff_type, float sharpness, float param)
297 {
298         r = fabsf(r);
299
300         if (falloff_type == SHD_SUBSURFACE_BURLEY ||
301             falloff_type == SHD_SUBSURFACE_RANDOM_WALK)
302         {
303                 return burley_profile(r, param) / BURLEY_TRUNCATE_CDF;
304         }
305         else if (falloff_type == SHD_SUBSURFACE_CUBIC) {
306                 return cubic_profile(r, param, sharpness);
307         }
308         else {
309                 return gaussian_profile(r, param);
310         }
311 }
312
313 /* Resolution for each sample of the precomputed kernel profile */
314 #define INTEGRAL_RESOLUTION 32
315 static float eval_integral(float x0, float x1, short falloff_type, float sharpness, float param)
316 {
317         const float range = x1 - x0;
318         const float step = range / INTEGRAL_RESOLUTION;
319         float integral = 0.0f;
320
321         for (int i = 0; i < INTEGRAL_RESOLUTION; ++i) {
322                 float x = x0 + range * ((float)i + 0.5f) / (float)INTEGRAL_RESOLUTION;
323                 float y = eval_profile(x, falloff_type, sharpness, param);
324                 integral += y * step;
325         }
326
327         return integral;
328 }
329 #undef INTEGRAL_RESOLUTION
330
331 static void compute_sss_kernel(
332         GPUSssKernelData *kd, float radii[3], int sample_ct, int falloff_type, float sharpness)
333 {
334         float rad[3];
335         /* Minimum radius */
336         rad[0] = MAX2(radii[0], 1e-15f);
337         rad[1] = MAX2(radii[1], 1e-15f);
338         rad[2] = MAX2(radii[2], 1e-15f);
339
340         /* Christensen-Burley fitting */
341         float l[3], d[3];
342
343         if (falloff_type == SHD_SUBSURFACE_BURLEY ||
344             falloff_type == SHD_SUBSURFACE_RANDOM_WALK)
345         {
346                 mul_v3_v3fl(l, rad, 0.25f * M_1_PI);
347                 const float A = 1.0f;
348                 const float s = 1.9f - A + 3.5f * (A - 0.8f) * (A - 0.8f);
349                 /* XXX 0.6f Out of nowhere to match cycles! Empirical! Can be tweak better. */
350                 mul_v3_v3fl(d, l, 0.6f / s);
351                 mul_v3_v3fl(rad, d, BURLEY_TRUNCATE);
352                 kd->max_radius = MAX3(rad[0], rad[1], rad[2]);
353
354                 copy_v3_v3(kd->param, d);
355         }
356         else if (falloff_type == SHD_SUBSURFACE_CUBIC) {
357                 copy_v3_v3(kd->param, rad);
358                 mul_v3_fl(rad, 1.0f + sharpness);
359                 kd->max_radius = MAX3(rad[0], rad[1], rad[2]);
360         }
361         else {
362                 kd->max_radius = MAX3(rad[0], rad[1], rad[2]);
363
364                 copy_v3_v3(kd->param, rad);
365         }
366
367         /* Compute samples locations on the 1d kernel [-1..1] */
368         sss_calculate_offsets(kd, sample_ct, SSS_EXPONENT);
369
370         /* Weights sum for normalization */
371         float sum[3] = {0.0f, 0.0f, 0.0f};
372
373         /* Compute integral of each sample footprint */
374         for (int i = 0; i < sample_ct; i++) {
375                 float x0, x1;
376
377                 if (i == 0) {
378                         x0 = kd->kernel[0][3] - fabsf(kd->kernel[0][3] - kd->kernel[1][3]) / 2.0f;
379                 }
380                 else {
381                         x0 = (kd->kernel[i - 1][3] + kd->kernel[i][3]) / 2.0f;
382                 }
383
384                 if (i == sample_ct - 1) {
385                         x1 = kd->kernel[sample_ct - 1][3] + fabsf(kd->kernel[sample_ct - 2][3] - kd->kernel[sample_ct - 1][3]) / 2.0f;
386                 }
387                 else {
388                         x1 = (kd->kernel[i][3] + kd->kernel[i + 1][3]) / 2.0f;
389                 }
390
391                 x0 *= kd->max_radius;
392                 x1 *= kd->max_radius;
393
394                 kd->kernel[i][0] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[0]);
395                 kd->kernel[i][1] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[1]);
396                 kd->kernel[i][2] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[2]);
397
398                 sum[0] += kd->kernel[i][0];
399                 sum[1] += kd->kernel[i][1];
400                 sum[2] += kd->kernel[i][2];
401         }
402
403         for (int i = 0; i < 3; ++i) {
404                 if (sum[i] > 0.0f) {
405                         /* Normalize */
406                         for (int j = 0; j < sample_ct; j++) {
407                                 kd->kernel[j][i] /= sum[i];
408                         }
409                 }
410                 else {
411                         /* Avoid 0 kernel sum. */
412                         kd->kernel[sample_ct / 2][i] = 1.0f;
413                 }
414         }
415
416         /* Put center sample at the start of the array (to sample first) */
417         float tmpv[4];
418         copy_v4_v4(tmpv, kd->kernel[sample_ct / 2]);
419         for (int i = sample_ct / 2; i > 0; i--) {
420                 copy_v4_v4(kd->kernel[i], kd->kernel[i - 1]);
421         }
422         copy_v4_v4(kd->kernel[0], tmpv);
423
424         kd->samples = sample_ct;
425 }
426
427 #define INTEGRAL_RESOLUTION 512
428 static void compute_sss_translucence_kernel(
429         const GPUSssKernelData *kd, int resolution, short falloff_type, float sharpness, float **output)
430 {
431         float (*texels)[4];
432         texels = MEM_callocN(sizeof(float) * 4 * resolution, "compute_sss_translucence_kernel");
433         *output = (float *)texels;
434
435         /* Last texel should be black, hence the - 1. */
436         for (int i = 0; i < resolution - 1; ++i) {
437                 /* Distance from surface. */
438                 float d = kd->max_radius * ((float)i + 0.00001f) / ((float)resolution);
439
440                 /* For each distance d we compute the radiance incomming from an hypothetic parallel plane. */
441                 /* Compute radius of the footprint on the hypothetic plane */
442                 float r_fp = sqrtf(kd->max_radius * kd->max_radius - d * d);
443                 float r_step = r_fp / INTEGRAL_RESOLUTION;
444                 float area_accum = 0.0f;
445                 for (float r = 0.0f; r < r_fp; r += r_step) {
446                         /* Compute distance to the "shading" point through the medium. */
447                         /* r_step * 0.5f to put sample between the area borders */
448                         float dist = hypotf(r + r_step * 0.5f, d);
449
450                         float profile[3];
451                         profile[0] = eval_profile(dist, falloff_type, sharpness, kd->param[0]);
452                         profile[1] = eval_profile(dist, falloff_type, sharpness, kd->param[1]);
453                         profile[2] = eval_profile(dist, falloff_type, sharpness, kd->param[2]);
454
455                         /* Since the profile and configuration are radially symetrical we
456                          * can just evaluate it once and weight it accordingly */
457                         float r_next = r + r_step;
458                         float disk_area = (M_PI * r_next * r_next) - (M_PI * r * r);
459
460                         mul_v3_fl(profile, disk_area);
461                         add_v3_v3(texels[i], profile);
462                         area_accum += disk_area;
463                 }
464                 /* Normalize over the disk. */
465                 mul_v3_fl(texels[i], 1.0f / (area_accum));
466         }
467
468         /* Normalize */
469         for (int j = resolution - 2; j > 0; j--) {
470                 texels[j][0] /= (texels[0][0] > 0.0f) ? texels[0][0] : 1.0f;
471                 texels[j][1] /= (texels[0][1] > 0.0f) ? texels[0][1] : 1.0f;
472                 texels[j][2] /= (texels[0][2] > 0.0f) ? texels[0][2] : 1.0f;
473         }
474
475         /* First texel should be white */
476         texels[0][0] = (texels[0][0] > 0.0f) ? 1.0f : 0.0f;
477         texels[0][1] = (texels[0][1] > 0.0f) ? 1.0f : 0.0f;
478         texels[0][2] = (texels[0][2] > 0.0f) ? 1.0f : 0.0f;
479
480         /* dim the last few texels for smoother transition */
481         mul_v3_fl(texels[resolution - 2], 0.25f);
482         mul_v3_fl(texels[resolution - 3], 0.5f);
483         mul_v3_fl(texels[resolution - 4], 0.75f);
484 }
485 #undef INTEGRAL_RESOLUTION
486
487 void GPU_material_sss_profile_create(GPUMaterial *material, float radii[3], short *falloff_type, float *sharpness)
488 {
489         copy_v3_v3(material->sss_radii, radii);
490         material->sss_falloff = (falloff_type) ? *falloff_type : 0.0;
491         material->sss_sharpness = (sharpness) ? *sharpness : 0.0;
492         material->sss_dirty = true;
493         material->sss_enabled = true;
494
495         /* Update / Create UBO */
496         if (material->sss_profile == NULL) {
497                 material->sss_profile = GPU_uniformbuffer_create(sizeof(GPUSssKernelData), NULL, NULL);
498         }
499 }
500
501 struct GPUUniformBuffer *GPU_material_sss_profile_get(GPUMaterial *material, int sample_ct, GPUTexture **tex_profile)
502 {
503         if (!material->sss_enabled)
504                 return NULL;
505
506         if (material->sss_dirty || (material->sss_samples != sample_ct)) {
507                 GPUSssKernelData kd;
508
509                 float sharpness = material->sss_sharpness;
510
511                 /* XXX Black magic but it seems to fit. Maybe because we integrate -1..1 */
512                 sharpness *= 0.5f;
513
514                 compute_sss_kernel(&kd, material->sss_radii, sample_ct, material->sss_falloff, sharpness);
515
516                 /* Update / Create UBO */
517                 GPU_uniformbuffer_update(material->sss_profile, &kd);
518
519                 /* Update / Create Tex */
520                 float *translucence_profile;
521                 compute_sss_translucence_kernel(&kd, 64, material->sss_falloff, sharpness, &translucence_profile);
522
523                 if (material->sss_tex_profile != NULL) {
524                         GPU_texture_free(material->sss_tex_profile);
525                 }
526
527                 material->sss_tex_profile = GPU_texture_create_1D(64, GPU_RGBA16F, translucence_profile, NULL);
528
529                 MEM_freeN(translucence_profile);
530
531                 material->sss_samples = sample_ct;
532                 material->sss_dirty = false;
533         }
534
535         if (tex_profile != NULL) {
536                 *tex_profile = material->sss_tex_profile;
537         }
538         return material->sss_profile;
539 }
540
541 #undef SSS_EXPONENT
542 #undef SSS_SAMPLES
543
544 void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs)
545 {
546         *attribs = material->attribs;
547 }
548
549 void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link)
550 {
551         if (!material->outlink)
552                 material->outlink = link;
553 }
554
555 void gpu_material_add_node(GPUMaterial *material, GPUNode *node)
556 {
557         BLI_addtail(&material->nodes, node);
558 }
559
560 /* Return true if the material compilation has not yet begin or begin. */
561 GPUMaterialStatus GPU_material_status(GPUMaterial *mat)
562 {
563         return mat->status;
564 }
565
566 /* Code generation */
567
568 bool GPU_material_do_color_management(GPUMaterial *mat)
569 {
570         if (!BKE_scene_check_color_management_enabled(mat->scene))
571                 return false;
572
573         return true;
574 }
575
576 bool GPU_material_use_domain_surface(GPUMaterial *mat)
577 {
578         return (mat->domain & GPU_DOMAIN_SURFACE);
579 }
580
581 bool GPU_material_use_domain_volume(GPUMaterial *mat)
582 {
583         return (mat->domain & GPU_DOMAIN_VOLUME);
584 }
585
586 GPUMaterial *GPU_material_from_nodetree_find(
587         ListBase *gpumaterials, const void *engine_type, int options)
588 {
589         for (LinkData *link = gpumaterials->first; link; link = link->next) {
590                 GPUMaterial *current_material = (GPUMaterial *)link->data;
591                 if (current_material->engine_type == engine_type &&
592                     current_material->options == options)
593                 {
594                         return current_material;
595                 }
596         }
597
598         return NULL;
599 }
600
601 /**
602  * \note Caller must use #GPU_material_from_nodetree_find to re-use existing materials,
603  * This is enforced since constructing other arguments to this function may be expensive
604  * so only do this when they are needed.
605  */
606 GPUMaterial *GPU_material_from_nodetree(
607         Scene *scene, struct bNodeTree *ntree, ListBase *gpumaterials, const void *engine_type, int options,
608         const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines)
609 {
610         LinkData *link;
611         bool has_volume_output, has_surface_output;
612
613         /* Caller must re-use materials. */
614         BLI_assert(GPU_material_from_nodetree_find(gpumaterials, engine_type, options) == NULL);
615
616         /* allocate material */
617         GPUMaterial *mat = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial");;
618         mat->scene = scene;
619         mat->engine_type = engine_type;
620         mat->options = options;
621
622         ntreeGPUMaterialNodes(ntree, mat, NODE_NEW_SHADING | NODE_NEWER_SHADING);
623         ntreeGPUMaterialDomain(ntree, &has_surface_output, &has_volume_output);
624
625         if (has_surface_output) {
626                 mat->domain |= GPU_DOMAIN_SURFACE;
627         }
628         if (has_volume_output) {
629                 mat->domain |= GPU_DOMAIN_VOLUME;
630         }
631
632         if (mat->outlink) {
633                 /* Prune the unused nodes and extract attribs before compiling so the
634                  * generated VBOs are ready to accept the future shader. */
635                 GPU_nodes_prune(&mat->nodes, mat->outlink);
636                 GPU_nodes_get_vertex_attributes(&mat->nodes, &mat->attribs);
637                 /* Create source code and search pass cache for an already compiled version. */
638                 mat->pass = GPU_generate_pass_new(mat,
639                                       mat->outlink,
640                                       &mat->attribs,
641                                       &mat->nodes,
642                                       vert_code,
643                                       geom_code,
644                                       frag_lib,
645                                       defines);
646
647                 if (mat->pass == NULL) {
648                         /* We had a cache hit and the shader has already failed to compile. */
649                         mat->status = GPU_MAT_FAILED;
650                 }
651                 else {
652                         GPUShader *sh = GPU_pass_shader_get(mat->pass);
653                         if (sh != NULL) {
654                                 /* We had a cache hit and the shader is already compiled. */
655                                 mat->status = GPU_MAT_SUCCESS;
656                                 GPU_nodes_extract_dynamic_inputs(sh, &mat->inputs, &mat->nodes);
657                         }
658                         else {
659                                 mat->status = GPU_MAT_QUEUED;
660                         }
661                 }
662         }
663         else {
664                 mat->status = GPU_MAT_FAILED;
665         }
666
667         /* note that even if building the shader fails in some way, we still keep
668          * it to avoid trying to compile again and again, and simply do not use
669          * the actual shader on drawing */
670
671         link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink");
672         link->data = mat;
673         BLI_addtail(gpumaterials, link);
674
675         return mat;
676 }
677
678 void GPU_material_compile(GPUMaterial *mat)
679 {
680         /* Only run once! */
681         BLI_assert(mat->status == GPU_MAT_QUEUED);
682         BLI_assert(mat->pass);
683
684         /* NOTE: The shader may have already been compiled here since we are
685          * sharing GPUShader across GPUMaterials. In this case it's a no-op. */
686         GPU_pass_compile(mat->pass);
687         GPUShader *sh = GPU_pass_shader_get(mat->pass);
688
689         if (sh != NULL) {
690                 mat->status = GPU_MAT_SUCCESS;
691                 GPU_nodes_extract_dynamic_inputs(sh, &mat->inputs, &mat->nodes);
692         }
693         else {
694                 mat->status = GPU_MAT_FAILED;
695                 GPU_pass_free_nodes(&mat->nodes);
696                 GPU_pass_release(mat->pass);
697                 mat->pass = NULL;
698         }
699 }
700
701 void GPU_materials_free(void)
702 {
703         Material *ma;
704         World *wo;
705         extern Material defmaterial;
706
707         for (ma = G.main->mat.first; ma; ma = ma->id.next)
708                 GPU_material_free(&ma->gpumaterial);
709
710         for (wo = G.main->world.first; wo; wo = wo->id.next)
711                 GPU_material_free(&wo->gpumaterial);
712
713         GPU_material_free(&defmaterial.gpumaterial);
714 }