Module: Mesa
Branch: master
Commit: e8f71f6ac48c14d3ec923e3cc819d79095a43070
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=e8f71f6ac48c14d3ec923e3cc819d79095a43070

Author: Mike Blumenkrantz <michael.blumenkra...@gmail.com>
Date:   Mon Jan 25 17:37:29 2021 -0500

mesa/st: add PIPE_CAP_GL_CLAMP

when this is not set, this triggers shader and sampler state updates any time a 
sampler
starts or stops using GL_CLAMP, applying bitmasks needed to run nir_lower_tex
and setting CLAMP_TO_BORDER/CLAMP_TO_EDGE as necessary to mimic the behavior

Reviewed-by: Eric Anholt <e...@anholt.net>
Reviewed-by: Marek Olšák <marek.ol...@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8756>

---

 docs/gallium/screen.rst                        |  1 +
 src/gallium/auxiliary/util/u_screen.c          |  1 +
 src/gallium/drivers/nouveau/nvc0/nvc0_screen.c |  1 +
 src/gallium/include/pipe/p_defines.h           |  2 +-
 src/mesa/main/mtypes.h                         |  3 ++
 src/mesa/main/samplerobj.c                     | 12 +++++++
 src/mesa/main/texparam.c                       | 12 +++++++
 src/mesa/state_tracker/st_atom_sampler.c       | 19 +++++++++++
 src/mesa/state_tracker/st_atom_shader.c        | 44 ++++++++++++++++++++++++++
 src/mesa/state_tracker/st_context.c            |  8 +++++
 src/mesa/state_tracker/st_context.h            |  1 +
 src/mesa/state_tracker/st_program.c            | 19 +++++++++++
 src/mesa/state_tracker/st_program.h            |  6 ++++
 13 files changed, 128 insertions(+), 1 deletion(-)

diff --git a/docs/gallium/screen.rst b/docs/gallium/screen.rst
index be505ecad8a..ebeef25d94e 100644
--- a/docs/gallium/screen.rst
+++ b/docs/gallium/screen.rst
@@ -610,6 +610,7 @@ The integer capabilities:
 * ``PIPE_CAP_MAX_TEXTURE_MB``: Maximum texture size in MB (default is 1024)
 * ``PIPE_CAP_DEVICE_PROTECTED_CONTENT``: Whether the device support protected 
/ encrypted content.
 * ``PIPE_CAP_PREFER_REAL_BUFFER_IN_CONSTBUF0``: The state tracker is 
encouraged to upload constants into a real buffer and bind it into constant 
buffer 0 instead of binding a user pointer. This may enable a faster codepath 
in a gallium frontend for drivers that really prefer a real buffer.
+* ``PIPE_CAP_GL_CLAMP``: Driver natively supports GL_CLAMP.  Required for 
non-NIR drivers with the GL frontend.  NIR drivers with the cap unavailable 
will have GL_CLAMP lowered to txd/txl with a saturate on the coordinates.
 
 .. _pipe_capf:
 
diff --git a/src/gallium/auxiliary/util/u_screen.c 
b/src/gallium/auxiliary/util/u_screen.c
index 1dc853af6bd..08d28f689e6 100644
--- a/src/gallium/auxiliary/util/u_screen.c
+++ b/src/gallium/auxiliary/util/u_screen.c
@@ -46,6 +46,7 @@ u_pipe_screen_get_param_defaults(struct pipe_screen *pscreen,
       return 0;
 
    case PIPE_CAP_GRAPHICS:
+   case PIPE_CAP_GL_CLAMP:
    case PIPE_CAP_MAX_RENDER_TARGETS:
       return 1;
 
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c 
b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
index 4555b35cb16..c4b66894996 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
@@ -300,6 +300,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum 
pipe_cap param)
    case PIPE_CAP_TEXTURE_SHADOW_LOD:
    case PIPE_CAP_PACKED_STREAM_OUTPUT:
    case PIPE_CAP_CLEAR_SCISSORED:
+   case PIPE_CAP_GL_CLAMP:
       return 1;
    case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
       return nouveau_screen(pscreen)->vram_domain & NOUVEAU_BO_VRAM ? 1 : 0;
diff --git a/src/gallium/include/pipe/p_defines.h 
b/src/gallium/include/pipe/p_defines.h
index db595c73728..3d93fb08233 100644
--- a/src/gallium/include/pipe/p_defines.h
+++ b/src/gallium/include/pipe/p_defines.h
@@ -977,7 +977,7 @@ enum pipe_cap
    PIPE_CAP_SHADER_ATOMIC_INT64,
    PIPE_CAP_DEVICE_PROTECTED_CONTENT,
    PIPE_CAP_PREFER_REAL_BUFFER_IN_CONSTBUF0,
-
+   PIPE_CAP_GL_CLAMP,
    PIPE_CAP_LAST,
    /* XXX do not add caps after PIPE_CAP_LAST! */
 };
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 6e257ad3531..d0581b39c06 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -4879,6 +4879,9 @@ struct gl_driver_flags
 
    /** Programmable sample location state for gl_context::DrawBuffer */
    uint64_t NewSampleLocations;
+
+   /** For GL_CLAMP emulation */
+   uint64_t NewSamplersWithClamp;
 };
 
 struct gl_buffer_binding
diff --git a/src/mesa/main/samplerobj.c b/src/mesa/main/samplerobj.c
index 7ac0700824e..8a17fb6f14b 100644
--- a/src/mesa/main/samplerobj.c
+++ b/src/mesa/main/samplerobj.c
@@ -536,6 +536,12 @@ _mesa_set_sampler_wrap(struct gl_context *ctx, struct 
gl_sampler_object *samp,
 #define INVALID_PNAME 0x101
 #define INVALID_VALUE 0x102
 
+static inline GLboolean
+is_wrap_gl_clamp(GLint param)
+{
+   return param == GL_CLAMP || param == GL_MIRROR_CLAMP_EXT;
+}
+
 static GLuint
 set_sampler_wrap_s(struct gl_context *ctx, struct gl_sampler_object *samp,
                    GLint param)
@@ -544,6 +550,8 @@ set_sampler_wrap_s(struct gl_context *ctx, struct 
gl_sampler_object *samp,
       return GL_FALSE;
    if (validate_texture_wrap_mode(ctx, param)) {
       flush(ctx);
+      if (is_wrap_gl_clamp(samp->Attrib.WrapS) != is_wrap_gl_clamp(param))
+         ctx->NewDriverState |= ctx->DriverFlags.NewSamplersWithClamp;
       samp->Attrib.WrapS = param;
       return GL_TRUE;
    }
@@ -559,6 +567,8 @@ set_sampler_wrap_t(struct gl_context *ctx, struct 
gl_sampler_object *samp,
       return GL_FALSE;
    if (validate_texture_wrap_mode(ctx, param)) {
       flush(ctx);
+      if (is_wrap_gl_clamp(samp->Attrib.WrapT) != is_wrap_gl_clamp(param))
+         ctx->NewDriverState |= ctx->DriverFlags.NewSamplersWithClamp;
       samp->Attrib.WrapT = param;
       return GL_TRUE;
    }
@@ -574,6 +584,8 @@ set_sampler_wrap_r(struct gl_context *ctx, struct 
gl_sampler_object *samp,
       return GL_FALSE;
    if (validate_texture_wrap_mode(ctx, param)) {
       flush(ctx);
+      if (is_wrap_gl_clamp(samp->Attrib.WrapR) != is_wrap_gl_clamp(param))
+         ctx->NewDriverState |= ctx->DriverFlags.NewSamplersWithClamp;
       samp->Attrib.WrapR = param;
       return GL_TRUE;
    }
diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c
index 2f0004458eb..07de903fb3b 100644
--- a/src/mesa/main/texparam.c
+++ b/src/mesa/main/texparam.c
@@ -239,6 +239,12 @@ _mesa_target_allows_setting_sampler_parameters(GLenum 
target)
 }
 
 
+static inline GLboolean
+is_wrap_gl_clamp(GLint param)
+{
+   return param == GL_CLAMP || param == GL_MIRROR_CLAMP_EXT;
+}
+
 /**
  * Set an integer-valued texture parameter
  * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
@@ -317,6 +323,8 @@ set_tex_parameteri(struct gl_context *ctx,
          return GL_FALSE;
       if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
          flush(ctx);
+         if (is_wrap_gl_clamp(texObj->Sampler.Attrib.WrapS) != 
is_wrap_gl_clamp(params[0]))
+            ctx->NewDriverState |= ctx->DriverFlags.NewSamplersWithClamp;
          texObj->Sampler.Attrib.WrapS = params[0];
          return GL_TRUE;
       }
@@ -330,6 +338,8 @@ set_tex_parameteri(struct gl_context *ctx,
          return GL_FALSE;
       if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
          flush(ctx);
+         if (is_wrap_gl_clamp(texObj->Sampler.Attrib.WrapT) != 
is_wrap_gl_clamp(params[0]))
+            ctx->NewDriverState |= ctx->DriverFlags.NewSamplersWithClamp;
          texObj->Sampler.Attrib.WrapT = params[0];
          return GL_TRUE;
       }
@@ -343,6 +353,8 @@ set_tex_parameteri(struct gl_context *ctx,
          return GL_FALSE;
       if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
          flush(ctx);
+         if (is_wrap_gl_clamp(texObj->Sampler.Attrib.WrapR) != 
is_wrap_gl_clamp(params[0]))
+            ctx->NewDriverState |= ctx->DriverFlags.NewSamplersWithClamp;
          texObj->Sampler.Attrib.WrapR = params[0];
          return GL_TRUE;
       }
diff --git a/src/mesa/state_tracker/st_atom_sampler.c 
b/src/mesa/state_tracker/st_atom_sampler.c
index 7416de3dc69..5e9bd37741e 100644
--- a/src/mesa/state_tracker/st_atom_sampler.c
+++ b/src/mesa/state_tracker/st_atom_sampler.c
@@ -98,6 +98,17 @@ gl_filter_to_img_filter(GLenum filter)
    return PIPE_TEX_FILTER_NEAREST;
 }
 
+static inline unsigned
+get_border_clamp(unsigned wrap, bool clamp_to_border)
+{
+   if (wrap == PIPE_TEX_WRAP_CLAMP)
+      wrap = clamp_to_border ? PIPE_TEX_WRAP_CLAMP_TO_BORDER :
+                               PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+   else if (wrap == PIPE_TEX_WRAP_MIRROR_CLAMP)
+      wrap = clamp_to_border ? PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER :
+                               PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE;
+   return wrap;
+}
 
 /**
  * Convert a gl_sampler_object to a pipe_sampler_state object.
@@ -123,6 +134,14 @@ st_convert_sampler(const struct st_context *st,
    }
    sampler->min_mip_filter = gl_filter_to_mip_filter(msamp->Attrib.MinFilter);
 
+   if (st->emulate_gl_clamp) {
+      bool clamp_to_border = sampler->min_img_filter != 
PIPE_TEX_FILTER_NEAREST &&
+                             sampler->mag_img_filter != 
PIPE_TEX_FILTER_NEAREST;
+      sampler->wrap_s = get_border_clamp(sampler->wrap_s, clamp_to_border);
+      sampler->wrap_t = get_border_clamp(sampler->wrap_t, clamp_to_border);
+      sampler->wrap_r = get_border_clamp(sampler->wrap_r, clamp_to_border);
+   }
+
    if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB)
       sampler->normalized_coords = 1;
 
diff --git a/src/mesa/state_tracker/st_atom_shader.c 
b/src/mesa/state_tracker/st_atom_shader.c
index b95ac91eddb..9d8311f5165 100644
--- a/src/mesa/state_tracker/st_atom_shader.c
+++ b/src/mesa/state_tracker/st_atom_shader.c
@@ -73,6 +73,45 @@ get_texture_index(struct gl_context *ctx, const unsigned 
unit)
 }
 
 
+static inline GLboolean
+is_wrap_gl_clamp(GLint param)
+{
+   return param == GL_CLAMP || param == GL_MIRROR_CLAMP_EXT;
+}
+
+static void
+update_gl_clamp(struct st_context *st, struct gl_program *prog, uint32_t 
*gl_clamp)
+{
+   if (!st->emulate_gl_clamp)
+      return;
+
+   gl_clamp[0] = gl_clamp[1] = gl_clamp[2] = 0;
+   GLbitfield samplers_used = prog->SamplersUsed;
+   unsigned unit;
+   /* same as st_atom_sampler.c */
+   for (unit = 0; samplers_used; unit++, samplers_used >>= 1) {
+      unsigned tex_unit = prog->SamplerUnits[unit];
+      if (samplers_used & 1 &&
+          (st->ctx->Texture.Unit[tex_unit]._Current->Target != 
GL_TEXTURE_BUFFER ||
+           st->texture_buffer_sampler)) {
+         const struct gl_texture_object *texobj;
+         struct gl_context *ctx = st->ctx;
+         const struct gl_sampler_object *msamp;
+
+         texobj = ctx->Texture.Unit[tex_unit]._Current;
+         assert(texobj);
+
+         msamp = _mesa_get_samplerobj(ctx, tex_unit);
+         if (is_wrap_gl_clamp(msamp->Attrib.WrapS))
+            gl_clamp[0] |= BITFIELD64_BIT(unit);
+         if (is_wrap_gl_clamp(msamp->Attrib.WrapT))
+            gl_clamp[1] |= BITFIELD64_BIT(unit);
+         if (is_wrap_gl_clamp(msamp->Attrib.WrapR))
+            gl_clamp[2] |= BITFIELD64_BIT(unit);
+      }
+   }
+}
+
 /**
  * Update fragment program state/atom.  This involves translating the
  * Mesa fragment program into a gallium fragment program and binding it.
@@ -143,6 +182,7 @@ st_update_fp( struct st_context *st )
       }
 
       key.external = st_get_external_sampler_key(st, &stfp->Base);
+      update_gl_clamp(st, st->ctx->FragmentProgram._Current, key.gl_clamp);
 
       simple_mtx_lock(&st->ctx->Shared->Mutex);
       shader = st_get_fp_variant(st, stfp, &key)->base.driver_shader;
@@ -218,6 +258,8 @@ st_update_vp( struct st_context *st )
             key.lower_ucp = st->ctx->Transform.ClipPlanesEnabled;
       }
 
+      update_gl_clamp(st, st->ctx->VertexProgram._Current, key.gl_clamp);
+
       simple_mtx_lock(&st->ctx->Shared->Mutex);
       st->vp_variant = st_get_vp_variant(st, stvp, &key);
       simple_mtx_unlock(&st->ctx->Shared->Mutex);
@@ -283,6 +325,8 @@ st_update_common_program(struct st_context *st, struct 
gl_program *prog,
 
    }
 
+   update_gl_clamp(st, prog, key.gl_clamp);
+
    simple_mtx_lock(&st->ctx->Shared->Mutex);
    void *result = st_get_common_variant(st, stp, &key)->driver_shader;
    simple_mtx_unlock(&st->ctx->Shared->Mutex);
diff --git a/src/mesa/state_tracker/st_context.c 
b/src/mesa/state_tracker/st_context.c
index 68a0a193ef2..6268e897f98 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -574,6 +574,12 @@ st_init_driver_flags(struct st_context *st)
    f->NewNvConservativeRasterization = ST_NEW_RASTERIZER;
    f->NewNvConservativeRasterizationParams = ST_NEW_RASTERIZER;
    f->NewIntelConservativeRasterization = ST_NEW_RASTERIZER;
+
+   if (st->emulate_gl_clamp)
+      f->NewSamplersWithClamp = ST_NEW_SAMPLERS |
+                                ST_NEW_VS_STATE | ST_NEW_TCS_STATE |
+                                ST_NEW_TES_STATE | ST_NEW_GS_STATE |
+                                ST_NEW_FS_STATE | ST_NEW_CS_STATE;
 }
 
 
@@ -690,6 +696,8 @@ st_create_context_priv(struct gl_context *ctx, struct 
pipe_context *pipe,
       !!(screen->get_param(screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) &
          (PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 |
           PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600));
+   st->emulate_gl_clamp =
+      !screen->get_param(screen, PIPE_CAP_GL_CLAMP);
    st->texture_buffer_sampler =
       screen->get_param(screen, PIPE_CAP_TEXTURE_BUFFER_SAMPLER);
    st->has_time_elapsed =
diff --git a/src/mesa/state_tracker/st_context.h 
b/src/mesa/state_tracker/st_context.h
index f7b5ef61d02..63657e95c29 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -182,6 +182,7 @@ struct st_context
 
    boolean needs_texcoord_semantic;
    boolean apply_texture_swizzle_to_border_color;
+   boolean emulate_gl_clamp;
    boolean texture_buffer_sampler;
 
    /* On old libGL's for linux we need to invalidate the drawables
diff --git a/src/mesa/state_tracker/st_program.c 
b/src/mesa/state_tracker/st_program.c
index 68918ba833a..ae052247f74 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -783,6 +783,15 @@ st_create_vp_variant(struct st_context *st,
          finalize = true;
       }
 
+      if (st->emulate_gl_clamp &&
+          (key->gl_clamp[0] || key->gl_clamp[1] || key->gl_clamp[2])) {
+         nir_lower_tex_options tex_opts = {0};
+         tex_opts.saturate_s = key->gl_clamp[0];
+         tex_opts.saturate_t = key->gl_clamp[1];
+         tex_opts.saturate_r = key->gl_clamp[2];
+         NIR_PASS_V(state.ir.nir, nir_lower_tex, &tex_opts);
+      }
+
       if (finalize || !st->allow_st_finalize_nir_twice) {
          st_finalize_nir(st, &stvp->Base, stvp->shader_program, state.ir.nir,
                          true, false);
@@ -1310,6 +1319,16 @@ st_create_fp_variant(struct st_context *st,
          finalize = true;
       }
 
+      if (st->emulate_gl_clamp &&
+          (key->gl_clamp[0] || key->gl_clamp[1] || key->gl_clamp[2])) {
+         nir_lower_tex_options tex_opts = {0};
+         tex_opts.saturate_s = key->gl_clamp[0];
+         tex_opts.saturate_t = key->gl_clamp[1];
+         tex_opts.saturate_r = key->gl_clamp[2];
+         NIR_PASS_V(state.ir.nir, nir_lower_tex, &tex_opts);
+         finalize = true;
+      }
+
       assert(!(key->bitmap && key->drawpixels));
 
       /* glBitmap */
diff --git a/src/mesa/state_tracker/st_program.h 
b/src/mesa/state_tracker/st_program.h
index f87339a5472..ad7830c2a0c 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -151,6 +151,9 @@ struct st_fp_variant_key
    uint8_t texture_index[MAX_NUM_FRAGMENT_REGISTERS_ATI];
 
    struct st_external_sampler_key external;
+
+   /* bitmask of sampler units; PIPE_CAP_GL_CLAMP */
+   uint32_t gl_clamp[3];
 };
 
 /**
@@ -209,6 +212,9 @@ struct st_common_variant_key
     * not for the driver.
     */
    bool is_draw_shader;
+
+   /* bitmask of sampler units; PIPE_CAP_GL_CLAMP */
+   uint32_t gl_clamp[3];
 };
 
 

_______________________________________________
mesa-commit mailing list
mesa-commit@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to