[Bf-blender-cvs] [9066f2e0437] master: Cycles: Add support for OSL texture intrinsic on the GPU

Patrick Mours noreply at git.blender.org
Thu Jan 19 19:15:15 CET 2023


Commit: 9066f2e0437a45d66f3b6a4bb0de7acf5ec40030
Author: Patrick Mours
Date:   Wed Jan 18 17:28:03 2023 +0100
Branches: master
https://developer.blender.org/rB9066f2e0437a45d66f3b6a4bb0de7acf5ec40030

Cycles: Add support for OSL texture intrinsic on the GPU

This makes it possible to use `texture` and `texture3d` in custom
OSL shaders with a constant image file name as argument on the
GPU, where previously texturing was only possible through Cycles
nodes.
For constant file name arguments, OSL calls
`OSL::RendererServices::get_texture_handle()` with the file name
string to convert it into an opaque handle for use on the GPU.
That is now used to load the respective image file using the Cycles
image manager and generate a SVM handle that can be used on
the GPU. Some care is necessary as the renderer services class is
shared across multiple Cycles instances, whereas the Cycles image
manager is local to each.

Maniphest Tasks: T101222

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

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

M	intern/cycles/kernel/osl/services.cpp
M	intern/cycles/kernel/osl/services.h
M	intern/cycles/kernel/osl/services_gpu.h
M	intern/cycles/kernel/osl/types.h
M	intern/cycles/kernel/svm/ies.h
M	intern/cycles/scene/image.cpp
M	intern/cycles/scene/image.h
M	intern/cycles/scene/osl.cpp

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

diff --git a/intern/cycles/kernel/osl/services.cpp b/intern/cycles/kernel/osl/services.cpp
index 95d58875b91..92708df3162 100644
--- a/intern/cycles/kernel/osl/services.cpp
+++ b/intern/cycles/kernel/osl/services.cpp
@@ -20,6 +20,7 @@
 
 #include "kernel/osl/globals.h"
 #include "kernel/osl/services.h"
+#include "kernel/osl/types.h"
 
 #include "util/foreach.h"
 #include "util/log.h"
@@ -119,6 +120,8 @@ ustring OSLRenderServices::u_u("u");
 ustring OSLRenderServices::u_v("v");
 ustring OSLRenderServices::u_empty;
 
+ImageManager *OSLRenderServices::image_manager = nullptr;
+
 OSLRenderServices::OSLRenderServices(OSL::TextureSystem *texture_system, int device_type)
     : OSL::RendererServices(texture_system), device_type_(device_type)
 {
@@ -1154,7 +1157,7 @@ TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(ustring file
     /* For non-OIIO textures, just return a pointer to our own OSLTextureHandle. */
     if (it != textures.end()) {
       if (it->second->type != OSLTextureHandle::OIIO) {
-        return (TextureSystem::TextureHandle *)it->second.get();
+        return reinterpret_cast<TextureSystem::TextureHandle *>(it->second.get());
       }
     }
 
@@ -1173,16 +1176,53 @@ TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(ustring file
 
     /* Assign OIIO texture handle and return. */
     it->second->oiio_handle = handle;
-    return (TextureSystem::TextureHandle *)it->second.get();
+    return reinterpret_cast<TextureSystem::TextureHandle *>(it->second.get());
   }
   else {
-    if (it != textures.end() && it->second->type == OSLTextureHandle::SVM &&
-        it->second->svm_slots[0].w == -1) {
-      return reinterpret_cast<TextureSystem::TextureHandle *>(
-          static_cast<uintptr_t>(it->second->svm_slots[0].y + 1));
+    /* Construct GPU texture handle for existing textures. */
+    if (it != textures.end()) {
+      switch (it->second->type) {
+        case OSLTextureHandle::OIIO:
+          return NULL;
+        case OSLTextureHandle::SVM:
+          if (!it->second->handle.empty() && it->second->handle.get_manager() != image_manager) {
+            it.clear();
+            break;
+          }
+          return reinterpret_cast<TextureSystem::TextureHandle *>(OSL_TEXTURE_HANDLE_TYPE_SVM |
+                                                                  it->second->svm_slots[0].y);
+        case OSLTextureHandle::IES:
+          if (!it->second->handle.empty() && it->second->handle.get_manager() != image_manager) {
+            it.clear();
+            break;
+          }
+          return reinterpret_cast<TextureSystem::TextureHandle *>(OSL_TEXTURE_HANDLE_TYPE_IES |
+                                                                  it->second->svm_slots[0].y);
+        case OSLTextureHandle::AO:
+          return reinterpret_cast<TextureSystem::TextureHandle *>(
+              OSL_TEXTURE_HANDLE_TYPE_AO_OR_BEVEL | 1);
+        case OSLTextureHandle::BEVEL:
+          return reinterpret_cast<TextureSystem::TextureHandle *>(
+              OSL_TEXTURE_HANDLE_TYPE_AO_OR_BEVEL | 2);
+      }
+    }
+
+    if (!image_manager) {
+      return NULL;
+    }
+
+    /* Load new textures using SVM image manager. */
+    ImageHandle handle = image_manager->add_image(filename.string(), ImageParams());
+    if (handle.empty()) {
+      return NULL;
+    }
+
+    if (!textures.insert(filename, new OSLTextureHandle(handle))) {
+      return NULL;
     }
 
-    return NULL;
+    return reinterpret_cast<TextureSystem::TextureHandle *>(OSL_TEXTURE_HANDLE_TYPE_SVM |
+                                                            handle.svm_slot());
   }
 }
 
diff --git a/intern/cycles/kernel/osl/services.h b/intern/cycles/kernel/osl/services.h
index 9d875ae8e94..747eb242d8c 100644
--- a/intern/cycles/kernel/osl/services.h
+++ b/intern/cycles/kernel/osl/services.h
@@ -16,6 +16,8 @@
 #include <OSL/oslexec.h>
 #include <OSL/rendererservices.h>
 
+#include "scene/image.h"
+
 #ifdef WITH_PTEX
 class PtexCache;
 #endif
@@ -54,10 +56,20 @@ struct OSLTextureHandle : public OIIO::RefCnt {
   {
   }
 
+  OSLTextureHandle(const ImageHandle &handle)
+      : type(SVM),
+        svm_slots(handle.get_svm_slots()),
+        oiio_handle(nullptr),
+        processor(nullptr),
+        handle(handle)
+  {
+  }
+
   Type type;
   vector<int4> svm_slots;
   OSL::TextureSystem::TextureHandle *oiio_handle;
   ColorSpaceProcessor *processor;
+  ImageHandle handle;
 };
 
 typedef OIIO::intrusive_ptr<OSLTextureHandle> OSLTextureHandleRef;
@@ -324,6 +336,8 @@ class OSLRenderServices : public OSL::RendererServices {
    * shading system. */
   OSLTextureHandleMap textures;
 
+  static ImageManager *image_manager;
+
  private:
   int device_type_;
 };
diff --git a/intern/cycles/kernel/osl/services_gpu.h b/intern/cycles/kernel/osl/services_gpu.h
index b9ffd959f1a..2fa4299d3f9 100644
--- a/intern/cycles/kernel/osl/services_gpu.h
+++ b/intern/cycles/kernel/osl/services_gpu.h
@@ -1443,6 +1443,8 @@ OSL_NOISE_IMPL(osl_snoise, snoise)
 
 /* Texturing */
 
+#include "kernel/svm/ies.h"
+
 ccl_device_extern ccl_private OSLTextureOptions *osl_get_texture_options(
     ccl_private ShaderGlobals *sg)
 {
@@ -1548,25 +1550,31 @@ ccl_device_extern bool osl_texture(ccl_private ShaderGlobals *sg,
                                    ccl_private float *dalphady,
                                    ccl_private void *errormessage)
 {
-  if (!texture_handle) {
-    return false;
+  const unsigned int type = OSL_TEXTURE_HANDLE_TYPE(texture_handle);
+  const unsigned int slot = OSL_TEXTURE_HANDLE_SLOT(texture_handle);
+
+  switch (type) {
+    case OSL_TEXTURE_HANDLE_TYPE_SVM: {
+      const float4 rgba = kernel_tex_image_interp(nullptr, slot, s, 1.0f - t);
+      if (nchannels > 0)
+        result[0] = rgba.x;
+      if (nchannels > 1)
+        result[1] = rgba.y;
+      if (nchannels > 2)
+        result[2] = rgba.z;
+      if (alpha)
+        *alpha = rgba.w;
+      return true;
+    }
+    case OSL_TEXTURE_HANDLE_TYPE_IES: {
+      if (nchannels > 0)
+        result[0] = kernel_ies_interp(nullptr, slot, s, t);
+      return true;
+    }
+    default: {
+      return false;
+    }
   }
-
-  /* Only SVM textures are supported. */
-  int id = static_cast<int>(reinterpret_cast<size_t>(texture_handle) - 1);
-
-  const float4 rgba = kernel_tex_image_interp(nullptr, id, s, 1.0f - t);
-
-  if (nchannels > 0)
-    result[0] = rgba.x;
-  if (nchannels > 1)
-    result[1] = rgba.y;
-  if (nchannels > 2)
-    result[2] = rgba.z;
-  if (alpha)
-    *alpha = rgba.w;
-
-  return true;
 }
 
 ccl_device_extern bool osl_texture3d(ccl_private ShaderGlobals *sg,
@@ -1586,25 +1594,26 @@ ccl_device_extern bool osl_texture3d(ccl_private ShaderGlobals *sg,
                                      ccl_private float *dalphady,
                                      ccl_private void *errormessage)
 {
-  if (!texture_handle) {
-    return false;
+  const unsigned int type = OSL_TEXTURE_HANDLE_TYPE(texture_handle);
+  const unsigned int slot = OSL_TEXTURE_HANDLE_SLOT(texture_handle);
+
+  switch (type) {
+    case OSL_TEXTURE_HANDLE_TYPE_SVM: {
+      const float4 rgba = kernel_tex_image_interp_3d(nullptr, slot, *P, INTERPOLATION_NONE);
+      if (nchannels > 0)
+        result[0] = rgba.x;
+      if (nchannels > 1)
+        result[1] = rgba.y;
+      if (nchannels > 2)
+        result[2] = rgba.z;
+      if (alpha)
+        *alpha = rgba.w;
+      return true;
+    }
+    default: {
+      return false;
+    }
   }
-
-  /* Only SVM textures are supported. */
-  int id = static_cast<int>(reinterpret_cast<size_t>(texture_handle) - 1);
-
-  const float4 rgba = kernel_tex_image_interp_3d(nullptr, id, *P, INTERPOLATION_NONE);
-
-  if (nchannels > 0)
-    result[0] = rgba.x;
-  if (nchannels > 1)
-    result[1] = rgba.y;
-  if (nchannels > 2)
-    result[2] = rgba.z;
-  if (alpha)
-    *alpha = rgba.w;
-
-  return true;
 }
 
 ccl_device_extern bool osl_environment(ccl_private ShaderGlobals *sg,
diff --git a/intern/cycles/kernel/osl/types.h b/intern/cycles/kernel/osl/types.h
index 692c2349a30..528f07ad58c 100644
--- a/intern/cycles/kernel/osl/types.h
+++ b/intern/cycles/kernel/osl/types.h
@@ -90,10 +90,17 @@ struct ShaderGlobals {
   int backfacing;
 };
 
-struct OSLNoiseOptions {
-};
+struct OSLNoiseOptions {};
 
-struct OSLTextureOptions {
-};
+struct OSLTextureOptions {};
+
+#define OSL_TEXTURE_HANDLE_TYPE_IES ((uintptr_t)0x2 << 30)
+#define OSL_TEXTURE_HANDLE_TYPE_SVM ((uintptr_t)0x1 << 30)
+#define OSL_TEXTURE_HANDLE_TYPE_AO_OR_BEVEL ((uintptr_t)0x3 << 30)
+
+#define OSL_TEXTURE_HANDLE_TYPE(handle) \
+  ((unsigned int)((uintptr_t)(handle) & ((uintptr_t)0x3 << 30)))
+#define OSL_TEXTURE_HANDLE_SLOT(handle) \
+  ((unsigned int)((uintptr_t)(handle) & ((uintptr_t)0x3FFFFFFF)))
 
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/ies.h b/intern/cycles/kernel/svm/ies.h
index 3648cb580d5..b40e04df62c 100644
--- a/intern/cycles/kernel/svm/ies.h
+++ b/intern/cycles/kernel/svm/ies.h
@@ -84,6 +84,7 @@ ccl_device_inline float kernel_ies_interp(KernelGlobals kg, int slot, float h_an
   return max(cubic_interp(a, b, c, d, h_frac), 0.0f);
 }
 
+#ifdef __SVM__
 ccl_device_noinline void svm_node_ies(KernelGlobals kg,
                                       ccl_private ShaderData *sd,
                                       ccl_private float *stack,
@@ -105,5 +106,6 @@ ccl_device_noinline void svm_node_ies(KernelGlobals kg,
     stack_store_float(stack, fac_offset, fac);
   }
 }
+#endif
 
 CCL_NAMESPACE_END
diff --git a/intern/cycles/scene/image.cpp b/intern/cycles/scene/image.cpp
index a5c794bc762..925583f88b5 100644
--- a/intern/cycles/scene/image.cpp
+++ b/intern/cycles/scene/image.cpp
@@ -222,6 +222,11 @@ VDBImageLoader *ImageHandle::vdb_loader(const int tile_index) const
   return NULL;
 }
 
+ImageManager *ImageHandle::get_manager() const
+{
+  return manager;
+}
+
 bool ImageHandle::operator==(const ImageHandle &other) const
 {
   return manager == other.manager && tile_slots == other.tile_slots;
diff --git a/intern/cycles/scene/image.h b/intern/cycles/scene/image.h
index da47d8144bc..36bfe17a69d 100644
--- a/intern/cycles/scene/image.h
+++ b/intern/cycles/scene/image.h
@@ -153,6 +153,8 @@ class I

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list