summaryrefslogtreecommitdiff
path: root/lib/mesa/src/gallium/drivers/zink/zink_compiler.c
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2022-02-24 01:57:18 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2022-02-24 01:57:18 +0000
commitb24b5b9049e889ee4eb39b565bcc8d48bd45ab48 (patch)
tree658ca4e6b41655f49463c85edbaeda48979c394c /lib/mesa/src/gallium/drivers/zink/zink_compiler.c
parent57768bbb154c2879d34ec20e401b19472e77aaf7 (diff)
Import Mesa 21.3.7
Diffstat (limited to 'lib/mesa/src/gallium/drivers/zink/zink_compiler.c')
-rw-r--r--lib/mesa/src/gallium/drivers/zink/zink_compiler.c895
1 files changed, 716 insertions, 179 deletions
diff --git a/lib/mesa/src/gallium/drivers/zink/zink_compiler.c b/lib/mesa/src/gallium/drivers/zink/zink_compiler.c
index c91d97dc7..d34c7a47a 100644
--- a/lib/mesa/src/gallium/drivers/zink/zink_compiler.c
+++ b/lib/mesa/src/gallium/drivers/zink/zink_compiler.c
@@ -76,8 +76,13 @@ reads_work_dim(nir_shader *shader)
}
static bool
-lower_discard_if_instr(nir_intrinsic_instr *instr, nir_builder *b)
+lower_discard_if_instr(nir_builder *b, nir_instr *instr_, UNUSED void *cb_data)
{
+ if (instr_->type != nir_instr_type_intrinsic)
+ return false;
+
+ nir_intrinsic_instr *instr = nir_instr_as_intrinsic(instr_);
+
if (instr->intrinsic == nir_intrinsic_discard_if) {
b->cursor = nir_before_instr(&instr->instr);
@@ -137,26 +142,10 @@ lower_discard_if_instr(nir_intrinsic_instr *instr, nir_builder *b)
static bool
lower_discard_if(nir_shader *shader)
{
- bool progress = false;
-
- nir_foreach_function(function, shader) {
- if (function->impl) {
- nir_builder builder;
- nir_builder_init(&builder, function->impl);
- nir_foreach_block(block, function->impl) {
- nir_foreach_instr_safe(instr, block) {
- if (instr->type == nir_instr_type_intrinsic)
- progress |= lower_discard_if_instr(
- nir_instr_as_intrinsic(instr),
- &builder);
- }
- }
-
- nir_metadata_preserve(function->impl, nir_metadata_dominance);
- }
- }
-
- return progress;
+ return nir_shader_instructions_pass(shader,
+ lower_discard_if_instr,
+ nir_metadata_dominance,
+ NULL);
}
static bool
@@ -379,17 +368,23 @@ zink_screen_init_compiler(struct zink_screen *screen)
.lower_fsat = true,
.lower_extract_byte = true,
.lower_extract_word = true,
+ .lower_insert_byte = true,
+ .lower_insert_word = true,
.lower_mul_high = true,
.lower_rotate = true,
.lower_uadd_carry = true,
.lower_pack_64_2x32_split = true,
.lower_unpack_64_2x32_split = true,
+ .lower_pack_32_2x16_split = true,
+ .lower_unpack_32_2x16_split = true,
.lower_vector_cmp = true,
.lower_int64_options = 0,
.lower_doubles_options = ~nir_lower_fp64_full_software,
+ .lower_uniforms_to_ubo = true,
.has_fsub = true,
.has_isub = true,
.lower_mul_2x32_64 = true,
+ .support_16bit_alu = true, /* not quite what it sounds like */
};
screen->nir_options = default_options;
@@ -443,6 +438,66 @@ optimize_nir(struct nir_shader *s)
NIR_PASS(progress, s, nir_opt_undef);
NIR_PASS(progress, s, zink_nir_lower_b2b);
} while (progress);
+
+ do {
+ progress = false;
+ NIR_PASS(progress, s, nir_opt_algebraic_late);
+ if (progress) {
+ NIR_PASS_V(s, nir_copy_prop);
+ NIR_PASS_V(s, nir_opt_dce);
+ NIR_PASS_V(s, nir_opt_cse);
+ }
+ } while (progress);
+}
+
+/* - copy the lowered fbfetch variable
+ * - set the new one up as an input attachment for descriptor 0.6
+ * - load it as an image
+ * - overwrite the previous load
+ */
+static bool
+lower_fbfetch_instr(nir_builder *b, nir_instr *instr, void *data)
+{
+ if (instr->type != nir_instr_type_intrinsic)
+ return false;
+ nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
+ if (intr->intrinsic != nir_intrinsic_load_deref)
+ return false;
+ nir_variable *var = nir_deref_instr_get_variable(nir_src_as_deref(intr->src[0]));
+ if (var != data)
+ return false;
+ b->cursor = nir_after_instr(instr);
+ nir_variable *fbfetch = nir_variable_clone(data, b->shader);
+ /* If Dim is SubpassData, ... Image Format must be Unknown
+ * - SPIRV OpTypeImage specification
+ */
+ fbfetch->data.image.format = 0;
+ fbfetch->data.index = 0; /* fix this if more than 1 fbfetch target is supported */
+ fbfetch->data.mode = nir_var_uniform;
+ fbfetch->data.binding = ZINK_FBFETCH_BINDING;
+ fbfetch->type = glsl_image_type(GLSL_SAMPLER_DIM_SUBPASS, false, GLSL_TYPE_FLOAT);
+ nir_shader_add_variable(b->shader, fbfetch);
+ nir_ssa_def *deref = &nir_build_deref_var(b, fbfetch)->dest.ssa;
+ nir_ssa_def *load = nir_image_deref_load(b, 4, 32, deref, nir_imm_vec4(b, 0, 0, 0, 1), nir_ssa_undef(b, 1, 32), nir_imm_int(b, 0));
+ unsigned swiz[4] = {2, 1, 0, 3};
+ nir_ssa_def *swizzle = nir_swizzle(b, load, swiz, 4);
+ nir_ssa_def_rewrite_uses(&intr->dest.ssa, swizzle);
+ return true;
+}
+
+static bool
+lower_fbfetch(nir_shader *shader, nir_variable **fbfetch)
+{
+ nir_foreach_shader_out_variable(var, shader) {
+ if (var->data.fb_fetch_output) {
+ *fbfetch = var;
+ break;
+ }
+ }
+ assert(*fbfetch);
+ if (!*fbfetch)
+ return false;
+ return nir_shader_instructions_pass(shader, lower_fbfetch_instr, nir_metadata_dominance, *fbfetch);
}
/* check for a genuine gl_PointSize output vs one from nir_lower_point_size_mov */
@@ -462,7 +517,7 @@ static void
update_so_info(struct zink_shader *zs, const struct pipe_stream_output_info *so_info,
uint64_t outputs_written, bool have_psiz)
{
- uint8_t reverse_map[64] = {};
+ uint8_t reverse_map[64] = {0};
unsigned slot = 0;
/* semi-copied from iris */
while (outputs_written) {
@@ -509,70 +564,229 @@ update_so_info(struct zink_shader *zs, const struct pipe_stream_output_info *so_
zs->streamout.have_xfb = !!zs->streamout.so_info.num_outputs;
}
+struct decompose_state {
+ nir_variable **split;
+ bool needs_w;
+};
+
+static bool
+lower_attrib(nir_builder *b, nir_instr *instr, void *data)
+{
+ struct decompose_state *state = data;
+ nir_variable **split = state->split;
+ if (instr->type != nir_instr_type_intrinsic)
+ return false;
+ nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
+ if (intr->intrinsic != nir_intrinsic_load_deref)
+ return false;
+ nir_deref_instr *deref = nir_src_as_deref(intr->src[0]);
+ nir_variable *var = nir_deref_instr_get_variable(deref);
+ if (var != split[0])
+ return false;
+ unsigned num_components = glsl_get_vector_elements(split[0]->type);
+ b->cursor = nir_after_instr(instr);
+ nir_ssa_def *loads[4];
+ for (unsigned i = 0; i < (state->needs_w ? num_components - 1 : num_components); i++)
+ loads[i] = nir_load_deref(b, nir_build_deref_var(b, split[i+1]));
+ if (state->needs_w) {
+ /* oob load w comopnent to get correct value for int/float */
+ loads[3] = nir_channel(b, loads[0], 3);
+ loads[0] = nir_channel(b, loads[0], 0);
+ }
+ nir_ssa_def *new_load = nir_vec(b, loads, num_components);
+ nir_ssa_def_rewrite_uses(&intr->dest.ssa, new_load);
+ nir_instr_remove_v(instr);
+ return true;
+}
+
+static bool
+decompose_attribs(nir_shader *nir, uint32_t decomposed_attrs, uint32_t decomposed_attrs_without_w)
+{
+ uint32_t bits = 0;
+ nir_foreach_variable_with_modes(var, nir, nir_var_shader_in)
+ bits |= BITFIELD_BIT(var->data.driver_location);
+ bits = ~bits;
+ u_foreach_bit(location, decomposed_attrs | decomposed_attrs_without_w) {
+ nir_variable *split[5];
+ struct decompose_state state;
+ state.split = split;
+ nir_variable *var = nir_find_variable_with_driver_location(nir, nir_var_shader_in, location);
+ assert(var);
+ split[0] = var;
+ bits |= BITFIELD_BIT(var->data.driver_location);
+ const struct glsl_type *new_type = glsl_type_is_scalar(var->type) ? var->type : glsl_get_array_element(var->type);
+ unsigned num_components = glsl_get_vector_elements(var->type);
+ state.needs_w = (decomposed_attrs_without_w & BITFIELD_BIT(location)) != 0 && num_components == 4;
+ for (unsigned i = 0; i < (state.needs_w ? num_components - 1 : num_components); i++) {
+ split[i+1] = nir_variable_clone(var, nir);
+ split[i+1]->name = ralloc_asprintf(nir, "%s_split%u", var->name, i);
+ if (decomposed_attrs_without_w & BITFIELD_BIT(location))
+ split[i+1]->type = !i && num_components == 4 ? var->type : new_type;
+ else
+ split[i+1]->type = new_type;
+ split[i+1]->data.driver_location = ffs(bits) - 1;
+ bits &= ~BITFIELD_BIT(split[i+1]->data.driver_location);
+ nir_shader_add_variable(nir, split[i+1]);
+ }
+ var->data.mode = nir_var_shader_temp;
+ nir_shader_instructions_pass(nir, lower_attrib, nir_metadata_dominance, &state);
+ }
+ nir_fixup_deref_modes(nir);
+ NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_shader_temp, NULL);
+ optimize_nir(nir);
+ return true;
+}
+
static void
-assign_io_locations(nir_shader *nir, unsigned char *shader_slot_map,
- unsigned char *shader_slots_reserved)
+assign_producer_var_io(gl_shader_stage stage, nir_variable *var, unsigned *reserved, unsigned char *slot_map)
{
- unsigned reserved = shader_slots_reserved ? *shader_slots_reserved : 0;
- nir_foreach_variable_with_modes(var, nir, nir_var_shader_in | nir_var_shader_out) {
- if ((nir->info.stage == MESA_SHADER_VERTEX && var->data.mode == nir_var_shader_in) ||
- (nir->info.stage == MESA_SHADER_FRAGMENT && var->data.mode == nir_var_shader_out))
- continue;
+ unsigned slot = var->data.location;
+ switch (var->data.location) {
+ case VARYING_SLOT_POS:
+ case VARYING_SLOT_PNTC:
+ case VARYING_SLOT_PSIZ:
+ case VARYING_SLOT_LAYER:
+ case VARYING_SLOT_PRIMITIVE_ID:
+ case VARYING_SLOT_CLIP_DIST0:
+ case VARYING_SLOT_CULL_DIST0:
+ case VARYING_SLOT_VIEWPORT:
+ case VARYING_SLOT_FACE:
+ case VARYING_SLOT_TESS_LEVEL_OUTER:
+ case VARYING_SLOT_TESS_LEVEL_INNER:
+ /* use a sentinel value to avoid counting later */
+ var->data.driver_location = UINT_MAX;
+ break;
+
+ default:
+ if (var->data.patch) {
+ assert(var->data.location >= VARYING_SLOT_PATCH0);
+ slot = var->data.location - VARYING_SLOT_PATCH0;
+ } else if (var->data.location >= VARYING_SLOT_VAR0 &&
+ var->data.mode == nir_var_shader_in &&
+ stage == MESA_SHADER_TESS_EVAL) {
+ slot = var->data.location - VARYING_SLOT_VAR0;
+ } else {
+ if (slot_map[var->data.location] == 0xff) {
+ assert(*reserved < MAX_VARYING);
+ slot_map[var->data.location] = *reserved;
+ *reserved += glsl_count_vec4_slots(var->type, false, false);
+ }
+ slot = slot_map[var->data.location];
+ assert(slot < MAX_VARYING);
+ }
+ var->data.driver_location = slot;
+ }
+}
- unsigned slot = var->data.location;
- switch (var->data.location) {
- case VARYING_SLOT_POS:
- case VARYING_SLOT_PNTC:
- case VARYING_SLOT_PSIZ:
- case VARYING_SLOT_LAYER:
- case VARYING_SLOT_PRIMITIVE_ID:
- case VARYING_SLOT_CLIP_DIST0:
- case VARYING_SLOT_CULL_DIST0:
- case VARYING_SLOT_VIEWPORT:
- case VARYING_SLOT_FACE:
- case VARYING_SLOT_TESS_LEVEL_OUTER:
- case VARYING_SLOT_TESS_LEVEL_INNER:
- /* use a sentinel value to avoid counting later */
- var->data.driver_location = UINT_MAX;
- break;
+ALWAYS_INLINE static bool
+is_texcoord(gl_shader_stage stage, const nir_variable *var)
+{
+ if (stage != MESA_SHADER_FRAGMENT)
+ return false;
+ return var->data.location >= VARYING_SLOT_TEX0 &&
+ var->data.location <= VARYING_SLOT_TEX7;
+}
- default:
- if (var->data.patch) {
- assert(var->data.location >= VARYING_SLOT_PATCH0);
- slot = var->data.location - VARYING_SLOT_PATCH0;
- } else if (var->data.location >= VARYING_SLOT_VAR0 &&
- ((var->data.mode == nir_var_shader_out &&
- nir->info.stage == MESA_SHADER_TESS_CTRL) ||
- (var->data.mode != nir_var_shader_out &&
- nir->info.stage == MESA_SHADER_TESS_EVAL))) {
- slot = var->data.location - VARYING_SLOT_VAR0;
- } else {
- if (shader_slot_map[var->data.location] == 0xff) {
- assert(reserved < MAX_VARYING);
- shader_slot_map[var->data.location] = reserved;
- if (nir->info.stage == MESA_SHADER_TESS_CTRL && var->data.location >= VARYING_SLOT_VAR0)
- reserved += (glsl_count_vec4_slots(var->type, false, false) / 32 /*MAX_PATCH_VERTICES*/);
- else
- reserved += glsl_count_vec4_slots(var->type, false, false);
- }
- slot = shader_slot_map[var->data.location];
- assert(slot < MAX_VARYING);
+static bool
+assign_consumer_var_io(gl_shader_stage stage, nir_variable *var, unsigned *reserved, unsigned char *slot_map)
+{
+ switch (var->data.location) {
+ case VARYING_SLOT_POS:
+ case VARYING_SLOT_PNTC:
+ case VARYING_SLOT_PSIZ:
+ case VARYING_SLOT_LAYER:
+ case VARYING_SLOT_PRIMITIVE_ID:
+ case VARYING_SLOT_CLIP_DIST0:
+ case VARYING_SLOT_CULL_DIST0:
+ case VARYING_SLOT_VIEWPORT:
+ case VARYING_SLOT_FACE:
+ case VARYING_SLOT_TESS_LEVEL_OUTER:
+ case VARYING_SLOT_TESS_LEVEL_INNER:
+ /* use a sentinel value to avoid counting later */
+ var->data.driver_location = UINT_MAX;
+ break;
+ default:
+ if (var->data.patch) {
+ assert(var->data.location >= VARYING_SLOT_PATCH0);
+ var->data.driver_location = var->data.location - VARYING_SLOT_PATCH0;
+ } else if (var->data.location >= VARYING_SLOT_VAR0 &&
+ stage == MESA_SHADER_TESS_CTRL &&
+ var->data.mode == nir_var_shader_out)
+ var->data.driver_location = var->data.location - VARYING_SLOT_VAR0;
+ else {
+ if (slot_map[var->data.location] == (unsigned char)-1) {
+ if (!is_texcoord(stage, var))
+ /* dead io */
+ return false;
+ /* texcoords can't be eliminated in fs due to GL_COORD_REPLACE */
+ slot_map[var->data.location] = (*reserved)++;
}
- var->data.driver_location = slot;
+ var->data.driver_location = slot_map[var->data.location];
}
}
+ return true;
+}
+
+
+static bool
+rewrite_and_discard_read(nir_builder *b, nir_instr *instr, void *data)
+{
+ nir_variable *var = data;
+ if (instr->type != nir_instr_type_intrinsic)
+ return false;
- if (shader_slots_reserved)
- *shader_slots_reserved = reserved;
+ nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
+ if (intr->intrinsic != nir_intrinsic_load_deref)
+ return false;
+ nir_variable *deref_var = nir_intrinsic_get_var(intr, 0);
+ if (deref_var != var)
+ return false;
+ nir_ssa_def *undef = nir_ssa_undef(b, nir_dest_num_components(intr->dest), nir_dest_bit_size(intr->dest));
+ nir_ssa_def_rewrite_uses(&intr->dest.ssa, undef);
+ return true;
+}
+
+void
+zink_compiler_assign_io(nir_shader *producer, nir_shader *consumer)
+{
+ unsigned reserved = 0;
+ unsigned char slot_map[VARYING_SLOT_MAX];
+ memset(slot_map, -1, sizeof(slot_map));
+ bool do_fixup = false;
+ nir_shader *nir = producer->info.stage == MESA_SHADER_TESS_CTRL ? producer : consumer;
+ if (producer->info.stage == MESA_SHADER_TESS_CTRL) {
+ /* never assign from tcs -> tes, always invert */
+ nir_foreach_variable_with_modes(var, consumer, nir_var_shader_in)
+ assign_producer_var_io(consumer->info.stage, var, &reserved, slot_map);
+ nir_foreach_variable_with_modes_safe(var, producer, nir_var_shader_out) {
+ if (!assign_consumer_var_io(producer->info.stage, var, &reserved, slot_map))
+ /* this is an output, nothing more needs to be done for it to be dropped */
+ do_fixup = true;
+ }
+ } else {
+ nir_foreach_variable_with_modes(var, producer, nir_var_shader_out)
+ assign_producer_var_io(producer->info.stage, var, &reserved, slot_map);
+ nir_foreach_variable_with_modes_safe(var, consumer, nir_var_shader_in) {
+ if (!assign_consumer_var_io(consumer->info.stage, var, &reserved, slot_map)) {
+ do_fixup = true;
+ /* input needs to be rewritten as an undef to ensure the entire deref chain is deleted */
+ nir_shader_instructions_pass(consumer, rewrite_and_discard_read, nir_metadata_dominance, var);
+ }
+ }
+ }
+ if (!do_fixup)
+ return;
+ nir_fixup_deref_modes(nir);
+ NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_shader_temp, NULL);
+ optimize_nir(nir);
}
VkShaderModule
-zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs, struct zink_shader_key *key,
- unsigned char *shader_slot_map, unsigned char *shader_slots_reserved)
+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;
- nir_shader *nir = nir_shader_clone(NULL, zs->nir);
+ nir_shader *nir = nir_shader_clone(NULL, base_nir);
if (key) {
if (key->inline_uniforms) {
@@ -587,48 +801,82 @@ zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs, struct z
NIR_PASS_V(nir, nir_io_add_const_offset_to_base, nir_var_shader_in |
nir_var_shader_out);
}
- }
- /* TODO: use a separate mem ctx here for ralloc */
- if (zs->nir->info.stage < MESA_SHADER_FRAGMENT) {
- if (zink_vs_key(key)->last_vertex_stage) {
- if (zs->streamout.have_xfb)
- streamout = &zs->streamout;
-
- if (!zink_vs_key(key)->clip_halfz) {
- NIR_PASS_V(nir, nir_lower_clip_halfz);
- }
- if (zink_vs_key(key)->push_drawid) {
- NIR_PASS_V(nir, lower_drawid);
+ /* TODO: use a separate mem ctx here for ralloc */
+ switch (zs->nir->info.stage) {
+ case MESA_SHADER_VERTEX: {
+ uint32_t decomposed_attrs = 0, decomposed_attrs_without_w = 0;
+ const struct zink_vs_key *vs_key = zink_vs_key(key);
+ switch (vs_key->size) {
+ case 4:
+ decomposed_attrs = vs_key->u32.decomposed_attrs;
+ decomposed_attrs_without_w = vs_key->u32.decomposed_attrs_without_w;
+ break;
+ case 2:
+ decomposed_attrs = vs_key->u16.decomposed_attrs;
+ decomposed_attrs_without_w = vs_key->u16.decomposed_attrs_without_w;
+ break;
+ case 1:
+ decomposed_attrs = vs_key->u8.decomposed_attrs;
+ decomposed_attrs_without_w = vs_key->u8.decomposed_attrs_without_w;
+ break;
+ default: break;
}
+ if (decomposed_attrs || decomposed_attrs_without_w)
+ NIR_PASS_V(nir, decompose_attribs, decomposed_attrs, decomposed_attrs_without_w);
+ FALLTHROUGH;
}
- } else if (zs->nir->info.stage == MESA_SHADER_FRAGMENT) {
- if (!zink_fs_key(key)->samples &&
- nir->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK)) {
- /* VK will always use gl_SampleMask[] values even if sample count is 0,
- * so we need to skip this write here to mimic GL's behavior of ignoring it
- */
- nir_foreach_shader_out_variable(var, nir) {
- if (var->data.location == FRAG_RESULT_SAMPLE_MASK)
- var->data.mode = nir_var_shader_temp;
+ case MESA_SHADER_TESS_EVAL:
+ case MESA_SHADER_GEOMETRY:
+ if (zink_vs_key_base(key)->last_vertex_stage) {
+ if (zs->streamout.have_xfb)
+ streamout = &zs->streamout;
+
+ if (!zink_vs_key_base(key)->clip_halfz) {
+ NIR_PASS_V(nir, nir_lower_clip_halfz);
+ }
+ if (zink_vs_key_base(key)->push_drawid) {
+ NIR_PASS_V(nir, lower_drawid);
+ }
}
- nir_fixup_deref_modes(nir);
- NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_shader_temp, NULL);
- optimize_nir(nir);
- }
- if (zink_fs_key(key)->force_dual_color_blend && nir->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DATA1)) {
- NIR_PASS_V(nir, lower_dual_blend);
- }
- if (zink_fs_key(key)->coord_replace_bits) {
- NIR_PASS_V(nir, nir_lower_texcoord_replace, zink_fs_key(key)->coord_replace_bits,
- false, zink_fs_key(key)->coord_replace_yinvert);
+ break;
+ case MESA_SHADER_FRAGMENT:
+ if (!zink_fs_key(key)->samples &&
+ nir->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK)) {
+ /* VK will always use gl_SampleMask[] values even if sample count is 0,
+ * so we need to skip this write here to mimic GL's behavior of ignoring it
+ */
+ nir_foreach_shader_out_variable(var, nir) {
+ if (var->data.location == FRAG_RESULT_SAMPLE_MASK)
+ var->data.mode = nir_var_shader_temp;
+ }
+ nir_fixup_deref_modes(nir);
+ NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_shader_temp, NULL);
+ optimize_nir(nir);
+ }
+ if (zink_fs_key(key)->force_dual_color_blend && nir->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DATA1)) {
+ NIR_PASS_V(nir, lower_dual_blend);
+ }
+ if (zink_fs_key(key)->coord_replace_bits) {
+ NIR_PASS_V(nir, nir_lower_texcoord_replace, zink_fs_key(key)->coord_replace_bits,
+ false, zink_fs_key(key)->coord_replace_yinvert);
+ }
+ if (nir->info.fs.uses_fbfetch_output) {
+ nir_variable *fbfetch = NULL;
+ NIR_PASS_V(nir, lower_fbfetch, &fbfetch);
+ /* old variable must be deleted to avoid spirv errors */
+ fbfetch->data.mode = nir_var_shader_temp;
+ nir_fixup_deref_modes(nir);
+ NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_shader_temp, NULL);
+ optimize_nir(nir);
+ }
+ break;
+ default: break;
}
}
NIR_PASS_V(nir, nir_convert_from_ssa, true);
- assign_io_locations(nir, shader_slot_map, shader_slots_reserved);
-
- struct spirv_shader *spirv = nir_to_spirv(nir, streamout);
+ struct spirv_shader *spirv = nir_to_spirv(nir, streamout, screen->spirv_version);
if (!spirv)
goto done;
@@ -644,12 +892,12 @@ zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs, struct z
}
}
- VkShaderModuleCreateInfo smci = {};
+ VkShaderModuleCreateInfo smci = {0};
smci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
smci.codeSize = spirv->num_words * sizeof(uint32_t);
smci.pCode = spirv->words;
- if (vkCreateShaderModule(screen->dev, &smci, NULL, &mod) != VK_SUCCESS)
+ if (VKSCR(CreateShaderModule)(screen->dev, &smci, NULL, &mod) != VK_SUCCESS)
mod = VK_NULL_HANDLE;
done:
@@ -794,6 +1042,288 @@ unbreak_bos(nir_shader *shader)
return true;
}
+/* this is a "default" bindless texture used if the shader has no texture variables */
+static nir_variable *
+create_bindless_texture(nir_shader *nir, nir_tex_instr *tex)
+{
+ unsigned binding = tex->sampler_dim == GLSL_SAMPLER_DIM_BUF ? 1 : 0;
+ nir_variable *var;
+
+ const struct glsl_type *sampler_type = glsl_sampler_type(tex->sampler_dim, tex->is_shadow, tex->is_array, GLSL_TYPE_FLOAT);
+ var = nir_variable_create(nir, nir_var_uniform, glsl_array_type(sampler_type, ZINK_MAX_BINDLESS_HANDLES, 0), "bindless_texture");
+ var->data.descriptor_set = ZINK_DESCRIPTOR_BINDLESS;
+ var->data.driver_location = var->data.binding = binding;
+ return var;
+}
+
+/* this is a "default" bindless image used if the shader has no image variables */
+static nir_variable *
+create_bindless_image(nir_shader *nir, enum glsl_sampler_dim dim)
+{
+ unsigned binding = dim == GLSL_SAMPLER_DIM_BUF ? 3 : 2;
+ nir_variable *var;
+
+ const struct glsl_type *image_type = glsl_image_type(dim, false, GLSL_TYPE_FLOAT);
+ var = nir_variable_create(nir, nir_var_uniform, glsl_array_type(image_type, ZINK_MAX_BINDLESS_HANDLES, 0), "bindless_image");
+ var->data.descriptor_set = ZINK_DESCRIPTOR_BINDLESS;
+ var->data.driver_location = var->data.binding = binding;
+ var->data.image.format = PIPE_FORMAT_R8G8B8A8_UNORM;
+ return var;
+}
+
+/* rewrite bindless instructions as array deref instructions */
+static bool
+lower_bindless_instr(nir_builder *b, nir_instr *in, void *data)
+{
+ nir_variable **bindless = data;
+
+ if (in->type == nir_instr_type_tex) {
+ nir_tex_instr *tex = nir_instr_as_tex(in);
+ int idx = nir_tex_instr_src_index(tex, nir_tex_src_texture_handle);
+ if (idx == -1)
+ return false;
+
+ nir_variable *var = tex->sampler_dim == GLSL_SAMPLER_DIM_BUF ? bindless[1] : bindless[0];
+ if (!var)
+ var = create_bindless_texture(b->shader, tex);
+ b->cursor = nir_before_instr(in);
+ nir_deref_instr *deref = nir_build_deref_var(b, var);
+ if (glsl_type_is_array(var->type))
+ deref = nir_build_deref_array(b, deref, nir_u2uN(b, tex->src[idx].src.ssa, 32));
+ nir_instr_rewrite_src_ssa(in, &tex->src[idx].src, &deref->dest.ssa);
+
+ /* bindless sampling uses the variable type directly, which means the tex instr has to exactly
+ * match up with it in contrast to normal sampler ops where things are a bit more flexible;
+ * this results in cases where a shader is passed with sampler2DArray but the tex instr only has
+ * 2 components, which explodes spirv compilation even though it doesn't trigger validation errors
+ *
+ * to fix this, pad the coord src here and fix the tex instr so that ntv will do the "right" thing
+ * - Warhammer 40k: Dawn of War III
+ */
+ unsigned needed_components = glsl_get_sampler_coordinate_components(glsl_without_array(var->type));
+ unsigned c = nir_tex_instr_src_index(tex, nir_tex_src_coord);
+ unsigned coord_components = nir_src_num_components(tex->src[c].src);
+ if (coord_components < needed_components) {
+ nir_ssa_def *def = nir_pad_vector(b, tex->src[c].src.ssa, needed_components);
+ nir_instr_rewrite_src_ssa(in, &tex->src[c].src, def);
+ tex->coord_components = needed_components;
+ }
+ return true;
+ }
+ if (in->type != nir_instr_type_intrinsic)
+ return false;
+ nir_intrinsic_instr *instr = nir_instr_as_intrinsic(in);
+
+ nir_intrinsic_op op;
+#define OP_SWAP(OP) \
+ case nir_intrinsic_bindless_image_##OP: \
+ op = nir_intrinsic_image_deref_##OP; \
+ break;
+
+
+ /* convert bindless intrinsics to deref intrinsics */
+ switch (instr->intrinsic) {
+ OP_SWAP(atomic_add)
+ OP_SWAP(atomic_and)
+ OP_SWAP(atomic_comp_swap)
+ OP_SWAP(atomic_dec_wrap)
+ OP_SWAP(atomic_exchange)
+ OP_SWAP(atomic_fadd)
+ OP_SWAP(atomic_fmax)
+ OP_SWAP(atomic_fmin)
+ OP_SWAP(atomic_imax)
+ OP_SWAP(atomic_imin)
+ OP_SWAP(atomic_inc_wrap)
+ OP_SWAP(atomic_or)
+ OP_SWAP(atomic_umax)
+ OP_SWAP(atomic_umin)
+ OP_SWAP(atomic_xor)
+ OP_SWAP(format)
+ OP_SWAP(load)
+ OP_SWAP(order)
+ OP_SWAP(samples)
+ OP_SWAP(size)
+ OP_SWAP(store)
+ default:
+ return false;
+ }
+
+ enum glsl_sampler_dim dim = nir_intrinsic_image_dim(instr);
+ nir_variable *var = dim == GLSL_SAMPLER_DIM_BUF ? bindless[3] : bindless[2];
+ if (!var)
+ var = create_bindless_image(b->shader, dim);
+ instr->intrinsic = op;
+ b->cursor = nir_before_instr(in);
+ nir_deref_instr *deref = nir_build_deref_var(b, var);
+ if (glsl_type_is_array(var->type))
+ deref = nir_build_deref_array(b, deref, nir_u2uN(b, instr->src[0].ssa, 32));
+ nir_instr_rewrite_src_ssa(in, &instr->src[0], &deref->dest.ssa);
+ return true;
+}
+
+static bool
+lower_bindless(nir_shader *shader, nir_variable **bindless)
+{
+ if (!nir_shader_instructions_pass(shader, lower_bindless_instr, nir_metadata_dominance, bindless))
+ return false;
+ nir_fixup_deref_modes(shader);
+ NIR_PASS_V(shader, nir_remove_dead_variables, nir_var_shader_temp, NULL);
+ optimize_nir(shader);
+ return true;
+}
+
+/* convert shader image/texture io variables to int64 handles for bindless indexing */
+static bool
+lower_bindless_io_instr(nir_builder *b, nir_instr *in, void *data)
+{
+ if (in->type != nir_instr_type_intrinsic)
+ return false;
+ nir_intrinsic_instr *instr = nir_instr_as_intrinsic(in);
+ if (instr->intrinsic != nir_intrinsic_load_deref &&
+ instr->intrinsic != nir_intrinsic_store_deref)
+ return false;
+
+ nir_deref_instr *src_deref = nir_src_as_deref(instr->src[0]);
+ nir_variable *var = nir_deref_instr_get_variable(src_deref);
+ if (var->data.bindless)
+ return false;
+ if (var->data.mode != nir_var_shader_in && var->data.mode != nir_var_shader_out)
+ return false;
+ if (!glsl_type_is_image(var->type) && !glsl_type_is_sampler(var->type))
+ return false;
+
+ var->type = glsl_int64_t_type();
+ var->data.bindless = 1;
+ b->cursor = nir_before_instr(in);
+ nir_deref_instr *deref = nir_build_deref_var(b, var);
+ if (instr->intrinsic == nir_intrinsic_load_deref) {
+ nir_ssa_def *def = nir_load_deref(b, deref);
+ nir_instr_rewrite_src_ssa(in, &instr->src[0], def);
+ nir_ssa_def_rewrite_uses(&instr->dest.ssa, def);
+ } else {
+ nir_store_deref(b, deref, instr->src[1].ssa, nir_intrinsic_write_mask(instr));
+ }
+ nir_instr_remove(in);
+ nir_instr_remove(&src_deref->instr);
+ return true;
+}
+
+static bool
+lower_bindless_io(nir_shader *shader)
+{
+ return nir_shader_instructions_pass(shader, lower_bindless_io_instr, nir_metadata_dominance, NULL);
+}
+
+static uint32_t
+zink_binding(gl_shader_stage stage, VkDescriptorType type, int index)
+{
+ if (stage == MESA_SHADER_NONE) {
+ unreachable("not supported");
+ } else {
+ switch (type) {
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ assert(index < PIPE_MAX_CONSTANT_BUFFERS);
+ return (stage * PIPE_MAX_CONSTANT_BUFFERS) + index;
+
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+ assert(index < PIPE_MAX_SAMPLERS);
+ return (stage * PIPE_MAX_SAMPLERS) + index;
+
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+ assert(index < PIPE_MAX_SHADER_BUFFERS);
+ return (stage * PIPE_MAX_SHADER_BUFFERS) + index;
+
+ case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+ assert(index < PIPE_MAX_SHADER_IMAGES);
+ return (stage * PIPE_MAX_SHADER_IMAGES) + index;
+
+ default:
+ unreachable("unexpected type");
+ }
+ }
+}
+
+static void
+handle_bindless_var(nir_shader *nir, nir_variable *var, const struct glsl_type *type, nir_variable **bindless)
+{
+ if (glsl_type_is_struct(type)) {
+ for (unsigned i = 0; i < glsl_get_length(type); i++)
+ handle_bindless_var(nir, var, glsl_get_struct_field(type, i), bindless);
+ return;
+ }
+
+ /* just a random scalar in a struct */
+ if (!glsl_type_is_image(type) && !glsl_type_is_sampler(type))
+ return;
+
+ VkDescriptorType vktype = glsl_type_is_image(type) ? zink_image_type(type) : zink_sampler_type(type);
+ unsigned binding;
+ switch (vktype) {
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ binding = 0;
+ break;
+ case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+ binding = 1;
+ break;
+ case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ binding = 2;
+ break;
+ case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+ binding = 3;
+ break;
+ default:
+ unreachable("unknown");
+ }
+ if (!bindless[binding]) {
+ bindless[binding] = nir_variable_clone(var, nir);
+ bindless[binding]->data.bindless = 0;
+ bindless[binding]->data.descriptor_set = ZINK_DESCRIPTOR_BINDLESS;
+ bindless[binding]->type = glsl_array_type(type, ZINK_MAX_BINDLESS_HANDLES, 0);
+ bindless[binding]->data.driver_location = bindless[binding]->data.binding = binding;
+ if (!bindless[binding]->data.image.format)
+ bindless[binding]->data.image.format = PIPE_FORMAT_R8G8B8A8_UNORM;
+ nir_shader_add_variable(nir, bindless[binding]);
+ } else {
+ assert(glsl_get_sampler_dim(glsl_without_array(bindless[binding]->type)) == glsl_get_sampler_dim(glsl_without_array(var->type)));
+ }
+ var->data.mode = nir_var_shader_temp;
+}
+
+static enum pipe_prim_type
+gl_prim_to_pipe(unsigned primitive_type)
+{
+ switch (primitive_type) {
+ case GL_POINTS:
+ return PIPE_PRIM_POINTS;
+ case GL_LINES:
+ case GL_LINE_LOOP:
+ case GL_LINE_STRIP:
+ case GL_LINES_ADJACENCY:
+ case GL_LINE_STRIP_ADJACENCY:
+ case GL_ISOLINES:
+ return PIPE_PRIM_LINES;
+ default:
+ return PIPE_PRIM_TRIANGLES;
+ }
+}
+
+static enum pipe_prim_type
+get_shader_base_prim_type(struct nir_shader *nir)
+{
+ switch (nir->info.stage) {
+ case MESA_SHADER_GEOMETRY:
+ return gl_prim_to_pipe(nir->info.gs.output_primitive);
+ case MESA_SHADER_TESS_EVAL:
+ return nir->info.tess.point_mode ? PIPE_PRIM_POINTS : gl_prim_to_pipe(nir->info.tess.primitive_mode);
+ default:
+ break;
+ }
+ return PIPE_PRIM_MAX;
+}
+
struct zink_shader *
zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
const struct pipe_stream_output_info *so_info)
@@ -801,16 +1331,26 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
struct zink_shader *ret = CALLOC_STRUCT(zink_shader);
bool have_psiz = false;
- ret->shader_id = p_atomic_inc_return(&screen->shader_id);
+ ret->hash = _mesa_hash_pointer(ret);
+ ret->reduced_prim = get_shader_base_prim_type(nir);
+
ret->programs = _mesa_pointer_set_create(NULL);
+ simple_mtx_init(&ret->lock, mtx_plain);
+
+ nir_variable_mode indirect_derefs_modes = nir_var_function_temp;
+ if (nir->info.stage == MESA_SHADER_TESS_CTRL ||
+ nir->info.stage == MESA_SHADER_TESS_EVAL)
+ indirect_derefs_modes |= nir_var_shader_in | nir_var_shader_out;
+
+ NIR_PASS_V(nir, nir_lower_indirect_derefs, indirect_derefs_modes,
+ UINT32_MAX);
if (nir->info.stage == MESA_SHADER_VERTEX)
create_vs_pushconst(nir);
else if (nir->info.stage == MESA_SHADER_TESS_CTRL ||
- nir->info.stage == MESA_SHADER_TESS_EVAL) {
- NIR_PASS_V(nir, nir_lower_indirect_derefs, nir_var_shader_in | nir_var_shader_out, UINT_MAX);
+ nir->info.stage == MESA_SHADER_TESS_EVAL)
NIR_PASS_V(nir, nir_lower_io_arrays_to_elements_no_indirects, false);
- } else if (nir->info.stage == MESA_SHADER_KERNEL)
+ else if (nir->info.stage == MESA_SHADER_KERNEL)
create_cs_pushconst(nir);
if (nir->info.stage < MESA_SHADER_FRAGMENT)
@@ -819,10 +1359,22 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
NIR_PASS_V(nir, lower_work_dim);
NIR_PASS_V(nir, nir_lower_regs_to_ssa);
NIR_PASS_V(nir, lower_baseinstance);
+
+ {
+ nir_lower_subgroups_options subgroup_options = {0};
+ subgroup_options.lower_to_scalar = true;
+ subgroup_options.subgroup_size = screen->info.props11.subgroupSize;
+ subgroup_options.ballot_bit_size = 32;
+ subgroup_options.ballot_components = 4;
+ subgroup_options.lower_subgroup_masks = true;
+ NIR_PASS_V(nir, nir_lower_subgroups, &subgroup_options);
+ }
+
optimize_nir(nir);
NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_function_temp, NULL);
NIR_PASS_V(nir, lower_discard_if);
- NIR_PASS_V(nir, nir_lower_fragcolor);
+ NIR_PASS_V(nir, nir_lower_fragcolor,
+ nir->info.fs.color_is_dual_source ? 1 : 8);
NIR_PASS_V(nir, lower_64bit_vertex_attribs);
NIR_PASS_V(nir, unbreak_bos);
@@ -832,7 +1384,18 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
fprintf(stderr, "---8<---\n");
}
- foreach_list_typed_reverse(nir_variable, var, node, &nir->variables) {
+ nir_variable *bindless[4] = {0};
+ bool has_bindless_io = false;
+ nir_foreach_variable_with_modes(var, nir, nir_var_shader_in | nir_var_shader_out) {
+ if (glsl_type_is_image(var->type) || glsl_type_is_sampler(var->type)) {
+ has_bindless_io = true;
+ break;
+ }
+ }
+ if (has_bindless_io)
+ NIR_PASS_V(nir, lower_bindless_io);
+
+ foreach_list_typed_reverse_safe(nir_variable, var, node, &nir->variables) {
if (_nir_shader_variable_has_mode(var, nir_var_uniform |
nir_var_mem_ubo |
nir_var_mem_ssbo)) {
@@ -840,10 +1403,13 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
const struct glsl_type *type = glsl_without_array(var->type);
if (var->data.mode == nir_var_mem_ubo) {
ztype = ZINK_DESCRIPTOR_TYPE_UBO;
- var->data.descriptor_set = ztype;
- var->data.binding = zink_binding(nir->info.stage,
- VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
- var->data.driver_location);
+ /* buffer 0 is a push descriptor */
+ var->data.descriptor_set = !!var->data.driver_location;
+ var->data.binding = !var->data.driver_location ? nir->info.stage :
+ zink_binding(nir->info.stage,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ var->data.driver_location);
+ assert(var->data.driver_location || var->data.binding < 10);
VkDescriptorType vktype = !var->data.driver_location ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
int binding = var->data.binding;
@@ -855,7 +1421,7 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
ret->num_bindings[ztype]++;
} else if (var->data.mode == nir_var_mem_ssbo) {
ztype = ZINK_DESCRIPTOR_TYPE_SSBO;
- var->data.descriptor_set = ztype;
+ var->data.descriptor_set = ztype + 1;
var->data.binding = zink_binding(nir->info.stage,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
var->data.driver_location);
@@ -867,14 +1433,17 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
ret->num_bindings[ztype]++;
} else {
assert(var->data.mode == nir_var_uniform);
- if (glsl_type_is_sampler(type) || glsl_type_is_image(type)) {
+ if (var->data.bindless) {
+ ret->bindless = true;
+ handle_bindless_var(nir, var, type, bindless);
+ } else if (glsl_type_is_sampler(type) || glsl_type_is_image(type)) {
VkDescriptorType vktype = glsl_type_is_image(type) ? zink_image_type(type) : zink_sampler_type(type);
ztype = zink_desc_type_from_vktype(vktype);
- var->data.descriptor_set = ztype;
+ if (vktype == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER)
+ ret->num_texel_buffers++;
var->data.driver_location = var->data.binding;
- var->data.binding = zink_binding(nir->info.stage,
- vktype,
- var->data.driver_location);
+ var->data.descriptor_set = ztype + 1;
+ var->data.binding = zink_binding(nir->info.stage, vktype, var->data.driver_location);
ret->bindings[ztype][ret->num_bindings[ztype]].index = var->data.driver_location;
ret->bindings[ztype][ret->num_bindings[ztype]].binding = var->data.binding;
ret->bindings[ztype][ret->num_bindings[ztype]].type = vktype;
@@ -887,6 +1456,9 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
}
}
}
+ bool bindless_lowered = false;
+ NIR_PASS(bindless_lowered, nir, lower_bindless, bindless);
+ ret->bindless |= bindless_lowered;
ret->nir = nir;
if (so_info && nir->info.outputs_written && nir->info.has_transform_feedback_varyings)
@@ -895,18 +1467,18 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
return ret;
}
-void
-zink_shader_finalize(struct pipe_screen *pscreen, void *nirptr, bool optimize)
+char *
+zink_shader_finalize(struct pipe_screen *pscreen, void *nirptr)
{
struct zink_screen *screen = zink_screen(pscreen);
nir_shader *nir = nirptr;
if (!screen->info.feats.features.shaderImageGatherExtended) {
- nir_lower_tex_options tex_opts = {};
+ nir_lower_tex_options tex_opts = {0};
tex_opts.lower_tg4_offsets = true;
NIR_PASS_V(nir, nir_lower_tex, &tex_opts);
}
- NIR_PASS_V(nir, nir_lower_uniforms_to_ubo, false, false);
+ NIR_PASS_V(nir, nir_lower_uniforms_to_ubo, true, false);
if (nir->info.stage == MESA_SHADER_GEOMETRY)
NIR_PASS_V(nir, nir_lower_gs_intrinsics, nir_lower_gs_intrinsics_per_stream);
optimize_nir(nir);
@@ -915,6 +1487,8 @@ zink_shader_finalize(struct pipe_screen *pscreen, void *nirptr, bool optimize)
nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
if (screen->driconf.inline_uniforms)
nir_find_inlinable_uniforms(nir);
+
+ return NULL;
}
void
@@ -924,30 +1498,25 @@ zink_shader_free(struct zink_context *ctx, struct zink_shader *shader)
set_foreach(shader->programs, entry) {
if (shader->nir->info.stage == MESA_SHADER_COMPUTE) {
struct zink_compute_program *comp = (void*)entry->key;
- _mesa_hash_table_remove_key(ctx->compute_program_cache, &comp->shader->shader_id);
+ if (!comp->base.removed) {
+ _mesa_hash_table_remove_key(&ctx->compute_program_cache, comp->shader);
+ comp->base.removed = true;
+ }
comp->shader = NULL;
- bool in_use = comp == ctx->curr_compute;
- if (in_use)
- ctx->compute_stage = NULL;
- if (zink_compute_program_reference(screen, &comp, NULL) && in_use)
- ctx->curr_compute = NULL;
+ zink_compute_program_reference(screen, &comp, NULL);
} else {
struct zink_gfx_program *prog = (void*)entry->key;
enum pipe_shader_type pstage = pipe_shader_type_from_mesa(shader->nir->info.stage);
assert(pstage < ZINK_SHADER_COUNT);
- bool in_use = prog == ctx->curr_program;
- if (shader->nir->info.stage != MESA_SHADER_TESS_CTRL || !shader->is_generated)
- _mesa_hash_table_remove_key(ctx->program_cache, prog->shaders);
+ if (!prog->base.removed && (shader->nir->info.stage != MESA_SHADER_TESS_CTRL || !shader->is_generated)) {
+ _mesa_hash_table_remove_key(&ctx->program_cache[prog->stages_present >> 2], prog->shaders);
+ prog->base.removed = true;
+ }
prog->shaders[pstage] = NULL;
if (shader->nir->info.stage == MESA_SHADER_TESS_EVAL && shader->generated)
/* automatically destroy generated tcs shaders when tes is destroyed */
zink_shader_free(ctx, shader->generated);
- if (in_use) {
- ctx->gfx_pipeline_state.modules[pstage] = VK_NULL_HANDLE;
- ctx->gfx_stages[pstage] = NULL;
- }
- if (zink_gfx_program_reference(screen, &prog, NULL) && in_use)
- ctx->curr_program = NULL;
+ zink_gfx_program_reference(screen, &prog, NULL);
}
}
_mesa_set_destroy(shader->programs, NULL);
@@ -978,14 +1547,14 @@ void main()
*/
struct zink_shader *
-zink_shader_tcs_create(struct zink_context *ctx, struct zink_shader *vs)
+zink_shader_tcs_create(struct zink_screen *screen, struct zink_shader *vs, unsigned vertices_per_patch)
{
- unsigned vertices_per_patch = ctx->gfx_pipeline_state.vertices_per_patch;
struct zink_shader *ret = CALLOC_STRUCT(zink_shader);
- ret->shader_id = 0; //special value for internal shaders
+ ret->hash = _mesa_hash_pointer(ret);
ret->programs = _mesa_pointer_set_create(NULL);
+ simple_mtx_init(&ret->lock, mtx_plain);
- nir_shader *nir = nir_shader_create(NULL, MESA_SHADER_TESS_CTRL, &zink_screen(ctx->base.screen)->nir_options, NULL);
+ nir_shader *nir = nir_shader_create(NULL, MESA_SHADER_TESS_CTRL, &screen->nir_options, NULL);
nir_function *fn = nir_function_create(nir, "main");
fn->is_entrypoint = true;
nir_function_impl *impl = nir_function_impl_create(fn);
@@ -1075,35 +1644,3 @@ zink_shader_tcs_create(struct zink_context *ctx, struct zink_shader *vs)
ret->is_generated = true;
return ret;
}
-
-uint32_t
-zink_binding(gl_shader_stage stage, VkDescriptorType type, int index)
-{
- if (stage == MESA_SHADER_NONE) {
- unreachable("not supported");
- } else {
- switch (type) {
- case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
- case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
- assert(index < PIPE_MAX_CONSTANT_BUFFERS);
- return (stage * PIPE_MAX_CONSTANT_BUFFERS) + index;
-
- case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
- case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
- assert(index < PIPE_MAX_SAMPLERS);
- return (stage * PIPE_MAX_SAMPLERS) + index;
-
- case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
- assert(index < PIPE_MAX_SHADER_BUFFERS);
- return (stage * PIPE_MAX_SHADER_BUFFERS) + index;
-
- case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
- case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
- assert(index < PIPE_MAX_SHADER_IMAGES);
- return (stage * PIPE_MAX_SHADER_IMAGES) + index;
-
- default:
- unreachable("unexpected type");
- }
- }
-}