summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2017-09-29 20:20:55 -0700
committerIan Romanick <ian.d.romanick@intel.com>2018-03-29 14:16:13 -0700
commitb362ba03cfa50d113a6e130400ef617d64c6374b (patch)
tree96ce8ef3fd853fe1c261e2f1f6a2d97e40396168
parentee7701a3805a235dc6f0213ea311eb5954aeb912 (diff)
WIP: glsl/spirv: Emit expressions
-rw-r--r--src/compiler/glsl/spirv_expression_visitor_cpp.py142
-rw-r--r--src/compiler/glsl/tests/emit_spirv_expression_test.cpp277
-rw-r--r--src/compiler/glsl/tests/validate_spirv.cpp40
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:
*