From 0f56fc09d92a3ea8a3c335045ae030ebde2fb511 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Wed, 1 Feb 2023 10:57:30 -0800 Subject: [PATCH] microsoft/compiler: Support raw buffer load/store intrinsics with 16bit alignment Part-of: --- src/microsoft/compiler/dxil_function.c | 2 + src/microsoft/compiler/dxil_module.c | 2 + src/microsoft/compiler/nir_to_dxil.c | 78 ++++++++++++++++++++++++-- 3 files changed, 77 insertions(+), 5 deletions(-) diff --git a/src/microsoft/compiler/dxil_function.c b/src/microsoft/compiler/dxil_function.c index b79b96973be..8320ce4decb 100644 --- a/src/microsoft/compiler/dxil_function.c +++ b/src/microsoft/compiler/dxil_function.c @@ -51,7 +51,9 @@ static struct predefined_func_descr predefined_funcs[] = { {"dx.op.isSpecialFloat", "b", "iO", DXIL_ATTR_KIND_READ_NONE}, {"dx.op.binary", "O", "iOO", DXIL_ATTR_KIND_READ_NONE}, {"dx.op.bufferStore", "v", "i@iiOOOOc", DXIL_ATTR_KIND_NONE}, +{"dx.op.rawBufferStore", "v", "i@iiOOOOci", DXIL_ATTR_KIND_NONE}, {"dx.op.bufferLoad", "R", "i@ii", DXIL_ATTR_KIND_READ_ONLY}, +{"dx.op.rawBufferLoad", "R", "i@iici", DXIL_ATTR_KIND_READ_ONLY}, {"dx.op.attributeAtVertex", "O", "iiicc", DXIL_ATTR_KIND_READ_NONE}, {"dx.op.sample", "R", "i@@ffffiiif", DXIL_ATTR_KIND_READ_ONLY}, {"dx.op.sampleBias", "R", "i@@ffffiiiff", DXIL_ATTR_KIND_READ_ONLY}, diff --git a/src/microsoft/compiler/dxil_module.c b/src/microsoft/compiler/dxil_module.c index e58881cffe1..d6e61a94ee4 100644 --- a/src/microsoft/compiler/dxil_module.c +++ b/src/microsoft/compiler/dxil_module.c @@ -855,8 +855,10 @@ dxil_module_get_resret_type(struct dxil_module *m, enum overload_type overload) { overload_type, overload_type, overload_type, overload_type, int32_type }; switch (overload) { + case DXIL_I16: name = "dx.types.ResRet.i16"; break; case DXIL_I32: name = "dx.types.ResRet.i32"; break; case DXIL_I64: name = "dx.types.ResRet.i64"; break; + case DXIL_F16: name = "dx.types.ResRet.f16"; break; case DXIL_F32: name = "dx.types.ResRet.f32"; break; case DXIL_F64: name = "dx.types.ResRet.f64"; break; default: diff --git a/src/microsoft/compiler/nir_to_dxil.c b/src/microsoft/compiler/nir_to_dxil.c index 8e303a83ac8..a066f66e02a 100644 --- a/src/microsoft/compiler/nir_to_dxil.c +++ b/src/microsoft/compiler/nir_to_dxil.c @@ -348,6 +348,9 @@ enum dxil_intr { DXIL_INTR_ATTRIBUTE_AT_VERTEX = 137, DXIL_INTR_VIEW_ID = 138, + DXIL_INTR_RAW_BUFFER_LOAD = 139, + DXIL_INTR_RAW_BUFFER_STORE = 140, + DXIL_INTR_ANNOTATE_HANDLE = 216, DXIL_INTR_CREATE_HANDLE_FROM_BINDING = 217, @@ -728,6 +731,29 @@ emit_groupid_call(struct ntd_context *ctx, const struct dxil_value *comp) return dxil_emit_call(&ctx->mod, func, args, ARRAY_SIZE(args)); } +static const struct dxil_value * +emit_raw_bufferload_call(struct ntd_context *ctx, + const struct dxil_value *handle, + const struct dxil_value *coord[2], + enum overload_type overload, + unsigned component_count, + unsigned alignment) +{ + const struct dxil_func *func = dxil_get_function(&ctx->mod, "dx.op.rawBufferLoad", overload); + if (!func) + return NULL; + + const struct dxil_value *opcode = dxil_module_get_int32_const(&ctx->mod, + DXIL_INTR_RAW_BUFFER_LOAD); + const struct dxil_value *args[] = { + opcode, handle, coord[0], coord[1], + dxil_module_get_int8_const(&ctx->mod, (1 << component_count) - 1), + dxil_module_get_int32_const(&ctx->mod, alignment), + }; + + return dxil_emit_call(&ctx->mod, func, args, ARRAY_SIZE(args)); +} + static const struct dxil_value * emit_bufferload_call(struct ntd_context *ctx, const struct dxil_value *handle, @@ -745,6 +771,33 @@ emit_bufferload_call(struct ntd_context *ctx, return dxil_emit_call(&ctx->mod, func, args, ARRAY_SIZE(args)); } +static bool +emit_raw_bufferstore_call(struct ntd_context *ctx, + const struct dxil_value *handle, + const struct dxil_value *coord[2], + const struct dxil_value *value[4], + const struct dxil_value *write_mask, + enum overload_type overload, + unsigned alignment) +{ + const struct dxil_func *func = dxil_get_function(&ctx->mod, "dx.op.rawBufferStore", overload); + + if (!func) + return false; + + const struct dxil_value *opcode = dxil_module_get_int32_const(&ctx->mod, + DXIL_INTR_RAW_BUFFER_STORE); + const struct dxil_value *args[] = { + opcode, handle, coord[0], coord[1], + value[0], value[1], value[2], value[3], + write_mask, + dxil_module_get_int32_const(&ctx->mod, alignment), + }; + + return dxil_emit_call_void(&ctx->mod, func, + args, ARRAY_SIZE(args)); +} + static bool emit_bufferstore_call(struct ntd_context *ctx, const struct dxil_value *handle, @@ -3149,7 +3202,12 @@ emit_load_ssbo(struct ntd_context *ctx, nir_intrinsic_instr *intr) int32_undef }; - const struct dxil_value *load = emit_bufferload_call(ctx, handle, coord, DXIL_I32); + const struct dxil_value *load = ctx->mod.minor_version >= 2 ? + emit_raw_bufferload_call(ctx, handle, coord, + get_overload(nir_type_uint, nir_dest_bit_size(intr->dest)), + nir_intrinsic_dest_components(intr), + nir_intrinsic_align(intr)) : + emit_bufferload_call(ctx, handle, coord, get_overload(nir_type_uint, nir_dest_bit_size(intr->dest))); if (!load) return false; @@ -3172,7 +3230,6 @@ emit_store_ssbo(struct ntd_context *ctx, nir_intrinsic_instr *intr) if (!handle || !offset) return false; - assert(nir_src_bit_size(intr->src[0]) == 32); unsigned num_components = nir_src_num_components(intr->src[0]); assert(num_components <= 4); const struct dxil_value *value[4]; @@ -3191,15 +3248,26 @@ emit_store_ssbo(struct ntd_context *ctx, nir_intrinsic_instr *intr) int32_undef }; - for (int i = num_components; i < 4; ++i) - value[i] = int32_undef; + unsigned bit_size = nir_src_bit_size(intr->src[0]); + enum overload_type overload = get_overload(nir_type_uint, bit_size); + if (num_components < 4) { + const struct dxil_type *value_undef_type = dxil_module_get_int_type(&ctx->mod, bit_size); + const struct dxil_value *value_undef = dxil_module_get_undef(&ctx->mod, value_undef_type); + if (!value_undef) + return false; + + for (int i = num_components; i < 4; ++i) + value[i] = value_undef; + } const struct dxil_value *write_mask = dxil_module_get_int8_const(&ctx->mod, (1u << num_components) - 1); if (!write_mask) return false; - return emit_bufferstore_call(ctx, handle, coord, value, write_mask, DXIL_I32); + return ctx->mod.minor_version >= 2 ? + emit_raw_bufferstore_call(ctx, handle, coord, value, write_mask, overload, nir_intrinsic_align(intr)) : + emit_bufferstore_call(ctx, handle, coord, value, write_mask, overload); } static bool