zink: move shader keys to be persistent on pipeline state

save a cycle or two zeroing and populating this on every recalc

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12842>
This commit is contained in:
Mike Blumenkrantz
2021-09-01 15:44:34 -04:00
parent 80604fee4a
commit 19fbdb9064
11 changed files with 215 additions and 170 deletions

View File

@@ -782,7 +782,7 @@ zink_compiler_assign_io(nir_shader *producer, nir_shader *consumer)
}
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;

View File

@@ -99,7 +99,7 @@ zink_screen_init_compiler(struct zink_screen *screen);
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,

View File

@@ -1000,12 +1000,22 @@ zink_set_inlinable_constants(struct pipe_context *pctx,
{
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;
}
}
@@ -1019,6 +1029,21 @@ unbind_ubo(struct zink_context *ctx, struct zink_resource *res, enum pipe_shader
update_res_bind_count(ctx, res, pstage == PIPE_SHADER_COMPUTE, 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,
@@ -1086,7 +1111,7 @@ zink_set_constant_buffer(struct pipe_context *pctx,
}
if (index == 0) {
/* Invalidate current inlinable uniforms. */
ctx->inlinable_uniforms_valid_mask &= ~(1 << shader);
invalidate_inlined_uniforms(ctx, shader);
}
if (update)
@@ -2066,7 +2091,6 @@ zink_set_framebuffer_state(struct pipe_context *pctx,
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
@@ -2095,9 +2119,16 @@ zink_set_framebuffer_state(struct pipe_context *pctx,
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;
@@ -3646,6 +3677,12 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
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);

View File

@@ -193,7 +193,7 @@ struct zink_context {
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];

View File

@@ -179,6 +179,9 @@ update_gfx_program(struct zink_context *ctx)
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);
@@ -489,14 +492,13 @@ zink_draw_vbo(struct pipe_context *pctx,
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;
@@ -508,7 +510,7 @@ zink_draw_vbo(struct pipe_context *pctx,
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;
@@ -762,7 +764,7 @@ zink_draw_vbo(struct pipe_context *pctx,
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) {

View File

@@ -160,7 +160,7 @@ zink_get_framebuffer_imageless(struct zink_context *ctx)
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);
@@ -289,7 +289,7 @@ zink_get_framebuffer(struct zink_context *ctx)
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);

View File

@@ -27,6 +27,7 @@
#include <vulkan/vulkan.h>
#include "pipe/p_state.h"
#include "zink_shader_keys.h"
#include "zink_state.h"
struct zink_blend_state;
@@ -75,11 +76,10 @@ struct zink_gfx_pipeline_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;

View File

@@ -69,17 +69,15 @@ debug_describe_zink_compute_program(char *buf, const struct zink_compute_program
/* 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)
@@ -91,7 +89,7 @@ static uint32_t
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
@@ -104,81 +102,9 @@ keybox_equals(const void *void_a, const void *void_b)
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) {
@@ -196,60 +122,36 @@ get_shader_module_for_stage(struct zink_context *ctx, struct zink_screen *screen
{
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);
@@ -264,7 +166,7 @@ get_shader_module_for_stage(struct zink_context *ctx, struct zink_screen *screen
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);
@@ -273,7 +175,7 @@ get_shader_module_for_stage(struct zink_context *ctx, struct zink_screen *screen
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;
@@ -954,16 +856,35 @@ bind_stage(struct zink_context *ctx, enum pipe_shader_type stage,
}
}
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);
@@ -972,6 +893,9 @@ zink_bind_vs_state(struct pipe_context *pctx,
ctx->shader_reads_drawid = false;
ctx->shader_reads_basevertex = false;
}
if (ctx->last_vertex_stage == prev)
ctx->last_vertex_stage = cso;
}
static void
@@ -979,6 +903,8 @@ zink_bind_fs_state(struct pipe_context *pctx,
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) {
@@ -998,20 +924,15 @@ zink_bind_gs_state(struct pipe_context *pctx,
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--;
}
@@ -1029,21 +950,17 @@ zink_bind_tes_state(struct pipe_context *pctx,
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 *

View File

@@ -278,6 +278,59 @@ zink_program_has_descriptors(const struct zink_program *pg)
{
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

View File

@@ -26,6 +26,8 @@
#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;
@@ -79,7 +81,6 @@ struct zink_shader_key {
struct zink_shader_key_base base;
unsigned inline_uniforms:1;
uint32_t size;
bool is_default_variant;
};
static inline const struct zink_fs_key *

View File

@@ -25,6 +25,7 @@
#include "zink_context.h"
#include "zink_format.h"
#include "zink_program.h"
#include "zink_screen.h"
#include "compiler/shader_enums.h"
@@ -178,11 +179,45 @@ zink_bind_vertex_elements_state(struct pipe_context *pctx,
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;
@@ -380,6 +415,10 @@ zink_bind_blend_state(struct pipe_context *pctx, void *cso)
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;
}
}
@@ -635,7 +674,6 @@ zink_bind_rasterizer_state(struct pipe_context *pctx, void *cso)
{
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;
@@ -654,8 +692,8 @@ zink_bind_rasterizer_state(struct pipe_context *pctx, void *cso)
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;
}
@@ -663,11 +701,8 @@ zink_bind_rasterizer_state(struct pipe_context *pctx, void *cso)
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;
}