[Bf-blender-cvs] [a0283355fcf] draw-colormanagement: OpenColorIO: Improve/Cleanup Implementation

Clément Foucault noreply at git.blender.org
Wed Jan 22 19:39:38 CET 2020


Commit: a0283355fcf4d0064224a13140e08c2ab880213a
Author: Clément Foucault
Date:   Wed Jan 22 14:55:38 2020 +0100
Branches: draw-colormanagement
https://developer.blender.org/rBa0283355fcf4d0064224a13140e08c2ab880213a

OpenColorIO: Improve/Cleanup Implementation

This split the shader cache into caches for Shader, Lut and CurveMapping.

This way we can have smoother updates when tweaking/animating the color
managment (i.e. exposure and gamma should only recompile the shader).

The curvemapping, predivide and dither options are no longer compile time
optimized but use uniforms. I did not measure any performance difference.

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

M	intern/opencolorio/gpu_shader_display_transform.glsl
M	intern/opencolorio/ocio_impl_glsl.cc

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

diff --git a/intern/opencolorio/gpu_shader_display_transform.glsl b/intern/opencolorio/gpu_shader_display_transform.glsl
index 9787398e2ae..bc8f5006dda 100644
--- a/intern/opencolorio/gpu_shader_display_transform.glsl
+++ b/intern/opencolorio/gpu_shader_display_transform.glsl
@@ -1,70 +1,65 @@
+/* Blender OpenColorIO implementation */
+
+uniform sampler1D curve_mapping_texture;
 uniform sampler2D image_texture;
 uniform sampler3D lut3d_texture;
 
-#ifdef USE_DITHER
 uniform float dither;
-#endif
-
-in vec2 texCoord_interp;
-out vec4 fragColor;
+uniform bool predivide;
+uniform bool curve_mapping;
 
-#ifdef USE_CURVE_MAPPING
-/* Curve mapping parameters
- *
- * See documentation for OCIO_CurveMappingSettings to get fields descriptions.
- * (this ones pretyt much copies stuff from C structure.)
- */
-uniform sampler1D curve_mapping_texture;
-uniform int curve_mapping_lut_size;
-uniform int use_curve_mapping_extend_extrapolate;
-uniform vec4 curve_mapping_mintable;
-uniform vec4 curve_mapping_range;
-uniform vec4 curve_mapping_ext_in_x;
-uniform vec4 curve_mapping_ext_in_y;
-uniform vec4 curve_mapping_ext_out_x;
-uniform vec4 curve_mapping_ext_out_y;
-uniform vec4 curve_mapping_first_x;
-uniform vec4 curve_mapping_first_y;
-uniform vec4 curve_mapping_last_x;
-uniform vec4 curve_mapping_last_y;
-uniform vec3 curve_mapping_black;
-uniform vec3 curve_mapping_bwmul;
+layout(std140) uniform OCIO_GLSLCurveMappingParameters
+{
+  /* Curve mapping parameters
+   *
+   * See documentation for OCIO_CurveMappingSettings to get fields descriptions.
+   * (this ones pretty much copies stuff from C structure.)
+   */
+  vec4 curve_mapping_mintable;
+  vec4 curve_mapping_range;
+  vec4 curve_mapping_ext_in_x;
+  vec4 curve_mapping_ext_in_y;
+  vec4 curve_mapping_ext_out_x;
+  vec4 curve_mapping_ext_out_y;
+  vec4 curve_mapping_first_x;
+  vec4 curve_mapping_first_y;
+  vec4 curve_mapping_last_x;
+  vec4 curve_mapping_last_y;
+  vec4 curve_mapping_black;
+  vec4 curve_mapping_bwmul;
+  int curve_mapping_lut_size;
+  int curve_mapping_use_extend_extrapolate;
+};
 
 float read_curve_mapping(int table, int index)
 {
-  /* TODO(sergey): Without -1 here image is getting darken after applying unite curve.
-   *               But is it actually correct to subtract 1 here?
-   */
-  float texture_index = float(index) / float(curve_mapping_lut_size - 1);
-  return texture(curve_mapping_texture, texture_index)[table];
+  return texelFetch(curve_mapping_texture, index, 0)[table];
 }
 
 float curvemap_calc_extend(int table, float x, vec2 first, vec2 last)
 {
   if (x <= first[0]) {
-    if (use_curve_mapping_extend_extrapolate == 0) {
+    if (curve_mapping_use_extend_extrapolate == 0) {
       /* horizontal extrapolation */
       return first[1];
     }
     else {
-      if (curve_mapping_ext_in_x[table] == 0.0)
-        return first[1] + curve_mapping_ext_in_y[table] * 10000.0;
-      else
-        return first[1] +
-               curve_mapping_ext_in_y[table] * (x - first[0]) / curve_mapping_ext_in_x[table];
+      float fac = (curve_mapping_ext_in_x[table] != 0.0) ?
+                      ((x - first[0]) / curve_mapping_ext_in_x[table]) :
+                      10000.0;
+      return first[1] + curve_mapping_ext_in_y[table] * fac;
     }
   }
   else if (x >= last[0]) {
-    if (use_curve_mapping_extend_extrapolate == 0) {
+    if (curve_mapping_use_extend_extrapolate == 0) {
       /* horizontal extrapolation */
       return last[1];
     }
     else {
-      if (curve_mapping_ext_out_x[table] == 0.0)
-        return last[1] - curve_mapping_ext_out_y[table] * 10000.0;
-      else
-        return last[1] +
-               curve_mapping_ext_out_y[table] * (x - last[0]) / curve_mapping_ext_out_x[table];
+      float fac = (curve_mapping_ext_out_x[table] != 0.0) ?
+                      ((x - last[0]) / curve_mapping_ext_out_x[table]) :
+                      -10000.0;
+      return last[1] + curve_mapping_ext_out_y[table] * fac;
     }
   }
   return 0.0;
@@ -92,80 +87,91 @@ float curvemap_evaluateF(int table, float value)
                                 vec2(curve_mapping_last_x[table], curve_mapping_last_y[table]));
   }
   else {
-    if (i < 0)
+    if (i < 0) {
       return read_curve_mapping(table, 0);
-    if (i >= CM_TABLE)
+    }
+    if (i >= CM_TABLE) {
       return read_curve_mapping(table, CM_TABLE);
-
+    }
     fi = fi - float(i);
-    return (1.0 - fi) * read_curve_mapping(table, i) + fi * read_curve_mapping(table, i + 1);
+    float cm1 = read_curve_mapping(table, i);
+    float cm2 = read_curve_mapping(table, i + 1);
+    return mix(cm1, cm2, fi);
   }
 }
 
 vec4 curvemapping_evaluate_premulRGBF(vec4 col)
 {
-  vec4 result = col;
-  result[0] = curvemap_evaluateF(0, (col[0] - curve_mapping_black[0]) * curve_mapping_bwmul[0]);
-  result[1] = curvemap_evaluateF(1, (col[1] - curve_mapping_black[1]) * curve_mapping_bwmul[1]);
-  result[2] = curvemap_evaluateF(2, (col[2] - curve_mapping_black[2]) * curve_mapping_bwmul[2]);
-  result[3] = col[3];
+  col.rgb = (col.rgb - curve_mapping_black.rgb) * curve_mapping_bwmul.rgb;
+
+  vec4 result;
+  result.r = curvemap_evaluateF(0, col.r);
+  result.g = curvemap_evaluateF(1, col.g);
+  result.b = curvemap_evaluateF(2, col.b);
+  result.a = col.a;
   return result;
 }
-#endif
 
-#ifdef USE_DITHER
 float dither_random_value(vec2 co)
 {
   return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453) * 0.005 * dither;
 }
 
-vec2 round_to_pixel(vec2 st)
+vec2 round_to_pixel(sampler2D tex, vec2 uv)
 {
-  vec2 result;
-  vec2 size = textureSize(image_texture, 0);
-  result.x = float(int(st.x * size.x)) / size.x;
-  result.y = float(int(st.y * size.y)) / size.y;
-  return result;
+  vec2 size = textureSize(tex, 0);
+  return vec2(ivec2(uv * size)) / size;
 }
 
-vec4 apply_dither(vec2 st, vec4 col)
+vec4 apply_dither(vec4 col, vec2 uv)
 {
-  vec4 result;
-  float random_value = dither_random_value(round_to_pixel(st));
-  result.r = col.r + random_value;
-  result.g = col.g + random_value;
-  result.b = col.b + random_value;
-  result.a = col.a;
-  return result;
+  col.rgb += dither_random_value(uv);
+  return col;
 }
-#endif
 
-void main()
+vec4 OCIO_ProcessColor(vec4 col, vec2 noise_uv)
 {
-  vec4 col = texture(image_texture, texCoord_interp.st);
-#ifdef USE_CURVE_MAPPING
-  col = curvemapping_evaluate_premulRGBF(col);
-#endif
+  if (curve_mapping) {
+    col = curvemapping_evaluate_premulRGBF(col);
+  }
 
-#ifdef USE_PREDIVIDE
-  if (col[3] > 0.0 && col[3] < 1.0) {
-    float inv_alpha = 1.0 / col[3];
-    col[0] *= inv_alpha;
-    col[1] *= inv_alpha;
-    col[2] *= inv_alpha;
+  if (predivide) {
+    if (col.a > 0.0 && col.a < 1.0) {
+      col.rgb *= 1.0 / col.a;
+    }
   }
-#endif
 
   /* NOTE: This is true we only do de-premul here and NO premul
    *       and the reason is simple -- opengl is always configured
    *       for straight alpha at this moment
    */
 
-  vec4 result = OCIODisplay(col, lut3d_texture);
+  col = OCIODisplay(col, lut3d_texture);
 
-#ifdef USE_DITHER
-  result = apply_dither(texCoord_interp.st, result);
-#endif
+  if (dither > 0.0) {
+    col = apply_dither(col, noise_uv);
+  }
+
+  return col;
+}
+
+/*  ------------------------------------------------------------------------  */
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+/* Standard Implementation. */
+void main()
+{
+  vec4 col = texture(image_texture, texCoord_interp.st);
+  vec2 noise_uv = round_to_pixel(image_texture, texCoord_interp.st);
 
-  fragColor = result;
+  fragColor = OCIO_ProcessColor(col, noise_uv);
 }
+
+#if 0 /* In-place transformation. No extra buffer required. */
+void main()
+{
+  /* TODO(fclem) use imageLoad/Store to do in-place color-management. */
+}
+#endif
diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc
index a80e29a2dec..45bb4ae27a7 100644
--- a/intern/opencolorio/ocio_impl_glsl.cc
+++ b/intern/opencolorio/ocio_impl_glsl.cc
@@ -56,62 +56,107 @@ using namespace OCIO_NAMESPACE;
 #include "ocio_impl.h"
 
 static const int LUT3D_EDGE_SIZE = 64;
+static const int LUT3D_TEXTURE_SIZE = sizeof(float) * 3 * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE *
+                                      LUT3D_EDGE_SIZE;
 static const int SHADER_CACHE_SIZE = 4;
 
+#define UBO_BIND_LOC 0
+
 extern "C" char datatoc_gpu_shader_display_transform_glsl[];
 extern "C" char datatoc_gpu_shader_display_transform_vertex_glsl[];
 
 /* **** OpenGL drawing routines using GLSL for color space transform ***** */
 
-typedef struct OCIO_GLSLShader {
-  /* Cache ID */
-  std::string lut3dCacheID;
-  std::string shaderCacheID;
-
-  /* LUT */
-  bool lut3d_texture_allocated; /* boolean flag indicating whether
-                                 * lut texture is allocated
-                                 */
-  bool lut3d_texture_valid;
-
-  GLuint lut3d_texture; /* OGL texture ID for 3D LUT */
-
-  float *lut3d; /* 3D LUT table */
-
-  /* Dither */
-  bool use_dither;
-
-  /* Curve Mapping */
-  bool use_curve_mapping;
-  bool curve_mapping_texture_allocated;
-  bool curve_mapping_texture_valid;
-  GLuint curve_mapping_texture;
-  size_t curve_mapping_cache_id;
-
-  /* Alpha Predivide */
-  bool use_predivide;
+/* Curve mapping parameters
+ *
+ * See documentation for OCIO_CurveMappingSettings to get fields descriptions.
+ * (this ones pretty much copies stuff from C structure.)
+ */
+typedef struct OCIO_GLSLCurveMappingParameters {
+  float curve_mapping_mintable[4];
+  float curve_mapping_range[4];
+  float curve_mapping_ext_in_x[4];
+  float curve_mapping_ext_in_y[4];
+  float curve_mapping_ext_out_x[4];
+  float curve_mapping_ext_out_y[4];
+  float curve_mapping_first_x[4];
+  float curve_mapping_first_y[4];
+  float curve_mapping_last_x[4];
+  float curve_mapping_last_y[4];
+  float curve_mapping_black[4];
+  float curve_mapping_bwmul[4];
+  int curve_mapping_lut_size;
+  int curve_mapping_use_extend_extrapolate;
+  int _pad[2];
+  /** WARNING: Needs to be 16byte aligned. Used as UBO data. */
+} OCIO_GLSLCurveMappingParameters;
 
-  /* GLSL stuff */
-  GLuint ocio_shader;
-  GLuint vert_shader;
+typedef struct OCIO_GLSLShader {
+  /** Cache IDs */
+  std::string cacheId;
+  /** IMM shader interface. TOD

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list