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];
/* 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 {
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);
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) {
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 =
/* 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)
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)
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,
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)
{
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;
unsigned min_samples;
struct panfrost_blend_state *blit_blend;
+ struct hash_table *blend_shaders;
};
/* Corresponds to the CSO */