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:
@@ -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;
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
@@ -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];
|
||||
|
@@ -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) {
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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 *
|
||||
|
@@ -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
|
||||
|
@@ -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 *
|
||||
|
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user