Spec Constant Operations

Approach:
Add a flag in `Builder` to indicate 'spec constant mode' and 'normal
mode'. When the builder is in 'normal mode', nothing changed. When the
builder is in 'spec constant mode', binary, unary and other instruction
creation rountines will be redirected to `createSpecConstantOp()` to
create instrution at module level with `OpSpecConstantOp <original
opcode> <operands>`.

'spec constant mode' should be enabled if and only if we are creating
spec constants. So a flager setter/recover guard is added when handling
binary/unary nodes in `createSpvConstantsFromConstSubTree()`.

Note when handling spec constants which are represented as ConstantUnion
Node, we should not use `OpSpecConstantOp` to initialize the composite
constant, so builder is set to 'normal mode'.

Tests:
Tests are added in Test/spv.specConstantOperations.vert, including:

1) Arithmetic, shift opeations for both scalar and composite type spec constants.
2) Size conversion from/to float and double for both scalar and vector.
3) Bitwise and/or/xor for both scalar and vector.
4) Unary negate/not for both scalar and vector.
5) Vector swizzles.
6) Comparisons for scalars.
7) == and != for composite type spec constants

Issues:
1) To implement == and != for composite type spec constants, the Spec needs
to allow OpAll, OpAny, OpFOrdEqual, OpFUnordEqual, OpOrdNotEqual,
OpFUnordNotEqual. Currently none of them are allowed in the Spec.
This commit is contained in:
qining 2016-03-21 09:51:37 -04:00
parent c3869fee41
commit 135452061a
6 changed files with 506 additions and 13 deletions

View File

@ -130,7 +130,7 @@ protected:
void addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value); void addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value);
spv::Id createSpvConstant(const glslang::TIntermTyped&); spv::Id createSpvConstant(const glslang::TIntermTyped&);
spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant); spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant);
spv::Id createSpvConstantFromConstSubTree(const glslang::TIntermTyped* subTree); spv::Id createSpvConstantFromConstSubTree(glslang::TIntermTyped* subTree);
bool isTrivialLeaf(const glslang::TIntermTyped* node); bool isTrivialLeaf(const glslang::TIntermTyped* node);
bool isTrivial(const glslang::TIntermTyped* node); bool isTrivial(const glslang::TIntermTyped* node);
spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right); spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right);
@ -3854,15 +3854,37 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla
return builder.makeCompositeConstant(typeId, spvConsts); return builder.makeCompositeConstant(typeId, spvConsts);
} }
namespace {
class SpecConstOpCodeGenerationSettingGuard{
public:
SpecConstOpCodeGenerationSettingGuard(spv::Builder* builder,
bool shouldGeneratingForSpecConst)
: builder_(builder) {
previous_flag_ = builder->isInSpecConstCodeGenMode();
shouldGeneratingForSpecConst ? builder->setToSpecConstCodeGenMode()
: builder->setToNormalCodeGenMode();
}
~SpecConstOpCodeGenerationSettingGuard() {
previous_flag_ ? builder_->setToSpecConstCodeGenMode()
: builder_->setToNormalCodeGenMode();
}
private:
spv::Builder* builder_;
bool previous_flag_;
};
}
// Create constant ID from const initializer sub tree. // Create constant ID from const initializer sub tree.
spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree( spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree(
const glslang::TIntermTyped* subTree) { glslang::TIntermTyped* subTree) {
const glslang::TType& glslangType = subTree->getType(); const glslang::TType& glslangType = subTree->getType();
spv::Id typeId = convertGlslangToSpvType(glslangType); spv::Id typeId = convertGlslangToSpvType(glslangType);
bool is_spec_const = subTree->getType().getQualifier().isSpecConstant(); bool is_spec_const = subTree->getType().getQualifier().isSpecConstant();
if (const glslang::TIntermAggregate* an = subTree->getAsAggregate()) { if (const glslang::TIntermAggregate* an = subTree->getAsAggregate()) {
// Aggregate node, we should generate OpConstantComposite or // Aggregate node, we should generate OpConstantComposite or
// OpSpecConstantComposite instruction. // OpSpecConstantComposite instruction.
std::vector<spv::Id> const_constituents; std::vector<spv::Id> const_constituents;
for (auto NI = an->getSequence().begin(); NI != an->getSequence().end(); for (auto NI = an->getSequence().begin(); NI != an->getSequence().end();
NI++) { NI++) {
@ -3881,17 +3903,27 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree(
return const_constituents.front(); return const_constituents.front();
} }
} else if (const glslang::TIntermBinary* bn = subTree->getAsBinaryNode()) { } else if (glslang::TIntermBinary* bn = subTree->getAsBinaryNode()) {
// Binary operation node, we should generate OpSpecConstantOp <binary op> // Binary operation node, we should generate OpSpecConstantOp <binary op>
// This case should only happen when Specialization Constants are involved. // This case should only happen when Specialization Constants are involved.
spv::MissingFunctionality("OpSpecConstantOp <binary op> not implemented");
return spv::NoResult;
} else if (const glslang::TIntermUnary* un = subTree->getAsUnaryNode()) { // Spec constants defined with binary operations and other constants requires
// OpSpecConstantOp instruction.
SpecConstOpCodeGenerationSettingGuard set_to_spec_const_mode(&builder, true);
bn->traverse(this);
return accessChainLoad(bn->getType());
} else if (glslang::TIntermUnary* un = subTree->getAsUnaryNode()) {
// Unary operation node, similar to binary operation node, should only // Unary operation node, similar to binary operation node, should only
// happen when specialization constants are involved. // happen when specialization constants are involved.
spv::MissingFunctionality("OpSpecConstantOp <unary op> not implemented");
return spv::NoResult; // Spec constants defined with unary operations and other constants requires
// OpSpecConstantOp instruction.
SpecConstOpCodeGenerationSettingGuard set_to_spec_const_mode(&builder, true);
un->traverse(this);
return accessChainLoad(un->getType());
} else if (const glslang::TIntermConstantUnion* cn = subTree->getAsConstantUnion()) { } else if (const glslang::TIntermConstantUnion* cn = subTree->getAsConstantUnion()) {
// ConstantUnion node, should redirect to // ConstantUnion node, should redirect to

View File

@ -64,7 +64,8 @@ Builder::Builder(unsigned int magicNumber) :
builderNumber(magicNumber), builderNumber(magicNumber),
buildPoint(0), buildPoint(0),
uniqueId(0), uniqueId(0),
mainFunction(0) mainFunction(0),
generatingOpCodeForSpecConst(false)
{ {
clearAccessChain(); clearAccessChain();
} }
@ -1063,6 +1064,11 @@ Id Builder::createArrayLength(Id base, unsigned int member)
Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index) Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
{ {
// Generate code for spec constants if in spec constant operation
// generation mode.
if (generatingOpCodeForSpecConst) {
return createSpecConstantOp(OpCompositeExtract, typeId, {composite}, {index});
}
Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
extract->addIdOperand(composite); extract->addIdOperand(composite);
extract->addImmediateOperand(index); extract->addImmediateOperand(index);
@ -1073,6 +1079,11 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
Id Builder::createCompositeExtract(Id composite, Id typeId, std::vector<unsigned>& indexes) Id Builder::createCompositeExtract(Id composite, Id typeId, std::vector<unsigned>& indexes)
{ {
// Generate code for spec constants if in spec constant operation
// generation mode.
if (generatingOpCodeForSpecConst) {
return createSpecConstantOp(OpCompositeExtract, typeId, {composite}, indexes);
}
Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
extract->addIdOperand(composite); extract->addIdOperand(composite);
for (int i = 0; i < (int)indexes.size(); ++i) for (int i = 0; i < (int)indexes.size(); ++i)
@ -1170,6 +1181,11 @@ void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemant
// An opcode that has one operands, a result id, and a type // An opcode that has one operands, a result id, and a type
Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand) Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand)
{ {
// Generate code for spec constants if in spec constant operation
// generation mode.
if (generatingOpCodeForSpecConst) {
return createSpecConstantOp(opCode, typeId, {operand}, {});
}
Instruction* op = new Instruction(getUniqueId(), typeId, opCode); Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
op->addIdOperand(operand); op->addIdOperand(operand);
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
@ -1179,6 +1195,11 @@ Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand)
Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right) Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right)
{ {
// Generate code for spec constants if in spec constant operation
// generation mode.
if (generatingOpCodeForSpecConst) {
return createSpecConstantOp(opCode, typeId, {left, right}, {});
}
Instruction* op = new Instruction(getUniqueId(), typeId, opCode); Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
op->addIdOperand(left); op->addIdOperand(left);
op->addIdOperand(right); op->addIdOperand(right);
@ -1208,6 +1229,102 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector<Id>& operands)
return op->getResultId(); return op->getResultId();
} }
Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands, const std::vector<unsigned>& literals) {
switch(opCode) {
// OpCodes that do not need any capababilities.
case OpSConvert:
case OpFConvert:
case OpSNegate:
case OpNot:
case OpIAdd:
case OpISub:
case OpIMul:
case OpUDiv:
case OpSDiv:
case OpUMod:
case OpSRem:
case OpSMod:
case OpShiftRightLogical:
case OpShiftRightArithmetic:
case OpShiftLeftLogical:
case OpBitwiseOr:
case OpBitwiseXor:
case OpBitwiseAnd:
case OpVectorShuffle:
case OpCompositeExtract:
case OpCompositeInsert:
case OpLogicalOr:
case OpLogicalAnd:
case OpLogicalNot:
case OpLogicalEqual:
case OpLogicalNotEqual:
case OpSelect:
case OpIEqual:
case OpULessThan:
case OpSLessThan:
case OpUGreaterThan:
case OpSGreaterThan:
case OpULessThanEqual:
case OpSLessThanEqual:
case OpUGreaterThanEqual:
case OpSGreaterThanEqual:
// Added temporarily to enable compsite type spec constants comparison.
// Remove this comment after Spec being updated.
case OpAll:
case OpAny:
case OpFOrdEqual:
case OpFUnordEqual:
case OpFOrdNotEqual:
case OpFUnordNotEqual:
break;
// OpCodes that need Shader capability.
case OpQuantizeToF16:
addCapability(CapabilityShader);
break;
// OpCodes that need Kernel capability.
case OpConvertFToS:
case OpConvertSToF:
case OpConvertFToU:
case OpConvertUToF:
case OpUConvert:
case OpConvertPtrToU:
case OpConvertUToPtr:
case OpGenericCastToPtr:
case OpPtrCastToGeneric:
case OpBitcast:
case OpFNegate:
case OpFAdd:
case OpFSub:
case OpFMul:
case OpFDiv:
case OpFRem:
case OpFMod:
case OpAccessChain:
case OpInBoundsAccessChain:
case OpPtrAccessChain:
case OpInBoundsPtrAccessChain:
addCapability(CapabilityKernel);
break;
default:
// Invalid OpCode for Spec Constant operations.
return NoResult;
}
Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp);
op->addImmediateOperand((unsigned) opCode);
for (auto it = operands.cbegin(); it != operands.cend(); ++it)
op->addIdOperand(*it);
for (auto it = literals.cbegin(); it != literals.cend(); ++it)
op->addImmediateOperand(*it);
module.mapInstruction(op);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(op));
return op->getResultId();
}
Id Builder::createFunctionCall(spv::Function* function, std::vector<spv::Id>& args) Id Builder::createFunctionCall(spv::Function* function, std::vector<spv::Id>& args)
{ {
Instruction* op = new Instruction(getUniqueId(), function->getReturnType(), OpFunctionCall); Instruction* op = new Instruction(getUniqueId(), function->getReturnType(), OpFunctionCall);
@ -1225,6 +1342,9 @@ Id Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source, std:
if (channels.size() == 1) if (channels.size() == 1)
return setPrecision(createCompositeExtract(source, typeId, channels.front()), precision); return setPrecision(createCompositeExtract(source, typeId, channels.front()), precision);
if (generatingOpCodeForSpecConst) {
return setPrecision(createSpecConstantOp(OpVectorShuffle, typeId, {source, source}, channels), precision);
}
Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle); Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
assert(isVector(source)); assert(isVector(source));
swizzle->addIdOperand(source); swizzle->addIdOperand(source);
@ -1290,10 +1410,23 @@ Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType)
if (numComponents == 1) if (numComponents == 1)
return scalar; return scalar;
Instruction* smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct); Instruction* smear = nullptr;
if (generatingOpCodeForSpecConst) {
auto members = std::vector<spv::Id>(numComponents, scalar);
// 'scalar' can not be spec constant here. All spec constant involved
// promotion is done in createSpvConstantFromConstUnionArray(). This
// 'if' branch is only accessed when 'scalar' is used in the def-chain
// of other vector type spec constants. In such cases, all the
// instructions needed to promote 'scalar' to a vector type constants
// should be added at module level.
auto result_id = makeCompositeConstant(vectorType, members, false);
smear = module.getInstruction(result_id);
} else {
smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct);
for (int c = 0; c < numComponents; ++c) for (int c = 0; c < numComponents; ++c)
smear->addIdOperand(scalar); smear->addIdOperand(scalar);
buildPoint->addInstruction(std::unique_ptr<Instruction>(smear)); buildPoint->addInstruction(std::unique_ptr<Instruction>(smear));
}
return setPrecision(smear->getResultId(), precision); return setPrecision(smear->getResultId(), precision);
} }

View File

@ -262,6 +262,7 @@ public:
Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3);
Id createOp(Op, Id typeId, const std::vector<Id>& operands); Id createOp(Op, Id typeId, const std::vector<Id>& operands);
Id createFunctionCall(spv::Function*, std::vector<spv::Id>&); Id createFunctionCall(spv::Function*, std::vector<spv::Id>&);
Id createSpecConstantOp(Op, Id typeId, const std::vector<spv::Id>& operands, const std::vector<unsigned>& literals);
// Take an rvalue (source) and a set of channels to extract from it to // Take an rvalue (source) and a set of channels to extract from it to
// make a new rvalue, which is returned. // make a new rvalue, which is returned.
@ -521,6 +522,13 @@ public:
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control); void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control);
// Sets to generate opcode for specialization constants.
void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }
// Sets to generate opcode for non-specialization constants (normal mode).
void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; }
// Check if the builder is generating code for spec constants.
bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; }
protected: protected:
Id makeIntConstant(Id typeId, unsigned value, bool specConstant); Id makeIntConstant(Id typeId, unsigned value, bool specConstant);
Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) const; Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) const;
@ -544,6 +552,7 @@ public:
Block* buildPoint; Block* buildPoint;
Id uniqueId; Id uniqueId;
Function* mainFunction; Function* mainFunction;
bool generatingOpCodeForSpecConst;
AccessChain accessChain; AccessChain accessChain;
// special blocks of instructions for output // special blocks of instructions for output

View File

@ -0,0 +1,191 @@
spv.specConstantOperations.vert
Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
Linked vertex stage:
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 163
Capability Shader
Capability Kernel
Capability Float64
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Vertex 4 "main"
Source GLSL 450
Name 4 "main"
Name 108 "int_float_double_vec2"
MemberName 108(int_float_double_vec2) 0 "i"
MemberName 108(int_float_double_vec2) 1 "f"
MemberName 108(int_float_double_vec2) 2 "d"
MemberName 108(int_float_double_vec2) 3 "v"
Decorate 7 SpecId 200
Decorate 9 SpecId 201
Decorate 11 SpecId 202
Decorate 12 SpecId 203
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
7: 6(float) SpecConstant 1078530010
8: TypeInt 32 1
9: 8(int) SpecConstant 10
10: TypeInt 32 0
11: 10(int) SpecConstant 100
12: 8(int) SpecConstant 4294967286
13: TypeFloat 64
14: 13(float) SpecConstantOp 115 7
15: 6(float) SpecConstantOp 115 14
16: 8(int) SpecConstantOp 126 9
17: 8(int) SpecConstantOp 200 9
18: 8(int) Constant 2
19: 8(int) SpecConstantOp 128 9 18
20: 8(int) SpecConstantOp 128 9 18
21: 8(int) Constant 3
22: 8(int) SpecConstantOp 130 20 21
23: 8(int) Constant 4
24: 8(int) SpecConstantOp 130 19 23
25: 8(int) SpecConstantOp 132 12 18
26: 10(int) Constant 2
27: 10(int) SpecConstantOp 132 11 26
28: 8(int) Constant 5
29: 8(int) SpecConstantOp 135 25 28
30: 10(int) Constant 5
31: 10(int) SpecConstantOp 134 27 30
32: 8(int) SpecConstantOp 139 12 23
33: 10(int) Constant 4
34: 10(int) SpecConstantOp 137 11 33
35: 8(int) SpecConstantOp 132 12 21
36: 8(int) SpecConstantOp 135 35 28
37: 8(int) Constant 10
38: 8(int) SpecConstantOp 195 12 37
39: 8(int) Constant 20
40: 10(int) SpecConstantOp 194 11 39
41: 8(int) Constant 1
42: 8(int) SpecConstantOp 196 12 41
43: 10(int) SpecConstantOp 196 11 18
44: 8(int) Constant 256
45: 8(int) SpecConstantOp 197 12 44
46: 10(int) Constant 512
47: 10(int) SpecConstantOp 198 11 46
48: 8(int) SpecConstantOp 124 11
49: 8(int) SpecConstantOp 199 12 48
50: TypeBool
51: 50(bool) SpecConstantOp 177 9 12
52: 10(int) SpecConstantOp 124 12
53: 50(bool) SpecConstantOp 176 11 52
54: 10(int) SpecConstantOp 124 12
55: 50(bool) SpecConstantOp 176 54 11
56: TypeVector 8(int) 4
57: 8(int) Constant 30
58: 56(ivec4) SpecConstantComposite 39 57 9 9
59: TypeVector 10(int) 4
60: 10(int) Constant 4294967295
61: 10(int) Constant 4294967294
62: 59(ivec4) SpecConstantComposite 11 11 60 61
63: TypeVector 6(float) 4
64: 6(float) Constant 1067450368
65: 63(fvec4) SpecConstantComposite 7 64 7 64
66: TypeVector 13(float) 4
67: 66(fvec4) SpecConstantOp 115 65
68: 63(fvec4) SpecConstantOp 115 67
69: 56(ivec4) SpecConstantOp 200 58
70: 63(fvec4) SpecConstantOp 111 69
71: 56(ivec4) SpecConstantOp 126 58
72: 56(ivec4) ConstantComposite 18 18 18 18
73: 56(ivec4) SpecConstantOp 128 58 72
74: 56(ivec4) SpecConstantOp 128 58 72
75: 56(ivec4) ConstantComposite 21 21 21 21
76: 56(ivec4) SpecConstantOp 130 74 75
77: 56(ivec4) ConstantComposite 23 23 23 23
78: 56(ivec4) SpecConstantOp 130 76 77
79: 56(ivec4) SpecConstantOp 132 58 72
80: 56(ivec4) ConstantComposite 28 28 28 28
81: 56(ivec4) SpecConstantOp 135 79 80
82: 56(ivec4) SpecConstantOp 139 58 77
83: 56(ivec4) ConstantComposite 37 37 37 37
84: 56(ivec4) SpecConstantOp 195 58 83
85: 56(ivec4) SpecConstantOp 196 58 72
86: 8(int) Constant 1024
87: 56(ivec4) ConstantComposite 86 86 86 86
88: 56(ivec4) SpecConstantOp 197 58 87
89: 10(int) Constant 2048
90: 59(ivec4) ConstantComposite 89 89 89 89
91: 59(ivec4) SpecConstantOp 198 62 90
92: 56(ivec4) SpecConstantOp 124 62
93: 56(ivec4) SpecConstantOp 199 58 92
94: 10(int) Constant 0
95: 8(int) SpecConstantOp 81 58 0
96: TypeVector 8(int) 2
97: 96(ivec2) SpecConstantOp 79 58 58 1(GLSL.std.450) 0
98: TypeVector 8(int) 3
99: 98(ivec3) SpecConstantOp 79 58 58 2 1(GLSL.std.450) 0
100: 56(ivec4) SpecConstantOp 79 58 58 1(GLSL.std.450) 2 0 3
101: 59(ivec4) SpecConstantOp 124 58
102: TypeVector 50(bool) 4
103: 102(bvec4) SpecConstantOp 170 101 62
104: 50(bool) SpecConstantOp 155 103
105: 59(ivec4) SpecConstantOp 124 58
106: 50(bool) SpecConstantOp 154 0
107: TypeVector 6(float) 2
108(int_float_double_vec2): TypeStruct 8(int) 6(float) 13(float) 107(fvec2)
109: 6(float) Constant 1065353216
110: 107(fvec2) SpecConstantComposite 15 109
111:108(int_float_double_vec2) SpecConstantComposite 9 7 14 110
112: 107(fvec2) SpecConstantComposite 15 109
113:108(int_float_double_vec2) SpecConstantComposite 9 7 14 112
114: 8(int) SpecConstantOp 81 111 0
115: 8(int) SpecConstantOp 81 113 0
116: 50(bool) SpecConstantOp 170 114 115
117: 6(float) SpecConstantOp 81 111 1(GLSL.std.450)
118: 6(float) SpecConstantOp 81 113 1(GLSL.std.450)
119: 50(bool) SpecConstantOp 180 117 118
120: 50(bool) SpecConstantOp 167 116 119
121: 13(float) SpecConstantOp 81 111 2
122: 13(float) SpecConstantOp 81 113 2
123: 50(bool) SpecConstantOp 180 121 122
124: 50(bool) SpecConstantOp 167 120 123
125: 107(fvec2) SpecConstantOp 81 111 3
126: 107(fvec2) SpecConstantOp 81 113 3
127: TypeVector 50(bool) 2
128: 127(bvec2) SpecConstantOp 180 125 126
129: 50(bool) SpecConstantOp 155 128
130: 50(bool) SpecConstantOp 167 124 129
131: 8(int) SpecConstantOp 81 111 0
132: 8(int) SpecConstantOp 81 113 0
133: 6(float) SpecConstantOp 81 111 1(GLSL.std.450)
134: 6(float) SpecConstantOp 81 113 1(GLSL.std.450)
135: 50(bool) SpecConstantOp 182 133 134
136: 50(bool) SpecConstantOp 166 0 135
137: 13(float) SpecConstantOp 81 111 2
138: 13(float) SpecConstantOp 81 113 2
139: 50(bool) SpecConstantOp 182 137 138
140: 50(bool) SpecConstantOp 166 136 139
141: 107(fvec2) SpecConstantOp 81 111 3
142: 107(fvec2) SpecConstantOp 81 113 3
143: 127(bvec2) SpecConstantOp 182 141 142
144: 50(bool) SpecConstantOp 154 143
145: 50(bool) SpecConstantOp 166 140 144
146: TypeArray 6(float) 26
147: 146 SpecConstantComposite 7 7
148: 146 SpecConstantComposite 7 7
149: 6(float) SpecConstantOp 81 147 0
150: 6(float) SpecConstantOp 81 148 0
151: 50(bool) SpecConstantOp 180 149 150
152: 6(float) SpecConstantOp 81 147 1(GLSL.std.450)
153: 6(float) SpecConstantOp 81 148 1(GLSL.std.450)
154: 50(bool) SpecConstantOp 180 152 153
155: 50(bool) SpecConstantOp 167 151 154
156: 6(float) SpecConstantOp 81 147 0
157: 6(float) SpecConstantOp 81 148 0
158: 50(bool) SpecConstantOp 182 156 157
159: 6(float) SpecConstantOp 81 147 1(GLSL.std.450)
160: 6(float) SpecConstantOp 81 148 1(GLSL.std.450)
161: 50(bool) SpecConstantOp 182 159 160
162: 50(bool) SpecConstantOp 166 158 161
4(main): 2 Function None 3
5: Label
Return
FunctionEnd

View File

@ -0,0 +1,127 @@
#version 450
layout(constant_id = 200) const float sp_float = 3.1415926;
layout(constant_id = 201) const int sp_int = 10;
layout(constant_id = 202) const uint sp_uint = 100;
layout(constant_id = 203) const int sp_sint = -10;
//
// Scalars
//
// Size convert
const double float_to_double = double(sp_float);
const float double_to_float = float(float_to_double);
// Negate and Not
const int negate_int = -sp_int;
const int not_int = ~sp_int;
// Add and Subtract
const int sp_int_add_two = sp_int + 2;
const int sp_int_add_two_sub_three = sp_int + 2 - 3;
const int sp_int_add_two_sub_four = sp_int_add_two - 4;
// Mul, Div and Rem
const int sp_sint_mul_two = sp_sint * 2;
const uint sp_uint_mul_two = sp_uint * 2;
const int sp_sint_mul_two_div_five = sp_sint_mul_two / 5;
const uint sp_uint_mul_two_div_five = sp_uint_mul_two / 5;
const int sp_sint_rem_four = sp_sint % 4;
const uint sp_uint_rem_four = sp_uint % 4;
const int sp_sint_mul_three_div_five = sp_sint * 3 / 5;
// Shift
const int sp_sint_shift_right_arithmetic = sp_sint >> 10;
const uint sp_uint_shift_right_arithmetic = sp_uint >> 20;
const int sp_sint_shift_left = sp_sint << 1;
const uint sp_uint_shift_left = sp_uint << 2;
// Bitwise And, Or, Xor
const int sp_sint_or_256 = sp_sint | 0x100;
const uint sp_uint_xor_512 = sp_uint ^ 0x200;
const int sp_sint_and_sp_uint = sp_sint & int(sp_uint);
// Scalar comparison
const bool sp_int_lt_sp_sint = sp_int < sp_sint;
const bool sp_uint_lt_sp_sint = sp_uint < sp_sint;
const bool sp_sint_lt_sp_uint = sp_sint < sp_uint;
//
// Vectors
//
const ivec4 iv = ivec4(20, 30, sp_int, sp_int);
const uvec4 uv = uvec4(sp_uint, sp_uint, -1, -2);
const vec4 fv = vec4(sp_float, 1.25, sp_float, 1.25);
// Size convert
const dvec4 fv_to_dv = dvec4(fv);
const vec4 dv_to_fv = vec4(fv_to_dv);
// Negate and Not
const vec4 not_iv = ~iv;
const ivec4 negate_iv = -iv;
// Add and Subtract
const ivec4 iv_add_two = iv + 2;
const ivec4 iv_add_two_sub_three = iv + 2 - 3;
const ivec4 iv_add_two_sub_four = iv_add_two_sub_three - 4;
// Mul, Div and Rem
const ivec4 iv_mul_two = iv * 2;
const ivec4 iv_mul_two_div_five = iv_mul_two / 5;
const ivec4 iv_rem_four = iv % 4;
// Shift
const ivec4 iv_shift_right_arithmetic = iv >> 10;
const ivec4 iv_shift_left = iv << 2;
// Bitwise And, Or, Xor
const ivec4 iv_or_1024 = iv | 0x400;
const uvec4 uv_xor_2048 = uv ^ 0x800;
const ivec4 iv_and_uv = iv & ivec4(uv);
// Swizzles
const int iv_x = iv.x;
const ivec2 iv_yx = iv.yx;
const ivec3 iv_zyx = iv.zyx;
const ivec4 iv_yzxw = iv.yzxw;
// Vector comparison, only == and != are supported and allowd.
const bool iv_equal_uv = iv == uv;
const bool iv_not_equal_uv = iv != uv;
//
// Composite types other than vectors
//
// Struct
struct int_float_double_vec2 {
int i;
float f;
double d;
vec2 v;
};
const int_float_double_vec2 sp_struct_a = {
sp_int, sp_float, float_to_double,
vec2(double_to_float, 1.0)
};
const int_float_double_vec2 sp_struct_b = {
sp_int, sp_float, float_to_double,
vec2(double_to_float, 1.0)
};
const bool struct_a_equal_struct_b = sp_struct_a == sp_struct_b;
const bool struct_a_not_equal_struct_b = sp_struct_a != sp_struct_b;
// Array
const float array_a[2] = {sp_float, sp_float};
const float array_b[2] = {sp_float, sp_float};
const bool array_a_equal_array_b = array_a == array_b;
const bool array_a_not_equal_array_b = array_a != array_b;
void main() {}

View File

@ -103,6 +103,7 @@ spv.subpass.frag
spv.specConstant.vert spv.specConstant.vert
spv.specConstant.comp spv.specConstant.comp
spv.specConstantComposite.vert spv.specConstantComposite.vert
spv.specConstantOperations.vert
# GLSL-level semantics # GLSL-level semantics
vulkan.frag vulkan.frag
vulkan.vert vulkan.vert