Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/SPIRV-Cross.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spirv_glsl.cpp')
-rw-r--r--spirv_glsl.cpp55
1 files changed, 46 insertions, 9 deletions
diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp
index a8129641..cf621904 100644
--- a/spirv_glsl.cpp
+++ b/spirv_glsl.cpp
@@ -5984,6 +5984,14 @@ void CompilerGLSL::emit_unary_op(uint32_t result_type, uint32_t result_id, uint3
inherit_expression_dependencies(result_id, op0);
}
+void CompilerGLSL::emit_unary_op_cast(uint32_t result_type, uint32_t result_id, uint32_t op0, const char *op)
+{
+ auto &type = get<SPIRType>(result_type);
+ bool forward = should_forward(op0);
+ emit_op(result_type, result_id, join(type_to_glsl(type), "(", op, to_enclosed_unpacked_expression(op0), ")"), forward);
+ inherit_expression_dependencies(result_id, op0);
+}
+
void CompilerGLSL::emit_binary_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op)
{
// Various FP arithmetic opcodes such as add, sub, mul will hit this.
@@ -6127,7 +6135,9 @@ bool CompilerGLSL::emit_complex_bitcast(uint32_t result_type, uint32_t id, uint3
}
void CompilerGLSL::emit_binary_op_cast(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1,
- const char *op, SPIRType::BaseType input_type, bool skip_cast_if_equal_type)
+ const char *op, SPIRType::BaseType input_type,
+ bool skip_cast_if_equal_type,
+ bool implicit_integer_promotion)
{
string cast_op0, cast_op1;
auto expected_type = binary_op_bitcast_helper(cast_op0, cast_op1, input_type, op0, op1, skip_cast_if_equal_type);
@@ -6136,17 +6146,23 @@ void CompilerGLSL::emit_binary_op_cast(uint32_t result_type, uint32_t result_id,
// We might have casted away from the result type, so bitcast again.
// For example, arithmetic right shift with uint inputs.
// Special case boolean outputs since relational opcodes output booleans instead of int/uint.
+ auto bitop = join(cast_op0, " ", op, " ", cast_op1);
string expr;
- if (out_type.basetype != input_type && out_type.basetype != SPIRType::Boolean)
+
+ if (implicit_integer_promotion)
+ {
+ // Simple value cast.
+ expr = join(type_to_glsl(out_type), '(', bitop, ')');
+ }
+ else if (out_type.basetype != input_type && out_type.basetype != SPIRType::Boolean)
{
expected_type.basetype = input_type;
- expr = bitcast_glsl_op(out_type, expected_type);
- expr += '(';
- expr += join(cast_op0, " ", op, " ", cast_op1);
- expr += ')';
+ expr = join(bitcast_glsl_op(out_type, expected_type), '(', bitop, ')');
}
else
- expr += join(cast_op0, " ", op, " ", cast_op1);
+ {
+ expr = std::move(bitop);
+ }
emit_op(result_type, result_id, expr, should_forward(op0) && should_forward(op1));
inherit_expression_dependencies(result_id, op0);
@@ -10751,8 +10767,10 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
#define GLSL_BOP(op) emit_binary_op(ops[0], ops[1], ops[2], ops[3], #op)
#define GLSL_BOP_CAST(op, type) \
- emit_binary_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, opcode_is_sign_invariant(opcode))
+ emit_binary_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, \
+ opcode_is_sign_invariant(opcode), implicit_integer_promotion)
#define GLSL_UOP(op) emit_unary_op(ops[0], ops[1], ops[2], #op)
+#define GLSL_UOP_CAST(op) emit_unary_op_cast(ops[0], ops[1], ops[2], #op)
#define GLSL_QFOP(op) emit_quaternary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], ops[5], #op)
#define GLSL_TFOP(op) emit_trinary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], #op)
#define GLSL_BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
@@ -10766,6 +10784,13 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
auto int_type = to_signed_basetype(integer_width);
auto uint_type = to_unsigned_basetype(integer_width);
+ // Handle C implicit integer promotion rules.
+ // If we get implicit promotion to int, need to make sure we cast by value to intended return type,
+ // otherwise, future sign-dependent operations and bitcasts will break.
+ bool implicit_integer_promotion = integer_width < 32 && backend.implicit_c_integer_promotion_rules &&
+ opcode_can_promote_integer_implicitly(opcode) &&
+ get<SPIRType>(ops[0]).vecsize == 1;
+
opcode = get_remapped_spirv_op(opcode);
switch (opcode)
@@ -11600,6 +11625,12 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
break;
case OpSNegate:
+ if (implicit_integer_promotion || expression_type_id(ops[2]) != ops[0])
+ GLSL_UOP_CAST(-);
+ else
+ GLSL_UOP(-);
+ break;
+
case OpFNegate:
GLSL_UOP(-);
break;
@@ -11744,6 +11775,9 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
auto expr = join(to_enclosed_expression(op0), " - ", to_enclosed_expression(op1), " * ", "(",
to_enclosed_expression(op0), " / ", to_enclosed_expression(op1), ")");
+ if (implicit_integer_promotion)
+ expr = join(type_to_glsl(get<SPIRType>(result_type)), '(', expr, ')');
+
emit_op(result_type, result_id, expr, forward);
inherit_expression_dependencies(result_id, op0);
inherit_expression_dependencies(result_id, op1);
@@ -11841,7 +11875,10 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
}
case OpNot:
- GLSL_UOP(~);
+ if (implicit_integer_promotion || expression_type_id(ops[2]) != ops[0])
+ GLSL_UOP_CAST(~);
+ else
+ GLSL_UOP(~);
break;
case OpUMod: