diff options
author | Ian Romanick <ian.d.romanick@intel.com> | 2017-09-29 20:20:55 -0700 |
---|---|---|
committer | Ian Romanick <ian.d.romanick@intel.com> | 2018-03-29 14:16:13 -0700 |
commit | b362ba03cfa50d113a6e130400ef617d64c6374b (patch) | |
tree | 96ce8ef3fd853fe1c261e2f1f6a2d97e40396168 | |
parent | ee7701a3805a235dc6f0213ea311eb5954aeb912 (diff) |
WIP: glsl/spirv: Emit expressions
-rw-r--r-- | src/compiler/glsl/spirv_expression_visitor_cpp.py | 142 | ||||
-rw-r--r-- | src/compiler/glsl/tests/emit_spirv_expression_test.cpp | 277 | ||||
-rw-r--r-- | src/compiler/glsl/tests/validate_spirv.cpp | 40 |
3 files changed, 457 insertions, 2 deletions
diff --git a/src/compiler/glsl/spirv_expression_visitor_cpp.py b/src/compiler/glsl/spirv_expression_visitor_cpp.py index 0bf1b44d58f..5bd0dfe3e66 100644 --- a/src/compiler/glsl/spirv_expression_visitor_cpp.py +++ b/src/compiler/glsl/spirv_expression_visitor_cpp.py @@ -70,6 +70,146 @@ d='d' # double, any matrix type, or uint. machine_description = [ + (('bit_not', a), ('Not', a)), + (('logic_not', a), ('LogicalNot', a)), + (('neg', 'a@int,uint'), ('SNegate', a)), + (('neg', 'a@float'), ('FNegate', a)), + (('abs', 'a@float'), ('GLSLstd450FAbs', a)), + (('abs', 'a@int'), ('GLSLstd450SAbs', a)), + (('sign', 'a@float'), ('GLSLstd450FSign', a)), + (('sign', 'a@int'), ('GLSLstd450SSign', a)), + (('rcp', a), ('FDiv', 1.0, a)), + (('rsq', a), ('GLSLstd450InverseSqrt', a)), + (('sqrt', a), ('GLSLstd450Sqrt', a)), + (('exp', a), ('GLSLstd450Exp', a)), + (('log', a), ('GLSLstd450Log', a)), + (('exp2', a), ('GLSLstd450Exp2', a)), + (('log2', a), ('GLSLstd450Log2', a)), + (('f2i', a), ('ConvertFToS', a)), + (('f2u', a), ('ConvertFToU', a)), + (('i2f', a), ('ConvertSToF', a)), + (('f2b', a), ('FOrdNotEqual', a, 0.0)), + (('b2f', a), ('Select', a, 1.0, 0.0)), + (('i2b', a), ('INotEqual', a, 0)), + (('b2i', a), ('Select', a, 1, 0)), + (('u2f', a), ('ConvertUToF', a)), + (('i2u', a), ('Bitcast', a)), + (('u2i', a), ('Bitcast', a)), + (('d2f', a), ('FConvert', a)), + (('f2d', a), ('FConvert', a)), + (('d2i', a), ('ConvertFToS', a)), + (('i2d', a), ('ConvertSToF', a)), + (('d2u', a), ('ConvertFToU', a)), + (('u2d', a), ('ConvertUToF', a)), + (('d2b', a), ('FOrdNotEqual', a, 0.0)), + (('bitcast_i2f', a), ('Bitcast', a)), + (('bitcast_f2i', a), ('Bitcast', a)), + (('bitcast_u2f', a), ('Bitcast', a)), + (('bitcast_f2u', a), ('Bitcast', a)), + (('bitcast_u642d', a), ('Bitcast', a)), + (('bitcast_i642d', a), ('Bitcast', a)), + (('bitcast_d2u64', a), ('Bitcast', a)), + (('bitcast_d2i64', a), ('Bitcast', a)), + (('i642i', a), ('SConvert', a)), + (('u642i', a), ('SConvert', a)), + (('i642u', a), ('UConvert', a)), + (('u642u', a), ('UConvert', a)), + (('i642b', a), ('INotEqual', a, 0)), + (('i642f', a), ('ConvertSToF', a)), + (('u642f', a), ('ConvertUToF', a)), + (('i642d', a), ('ConvertSToF', a)), + (('u642d', a), ('ConvertSToF', a)), + (('i2i64', a), ('SConvert', a)), + (('u2i64', a), ('SConvert', a)), + (('b2i64', a), ('Select', a, 1, 0)), + (('f2i64', a), ('ConvertFToS', a)), + (('d2i64', a), ('ConvertFToS', a)), + (('i2u64', a), ('UConvert', a)), + (('u2u64', a), ('UConvert', a)), + (('f2u64', a), ('ConvertFToU', a)), + (('d2u64', a), ('ConvertFToU', a)), + (('u642i64', a), ('Bitcast', a)), + (('i642u64', a), ('Bitcast', a)), + + (('trunc', a), ('GLSLstd450Trunc', a)), + (('ceil', a), ('GLSLstd450Ceil', a)), + (('floor', a), ('GLSLstd450Floor', a)), + (('fract', a), ('GLSLstd450Fract', a)), + (('round_even', a), ('GLSLstd450RoundEven', a)), + (('sin', a), ('GLSLstd450Sin', a)), + (('cos', a), ('GLSLstd450Cos', a)), + (('dFdx', a), ('DPdx', a)), + (('dFdy', a), ('DPdy', a)), + + (('bitfield_reverse', a), ('BitReverse', a)), + + (('saturate', 'a@float'), ('GLSLstd450FClamp', a, 0.0, 1.0)), + + (('add', 'a@int,uint', b), ('IAdd', a, b)), + (('add', a, b), ('FAdd', a, b)), + (('sub', 'a@int,uint', b), ('ISub', a, b)), + (('sub', a, b), ('FSub', a, b)), + (('mul', 'a@int,uint', b), ('IMul', a, b)), + (('mul', 'a@matrix', 'b@matrix'), ('MatrixTimesMatrix', a, b)), + (('mul', 'a@matrix', 'b@vector'), ('MatrixTimesVector', a, b)), + (('mul', 'a@matrix', 'b@scalar'), ('MatrixTimesScalar', a, b)), + (('mul', 'a@float,vector', 'b@scalar'), ('VectorTimesScalar', a, b)), + (('mul', a, b), ('FMul', a, b)), + (('div', 'a@float,scalar', 'b@scalar'), ('FDiv', a, b)), + (('div', 'a@float,vector', 'b@vector'), ('FDiv', a, b)), + (('div', 'a@int,scalar', 'b@scalar'), ('SDiv', a, b)), + (('div', 'a@int,vector', 'b@vector'), ('SDiv', a, b)), + (('div', 'a@uint,scalar', 'b@scalar'), ('UDiv', a, b)), + (('div', 'a@uint,vector', 'b@vector'), ('UDiv', a, b)), + + (('mod', 'a@int', b), ('SRem', a, b)), + (('mod', 'a@uint', b), ('UMod', a, b)), + (('mod', a, b), ('FRem', a, b)), + + (('less', 'a@float', b), ('FOrdLessThan', a, b)), + (('less', 'a@uint', b), ('ULessThan', a, b)), + (('less', 'a@int', b), ('SLessThan', a, b)), + (('gequal', 'a@float', b), ('FOrdGreaterThanEqual', a, b)), + (('gequal', 'a@uint', b), ('UGreaterThanEqual', a, b)), + (('gequal', 'a@int', b), ('SGreaterThanEqual', a, b)), + (('equal', 'a@float', b), ('FOrdEqual', a, b)), + (('equal', 'a@uint,int', b), ('IEqual', a, b)), + (('equal', 'a@bool', b), ('LogicalEqual', a, b)), + (('nequal', 'a@float', b), ('FOrdNotEqual', a, b)), + (('nequal', 'a@uint,int', b), ('INotEqual', a, b)), + (('nequal', 'a@bool', b), ('LogicalNotEqual', a, b)), + + (('all_equal', 'a@float', b), ('All', ('FOrdEqual', a, b))), + (('all_equal', 'a@uint,int', b), ('All', ('IEqual', a, b))), + (('all_equal', 'a@bool,vector', 'b@bool,vector'), ('All', ('LogicalEqual', a, b))), + + (('any_nequal', 'a@float', b), ('Any', ('FOrdNotEqual', a, b))), + (('any_nequal', 'a@uint,int', b), ('Any', ('INotEqual', a, b))), + (('any_nequal', 'a@bool', b), ('Any', ('LogicalNotEqual', a, b))), + + (('lshift', a, b), ('ShiftLeftLogical', a, b)), + (('rshift', 'a@uint', b), ('ShiftRightLogical', a, b)), + (('rshift', 'a@int', b), ('ShiftRightArithmetic', a, b)), + (('bit_and', a, b), ('BitwiseAnd', a, b)), + (('bit_xor', a, b), ('BitwiseXor', a, b)), + (('bit_or', a, b), ('BitwiseOr', a, b)), + (('logic_and', a, b), ('LogicalAnd', a, b)), + (('logic_xor', a, b), ('LogicalNotEqual', a, b)), + (('logic_or', a, b), ('LogicalOr', a, b)), + (('dot', a, b), ('Dot', a, b)), + (('min', 'a@uint', b), ('GLSLstd450UMin', a, b)), + (('min', 'a@int', b), ('GLSLstd450SMin', a, b)), + (('min', 'a@float', b), ('GLSLstd450FMin', a, b)), + (('max', 'a@uint', b), ('GLSLstd450UMax', a, b)), + (('max', 'a@int', b), ('GLSLstd450SMax', a, b)), + (('max', 'a@float', b), ('GLSLstd450FMax', a, b)), + (('pow', a, b), ('GLSLstd450Pow', a, b)), + + (('fma', a, b, c), ('GLSLstd450Fma', a, b, c)), + (('lrp', a, b, c), ('GLSLstd450FMix', a, b, c)), + (('csel', a, b, c), ('Select', a, b, c)), + + (('bitfield_insert', a, b, c, d), ('BitFieldInsert', a, b, c, d)), ] def parse_args(): @@ -390,7 +530,7 @@ class EmitExpression(Expression): if len(lines) > 0: lines.append("") - lines.append("{} = prog->next_id++;".format(result_name)) + lines.append("{} = prog->known_items.get_next_id();".format(result_name)) lines.append("") if self.opcode[:10] == "GLSLstd450": diff --git a/src/compiler/glsl/tests/emit_spirv_expression_test.cpp b/src/compiler/glsl/tests/emit_spirv_expression_test.cpp index 92e002b121d..8f8e83fbf45 100644 --- a/src/compiler/glsl/tests/emit_spirv_expression_test.cpp +++ b/src/compiler/glsl/tests/emit_spirv_expression_test.cpp @@ -52,9 +52,16 @@ public: void SetUp(); void TearDown(); + void create_variables(const glsl_type *t, ...); + exec_list instructions; ir_factory body; spirv_visitor *v; + + ir_variable *var[8]; + unsigned var_id[8]; + unsigned var_type[8]; + gl_shader_stage stage; }; void @@ -69,7 +76,8 @@ validate_emit_expression::SetUp() */ body.mem_ctx = mem_ctx; - v = new spirv_visitor(spv, MESA_SHADER_VERTEX); + stage = MESA_SHADER_VERTEX; + v = new spirv_visitor(spv, stage); } void @@ -78,3 +86,270 @@ validate_emit_expression::TearDown() delete v; validate_emit_spirv::TearDown(); } + +void +validate_emit_expression::create_variables(const glsl_type *t, ...) +{ + char name[2]; + va_list ap; + + name[1] = '\0'; + + name[0] = 'a' + 0; + var[0] = new(mem_ctx) ir_variable(t, name, ir_var_auto); + var_id[0] = spv->emit_variable(var[0], stage); + var_type[0] = spv->known_items.get_id(t); + + va_start(ap, t); + + const glsl_type *type = NULL; + unsigned i = 1; + while ((type = va_arg(ap, const glsl_type *)) != NULL) { + assert(i < ARRAY_SIZE(var)); + + name[0] = 'a' + i; + var[i] = new(mem_ctx) ir_variable(type, name, ir_var_auto); + var_id[i] = spv->emit_variable(var[i], stage); + var_type[i] = spv->known_items.get_id(type); + + i++; + } + + va_end(ap); + +} + +#define ssa1 uint32_t(-1) +#define ssa2 uint32_t(-2) +#define ssa3 uint32_t(-3) +#define ssa4 uint32_t(-4) +#define ssa5 uint32_t(-5) +#define ssa6 uint32_t(-6) +#define ssa7 uint32_t(-7) +#define ssa8 uint32_t(-8) +#define ssa9 uint32_t(-9) + +/** + * \name Short-hand macros for common instructions. + */ +/*@{*/ +#define OpLoad(result_type, result, pointer) \ + 0x0004003d, \ + result_type, \ + result, \ + pointer + +#define OpStore(result_type, target, source) \ + 0x0003003e, \ + target, \ + source + +#define OpCompositeExtract1(result_type, result, vector1, component0) \ + 0x00050051, \ + result_type, \ + result, \ + vector1, \ + component0 + +#define OpVectorShuffle2(result_type, result, vector1, vector2, component0, component1) \ + 0x0007004f, \ + result_type, \ + result, \ + vector1, \ + vector2, \ + component0, \ + component1 + +#define OpVectorShuffle3(result_type, result, vector1, vector2, component0, component1, component2) \ + 0x0008004f, \ + result_type, \ + result, \ + vector1, \ + vector2, \ + component0, \ + component1, \ + component2 + +#define OpVectorShuffle4(result_type, result, vector1, vector2, component0, component1, component2, component3) \ + 0x0009004f, \ + result_type, \ + result, \ + vector1, \ + vector2, \ + component0, \ + component1, \ + component2, \ + component3 + +#define OpSNegate(result_type, result, operand) \ + 0x0004007e, \ + result_type, \ + result, \ + operand + +#define OpFNegate(result_type, result, operand) \ + 0x0004007f, \ + result_type, \ + result, \ + operand + +#define OpIAdd(result_type, result, operand1, operand2) \ + 0x00050080, \ + result_type, \ + result, \ + operand1, \ + operand2 + +#define OpFAdd(result_type, result, operand1, operand2) \ + 0x00050081, \ + result_type, \ + result, \ + operand1, \ + operand2 + +#define OpISub(result_type, result, operand1, operand2) \ + 0x00050082, \ + result_type, \ + result, \ + operand1, \ + operand2 + +#define OpFSub(result_type, result, operand1, operand2) \ + 0x00050083, \ + result_type, \ + result, \ + operand1, \ + operand2 + +#define OpIMul(result_type, result, operand1, operand2) \ + 0x00050084, \ + result_type, \ + result, \ + operand1, \ + operand2 + +#define OpFMul(result_type, result, operand1, operand2) \ + 0x00050085, \ + result_type, \ + result, \ + operand1, \ + operand2 +/*@}*/ + +#if 0 +void +validate_emit_expression::check_unop_GLSL450(ir_expression *expr, uint32_t opcode) +{ + const unsigned result_id = v->get_result(expr); + + const unsigned operand = + spv->known_items.get_id(expr->operands[0]->as_constant()); + const unsigned type_id = spv->known_items.get_id(expr->type); + + EXPECT_NE(0, type_id); + EXPECT_LT(type_id, operand); + EXPECT_LT(operand, result_id); + + const unsigned ext_inst_import_size = spv->ext_inst_imports.size_in_bytes(); + + EXPECT_NE(0, ext_inst_import_size); + + const unsigned glsl450_id = spv->GLSL450_extension(); + + EXPECT_EQ(ext_inst_import_size, spv->ext_inst_imports.size_in_bytes()); + EXPECT_NE(0, glsl450_id); + + EXPECT_INSTRUCTIONS(spv->ext_inst_imports, + 0x0006000b, /* SpvOpExtInstImport */ + glsl450_id, /* Result */ + chars_to_word("GLSL.std.450" + 0), + chars_to_word("GLSL.std.450" + 4), + chars_to_word("GLSL.std.450" + 8), + 0x00000000 + ); + + EXPECT_INSTRUCTIONS(spv->functions, + 0x0006000c, /* SpvOpExtInst */ + type_id, + result_id, + glsl450_id, + opcode, + operand + ); +} +#endif + +TEST_F(validate_emit_expression, fadd) +{ + create_variables(glsl_type::float_type, + glsl_type::float_type, + NULL); + + ir_expression *const ir = add(var[0], var[1]); + + const unsigned result_id = v->get_result(ir); + + EXPECT_TRUE(get_success(v)); + + const unsigned result_type_id = spv->known_items.get_id(ir->type); + + VALIDATE_INSTRUCTIONS(spv->functions, + OpLoad(var_type[0], ssa1, var_id[0]), + OpLoad(var_type[1], ssa2, var_id[1]), + OpFAdd(result_type_id, result_id, ssa2, ssa1) + ); +} + +TEST_F(validate_emit_expression, iadd) +{ + create_variables(glsl_type::int_type, + glsl_type::int_type, + glsl_type::int_type, + NULL); + + ir_expression *const ir = add(var[2], add(var[0], var[1])); + + const unsigned result_id = v->get_result(ir); + + EXPECT_TRUE(get_success(v)); + + const unsigned result_type_id = spv->known_items.get_id(ir->type); + + VALIDATE_INSTRUCTIONS(spv->functions, + OpLoad(var_type[0], ssa1, var_id[0]), + OpLoad(var_type[1], ssa2, var_id[1]), + OpLoad(var_type[2], ssa4, var_id[2]), + OpIAdd(result_type_id, ssa3, ssa2, ssa1), + OpIAdd(result_type_id, result_id, ssa3, ssa4) + ); +} + +TEST_F(validate_emit_expression, fmul_fadd_fneg_shuffle) +{ + create_variables(glsl_type::vec4_type, + glsl_type::vec4_type, + NULL); + + ir_expression *const ir = add(mul(body.constant(2.0f), swizzle_z(var[0])), + neg(swizzle_w(var[1]))); + + const unsigned result_id = v->get_result(ir); + + EXPECT_TRUE(get_success(v)); + + const unsigned result_type_id = spv->known_items.get_id(ir->type); + const unsigned float_type = spv->known_items.get_id(glsl_type::float_type); + const unsigned const_2 = spv->known_items.get_id(body.constant(2.0f)); + + VALIDATE_INSTRUCTIONS(spv->functions, + OpLoad(var_type[0], ssa4, var_id[0]), + OpCompositeExtract1(float_type, ssa5, ssa4, 2), + + OpLoad(var_type[0], ssa1, var_id[1]), + OpCompositeExtract1(float_type, ssa2, ssa1, 3), + + OpFNegate(float_type, ssa3, ssa2), + OpFMul(float_type, ssa6, const_2, ssa5), + OpFAdd(result_type_id, result_id, ssa3, ssa6) + ); +} diff --git a/src/compiler/glsl/tests/validate_spirv.cpp b/src/compiler/glsl/tests/validate_spirv.cpp index abad49eaebe..5cf792173a3 100644 --- a/src/compiler/glsl/tests/validate_spirv.cpp +++ b/src/compiler/glsl/tests/validate_spirv.cpp @@ -238,6 +238,46 @@ validate_instruction_stream(const uint32_t *expected, unsigned len_expected, memcpy(temp, &expected[i], sizeof(uint32_t) * inst_size); switch (opcode) { + case SpvOpSNegate: + case SpvOpFNegate: { + /* These instructions all have the form: + * + * OpCode ResultType ResultId Operand + */ + EXPECT_EQ(4, inst_size); + + /* The type must be set in advance. */ + EXPECT_LT(0, int(expected[1])); + + unknown_src = process_sources(1, &temp[3], id_map); + + dst_id_offset = 2; + commute[0] = 0; + commute[1] = 0; + break; + } + + case SpvOpIAdd: + case SpvOpFAdd: + case SpvOpIMul: + case SpvOpFMul: { + /* These instructions all have the form: + * + * OpCode ResultType ResultId Operand1 Operand2 + */ + EXPECT_EQ(5, inst_size); + + /* The type must be set in advance. */ + EXPECT_LT(0, int(expected[1])); + + unknown_src = process_sources(2, &temp[3], id_map); + + dst_id_offset = 2; + commute[0] = 3; + commute[1] = 4; + break; + } + case SpvOpLoad: { /* This instruction has the form: * |