Commit 647fccaf by John Kessenich

AST: Fix shift conversions, which don't require matching types.

The base and shift amount need to be integers, but not of the same type. This fixes #1296 and replaces #1297.
parent 6e899be5
spv.rankShift.comp
// Module Version 10000
// Generated by (magic number): 80006
// Id's are bound by 33
Capability Shader
Capability Int64
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint GLCompute 4 "main"
ExecutionMode 4 LocalSize 54 1 1
Source GLSL 450
SourceExtension "GL_ARB_gpu_shader_int64"
Name 4 "main"
Name 8 "result"
Name 11 "arg0"
Name 15 "arg1"
Decorate 11(arg0) Location 4
Decorate 15(arg1) Location 5
Decorate 32 BuiltIn WorkgroupSize
2: TypeVoid
3: TypeFunction 2
6: TypeInt 64 0
7: TypePointer Function 6(int)
9: TypeInt 64 1
10: TypePointer UniformConstant 9(int)
11(arg0): 10(ptr) Variable UniformConstant
13: TypeInt 32 0
14: TypePointer UniformConstant 13(int)
15(arg1): 14(ptr) Variable UniformConstant
29: TypeVector 13(int) 3
30: 13(int) Constant 54
31: 13(int) Constant 1
32: 29(ivec3) ConstantComposite 30 31 31
4(main): 2 Function None 3
5: Label
8(result): 7(ptr) Variable Function
12: 9(int) Load 11(arg0)
16: 13(int) Load 15(arg1)
17: 9(int) ShiftLeftLogical 12 16
18: 6(int) Bitcast 17
Store 8(result) 18
19: 9(int) Load 11(arg0)
20: 13(int) Load 15(arg1)
21: 9(int) ShiftRightArithmetic 19 20
22: 6(int) Bitcast 21
Store 8(result) 22
23: 13(int) Load 15(arg1)
24: 6(int) Load 8(result)
25: 6(int) ShiftLeftLogical 24 23
Store 8(result) 25
26: 13(int) Load 15(arg1)
27: 6(int) Load 8(result)
28: 6(int) ShiftRightLogical 27 26
Store 8(result) 28
Return
FunctionEnd
......@@ -116,6 +116,8 @@ void operators()
i64 = i64 % i;
// Shift
u64v = u64v << i;
i64 = i64 >> uv.y;
u64v <<= i;
i64 >>= uv.y;
......
#version 450
#extension GL_ARB_gpu_shader_int64 : require
layout(local_size_x = 54) in;
layout(location=4) uniform int64_t arg0;
layout(location=5) uniform uint arg1;
void main()
{
uint64_t result = arg0 << arg1;
result = arg0 >> arg1;
result <<= arg1;
result >>= arg1;
}
\ No newline at end of file
......@@ -744,9 +744,6 @@ TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* no
auto promoteTo = std::make_tuple(EbtNumTypes, EbtNumTypes);
TBasicType type0 = node0->getType().getBasicType();
TBasicType type1 = node1->getType().getBasicType();
switch (op) {
//
// List all the binary ops that can implicitly convert one operand to the other's type;
......@@ -776,10 +773,10 @@ TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* no
case EOpSequence: // used by ?:
if (type0 == type1)
if (node0->getBasicType() == node1->getBasicType())
return std::make_tuple(node0, node1);
promoteTo = getConversionDestinatonType(type0, type1, op);
promoteTo = getConversionDestinatonType(node0->getBasicType(), node1->getBasicType(), op);
if (std::get<0>(promoteTo) == EbtNumTypes || std::get<1>(promoteTo) == EbtNumTypes)
return std::make_tuple(nullptr, nullptr);
......@@ -794,23 +791,25 @@ TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* no
return std::make_tuple(node0, node1);
break;
// Shifts can have mixed types as long as they are integer and of the same rank,
// without converting.
// There are no conversions needed for GLSL; the shift amount just needs to be an
// integer type, as does the base.
// HLSL can promote bools to ints to make this work.
case EOpLeftShift:
case EOpRightShift:
if (node0->getType() == node1->getType())
return std::make_tuple(node0, node1);
if (isTypeInt(type0) && isTypeInt(type1)) {
if (getTypeRank(type0) == getTypeRank(type1)) {
if (source == EShSourceHlsl) {
TBasicType node0BasicType = node0->getBasicType();
if (node0BasicType == EbtBool)
node0BasicType = EbtInt;
if (node1->getBasicType() == EbtBool)
promoteTo = std::make_tuple(node0BasicType, EbtInt);
else
promoteTo = std::make_tuple(node0BasicType, node1->getBasicType());
} else {
if (isTypeInt(node0->getBasicType()) && isTypeInt(node1->getBasicType()))
return std::make_tuple(node0, node1);
} else {
promoteTo = getConversionDestinatonType(type0, type1, op);
if (std::get<0>(promoteTo) == EbtNumTypes || std::get<1>(promoteTo) == EbtNumTypes)
return std::make_tuple(nullptr, nullptr);
}
} else
return std::make_tuple(nullptr, nullptr);
else
return std::make_tuple(nullptr, nullptr);
}
break;
default:
......@@ -964,35 +963,24 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
if (type.getBasicType() == node->getType().getBasicType())
return node;
if (canImplicitlyPromote(node->getType().getBasicType(), type.getBasicType(), op))
if (canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op))
promoteTo = type.getBasicType();
else
return nullptr;
break;
// Shifts can have mixed types as long as they are integer and of the same rank,
// without converting.
// It's the left operand's type that determines the resulting type, so no issue
// with assign shift ops either.
// For GLSL, there are no conversions needed; the shift amount just needs to be an
// integer type, as do the base/result.
// HLSL can convert the shift from a bool to an int.
case EOpLeftShiftAssign:
case EOpRightShiftAssign:
{
TBasicType type0 = type.getBasicType();
TBasicType type1 = node->getType().getBasicType();
if (source == EShSourceHlsl && node->getType().getBasicType() == EbtBool) {
promoteTo = type0;
} else {
if (isTypeInt(type0) && isTypeInt(type1)) {
if (getTypeRank(type0) == getTypeRank(type1)) {
return node;
} else {
if (canImplicitlyPromote(type1, type0, op))
promoteTo = type0;
else
return nullptr;
}
} else
if (source == EShSourceHlsl && node->getType().getBasicType() == EbtBool)
promoteTo = type.getBasicType();
else {
if (isTypeInt(type.getBasicType()) && isTypeInt(node->getBasicType()))
return node;
else
return nullptr;
}
break;
......@@ -1437,9 +1425,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_float32) ||
extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_float64);
if(explicitTypesEnabled)
{
if(explicitTypesEnabled) {
// integral promotions
if (isIntegralPromotion(from, to)) {
return true;
......
......@@ -416,6 +416,7 @@ INSTANTIATE_TEST_CASE_P(
"spv.460.comp",
"spv.atomic.comp",
"spv.glFragColor.frag",
"spv.rankShift.comp",
"spv.specConst.vert",
"spv.OVR_multiview.vert",
})),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment