panfrost: Move the blend shader cache at the context level
Blend shaders can be shared among blend states, so let's move the blend shader one level up so we don't have to re-create/re-compile shaders when another blend state already asked for it. Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7066>
This commit is contained in:

committed by
Marge Bot

parent
a5005c349d
commit
fd4d0b447c
@@ -33,19 +33,31 @@
|
||||
|
||||
struct panfrost_bo;
|
||||
|
||||
struct panfrost_blend_shader_key {
|
||||
/* RT format */
|
||||
enum pipe_format format;
|
||||
|
||||
/* Render target */
|
||||
unsigned rt : 3;
|
||||
|
||||
/* Blend shader uses blend constants */
|
||||
unsigned has_constants : 1;
|
||||
|
||||
/* Logic Op info */
|
||||
unsigned logicop_enable : 1;
|
||||
unsigned logicop_func:4;
|
||||
|
||||
struct pipe_rt_blend_state equation;
|
||||
};
|
||||
|
||||
/* An internal blend shader descriptor, from the compiler */
|
||||
|
||||
struct panfrost_blend_shader {
|
||||
struct panfrost_blend_shader_key key;
|
||||
struct panfrost_context *ctx;
|
||||
|
||||
nir_shader *nir;
|
||||
|
||||
/* Render target */
|
||||
unsigned rt;
|
||||
|
||||
/* RT format */
|
||||
enum pipe_format format;
|
||||
|
||||
/* Blend constants */
|
||||
float constants[4];
|
||||
|
||||
@@ -92,11 +104,6 @@ struct panfrost_blend_rt {
|
||||
|
||||
/* Properties of the blend mode */
|
||||
bool opaque, load_dest, no_colour;
|
||||
|
||||
/* Regardless of fixed-function blending, this is a map of pipe_format
|
||||
* to panfrost_blend_shader */
|
||||
|
||||
struct hash_table_u64 *shaders;
|
||||
};
|
||||
|
||||
struct panfrost_blend_state {
|
||||
|
@@ -77,16 +77,30 @@ panfrost_get_blend_shader(struct panfrost_context *ctx,
|
||||
assert(fmt != 0);
|
||||
|
||||
/* Check the cache. Key by the RT and format */
|
||||
struct hash_table_u64 *shaders = blend->rt[rt].shaders;
|
||||
unsigned key = (fmt << 4) | ((constants != NULL) << 3) | rt;
|
||||
struct hash_table *shaders = ctx->blend_shaders;
|
||||
struct panfrost_blend_shader_key key = {
|
||||
.rt = rt,
|
||||
.format = fmt,
|
||||
.has_constants = constants != NULL,
|
||||
.logicop_enable = blend->base.logicop_enable,
|
||||
};
|
||||
|
||||
struct panfrost_blend_shader *shader =
|
||||
_mesa_hash_table_u64_search(shaders, key);
|
||||
if (blend->base.logicop_enable) {
|
||||
key.logicop_func = blend->base.logicop_func;
|
||||
} else {
|
||||
unsigned idx = blend->base.independent_blend_enable ? rt : 0;
|
||||
|
||||
if (blend->base.rt[idx].blend_enable)
|
||||
key.equation = blend->base.rt[idx];
|
||||
}
|
||||
|
||||
struct hash_entry *he = _mesa_hash_table_search(shaders, &key);
|
||||
struct panfrost_blend_shader *shader = he ? he->data : NULL;
|
||||
|
||||
if (!shader) {
|
||||
/* Cache miss. Build one instead, cache it, and go */
|
||||
shader = panfrost_create_blend_shader(ctx, blend, fmt, rt);
|
||||
_mesa_hash_table_u64_insert(shaders, key, shader);
|
||||
shader = panfrost_create_blend_shader(ctx, blend, &key);
|
||||
_mesa_hash_table_insert(shaders, &shader->key, shader);
|
||||
}
|
||||
|
||||
panfrost_compile_blend_shader(shader, constants);
|
||||
@@ -114,7 +128,6 @@ panfrost_create_blend_state(struct pipe_context *pipe,
|
||||
struct pipe_rt_blend_state pipe = blend->rt[g];
|
||||
|
||||
struct panfrost_blend_rt *rt = &so->rt[c];
|
||||
rt->shaders = _mesa_hash_table_u64_create(so);
|
||||
|
||||
/* Logic ops are always shader */
|
||||
if (blend->logicop_enable) {
|
||||
|
@@ -132,23 +132,21 @@ nir_iclamp(nir_builder *b, nir_ssa_def *v, int32_t lo, int32_t hi)
|
||||
struct panfrost_blend_shader *
|
||||
panfrost_create_blend_shader(struct panfrost_context *ctx,
|
||||
struct panfrost_blend_state *state,
|
||||
enum pipe_format format,
|
||||
unsigned rt)
|
||||
const struct panfrost_blend_shader_key *key)
|
||||
{
|
||||
struct panfrost_blend_shader *res = rzalloc(state, struct panfrost_blend_shader);
|
||||
struct panfrost_blend_shader *res = rzalloc(ctx, struct panfrost_blend_shader);
|
||||
|
||||
res->ctx = ctx;
|
||||
res->rt = rt;
|
||||
res->format = format;
|
||||
res->key = *key;
|
||||
|
||||
/* Build the shader */
|
||||
|
||||
nir_shader *shader = nir_shader_create(state, MESA_SHADER_FRAGMENT, &midgard_nir_options, NULL);
|
||||
nir_shader *shader = nir_shader_create(ctx, MESA_SHADER_FRAGMENT, &midgard_nir_options, NULL);
|
||||
nir_function *fn = nir_function_create(shader, "main");
|
||||
nir_function_impl *impl = nir_function_impl_create(fn);
|
||||
|
||||
const struct util_format_description *format_desc =
|
||||
util_format_description(format);
|
||||
util_format_description(key->format);
|
||||
|
||||
nir_alu_type T = pan_unpacked_type_for_format(format_desc);
|
||||
enum glsl_base_type g =
|
||||
@@ -201,8 +199,8 @@ panfrost_create_blend_shader(struct panfrost_context *ctx,
|
||||
/* Build a trivial blend shader */
|
||||
nir_store_var(b, c_out, s_src[0], 0xFF);
|
||||
|
||||
nir_lower_blend_options options = nir_make_options(&state->base, rt);
|
||||
options.format = format;
|
||||
nir_lower_blend_options options = nir_make_options(&state->base, key->rt);
|
||||
options.format = key->format;
|
||||
options.src1 = s_src[1];
|
||||
|
||||
if (T == nir_type_float16)
|
||||
@@ -235,8 +233,8 @@ panfrost_compile_blend_shader(struct panfrost_blend_shader *shader,
|
||||
struct panfrost_compile_inputs inputs = {
|
||||
.gpu_id = dev->gpu_id,
|
||||
.is_blend = true,
|
||||
.blend.rt = shader->rt,
|
||||
.rt_formats = {shader->format},
|
||||
.blend.rt = shader->key.rt,
|
||||
.rt_formats = {shader->key.format},
|
||||
};
|
||||
|
||||
if (constants)
|
||||
|
@@ -34,8 +34,7 @@
|
||||
struct panfrost_blend_shader *
|
||||
panfrost_create_blend_shader(struct panfrost_context *ctx,
|
||||
struct panfrost_blend_state *state,
|
||||
enum pipe_format format,
|
||||
unsigned rt);
|
||||
const struct panfrost_blend_shader_key *key);
|
||||
|
||||
void
|
||||
panfrost_compile_blend_shader(struct panfrost_blend_shader *shader,
|
||||
|
@@ -1504,6 +1504,16 @@ panfrost_set_stream_output_targets(struct pipe_context *pctx,
|
||||
so->num_targets = num_targets;
|
||||
}
|
||||
|
||||
static uint32_t panfrost_shader_key_hash(const void *key)
|
||||
{
|
||||
return _mesa_hash_data(key, sizeof(struct panfrost_blend_shader_key));
|
||||
}
|
||||
|
||||
static bool panfrost_shader_key_equal(const void *a, const void *b)
|
||||
{
|
||||
return !memcmp(a, b, sizeof(struct panfrost_blend_shader_key));
|
||||
}
|
||||
|
||||
struct pipe_context *
|
||||
panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags)
|
||||
{
|
||||
@@ -1607,11 +1617,11 @@ panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags)
|
||||
|
||||
panfrost_batch_init(ctx);
|
||||
|
||||
if (!(dev->quirks & IS_BIFROST)) {
|
||||
ctx->blit_blend = rzalloc(ctx, struct panfrost_blend_state);
|
||||
for (unsigned c = 0; c < PIPE_MAX_COLOR_BUFS; ++c)
|
||||
ctx->blit_blend->rt[c].shaders = _mesa_hash_table_u64_create(ctx);
|
||||
}
|
||||
ctx->blit_blend = rzalloc(ctx, struct panfrost_blend_state);
|
||||
ctx->blend_shaders =
|
||||
_mesa_hash_table_create(ctx,
|
||||
panfrost_shader_key_hash,
|
||||
panfrost_shader_key_equal);
|
||||
|
||||
/* By default mask everything on */
|
||||
ctx->sample_mask = ~0;
|
||||
|
@@ -179,6 +179,7 @@ struct panfrost_context {
|
||||
unsigned min_samples;
|
||||
|
||||
struct panfrost_blend_state *blit_blend;
|
||||
struct hash_table *blend_shaders;
|
||||
};
|
||||
|
||||
/* Corresponds to the CSO */
|
||||
|
Reference in New Issue
Block a user