mesa/st: add PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_FREEDRENO
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>
Wed, 22 Jun 2022 13:14:51 +0000 (09:14 -0400)
committerMarge Bot <emma+marge@anholt.net>
Thu, 7 Jul 2022 20:39:30 +0000 (20:39 +0000)
this is for drivers (like freedreno) which need the format in the sampler
state in order to accurately handle border colors

when set, drivers MAY receive a format in the sampler state if the frontend
supports it (e.g., nine does not), and the cso sampler cache will include
the format member of the struct

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17189>

src/gallium/auxiliary/cso_cache/cso_context.c
src/gallium/auxiliary/driver_trace/tr_dump_state.c
src/gallium/frontends/nine/nine_pipe.c
src/gallium/include/pipe/p_defines.h
src/gallium/include/pipe/p_state.h
src/mesa/state_tracker/st_atom_sampler.c
src/mesa/state_tracker/st_context.c
src/mesa/state_tracker/st_context.h

index 111de3f..2684c75 100644 (file)
@@ -68,6 +68,7 @@ struct cso_context {
    struct u_vbuf *vbuf;
    struct u_vbuf *vbuf_current;
    bool always_use_vbuf;
+   bool sampler_format;
 
    boolean has_geometry_shader;
    boolean has_tessellation;
@@ -285,6 +286,10 @@ cso_create_context(struct pipe_context *pipe, unsigned flags)
       ctx->has_streamout = TRUE;
    }
 
+   if (pipe->screen->get_param(pipe->screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) &
+       PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_FREEDRENO)
+      ctx->sampler_format = true;
+
    ctx->max_fs_samplerviews = pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_FRAGMENT,
                                                              PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS);
 
@@ -1208,11 +1213,10 @@ cso_set_vertex_buffers_and_elements(struct cso_context *ctx,
    cso_set_vertex_elements_direct(ctx, velems);
 }
 
-static bool
-cso_set_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage,
-                unsigned idx, const struct pipe_sampler_state *templ)
+ALWAYS_INLINE static struct cso_sampler *
+set_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage,
+            unsigned idx, const struct pipe_sampler_state *templ, size_t key_size)
 {
-   unsigned key_size = sizeof(struct pipe_sampler_state);
    unsigned hash_key = cso_construct_key((void*)templ, key_size);
    struct cso_sampler *cso;
    struct cso_hash_iter iter =
@@ -1237,7 +1241,14 @@ cso_set_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage,
    } else {
       cso = cso_hash_iter_data(iter);
    }
+   return cso;
+}
 
+ALWAYS_INLINE  static bool
+cso_set_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage,
+                unsigned idx, const struct pipe_sampler_state *templ, size_t size)
+{
+   struct cso_sampler *cso = set_sampler(ctx, shader_stage, idx, templ, size);
    ctx->samplers[shader_stage].cso_samplers[idx] = cso;
    ctx->samplers[shader_stage].samplers[idx] = cso->data;
    return true;
@@ -1247,7 +1258,9 @@ void
 cso_single_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage,
                    unsigned idx, const struct pipe_sampler_state *templ)
 {
-   if (cso_set_sampler(ctx, shader_stage, idx, templ))
+   size_t size = ctx->sampler_format ? sizeof(struct pipe_sampler_state) :
+                                       offsetof(struct pipe_sampler_state, border_color_format);
+   if (cso_set_sampler(ctx, shader_stage, idx, templ, size))
       ctx->max_sampler_seen = MAX2(ctx->max_sampler_seen, (int)idx);
 }
 
@@ -1269,20 +1282,14 @@ cso_single_sampler_done(struct cso_context *ctx,
    ctx->max_sampler_seen = -1;
 }
 
-
-/*
- * If the function encouters any errors it will return the
- * last one. Done to always try to set as many samplers
- * as possible.
- */
-void
-cso_set_samplers(struct cso_context *ctx,
-                 enum pipe_shader_type shader_stage,
-                 unsigned nr,
-                 const struct pipe_sampler_state **templates)
+ALWAYS_INLINE static int
+set_samplers(struct cso_context *ctx,
+             enum pipe_shader_type shader_stage,
+             unsigned nr,
+             const struct pipe_sampler_state **templates,
+             size_t key_size)
 {
    int last = -1;
-
    for (unsigned i = 0; i < nr; i++) {
       if (!templates[i])
          continue;
@@ -1302,18 +1309,38 @@ cso_set_samplers(struct cso_context *ctx,
        */
       if (last >= 0 &&
           !memcmp(templates[i], templates[last],
-                  sizeof(struct pipe_sampler_state))) {
+                  key_size)) {
          ctx->samplers[shader_stage].cso_samplers[i] =
             ctx->samplers[shader_stage].cso_samplers[last];
          ctx->samplers[shader_stage].samplers[i] =
             ctx->samplers[shader_stage].samplers[last];
       } else {
          /* Look up the sampler state CSO. */
-         cso_set_sampler(ctx, shader_stage, i, templates[i]);
+         cso_set_sampler(ctx, shader_stage, i, templates[i], key_size);
       }
 
       last = i;
    }
+   return last;
+}
+
+/*
+ * If the function encouters any errors it will return the
+ * last one. Done to always try to set as many samplers
+ * as possible.
+ */
+void
+cso_set_samplers(struct cso_context *ctx,
+                 enum pipe_shader_type shader_stage,
+                 unsigned nr,
+                 const struct pipe_sampler_state **templates)
+{
+   int last = -1;
+
+   /* ensure sampler size is a constant for memcmp */
+   size_t size = ctx->sampler_format ? sizeof(struct pipe_sampler_state) :
+                                       offsetof(struct pipe_sampler_state, border_color_format);
+   last = set_samplers(ctx, shader_stage, nr, templates, size);
 
    ctx->max_sampler_seen = MAX2(ctx->max_sampler_seen, last);
    cso_single_sampler_done(ctx, shader_stage);
index 6933f98..45a02a0 100644 (file)
@@ -549,6 +549,7 @@ void trace_dump_sampler_state(const struct pipe_sampler_state *state)
    trace_dump_member(float, state, min_lod);
    trace_dump_member(float, state, max_lod);
    trace_dump_member_array(float, state, border_color.f);
+   trace_dump_member(format, state, border_color_format);
 
    trace_dump_struct_end();
 }
index eaa9110..d35211a 100644 (file)
@@ -251,6 +251,7 @@ nine_convert_sampler_state(struct cso_context *ctx, int idx, const DWORD *ss)
     samp.border_color_is_integer = 0;
     samp.reduction_mode = 0;
     samp.pad = 0;
+    samp.border_color_format = PIPE_FORMAT_NONE;
     d3dcolor_to_pipe_color_union(&samp.border_color, ss[D3DSAMP_BORDERCOLOR]);
 
     /* see nine_state.h */
index e576939..3a10ee0 100644 (file)
@@ -1036,6 +1036,7 @@ enum pipe_texture_transfer_mode {
 
 #define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 (1 << 0)
 #define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600 (1 << 1)
+#define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_FREEDRENO (1 << 2)
 
 enum pipe_endian
 {
index 4661380..282a57a 100644 (file)
@@ -426,6 +426,7 @@ struct pipe_sampler_state
    float lod_bias;               /**< LOD/lambda bias */
    float min_lod, max_lod;       /**< LOD clamp range, after bias */
    union pipe_color_union border_color;
+   enum pipe_format border_color_format;      /**< only with PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_FREEDRENO, must be last */
 };
 
 union pipe_surface_desc {
index 7aaaa22..bf6122c 100644 (file)
@@ -128,6 +128,9 @@ st_convert_sampler(const struct st_context *st,
       } else {
          st_translate_color(&sampler->border_color,
                             texBaseFormat, is_integer);
+         if (st->use_format_with_border_color)
+            sampler->border_color_format = st_get_sampler_view_format(st, texobj,
+                                                                      msamp->Attrib.sRGBDecode == GL_SKIP_DECODE_EXT);
       }
       sampler->border_color_is_integer = is_integer;
    }
index b9c69e5..d3fc977 100644 (file)
@@ -595,6 +595,9 @@ 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->use_format_with_border_color =
+      !!(screen->get_param(screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) &
+         PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_FREEDRENO);
    st->emulate_gl_clamp =
       !screen->get_param(screen, PIPE_CAP_GL_CLAMP);
    st->texture_buffer_sampler =
index 2f1f2f8..e90c170 100644 (file)
@@ -185,6 +185,7 @@ struct st_context
 
    boolean needs_texcoord_semantic;
    boolean apply_texture_swizzle_to_border_color;
+   boolean use_format_with_border_color;
    boolean emulate_gl_clamp;
    boolean texture_buffer_sampler;