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