[Bf-blender-cvs] [7f840426fd4] master: GPU: add mechanism for splitting up big gpu_shader_material.glsl file

Brecht Van Lommel noreply at git.blender.org
Mon Aug 26 19:20:51 CEST 2019


Commit: 7f840426fd4917f56e7bafcffffd51b93c1fc6f7
Author: Brecht Van Lommel
Date:   Fri Aug 23 14:36:22 2019 +0200
Branches: master
https://developer.blender.org/rB7f840426fd4917f56e7bafcffffd51b93c1fc6f7

GPU: add mechanism for splitting up big gpu_shader_material.glsl file

Compiling this big file for every Eevee material is bad for performance, and
now that we are adding more nodes it gets worse. This patch adds a simple
mechanism to split up that file, and use only the parts used by shader nodes.

When a function is used by GPU_link, we detect which GLSL file it came from
and use it in GLSL code generation automatically. Dependencies between GLSL
files are manually specified, and function names must be unique across all
GLSL files.

Most of the actual splitting up will be done in later commits.

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

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

M	source/blender/gpu/CMakeLists.txt
M	source/blender/gpu/intern/gpu_codegen.c
M	source/blender/gpu/intern/gpu_codegen.h
M	source/blender/gpu/intern/gpu_material.c
A	source/blender/gpu/intern/gpu_material_library.h
M	source/blender/gpu/shaders/gpu_shader_material.glsl
A	source/blender/gpu/shaders/gpu_shader_material_hash.glsl
A	source/blender/gpu/shaders/gpu_shader_material_magic.glsl
A	source/blender/gpu/shaders/gpu_shader_material_white_noise.glsl

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

diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index fb7d3c1ace8..4a67f5f6af8 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -116,6 +116,7 @@ set(SRC
   intern/gpu_batch_private.h
   intern/gpu_codegen.h
   intern/gpu_context_private.h
+  intern/gpu_material_library.h
   intern/gpu_matrix_private.h
   intern/gpu_primitive_private.h
   intern/gpu_private.h
@@ -232,6 +233,9 @@ data_to_c_simple(shaders/gpu_shader_keyframe_diamond_frag.glsl SRC)
 
 data_to_c_simple(shaders/gpu_shader_geometry.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_material.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_material_hash.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_material_magic.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_material_white_noise.glsl SRC)
 
 data_to_c_simple(shaders/gpu_shader_gpencil_stroke_vert.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_gpencil_stroke_frag.glsl SRC)
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 55337596cbe..cbf6665b3bb 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -51,15 +51,11 @@
 #include "BLI_sys_types.h" /* for intptr_t support */
 
 #include "gpu_codegen.h"
+#include "gpu_material_library.h"
 
 #include <string.h>
 #include <stdarg.h>
 
-extern char datatoc_gpu_shader_material_glsl[];
-extern char datatoc_gpu_shader_geometry_glsl[];
-
-static char *glsl_material_library = NULL;
-
 /* -------------------- GPUPass Cache ------------------ */
 /**
  * Internal shader cache: This prevent the shader recompilation / stall when
@@ -147,6 +143,7 @@ typedef struct GPUFunction {
   eGPUType paramtype[MAX_PARAMETER];
   GPUFunctionQual paramqual[MAX_PARAMETER];
   int totparam;
+  GPUMaterialLibrary *library;
 } GPUFunction;
 
 /* Indices match the eGPUType enum */
@@ -230,15 +227,17 @@ static char *gpu_str_skip_token(char *str, char *token, int max)
   return str;
 }
 
-static void gpu_parse_functions_string(GHash *hash, char *code)
+static void gpu_parse_material_library(GHash *hash, GPUMaterialLibrary *library)
 {
   GPUFunction *function;
   eGPUType type;
   GPUFunctionQual qual;
   int i;
+  char *code = library->code;
 
   while ((code = strstr(code, "void "))) {
     function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
+    function->library = library;
 
     code = gpu_str_skip_token(code, NULL, 0);
     code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME);
@@ -367,11 +366,6 @@ static char *gpu_generate_function_prototyps(GHash *hash)
 
 static GPUFunction *gpu_lookup_function(const char *name)
 {
-  if (!FUNCTION_HASH) {
-    FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh");
-    gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library);
-  }
-
   return BLI_ghash_lookup(FUNCTION_HASH, (const void *)name);
 }
 
@@ -395,11 +389,6 @@ void gpu_codegen_exit(void)
 
   GPU_shader_free_builtin_shaders();
 
-  if (glsl_material_library) {
-    MEM_freeN(glsl_material_library);
-    glsl_material_library = NULL;
-  }
-
 #if 0
   if (FUNCTION_PROTOTYPES) {
     MEM_freeN(FUNCTION_PROTOTYPES);
@@ -1381,20 +1370,15 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code, cons
 
 void GPU_code_generate_glsl_lib(void)
 {
-  DynStr *ds;
-
-  /* only initialize the library once */
-  if (glsl_material_library) {
+  /* Only parse GLSL shader files once. */
+  if (FUNCTION_HASH) {
     return;
   }
 
-  ds = BLI_dynstr_new();
-
-  BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);
-
-  glsl_material_library = BLI_dynstr_get_cstring(ds);
-
-  BLI_dynstr_free(ds);
+  FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh");
+  for (int i = 0; gpu_material_libraries[i].code; i++) {
+    gpu_parse_material_library(FUNCTION_HASH, &gpu_material_libraries[i]);
+  }
 }
 
 /* GPU pass binding/unbinding */
@@ -1796,6 +1780,19 @@ GPUNodeLink *GPU_builtin(eGPUBuiltin builtin)
   return link;
 }
 
+static void gpu_material_use_library(GPUMaterial *material, GPUMaterialLibrary *library)
+{
+  GSet *used_libraries = gpu_material_used_libraries(material);
+
+  if (BLI_gset_add(used_libraries, library->code)) {
+    if (library->dependencies) {
+      for (int i = 0; library->dependencies[i]; i++) {
+        BLI_gset_add(used_libraries, library->dependencies[i]);
+      }
+    }
+  }
+}
+
 bool GPU_link(GPUMaterial *mat, const char *name, ...)
 {
   GPUNode *node;
@@ -1810,6 +1807,8 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...)
     return false;
   }
 
+  gpu_material_use_library(mat, function->library);
+
   node = GPU_node_begin(name);
 
   va_start(params, name);
@@ -1849,6 +1848,8 @@ bool GPU_stack_link(GPUMaterial *material,
     return false;
   }
 
+  gpu_material_use_library(material, function->library);
+
   node = GPU_node_begin(name);
   totin = 0;
   totout = 0;
@@ -1962,6 +1963,30 @@ static bool gpu_pass_is_valid(GPUPass *pass)
   return (pass->compiled == false || pass->shader != NULL);
 }
 
+static char *code_generate_material_library(GPUMaterial *material, const char *frag_lib)
+{
+  DynStr *ds = BLI_dynstr_new();
+
+  if (frag_lib) {
+    BLI_dynstr_append(ds, frag_lib);
+  }
+
+  GSet *used_libraries = gpu_material_used_libraries(material);
+
+  /* Add library code in order, for dependencies. */
+  for (int i = 0; gpu_material_libraries[i].code; i++) {
+    GPUMaterialLibrary *library = &gpu_material_libraries[i];
+    if (BLI_gset_haskey(used_libraries, library->code)) {
+      BLI_dynstr_append(ds, library->code);
+    }
+  }
+
+  char *result = BLI_dynstr_get_cstring(ds);
+  BLI_dynstr_free(ds);
+
+  return result;
+}
+
 GPUPass *GPU_generate_pass(GPUMaterial *material,
                            GPUNodeLink *frag_outlink,
                            struct GPUVertAttrLayers *attrs,
@@ -2000,7 +2025,7 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
 
   /* Either the shader is not compiled or there is a hash collision...
    * continue generating the shader strings. */
-  char *tmp = BLI_strdupcat(frag_lib, glsl_material_library);
+  char *tmp = code_generate_material_library(material, frag_lib);
 
   geometrycode = code_generate_geometry(nodes, geom_code, defines);
   vertexcode = code_generate_vertex(nodes, vert_code, (geometrycode != NULL));
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index 6eb6bc2f05f..4e09f16ebf8 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -33,6 +33,7 @@ struct GPUNode;
 struct GPUOutput;
 struct GPUShader;
 struct GPUVertAttrLayers;
+struct GSet;
 struct ListBase;
 
 /* Pass Generation
@@ -207,4 +208,6 @@ struct GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat,
                                                       float *pixels,
                                                       float *row);
 
+struct GSet *gpu_material_used_libraries(struct GPUMaterial *material);
+
 #endif
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 20b91c0c95d..05d991105c0 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -37,6 +37,7 @@
 #include "BLI_utildefines.h"
 #include "BLI_string.h"
 #include "BLI_string_utils.h"
+#include "BLI_ghash.h"
 
 #include "BKE_main.h"
 #include "BKE_node.h"
@@ -102,6 +103,8 @@ struct GPUMaterial {
   GPUTexture *coba_tex; /* 1D Texture array containing all color bands. */
   GPUColorBandBuilder *coba_builder;
 
+  GSet *used_libraries;
+
 #ifndef NDEBUG
   char name[64];
 #endif
@@ -183,6 +186,8 @@ static void gpu_material_free_single(GPUMaterial *material)
   if (material->coba_tex != NULL) {
     GPU_texture_free(material->coba_tex);
   }
+
+  BLI_gset_free(material->used_libraries, NULL);
 }
 
 void GPU_material_free(ListBase *gpumaterial)
@@ -582,6 +587,11 @@ void gpu_material_add_node(GPUMaterial *material, GPUNode *node)
   BLI_addtail(&material->nodes, node);
 }
 
+GSet *gpu_material_used_libraries(GPUMaterial *material)
+{
+  return material->used_libraries;
+}
+
 /* Return true if the material compilation has not yet begin or begin. */
 eGPUMaterialStatus GPU_material_status(GPUMaterial *mat)
 {
@@ -659,6 +669,9 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
   UNUSED_VARS(name);
 #endif
 
+  mat->used_libraries = BLI_gset_new(
+      BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "GPUMaterial.used_libraries");
+
   /* localize tree to create links for reroute and mute */
   bNodeTree *localtree = ntreeLocalize(ntree);
   ntreeGPUMaterialNodes(localtree, mat, &has_surface_output, &has_volume_output);
diff --git a/source/blender/gpu/intern/gpu_material_library.h b/source/blender/gpu/intern/gpu_material_library.h
new file mode 100644
index 00000000000..7160a56a60e
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_material_library.h
@@ -0,0 +1,49 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * List of all gpu_shader_material_*.glsl files used by GLSL materials. These
+ * will be parsed to make all functions in them available to use for GPU_link().
+ *
+ * If a file uses functions from another file, it must be added to the list of
+ * dependencies, and be placed after that file in the list. */
+
+#ifndef __GPU_MATERIAL_LIBRARY_H__
+#define __GPU_MATERIAL_LIBRARY_H__
+


@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list