mesa/st: add PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_FREEDRENO

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>
This commit is contained in:
Mike Blumenkrantz 2022-06-22 09:14:51 -04:00 committed by Marge Bot
parent ad0ee7ad42
commit c4e18cd4dd
8 changed files with 57 additions and 19 deletions

View 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);

View 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();
}

View 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 */

View 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
{

View 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 {

View 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;
}

View 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 =

View 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;