diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index dd5afd4b..ee48b3c1 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -130,7 +130,7 @@ protected: void addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value); spv::Id createSpvConstant(const glslang::TIntermTyped&); 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 isTrivial(const glslang::TIntermTyped* node); 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); } +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. spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree( - const glslang::TIntermTyped* subTree) { + glslang::TIntermTyped* subTree) { const glslang::TType& glslangType = subTree->getType(); spv::Id typeId = convertGlslangToSpvType(glslangType); bool is_spec_const = subTree->getType().getQualifier().isSpecConstant(); if (const glslang::TIntermAggregate* an = subTree->getAsAggregate()) { // Aggregate node, we should generate OpConstantComposite or // OpSpecConstantComposite instruction. + std::vector const_constituents; for (auto NI = an->getSequence().begin(); NI != an->getSequence().end(); NI++) { @@ -3881,17 +3903,27 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree( 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 // This case should only happen when Specialization Constants are involved. - spv::MissingFunctionality("OpSpecConstantOp 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 // happen when specialization constants are involved. - spv::MissingFunctionality("OpSpecConstantOp 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()) { // ConstantUnion node, should redirect to diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index 336d3de3..3c0e2f63 100644 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -64,7 +64,8 @@ Builder::Builder(unsigned int magicNumber) : builderNumber(magicNumber), buildPoint(0), uniqueId(0), - mainFunction(0) + mainFunction(0), + generatingOpCodeForSpecConst(false) { clearAccessChain(); } @@ -1063,6 +1064,11 @@ Id Builder::createArrayLength(Id base, unsigned int member) 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); extract->addIdOperand(composite); 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& 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); extract->addIdOperand(composite); 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 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); op->addIdOperand(operand); buildPoint->addInstruction(std::unique_ptr(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) { + // 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); op->addIdOperand(left); op->addIdOperand(right); @@ -1208,6 +1229,102 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector& operands) return op->getResultId(); } +Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector& operands, const std::vector& 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(op)); + + return op->getResultId(); +} + Id Builder::createFunctionCall(spv::Function* function, std::vector& args) { 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) 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); assert(isVector(source)); swizzle->addIdOperand(source); @@ -1290,10 +1410,23 @@ Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType) if (numComponents == 1) return scalar; - Instruction* smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct); - for (int c = 0; c < numComponents; ++c) - smear->addIdOperand(scalar); - buildPoint->addInstruction(std::unique_ptr(smear)); + Instruction* smear = nullptr; + if (generatingOpCodeForSpecConst) { + auto members = std::vector(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) + smear->addIdOperand(scalar); + buildPoint->addInstruction(std::unique_ptr(smear)); + } return setPrecision(smear->getResultId(), precision); } diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h index e16ba38c..46bdee84 100755 --- a/SPIRV/SpvBuilder.h +++ b/SPIRV/SpvBuilder.h @@ -262,6 +262,7 @@ public: Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); Id createOp(Op, Id typeId, const std::vector& operands); Id createFunctionCall(spv::Function*, std::vector&); + Id createSpecConstantOp(Op, Id typeId, const std::vector& operands, const std::vector& literals); // Take an rvalue (source) and a set of channels to extract from it to // make a new rvalue, which is returned. @@ -521,6 +522,13 @@ public: void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); 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: Id makeIntConstant(Id typeId, unsigned value, bool specConstant); Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) const; @@ -544,6 +552,7 @@ public: Block* buildPoint; Id uniqueId; Function* mainFunction; + bool generatingOpCodeForSpecConst; AccessChain accessChain; // special blocks of instructions for output diff --git a/Test/baseResults/spv.specConstantOperations.vert.out b/Test/baseResults/spv.specConstantOperations.vert.out new file mode 100644 index 00000000..c3eaedd5 --- /dev/null +++ b/Test/baseResults/spv.specConstantOperations.vert.out @@ -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 diff --git a/Test/spv.specConstantOperations.vert b/Test/spv.specConstantOperations.vert new file mode 100644 index 00000000..93588bf8 --- /dev/null +++ b/Test/spv.specConstantOperations.vert @@ -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() {} + diff --git a/Test/test-spirv-list b/Test/test-spirv-list index 4534132f..b7dfd537 100644 --- a/Test/test-spirv-list +++ b/Test/test-spirv-list @@ -103,6 +103,7 @@ spv.subpass.frag spv.specConstant.vert spv.specConstant.comp spv.specConstantComposite.vert +spv.specConstantOperations.vert # GLSL-level semantics vulkan.frag vulkan.vert