}
VkShaderModule
-zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs, nir_shader *base_nir, struct zink_shader_key *key)
+zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs, nir_shader *base_nir, const struct zink_shader_key *key)
{
VkShaderModule mod = VK_NULL_HANDLE;
void *streamout = NULL;
void
zink_compiler_assign_io(nir_shader *producer, nir_shader *consumer);
VkShaderModule
-zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs, nir_shader *nir, struct zink_shader_key *key);
+zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs, nir_shader *nir, const struct zink_shader_key *key);
struct zink_shader *
zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
{
struct zink_context *ctx = (struct zink_context *)pctx;
const uint32_t bit = BITFIELD_BIT(shader);
+ uint32_t *inlinable_uniforms;
+ struct zink_shader_key *key = NULL;
+ if (shader == PIPE_SHADER_COMPUTE) {
+ inlinable_uniforms = ctx->compute_inlinable_uniforms;
+ } else {
+ key = &ctx->gfx_pipeline_state.shader_keys.key[shader];
+ inlinable_uniforms = key->base.inlined_uniform_values;
+ }
if (!(ctx->inlinable_uniforms_valid_mask & bit) ||
- memcmp(ctx->inlinable_uniforms[shader], values, num_values * 4)) {
- memcpy(ctx->inlinable_uniforms[shader], values, num_values * 4);
+ memcmp(inlinable_uniforms, values, num_values * 4)) {
+ memcpy(inlinable_uniforms, values, num_values * 4);
ctx->dirty_shader_stages |= bit;
ctx->inlinable_uniforms_valid_mask |= bit;
+ if (key)
+ key->inline_uniforms = true;
}
}
}
static void
+invalidate_inlined_uniforms(struct zink_context *ctx, enum pipe_shader_type pstage)
+{
+ unsigned bit = BITFIELD_BIT(pstage);
+ if (!(ctx->inlinable_uniforms_valid_mask & bit))
+ return;
+ ctx->inlinable_uniforms_valid_mask &= ~bit;
+ ctx->dirty_shader_stages |= bit;
+ if (pstage == PIPE_SHADER_COMPUTE)
+ return;
+
+ struct zink_shader_key *key = &ctx->gfx_pipeline_state.shader_keys.key[pstage];
+ key->inline_uniforms = false;
+}
+
+static void
zink_set_constant_buffer(struct pipe_context *pctx,
enum pipe_shader_type shader, uint index,
bool take_ownership,
}
if (index == 0) {
/* Invalidate current inlinable uniforms. */
- ctx->inlinable_uniforms_valid_mask &= ~(1 << shader);
+ invalidate_inlined_uniforms(ctx, shader);
}
if (update)
ctx->scissor_changed = true;
rebind_fb_state(ctx, NULL, true);
ctx->fb_state.samples = util_framebuffer_get_num_samples(state);
- uint8_t rast_samples = ctx->fb_state.samples - 1;
/* get_framebuffer adds a ref if the fb is reused or created;
* always do get_framebuffer first to avoid deleting the same fb
* we're about to use
ctx->fb_changed |= ctx->framebuffer != fb;
ctx->framebuffer = fb;
- /* in vulkan, gl_SampleMask needs to be explicitly ignored for sampleCount == 1 */
- if ((ctx->gfx_pipeline_state.rast_samples > 0) != (rast_samples > 0))
- ctx->dirty_shader_stages |= 1 << PIPE_SHADER_FRAGMENT;
+ uint8_t rast_samples = ctx->fb_state.samples - 1;
+ /* update the shader key if applicable:
+ * if gl_SampleMask[] is written to, we have to ensure that we get a shader with the same sample count:
+ * in GL, rast_samples==1 means ignore gl_SampleMask[]
+ * in VK, gl_SampleMask[] is never ignored
+ */
+ if (rast_samples != ctx->gfx_pipeline_state.rast_samples &&
+ (!ctx->gfx_stages[PIPE_SHADER_FRAGMENT] ||
+ ctx->gfx_stages[PIPE_SHADER_FRAGMENT]->nir->info.outputs_written & (1 << FRAG_RESULT_SAMPLE_MASK)))
+ zink_set_fs_key(ctx)->samples = ctx->fb_state.samples > 0;
if (ctx->gfx_pipeline_state.rast_samples != rast_samples) {
ctx->sample_locations_changed |= ctx->gfx_pipeline_state.sample_locations_enabled;
ctx->gfx_pipeline_state.dirty = true;
if (!ctx->blitter)
goto fail;
+ ctx->gfx_pipeline_state.shader_keys.last_vertex.key.vs_base.last_vertex_stage = true;
+ ctx->last_vertex_stage_dirty = true;
+ ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_VERTEX].size = sizeof(struct zink_vs_key_base);
+ ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_TESS_EVAL].size = sizeof(struct zink_vs_key_base);
+ ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_GEOMETRY].size = sizeof(struct zink_vs_key_base);
+ ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_FRAGMENT].size = sizeof(struct zink_fs_key);
_mesa_hash_table_init(&ctx->compute_program_cache, ctx, _mesa_hash_pointer, _mesa_key_pointer_equal);
_mesa_hash_table_init(&ctx->framebuffer_cache, ctx, hash_framebuffer_imageless, equals_framebuffer_imageless);
_mesa_set_init(&ctx->render_pass_state_cache, ctx, hash_rp_state, equals_rp_state);
unsigned shader_has_inlinable_uniforms_mask;
unsigned inlinable_uniforms_valid_mask;
- uint32_t inlinable_uniforms[PIPE_SHADER_TYPES][MAX_INLINABLE_UNIFORMS];
+ uint32_t compute_inlinable_uniforms[MAX_INLINABLE_UNIFORMS];
struct pipe_constant_buffer ubos[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
struct pipe_shader_buffer ssbos[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS];
if (ctx->last_vertex_stage_dirty) {
enum pipe_shader_type pstage = pipe_shader_type_from_mesa(ctx->last_vertex_stage->nir->info.stage);
ctx->dirty_shader_stages |= BITFIELD_BIT(pstage);
+ memcpy(&ctx->gfx_pipeline_state.shader_keys.key[pstage].key.vs_base,
+ &ctx->gfx_pipeline_state.shader_keys.last_vertex.key.vs_base,
+ sizeof(struct zink_vs_key_base));
ctx->last_vertex_stage_dirty = false;
}
unsigned bits = BITFIELD_MASK(PIPE_SHADER_COMPUTE);
uint8_t vertices_per_patch = ctx->gfx_pipeline_state.patch_vertices ? ctx->gfx_pipeline_state.patch_vertices - 1 : 0;
if (ctx->gfx_pipeline_state.vertices_per_patch != vertices_per_patch)
ctx->gfx_pipeline_state.dirty = true;
- bool drawid_broken = ctx->gfx_pipeline_state.drawid_broken;
- ctx->gfx_pipeline_state.drawid_broken = false;
+ bool drawid_broken = false;
if (reads_drawid && (!dindirect || !dindirect->buffer))
- ctx->gfx_pipeline_state.drawid_broken = (drawid_offset != 0 ||
- (!HAS_MULTIDRAW && num_draws > 1) ||
- (HAS_MULTIDRAW && num_draws > 1 && !dinfo->increment_draw_id));
- if (drawid_broken != ctx->gfx_pipeline_state.drawid_broken)
- ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_VERTEX);
+ drawid_broken = (drawid_offset != 0 ||
+ (!HAS_MULTIDRAW && num_draws > 1) ||
+ (HAS_MULTIDRAW && num_draws > 1 && !dinfo->increment_draw_id));
+ if (drawid_broken != zink_get_last_vertex_key(ctx)->push_drawid)
+ zink_set_last_vertex_key(ctx)->push_drawid = drawid_broken;
ctx->gfx_pipeline_state.vertices_per_patch = vertices_per_patch;
if (mode_changed) {
bool points_changed = false;
points_changed = true;
}
if (points_changed && ctx->rast_state->base.point_quad_rasterization)
- ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_FRAGMENT);
+ zink_set_fs_point_coord_key(ctx);
}
ctx->gfx_pipeline_state.gfx_prim_mode = mode;
VKCTX(CmdBeginTransformFeedbackEXT)(batch->state->cmdbuf, 0, ctx->num_so_targets, counter_buffers, counter_buffer_offsets);
}
- bool needs_drawid = reads_drawid && ctx->gfx_pipeline_state.drawid_broken;
+ bool needs_drawid = reads_drawid && zink_get_last_vertex_key(ctx)->push_drawid;
work_count += num_draws;
if (index_size > 0) {
if (dindirect && dindirect->buffer) {
state.width = MAX2(ctx->fb_state.width, 1);
state.height = MAX2(ctx->fb_state.height, 1);
state.layers = MAX2(util_framebuffer_get_num_layers(&ctx->fb_state), 1) - 1;
- state.samples = ctx->gfx_pipeline_state.rast_samples;
+ state.samples = ctx->fb_state.samples - 1;
struct zink_framebuffer *fb;
struct hash_entry *entry = _mesa_hash_table_search(&ctx->framebuffer_cache, &state);
state.width = MAX2(ctx->fb_state.width, 1);
state.height = MAX2(ctx->fb_state.height, 1);
state.layers = MAX2(util_framebuffer_get_num_layers(&ctx->fb_state), 1) - 1;
- state.samples = ctx->gfx_pipeline_state.rast_samples;
+ state.samples = ctx->fb_state.samples - 1;
struct zink_framebuffer *fb;
simple_mtx_lock(&screen->framebuffer_mtx);
#include <vulkan/vulkan.h>
#include "pipe/p_state.h"
+#include "zink_shader_keys.h"
#include "zink_state.h"
struct zink_blend_state;
bool have_EXT_extended_dynamic_state;
bool have_EXT_extended_dynamic_state2;
uint8_t has_points; //either gs outputs points or prim type is points
- uint8_t coord_replace_bits;
- bool coord_replace_yinvert;
- bool drawid_broken;
- uint32_t decomposed_attrs;
- uint32_t decomposed_attrs_without_w;
+ struct {
+ struct zink_shader_key key[5];
+ struct zink_shader_key last_vertex;
+ } shader_keys;
struct zink_blend_state *blend_state;
struct zink_render_pass *render_pass;
VkPipeline pipeline;
/* copied from iris */
struct keybox {
uint16_t size;
- gl_shader_stage stage;
uint8_t data[0];
};
static struct keybox *
-make_keybox(void *mem_ctx, gl_shader_stage stage, const void *key, uint32_t key_size, void *base, uint32_t base_size)
+make_keybox(void *mem_ctx, const void *key, uint32_t key_size, const void *base, uint32_t base_size)
{
struct keybox *keybox =
ralloc_size(mem_ctx, sizeof(struct keybox) + key_size + base_size);
- keybox->stage = stage;
keybox->size = key_size + base_size;
memcpy(keybox->data, key, key_size);
if (base_size)
keybox_hash(const void *void_key)
{
const struct keybox *key = void_key;
- return _mesa_hash_data(&key->stage, key->size + sizeof(key->stage));
+ return _mesa_hash_data(&key->data, key->size);
}
static bool
return memcmp(a->data, b->data, a->size) == 0;
}
-static void
-shader_key_vs_gen(struct zink_screen *screen, struct zink_shader *zs,
- struct zink_shader *shaders[ZINK_SHADER_COUNT], struct zink_shader_key *key,
- const struct zink_gfx_pipeline_state *state)
-{
- struct zink_vs_key_base *vs_key = &key->key.vs_base;
- const struct zink_rasterizer_hw_state *rast_state = (void*)state;
- key->size = sizeof(struct zink_vs_key_base);
-
- vs_key->clip_halfz = rast_state->clip_halfz;
- switch (zs->nir->info.stage) {
- case MESA_SHADER_VERTEX:
- vs_key->last_vertex_stage = !shaders[PIPE_SHADER_TESS_EVAL] && !shaders[PIPE_SHADER_GEOMETRY];
- vs_key->push_drawid = state->drawid_broken;
- break;
- case MESA_SHADER_TESS_EVAL:
- vs_key->last_vertex_stage = !shaders[PIPE_SHADER_GEOMETRY];
- break;
- case MESA_SHADER_GEOMETRY:
- vs_key->last_vertex_stage = true;
- break;
- default:
- unreachable("impossible case");
- }
-}
-
-static void
-shader_key_fs_gen(struct zink_screen *screen, struct zink_shader *zs,
- struct zink_shader *shaders[ZINK_SHADER_COUNT], struct zink_shader_key *key,
- const struct zink_gfx_pipeline_state *state)
-{
- struct zink_fs_key *fs_key = &key->key.fs;
- key->size = sizeof(struct zink_fs_key);
-
- /* if gl_SampleMask[] is written to, we have to ensure that we get a shader with the same sample count:
- * in GL, rast_samples==1 means ignore gl_SampleMask[]
- * in VK, gl_SampleMask[] is never ignored
- */
- if (zs->nir->info.outputs_written & (1 << FRAG_RESULT_SAMPLE_MASK))
- fs_key->samples = state->render_pass->state.samples;
- fs_key->force_dual_color_blend = screen->driconf.dual_color_blend_by_location &&
- state->blend_state &&
- state->blend_state->dual_src_blend &&
- state->blend_state->attachments[1].blendEnable;
- if (state->has_points && state->coord_replace_bits) {
- fs_key->coord_replace_bits = state->coord_replace_bits;
- fs_key->coord_replace_yinvert = state->coord_replace_yinvert;
- }
-}
-
-static void
-shader_key_tcs_gen(struct zink_screen *screen, struct zink_shader *zs,
- struct zink_shader *shaders[ZINK_SHADER_COUNT], struct zink_shader_key *key,
- const struct zink_gfx_pipeline_state *state)
-{
- key->size = 0;
-}
-
-typedef void (*zink_shader_key_gen)(struct zink_screen *screen, struct zink_shader *zs,
- struct zink_shader *shaders[ZINK_SHADER_COUNT],
- struct zink_shader_key *key,
- const struct zink_gfx_pipeline_state *state);
-static zink_shader_key_gen shader_key_vtbl[] =
-{
- [MESA_SHADER_VERTEX] = shader_key_vs_gen,
- [MESA_SHADER_TESS_CTRL] = shader_key_tcs_gen,
- /* reusing vs key for now since we're only using clip_halfz */
- [MESA_SHADER_TESS_EVAL] = shader_key_vs_gen,
- [MESA_SHADER_GEOMETRY] = shader_key_vs_gen,
- [MESA_SHADER_FRAGMENT] = shader_key_fs_gen,
-};
-
/* return pointer to make function reusable */
static inline struct zink_shader_module **
-get_default_shader_module_ptr(struct zink_gfx_program *prog, struct zink_shader *zs, struct zink_shader_key *key)
+get_default_shader_module_ptr(struct zink_gfx_program *prog, struct zink_shader *zs, const struct zink_shader_key *key)
{
if (zs->nir->info.stage == MESA_SHADER_VERTEX ||
zs->nir->info.stage == MESA_SHADER_TESS_EVAL) {
{
gl_shader_stage stage = zs->nir->info.stage;
enum pipe_shader_type pstage = pipe_shader_type_from_mesa(stage);
- struct zink_shader_key key = {0};
VkShaderModule mod;
struct zink_shader_module *zm;
struct zink_shader_module **default_zm = NULL;
struct keybox *keybox;
uint32_t hash;
unsigned base_size = 0;
+ bool is_default_variant;
+ const struct zink_shader_key *key = &state->shader_keys.key[pstage];
- shader_key_vtbl[stage](screen, zs, prog->shaders, &key, state);
- if (ctx && stage == MESA_SHADER_VERTEX) {
- unsigned size = MAX2(ctx->element_state->decomposed_attrs_size, ctx->element_state->decomposed_attrs_without_w_size);
- switch (size) {
- case 1:
- key.key.vs.u8.decomposed_attrs = ctx->element_state->decomposed_attrs;
- key.key.vs.u8.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w;
- break;
- case 2:
- key.key.vs.u16.decomposed_attrs = ctx->element_state->decomposed_attrs;
- key.key.vs.u16.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w;
- break;
- case 4:
- key.key.vs.u32.decomposed_attrs = ctx->element_state->decomposed_attrs;
- key.key.vs.u32.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w;
- break;
- default: break;
- }
- key.key.vs.size = size;
- key.size += 2 * size;
- }
/* this is default variant if there is no default or it matches the default */
if (pstage != PIPE_SHADER_TESS_CTRL && prog->default_variant_key[pstage]) {
const struct keybox *tmp = prog->default_variant_key[pstage];
/* if comparing against the existing default, use the base variant key size since
* we're only checking the stage-specific data
*/
- key.is_default_variant = tmp->size == key.size && !memcmp(tmp->data, &key, key.size);
+ is_default_variant = tmp->size == key->size && !memcmp(tmp->data, &key, key->size);
} else
- key.is_default_variant = true;
+ is_default_variant = true;
if (ctx && zs->nir->info.num_inlinable_uniforms &&
ctx->inlinable_uniforms_valid_mask & BITFIELD64_BIT(pstage)) {
- key.inline_uniforms = true;
- memcpy(key.base.inlined_uniform_values,
- ctx->inlinable_uniforms[pstage],
- zs->nir->info.num_inlinable_uniforms * 4);
base_size = zs->nir->info.num_inlinable_uniforms * sizeof(uint32_t);
- key.is_default_variant = false;
+ is_default_variant = false;
}
- if (key.is_default_variant) {
- default_zm = get_default_shader_module_ptr(prog, zs, &key);
+ if (is_default_variant) {
+ default_zm = get_default_shader_module_ptr(prog, zs, key);
if (*default_zm)
return *default_zm;
}
- keybox = make_keybox(prog, stage, &key, key.size, &key.base, base_size);
+ keybox = make_keybox(prog, key, key->size, &key->base, base_size);
hash = keybox_hash(keybox);
struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(&prog->base.shader_cache[pstage],
hash, keybox);
return NULL;
}
zm->hash = hash;
- mod = zink_shader_compile(screen, zs, prog->nir[stage], &key);
+ mod = zink_shader_compile(screen, zs, prog->nir[stage], key);
if (!mod) {
ralloc_free(keybox);
FREE(zm);
zm->shader = mod;
_mesa_hash_table_insert_pre_hashed(&prog->base.shader_cache[pstage], hash, keybox, zm);
- if (key.is_default_variant) {
+ if (is_default_variant) {
/* previously returned */
*default_zm = zm;
zm->default_variant = true;
}
static void
+bind_last_vertex_stage(struct zink_context *ctx)
+{
+ enum pipe_shader_type old = ctx->last_vertex_stage ? pipe_shader_type_from_mesa(ctx->last_vertex_stage->nir->info.stage) : PIPE_SHADER_TYPES;
+ if (ctx->gfx_stages[PIPE_SHADER_GEOMETRY])
+ ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_GEOMETRY];
+ else if (ctx->gfx_stages[PIPE_SHADER_TESS_EVAL])
+ ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_TESS_EVAL];
+ else
+ ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_VERTEX];
+ enum pipe_shader_type current = ctx->last_vertex_stage ? pipe_shader_type_from_mesa(ctx->last_vertex_stage->nir->info.stage) : PIPE_SHADER_VERTEX;
+ if (old != current) {
+ if (old != PIPE_SHADER_TYPES) {
+ memset(&ctx->gfx_pipeline_state.shader_keys.key[old].key.vs_base, 0, sizeof(struct zink_vs_key_base));
+ ctx->dirty_shader_stages |= BITFIELD_BIT(old);
+ }
+ ctx->last_vertex_stage_dirty = true;
+ }
+}
+
+static void
zink_bind_vs_state(struct pipe_context *pctx,
void *cso)
{
struct zink_context *ctx = zink_context(pctx);
+ if (!cso && !ctx->gfx_stages[PIPE_SHADER_VERTEX])
+ return;
+ void *prev = ctx->gfx_stages[PIPE_SHADER_VERTEX];
bind_stage(ctx, PIPE_SHADER_VERTEX, cso);
- if (!ctx->gfx_stages[PIPE_SHADER_GEOMETRY] &&
- !ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]) {
- ctx->last_vertex_stage = cso;
- }
if (cso) {
struct zink_shader *zs = cso;
ctx->shader_reads_drawid = BITSET_TEST(zs->nir->info.system_values_read, SYSTEM_VALUE_DRAW_ID);
ctx->shader_reads_drawid = false;
ctx->shader_reads_basevertex = false;
}
+ if (ctx->last_vertex_stage == prev)
+ ctx->last_vertex_stage = cso;
+
}
static void
void *cso)
{
struct zink_context *ctx = zink_context(pctx);
+ if (!cso && !ctx->gfx_stages[PIPE_SHADER_FRAGMENT])
+ return;
bind_stage(ctx, PIPE_SHADER_FRAGMENT, cso);
ctx->fbfetch_outputs = 0;
if (cso) {
void *cso)
{
struct zink_context *ctx = zink_context(pctx);
+ if (!cso && !ctx->gfx_stages[PIPE_SHADER_GEOMETRY])
+ return;
bool had_points = ctx->gfx_stages[PIPE_SHADER_GEOMETRY] ? ctx->gfx_stages[PIPE_SHADER_GEOMETRY]->nir->info.gs.output_primitive == GL_POINTS : false;
- if (!!ctx->gfx_stages[PIPE_SHADER_GEOMETRY] != !!cso)
- ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_VERTEX) |
- BITFIELD_BIT(PIPE_SHADER_TESS_EVAL);
bind_stage(ctx, PIPE_SHADER_GEOMETRY, cso);
+ bind_last_vertex_stage(ctx);
if (cso) {
- ctx->last_vertex_stage = cso;
if (!had_points && ctx->last_vertex_stage->nir->info.gs.output_primitive == GL_POINTS)
ctx->gfx_pipeline_state.has_points++;
} else {
- if (ctx->gfx_stages[PIPE_SHADER_TESS_EVAL])
- ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_TESS_EVAL];
- else
- ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_VERTEX];
if (had_points)
ctx->gfx_pipeline_state.has_points--;
}
void *cso)
{
struct zink_context *ctx = zink_context(pctx);
+ if (!cso && !ctx->gfx_stages[PIPE_SHADER_TESS_EVAL])
+ return;
if (!!ctx->gfx_stages[PIPE_SHADER_TESS_EVAL] != !!cso) {
if (!cso) {
/* if unsetting a TESS that uses a generated TCS, ensure the TCS is unset */
if (ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]->generated)
ctx->gfx_stages[PIPE_SHADER_TESS_CTRL] = NULL;
}
- ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_VERTEX);
}
bind_stage(ctx, PIPE_SHADER_TESS_EVAL, cso);
- if (!ctx->gfx_stages[PIPE_SHADER_GEOMETRY]) {
- if (cso)
- ctx->last_vertex_stage = cso;
- else
- ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_VERTEX];
- }
+ bind_last_vertex_stage(ctx);
}
static void *
{
return pg->num_dsl > 0;
}
+
+static inline struct zink_fs_key *
+zink_set_fs_key(struct zink_context *ctx)
+{
+ ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_FRAGMENT);
+ return (struct zink_fs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_FRAGMENT];
+}
+
+static inline const struct zink_fs_key *
+zink_get_fs_key(struct zink_context *ctx)
+{
+ return (const struct zink_fs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_FRAGMENT];
+}
+
+static inline struct zink_vs_key *
+zink_set_vs_key(struct zink_context *ctx)
+{
+ ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_VERTEX);
+ return (struct zink_vs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_VERTEX];
+}
+
+static inline const struct zink_vs_key *
+zink_get_vs_key(struct zink_context *ctx)
+{
+ return (const struct zink_vs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_VERTEX];
+}
+
+static inline struct zink_vs_key_base *
+zink_set_last_vertex_key(struct zink_context *ctx)
+{
+ ctx->last_vertex_stage_dirty = true;
+ return (struct zink_vs_key_base *)&ctx->gfx_pipeline_state.shader_keys.last_vertex;
+}
+
+static inline const struct zink_vs_key_base *
+zink_get_last_vertex_key(struct zink_context *ctx)
+{
+ return (const struct zink_vs_key_base *)&ctx->gfx_pipeline_state.shader_keys.last_vertex;
+}
+
+static inline void
+zink_set_fs_point_coord_key(struct zink_context *ctx)
+{
+ const struct zink_fs_key *fs = zink_get_fs_key(ctx);
+ bool disable = !ctx->gfx_pipeline_state.has_points || !ctx->rast_state->base.sprite_coord_enable;
+ uint8_t coord_replace_bits = disable ? 0 : ctx->rast_state->base.sprite_coord_enable;
+ bool coord_replace_yinvert = disable ? false : !!ctx->rast_state->base.sprite_coord_mode;
+ if (fs->coord_replace_bits != coord_replace_bits || fs->coord_replace_yinvert != coord_replace_yinvert) {
+ zink_set_fs_key(ctx)->coord_replace_bits = coord_replace_bits;
+ zink_set_fs_key(ctx)->coord_replace_yinvert = coord_replace_yinvert;
+ }
+}
+
#ifdef __cplusplus
}
#endif
#ifndef ZINK_SHADER_KEYS_H
# define ZINK_SHADER_KEYS_H
+#include "compiler/shader_info.h"
+
struct zink_vs_key_base {
bool clip_halfz;
bool push_drawid;
struct zink_shader_key_base base;
unsigned inline_uniforms:1;
uint32_t size;
- bool is_default_variant;
};
static inline const struct zink_fs_key *
#include "zink_context.h"
#include "zink_format.h"
+#include "zink_program.h"
#include "zink_screen.h"
#include "compiler/shader_enums.h"
ctx->vertex_state_changed = !zink_screen(pctx->screen)->info.have_EXT_vertex_input_dynamic_state;
ctx->vertex_buffers_dirty = ctx->element_state->hw_state.num_bindings > 0;
}
- if (ctx->element_state->decomposed_attrs != state->decomposed_attrs ||
- ctx->element_state->decomposed_attrs_without_w != state->decomposed_attrs_without_w)
- ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_VERTEX);
- state->decomposed_attrs = ctx->element_state->decomposed_attrs;
- state->decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w;
+ const struct zink_vs_key *vs = zink_get_vs_key(ctx);
+ uint32_t decomposed_attrs = 0, decomposed_attrs_without_w = 0;
+ switch (vs->size) {
+ case 1:
+ decomposed_attrs = vs->u8.decomposed_attrs;
+ decomposed_attrs_without_w = vs->u8.decomposed_attrs_without_w;
+ break;
+ case 2:
+ decomposed_attrs = vs->u16.decomposed_attrs;
+ decomposed_attrs_without_w = vs->u16.decomposed_attrs_without_w;
+ break;
+ case 4:
+ decomposed_attrs = vs->u16.decomposed_attrs;
+ decomposed_attrs_without_w = vs->u16.decomposed_attrs_without_w;
+ break;
+ }
+ if (ctx->element_state->decomposed_attrs != decomposed_attrs ||
+ ctx->element_state->decomposed_attrs_without_w != decomposed_attrs_without_w) {
+ unsigned size = MAX2(ctx->element_state->decomposed_attrs_size, ctx->element_state->decomposed_attrs_without_w_size);
+ struct zink_shader_key *key = (struct zink_shader_key *)zink_set_vs_key(ctx);
+ key->size -= 2 * key->key.vs.size;
+ switch (size) {
+ case 1:
+ key->key.vs.u8.decomposed_attrs = ctx->element_state->decomposed_attrs;
+ key->key.vs.u8.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w;
+ break;
+ case 2:
+ key->key.vs.u16.decomposed_attrs = ctx->element_state->decomposed_attrs;
+ key->key.vs.u16.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w;
+ break;
+ case 4:
+ key->key.vs.u32.decomposed_attrs = ctx->element_state->decomposed_attrs;
+ key->key.vs.u32.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w;
+ break;
+ default: break;
+ }
+ key->key.vs.size = size;
+ key->size += 2 * size;
+ }
state->element_state = &ctx->element_state->hw_state;
} else {
state->element_state = NULL;
state->blend_state = cso;
state->blend_id = blend ? blend->hash : 0;
state->dirty = true;
+ bool force_dual_color_blend = zink_screen(pctx->screen)->driconf.dual_color_blend_by_location &&
+ blend && blend->dual_src_blend && state->blend_state->attachments[1].blendEnable;
+ if (force_dual_color_blend != zink_get_fs_key(ctx)->force_dual_color_blend)
+ zink_set_fs_key(ctx)->force_dual_color_blend = force_dual_color_blend;
ctx->blend_state_changed = true;
}
}
{
struct zink_context *ctx = zink_context(pctx);
struct zink_screen *screen = zink_screen(pctx->screen);
- bool clip_halfz = ctx->rast_state ? ctx->rast_state->base.clip_halfz : false;
bool point_quad_rasterization = ctx->rast_state ? ctx->rast_state->base.point_quad_rasterization : false;
bool scissor = ctx->rast_state ? ctx->rast_state->base.scissor : false;
bool pv_last = ctx->rast_state ? ctx->rast_state->hw_state.pv_last : false;
ctx->gfx_pipeline_state.dirty = true;
ctx->rast_state_changed = true;
- if (clip_halfz != ctx->rast_state->base.clip_halfz) {
- ctx->last_vertex_stage_dirty = true;
+ if (zink_get_last_vertex_key(ctx)->clip_halfz != ctx->rast_state->base.clip_halfz) {
+ zink_set_last_vertex_key(ctx)->clip_halfz = ctx->rast_state->base.clip_halfz;
ctx->vp_state_changed = true;
}
ctx->gfx_pipeline_state.dyn_state1.front_face = ctx->rast_state->front_face;
ctx->gfx_pipeline_state.dirty |= !zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state;
}
- if (ctx->rast_state->base.point_quad_rasterization != point_quad_rasterization) {
- ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_FRAGMENT);
- ctx->gfx_pipeline_state.coord_replace_bits = ctx->rast_state->base.sprite_coord_enable;
- ctx->gfx_pipeline_state.coord_replace_yinvert = !!ctx->rast_state->base.sprite_coord_mode;
- }
+ if (ctx->rast_state->base.point_quad_rasterization != point_quad_rasterization)
+ zink_set_fs_point_coord_key(ctx);
if (ctx->rast_state->base.scissor != scissor)
ctx->scissor_changed = true;
}