[Bf-blender-cvs] [e449861b64e] tmp-workbench-rewrite2: Group passes by material

Miguel Pozo noreply at git.blender.org
Fri Jan 27 20:53:41 CET 2023


Commit: e449861b64e31e7015206420fc229d3454bef071
Author: Miguel Pozo
Date:   Fri Jan 27 18:21:40 2023 +0100
Branches: tmp-workbench-rewrite2
https://developer.blender.org/rBe449861b64e31e7015206420fc229d3454bef071

Group passes by material

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

M	source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh
M	source/blender/draw/engines/workbench/shaders/workbench_material_lib.glsl
M	source/blender/draw/engines/workbench/workbench_engine.cc
M	source/blender/draw/engines/workbench/workbench_mesh_passes.cc
M	source/blender/draw/engines/workbench/workbench_private.hh

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

diff --git a/source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh b/source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh
index 92452eefed2..d49e500a32c 100644
--- a/source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh
+++ b/source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh
@@ -126,19 +126,18 @@ GPU_SHADER_CREATE_INFO(workbench_next_prepass)
 
 GPU_SHADER_CREATE_INFO(workbench_color_material)
     .define("WORKBENCH_COLOR_MATERIAL")
-    .storage_buf(WB_MATERIAL_SLOT, Qualifier::READ, "vec4", "materials_data[]");
+    .push_constant(Type::VEC4, "material_data");
 
 GPU_SHADER_CREATE_INFO(workbench_color_texture)
     .define("WORKBENCH_COLOR_TEXTURE")
     .define("WORKBENCH_TEXTURE_IMAGE_ARRAY")
-    .define("WORKBENCH_COLOR_MATERIAL")
-    .storage_buf(WB_MATERIAL_SLOT, Qualifier::READ, "vec4", "materials_data[]")
     .sampler(1, ImageType::FLOAT_2D, "imageTexture", Frequency::BATCH)
     .sampler(2, ImageType::FLOAT_2D_ARRAY, "imageTileArray", Frequency::BATCH)
     .sampler(3, ImageType::FLOAT_1D_ARRAY, "imageTileData", Frequency::BATCH)
     .push_constant(Type::BOOL, "isImageTile")
     .push_constant(Type::BOOL, "imagePremult")
-    .push_constant(Type::FLOAT, "imageTransparencyCutoff");
+    .push_constant(Type::FLOAT, "imageTransparencyCutoff")
+    .additional_info("workbench_color_material");
 
 GPU_SHADER_CREATE_INFO(workbench_color_vertex).define("WORKBENCH_COLOR_VERTEX");
 
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_material_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_material_lib.glsl
index 59e30b310bb..47eadab28c3 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_material_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_material_lib.glsl
@@ -17,7 +17,7 @@ void workbench_material_data_get(int handle,
 #else
 
 #  ifdef WORKBENCH_COLOR_MATERIAL
-  vec4 data = materials_data[handle];
+  vec4 data = material_data;
 #  else
   vec4 data = vec4(0.0);
 #  endif
diff --git a/source/blender/draw/engines/workbench/workbench_engine.cc b/source/blender/draw/engines/workbench/workbench_engine.cc
index a04f61418f6..abd3b3f1027 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.cc
+++ b/source/blender/draw/engines/workbench/workbench_engine.cc
@@ -196,12 +196,7 @@ class Instance {
             if (batches[i] == nullptr) {
               continue;
             }
-            /* TODO(fclem): This create a cull-able instance for each sub-object. This is done
-             * for simplicity to reduce complexity. But this increase the overhead per object.
-             * Instead, we should use an indirection buffer to the material buffer. */
-            ResourceHandle _handle = i == 0 ? handle : manager.resource_handle(ob_ref);
-
-            Material &mat = resources.material_buf.get_or_resize(_handle.resource_index());
+            Material mat;
 
             if (::Material *_mat = BKE_object_material_get_eval(ob_ref.object, i + 1)) {
               mat = Material(*_mat);
@@ -219,7 +214,7 @@ class Instance {
               get_material_image(ob_ref.object, i + 1, image, iuser, sampler_state);
             }
 
-            draw_mesh(ob_ref, mat, batches[i], _handle, image, sampler_state, iuser);
+            draw_mesh(ob_ref, mat, batches[i], handle, image, sampler_state, iuser);
           }
         }
       }
@@ -241,7 +236,7 @@ class Instance {
         }
 
         if (batch) {
-          Material &mat = resources.material_buf.get_or_resize(handle.resource_index());
+          Material mat;
 
           if (object_state.color_type == V3D_SHADING_OBJECT_COLOR) {
             mat = Material(*ob_ref.object);
@@ -287,7 +282,7 @@ class Instance {
     const bool in_front = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0;
 
     auto draw = [&](MeshPass &pass) {
-      pass.draw(ob_ref, batch, handle, image, sampler_state, iuser);
+      pass.draw(ob_ref, batch, handle, material, image, sampler_state, iuser);
     };
 
     if (scene_state.xray_mode || material.is_transparent()) {
diff --git a/source/blender/draw/engines/workbench/workbench_mesh_passes.cc b/source/blender/draw/engines/workbench/workbench_mesh_passes.cc
index bc90f26b33d..6edbe2ac63c 100644
--- a/source/blender/draw/engines/workbench/workbench_mesh_passes.cc
+++ b/source/blender/draw/engines/workbench/workbench_mesh_passes.cc
@@ -34,6 +34,7 @@ void MeshPass::init_subpasses(ePipelineType pipeline,
                               bool clip,
                               ShaderCache &shaders)
 {
+  material_subpass_map_.clear();
   texture_subpass_map_.clear();
 
   static std::string pass_names[geometry_type_len][shader_type_len] = {};
@@ -57,6 +58,7 @@ void MeshPass::init_subpasses(ePipelineType pipeline,
 void MeshPass::draw(ObjectRef &ref,
                     GPUBatch *batch,
                     ResourceHandle handle,
+                    Material material,
                     ::Image *image /* = nullptr */,
                     eGPUSamplerState sampler_state /* = GPU_SAMPLER_DEFAULT */,
                     ImageUser *iuser /* = nullptr */)
@@ -64,6 +66,7 @@ void MeshPass::draw(ObjectRef &ref,
   is_empty_ = false;
 
   eGeometryType geometry_type = geometry_type_from_object(ref.object);
+
   if (image) {
     GPUTexture *texture = nullptr;
     GPUTexture *tilemap = nullptr;
@@ -75,33 +78,47 @@ void MeshPass::draw(ObjectRef &ref,
       texture = BKE_image_get_gpu_texture(image, iuser, nullptr);
     }
     if (texture) {
-      auto add_cb = [&] {
-        PassMain::Sub *sub_pass =
-            passes_[static_cast<int>(geometry_type)][static_cast<int>(eShaderType::TEXTURE)];
-        sub_pass = &sub_pass->sub(image->id.name);
+      auto add_texture_cb = [&] {
+        PassMain::Sub &sub_pass =
+            passes_[static_cast<int>(geometry_type)][static_cast<int>(eShaderType::TEXTURE)]->sub(
+                image->id.name);
+
+        sub_pass.push_constant("material_data", *reinterpret_cast<float4 *>(&material));
         if (tilemap) {
-          sub_pass->bind_texture(WB_TILE_ARRAY_SLOT, texture, sampler_state);
-          sub_pass->bind_texture(WB_TILE_DATA_SLOT, tilemap);
+          sub_pass.bind_texture(WB_TILE_ARRAY_SLOT, texture, sampler_state);
+          sub_pass.bind_texture(WB_TILE_DATA_SLOT, tilemap);
         }
         else {
-          sub_pass->bind_texture(WB_TEXTURE_SLOT, texture, sampler_state);
+          sub_pass.bind_texture(WB_TEXTURE_SLOT, texture, sampler_state);
         }
-        sub_pass->push_constant("isImageTile", tilemap != nullptr);
-        sub_pass->push_constant("imagePremult", image && image->alpha_mode == IMA_ALPHA_PREMUL);
+        sub_pass.push_constant("isImageTile", tilemap != nullptr);
+        sub_pass.push_constant("imagePremult", image && image->alpha_mode == IMA_ALPHA_PREMUL);
         /* TODO(Miguel Pozo): This setting should be exposed on the user side,
          * either as a global parameter (and set it here)
          * or by reading the Material Clipping Threshold (and set it per material) */
-        sub_pass->push_constant("imageTransparencyCutoff", 0.1f);
-        return sub_pass;
+        sub_pass.push_constant("imageTransparencyCutoff", 0.1f);
+        return &sub_pass;
       };
 
-      texture_subpass_map_.lookup_or_add_cb(TextureSubPassKey(texture, geometry_type), add_cb)
+      texture_subpass_map_
+          .lookup_or_add_cb(TextureSubPassKey(texture, geometry_type), add_texture_cb)
           ->draw(batch, handle);
       return;
     }
   }
-  passes_[static_cast<int>(geometry_type)][static_cast<int>(eShaderType::MATERIAL)]->draw(batch,
-                                                                                          handle);
+
+  auto add_material_cb = [&] {
+    PassMain::Sub &sub_pass =
+        passes_[static_cast<int>(geometry_type)][static_cast<int>(eShaderType::MATERIAL)]->sub(
+            "Material");
+
+    sub_pass.push_constant("material_data", *reinterpret_cast<float4 *>(&material));
+    return &sub_pass;
+  };
+
+  material_subpass_map_
+      .lookup_or_add_cb(MaterialSubPassKey(material, geometry_type), add_material_cb)
+      ->draw(batch, handle);
 }
 
 /** \} */
diff --git a/source/blender/draw/engines/workbench/workbench_private.hh b/source/blender/draw/engines/workbench/workbench_private.hh
index 086553ca5c1..fa809377272 100644
--- a/source/blender/draw/engines/workbench/workbench_private.hh
+++ b/source/blender/draw/engines/workbench/workbench_private.hh
@@ -51,6 +51,16 @@ struct Material {
   static uint32_t pack_data(float metallic, float roughness, float alpha);
 
   bool is_transparent();
+
+  inline bool operator==(const Material &a) const
+  {
+    return packed_data == a.packed_data && base_color == a.base_color;
+  }
+
+  inline uint64_t hash() const
+  {
+    return get_default_hash_4(base_color.x, base_color.y, base_color.z, packed_data);
+  }
 };
 
 void get_material_image(Object *ob,
@@ -161,8 +171,10 @@ struct SceneResources {
 
 class MeshPass : public PassMain {
  private:
+  using MaterialSubPassKey = std::pair<Material, eGeometryType>;
   using TextureSubPassKey = std::pair<GPUTexture *, eGeometryType>;
 
+  Map<MaterialSubPassKey, PassMain::Sub *> material_subpass_map_ = {};
   Map<TextureSubPassKey, PassMain::Sub *> texture_subpass_map_ = {};
 
   PassMain::Sub *passes_[geometry_type_len][shader_type_len] = {{nullptr}};
@@ -184,6 +196,7 @@ class MeshPass : public PassMain {
   void draw(ObjectRef &ref,
             GPUBatch *batch,
             ResourceHandle handle,
+            Material material,
             ::Image *image = nullptr,
             eGPUSamplerState sampler_state = eGPUSamplerState::GPU_SAMPLER_DEFAULT,
             ImageUser *iuser = nullptr);



More information about the Bf-blender-cvs mailing list