Blender  V3.3
gpu_codegen.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2005 Blender Foundation. */
3 
10 #include "MEM_guardedalloc.h"
11 
12 #include "DNA_customdata_types.h"
13 #include "DNA_image_types.h"
14 
15 #include "BLI_ghash.h"
16 #include "BLI_hash_mm2a.h"
17 #include "BLI_link_utils.h"
18 #include "BLI_threads.h"
19 #include "BLI_utildefines.h"
20 
21 #include "PIL_time.h"
22 
23 #include "BKE_material.h"
24 
25 #include "GPU_capabilities.h"
26 #include "GPU_material.h"
27 #include "GPU_shader.h"
28 #include "GPU_uniform_buffer.h"
29 #include "GPU_vertex_format.h"
30 
31 #include "BLI_sys_types.h" /* for intptr_t support */
32 #include "BLI_vector.hh"
33 
34 #include "gpu_codegen.h"
35 #include "gpu_node_graph.h"
38 
39 #include <cstdarg>
40 #include <cstring>
41 
42 #include <sstream>
43 #include <string>
44 
45 using namespace blender::gpu::shader;
46 
54  struct NameBuffer {
55  using NameEntry = std::array<char, 32>;
56 
58  char attr_names[16][GPU_MAX_SAFE_ATTR_NAME + 1];
59  char var_names[16][8];
61 
62  /* Returns the appended name memory location */
63  const char *append_sampler_name(const char name[32])
64  {
65  auto index = sampler_names.size();
66  sampler_names.append(std::make_unique<NameEntry>());
67  char *name_buffer = sampler_names[index]->data();
68  memcpy(name_buffer, name, 32);
69  return name_buffer;
70  }
71  };
72 
74  StageInterfaceInfo *interface_generated = nullptr;
77 
78  GPUCodegenCreateInfo(const char *name) : ShaderCreateInfo(name){};
80  {
81  delete interface_generated;
82  };
83 };
84 
85 struct GPUPass {
86  struct GPUPass *next;
87 
95  bool compiled;
96 };
97 
98 /* -------------------------------------------------------------------- */
106 /* Only use one linklist that contains the GPUPasses grouped by hash. */
107 static GPUPass *pass_cache = nullptr;
109 
110 /* Search by hash only. Return first pass with the same hash.
111  * There is hash collision if (pass->next && pass->next->hash == hash) */
113 {
115  /* Could be optimized with a Lookup table. */
116  for (GPUPass *pass = pass_cache; pass; pass = pass->next) {
117  if (pass->hash == hash) {
119  return pass;
120  }
121  }
123  return nullptr;
124 }
125 
127 {
129  if (node != nullptr) {
130  /* Add after the first pass having the same hash. */
131  pass->next = node->next;
132  node->next = pass;
133  }
134  else {
135  /* No other pass have same hash, just prepend to the list. */
137  }
139 }
140 
141 /* Check all possible passes with the same hash. */
143  GPUShaderCreateInfo *info,
144  uint32_t hash)
145 {
147  for (; pass && (pass->hash == hash); pass = pass->next) {
148  if (*reinterpret_cast<ShaderCreateInfo *>(info) ==
149  *reinterpret_cast<ShaderCreateInfo *>(pass->create_info)) {
151  return pass;
152  }
153  }
155  return nullptr;
156 }
157 
158 static bool gpu_pass_is_valid(GPUPass *pass)
159 {
160  /* Shader is not null if compilation is successful. */
161  return (pass->compiled == false || pass->shader != nullptr);
162 }
163 
166 /* -------------------------------------------------------------------- */
170 static std::ostream &operator<<(std::ostream &stream, const GPUInput *input)
171 {
172  switch (input->source) {
174  case GPU_SOURCE_OUTPUT:
175  return stream << "tmp" << input->id;
176  case GPU_SOURCE_CONSTANT:
177  return stream << "cons" << input->id;
178  case GPU_SOURCE_UNIFORM:
179  return stream << "node_tree.u" << input->id;
180  case GPU_SOURCE_ATTR:
181  return stream << "var_attrs.v" << input->attr->id;
183  return stream << "unf_attrs[resource_id].attr" << input->uniform_attr->id;
184  case GPU_SOURCE_STRUCT:
185  return stream << "strct" << input->id;
186  case GPU_SOURCE_TEX:
187  return stream << input->texture->sampler_name;
189  return stream << input->texture->tiled_mapping_name;
190  default:
191  BLI_assert(0);
192  return stream;
193  }
194 }
195 
196 static std::ostream &operator<<(std::ostream &stream, const GPUOutput *output)
197 {
198  return stream << "tmp" << output->id;
199 }
200 
201 /* Trick type to change overload and keep a somewhat nice syntax. */
202 struct GPUConstant : public GPUInput {
203 };
204 
205 /* Print data constructor (i.e: vec2(1.0f, 1.0f)). */
206 static std::ostream &operator<<(std::ostream &stream, const GPUConstant *input)
207 {
208  stream << input->type << "(";
209  for (int i = 0; i < input->type; i++) {
210  char formated_float[32];
211  /* Print with the maximum precision for single precision float using scientific notation.
212  * See https://stackoverflow.com/questions/16839658/#answer-21162120 */
213  SNPRINTF(formated_float, "%.9g", input->vec[i]);
214  stream << formated_float;
215  if (i < input->type - 1) {
216  stream << ", ";
217  }
218  }
219  stream << ")";
220  return stream;
221 }
222 
225 /* -------------------------------------------------------------------- */
229 class GPUCodegen {
230  public:
234  GPUCodegenCreateInfo *create_info = nullptr;
235 
236  private:
237  uint32_t hash_ = 0;
238  BLI_HashMurmur2A hm2a_;
239  ListBase ubo_inputs_ = {nullptr, nullptr};
240 
241  public:
242  GPUCodegen(GPUMaterial *mat_, GPUNodeGraph *graph_) : mat(*mat_), graph(*graph_)
243  {
246  create_info = new GPUCodegenCreateInfo("codegen");
247  output.create_info = reinterpret_cast<GPUShaderCreateInfo *>(
248  static_cast<ShaderCreateInfo *>(create_info));
249 
251  create_info->additional_info("draw_object_infos");
252  }
253  }
254 
256  {
257  MEM_SAFE_FREE(output.attr_load);
258  MEM_SAFE_FREE(output.surface);
259  MEM_SAFE_FREE(output.volume);
260  MEM_SAFE_FREE(output.thickness);
261  MEM_SAFE_FREE(output.displacement);
262  MEM_SAFE_FREE(output.material_functions);
263  delete create_info;
264  BLI_freelistN(&ubo_inputs_);
265  };
266 
267  void generate_graphs();
268  void generate_uniform_buffer();
269  void generate_attribs();
270  void generate_resources();
271  void generate_library();
272 
274  {
275  return hash_;
276  }
277 
278  private:
279  void set_unique_ids();
280 
281  void node_serialize(std::stringstream &eval_ss, const GPUNode *node);
282  char *graph_serialize(eGPUNodeTag tree_tag, GPUNodeLink *output_link);
283 
284  static char *extract_c_str(std::stringstream &stream)
285  {
286  auto string = stream.str();
287  return BLI_strdup(string.c_str());
288  }
289 };
290 
292 {
293  if (BLI_listbase_is_empty(&graph.attributes)) {
294  output.attr_load = nullptr;
295  return;
296  }
297 
298  GPUCodegenCreateInfo &info = *create_info;
299 
300  info.interface_generated = new StageInterfaceInfo("codegen_iface", "var_attrs");
302  info.vertex_out(iface);
303 
304  /* Input declaration, loading / assignment to interface and geometry shader passthrough. */
305  std::stringstream load_ss;
306 
307  int slot = 15;
308  LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph.attributes) {
309  if (slot == -1) {
310  BLI_assert_msg(0, "Too many attributes");
311  break;
312  }
313  STRNCPY(info.name_buffer.attr_names[slot], attr->input_name);
314  SNPRINTF(info.name_buffer.var_names[slot], "v%d", attr->id);
315 
316  blender::StringRefNull attr_name = info.name_buffer.attr_names[slot];
317  blender::StringRefNull var_name = info.name_buffer.var_names[slot];
318 
319  eGPUType input_type, iface_type;
320 
321  load_ss << "var_attrs." << var_name;
322  switch (attr->type) {
323  case CD_ORCO:
324  /* Need vec4 to detect usage of default attribute. */
325  input_type = GPU_VEC4;
326  iface_type = GPU_VEC3;
327  load_ss << " = attr_load_orco(" << attr_name << ");\n";
328  break;
329  case CD_HAIRLENGTH:
330  iface_type = input_type = GPU_FLOAT;
331  load_ss << " = attr_load_" << input_type << "(" << attr_name << ");\n";
332  break;
333  case CD_TANGENT:
334  iface_type = input_type = GPU_VEC4;
335  load_ss << " = attr_load_tangent(" << attr_name << ");\n";
336  break;
337  default:
338  iface_type = input_type = GPU_VEC4;
339  load_ss << " = attr_load_" << input_type << "(" << attr_name << ");\n";
340  break;
341  }
342 
343  info.vertex_in(slot--, to_type(input_type), attr_name);
344  iface.smooth(to_type(iface_type), var_name);
345  }
346 
347  output.attr_load = extract_c_str(load_ss);
348 }
349 
351 {
352  GPUCodegenCreateInfo &info = *create_info;
353 
354  /* Ref. T98190: Defines are optimizations for old compilers.
355  * Might become unecessary with EEVEE-Next. */
357  info.define("PRINCIPLED_CLEARCOAT");
358  }
360  info.define("PRINCIPLED_METALLIC");
361  }
363  info.define("PRINCIPLED_DIELECTRIC");
364  }
366  info.define("PRINCIPLED_GLASS");
367  }
369  info.define("PRINCIPLED_ANY");
370  }
371 
372  std::stringstream ss;
373 
374  /* Textures. */
375  LISTBASE_FOREACH (GPUMaterialTexture *, tex, &graph.textures) {
376  if (tex->colorband) {
377  const char *name = info.name_buffer.append_sampler_name(tex->sampler_name);
379  }
380  else if (tex->tiled_mapping_name[0] != '\0') {
381  const char *name = info.name_buffer.append_sampler_name(tex->sampler_name);
383 
384  const char *name_mapping = info.name_buffer.append_sampler_name(tex->tiled_mapping_name);
385  info.sampler(0, ImageType::FLOAT_1D_ARRAY, name_mapping, Frequency::BATCH);
386  }
387  else {
388  const char *name = info.name_buffer.append_sampler_name(tex->sampler_name);
390  }
391  }
392 
393  if (!BLI_listbase_is_empty(&ubo_inputs_)) {
394  /* NOTE: generate_uniform_buffer() should have sorted the inputs before this. */
395  ss << "struct NodeTree {\n";
396  LISTBASE_FOREACH (LinkData *, link, &ubo_inputs_) {
397  GPUInput *input = (GPUInput *)(link->data);
398  ss << input->type << " u" << input->id << ";\n";
399  }
400  ss << "};\n\n";
401 
402  info.uniform_buf(0, "NodeTree", GPU_UBO_BLOCK_NAME, Frequency::BATCH);
403  }
404 
405  if (!BLI_listbase_is_empty(&graph.uniform_attrs.list)) {
406  ss << "struct UniformAttrs {\n";
407  LISTBASE_FOREACH (GPUUniformAttr *, attr, &graph.uniform_attrs.list) {
408  ss << "vec4 attr" << attr->id << ";\n";
409  }
410  ss << "};\n\n";
411 
412  /* TODO(fclem): Use the macro for length. Currently not working for EEVEE. */
413  /* DRW_RESOURCE_CHUNK_LEN = 512 */
414  info.uniform_buf(0, "UniformAttrs", GPU_ATTRIBUTE_UBO_BLOCK_NAME "[512]", Frequency::BATCH);
415  }
416 
417  info.typedef_source_generated = ss.str();
418 }
419 
421 {
422  GPUCodegenCreateInfo &info = *create_info;
423 
424  void *value;
425  GSetIterState pop_state = {};
426  while (BLI_gset_pop(graph.used_libraries, &pop_state, &value)) {
427  auto deps = gpu_shader_dependency_get_resolved_source((const char *)value);
429  }
430 }
431 
432 void GPUCodegen::node_serialize(std::stringstream &eval_ss, const GPUNode *node)
433 {
434  /* Declare constants. */
435  LISTBASE_FOREACH (GPUInput *, input, &node->inputs) {
436  switch (input->source) {
438  eval_ss << input->type << " " << input << "; " << input->function_call << input << ");\n";
439  break;
440  case GPU_SOURCE_STRUCT:
441  eval_ss << input->type << " " << input << " = CLOSURE_DEFAULT;\n";
442  break;
443  case GPU_SOURCE_CONSTANT:
444  eval_ss << input->type << " " << input << " = " << (GPUConstant *)input << ";\n";
445  break;
446  default:
447  break;
448  }
449  }
450  /* Declare temporary variables for node output storage. */
451  LISTBASE_FOREACH (GPUOutput *, output, &node->outputs) {
452  eval_ss << output->type << " " << output << ";\n";
453  }
454 
455  /* Function call. */
456  eval_ss << node->name << "(";
457  /* Input arguments. */
458  LISTBASE_FOREACH (GPUInput *, input, &node->inputs) {
459  switch (input->source) {
460  case GPU_SOURCE_OUTPUT:
461  case GPU_SOURCE_ATTR: {
462  /* These inputs can have non matching types. Do conversion. */
463  eGPUType to = input->type;
464  eGPUType from = (input->source == GPU_SOURCE_ATTR) ? input->attr->gputype :
465  input->link->output->type;
466  if (from != to) {
467  /* Use defines declared inside codegen_lib (i.e: vec4_from_float). */
468  eval_ss << to << "_from_" << from << "(";
469  }
470 
471  if (input->source == GPU_SOURCE_ATTR) {
472  eval_ss << input;
473  }
474  else {
475  eval_ss << input->link->output;
476  }
477 
478  if (from != to) {
479  eval_ss << ")";
480  }
481  break;
482  }
483  default:
484  eval_ss << input;
485  break;
486  }
487  eval_ss << ", ";
488  }
489  /* Output arguments. */
490  LISTBASE_FOREACH (GPUOutput *, output, &node->outputs) {
491  eval_ss << output;
492  if (output->next) {
493  eval_ss << ", ";
494  }
495  }
496  eval_ss << ");\n\n";
497 }
498 
499 char *GPUCodegen::graph_serialize(eGPUNodeTag tree_tag, GPUNodeLink *output_link)
500 {
501  if (output_link == nullptr) {
502  return nullptr;
503  }
504 
505  std::stringstream eval_ss;
506  /* NOTE: The node order is already top to bottom (or left to right in node editor)
507  * because of the evaluation order inside ntreeExecGPUNodes(). */
508  LISTBASE_FOREACH (GPUNode *, node, &graph.nodes) {
509  if ((node->tag & tree_tag) == 0) {
510  continue;
511  }
512  node_serialize(eval_ss, node);
513  }
514  eval_ss << "return " << output_link->output << ";\n";
515 
516  char *eval_c_str = extract_c_str(eval_ss);
517  BLI_hash_mm2a_add(&hm2a_, (uchar *)eval_c_str, eval_ss.str().size());
518  return eval_c_str;
519 }
520 
522 {
523  /* Extract uniform inputs. */
524  LISTBASE_FOREACH (GPUNode *, node, &graph.nodes) {
525  LISTBASE_FOREACH (GPUInput *, input, &node->inputs) {
526  if (input->source == GPU_SOURCE_UNIFORM && !input->link) {
527  /* We handle the UBO uniforms separately. */
528  BLI_addtail(&ubo_inputs_, BLI_genericNodeN(input));
529  }
530  }
531  }
532  if (!BLI_listbase_is_empty(&ubo_inputs_)) {
533  /* This sorts the inputs based on size. */
534  GPU_material_uniform_buffer_create(&mat, &ubo_inputs_);
535  }
536 }
537 
538 /* Sets id for unique names for all inputs, resources and temp variables. */
539 void GPUCodegen::set_unique_ids()
540 {
541  int id = 1;
542  LISTBASE_FOREACH (GPUNode *, node, &graph.nodes) {
543  LISTBASE_FOREACH (GPUInput *, input, &node->inputs) {
544  input->id = id++;
545  }
546  LISTBASE_FOREACH (GPUOutput *, output, &node->outputs) {
547  output->id = id++;
548  }
549  }
550 }
551 
553 {
554  set_unique_ids();
555 
556  output.surface = graph_serialize(GPU_NODE_TAG_SURFACE | GPU_NODE_TAG_AOV, graph.outlink_surface);
557  output.volume = graph_serialize(GPU_NODE_TAG_VOLUME, graph.outlink_volume);
558  output.displacement = graph_serialize(GPU_NODE_TAG_DISPLACEMENT, graph.outlink_displacement);
559  output.thickness = graph_serialize(GPU_NODE_TAG_THICKNESS, graph.outlink_thickness);
560 
561  if (!BLI_listbase_is_empty(&graph.material_functions)) {
562  std::stringstream eval_ss;
563  eval_ss << "\n/* Generated Functions */\n\n";
564  LISTBASE_FOREACH (GPUNodeGraphFunctionLink *, func_link, &graph.material_functions) {
565  char *fn = graph_serialize(GPU_NODE_TAG_FUNCTION, func_link->outlink);
566  eval_ss << "float " << func_link->name << "() {\n" << fn << "}\n\n";
567  MEM_SAFE_FREE(fn);
568  }
569  output.material_functions = extract_c_str(eval_ss);
570  }
571 
572  LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph.attributes) {
573  BLI_hash_mm2a_add(&hm2a_, (uchar *)attr->name, strlen(attr->name));
574  }
575 
576  hash_ = BLI_hash_mm2a_end(&hm2a_);
577 }
578 
581 /* -------------------------------------------------------------------- */
587  GPUCodegenCallbackFn finalize_source_cb,
588  void *thunk)
589 {
590  /* Prune the unused nodes and extract attributes before compiling so the
591  * generated VBOs are ready to accept the future shader. */
594 
595  GPUCodegen codegen(material, graph);
596  codegen.generate_graphs();
597  codegen.generate_uniform_buffer();
598 
599  /* Cache lookup: Reuse shaders already compiled. */
600  GPUPass *pass_hash = gpu_pass_cache_lookup(codegen.hash_get());
601 
602  /* FIXME(fclem): This is broken. Since we only check for the hash and not the full source
603  * there is no way to have a collision currently. Some advocated to only use a bigger hash. */
604  if (pass_hash && (pass_hash->next == nullptr || pass_hash->next->hash != codegen.hash_get())) {
605  if (!gpu_pass_is_valid(pass_hash)) {
606  /* Shader has already been created but failed to compile. */
607  return nullptr;
608  }
609  /* No collision, just return the pass. */
611  pass_hash->refcount += 1;
613  return pass_hash;
614  }
615 
616  /* Either the shader is not compiled or there is a hash collision...
617  * continue generating the shader strings. */
618  codegen.generate_attribs();
619  codegen.generate_resources();
620  codegen.generate_library();
621 
622  /* Make engine add its own code and implement the generated functions. */
623  finalize_source_cb(thunk, material, &codegen.output);
624 
625  GPUPass *pass = nullptr;
626  if (pass_hash) {
627  /* Cache lookup: Reuse shaders already compiled. */
629  pass_hash, codegen.output.create_info, codegen.hash_get());
630  }
631 
632  if (pass) {
633  /* Cache hit. Reuse the same GPUPass and GPUShader. */
634  if (!gpu_pass_is_valid(pass)) {
635  /* Shader has already been created but failed to compile. */
636  return nullptr;
637  }
639  pass->refcount += 1;
641  }
642  else {
643  /* We still create a pass even if shader compilation
644  * fails to avoid trying to compile again and again. */
645  pass = (GPUPass *)MEM_callocN(sizeof(GPUPass), "GPUPass");
646  pass->shader = nullptr;
647  pass->refcount = 1;
648  pass->create_info = codegen.create_info;
649  pass->hash = codegen.hash_get();
650  pass->compiled = false;
651 
652  codegen.create_info = nullptr;
653 
654  gpu_pass_cache_insert_after(pass_hash, pass);
655  }
656  return pass;
657 }
658 
661 /* -------------------------------------------------------------------- */
666 {
667  int num_samplers = 0;
668 
669  for (const ShaderCreateInfo::Resource &res : pass->create_info->pass_resources_) {
670  if (res.bind_type == ShaderCreateInfo::Resource::BindType::SAMPLER) {
671  if (GPU_shader_get_uniform(shader, res.sampler.name.c_str()) != -1) {
672  num_samplers += 1;
673  }
674  }
675  }
676 
677  return num_samplers;
678 }
679 
680 static bool gpu_pass_shader_validate(GPUPass *pass, GPUShader *shader)
681 {
682  if (shader == nullptr) {
683  return false;
684  }
685 
686  /* NOTE: The only drawback of this method is that it will count a sampler
687  * used in the fragment shader and only declared (but not used) in the vertex
688  * shader as used by both. But this corner case is not happening for now. */
689  int active_samplers_len = count_active_texture_sampler(pass, shader);
690 
691  /* Validate against opengl limit. */
692  if ((active_samplers_len > GPU_max_textures_frag()) ||
693  (active_samplers_len > GPU_max_textures_vert())) {
694  return false;
695  }
696 
697  if (pass->create_info->geometry_source_.is_empty() == false) {
698  if (active_samplers_len > GPU_max_textures_geom()) {
699  return false;
700  }
701  }
702 
703  return (active_samplers_len * 3 <= GPU_max_textures());
704 }
705 
706 bool GPU_pass_compile(GPUPass *pass, const char *shname)
707 {
708  bool success = true;
709  if (!pass->compiled) {
710  GPUShaderCreateInfo *info = reinterpret_cast<GPUShaderCreateInfo *>(
711  static_cast<ShaderCreateInfo *>(pass->create_info));
712 
713  pass->create_info->name_ = shname;
714 
715  GPUShader *shader = GPU_shader_create_from_info(info);
716 
717  /* NOTE: Some drivers / gpu allows more active samplers than the opengl limit.
718  * We need to make sure to count active samplers to avoid undefined behavior. */
719  if (!gpu_pass_shader_validate(pass, shader)) {
720  success = false;
721  if (shader != nullptr) {
722  fprintf(stderr, "GPUShader: error: too many samplers in shader.\n");
723  GPU_shader_free(shader);
724  shader = nullptr;
725  }
726  }
727  pass->shader = shader;
728  pass->compiled = true;
729  }
730  return success;
731 }
732 
734 {
735  return pass->shader;
736 }
737 
739 {
741  BLI_assert(pass->refcount > 0);
742  pass->refcount--;
744 }
745 
746 static void gpu_pass_free(GPUPass *pass)
747 {
748  BLI_assert(pass->refcount == 0);
749  if (pass->shader) {
750  GPU_shader_free(pass->shader);
751  }
752  delete pass->create_info;
753  MEM_freeN(pass);
754 }
755 
757 {
758  static int lasttime = 0;
759  const int shadercollectrate = 60; /* hardcoded for now. */
760  int ctime = (int)PIL_check_seconds_timer();
761 
762  if (ctime < shadercollectrate + lasttime) {
763  return;
764  }
765 
766  lasttime = ctime;
767 
769  GPUPass *next, **prev_pass = &pass_cache;
770  for (GPUPass *pass = pass_cache; pass; pass = next) {
771  next = pass->next;
772  if (pass->refcount == 0) {
773  /* Remove from list */
774  *prev_pass = next;
775  gpu_pass_free(pass);
776  }
777  else {
778  prev_pass = &pass->next;
779  }
780  }
782 }
783 
785 {
787 }
788 
790 {
792  while (pass_cache) {
795  pass_cache = next;
796  }
798 
800 }
801 
804 /* -------------------------------------------------------------------- */
809 {
810 }
811 
813 {
814  // BKE_world_defaults_free_gpu();
817 }
818 
General operations, lookup, etc. for materials.
void BKE_material_defaults_free_gpu(void)
Definition: material.c:2066
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
bool BLI_gset_pop(GSet *gs, GSetIterState *state, void **r_key) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_ghash.c:1012
void BLI_hash_mm2a_init(BLI_HashMurmur2A *mm2, uint32_t seed)
Definition: hash_mm2a.c:61
void BLI_hash_mm2a_add(BLI_HashMurmur2A *mm2, const unsigned char *data, size_t len)
Definition: hash_mm2a.c:69
void BLI_hash_mm2a_add_int(BLI_HashMurmur2A *mm2, int data)
Definition: hash_mm2a.c:84
uint32_t BLI_hash_mm2a_end(BLI_HashMurmur2A *mm2)
Definition: hash_mm2a.c:89
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
struct LinkData * BLI_genericNodeN(void *data)
Definition: listbase.c:842
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
#define STRNCPY(dst, src)
Definition: BLI_string.h:483
#define SNPRINTF(dst, format,...)
Definition: BLI_string.h:485
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:42
unsigned char uchar
Definition: BLI_sys_types.h:70
unsigned int uint
Definition: BLI_sys_types.h:67
pthread_spinlock_t SpinLock
Definition: BLI_threads.h:110
void BLI_spin_init(SpinLock *spin)
Definition: threads.cc:419
void BLI_spin_unlock(SpinLock *spin)
Definition: threads.cc:452
void BLI_spin_lock(SpinLock *spin)
Definition: threads.cc:433
void BLI_spin_end(SpinLock *spin)
Definition: threads.cc:467
@ CD_HAIRLENGTH
@ CD_TANGENT
int GPU_max_textures_vert(void)
int GPU_max_textures_frag(void)
int GPU_max_textures_geom(void)
int GPU_max_textures(void)
_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 type
uint64_t GPU_material_uuid_get(GPUMaterial *mat)
Definition: gpu_material.c:619
void(* GPUCodegenCallbackFn)(void *thunk, GPUMaterial *mat, GPUCodegenOutput *codegen)
Definition: GPU_material.h:137
bool GPU_material_flag_get(const GPUMaterial *mat, eGPUMaterialFlag flag)
Definition: gpu_material.c:601
@ GPU_MATFLAG_PRINCIPLED_GLASS
Definition: GPU_material.h:91
@ GPU_MATFLAG_OBJECT_INFO
Definition: GPU_material.h:82
@ GPU_MATFLAG_PRINCIPLED_DIELECTRIC
Definition: GPU_material.h:90
@ GPU_MATFLAG_PRINCIPLED_CLEARCOAT
Definition: GPU_material.h:88
@ GPU_MATFLAG_PRINCIPLED_ANY
Definition: GPU_material.h:92
@ GPU_MATFLAG_PRINCIPLED_METALLIC
Definition: GPU_material.h:89
eGPUMaterialFlag GPU_material_flag(const GPUMaterial *mat)
Definition: gpu_material.c:606
eGPUType
Definition: GPU_material.h:45
@ GPU_VEC4
Definition: GPU_material.h:52
@ GPU_VEC3
Definition: GPU_material.h:51
@ GPU_FLOAT
Definition: GPU_material.h:49
void GPU_material_uniform_buffer_create(GPUMaterial *material, ListBase *inputs)
Definition: gpu_material.c:206
int GPU_shader_get_uniform(GPUShader *shader, const char *name)
Definition: gpu_shader.cc:559
struct GPUShader GPUShader
Definition: GPU_shader.h:20
void GPU_shader_free_builtin_shaders(void)
struct GPUShaderCreateInfo GPUShaderCreateInfo
Definition: GPU_shader.h:18
void GPU_shader_free(GPUShader *shader)
Definition: gpu_shader.cc:200
GPUShader * GPU_shader_create_from_info(const GPUShaderCreateInfo *_info)
Definition: gpu_shader.cc:277
#define GPU_UBO_BLOCK_NAME
#define GPU_ATTRIBUTE_UBO_BLOCK_NAME
#define GPU_MAX_SAFE_ATTR_NAME
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Platform independent time functions.
GPUCodegenCreateInfo * create_info
Definition: gpu_codegen.cc:234
void generate_graphs()
Definition: gpu_codegen.cc:552
uint32_t hash_get() const
Definition: gpu_codegen.cc:273
GPUMaterial & mat
Definition: gpu_codegen.cc:231
GPUNodeGraph & graph
Definition: gpu_codegen.cc:232
void generate_library()
Definition: gpu_codegen.cc:420
GPUCodegenOutput output
Definition: gpu_codegen.cc:233
void generate_resources()
Definition: gpu_codegen.cc:350
GPUCodegen(GPUMaterial *mat_, GPUNodeGraph *graph_)
Definition: gpu_codegen.cc:242
void generate_uniform_buffer()
Definition: gpu_codegen.cc:521
void generate_attribs()
Definition: gpu_codegen.cc:291
constexpr bool is_empty() const
constexpr const char * c_str() const
int64_t size() const
Definition: BLI_vector.hh:694
void append(const T &value)
Definition: BLI_vector.hh:433
void extend_non_duplicates(Span< T > array)
Definition: BLI_vector.hh:545
OperationNode * node
Depsgraph * graph
StackEntry * from
Material material
GPUPass * GPU_generate_pass(GPUMaterial *material, GPUNodeGraph *graph, GPUCodegenCallbackFn finalize_source_cb, void *thunk)
Definition: gpu_codegen.cc:585
static GPUPass * gpu_pass_cache_lookup(uint32_t hash)
Definition: gpu_codegen.cc:112
static SpinLock pass_cache_spin
Definition: gpu_codegen.cc:108
static int count_active_texture_sampler(GPUPass *pass, GPUShader *shader)
Definition: gpu_codegen.cc:665
static void gpu_pass_free(GPUPass *pass)
Definition: gpu_codegen.cc:746
static bool gpu_pass_is_valid(GPUPass *pass)
Definition: gpu_codegen.cc:158
static GPUPass * gpu_pass_cache_resolve_collision(GPUPass *pass, GPUShaderCreateInfo *info, uint32_t hash)
Definition: gpu_codegen.cc:142
static GPUPass * pass_cache
Definition: gpu_codegen.cc:107
void GPU_pass_cache_free(void)
Definition: gpu_codegen.cc:789
void GPU_pass_release(GPUPass *pass)
Definition: gpu_codegen.cc:738
void gpu_codegen_init(void)
Definition: gpu_codegen.cc:808
bool GPU_pass_compile(GPUPass *pass, const char *shname)
Definition: gpu_codegen.cc:706
static void gpu_pass_cache_insert_after(GPUPass *node, GPUPass *pass)
Definition: gpu_codegen.cc:126
static bool gpu_pass_shader_validate(GPUPass *pass, GPUShader *shader)
Definition: gpu_codegen.cc:680
void GPU_pass_cache_garbage_collect(void)
Definition: gpu_codegen.cc:756
void GPU_pass_cache_init(void)
Definition: gpu_codegen.cc:784
GPUShader * GPU_pass_shader_get(GPUPass *pass)
Definition: gpu_codegen.cc:733
void gpu_codegen_exit(void)
Definition: gpu_codegen.cc:812
void gpu_node_graph_finalize_uniform_attrs(GPUNodeGraph *graph)
void gpu_node_graph_prune_unused(GPUNodeGraph *graph)
eGPUNodeTag
@ GPU_NODE_TAG_SURFACE
@ GPU_NODE_TAG_DISPLACEMENT
@ GPU_NODE_TAG_VOLUME
@ GPU_NODE_TAG_FUNCTION
@ GPU_NODE_TAG_THICKNESS
@ GPU_NODE_TAG_AOV
@ GPU_SOURCE_CONSTANT
@ GPU_SOURCE_FUNCTION_CALL
@ GPU_SOURCE_ATTR
@ GPU_SOURCE_UNIFORM
@ GPU_SOURCE_OUTPUT
@ GPU_SOURCE_TEX_TILED_MAPPING
@ GPU_SOURCE_UNIFORM_ATTR
@ GPU_SOURCE_STRUCT
@ GPU_SOURCE_TEX
ccl_global KernelShaderEvalInput ccl_global float * output
ccl_global KernelShaderEvalInput * input
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static ulong * next
static Type to_type(const eGPUType type)
static std::ostream & operator<<(std::ostream &stream, const Type type)
Vector< const char * > gpu_shader_dependency_get_resolved_source(const StringRefNull shader_source_name)
#define hash
Definition: noise.c:153
unsigned int uint32_t
Definition: stdint.h:80
char attr_names[16][GPU_MAX_SAFE_ATTR_NAME+1]
Definition: gpu_codegen.cc:58
std::array< char, 32 > NameEntry
Definition: gpu_codegen.cc:55
blender::Vector< std::unique_ptr< NameEntry >, 16 > sampler_names
Definition: gpu_codegen.cc:60
const char * append_sampler_name(const char name[32])
Definition: gpu_codegen.cc:63
StageInterfaceInfo * interface_generated
Definition: gpu_codegen.cc:74
NameBuffer name_buffer
Definition: gpu_codegen.cc:76
GPUCodegenCreateInfo(const char *name)
Definition: gpu_codegen.cc:78
GPUShaderCreateInfo * create_info
Definition: GPU_material.h:134
GPUShader * shader
Definition: gpu_codegen.cc:88
bool compiled
Definition: gpu_codegen.cc:95
uint32_t hash
Definition: gpu_codegen.cc:93
GPUCodegenCreateInfo * create_info
Definition: gpu_codegen.cc:89
uint refcount
Definition: gpu_codegen.cc:91
struct GPUPass * next
Definition: gpu_codegen.cc:86
Describe inputs & outputs, stage interfaces, resources and sources of a shader. If all data is correc...
Self & uniform_buf(int slot, StringRefNull type_name, StringRefNull name, Frequency freq=Frequency::PASS)
Self & sampler(int slot, ImageType type, StringRefNull name, Frequency freq=Frequency::PASS, eGPUSamplerState sampler=(eGPUSamplerState) -1)
Self & additional_info(StringRefNull info_name0, StringRefNull info_name1="", StringRefNull info_name2="", StringRefNull info_name3="", StringRefNull info_name4="", StringRefNull info_name5="", StringRefNull info_name6="")
Self & vertex_in(int slot, Type type, StringRefNull name)
Self & vertex_out(StageInterfaceInfo &interface)
Self & define(StringRefNull name, StringRefNull value="")
Self & smooth(Type type, StringRefNull _name)
double PIL_check_seconds_timer(void)
Definition: time.c:64