zink: handle global and scratch vars

also delete cs pushconst since that was for clover and I don't care anymore

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19044>
This commit is contained in:
Mike Blumenkrantz
2022-10-11 21:53:49 -04:00
parent 19a74229c9
commit ddc5c30489
2 changed files with 126 additions and 17 deletions

View File

@@ -89,6 +89,7 @@ struct ntv_context {
SpvId loop_break, loop_cont;
SpvId shared_block_var[5]; //8, 16, 32, unused, 64
SpvId scratch_block_var[5]; //8, 16, 32, unused, 64
SpvId front_face_var, instance_id_var, vertex_id_var,
primitive_id_var, invocation_id_var, // geometry
@@ -500,6 +501,34 @@ get_glsl_type(struct ntv_context *ctx, const struct glsl_type *type)
return ret;
}
static void
create_scratch_block(struct ntv_context *ctx, unsigned scratch_size, unsigned bit_size)
{
unsigned idx = bit_size >> 4;
SpvId type = spirv_builder_type_uint(&ctx->builder, bit_size);
unsigned block_size = scratch_size / (bit_size / 8);
assert(block_size);
SpvId array = spirv_builder_type_array(&ctx->builder, type, emit_uint_const(ctx, 32, block_size));
spirv_builder_emit_array_stride(&ctx->builder, array, bit_size / 8);
SpvId ptr_type = spirv_builder_type_pointer(&ctx->builder,
SpvStorageClassPrivate,
array);
ctx->scratch_block_var[idx] = spirv_builder_emit_var(&ctx->builder, ptr_type, SpvStorageClassPrivate);
if (ctx->spirv_1_4_interfaces) {
assert(ctx->num_entry_ifaces < ARRAY_SIZE(ctx->entry_ifaces));
ctx->entry_ifaces[ctx->num_entry_ifaces++] = ctx->scratch_block_var[idx];
}
}
static SpvId
get_scratch_block(struct ntv_context *ctx, unsigned bit_size)
{
unsigned idx = bit_size >> 4;
if (!ctx->scratch_block_var[idx])
create_scratch_block(ctx, ctx->nir->scratch_size, bit_size);
return ctx->scratch_block_var[idx];
}
static void
create_shared_block(struct ntv_context *ctx, unsigned shared_size, unsigned bit_size)
{
@@ -2519,6 +2548,59 @@ emit_store_shared(struct ntv_context *ctx, nir_intrinsic_instr *intr)
}
}
static void
emit_load_scratch(struct ntv_context *ctx, nir_intrinsic_instr *intr)
{
SpvId dest_type = get_dest_type(ctx, &intr->dest, nir_type_uint);
unsigned num_components = nir_dest_num_components(intr->dest);
unsigned bit_size = nir_dest_bit_size(intr->dest);
SpvId uint_type = get_uvec_type(ctx, bit_size, 1);
SpvId ptr_type = spirv_builder_type_pointer(&ctx->builder,
SpvStorageClassPrivate,
uint_type);
SpvId offset = get_src(ctx, &intr->src[0]);
SpvId constituents[NIR_MAX_VEC_COMPONENTS];
SpvId scratch_block = get_scratch_block(ctx, bit_size);
/* need to convert array -> vec */
for (unsigned i = 0; i < num_components; i++) {
SpvId member = spirv_builder_emit_access_chain(&ctx->builder, ptr_type,
scratch_block, &offset, 1);
constituents[i] = spirv_builder_emit_load(&ctx->builder, uint_type, member);
offset = emit_binop(ctx, SpvOpIAdd, spirv_builder_type_uint(&ctx->builder, 32), offset, emit_uint_const(ctx, 32, 1));
}
SpvId result;
if (num_components > 1)
result = spirv_builder_emit_composite_construct(&ctx->builder, dest_type, constituents, num_components);
else
result = bitcast_to_uvec(ctx, constituents[0], bit_size, num_components);
store_dest(ctx, &intr->dest, result, nir_type_uint);
}
static void
emit_store_scratch(struct ntv_context *ctx, nir_intrinsic_instr *intr)
{
SpvId src = get_src(ctx, &intr->src[0]);
unsigned wrmask = nir_intrinsic_write_mask(intr);
unsigned bit_size = nir_src_bit_size(intr->src[0]);
SpvId uint_type = get_uvec_type(ctx, bit_size, 1);
SpvId ptr_type = spirv_builder_type_pointer(&ctx->builder,
SpvStorageClassPrivate,
uint_type);
SpvId offset = get_src(ctx, &intr->src[1]);
SpvId scratch_block = get_scratch_block(ctx, bit_size);
/* this is a partial write, so we have to loop and do a per-component write */
u_foreach_bit(i, wrmask) {
SpvId scratch_offset = emit_binop(ctx, SpvOpIAdd, spirv_builder_type_uint(&ctx->builder, 32), offset, emit_uint_const(ctx, 32, i));
SpvId val = src;
if (nir_src_num_components(intr->src[0]) != 1)
val = spirv_builder_emit_composite_extract(&ctx->builder, uint_type, src, &i, 1);
SpvId member = spirv_builder_emit_access_chain(&ctx->builder, ptr_type,
scratch_block, &scratch_offset, 1);
spirv_builder_emit_store(&ctx->builder, member, val);
}
}
static void
emit_load_push_const(struct ntv_context *ctx, nir_intrinsic_instr *intr)
{
@@ -2572,6 +2654,33 @@ emit_load_push_const(struct ntv_context *ctx, nir_intrinsic_instr *intr)
store_dest(ctx, &intr->dest, result, nir_type_uint);
}
static void
emit_load_global(struct ntv_context *ctx, nir_intrinsic_instr *intr)
{
spirv_builder_emit_cap(&ctx->builder, SpvCapabilityPhysicalStorageBufferAddresses);
SpvId dest_type = get_dest_type(ctx, &intr->dest, nir_type_uint);
SpvId pointer_type = spirv_builder_type_pointer(&ctx->builder,
SpvStorageClassPhysicalStorageBuffer,
dest_type);
SpvId ptr = emit_bitcast(ctx, pointer_type, get_src(ctx, &intr->src[0]));
SpvId result = spirv_builder_emit_load(&ctx->builder, dest_type, ptr);
store_dest(ctx, &intr->dest, result, nir_type_uint);
}
static void
emit_store_global(struct ntv_context *ctx, nir_intrinsic_instr *intr)
{
spirv_builder_emit_cap(&ctx->builder, SpvCapabilityPhysicalStorageBufferAddresses);
unsigned bit_size = nir_src_bit_size(intr->src[0]);
SpvId dest_type = get_uvec_type(ctx, bit_size, 1);
SpvId pointer_type = spirv_builder_type_pointer(&ctx->builder,
SpvStorageClassPhysicalStorageBuffer,
dest_type);
SpvId param = get_src(ctx, &intr->src[0]);
SpvId ptr = emit_bitcast(ctx, pointer_type, get_src(ctx, &intr->src[1]));
spirv_builder_emit_store(&ctx->builder, ptr, param);
}
static SpvId
create_builtin_var(struct ntv_context *ctx, SpvId var_type,
SpvStorageClass storage_class,
@@ -3093,6 +3202,14 @@ emit_intrinsic(struct ntv_context *ctx, nir_intrinsic_instr *intr)
emit_load_push_const(ctx, intr);
break;
case nir_intrinsic_load_global:
emit_load_global(ctx, intr);
break;
case nir_intrinsic_store_global:
emit_store_global(ctx, intr);
break;
case nir_intrinsic_load_front_face:
emit_load_front_face(ctx, intr);
break;
@@ -3361,6 +3478,14 @@ emit_intrinsic(struct ntv_context *ctx, nir_intrinsic_instr *intr)
emit_store_shared(ctx, intr);
break;
case nir_intrinsic_load_scratch:
emit_load_scratch(ctx, intr);
break;
case nir_intrinsic_store_scratch:
emit_store_scratch(ctx, intr);
break;
case nir_intrinsic_shader_clock:
emit_shader_clock(ctx, intr);
break;
@@ -4297,7 +4422,7 @@ nir_to_spirv(struct nir_shader *s, const struct zink_shader_info *sinfo, uint32_
if (s->info.cs.ptr_size == 32)
model = SpvAddressingModelPhysical32;
else if (s->info.cs.ptr_size == 64)
model = SpvAddressingModelPhysical64;
model = SpvAddressingModelPhysicalStorageBuffer64;
else
model = SpvAddressingModelLogical;
spirv_builder_emit_mem_model(&ctx.builder, model,

View File

@@ -62,20 +62,6 @@ create_vs_pushconst(nir_shader *nir)
vs_pushconst->data.location = INT_MAX; //doesn't really matter
}
static void
create_cs_pushconst(nir_shader *nir)
{
nir_variable *cs_pushconst;
/* create compatible layout for the ntv push constant loader */
struct glsl_struct_field *fields = rzalloc_size(nir, 1 * sizeof(struct glsl_struct_field));
fields[0].type = glsl_array_type(glsl_uint_type(), 1, 0);
fields[0].name = ralloc_asprintf(nir, "work_dim");
fields[0].offset = 0;
cs_pushconst = nir_variable_create(nir, nir_var_mem_push_const,
glsl_struct_type(fields, 1, "struct", false), "cs_pushconst");
cs_pushconst->data.location = INT_MAX; //doesn't really matter
}
static bool
reads_work_dim(nir_shader *shader)
{
@@ -3155,8 +3141,6 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
else if (nir->info.stage == MESA_SHADER_TESS_CTRL ||
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)
create_cs_pushconst(nir);
if (nir->info.stage < MESA_SHADER_FRAGMENT)
have_psiz = check_psiz(nir);