[Bf-blender-cvs] [b639e608644] master: Realtime Compositor: Add needed GPU module changes

Omar Emara noreply at git.blender.org
Fri Jul 29 08:49:12 CEST 2022


Commit: b639e6086445f20d428df1f471c73922bbd54b67
Author: Omar Emara
Date:   Fri Jul 29 08:37:57 2022 +0200
Branches: master
https://developer.blender.org/rBb639e6086445f20d428df1f471c73922bbd54b67

Realtime Compositor: Add needed GPU module changes

This patch implements the necessary changes to the GPU module that are
needed by the realtime compositor.

A new function GPU_material_from_callbacks was added to construct a GPU
material from a number of callbacks. A callback to construct the
material graph by adding and linking the necessary GPU material nodes.
And the existing code generator callback. This essentially allows the
construction of GPU materials independent of node trees and without the
need to do any node tree localization.

A new composite source output to the code generator was added. This
output contains the serialization of nodes that are tagged with
GPU_NODE_TAG_COMPOSITOR, which are the nodes linked to the newly added
composite output links.

Two new GPU uniform setters were added for int2 and matrix3 types.

Shader create info now supports generated compute sources.

Shaders starting with gpu_shader_compositor are now considered part of
the shader library.

Additionally, two fixes were implemented. First, GPU setter node
de-duplication now appropriately increments the reference count of the
references resources. Second, unlinked sockets now get their value from
their associated GPU node stack instead of the socket itself.

Differential Revision: https://developer.blender.org/D14690

Reviewed By: Clement

===================================================================

M	source/blender/gpu/GPU_material.h
M	source/blender/gpu/GPU_shader.h
M	source/blender/gpu/intern/gpu_codegen.cc
M	source/blender/gpu/intern/gpu_material.c
M	source/blender/gpu/intern/gpu_node_graph.c
M	source/blender/gpu/intern/gpu_node_graph.h
M	source/blender/gpu/intern/gpu_shader.cc
M	source/blender/gpu/intern/gpu_shader_create_info.hh
M	source/blender/gpu/intern/gpu_shader_dependency.cc

===================================================================

diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 3ca465fa57a..12a7cf49f9d 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -121,6 +121,7 @@ typedef struct GPUCodegenOutput {
   char *surface;
   char *volume;
   char *thickness;
+  char *composite;
   char *material_functions;
 
   GPUShaderCreateInfo *create_info;
@@ -178,6 +179,8 @@ void GPU_material_output_thickness(GPUMaterial *material, GPUNodeLink *link);
 
 void GPU_material_add_output_link_aov(GPUMaterial *material, GPUNodeLink *link, int hash);
 
+void GPU_material_add_output_link_composite(GPUMaterial *material, GPUNodeLink *link);
+
 /**
  * Wrap a part of the material graph into a function. You need then need to call the function by
  * using something like #GPU_differentiate_float_function.
@@ -218,6 +221,7 @@ GPUMaterial *GPU_material_from_nodetree(struct Scene *scene,
                                         void *thunk);
 
 void GPU_material_compile(GPUMaterial *mat);
+void GPU_material_free_single(GPUMaterial *material);
 void GPU_material_free(struct ListBase *gpumaterial);
 
 void GPU_material_acquire(GPUMaterial *mat);
@@ -319,6 +323,16 @@ struct GHash *GPU_uniform_attr_list_hash_new(const char *info);
 void GPU_uniform_attr_list_copy(GPUUniformAttrList *dest, GPUUniformAttrList *src);
 void GPU_uniform_attr_list_free(GPUUniformAttrList *set);
 
+/* A callback passed to GPU_material_from_callbacks to construct the material graph by adding and
+ * linking the necessary GPU material nodes. */
+typedef void (*ConstructGPUMaterialFn)(void *thunk, GPUMaterial *material);
+
+/* Construct a GPU material from a set of callbacks. See the callback types for more information.
+ * The given thunk will be passed as the first parameter of each callback. */
+GPUMaterial *GPU_material_from_callbacks(ConstructGPUMaterialFn construct_function_cb,
+                                         GPUCodegenCallbackFn generate_code_function_cb,
+                                         void *thunk);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index 3460d33fe68..c154f1adc8b 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -177,7 +177,9 @@ void GPU_shader_uniform_4f(GPUShader *sh, const char *name, float x, float y, fl
 void GPU_shader_uniform_2fv(GPUShader *sh, const char *name, const float data[2]);
 void GPU_shader_uniform_3fv(GPUShader *sh, const char *name, const float data[3]);
 void GPU_shader_uniform_4fv(GPUShader *sh, const char *name, const float data[4]);
+void GPU_shader_uniform_2iv(GPUShader *sh, const char *name, const int data[2]);
 void GPU_shader_uniform_mat4(GPUShader *sh, const char *name, const float data[4][4]);
+void GPU_shader_uniform_mat3_as_mat4(GPUShader *sh, const char *name, const float data[3][3]);
 void GPU_shader_uniform_2fv_array(GPUShader *sh, const char *name, int len, const float (*val)[2]);
 void GPU_shader_uniform_4fv_array(GPUShader *sh, const char *name, int len, const float (*val)[4]);
 
diff --git a/source/blender/gpu/intern/gpu_codegen.cc b/source/blender/gpu/intern/gpu_codegen.cc
index 82441c3c89c..4a45a3e63ed 100644
--- a/source/blender/gpu/intern/gpu_codegen.cc
+++ b/source/blender/gpu/intern/gpu_codegen.cc
@@ -280,6 +280,7 @@ class GPUCodegen {
 
   void node_serialize(std::stringstream &eval_ss, const GPUNode *node);
   char *graph_serialize(eGPUNodeTag tree_tag, GPUNodeLink *output_link);
+  char *graph_serialize(eGPUNodeTag tree_tag);
 
   static char *extract_c_str(std::stringstream &stream)
   {
@@ -500,6 +501,19 @@ char *GPUCodegen::graph_serialize(eGPUNodeTag tree_tag, GPUNodeLink *output_link
   return eval_c_str;
 }
 
+char *GPUCodegen::graph_serialize(eGPUNodeTag tree_tag)
+{
+  std::stringstream eval_ss;
+  LISTBASE_FOREACH (GPUNode *, node, &graph.nodes) {
+    if (node->tag & tree_tag) {
+      node_serialize(eval_ss, node);
+    }
+  }
+  char *eval_c_str = extract_c_str(eval_ss);
+  BLI_hash_mm2a_add(&hm2a_, (uchar *)eval_c_str, eval_ss.str().size());
+  return eval_c_str;
+}
+
 void GPUCodegen::generate_uniform_buffer()
 {
   /* Extract uniform inputs. */
@@ -539,6 +553,9 @@ void GPUCodegen::generate_graphs()
   output.volume = graph_serialize(GPU_NODE_TAG_VOLUME, graph.outlink_volume);
   output.displacement = graph_serialize(GPU_NODE_TAG_DISPLACEMENT, graph.outlink_displacement);
   output.thickness = graph_serialize(GPU_NODE_TAG_THICKNESS, graph.outlink_thickness);
+  if (!BLI_listbase_is_empty(&graph.outlink_compositor)) {
+    output.composite = graph_serialize(GPU_NODE_TAG_COMPOSITOR);
+  }
 
   if (!BLI_listbase_is_empty(&graph.material_functions)) {
     std::stringstream eval_ss;
@@ -569,9 +586,10 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
                            GPUCodegenCallbackFn finalize_source_cb,
                            void *thunk)
 {
-  /* Prune the unused nodes and extract attributes before compiling so the
-   * generated VBOs are ready to accept the future shader. */
   gpu_node_graph_prune_unused(graph);
+
+  /* Extract attributes before compiling so the generated VBOs are ready to accept the future
+   * shader. */
   gpu_node_graph_finalize_uniform_attrs(graph);
 
   GPUCodegen codegen(material, graph);
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 4d3ea3e0c99..a4842ef0e43 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -141,7 +141,7 @@ static void gpu_material_ramp_texture_build(GPUMaterial *mat)
   mat->coba_builder = NULL;
 }
 
-static void gpu_material_free_single(GPUMaterial *material)
+void GPU_material_free_single(GPUMaterial *material)
 {
   bool do_free = atomic_sub_and_fetch_uint32(&material->refcount, 1) == 0;
   if (!do_free) {
@@ -173,7 +173,7 @@ void GPU_material_free(ListBase *gpumaterial)
   LISTBASE_FOREACH (LinkData *, link, gpumaterial) {
     GPUMaterial *material = link->data;
     DRW_deferred_shader_remove(material);
-    gpu_material_free_single(material);
+    GPU_material_free_single(material);
   }
   BLI_freelistN(gpumaterial);
 }
@@ -538,6 +538,13 @@ void GPU_material_add_output_link_aov(GPUMaterial *material, GPUNodeLink *link,
   BLI_addtail(&material->graph.outlink_aovs, aov_link);
 }
 
+void GPU_material_add_output_link_composite(GPUMaterial *material, GPUNodeLink *link)
+{
+  GPUNodeGraphOutputLink *compositor_link = MEM_callocN(sizeof(GPUNodeGraphOutputLink), __func__);
+  compositor_link->outlink = link;
+  BLI_addtail(&material->graph.outlink_compositor, compositor_link);
+}
+
 char *GPU_material_split_sub_function(GPUMaterial *material,
                                       eGPUType return_type,
                                       GPUNodeLink **link)
@@ -721,7 +728,7 @@ void GPU_material_acquire(GPUMaterial *mat)
 
 void GPU_material_release(GPUMaterial *mat)
 {
-  gpu_material_free_single(mat);
+  GPU_material_free_single(mat);
 }
 
 void GPU_material_compile(GPUMaterial *mat)
@@ -772,3 +779,42 @@ void GPU_materials_free(Main *bmain)
   // BKE_world_defaults_free_gpu();
   BKE_material_defaults_free_gpu();
 }
+
+GPUMaterial *GPU_material_from_callbacks(ConstructGPUMaterialFn construct_function_cb,
+                                         GPUCodegenCallbackFn generate_code_function_cb,
+                                         void *thunk)
+{
+  /* Allocate a new material and its material graph, and initialize its reference count. */
+  GPUMaterial *material = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial");
+  material->graph.used_libraries = BLI_gset_new(
+      BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "GPUNodeGraph.used_libraries");
+  material->refcount = 1;
+
+  /* Construct the material graph by adding and linking the necessary GPU material nodes. */
+  construct_function_cb(thunk, material);
+
+  /* Create and initialize the texture storing color bands used by Ramp and Curve nodes. */
+  gpu_material_ramp_texture_build(material);
+
+  /* Lookup an existing pass in the cache or generate a new one. */
+  material->pass = GPU_generate_pass(material, &material->graph, generate_code_function_cb, thunk);
+
+  /* The pass already exists in the pass cache but its shader already failed to compile. */
+  if (material->pass == NULL) {
+    material->status = GPU_MAT_FAILED;
+    gpu_node_graph_free(&material->graph);
+    return material;
+  }
+
+  /* The pass already exists in the pass cache and its shader is already compiled. */
+  GPUShader *shader = GPU_pass_shader_get(material->pass);
+  if (shader != NULL) {
+    material->status = GPU_MAT_SUCCESS;
+    gpu_node_graph_free_nodes(&material->graph);
+    return material;
+  }
+
+  /* The material was created successfully but still needs to be compiled. */
+  material->status = GPU_MAT_CREATED;
+  return material;
+}
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
index 684070dbdc0..c7b2fde492f 100644
--- a/source/blender/gpu/intern/gpu_node_graph.c
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -75,9 +75,26 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType
 
     if (STR_ELEM(name, "set_value", "set_rgb", "set_rgba") && (input->type == type)) {
       input = MEM_dupallocN(outnode->inputs.first);
+
+      switch (input->source) {
+        case GPU_SOURCE_ATTR:
+          input->attr->users++;
+          break;
+        case GPU_SOURCE_UNIFORM_ATTR:
+          input->uniform_attr->users++;
+          break;
+        case GPU_SOURCE_TEX:
+        case GPU_SOURCE_TEX_TILED_MAPPING:
+          input->texture->users++;
+          break;
+        default:
+          break;
+      }
+
       if (input->link) {
         input->link->users++;
       }
+
       BLI_addtail(&node->inputs, input);
       return;
     }
@@ -179,35 +196,21 @@ static GPUNodeLink *gpu_uniformbuffer_link(GPUMaterial *mat,
   BLI_assert(socket != NULL);
   BLI_assert(socket->in_out == in_out);
 
-  if ((socket->flag & SOCK_HIDE_VALUE) == 0) {
-    GPUNodeLink *link;
-    switch (socket->type) {
-      case SOCK_FLOAT: {
-        bNodeSocketValueFloat *socke

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list