microsoft/compiler: Better support UBO/SSBO references to descriptors

Previously UBOs only supported static indices, and SSBOs only
supported dynamic indices. UBO support for descriptors was added
as an alternative to static indices, but the logic for detecting
descriptors to SSBOs couldn't just differentiate on constants vs not.

Add a helper which can differentiate cleanly across the board and
handle pre-created handles from descriptors, or static/dynamic raw
indices.

Reviewed-by: Enrico Galli <enrico.galli@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10149>
This commit is contained in:
Jesse Natalie
2021-04-13 09:56:05 -07:00
committed by Marge Bot
parent d6b5aaaff8
commit 50d7e97c1d

View File

@@ -749,6 +749,43 @@ add_resource(struct ntd_context *ctx, enum dxil_resource_type type,
ctx->num_resources++;
}
static unsigned
get_resource_id(struct ntd_context *ctx, enum dxil_resource_class class,
unsigned space, unsigned binding)
{
unsigned offset = 0;
unsigned count = 0;
switch (class) {
case DXIL_RESOURCE_CLASS_UAV:
offset = ctx->num_srv_arrays + ctx->num_sampler_arrays + ctx->num_cbv_arrays;
count = ctx->num_uav_arrays;
break;
case DXIL_RESOURCE_CLASS_SRV:
offset = ctx->num_sampler_arrays + ctx->num_cbv_arrays;
count = ctx->num_srv_arrays;
break;
case DXIL_RESOURCE_CLASS_SAMPLER:
offset = ctx->num_cbv_arrays;
count = ctx->num_sampler_arrays;
break;
case DXIL_RESOURCE_CLASS_CBV:
offset = 0;
count = ctx->num_cbv_arrays;
break;
}
assert(offset + count <= ctx->num_resources);
for (unsigned i = offset; i < offset + count; ++i) {
if (ctx->resources[i].space == space &&
ctx->resources[i].lower_bound <= binding &&
ctx->resources[i].upper_bound >= binding) {
return i - offset;
}
}
unreachable("Resource access for undeclared range");
return 0;
}
static bool
emit_srv(struct ntd_context *ctx, nir_variable *var, unsigned binding, unsigned count)
{
@@ -2282,26 +2319,57 @@ emit_gep_for_index(struct ntd_context *ctx, const nir_variable *var,
return dxil_emit_gep_inbounds(&ctx->mod, ops, ARRAY_SIZE(ops));
}
static const struct dxil_value *
get_ubo_ssbo_handle(struct ntd_context *ctx, nir_src *src, enum dxil_resource_class class, unsigned base_binding)
{
assume(class == DXIL_RESOURCE_CLASS_CBV || class == DXIL_RESOURCE_CLASS_UAV);
/* This source might be one of:
* 1. Constant resource index - just look it up in precomputed handle arrays
* If it's null in that array, create a handle, and store the result
* 2. A handle from load_vulkan_descriptor - just get the stored SSA value
* 3. Dynamic resource index - create a handle for it here
*/
assert(src->ssa->num_components == 1 && src->ssa->bit_size == 32);
nir_const_value *const_block_index = nir_src_as_const_value(*src);
const struct dxil_value **handle_entry = NULL;
if (const_block_index) {
if (class == DXIL_RESOURCE_CLASS_CBV)
handle_entry = &ctx->cbv_handles[const_block_index->u32];
else
handle_entry = &ctx->uav_handles[const_block_index->u32];
}
if (handle_entry && *handle_entry)
return *handle_entry;
const struct dxil_value *value = get_src_ssa(ctx, src->ssa, 0);
if (ctx->opts->vulkan_environment) {
return value;
}
const struct dxil_value *handle = emit_createhandle_call(ctx, class,
get_resource_id(ctx, class, 0, base_binding), value, !const_block_index);
if (handle_entry)
*handle_entry = handle;
return handle;
}
static bool
emit_load_ssbo(struct ntd_context *ctx, nir_intrinsic_instr *intr)
{
const struct dxil_value *int32_undef = get_int32_undef(&ctx->mod);
const struct dxil_value *buffer =
get_src(ctx, &intr->src[0], 0, nir_type_uint);
const struct dxil_value *handle = get_ubo_ssbo_handle(ctx, &intr->src[0], DXIL_RESOURCE_CLASS_UAV, 0);
const struct dxil_value *offset =
get_src(ctx, &intr->src[1], 0, nir_type_uint);
if (!int32_undef || !buffer || !offset)
if (!int32_undef || !handle || !offset)
return false;
assert(nir_src_bit_size(intr->src[0]) == 32);
assert(nir_intrinsic_dest_components(intr) <= 4);
const struct dxil_value *handle =
emit_createhandle_call(ctx, DXIL_RESOURCE_CLASS_UAV, 0, buffer,
nir_src_is_const(intr->src[0]));
if (!handle)
return false;
const struct dxil_value *coord[2] = {
offset,
int32_undef
@@ -2324,17 +2392,10 @@ emit_load_ssbo(struct ntd_context *ctx, nir_intrinsic_instr *intr)
static bool
emit_store_ssbo(struct ntd_context *ctx, nir_intrinsic_instr *intr)
{
const struct dxil_value *buffer =
get_src(ctx, &intr->src[1], 0, nir_type_uint);
const struct dxil_value* handle = get_ubo_ssbo_handle(ctx, &intr->src[1], DXIL_RESOURCE_CLASS_UAV, 0);
const struct dxil_value *offset =
get_src(ctx, &intr->src[2], 0, nir_type_uint);
if (!buffer || !offset)
return false;
const struct dxil_value *handle =
emit_createhandle_call(ctx, DXIL_RESOURCE_CLASS_UAV, 0, buffer,
nir_src_is_const(intr->src[1]));
if (!handle)
if (!handle || !offset)
return false;
assert(nir_src_bit_size(intr->src[0]) == 32);
@@ -2374,17 +2435,10 @@ emit_store_ssbo_masked(struct ntd_context *ctx, nir_intrinsic_instr *intr)
get_src(ctx, &intr->src[0], 0, nir_type_uint);
const struct dxil_value *mask =
get_src(ctx, &intr->src[1], 0, nir_type_uint);
const struct dxil_value *buffer =
get_src(ctx, &intr->src[2], 0, nir_type_uint);
const struct dxil_value* handle = get_ubo_ssbo_handle(ctx, &intr->src[2], DXIL_RESOURCE_CLASS_UAV, 0);
const struct dxil_value *offset =
get_src(ctx, &intr->src[3], 0, nir_type_uint);
if (!value || !mask || !buffer || !offset)
return false;
const struct dxil_value *handle =
emit_createhandle_call(ctx, DXIL_RESOURCE_CLASS_UAV, 0, buffer,
nir_src_is_const(intr->src[2]));
if (!handle)
if (!value || !mask || !handle || !offset)
return false;
const struct dxil_value *int32_undef = get_int32_undef(&ctx->mod);
@@ -2482,16 +2536,10 @@ emit_store_scratch(struct ntd_context *ctx, nir_intrinsic_instr *intr)
static bool
emit_load_ubo(struct ntd_context *ctx, nir_intrinsic_instr *intr)
{
const struct dxil_value* handle = NULL;
nir_const_value* const_block_index = nir_src_as_const_value(intr->src[0]);
if (const_block_index) {
handle = ctx->cbv_handles[const_block_index->u32];
} else {
assert(nir_src_num_components(intr->src[0]) == 1);
handle = get_src_ssa(ctx, intr->src[0].ssa, 0);
}
const struct dxil_value* handle = get_ubo_ssbo_handle(ctx, &intr->src[0], DXIL_RESOURCE_CLASS_CBV, 0);
if (!handle)
return false;
assert(handle);
const struct dxil_value *offset;
nir_const_value *const_offset = nir_src_as_const_value(intr->src[1]);
if (const_offset) {
@@ -2521,17 +2569,7 @@ emit_load_ubo_dxil(struct ntd_context *ctx, nir_intrinsic_instr *intr)
assert(nir_dest_num_components(intr->dest) <= 4);
assert(nir_dest_bit_size(intr->dest) == 32);
nir_const_value *index = nir_src_as_const_value(intr->src[0]);
const struct dxil_value* handle = NULL;
if (index) {
assert(index && index->u32 < ARRAY_SIZE(ctx->cbv_handles));
handle = ctx->cbv_handles[index->u32];
} else {
assert(nir_src_num_components(intr->src[0]) == 1);
handle = get_src_ssa(ctx, intr->src[0].ssa, 0);
}
const struct dxil_value* handle = get_ubo_ssbo_handle(ctx, &intr->src[0], DXIL_RESOURCE_CLASS_CBV, 0);
const struct dxil_value *offset =
get_src(ctx, &intr->src[1], 0, nir_type_uint);
@@ -3065,20 +3103,13 @@ static bool
emit_ssbo_atomic(struct ntd_context *ctx, nir_intrinsic_instr *intr,
enum dxil_atomic_op op, nir_alu_type type)
{
const struct dxil_value *buffer =
get_src(ctx, &intr->src[0], 0, nir_type_uint);
const struct dxil_value* handle = get_ubo_ssbo_handle(ctx, &intr->src[0], DXIL_RESOURCE_CLASS_UAV, 0);
const struct dxil_value *offset =
get_src(ctx, &intr->src[1], 0, nir_type_uint);
const struct dxil_value *value =
get_src(ctx, &intr->src[2], 0, type);
if (!value || !buffer || !offset)
return false;
const struct dxil_value *handle =
emit_createhandle_call(ctx, DXIL_RESOURCE_CLASS_UAV, 0, buffer,
nir_src_is_const(intr->src[0]));
if (!handle)
if (!value || !handle || !offset)
return false;
const struct dxil_value *int32_undef = get_int32_undef(&ctx->mod);
@@ -3102,8 +3133,7 @@ emit_ssbo_atomic(struct ntd_context *ctx, nir_intrinsic_instr *intr,
static bool
emit_ssbo_atomic_comp_swap(struct ntd_context *ctx, nir_intrinsic_instr *intr)
{
const struct dxil_value *buffer =
get_src(ctx, &intr->src[0], 0, nir_type_uint);
const struct dxil_value* handle = get_ubo_ssbo_handle(ctx, &intr->src[0], DXIL_RESOURCE_CLASS_UAV, 0);
const struct dxil_value *offset =
get_src(ctx, &intr->src[1], 0, nir_type_uint);
const struct dxil_value *cmpval =
@@ -3111,13 +3141,7 @@ emit_ssbo_atomic_comp_swap(struct ntd_context *ctx, nir_intrinsic_instr *intr)
const struct dxil_value *newval =
get_src(ctx, &intr->src[3], 0, nir_type_int);
if (!cmpval || !newval || !buffer || !offset)
return false;
const struct dxil_value *handle =
emit_createhandle_call(ctx, DXIL_RESOURCE_CLASS_UAV, 0, buffer,
nir_src_is_const(intr->src[0]));
if (!handle)
if (!cmpval || !newval || !handle || !offset)
return false;
const struct dxil_value *int32_undef = get_int32_undef(&ctx->mod);
@@ -3269,7 +3293,7 @@ emit_load_vulkan_descriptor(struct ntd_context *ctx, nir_intrinsic_instr *intr)
handle = *handle_entry;
if (!handle || !const_index) {
handle = emit_createhandle_call(ctx, resource_class,
0,
get_resource_id(ctx, resource_class, 0, binding),
get_src(ctx, &intr->src[0], 0, nir_type_uint32), false);
if (const_index)
*handle_entry = handle;