zink: use PIPE_CAP_NIR_SAMPLERS_AS_DEREF

this simplifies a bunch of stuff, though it also requires manually
clamping constnat oob indexing to avoid piglit hangs

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30001>
This commit is contained in:
Mike Blumenkrantz 2024-07-02 12:32:21 -04:00 committed by Marge Bot
parent 235eb1af96
commit da47c0ed65
6 changed files with 97 additions and 158 deletions

View file

@ -119,7 +119,6 @@ spec@arb_post_depth_coverage@arb_post_depth_coverage-multisampling,Fail
spec@arb_shader_image_load_store@early-z,Fail
spec@arb_shader_image_load_store@early-z@occlusion query test/early-z pass,Fail
spec@arb_shader_image_load_store@execution@image-array-out-of-bounds-access-load,Crash
spec@arb_shader_image_load_store@execution@image-array-out-of-bounds-access-store,Crash
#literally no driver can pass these

View file

@ -64,7 +64,6 @@ struct ntv_context {
struct hash_table image_types;
SpvId samplers[PIPE_MAX_SHADER_SAMPLER_VIEWS];
SpvId bindless_samplers[2];
SpvId cl_samplers[PIPE_MAX_SAMPLERS];
nir_variable *sampler_var[PIPE_MAX_SHADER_SAMPLER_VIEWS]; /* driver_location -> variable */
nir_variable *bindless_sampler_var[2];
unsigned last_sampler;
@ -1248,7 +1247,7 @@ emit_image(struct ntv_context *ctx, struct nir_variable *var, SpvId image_type)
}
static void
emit_sampler(struct ntv_context *ctx, unsigned sampler_index, unsigned desc_set)
emit_sampler(struct ntv_context *ctx, nir_variable *var)
{
SpvId type = spirv_builder_type_sampler(&ctx->builder);
SpvId pointer_type = spirv_builder_type_pointer(&ctx->builder,
@ -1258,16 +1257,15 @@ emit_sampler(struct ntv_context *ctx, unsigned sampler_index, unsigned desc_set)
SpvId var_id = spirv_builder_emit_var(&ctx->builder, pointer_type,
SpvStorageClassUniformConstant);
char buf[128];
snprintf(buf, sizeof(buf), "sampler_%u", sampler_index);
snprintf(buf, sizeof(buf), "sampler_%u", var->data.driver_location);
spirv_builder_emit_name(&ctx->builder, var_id, buf);
spirv_builder_emit_descriptor_set(&ctx->builder, var_id, desc_set);
spirv_builder_emit_binding(&ctx->builder, var_id, sampler_index);
ctx->cl_samplers[sampler_index] = var_id;
spirv_builder_emit_descriptor_set(&ctx->builder, var_id, var->data.descriptor_set);
spirv_builder_emit_binding(&ctx->builder, var_id, var->data.driver_location);
_mesa_hash_table_insert(ctx->vars, var, (void *)(intptr_t)var_id);
if (ctx->spirv_1_4_interfaces) {
assert(ctx->num_entry_ifaces < ARRAY_SIZE(ctx->entry_ifaces));
ctx->entry_ifaces[ctx->num_entry_ifaces++] = var_id;
}
}
static SpvId
@ -3536,16 +3534,25 @@ tex_instr_is_lod_allowed(nir_tex_instr *tex)
tex->sampler_dim == GLSL_SAMPLER_DIM_RECT);
}
static void
static nir_variable *
get_tex_srcs(struct ntv_context *ctx, nir_tex_instr *tex,
nir_variable **bindless_var, unsigned *coord_components,
struct spriv_tex_src *tex_src)
{
tex_src->sparse = tex->is_sparse;
nir_variable *var = NULL;
nir_alu_type atype;
tex_src->sparse = tex->is_sparse;
for (unsigned i = 0; i < tex->num_srcs; i++) {
nir_const_value *cv;
switch (tex->src[i].src_type) {
case nir_tex_src_texture_deref:
var = nir_deref_instr_get_variable(nir_instr_as_deref(tex->src[i].src.ssa->parent_instr));
tex_src->src = get_src(ctx, &tex->src[i].src, &atype);
break;
case nir_tex_src_sampler_deref:
tex_src->cl_sampler = get_src(ctx, &tex->src[i].src, &atype);
break;
case nir_tex_src_coord:
if (tex->op == nir_texop_txf ||
tex->op == nir_texop_txf_ms)
@ -3639,8 +3646,8 @@ get_tex_srcs(struct ntv_context *ctx, nir_tex_instr *tex,
break;
case nir_tex_src_texture_handle:
tex_src->bindless = get_src(ctx, &tex->src[i].src, &atype);
*bindless_var = nir_deref_instr_get_variable(nir_src_as_deref(tex->src[i].src));
tex_src->src = get_src(ctx, &tex->src[i].src, &atype);
var = *bindless_var = nir_deref_instr_get_variable(nir_src_as_deref(tex->src[i].src));
break;
default:
@ -3648,44 +3655,18 @@ get_tex_srcs(struct ntv_context *ctx, nir_tex_instr *tex,
unreachable("unknown texture source");
}
}
}
static void
find_sampler_and_texture_index(struct ntv_context *ctx, struct spriv_tex_src *tex_src,
nir_variable *bindless_var,
nir_variable **var, uint32_t *texture_index)
{
*var = bindless_var ? bindless_var : ctx->sampler_var[*texture_index];
nir_variable **sampler_var = tex_src->bindless ? ctx->bindless_sampler_var : ctx->sampler_var;
if (!bindless_var && (!tex_src->tex_offset || !var)) {
if (sampler_var[*texture_index]) {
if (glsl_type_is_array(sampler_var[*texture_index]->type))
tex_src->tex_offset = emit_uint_const(ctx, 32, 0);
} else {
/* convert constant index back to base + offset */
for (int i = *texture_index; i >= 0; i--) {
if (sampler_var[i]) {
assert(glsl_type_is_array(sampler_var[i]->type));
if (!tex_src->tex_offset)
tex_src->tex_offset = emit_uint_const(ctx, 32, *texture_index - i);
*var = sampler_var[i];
*texture_index = i;
break;
}
}
}
}
return var;
}
static SpvId
get_texture_load(struct ntv_context *ctx, SpvId sampler_id, nir_tex_instr *tex,
SpvId image_type, SpvId sampled_type)
SpvId cl_sampler, SpvId image_type, SpvId sampled_type)
{
if (ctx->stage == MESA_SHADER_KERNEL) {
SpvId image_load = spirv_builder_emit_load(&ctx->builder, image_type, sampler_id);
if (nir_tex_instr_need_sampler(tex)) {
SpvId sampler_load = spirv_builder_emit_load(&ctx->builder, spirv_builder_type_sampler(&ctx->builder),
ctx->cl_samplers[tex->sampler_index]);
cl_sampler);
return spirv_builder_emit_sampled_image(&ctx->builder, sampled_type, image_load, sampler_load);
} else {
return image_load;
@ -3822,16 +3803,11 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
tex->op == nir_texop_tg4 ||
tex->op == nir_texop_texture_samples ||
tex->op == nir_texop_query_levels);
assert(tex->texture_index == tex->sampler_index || ctx->stage == MESA_SHADER_KERNEL);
struct spriv_tex_src tex_src = {0};
unsigned coord_components = 0;
nir_variable *bindless_var = NULL;
nir_variable *var = NULL;
uint32_t texture_index = tex->texture_index;
get_tex_srcs(ctx, tex, &bindless_var, &coord_components, &tex_src);
find_sampler_and_texture_index(ctx, &tex_src, bindless_var, &var, &texture_index);
nir_variable *var = get_tex_srcs(ctx, tex, &bindless_var, &coord_components, &tex_src);
assert(var);
SpvId image_type = find_image_type(ctx, var);
@ -3843,13 +3819,13 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
spirv_builder_type_sampled_image(&ctx->builder, image_type);
assert(sampled_type);
SpvId sampler_id = tex_src.bindless ? tex_src.bindless : ctx->samplers[texture_index];
SpvId sampler_id = tex_src.src;
if (tex_src.tex_offset) {
SpvId ptr = spirv_builder_type_pointer(&ctx->builder, SpvStorageClassUniformConstant, sampled_type);
sampler_id = spirv_builder_emit_access_chain(&ctx->builder, ptr, sampler_id, &tex_src.tex_offset, 1);
}
SpvId load = get_texture_load(ctx, sampler_id, tex, image_type, sampled_type);
SpvId load = get_texture_load(ctx, sampler_id, tex, tex_src.cl_sampler, image_type, sampled_type);
if (tex->is_sparse)
tex->def.num_components--;
@ -4034,10 +4010,8 @@ emit_deref_array(struct ntv_context *ctx, nir_deref_instr *deref)
case nir_var_uniform:
case nir_var_image: {
struct hash_entry *he = _mesa_hash_table_search(ctx->vars, var);
assert(he);
base = (SpvId)(intptr_t)he->data;
const struct glsl_type *gtype = glsl_without_array(var->type);
base = get_src(ctx, &deref->parent, &atype);
const struct glsl_type *gtype = glsl_without_array(deref->type);
type = get_image_type(ctx, var,
glsl_type_is_sampler(gtype),
glsl_get_sampler_dim(gtype) == GLSL_SAMPLER_DIM_BUF);
@ -4585,22 +4559,11 @@ nir_to_spirv(struct nir_shader *s, const struct zink_shader_info *sinfo, const s
ctx.last_sampler = MAX2(ctx.last_sampler, var->data.driver_location);
}
}
if (sinfo->sampler_mask) {
assert(s->info.stage == MESA_SHADER_KERNEL);
int desc_set = -1;
nir_foreach_variable_with_modes(var, s, nir_var_uniform) {
if (glsl_type_is_sampler(glsl_without_array(var->type))) {
desc_set = var->data.descriptor_set;
break;
}
}
assert(desc_set != -1);
u_foreach_bit(sampler, sinfo->sampler_mask)
emit_sampler(&ctx, sampler, desc_set);
}
nir_foreach_variable_with_modes(var, s, nir_var_image | nir_var_uniform) {
const struct glsl_type *type = glsl_without_array(var->type);
if (glsl_type_is_sampler(type))
if (glsl_type_is_bare_sampler(type))
emit_sampler(&ctx, var);
else if (glsl_type_is_sampler(type))
emit_image(&ctx, var, get_bare_image_type(&ctx, var, true));
else if (glsl_type_is_image(type))
emit_image(&ctx, var, get_bare_image_type(&ctx, var, false));

View file

@ -63,6 +63,8 @@ struct spirv_builder {
};
struct spriv_tex_src {
SpvId src;
SpvId cl_sampler;
SpvId coord;
SpvId proj;
SpvId bias;
@ -74,7 +76,6 @@ struct spriv_tex_src {
SpvId offset;
SpvId sample;
SpvId tex_offset;
SpvId bindless;
SpvId min_lod;
bool sparse;
};

View file

@ -1744,18 +1744,23 @@ lower_txf_lod_robustness_instr(nir_builder *b, nir_instr *in, void *data)
int offset_idx = nir_tex_instr_src_index(txf, nir_tex_src_texture_offset);
int handle_idx = nir_tex_instr_src_index(txf, nir_tex_src_texture_handle);
int deref_idx = nir_tex_instr_src_index(txf, nir_tex_src_texture_deref);
nir_tex_instr *levels = nir_tex_instr_create(b->shader,
!!(offset_idx >= 0) + !!(handle_idx >= 0));
1 + !!(offset_idx >= 0) + !!(handle_idx >= 0));
unsigned src_idx = 0;
levels->op = nir_texop_query_levels;
levels->texture_index = txf->texture_index;
levels->dest_type = nir_type_int | lod->bit_size;
if (deref_idx >= 0) {
levels->src[src_idx].src_type = nir_tex_src_texture_deref;
levels->src[src_idx++].src = nir_src_for_ssa(txf->src[deref_idx].src.ssa);
}
if (offset_idx >= 0) {
levels->src[0].src_type = nir_tex_src_texture_offset;
levels->src[0].src = nir_src_for_ssa(txf->src[offset_idx].src.ssa);
levels->src[src_idx].src_type = nir_tex_src_texture_offset;
levels->src[src_idx++].src = nir_src_for_ssa(txf->src[offset_idx].src.ssa);
}
if (handle_idx >= 0) {
levels->src[!!(offset_idx >= 0)].src_type = nir_tex_src_texture_handle;
levels->src[!!(offset_idx >= 0)].src = nir_src_for_ssa(txf->src[handle_idx].src.ssa);
levels->src[src_idx].src_type = nir_tex_src_texture_handle;
levels->src[src_idx++].src = nir_src_for_ssa(txf->src[handle_idx].src.ssa);
}
nir_def_init(&levels->instr, &levels->def,
nir_tex_instr_dest_size(levels), 32);
@ -3588,16 +3593,7 @@ lower_zs_swizzle_tex_instr(nir_builder *b, nir_instr *instr, void *data)
if (handle != -1)
/* gtfo bindless depth texture mode */
return false;
nir_foreach_variable_with_modes(img, b->shader, nir_var_uniform) {
if (glsl_type_is_sampler(glsl_without_array(img->type))) {
unsigned size = glsl_type_is_array(img->type) ? glsl_get_aoa_size(img->type) : 1;
if (tex->texture_index >= img->data.driver_location &&
tex->texture_index < img->data.driver_location + size) {
var = img;
break;
}
}
}
var = nir_deref_instr_get_variable(nir_instr_as_deref(tex->src[nir_tex_instr_src_index(tex, nir_tex_src_texture_deref)].src.ssa->parent_instr));
assert(var);
uint32_t sampler_id = var->data.binding - state->base_sampler_id;
const struct glsl_type *type = glsl_without_array(var->type);
@ -4407,15 +4403,11 @@ analyze_io(struct zink_shader *zs, nir_shader *shader)
if (shader->info.stage != MESA_SHADER_KERNEL && instr->type == nir_instr_type_tex) {
/* gl_nir_lower_samplers_as_deref is where this would normally be set, but zink doesn't use it */
nir_tex_instr *tex = nir_instr_as_tex(instr);
nir_foreach_variable_with_modes(img, shader, nir_var_uniform) {
if (glsl_type_is_sampler(glsl_without_array(img->type))) {
unsigned size = glsl_type_is_array(img->type) ? glsl_get_aoa_size(img->type) : 1;
if (tex->texture_index >= img->data.driver_location &&
tex->texture_index < img->data.driver_location + size) {
BITSET_SET_RANGE(shader->info.textures_used, img->data.driver_location, img->data.driver_location + (size - 1));
break;
}
}
int deref_idx = nir_tex_instr_src_index(tex, nir_tex_src_texture_deref);
if (deref_idx >= 0) {
nir_variable *img = nir_deref_instr_get_variable(nir_instr_as_deref(tex->src[deref_idx].src.ssa->parent_instr));
unsigned size = glsl_type_is_array(img->type) ? glsl_get_aoa_size(img->type) : 1;
BITSET_SET_RANGE(shader->info.textures_used, img->data.driver_location, img->data.driver_location + (size - 1));
}
continue;
}
@ -4769,8 +4761,10 @@ lower_1d_shadow(nir_shader *shader, struct zink_screen *screen)
found = true;
}
if (found)
if (found) {
nir_shader_instructions_pass(shader, convert_1d_shadow_tex, nir_metadata_dominance, screen);
nir_fixup_deref_types(shader);
}
return found;
}
@ -4871,17 +4865,7 @@ match_tex_dests_instr(nir_builder *b, nir_instr *in, void *data, bool pre)
return false;
var = nir_deref_instr_get_variable(nir_src_as_deref(tex->src[handle].src));
} else {
nir_foreach_variable_with_modes(img, b->shader, nir_var_uniform) {
if (glsl_type_is_sampler(glsl_without_array(img->type))) {
unsigned size = glsl_type_is_array(img->type) ? glsl_get_aoa_size(img->type) : 1;
int location = pre ? img->data.binding : img->data.driver_location;
if (tex->texture_index >= location &&
tex->texture_index < location + size) {
var = img;
break;
}
}
}
var = nir_deref_instr_get_variable(nir_instr_as_deref(tex->src[nir_tex_instr_src_index(tex, nir_tex_src_texture_deref)].src.ssa->parent_instr));
}
if (pre) {
flag_shadow_tex_instr(b, tex, var, data);
@ -5111,7 +5095,7 @@ type_image(nir_shader *nir, nir_variable *var)
}
static bool
type_sampler_vars(nir_shader *nir, unsigned *sampler_mask)
type_sampler_vars(nir_shader *nir)
{
bool progress = false;
nir_foreach_function_impl(impl, nir) {
@ -5120,9 +5104,7 @@ type_sampler_vars(nir_shader *nir, unsigned *sampler_mask)
if (instr->type != nir_instr_type_tex)
continue;
nir_tex_instr *tex = nir_instr_as_tex(instr);
if (nir_tex_instr_need_sampler(tex))
*sampler_mask |= BITFIELD_BIT(tex->sampler_index);
nir_variable *var = nir_find_sampler_variable_with_tex_index(nir, tex->texture_index);
nir_variable *var = nir_deref_instr_get_variable(nir_instr_as_deref(tex->src[nir_tex_instr_src_index(tex, nir_tex_src_texture_deref)].src.ssa->parent_instr));
assert(var);
if (glsl_get_sampler_result_type(glsl_without_array(var->type)) != GLSL_TYPE_VOID &&
nir_tex_instr_is_query(tex))
@ -5140,28 +5122,18 @@ type_sampler_vars(nir_shader *nir, unsigned *sampler_mask)
}
static bool
delete_samplers(nir_shader *nir)
type_images(nir_shader *nir)
{
bool progress = false;
nir_foreach_variable_with_modes(var, nir, nir_var_uniform) {
if (glsl_type_is_sampler(glsl_without_array(var->type))) {
var->data.mode = nir_var_shader_temp;
progress = true;
}
}
return progress;
}
static bool
type_images(nir_shader *nir, unsigned *sampler_mask)
{
bool progress = false;
progress |= delete_samplers(nir);
progress |= type_sampler_vars(nir, sampler_mask);
progress |= type_sampler_vars(nir);
nir_foreach_variable_with_modes(var, nir, nir_var_image) {
type_image(nir, var);
progress = true;
}
if (progress) {
nir_fixup_deref_types(nir);
nir_fixup_deref_modes(nir);
}
return progress;
}
@ -6160,6 +6132,35 @@ flatten_image_arrays(nir_shader *nir)
return progress;
}
static bool
bound_image_arrays_instr(struct nir_builder *b, nir_instr *instr, void *data)
{
if (instr->type != nir_instr_type_deref)
return false;
nir_deref_instr *deref = nir_instr_as_deref(instr);
if (deref->deref_type != nir_deref_type_array)
return false;
if (!nir_src_is_const(deref->arr.index))
return false;
nir_deref_instr *parent = nir_deref_instr_parent(deref);
int parent_size = glsl_array_size(parent->type);
unsigned idx = nir_src_as_uint(deref->arr.index);
if (idx >= parent_size) {
b->cursor = nir_before_instr(instr);
nir_src_rewrite(&deref->arr.index, nir_imm_zero(b, 1, 32));
return true;
}
return false;
}
static bool
bound_image_arrays(nir_shader *nir)
{
return nir_shader_instructions_pass(nir, bound_image_arrays_instr, nir_metadata_dominance, NULL);
}
struct zink_shader *
zink_shader_create(struct zink_screen *screen, struct nir_shader *nir)
{
@ -6232,8 +6233,9 @@ zink_shader_init(struct zink_screen *screen, struct zink_shader *zs)
}
NIR_PASS_V(nir, nir_lower_io_to_scalar, nir_var_shader_in | nir_var_shader_out, NULL, NULL);
NIR_PASS_V(nir, flatten_image_arrays);
optimize_nir(nir, NULL, true);
NIR_PASS_V(nir, bound_image_arrays);
NIR_PASS_V(nir, flatten_image_arrays);
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)) {
NIR_PASS_V(nir, lower_bindless_io);
@ -6317,19 +6319,8 @@ zink_shader_init(struct zink_screen *screen, struct zink_shader *zs)
optimize_nir(nir, NULL, true);
prune_io(nir);
unsigned sampler_mask = 0;
if (nir->info.stage == MESA_SHADER_KERNEL) {
NIR_PASS_V(nir, type_images, &sampler_mask);
enum zink_descriptor_type ztype = ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW;
VkDescriptorType vktype = VK_DESCRIPTOR_TYPE_SAMPLER;
u_foreach_bit(s, sampler_mask) {
zs->bindings[ztype][zs->num_bindings[ztype]].index = s;
zs->bindings[ztype][zs->num_bindings[ztype]].binding = zink_binding(MESA_SHADER_KERNEL, vktype, s, screen->compact_descriptors);
zs->bindings[ztype][zs->num_bindings[ztype]].type = vktype;
zs->bindings[ztype][zs->num_bindings[ztype]].size = 1;
zs->num_bindings[ztype]++;
}
zs->sinfo.sampler_mask = sampler_mask;
NIR_PASS_V(nir, type_images);
}
unsigned ubo_binding_mask = 0;
@ -6388,7 +6379,7 @@ zink_shader_init(struct zink_screen *screen, struct zink_shader *zs)
zs->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);
VkDescriptorType vktype = glsl_type_is_image(type) ? zink_image_type(type) : glsl_type_is_bare_sampler(type) ? VK_DESCRIPTOR_TYPE_SAMPLER : zink_sampler_type(type);
if (nir->info.stage == MESA_SHADER_KERNEL && vktype == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
vktype = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
ztype = zink_desc_type_from_vktype(vktype);

View file

@ -53,6 +53,7 @@ lower_cubemap_to_array_filter(const nir_instr *instr, const void *mask)
const uint32_t *nonseamless_cube_mask = mask;
if (instr->type == nir_instr_type_tex) {
nir_tex_instr *tex = nir_instr_as_tex(instr);
nir_variable *var = nir_deref_instr_get_variable(nir_instr_as_deref(tex->src[nir_tex_instr_src_index(tex, nir_tex_src_texture_deref)].src.ssa->parent_instr));
if (tex->sampler_dim != GLSL_SAMPLER_DIM_CUBE)
return false;
@ -69,7 +70,7 @@ lower_cubemap_to_array_filter(const nir_instr *instr, const void *mask)
default:
return false;
}
return (BITFIELD_BIT(tex->sampler_index) & (*nonseamless_cube_mask)) != 0;
return (BITFIELD_BIT(var->data.driver_location) & (*nonseamless_cube_mask)) != 0;
}
return false;
@ -387,24 +388,7 @@ lower_cube_coords(nir_builder *b, nir_def *coord, bool is_array)
static void
rewrite_cube_var_type(nir_builder *b, nir_tex_instr *tex)
{
unsigned index = tex->texture_index;
nir_variable *sampler = NULL;
int highest = -1;
nir_foreach_variable_with_modes(var, b->shader, nir_var_uniform) {
if (!glsl_type_is_sampler(glsl_without_array(var->type)))
continue;
unsigned size = glsl_type_is_array(var->type) ? glsl_get_length(var->type) : 1;
if (var->data.driver_location == index ||
(var->data.driver_location < index && var->data.driver_location + size > index)) {
sampler = var;
break;
}
/* handle array sampler access: use the next-closest sampler */
if (var->data.driver_location > highest && var->data.driver_location < index) {
highest = var->data.driver_location;
sampler = var;
}
}
nir_variable *sampler = nir_deref_instr_get_variable(nir_instr_as_deref(tex->src[nir_tex_instr_src_index(tex, nir_tex_src_texture_deref)].src.ssa->parent_instr));
assert(sampler);
sampler->type = make_2darray_from_cubemap_with_array(sampler->type);
}

View file

@ -626,6 +626,7 @@ zink_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_LOAD_CONSTBUF:
case PIPE_CAP_MULTISAMPLE_Z_RESOLVE:
case PIPE_CAP_ALLOW_GLTHREAD_BUFFER_SUBDATA_OPT:
case PIPE_CAP_NIR_SAMPLERS_AS_DEREF:
return 1;
case PIPE_CAP_DRAW_VERTEX_STATE: