Blender  V2.93
gpu_material.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2006 Blender Foundation.
17  * All rights reserved.
18  */
19 
26 #include <math.h>
27 #include <string.h>
28 
29 #include "MEM_guardedalloc.h"
30 
31 #include "DNA_material_types.h"
32 #include "DNA_scene_types.h"
33 #include "DNA_world_types.h"
34 
35 #include "BLI_ghash.h"
36 #include "BLI_listbase.h"
37 #include "BLI_math.h"
38 #include "BLI_string.h"
39 #include "BLI_string_utils.h"
40 #include "BLI_utildefines.h"
41 
42 #include "BKE_main.h"
43 #include "BKE_material.h"
44 #include "BKE_node.h"
45 #include "BKE_scene.h"
46 
47 #include "GPU_material.h"
48 #include "GPU_shader.h"
49 #include "GPU_texture.h"
50 #include "GPU_uniform_buffer.h"
51 
52 #include "DRW_engine.h"
53 
54 #include "gpu_codegen.h"
55 #include "gpu_node_graph.h"
56 
57 /* Structs */
58 #define MAX_COLOR_BAND 128
59 
60 typedef struct GPUColorBandBuilder {
61  float pixels[MAX_COLOR_BAND][CM_TABLE + 1][4];
64 
65 struct GPUMaterial {
66  Scene *scene; /* DEPRECATED was only useful for lights. */
68 
70 
71  const void *engine_type; /* attached engine type */
72  int options; /* to identify shader variations (shadow, probe, world background...) */
73  bool is_volume_shader; /* is volumetric shader */
74 
75  /* Nodes */
77 
78  /* for binding the material */
80 
81  /* XXX: Should be in Material. But it depends on the output node
82  * used and since the output selection is different for GPUMaterial...
83  */
86 
87  /* Only used by Eevee to know which bsdf are used. */
89 
90  /* Used by 2.8 pipeline */
91  GPUUniformBuf *ubo; /* UBOs for shader uniforms. */
92 
93  /* Eevee SSS */
94  GPUUniformBuf *sss_profile; /* UBO containing SSS profile. */
95  GPUTexture *sss_tex_profile; /* Texture containing SSS profile. */
96  float sss_enabled;
97  float sss_radii[3];
99  short int sss_falloff;
101  bool sss_dirty;
102 
103  GPUTexture *coba_tex; /* 1D Texture array containing all color bands. */
105 
107 
108 #ifndef NDEBUG
109  char name[64];
110 #endif
111 };
112 
113 enum {
116 };
117 
118 /* Functions */
119 
120 /* Returns the address of the future pointer to coba_tex */
122  int size,
123  float *pixels,
124  float *row)
125 {
126  /* In order to put all the color-bands into one 1D array texture,
127  * we need them to be the same size. */
128  BLI_assert(size == CM_TABLE + 1);
130 
131  if (mat->coba_builder == NULL) {
132  mat->coba_builder = MEM_mallocN(sizeof(GPUColorBandBuilder), "GPUColorBandBuilder");
133  mat->coba_builder->current_layer = 0;
134  }
135 
136  int layer = mat->coba_builder->current_layer;
137  *row = (float)layer;
138 
139  if (*row == MAX_COLOR_BAND) {
140  printf("Too many color band in shader! Remove some Curve, Black Body or Color Ramp Node.\n");
141  }
142  else {
143  float *dst = (float *)mat->coba_builder->pixels[layer];
144  memcpy(dst, pixels, sizeof(float) * (CM_TABLE + 1) * 4);
145  mat->coba_builder->current_layer += 1;
146  }
147 
148  return &mat->coba_tex;
149 }
150 
152 {
153  if (mat->coba_builder == NULL) {
154  return;
155  }
156 
157  GPUColorBandBuilder *builder = mat->coba_builder;
158 
160  "mat_ramp", CM_TABLE + 1, builder->current_layer, 1, GPU_RGBA16F, (float *)builder->pixels);
161 
162  MEM_freeN(builder);
163  mat->coba_builder = NULL;
164 }
165 
167 {
168  /* Cancel / wait any pending lazy compilation. */
170 
171  gpu_node_graph_free(&material->graph);
172 
173  if (material->pass != NULL) {
174  GPU_pass_release(material->pass);
175  }
176  if (material->ubo != NULL) {
178  }
179  if (material->sss_tex_profile != NULL) {
180  GPU_texture_free(material->sss_tex_profile);
181  }
182  if (material->sss_profile != NULL) {
183  GPU_uniformbuf_free(material->sss_profile);
184  }
185  if (material->coba_tex != NULL) {
186  GPU_texture_free(material->coba_tex);
187  }
188 
189  BLI_gset_free(material->used_libraries, NULL);
190 }
191 
192 void GPU_material_free(ListBase *gpumaterial)
193 {
194  LISTBASE_FOREACH (LinkData *, link, gpumaterial) {
195  GPUMaterial *material = link->data;
198  }
199  BLI_freelistN(gpumaterial);
200 }
201 
203 {
204  return material->scene;
205 }
206 
208 {
209  return material->pass;
210 }
211 
213 {
214  return material->pass ? GPU_pass_shader_get(material->pass) : NULL;
215 }
216 
217 /* Return can be NULL if it's a world material. */
219 {
220  return material->ma;
221 }
222 
224 {
225  return material->ubo;
226 }
227 
234 {
235 #ifndef NDEBUG
236  const char *name = material->name;
237 #else
238  const char *name = "Material";
239 #endif
241 }
242 
243 /* Eevee Subsurface scattering. */
244 /* Based on Separable SSS. by Jorge Jimenez and Diego Gutierrez */
245 
246 #define SSS_SAMPLES 65
247 #define SSS_EXPONENT 2.0f /* Importance sampling exponent */
248 
249 typedef struct GPUSssKernelData {
250  float kernel[SSS_SAMPLES][4];
251  float param[3], max_radius;
252  int samples;
253  int pad[3];
255 
257 
258 static void sss_calculate_offsets(GPUSssKernelData *kd, int count, float exponent)
259 {
260  float step = 2.0f / (float)(count - 1);
261  for (int i = 0; i < count; i++) {
262  float o = ((float)i) * step - 1.0f;
263  float sign = (o < 0.0f) ? -1.0f : 1.0f;
264  float ofs = sign * fabsf(powf(o, exponent));
265  kd->kernel[i][3] = ofs;
266  }
267 }
268 
269 #define GAUSS_TRUNCATE 12.46f
270 static float gaussian_profile(float r, float radius)
271 {
272  const float v = radius * radius * (0.25f * 0.25f);
273  const float Rm = sqrtf(v * GAUSS_TRUNCATE);
274 
275  if (r >= Rm) {
276  return 0.0f;
277  }
278  return expf(-r * r / (2.0f * v)) / (2.0f * M_PI * v);
279 }
280 
281 #define BURLEY_TRUNCATE 16.0f
282 #define BURLEY_TRUNCATE_CDF 0.9963790093708328f // cdf(BURLEY_TRUNCATE)
283 static float burley_profile(float r, float d)
284 {
285  float exp_r_3_d = expf(-r / (3.0f * d));
286  float exp_r_d = exp_r_3_d * exp_r_3_d * exp_r_3_d;
287  return (exp_r_d + exp_r_3_d) / (4.0f * d);
288 }
289 
290 static float cubic_profile(float r, float radius, float sharpness)
291 {
292  float Rm = radius * (1.0f + sharpness);
293 
294  if (r >= Rm) {
295  return 0.0f;
296  }
297  /* custom variation with extra sharpness, to match the previous code */
298  const float y = 1.0f / (1.0f + sharpness);
299  float Rmy, ry, ryinv;
300 
301  Rmy = powf(Rm, y);
302  ry = powf(r, y);
303  ryinv = (r > 0.0f) ? powf(r, y - 1.0f) : 0.0f;
304 
305  const float Rmy5 = (Rmy * Rmy) * (Rmy * Rmy) * Rmy;
306  const float f = Rmy - ry;
307  const float num = f * (f * f) * (y * ryinv);
308 
309  return (10.0f * num) / (Rmy5 * M_PI);
310 }
311 
312 static float eval_profile(float r, short falloff_type, float sharpness, float param)
313 {
314  r = fabsf(r);
315 
317  return burley_profile(r, param) / BURLEY_TRUNCATE_CDF;
318  }
319  if (falloff_type == SHD_SUBSURFACE_CUBIC) {
320  return cubic_profile(r, param, sharpness);
321  }
322 
323  return gaussian_profile(r, param);
324 }
325 
326 /* Resolution for each sample of the precomputed kernel profile */
327 #define INTEGRAL_RESOLUTION 32
328 static float eval_integral(float x0, float x1, short falloff_type, float sharpness, float param)
329 {
330  const float range = x1 - x0;
331  const float step = range / INTEGRAL_RESOLUTION;
332  float integral = 0.0f;
333 
334  for (int i = 0; i < INTEGRAL_RESOLUTION; i++) {
335  float x = x0 + range * ((float)i + 0.5f) / (float)INTEGRAL_RESOLUTION;
336  float y = eval_profile(x, falloff_type, sharpness, param);
337  integral += y * step;
338  }
339 
340  return integral;
341 }
342 #undef INTEGRAL_RESOLUTION
343 
344 static void compute_sss_kernel(
345  GPUSssKernelData *kd, const float radii[3], int sample_len, int falloff_type, float sharpness)
346 {
347  float rad[3];
348  /* Minimum radius */
349  rad[0] = MAX2(radii[0], 1e-15f);
350  rad[1] = MAX2(radii[1], 1e-15f);
351  rad[2] = MAX2(radii[2], 1e-15f);
352 
353  /* Christensen-Burley fitting */
354  float l[3], d[3];
355 
357  mul_v3_v3fl(l, rad, 0.25f * M_1_PI);
358  const float A = 1.0f;
359  const float s = 1.9f - A + 3.5f * (A - 0.8f) * (A - 0.8f);
360  /* XXX 0.6f Out of nowhere to match cycles! Empirical! Can be tweak better. */
361  mul_v3_v3fl(d, l, 0.6f / s);
362  mul_v3_v3fl(rad, d, BURLEY_TRUNCATE);
363  kd->max_radius = MAX3(rad[0], rad[1], rad[2]);
364 
365  copy_v3_v3(kd->param, d);
366  }
367  else if (falloff_type == SHD_SUBSURFACE_CUBIC) {
368  copy_v3_v3(kd->param, rad);
369  mul_v3_fl(rad, 1.0f + sharpness);
370  kd->max_radius = MAX3(rad[0], rad[1], rad[2]);
371  }
372  else {
373  kd->max_radius = MAX3(rad[0], rad[1], rad[2]);
374 
375  copy_v3_v3(kd->param, rad);
376  }
377 
378  /* Compute samples locations on the 1d kernel [-1..1] */
379  sss_calculate_offsets(kd, sample_len, SSS_EXPONENT);
380 
381  /* Weights sum for normalization */
382  float sum[3] = {0.0f, 0.0f, 0.0f};
383 
384  /* Compute integral of each sample footprint */
385  for (int i = 0; i < sample_len; i++) {
386  float x0, x1;
387 
388  if (i == 0) {
389  x0 = kd->kernel[0][3] - fabsf(kd->kernel[0][3] - kd->kernel[1][3]) / 2.0f;
390  }
391  else {
392  x0 = (kd->kernel[i - 1][3] + kd->kernel[i][3]) / 2.0f;
393  }
394 
395  if (i == sample_len - 1) {
396  x1 = kd->kernel[sample_len - 1][3] +
397  fabsf(kd->kernel[sample_len - 2][3] - kd->kernel[sample_len - 1][3]) / 2.0f;
398  }
399  else {
400  x1 = (kd->kernel[i][3] + kd->kernel[i + 1][3]) / 2.0f;
401  }
402 
403  x0 *= kd->max_radius;
404  x1 *= kd->max_radius;
405 
406  kd->kernel[i][0] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[0]);
407  kd->kernel[i][1] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[1]);
408  kd->kernel[i][2] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[2]);
409 
410  sum[0] += kd->kernel[i][0];
411  sum[1] += kd->kernel[i][1];
412  sum[2] += kd->kernel[i][2];
413  }
414 
415  for (int i = 0; i < 3; i++) {
416  if (sum[i] > 0.0f) {
417  /* Normalize */
418  for (int j = 0; j < sample_len; j++) {
419  kd->kernel[j][i] /= sum[i];
420  }
421  }
422  else {
423  /* Avoid 0 kernel sum. */
424  kd->kernel[sample_len / 2][i] = 1.0f;
425  }
426  }
427 
428  /* Put center sample at the start of the array (to sample first) */
429  float tmpv[4];
430  copy_v4_v4(tmpv, kd->kernel[sample_len / 2]);
431  for (int i = sample_len / 2; i > 0; i--) {
432  copy_v4_v4(kd->kernel[i], kd->kernel[i - 1]);
433  }
434  copy_v4_v4(kd->kernel[0], tmpv);
435 
436  kd->samples = sample_len;
437 }
438 
439 #define INTEGRAL_RESOLUTION 512
441  int resolution,
442  short falloff_type,
443  float sharpness,
444  float **output)
445 {
446  float(*texels)[4];
447  texels = MEM_callocN(sizeof(float[4]) * resolution, "compute_sss_translucence_kernel");
448  *output = (float *)texels;
449 
450  /* Last texel should be black, hence the - 1. */
451  for (int i = 0; i < resolution - 1; i++) {
452  /* Distance from surface. */
453  float d = kd->max_radius * ((float)i + 0.00001f) / ((float)resolution);
454 
455  /* For each distance d we compute the radiance incoming from an hypothetic parallel plane. */
456  /* Compute radius of the footprint on the hypothetic plane */
457  float r_fp = sqrtf(kd->max_radius * kd->max_radius - d * d);
458  float r_step = r_fp / INTEGRAL_RESOLUTION;
459  float area_accum = 0.0f;
460  for (float r = 0.0f; r < r_fp; r += r_step) {
461  /* Compute distance to the "shading" point through the medium. */
462  /* r_step * 0.5f to put sample between the area borders */
463  float dist = hypotf(r + r_step * 0.5f, d);
464 
465  float profile[3];
466  profile[0] = eval_profile(dist, falloff_type, sharpness, kd->param[0]);
467  profile[1] = eval_profile(dist, falloff_type, sharpness, kd->param[1]);
468  profile[2] = eval_profile(dist, falloff_type, sharpness, kd->param[2]);
469 
470  /* Since the profile and configuration are radially symmetrical we
471  * can just evaluate it once and weight it accordingly */
472  float r_next = r + r_step;
473  float disk_area = (M_PI * r_next * r_next) - (M_PI * r * r);
474 
475  mul_v3_fl(profile, disk_area);
476  add_v3_v3(texels[i], profile);
477  area_accum += disk_area;
478  }
479  /* Normalize over the disk. */
480  mul_v3_fl(texels[i], 1.0f / (area_accum));
481  }
482 
483  /* Normalize */
484  for (int j = resolution - 2; j > 0; j--) {
485  texels[j][0] /= (texels[0][0] > 0.0f) ? texels[0][0] : 1.0f;
486  texels[j][1] /= (texels[0][1] > 0.0f) ? texels[0][1] : 1.0f;
487  texels[j][2] /= (texels[0][2] > 0.0f) ? texels[0][2] : 1.0f;
488  }
489 
490  /* First texel should be white */
491  texels[0][0] = (texels[0][0] > 0.0f) ? 1.0f : 0.0f;
492  texels[0][1] = (texels[0][1] > 0.0f) ? 1.0f : 0.0f;
493  texels[0][2] = (texels[0][2] > 0.0f) ? 1.0f : 0.0f;
494 
495  /* dim the last few texels for smoother transition */
496  mul_v3_fl(texels[resolution - 2], 0.25f);
497  mul_v3_fl(texels[resolution - 3], 0.5f);
498  mul_v3_fl(texels[resolution - 4], 0.75f);
499 }
500 #undef INTEGRAL_RESOLUTION
501 
503  float radii[3],
504  const short *falloff_type,
505  const float *sharpness)
506 {
507  copy_v3_v3(material->sss_radii, radii);
508  material->sss_falloff = (falloff_type) ? *falloff_type : 0.0;
509  material->sss_sharpness = (sharpness) ? *sharpness : 0.0;
510  material->sss_dirty = true;
511  material->sss_enabled = true;
512 
513  /* Update / Create UBO */
514  if (material->sss_profile == NULL) {
515  material->sss_profile = GPU_uniformbuf_create(sizeof(GPUSssKernelData));
516  }
517 }
518 
520  int sample_len,
521  GPUTexture **tex_profile)
522 {
523  if (!material->sss_enabled) {
524  return NULL;
525  }
526 
527  if (material->sss_dirty || (material->sss_samples != sample_len)) {
528  GPUSssKernelData kd;
529 
530  float sharpness = material->sss_sharpness;
531 
532  /* XXX Black magic but it seems to fit. Maybe because we integrate -1..1 */
533  sharpness *= 0.5f;
534 
535  compute_sss_kernel(&kd, material->sss_radii, sample_len, material->sss_falloff, sharpness);
536 
537  /* Update / Create UBO */
538  GPU_uniformbuf_update(material->sss_profile, &kd);
539 
540  /* Update / Create Tex */
541  float *translucence_profile;
543  &kd, 64, material->sss_falloff, sharpness, &translucence_profile);
544 
545  if (material->sss_tex_profile != NULL) {
546  GPU_texture_free(material->sss_tex_profile);
547  }
548 
549  material->sss_tex_profile = GPU_texture_create_1d(
550  "sss_tex_profile", 64, 1, GPU_RGBA16F, translucence_profile);
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 
565 {
566  return GPU_uniformbuf_create(sizeof(GPUSssKernelData));
567 }
568 
569 #undef SSS_EXPONENT
570 #undef SSS_SAMPLES
571 
573 {
574  return material->graph.attributes;
575 }
576 
578 {
579  return material->graph.textures;
580 }
581 
583 {
584  return material->graph.volume_grids;
585 }
586 
588 {
589  GPUUniformAttrList *attrs = &material->graph.uniform_attrs;
590  return attrs->count > 0 ? attrs : NULL;
591 }
592 
594 {
595  if (!material->graph.outlink) {
596  material->graph.outlink = link;
597  }
598 }
599 
601 {
602  GPUNodeGraphOutputLink *aov_link = MEM_callocN(sizeof(GPUNodeGraphOutputLink), __func__);
603  aov_link->outlink = link;
604  aov_link->hash = hash;
605  BLI_addtail(&material->graph.outlink_aovs, aov_link);
606 }
607 
609 {
610  return &material->graph;
611 }
612 
614 {
615  return material->used_libraries;
616 }
617 
618 /* Return true if the material compilation has not yet begin or begin. */
620 {
621  return mat->status;
622 }
623 
624 /* Code generation */
625 
627 {
628  return mat->has_surface_output;
629 }
630 
632 {
633  return mat->has_volume_output;
634 }
635 
637 {
638  return mat->is_volume_shader;
639 }
640 
642 {
643  mat->flag |= flag;
644 }
645 
647 {
648  return (mat->flag & flag) != 0;
649 }
650 
652  const void *engine_type,
653  int options)
654 {
655  LISTBASE_FOREACH (LinkData *, link, gpumaterials) {
656  GPUMaterial *current_material = (GPUMaterial *)link->data;
657  if (current_material->engine_type == engine_type && current_material->options == options) {
658  return current_material;
659  }
660  }
661 
662  return NULL;
663 }
664 
671  struct Material *ma,
672  struct bNodeTree *ntree,
673  ListBase *gpumaterials,
674  const void *engine_type,
675  const int options,
676  const bool is_volume_shader,
677  const char *vert_code,
678  const char *geom_code,
679  const char *frag_lib,
680  const char *defines,
681  const char *name,
683 {
684  LinkData *link;
685  bool has_volume_output, has_surface_output;
686 
687  /* Caller must re-use materials. */
688  BLI_assert(GPU_material_from_nodetree_find(gpumaterials, engine_type, options) == NULL);
689 
690  /* HACK: Eevee assume this to create Ghash keys. */
691  BLI_assert(sizeof(GPUPass) > 16);
692 
693  /* allocate material */
694  GPUMaterial *mat = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial");
695  mat->ma = ma;
696  mat->scene = scene;
697  mat->engine_type = engine_type;
698  mat->options = options;
699  mat->is_volume_shader = is_volume_shader;
700 #ifndef NDEBUG
701  BLI_snprintf(mat->name, sizeof(mat->name), "%s", name);
702 #else
703  UNUSED_VARS(name);
704 #endif
705 
707  BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "GPUMaterial.used_libraries");
708 
709  /* localize tree to create links for reroute and mute */
710  bNodeTree *localtree = ntreeLocalize(ntree);
711  ntreeGPUMaterialNodes(localtree, mat, &has_surface_output, &has_volume_output);
712 
714 
715  mat->has_surface_output = has_surface_output;
716  mat->has_volume_output = has_volume_output;
717 
718  if (mat->graph.outlink) {
719  if (callback) {
720  callback(mat, options, &vert_code, &geom_code, &frag_lib, &defines);
721  }
722  /* HACK: this is only for eevee. We add the define here after the nodetree evaluation. */
724  defines = BLI_string_joinN(defines,
725  "#ifndef USE_ALPHA_BLEND\n"
726  "# define USE_SSS\n"
727  "#endif\n");
728  }
729  /* Create source code and search pass cache for an already compiled version. */
730  mat->pass = GPU_generate_pass(mat, &mat->graph, vert_code, geom_code, frag_lib, defines);
731 
733  MEM_freeN((char *)defines);
734  }
735 
736  if (mat->pass == NULL) {
737  /* We had a cache hit and the shader has already failed to compile. */
738  mat->status = GPU_MAT_FAILED;
739  gpu_node_graph_free(&mat->graph);
740  }
741  else {
742  GPUShader *sh = GPU_pass_shader_get(mat->pass);
743  if (sh != NULL) {
744  /* We had a cache hit and the shader is already compiled. */
745  mat->status = GPU_MAT_SUCCESS;
747  }
748  else {
749  mat->status = GPU_MAT_QUEUED;
750  }
751  }
752  }
753  else {
754  mat->status = GPU_MAT_FAILED;
755  gpu_node_graph_free(&mat->graph);
756  }
757 
758  /* Only free after GPU_pass_shader_get where GPUUniformBuf
759  * read data from the local tree. */
760  ntreeFreeLocalTree(localtree);
761  BLI_assert(!localtree->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
762  MEM_freeN(localtree);
763 
764  /* note that even if building the shader fails in some way, we still keep
765  * it to avoid trying to compile again and again, and simply do not use
766  * the actual shader on drawing */
767 
768  link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink");
769  link->data = mat;
770  BLI_addtail(gpumaterials, link);
771 
772  return mat;
773 }
774 
776 {
777  bool success;
778 
780  BLI_assert(mat->pass);
781 
782  /* NOTE: The shader may have already been compiled here since we are
783  * sharing GPUShader across GPUMaterials. In this case it's a no-op. */
784 #ifndef NDEBUG
785  success = GPU_pass_compile(mat->pass, mat->name);
786 #else
787  success = GPU_pass_compile(mat->pass, __func__);
788 #endif
789 
790  if (success) {
791  GPUShader *sh = GPU_pass_shader_get(mat->pass);
792  if (sh != NULL) {
793  mat->status = GPU_MAT_SUCCESS;
795  }
796  }
797  else {
798  mat->status = GPU_MAT_FAILED;
799  GPU_pass_release(mat->pass);
800  mat->pass = NULL;
801  gpu_node_graph_free(&mat->graph);
802  }
803 }
804 
806 {
807  LISTBASE_FOREACH (Material *, ma, &bmain->materials) {
808  GPU_material_free(&ma->gpumaterial);
809  }
810 
811  LISTBASE_FOREACH (World *, wo, &bmain->worlds) {
812  GPU_material_free(&wo->gpumaterial);
813  }
814 
816 }
typedef float(TangentPoint)[2]
General operations, lookup, etc. for materials.
void BKE_material_defaults_free_gpu(void)
Definition: material.c:1844
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_STATIC_ASSERT_ALIGN(st, align)
Definition: BLI_assert.h:89
struct GSet GSet
Definition: BLI_ghash.h:189
unsigned int BLI_ghashutil_ptrhash(const void *key)
GSet * BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:1125
bool BLI_ghashutil_ptrcmp(const void *a, const void *b)
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1253
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
#define M_1_PI
Definition: BLI_math_base.h:59
#define M_PI
Definition: BLI_math_base.h:38
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
#define BLI_string_joinN(...)
#define MAX3(a, b, c)
#define UNUSED_VARS(...)
#define UNUSED_VARS_NDEBUG(...)
#define MAX2(a, b)
#define ELEM(...)
#define CM_TABLE
@ SHD_SUBSURFACE_BURLEY
@ SHD_SUBSURFACE_CUBIC
@ SHD_SUBSURFACE_RANDOM_WALK
void(* GPUMaterialEvalCallbackFn)(struct GPUMaterial *mat, int options, const char **vert_code, const char **geom_code, const char **frag_lib, const char **defines)
Definition: DRW_render.h:200
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
eGPUMatFlag
Definition: GPU_material.h:108
@ GPU_MATFLAG_SSS
Definition: GPU_material.h:112
eGPUMaterialStatus
Definition: GPU_material.h:126
@ GPU_MAT_QUEUED
Definition: GPU_material.h:128
@ GPU_MAT_FAILED
Definition: GPU_material.h:127
@ GPU_MAT_SUCCESS
Definition: GPU_material.h:129
struct GPUShader GPUShader
Definition: GPU_shader.h:33
GPUTexture * GPU_texture_create_1d_array(const char *name, int w, int h, int mip_len, eGPUTextureFormat format, const float *data)
Definition: gpu_texture.cc:243
GPUTexture * GPU_texture_create_1d(const char *name, int w, int mip_len, eGPUTextureFormat format, const float *data)
Definition: gpu_texture.cc:237
struct GPUTexture GPUTexture
Definition: GPU_texture.h:33
void GPU_texture_free(GPUTexture *tex)
Definition: gpu_texture.cc:508
@ GPU_RGBA16F
Definition: GPU_texture.h:94
struct GPUUniformBuf GPUUniformBuf
#define GPU_uniformbuf_create(size)
GPUUniformBuf * GPU_uniformbuf_create_from_list(struct ListBase *inputs, const char *name)
void GPU_uniformbuf_update(GPUUniformBuf *ubo, const void *data)
void GPU_uniformbuf_free(GPUUniformBuf *ubo)
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define A
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
#define output
static T sum(const btAlignedObjectArray< T > &items)
CCL_NAMESPACE_BEGIN struct Options options
Scene scene
Material material
DEGForeachIDComponentCallback callback
bNodeTree * ntree
void GPU_pass_release(GPUPass *pass)
Definition: gpu_codegen.c:1049
GPUPass * GPU_generate_pass(GPUMaterial *material, GPUNodeGraph *graph, const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines)
Definition: gpu_codegen.c:839
bool GPU_pass_compile(GPUPass *pass, const char *shname)
Definition: gpu_codegen.c:1025
GPUShader * GPU_pass_shader_get(GPUPass *pass)
Definition: gpu_codegen.c:826
#define SSS_EXPONENT
Definition: gpu_material.c:247
static void gpu_material_ramp_texture_build(GPUMaterial *mat)
Definition: gpu_material.c:151
static void gpu_material_free_single(GPUMaterial *material)
Definition: gpu_material.c:166
static void compute_sss_kernel(GPUSssKernelData *kd, const float radii[3], int sample_len, int falloff_type, float sharpness)
Definition: gpu_material.c:344
GSet * gpu_material_used_libraries(GPUMaterial *material)
Definition: gpu_material.c:613
GPUNodeGraph * gpu_material_node_graph(GPUMaterial *material)
Definition: gpu_material.c:608
GPUUniformAttrList * GPU_material_uniform_attributes(GPUMaterial *material)
Definition: gpu_material.c:587
void GPU_material_compile(GPUMaterial *mat)
Definition: gpu_material.c:775
void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link)
Definition: gpu_material.c:593
bool GPU_material_has_surface_output(GPUMaterial *mat)
Definition: gpu_material.c:626
GPUMaterial * GPU_material_from_nodetree(Scene *scene, struct Material *ma, struct bNodeTree *ntree, ListBase *gpumaterials, const void *engine_type, const int options, const bool is_volume_shader, const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines, const char *name, GPUMaterialEvalCallbackFn callback)
Definition: gpu_material.c:670
static float eval_integral(float x0, float x1, short falloff_type, float sharpness, float param)
Definition: gpu_material.c:328
void GPU_materials_free(Main *bmain)
Definition: gpu_material.c:805
void GPU_material_free(ListBase *gpumaterial)
Definition: gpu_material.c:192
static float burley_profile(float r, float d)
Definition: gpu_material.c:283
struct GPUColorBandBuilder GPUColorBandBuilder
void GPU_material_add_output_link_aov(GPUMaterial *material, GPUNodeLink *link, int hash)
Definition: gpu_material.c:600
static float cubic_profile(float r, float radius, float sharpness)
Definition: gpu_material.c:290
GPUShader * GPU_material_get_shader(GPUMaterial *material)
Definition: gpu_material.c:212
#define BURLEY_TRUNCATE
Definition: gpu_material.c:281
ListBase GPU_material_textures(GPUMaterial *material)
Definition: gpu_material.c:577
GPUUniformBuf * GPU_material_uniform_buffer_get(GPUMaterial *material)
Definition: gpu_material.c:223
struct GPUUniformBuf * GPU_material_sss_profile_get(GPUMaterial *material, int sample_len, GPUTexture **tex_profile)
Definition: gpu_material.c:519
GPUTexture ** gpu_material_ramp_texture_row_set(GPUMaterial *mat, int size, float *pixels, float *row)
Definition: gpu_material.c:121
GPUPass * GPU_material_get_pass(GPUMaterial *material)
Definition: gpu_material.c:207
static void compute_sss_translucence_kernel(const GPUSssKernelData *kd, int resolution, short falloff_type, float sharpness, float **output)
Definition: gpu_material.c:440
static float eval_profile(float r, short falloff_type, float sharpness, float param)
Definition: gpu_material.c:312
GPUMaterial * GPU_material_from_nodetree_find(ListBase *gpumaterials, const void *engine_type, int options)
Definition: gpu_material.c:651
#define BURLEY_TRUNCATE_CDF
Definition: gpu_material.c:282
@ GPU_USE_VOLUME_OUTPUT
Definition: gpu_material.c:115
@ GPU_USE_SURFACE_OUTPUT
Definition: gpu_material.c:114
#define GAUSS_TRUNCATE
Definition: gpu_material.c:269
Scene * GPU_material_scene(GPUMaterial *material)
Definition: gpu_material.c:202
eGPUMaterialStatus GPU_material_status(GPUMaterial *mat)
Definition: gpu_material.c:619
bool GPU_material_is_volume_shader(GPUMaterial *mat)
Definition: gpu_material.c:636
struct GPUUniformBuf * GPU_material_create_sss_profile_ubo(void)
Definition: gpu_material.c:564
Material * GPU_material_get_material(GPUMaterial *material)
Definition: gpu_material.c:218
void GPU_material_flag_set(GPUMaterial *mat, eGPUMatFlag flag)
Definition: gpu_material.c:641
struct GPUSssKernelData GPUSssKernelData
#define SSS_SAMPLES
Definition: gpu_material.c:246
ListBase GPU_material_volume_grids(GPUMaterial *material)
Definition: gpu_material.c:582
ListBase GPU_material_attributes(GPUMaterial *material)
Definition: gpu_material.c:572
static void sss_calculate_offsets(GPUSssKernelData *kd, int count, float exponent)
Definition: gpu_material.c:258
static float gaussian_profile(float r, float radius)
Definition: gpu_material.c:270
void GPU_material_sss_profile_create(GPUMaterial *material, float radii[3], const short *falloff_type, const float *sharpness)
Definition: gpu_material.c:502
#define INTEGRAL_RESOLUTION
Definition: gpu_material.c:439
void GPU_material_uniform_buffer_create(GPUMaterial *material, ListBase *inputs)
Definition: gpu_material.c:233
#define MAX_COLOR_BAND
Definition: gpu_material.c:58
bool GPU_material_has_volume_output(GPUMaterial *mat)
Definition: gpu_material.c:631
bool GPU_material_flag_get(GPUMaterial *mat, eGPUMatFlag flag)
Definition: gpu_material.c:646
void gpu_node_graph_free(GPUNodeGraph *graph)
void gpu_node_graph_free_nodes(GPUNodeGraph *graph)
int count
void * DRW_deferred_shader_remove
void * ntreeGPUMaterialNodes
#define expf(x)
#define powf(x, y)
#define hypotf(x, y)
#define fabsf(x)
#define sqrtf(x)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
double sign(double arg)
Definition: utility.h:250
static bNodeSocketTemplate inputs[]
#define hash
Definition: noise.c:169
float pixels[MAX_COLOR_BAND][CM_TABLE+1][4]
Definition: gpu_material.c:61
GPUUniformBuf * ubo
Definition: gpu_material.c:91
GSet * used_libraries
Definition: gpu_material.c:106
GPUColorBandBuilder * coba_builder
Definition: gpu_material.c:104
Scene * scene
Definition: gpu_material.c:66
float sss_radii[3]
Definition: gpu_material.c:97
GPUTexture * sss_tex_profile
Definition: gpu_material.c:95
float sss_sharpness
Definition: gpu_material.c:100
eGPUMatFlag flag
Definition: gpu_material.c:88
GPUUniformBuf * sss_profile
Definition: gpu_material.c:94
bool has_volume_output
Definition: gpu_material.c:84
bool has_surface_output
Definition: gpu_material.c:85
short int sss_falloff
Definition: gpu_material.c:99
GPUTexture * coba_tex
Definition: gpu_material.c:103
Material * ma
Definition: gpu_material.c:67
char name[64]
Definition: gpu_material.c:109
GPUPass * pass
Definition: gpu_material.c:79
GPUNodeGraph graph
Definition: gpu_material.c:76
bool is_volume_shader
Definition: gpu_material.c:73
eGPUMaterialStatus status
Definition: gpu_material.c:69
const void * engine_type
Definition: gpu_material.c:71
float sss_enabled
Definition: gpu_material.c:96
GPUNodeLink * outlink
float kernel[SSS_SAMPLES][4]
Definition: gpu_material.c:250
unsigned int count
Definition: GPU_material.h:281
void * py_instance
Definition: DNA_ID.h:340
void * data
Definition: DNA_listBase.h:42
Definition: BKE_main.h:116
ListBase materials
Definition: BKE_main.h:152
ListBase worlds
Definition: BKE_main.h:160