[Bf-blender-cvs] [0e1938e6db9] tmp-texture-sampler: GPU: Texture: Replace internal sampler state by explicit state object

Clément Foucault noreply at git.blender.org
Mon May 25 10:49:45 CEST 2020


Commit: 0e1938e6db9bffd462a04c792908ee7512513f59
Author: Clément Foucault
Date:   Sat May 23 00:01:57 2020 +0200
Branches: tmp-texture-sampler
https://developer.blender.org/rB0e1938e6db9bffd462a04c792908ee7512513f59

GPU: Texture: Replace internal sampler state by explicit state object

This is closer to vulkan design and allow for easier state management in
the future. For instance, adding the ability to bind the texture twice
with different sampler params.

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

M	source/blender/gpu/GPU_texture.h
M	source/blender/gpu/intern/gpu_extensions.c
M	source/blender/gpu/intern/gpu_texture.c

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

diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 3d99a3c8a56..5c86ec0d990 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -41,6 +41,30 @@ struct PreviewImage;
 struct GPUFrameBuffer;
 typedef struct GPUTexture GPUTexture;
 
+/* GPU Samplers state
+ * - Specify the sampler state to bind a texture with.
+ * - Internally used by textures.
+ * - All states are created at startup to avoid runtime costs.
+ */
+
+typedef enum eGPUSamplerState {
+  GPU_SAMPLER_FILTER = (1 << 0),
+  GPU_SAMPLER_MIPMAP = (1 << 1),
+  GPU_SAMPLER_REPEAT_S = (1 << 2),
+  GPU_SAMPLER_REPEAT_T = (1 << 3),
+  GPU_SAMPLER_REPEAT_R = (1 << 4),
+  GPU_SAMPLER_CLAMP_BORDER = (1 << 5), /* Clamp to border color instead of border texel. */
+  GPU_SAMPLER_COMPARE = (1 << 6),
+  /* Don't use that. */
+  GPU_SAMPLER_MAX = (1 << 7),
+} eGPUSamplerState;
+
+#define GPU_SAMPLER_DEFAULT GPU_SAMPLER_FILTER
+#define GPU_SAMPLER_REPEAT (GPU_SAMPLER_REPEAT_S | GPU_SAMPLER_REPEAT_T | GPU_SAMPLER_REPEAT_R)
+
+void GPU_samplers_init(void);
+void GPU_samplers_free(void);
+
 /* GPU Texture
  * - always returns unsigned char RGBA textures
  * - if texture with non square dimensions is created, depending on the
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index ff745787630..8f911f3c77d 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -355,11 +355,13 @@ void gpu_extensions_init(void)
   }
 
   GPU_invalid_tex_init();
+  GPU_samplers_init();
 }
 
 void gpu_extensions_exit(void)
 {
   GPU_invalid_tex_free();
+  GPU_samplers_free();
 }
 
 bool GPU_mem_stats_supported(void)
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index fd01ddf8597..f5dd24219df 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -50,7 +50,9 @@ static struct GPUTextureGlobal {
   GPUTexture *invalid_tex_1D;
   GPUTexture *invalid_tex_2D;
   GPUTexture *invalid_tex_3D;
-} GG = {NULL, NULL, NULL};
+  /** Sampler objects used to replace internal texture parameters. */
+  GLuint samplers[GPU_SAMPLER_MAX];
+} GG = {NULL};
 
 /* Maximum number of FBOs a texture can be attached to. */
 #define GPU_TEX_MAX_FBO_ATTACHED 12
@@ -81,6 +83,7 @@ struct GPUTexture {
 
   eGPUTextureFormat format;
   eGPUTextureFormatFlag format_flag;
+  eGPUSamplerState sampler_state; /* Internal Sampler state. */
 
   int mipmaps;    /* number of mipmaps */
   int components; /* number of color/alpha channels */
@@ -975,26 +978,13 @@ GPUTexture *GPU_texture_create_nD(int w,
   if (GPU_texture_stencil(tex) || /* Does not support filtering */
       GPU_texture_integer(tex) || /* Does not support filtering */
       GPU_texture_depth(tex)) {
-    glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    tex->sampler_state = GPU_SAMPLER_DEFAULT & ~GPU_SAMPLER_FILTER;
   }
   else {
-    glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  }
-
-  if (GPU_texture_depth(tex)) {
-    glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
-    glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
-  }
-
-  glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-  if (n > 1) {
-    glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-  }
-  if (n > 2) {
-    glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+    tex->sampler_state = GPU_SAMPLER_DEFAULT;
   }
+  /* Avoid issue with incomplete textures. */
+  glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 
   glBindTexture(tex->target, 0);
 
@@ -1116,22 +1106,13 @@ GPUTexture *GPU_texture_cube_create(int w,
   if (GPU_texture_stencil(tex) || /* Does not support filtering */
       GPU_texture_integer(tex) || /* Does not support filtering */
       GPU_texture_depth(tex)) {
-    glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    tex->sampler_state = GPU_SAMPLER_DEFAULT & ~GPU_SAMPLER_FILTER;
   }
   else {
-    glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  }
-
-  if (GPU_texture_depth(tex)) {
-    glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
-    glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+    tex->sampler_state = GPU_SAMPLER_DEFAULT;
   }
-
-  glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-  glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-  glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+  /* Avoid issue with incomplete textures. */
+  glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 
   glBindTexture(tex->target, 0);
 
@@ -1659,9 +1640,11 @@ void GPU_texture_bind(GPUTexture *tex, int number)
 
   if (tex->bindcode != 0) {
     glBindTexture(tex->target, tex->bindcode);
+    glBindSampler(number, GG.samplers[tex->sampler_state]);
   }
   else {
     GPU_invalid_tex_bind(tex->target_base);
+    glBindSampler(number, 0);
   }
 
   tex->number = number;
@@ -1675,6 +1658,7 @@ void GPU_texture_unbind(GPUTexture *tex)
 
   glActiveTexture(GL_TEXTURE0 + tex->number);
   glBindTexture(tex->target, 0);
+  glBindSampler(tex->number, 0);
 
   tex->number = -1;
 }
@@ -1812,69 +1796,35 @@ void GPU_texture_copy(GPUTexture *dst, GPUTexture *src)
 
 void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare)
 {
-  WARN_NOT_BOUND(tex);
-
   /* Could become an assertion ? (fclem) */
   if (!GPU_texture_depth(tex)) {
     return;
   }
-
-  GLenum mode = (use_compare) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE;
-
-  glActiveTexture(GL_TEXTURE0 + tex->number);
-  glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, mode);
+  SET_FLAG_FROM_TEST(tex->sampler_state, use_compare, GPU_SAMPLER_COMPARE);
 }
 
 void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter)
 {
-  WARN_NOT_BOUND(tex);
-
   /* Stencil and integer format does not support filtering. */
   BLI_assert(!use_filter || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
 
-  GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST;
-
-  glActiveTexture(GL_TEXTURE0 + tex->number);
-  glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
-  glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, filter);
+  SET_FLAG_FROM_TEST(tex->sampler_state, use_filter, GPU_SAMPLER_FILTER);
 }
 
 void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter)
 {
-  WARN_NOT_BOUND(tex);
-
   /* Stencil and integer format does not support filtering. */
-  BLI_assert((!use_filter && !use_mipmap) ||
+  BLI_assert(!(use_filter || use_mipmap) ||
              !(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
 
-  GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST;
-  GLenum mipmap = ((use_filter) ? (use_mipmap) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR :
-                                  (use_mipmap) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST);
-
-  glActiveTexture(GL_TEXTURE0 + tex->number);
-  glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, mipmap);
-  glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
+  SET_FLAG_FROM_TEST(tex->sampler_state, use_mipmap, GPU_SAMPLER_MIPMAP);
+  SET_FLAG_FROM_TEST(tex->sampler_state, use_filter, GPU_SAMPLER_FILTER);
 }
 
 void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat, bool use_clamp)
 {
-  WARN_NOT_BOUND(tex);
-
-  GLenum repeat = (use_repeat) ? GL_REPEAT : (use_clamp) ? GL_CLAMP_TO_EDGE : GL_CLAMP_TO_BORDER;
-
-  glActiveTexture(GL_TEXTURE0 + tex->number);
-  glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, repeat);
-  if (tex->target_base != GL_TEXTURE_1D) {
-    glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, repeat);
-  }
-  if (tex->target_base == GL_TEXTURE_3D) {
-    glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, repeat);
-  }
-
-  if (repeat == GL_CLAMP_TO_BORDER) {
-    const float black[] = {0.0f, 0.0f, 0.0f, 0.0f};
-    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, black);
-  }
+  SET_FLAG_FROM_TEST(tex->sampler_state, use_repeat, GPU_SAMPLER_REPEAT);
+  SET_FLAG_FROM_TEST(tex->sampler_state, !use_clamp, GPU_SAMPLER_CLAMP_BORDER);
 }
 
 void GPU_texture_swizzle_channel_auto(GPUTexture *tex, int channels)
@@ -1888,34 +1838,6 @@ void GPU_texture_swizzle_channel_auto(GPUTexture *tex, int channels)
   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, (channels >= 4) ? GL_ALPHA : GL_ONE);
 }
 
-static GLenum gpu_get_gl_filterfunction(eGPUFilterFunction filter)
-{
-  switch (filter) {
-    case GPU_NEAREST:
-      return GL_NEAREST;
-    case GPU_LINEAR:
-      return GL_LINEAR;
-    default:
-      BLI_assert(!"Unhandled filter mode");
-      return GL_NEAREST;
-  }
-}
-
-void GPU_texture_filters(GPUTexture *tex,
-                         eGPUFilterFunction min_filter,
-                         eGPUFilterFunction mag_filter)
-{
-  WARN_NOT_BOUND(tex);
-
-  /* Stencil and integer format does not support filtering. */
-  BLI_assert(!(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
-  BLI_assert(mag_filter == GPU_NEAREST || mag_filter == GPU_LINEAR);
-
-  glActiveTexture(GL_TEXTURE0 + tex->number);
-  glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, gpu_get_gl_filterfunction(min_filter));
-  glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, gpu_get_gl_filterfunction(mag_filter));
-}
-
 void GPU_texture_free(GPUTexture *tex)
 {
   tex->refcount--;
@@ -2076,3 +1998,52 @@ void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *size)
     size[2] = max_ii(1, tex->d / div);
   }
 }
+
+/* -------------------------------------------------------------------- */
+/** \name GPU Sampler Objects
+ *
+ * Simple wrapper around opengl sampler objects.
+ * Override texture sampler state for one sampler unit only.
+ * \

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list