microsoft/compiler: Implement new double pack/unpack alu ops

MakeDouble is pretty straightforward, but SplitDouble is interesting
since it returns a unique 2-element struct.

Reviewed-by: Enrico Galli <enrico.galli@intel.com>
This commit is contained in:
Jesse Natalie 2021-04-06 10:46:21 -07:00
parent 79fc0fbdbf
commit 11151340f4
5 changed files with 81 additions and 0 deletions

View file

@ -69,6 +69,8 @@ static struct predefined_func_descr predefined_funcs[] = {
{"dx.op.primitiveID", "i", "i", DXIL_ATTR_KIND_READ_NONE},
{"dx.op.legacyF16ToF32", "f", "ii", DXIL_ATTR_KIND_READ_ONLY},
{"dx.op.legacyF32ToF16", "i", "if", DXIL_ATTR_KIND_READ_ONLY},
{"dx.op.makeDouble", "g", "iii", DXIL_ATTR_KIND_READ_NONE},
{"dx.op.splitDouble", "G", "ig", DXIL_ATTR_KIND_READ_NONE},
};
struct func_descr {
@ -171,6 +173,7 @@ get_type_from_string(struct dxil_module *mod, const char *param_descr,
case DXIL_FUNC_PARAM_RESRET: return dxil_module_get_resret_type(mod, overload);
case DXIL_FUNC_PARAM_DIM: return dxil_module_get_dimret_type(mod);
case DXIL_FUNC_PARAM_CBUF_RET: return dxil_module_get_cbuf_ret_type(mod, overload);
case DXIL_FUNC_PARAM_SPLIT_DOUBLE: return dxil_module_get_split_double_ret_type(mod);
case DXIL_FUNC_PARAM_POINTER: {
const struct dxil_type *target = get_type_from_string(mod, param_descr, overload, idx);
return dxil_module_get_pointer_type(mod, target);

View file

@ -40,6 +40,7 @@
#define DXIL_FUNC_PARAM_RESRET 'R'
#define DXIL_FUNC_PARAM_CBUF_RET 'B'
#define DXIL_FUNC_PARAM_DIM 'D'
#define DXIL_FUNC_PARAM_SPLIT_DOUBLE 'G'
#include "dxil_module.h"
#include "util/rb_tree.h"

View file

@ -728,6 +728,15 @@ dxil_module_get_cbuf_ret_type(struct dxil_module *mod, enum overload_type overlo
return dxil_module_get_struct_type(mod, name, fields, num_fields);
}
const struct dxil_type *
dxil_module_get_split_double_ret_type(struct dxil_module *mod)
{
const struct dxil_type *int32_type = dxil_module_get_int_type(mod, 32);
const struct dxil_type *fields[2] = { int32_type, int32_type };
return dxil_module_get_struct_type(mod, "dx.types.splitDouble", fields, 2);
}
static const struct dxil_type *
dxil_module_get_type_from_comp_type(struct dxil_module *m, enum dxil_component_type comp_type)
{

View file

@ -263,6 +263,9 @@ dxil_module_get_handle_type(struct dxil_module *m);
const struct dxil_type *
dxil_module_get_cbuf_ret_type(struct dxil_module *mod, enum overload_type overload);
const struct dxil_type *
dxil_module_get_split_double_ret_type(struct dxil_module *mod);
const struct dxil_type *
dxil_module_get_res_type(struct dxil_module *m, enum dxil_resource_kind kind,
enum dxil_component_type comp_type, bool readwrite);

View file

@ -250,6 +250,9 @@ enum dxil_intr {
DXIL_INTR_EMIT_STREAM = 97,
DXIL_INTR_CUT_STREAM = 98,
DXIL_INTR_MAKE_DOUBLE = 101,
DXIL_INTR_SPLIT_DOUBLE = 102,
DXIL_INTR_PRIMITIVE_ID = 108,
DXIL_INTR_LEGACY_F32TOF16 = 130,
@ -1859,6 +1862,64 @@ emit_vec(struct ntd_context *ctx, nir_alu_instr *alu, unsigned num_inputs)
return true;
}
static bool
emit_make_double(struct ntd_context *ctx, nir_alu_instr *alu)
{
const struct dxil_func *func = dxil_get_function(&ctx->mod, "dx.op.makeDouble", DXIL_F64);
if (!func)
return false;
const struct dxil_value *opcode = dxil_module_get_int32_const(&ctx->mod, DXIL_INTR_MAKE_DOUBLE);
if (!opcode)
return false;
const struct dxil_value *args[3] = {
opcode,
get_src(ctx, &alu->src[0].src, 0, nir_type_uint32),
get_src(ctx, &alu->src[0].src, 1, nir_type_uint32),
};
if (!args[1] || !args[2])
return false;
const struct dxil_value *v = dxil_emit_call(&ctx->mod, func, args, ARRAY_SIZE(args));
if (!v)
return false;
store_alu_dest(ctx, alu, 0, v);
return true;
}
static bool
emit_split_double(struct ntd_context *ctx, nir_alu_instr *alu)
{
const struct dxil_func *func = dxil_get_function(&ctx->mod, "dx.op.splitDouble", DXIL_F64);
if (!func)
return false;
const struct dxil_value *opcode = dxil_module_get_int32_const(&ctx->mod, DXIL_INTR_SPLIT_DOUBLE);
if (!opcode)
return false;
const struct dxil_value *args[] = {
opcode,
get_alu_src(ctx, alu, 0)
};
if (!args[1])
return false;
const struct dxil_value *v = dxil_emit_call(&ctx->mod, func, args, ARRAY_SIZE(args));
if (!v)
return false;
const struct dxil_value *hi = dxil_emit_extractval(&ctx->mod, v, 0);
const struct dxil_value *lo = dxil_emit_extractval(&ctx->mod, v, 1);
if (!hi || !lo)
return false;
store_dest_value(ctx, &alu->dest.dest, 0, hi);
store_dest_value(ctx, &alu->dest.dest, 1, lo);
return true;
}
static bool
emit_alu(struct ntd_context *ctx, nir_alu_instr *alu)
{
@ -1878,6 +1939,10 @@ emit_alu(struct ntd_context *ctx, nir_alu_instr *alu)
alu->src->src.ssa, alu->src->swizzle[0]));
return true;
}
case nir_op_pack_double_2x32_dxil:
return emit_make_double(ctx, alu);
case nir_op_unpack_double_2x32_dxil:
return emit_split_double(ctx, alu);
default:
/* silence warnings */
;