[Bf-blender-cvs] [578771ae4dc] master: UDIM: Add support for packing inside .blend files

Jesse Yurkovich noreply at git.blender.org
Thu May 12 05:21:49 CEST 2022


Commit: 578771ae4dcb8643214c69a7b9761ca154f40f63
Author: Jesse Yurkovich
Date:   Wed May 11 20:11:44 2022 -0700
Branches: master
https://developer.blender.org/rB578771ae4dcb8643214c69a7b9761ca154f40f63

UDIM: Add support for packing inside .blend files

This completes support for tiled texture packing on the Blender / Cycles
side of things.

Most of these changes fall into one of three categories:
- Updating Image handling code to pack/unpack tiled and multi-view images
- Updating Cycles to handle tiled textures through BlenderImageLoader
- Updating OSL to properly handle textures with multiple slots

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

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

M	intern/cycles/blender/image.cpp
M	intern/cycles/blender/image.h
M	intern/cycles/blender/shader.cpp
M	intern/cycles/kernel/osl/services.cpp
M	intern/cycles/kernel/osl/services.h
M	intern/cycles/scene/image.cpp
M	intern/cycles/scene/image.h
M	intern/cycles/scene/osl.cpp
M	intern/cycles/scene/osl.h
M	intern/cycles/scene/shader_nodes.cpp
M	source/blender/blenkernel/intern/image.cc
M	source/blender/blenkernel/intern/packedFile.c
M	source/blender/blenloader/intern/versioning_300.c
M	source/blender/editors/space_image/image_ops.c
M	source/blender/makesdna/DNA_image_types.h
M	source/blender/makesrna/intern/rna_image.c
M	source/blender/makesrna/intern/rna_image_api.c

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

diff --git a/intern/cycles/blender/image.cpp b/intern/cycles/blender/image.cpp
index ca4c8f5904a..e01b72c1653 100644
--- a/intern/cycles/blender/image.cpp
+++ b/intern/cycles/blender/image.cpp
@@ -13,9 +13,11 @@ CCL_NAMESPACE_BEGIN
 
 BlenderImageLoader::BlenderImageLoader(BL::Image b_image,
                                        const int frame,
+                                       const int tile_number,
                                        const bool is_preview_render)
     : b_image(b_image),
       frame(frame),
+      tile_number(tile_number),
       /* Don't free cache for preview render to avoid race condition from T93560, to be fixed
          properly later as we are close to release. */
       free_cache(!is_preview_render && !b_image.has_data())
@@ -66,12 +68,11 @@ bool BlenderImageLoader::load_pixels(const ImageMetaData &metadata,
 {
   const size_t num_pixels = ((size_t)metadata.width) * metadata.height;
   const int channels = metadata.channels;
-  const int tile = 0; /* TODO(lukas): Support tiles here? */
 
   if (b_image.is_float()) {
     /* image data */
     float *image_pixels;
-    image_pixels = image_get_float_pixels_for_frame(b_image, frame, tile);
+    image_pixels = image_get_float_pixels_for_frame(b_image, frame, tile_number);
 
     if (image_pixels && num_pixels * channels == pixels_size) {
       memcpy(pixels, image_pixels, pixels_size * sizeof(float));
@@ -99,7 +100,7 @@ bool BlenderImageLoader::load_pixels(const ImageMetaData &metadata,
     }
   }
   else {
-    unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame, tile);
+    unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame, tile_number);
 
     if (image_pixels && num_pixels * channels == pixels_size) {
       memcpy(pixels, image_pixels, pixels_size * sizeof(unsigned char));
@@ -153,7 +154,13 @@ string BlenderImageLoader::name() const
 bool BlenderImageLoader::equals(const ImageLoader &other) const
 {
   const BlenderImageLoader &other_loader = (const BlenderImageLoader &)other;
-  return b_image == other_loader.b_image && frame == other_loader.frame;
+  return b_image == other_loader.b_image && frame == other_loader.frame &&
+         tile_number == other_loader.tile_number;
+}
+
+int BlenderImageLoader::get_tile_number() const
+{
+  return tile_number;
 }
 
 /* Point Density */
diff --git a/intern/cycles/blender/image.h b/intern/cycles/blender/image.h
index ee576b31f7e..c2cc0f51b9b 100644
--- a/intern/cycles/blender/image.h
+++ b/intern/cycles/blender/image.h
@@ -12,7 +12,10 @@ CCL_NAMESPACE_BEGIN
 
 class BlenderImageLoader : public ImageLoader {
  public:
-  BlenderImageLoader(BL::Image b_image, const int frame, const bool is_preview_render);
+  BlenderImageLoader(BL::Image b_image,
+                     const int frame,
+                     const int tile_number,
+                     const bool is_preview_render);
 
   bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override;
   bool load_pixels(const ImageMetaData &metadata,
@@ -22,8 +25,11 @@ class BlenderImageLoader : public ImageLoader {
   string name() const override;
   bool equals(const ImageLoader &other) const override;
 
+  int get_tile_number() const override;
+
   BL::Image b_image;
   int frame;
+  int tile_number;
   bool free_cache;
 };
 
diff --git a/intern/cycles/blender/shader.cpp b/intern/cycles/blender/shader.cpp
index 35c98a71558..81a64457c88 100644
--- a/intern/cycles/blender/shader.cpp
+++ b/intern/cycles/blender/shader.cpp
@@ -776,9 +776,21 @@ static ShaderNode *add_node(Scene *scene,
          */
         int scene_frame = b_scene.frame_current();
         int image_frame = image_user_frame_number(b_image_user, b_image, scene_frame);
-        image->handle = scene->image_manager->add_image(
-            new BlenderImageLoader(b_image, image_frame, b_engine.is_preview()),
-            image->image_params());
+        if (b_image.source() != BL::Image::source_TILED) {
+          image->handle = scene->image_manager->add_image(
+              new BlenderImageLoader(b_image, image_frame, 0, b_engine.is_preview()),
+              image->image_params());
+        }
+        else {
+          vector<ImageLoader *> loaders;
+          loaders.reserve(image->get_tiles().size());
+          for (int tile_number : image->get_tiles()) {
+            loaders.push_back(
+                new BlenderImageLoader(b_image, image_frame, tile_number, b_engine.is_preview()));
+          }
+
+          image->handle = scene->image_manager->add_image(loaders, image->image_params());
+        }
       }
       else {
         ustring filename = ustring(
@@ -814,7 +826,7 @@ static ShaderNode *add_node(Scene *scene,
         int scene_frame = b_scene.frame_current();
         int image_frame = image_user_frame_number(b_image_user, b_image, scene_frame);
         env->handle = scene->image_manager->add_image(
-            new BlenderImageLoader(b_image, image_frame, b_engine.is_preview()),
+            new BlenderImageLoader(b_image, image_frame, 0, b_engine.is_preview()),
             env->image_params());
       }
       else {
diff --git a/intern/cycles/kernel/osl/services.cpp b/intern/cycles/kernel/osl/services.cpp
index 832498f1f73..e2e10b5b83f 100644
--- a/intern/cycles/kernel/osl/services.cpp
+++ b/intern/cycles/kernel/osl/services.cpp
@@ -1304,8 +1304,38 @@ bool OSLRenderServices::texture(ustring filename,
       break;
     }
     case OSLTextureHandle::SVM: {
-      /* Packed texture. */
-      float4 rgba = kernel_tex_image_interp(kernel_globals, handle->svm_slot, s, 1.0f - t);
+      int id = -1;
+      if (handle->svm_slots[0].w == -1) {
+        /* Packed single texture. */
+        id = handle->svm_slots[0].y;
+      }
+      else {
+        /* Packed tiled texture. */
+        int tx = (int)s;
+        int ty = (int)t;
+        int tile = 1001 + 10 * ty + tx;
+        for (int4 tile_node : handle->svm_slots) {
+          if (tile_node.x == tile) {
+            id = tile_node.y;
+            break;
+          }
+          if (tile_node.z == tile) {
+            id = tile_node.w;
+            break;
+          }
+        }
+        s -= tx;
+        t -= ty;
+      }
+
+      float4 rgba;
+      if (id == -1) {
+        rgba = make_float4(
+            TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B, TEX_IMAGE_MISSING_A);
+      }
+      else {
+        rgba = kernel_tex_image_interp(kernel_globals, id, s, 1.0f - t);
+      }
 
       result[0] = rgba[0];
       if (nchannels > 1)
@@ -1319,7 +1349,7 @@ bool OSLRenderServices::texture(ustring filename,
     }
     case OSLTextureHandle::IES: {
       /* IES light. */
-      result[0] = kernel_ies_interp(kernel_globals, handle->svm_slot, s, t);
+      result[0] = kernel_ies_interp(kernel_globals, handle->svm_slots[0].y, s, t);
       status = true;
       break;
     }
@@ -1413,7 +1443,7 @@ bool OSLRenderServices::texture3d(ustring filename,
       /* Packed texture. */
       ShaderData *sd = (ShaderData *)(sg->renderstate);
       KernelGlobals kernel_globals = sd->osl_globals;
-      int slot = handle->svm_slot;
+      int slot = handle->svm_slots[0].y;
       float3 P_float3 = make_float3(P.x, P.y, P.z);
       float4 rgba = kernel_tex_image_interp_3d(kernel_globals, slot, P_float3, INTERPOLATION_NONE);
 
diff --git a/intern/cycles/kernel/osl/services.h b/intern/cycles/kernel/osl/services.h
index 653fa017140..27d7f7fb8e1 100644
--- a/intern/cycles/kernel/osl/services.h
+++ b/intern/cycles/kernel/osl/services.h
@@ -39,18 +39,26 @@ struct KernelGlobalsCPU;
  * with additional data.
  *
  * These are stored in a concurrent hash map, because OSL can compile multiple
- * shaders in parallel. */
+ * shaders in parallel.
+ *
+ * Note: The svm_slots array contains a compressed mapping of tile to svm_slot pairs
+ * stored as follows: x:tile_a, y:svm_slot_a, z:tile_b, w:svm_slot_b etc. */
 
 struct OSLTextureHandle : public OIIO::RefCnt {
   enum Type { OIIO, SVM, IES, BEVEL, AO };
 
+  OSLTextureHandle(Type type, const vector<int4> &svm_slots)
+      : type(type), svm_slots(svm_slots), oiio_handle(NULL), processor(NULL)
+  {
+  }
+
   OSLTextureHandle(Type type = OIIO, int svm_slot = -1)
-      : type(type), svm_slot(svm_slot), oiio_handle(NULL), processor(NULL)
+      : OSLTextureHandle(type, {make_int4(0, svm_slot, -1, -1)})
   {
   }
 
   Type type;
-  int svm_slot;
+  vector<int4> svm_slots;
   OSL::TextureSystem::TextureHandle *oiio_handle;
   ColorSpaceProcessor *processor;
 };
diff --git a/intern/cycles/scene/image.cpp b/intern/cycles/scene/image.cpp
index 21fde88915e..c61ad1f1d71 100644
--- a/intern/cycles/scene/image.cpp
+++ b/intern/cycles/scene/image.cpp
@@ -117,12 +117,12 @@ void ImageHandle::clear()
   manager = NULL;
 }
 
-bool ImageHandle::empty()
+bool ImageHandle::empty() const
 {
   return tile_slots.empty();
 }
 
-int ImageHandle::num_tiles()
+int ImageHandle::num_tiles() const
 {
   return tile_slots.size();
 }
@@ -154,6 +154,35 @@ int ImageHandle::svm_slot(const int tile_index) const
   return tile_slots[tile_index];
 }
 
+vector<int4> ImageHandle::get_svm_slots() const
+{
+  const size_t num_nodes = divide_up(tile_slots.size(), 2);
+
+  vector<int4> svm_slots;
+  svm_slots.reserve(num_nodes);
+  for (size_t i = 0; i < num_nodes; i++) {
+    int4 node;
+
+    int slot = tile_slots[2 * i];
+    node.x = manager->images[slot]->loader->get_tile_number();
+    node.y = slot;
+
+    if ((2 * i + 1) < tile_slots.size()) {
+      slot = tile_slots[2 * i + 1];
+      node.z = manager->images[slot]->loader->get_tile_number();
+      node.w = slot;
+    }
+    else {
+      node.z = -1;
+      node.w = -1;
+    }
+
+    svm_slots.push_back(node);
+  }
+
+  return svm_slots;
+}
+
 device_texture *ImageHandle::image_memory(const int tile_index) const
 {
   if (tile_index >= tile_slots.size()) {
@@ -266,6 +295,11 @@ ustring ImageLoader::osl_filepath() const
   return ustring();
 }
 
+int ImageLoader::get_tile_number() const
+{
+  return 0;
+}
+
 bool ImageLoader::equals(const ImageLoader *a, const ImageLoader *b)
 {
   if (a == NULL && b == NULL) {
@@ -397,6 +431,19 @@ ImageHandle ImageManager::add_image(ImageLoader *loader,
   return handle;
 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list