SPV 1.4: Emit SignExtend and ZeroExtend for integer image reads/writes.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index f5cbb88..5a2b85a 100644
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -4182,15 +4182,26 @@
// Process a GLSL texturing op (will be SPV image)
- const glslang::TType &imageType = node->getAsAggregate() ? node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType()
- : node->getAsUnaryNode()->getOperand()->getAsTyped()->getType();
+ const glslang::TType &imageType = node->getAsAggregate()
+ ? node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType()
+ : node->getAsUnaryNode()->getOperand()->getAsTyped()->getType();
const glslang::TSampler sampler = imageType.getSampler();
#ifdef AMD_EXTENSIONS
bool f16ShadowCompare = (sampler.shadow && node->getAsAggregate())
- ? node->getAsAggregate()->getSequence()[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16
- : false;
+ ? node->getAsAggregate()->getSequence()[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16
+ : false;
#endif
+ const auto signExtensionMask = [&]() {
+ if (builder.getSpvVersion() >= spv::Spv_1_4) {
+ if (sampler.type == glslang::EbtUint)
+ return spv::ImageOperandsZeroExtendMask;
+ else if (sampler.type == glslang::EbtInt)
+ return spv::ImageOperandsSignExtendMask;
+ }
+ return spv::ImageOperandsMaskNone;
+ };
+
std::vector<spv::Id> arguments;
if (node->getAsAggregate())
translateArguments(*node->getAsAggregate(), arguments);
@@ -4269,11 +4280,17 @@
spv::IdImmediate coord = { true,
builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps) };
operands.push_back(coord);
+ spv::IdImmediate imageOperands = { false, spv::ImageOperandsMaskNone };
+ imageOperands.word = imageOperands.word | signExtensionMask();
if (sampler.ms) {
- spv::IdImmediate imageOperands = { false, spv::ImageOperandsSampleMask };
+ imageOperands.word = imageOperands.word | spv::ImageOperandsSampleMask;
+ }
+ if (imageOperands.word != spv::ImageOperandsMaskNone) {
operands.push_back(imageOperands);
- spv::IdImmediate imageOperand = { true, *(opIt++) };
- operands.push_back(imageOperand);
+ if (sampler.ms) {
+ spv::IdImmediate imageOperand = { true, *(opIt++) };
+ operands.push_back(imageOperand);
+ }
}
spv::Id result = builder.createOp(spv::OpImageRead, resultType(), operands);
builder.setPrecision(result, precision);
@@ -4300,7 +4317,8 @@
#endif
mask = mask | TranslateImageOperands(TranslateCoherent(imageType));
mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelAvailableKHRMask);
- if (mask) {
+ mask = mask | signExtensionMask();
+ if (mask != spv::MemoryAccessMaskNone) {
spv::IdImmediate imageOperands = { false, (unsigned int)mask };
operands.push_back(imageOperands);
}
@@ -4315,7 +4333,8 @@
}
#endif
if (mask & spv::ImageOperandsMakeTexelVisibleKHRMask) {
- spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) };
+ spv::IdImmediate imageOperand = { true,
+ builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) };
operands.push_back(imageOperand);
}
@@ -4362,7 +4381,8 @@
#endif
mask = mask | TranslateImageOperands(TranslateCoherent(imageType));
mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelVisibleKHRMask);
- if (mask) {
+ mask = mask | signExtensionMask();
+ if (mask != spv::MemoryAccessMaskNone) {
spv::IdImmediate imageOperands = { false, (unsigned int)mask };
operands.push_back(imageOperands);
}
@@ -4377,7 +4397,8 @@
}
#endif
if (mask & spv::ImageOperandsMakeTexelAvailableKHRMask) {
- spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) };
+ spv::IdImmediate imageOperand = { true,
+ builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) };
operands.push_back(imageOperand);
}
@@ -4386,7 +4407,8 @@
builder.addCapability(spv::CapabilityStorageImageWriteWithoutFormat);
return spv::NoResult;
#ifdef AMD_EXTENSIONS
- } else if (node->getOp() == glslang::EOpSparseImageLoad || node->getOp() == glslang::EOpSparseImageLoadLod) {
+ } else if (node->getOp() == glslang::EOpSparseImageLoad ||
+ node->getOp() == glslang::EOpSparseImageLoadLod) {
#else
} else if (node->getOp() == glslang::EOpSparseImageLoad) {
#endif
@@ -4408,7 +4430,8 @@
#endif
mask = mask | TranslateImageOperands(TranslateCoherent(imageType));
mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelAvailableKHRMask);
- if (mask) {
+ mask = mask | signExtensionMask();
+ if (mask != spv::MemoryAccessMaskNone) {
spv::IdImmediate imageOperands = { false, (unsigned int)mask };
operands.push_back(imageOperands);
}
@@ -4710,7 +4733,8 @@
spv::Id resType = builder.makeStructType(members, "ResType");
//call ImageFootprintNV
- spv::Id res = builder.createTextureCall(precision, resType, sparse, cracked.fetch, cracked.proj, cracked.gather, noImplicitLod, params);
+ spv::Id res = builder.createTextureCall(precision, resType, sparse, cracked.fetch, cracked.proj,
+ cracked.gather, noImplicitLod, params, signExtensionMask());
//copy resType (SPIR-V type) to resultStructType(OpenGL type)
for (int i = 0; i < 5; i++) {
@@ -4763,7 +4787,8 @@
}
std::vector<spv::Id> result( 1,
- builder.createTextureCall(precision, resultType(), sparse, cracked.fetch, cracked.proj, cracked.gather, noImplicitLod, params)
+ builder.createTextureCall(precision, resultType(), sparse, cracked.fetch, cracked.proj, cracked.gather,
+ noImplicitLod, params, signExtensionMask())
);
if (components != node->getType().getVectorSize())
diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp
index 773e5f1..4ef7e5f 100644
--- a/SPIRV/SpvBuilder.cpp
+++ b/SPIRV/SpvBuilder.cpp
@@ -1808,7 +1808,7 @@
// Accept all parameters needed to create a texture instruction.
// Create the correct instruction based on the inputs, and make the call.
Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather,
- bool noImplicitLod, const TextureParameters& parameters)
+ bool noImplicitLod, const TextureParameters& parameters, ImageOperandsMask signExtensionMask)
{
static const int maxTextureArgs = 10;
Id texArgs[maxTextureArgs] = {};
@@ -1835,8 +1835,8 @@
//
// Set up the optional arguments
//
- int optArgNum = numArgs; // track which operand, if it exists, is the mask of optional arguments
- ++numArgs; // speculatively make room for the mask operand
+ int optArgNum = numArgs; // track which operand, if it exists, is the mask of optional arguments
+ ++numArgs; // speculatively make room for the mask operand
ImageOperandsMask mask = ImageOperandsMaskNone; // the mask operand
if (parameters.bias) {
mask = (ImageOperandsMask)(mask | ImageOperandsBiasMask);
@@ -1889,6 +1889,7 @@
if (parameters.volatil) {
mask = mask | ImageOperandsVolatileTexelKHRMask;
}
+ mask = mask | signExtensionMask;
if (mask == ImageOperandsMaskNone)
--numArgs; // undo speculative reservation for the mask argument
else
diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h
index aee9781..faed8e8 100644
--- a/SPIRV/SpvBuilder.h
+++ b/SPIRV/SpvBuilder.h
@@ -416,7 +416,8 @@
};
// Select the correct texture operation based on all inputs, and emit the correct instruction
- Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, bool noImplicit, const TextureParameters&);
+ Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather,
+ bool noImplicit, const TextureParameters&, ImageOperandsMask);
// Emit the OpTextureQuery* instruction that was passed in.
// Figure out the right return value and type, and return it.
diff --git a/SPIRV/doc.cpp b/SPIRV/doc.cpp
index 0d2540a..3b85767 100644
--- a/SPIRV/doc.cpp
+++ b/SPIRV/doc.cpp
@@ -575,7 +575,7 @@
}
}
-const int ImageOperandsCeiling = 12;
+const int ImageOperandsCeiling = 14;
const char* ImageOperandsString(int format)
{
@@ -592,6 +592,8 @@
case ImageOperandsMakeTexelVisibleKHRShift: return "MakeTexelVisibleKHR";
case ImageOperandsNonPrivateTexelKHRShift: return "NonPrivateTexelKHR";
case ImageOperandsVolatileTexelKHRShift: return "VolatileTexelKHR";
+ case ImageOperandsSignExtendShift: return "SignExtend";
+ case ImageOperandsZeroExtendShift: return "ZeroExtend";
case ImageOperandsCeiling:
default:
diff --git a/Test/baseResults/spv.1.4.image.frag.out b/Test/baseResults/spv.1.4.image.frag.out
new file mode 100755
index 0000000..02e379c
--- /dev/null
+++ b/Test/baseResults/spv.1.4.image.frag.out
@@ -0,0 +1,160 @@
+spv.1.4.image.frag
+Validation failed
+// Module Version 10400
+// Generated by (magic number): 80007
+// Id's are bound by 104
+
+ Capability Shader
+ Capability StorageImageMultisample
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Fragment 4 "main" 26 30 40 52 64 77 89 100 103
+ ExecutionMode 4 OriginUpperLeft
+ Source GLSL 450
+ Name 4 "main"
+ Name 9 "v"
+ Name 15 "iv"
+ Name 21 "uv"
+ Name 26 "i2D"
+ Name 30 "ic2D"
+ Name 40 "ii2D"
+ Name 52 "ui2D"
+ Name 64 "i2DMS"
+ Name 77 "ii2DMS"
+ Name 89 "ui2DMS"
+ Name 100 "fragData"
+ Name 103 "value"
+ Decorate 26(i2D) DescriptorSet 0
+ Decorate 26(i2D) Binding 1
+ Decorate 30(ic2D) Flat
+ Decorate 40(ii2D) DescriptorSet 0
+ Decorate 40(ii2D) Binding 12
+ Decorate 52(ui2D) DescriptorSet 0
+ Decorate 52(ui2D) Binding 12
+ Decorate 64(i2DMS) DescriptorSet 0
+ Decorate 64(i2DMS) Binding 9
+ Decorate 77(ii2DMS) DescriptorSet 0
+ Decorate 77(ii2DMS) Binding 13
+ Decorate 89(ui2DMS) DescriptorSet 0
+ Decorate 89(ui2DMS) Binding 13
+ Decorate 103(value) Flat
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeFloat 32
+ 7: TypeVector 6(float) 4
+ 8: TypePointer Function 7(fvec4)
+ 10: 6(float) Constant 0
+ 11: 7(fvec4) ConstantComposite 10 10 10 10
+ 12: TypeInt 32 1
+ 13: TypeVector 12(int) 4
+ 14: TypePointer Function 13(ivec4)
+ 16: 12(int) Constant 0
+ 17: 13(ivec4) ConstantComposite 16 16 16 16
+ 18: TypeInt 32 0
+ 19: TypeVector 18(int) 4
+ 20: TypePointer Function 19(ivec4)
+ 22: 18(int) Constant 0
+ 23: 19(ivec4) ConstantComposite 22 22 22 22
+ 24: TypeImage 6(float) 2D nonsampled format:Rgba32f
+ 25: TypePointer UniformConstant 24
+ 26(i2D): 25(ptr) Variable UniformConstant
+ 28: TypeVector 12(int) 2
+ 29: TypePointer Input 28(ivec2)
+ 30(ic2D): 29(ptr) Variable Input
+ 38: TypeImage 12(int) 2D nonsampled format:R32i
+ 39: TypePointer UniformConstant 38
+ 40(ii2D): 39(ptr) Variable UniformConstant
+ 50: TypeImage 18(int) 2D nonsampled format:R32ui
+ 51: TypePointer UniformConstant 50
+ 52(ui2D): 51(ptr) Variable UniformConstant
+ 62: TypeImage 6(float) 2D multi-sampled nonsampled format:Rgba32f
+ 63: TypePointer UniformConstant 62
+ 64(i2DMS): 63(ptr) Variable UniformConstant
+ 67: 12(int) Constant 1
+ 73: 12(int) Constant 2
+ 75: TypeImage 12(int) 2D multi-sampled nonsampled format:R32i
+ 76: TypePointer UniformConstant 75
+ 77(ii2DMS): 76(ptr) Variable UniformConstant
+ 87: TypeImage 18(int) 2D multi-sampled nonsampled format:R32ui
+ 88: TypePointer UniformConstant 87
+ 89(ui2DMS): 88(ptr) Variable UniformConstant
+ 99: TypePointer Output 7(fvec4)
+ 100(fragData): 99(ptr) Variable Output
+ 102: TypePointer Input 18(int)
+ 103(value): 102(ptr) Variable Input
+ 4(main): 2 Function None 3
+ 5: Label
+ 9(v): 8(ptr) Variable Function
+ 15(iv): 14(ptr) Variable Function
+ 21(uv): 20(ptr) Variable Function
+ Store 9(v) 11
+ Store 15(iv) 17
+ Store 21(uv) 23
+ 27: 24 Load 26(i2D)
+ 31: 28(ivec2) Load 30(ic2D)
+ 32: 7(fvec4) ImageRead 27 31
+ 33: 7(fvec4) Load 9(v)
+ 34: 7(fvec4) FAdd 33 32
+ Store 9(v) 34
+ 35: 24 Load 26(i2D)
+ 36: 28(ivec2) Load 30(ic2D)
+ 37: 7(fvec4) Load 9(v)
+ ImageWrite 35 36 37
+ 41: 38 Load 40(ii2D)
+ 42: 28(ivec2) Load 30(ic2D)
+ 43: 13(ivec4) ImageRead 41 42 SignExtend
+ 44: 7(fvec4) ConvertSToF 43
+ 45: 7(fvec4) Load 9(v)
+ 46: 7(fvec4) FAdd 45 44
+ Store 9(v) 46
+ 47: 38 Load 40(ii2D)
+ 48: 28(ivec2) Load 30(ic2D)
+ 49: 13(ivec4) Load 15(iv)
+ ImageWrite 47 48 49 SignExtend
+ 53: 50 Load 52(ui2D)
+ 54: 28(ivec2) Load 30(ic2D)
+ 55: 19(ivec4) ImageRead 53 54 ZeroExtend
+ 56: 7(fvec4) ConvertUToF 55
+ 57: 7(fvec4) Load 9(v)
+ 58: 7(fvec4) FAdd 57 56
+ Store 9(v) 58
+ 59: 50 Load 52(ui2D)
+ 60: 28(ivec2) Load 30(ic2D)
+ 61: 19(ivec4) Load 21(uv)
+ ImageWrite 59 60 61 ZeroExtend
+ 65: 62 Load 64(i2DMS)
+ 66: 28(ivec2) Load 30(ic2D)
+ 68: 7(fvec4) ImageRead 65 66 Sample 67
+ 69: 7(fvec4) Load 9(v)
+ 70: 7(fvec4) FAdd 69 68
+ Store 9(v) 70
+ 71: 62 Load 64(i2DMS)
+ 72: 28(ivec2) Load 30(ic2D)
+ 74: 7(fvec4) Load 9(v)
+ ImageWrite 71 72 74 Sample 73
+ 78: 75 Load 77(ii2DMS)
+ 79: 28(ivec2) Load 30(ic2D)
+ 80: 13(ivec4) ImageRead 78 79 Sample SignExtend 67
+ 81: 7(fvec4) ConvertSToF 80
+ 82: 7(fvec4) Load 9(v)
+ 83: 7(fvec4) FAdd 82 81
+ Store 9(v) 83
+ 84: 75 Load 77(ii2DMS)
+ 85: 28(ivec2) Load 30(ic2D)
+ 86: 13(ivec4) Load 15(iv)
+ ImageWrite 84 85 86 Sample SignExtend 73
+ 90: 87 Load 89(ui2DMS)
+ 91: 28(ivec2) Load 30(ic2D)
+ 92: 19(ivec4) ImageRead 90 91 Sample ZeroExtend 67
+ 93: 7(fvec4) ConvertUToF 92
+ 94: 7(fvec4) Load 9(v)
+ 95: 7(fvec4) FAdd 94 93
+ Store 9(v) 95
+ 96: 87 Load 89(ui2DMS)
+ 97: 28(ivec2) Load 30(ic2D)
+ 98: 19(ivec4) Load 21(uv)
+ ImageWrite 96 97 98 Sample ZeroExtend 73
+ 101: 7(fvec4) Load 9(v)
+ Store 100(fragData) 101
+ Return
+ FunctionEnd
diff --git a/Test/baseResults/spv.1.4.sparseTexture.frag.out b/Test/baseResults/spv.1.4.sparseTexture.frag.out
new file mode 100755
index 0000000..a36d802
--- /dev/null
+++ b/Test/baseResults/spv.1.4.sparseTexture.frag.out
@@ -0,0 +1,327 @@
+spv.1.4.sparseTexture.frag
+Validation failed
+// Module Version 10400
+// Generated by (magic number): 80007
+// Id's are bound by 213
+
+ Capability Shader
+ Capability StorageImageMultisample
+ Capability SparseResidency
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Fragment 4 "main" 29 33 42 46 59 63 84 96 119 133 149 152 159 162 177 181 189 206 208 212
+ ExecutionMode 4 OriginUpperLeft
+ Source GLSL 450
+ SourceExtension "GL_ARB_sparse_texture2"
+ Name 4 "main"
+ Name 8 "resident"
+ Name 13 "texel"
+ Name 18 "itexel"
+ Name 23 "utexel"
+ Name 29 "s2D"
+ Name 33 "c2"
+ Name 35 "ResType"
+ Name 42 "tempReturn"
+ Name 46 "is2D"
+ Name 49 "tempArg"
+ Name 50 "ResType"
+ Name 59 "tempReturn"
+ Name 63 "us2D"
+ Name 66 "tempArg"
+ Name 67 "ResType"
+ Name 84 "tempReturn"
+ Name 87 "tempArg"
+ Name 96 "tempReturn"
+ Name 99 "tempArg"
+ Name 119 "tempReturn"
+ Name 123 "tempArg"
+ Name 133 "tempReturn"
+ Name 137 "tempArg"
+ Name 149 "i2D"
+ Name 152 "ic2"
+ Name 159 "tempReturn"
+ Name 162 "ii2DMS"
+ Name 166 "tempArg"
+ Name 177 "ui3D"
+ Name 181 "ic3"
+ Name 189 "outColor"
+ Name 206 "c3"
+ Name 208 "c4"
+ Name 212 "offsets"
+ Decorate 29(s2D) DescriptorSet 0
+ Decorate 29(s2D) Binding 0
+ Decorate 46(is2D) DescriptorSet 0
+ Decorate 46(is2D) Binding 0
+ Decorate 63(us2D) DescriptorSet 0
+ Decorate 63(us2D) Binding 0
+ Decorate 149(i2D) DescriptorSet 0
+ Decorate 149(i2D) Binding 0
+ Decorate 152(ic2) Flat
+ Decorate 162(ii2DMS) DescriptorSet 0
+ Decorate 162(ii2DMS) Binding 0
+ Decorate 177(ui3D) DescriptorSet 0
+ Decorate 177(ui3D) Binding 0
+ Decorate 181(ic3) Flat
+ Decorate 212(offsets) Flat
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeInt 32 1
+ 7: TypePointer Function 6(int)
+ 9: 6(int) Constant 0
+ 10: TypeFloat 32
+ 11: TypeVector 10(float) 4
+ 12: TypePointer Function 11(fvec4)
+ 14: 10(float) Constant 0
+ 15: 11(fvec4) ConstantComposite 14 14 14 14
+ 16: TypeVector 6(int) 4
+ 17: TypePointer Function 16(ivec4)
+ 19: 16(ivec4) ConstantComposite 9 9 9 9
+ 20: TypeInt 32 0
+ 21: TypeVector 20(int) 4
+ 22: TypePointer Function 21(ivec4)
+ 24: 20(int) Constant 0
+ 25: 21(ivec4) ConstantComposite 24 24 24 24
+ 26: TypeImage 10(float) 2D sampled format:Unknown
+ 27: TypeSampledImage 26
+ 28: TypePointer UniformConstant 27
+ 29(s2D): 28(ptr) Variable UniformConstant
+ 31: TypeVector 10(float) 2
+ 32: TypePointer Input 31(fvec2)
+ 33(c2): 32(ptr) Variable Input
+ 35(ResType): TypeStruct 6(int) 11(fvec4)
+ 41: TypePointer Private 6(int)
+ 42(tempReturn): 41(ptr) Variable Private
+ 43: TypeImage 6(int) 2D sampled format:Unknown
+ 44: TypeSampledImage 43
+ 45: TypePointer UniformConstant 44
+ 46(is2D): 45(ptr) Variable UniformConstant
+ 50(ResType): TypeStruct 6(int) 16(ivec4)
+ 59(tempReturn): 41(ptr) Variable Private
+ 60: TypeImage 20(int) 2D sampled format:Unknown
+ 61: TypeSampledImage 60
+ 62: TypePointer UniformConstant 61
+ 63(us2D): 62(ptr) Variable UniformConstant
+ 67(ResType): TypeStruct 6(int) 21(ivec4)
+ 78: 10(float) Constant 1073741824
+ 84(tempReturn): 41(ptr) Variable Private
+ 96(tempReturn): 41(ptr) Variable Private
+ 110: TypeVector 6(int) 2
+ 112: 6(int) Constant 2
+ 119(tempReturn): 41(ptr) Variable Private
+ 133(tempReturn): 41(ptr) Variable Private
+ 147: TypeImage 10(float) 2D nonsampled format:Rgba32f
+ 148: TypePointer UniformConstant 147
+ 149(i2D): 148(ptr) Variable UniformConstant
+ 151: TypePointer Input 110(ivec2)
+ 152(ic2): 151(ptr) Variable Input
+ 159(tempReturn): 41(ptr) Variable Private
+ 160: TypeImage 6(int) 2D multi-sampled nonsampled format:Rgba32i
+ 161: TypePointer UniformConstant 160
+ 162(ii2DMS): 161(ptr) Variable UniformConstant
+ 165: 6(int) Constant 3
+ 175: TypeImage 20(int) 3D nonsampled format:Rgba32ui
+ 176: TypePointer UniformConstant 175
+ 177(ui3D): 176(ptr) Variable UniformConstant
+ 179: TypeVector 6(int) 3
+ 180: TypePointer Input 179(ivec3)
+ 181(ic3): 180(ptr) Variable Input
+ 188: TypePointer Output 11(fvec4)
+ 189(outColor): 188(ptr) Variable Output
+ 191: TypeBool
+ 204: TypeVector 10(float) 3
+ 205: TypePointer Input 204(fvec3)
+ 206(c3): 205(ptr) Variable Input
+ 207: TypePointer Input 11(fvec4)
+ 208(c4): 207(ptr) Variable Input
+ 209: 20(int) Constant 4
+ 210: TypeArray 110(ivec2) 209
+ 211: TypePointer Input 210
+ 212(offsets): 211(ptr) Variable Input
+ 4(main): 2 Function None 3
+ 5: Label
+ 8(resident): 7(ptr) Variable Function
+ 13(texel): 12(ptr) Variable Function
+ 18(itexel): 17(ptr) Variable Function
+ 23(utexel): 22(ptr) Variable Function
+ 49(tempArg): 17(ptr) Variable Function
+ 66(tempArg): 22(ptr) Variable Function
+ 87(tempArg): 17(ptr) Variable Function
+ 99(tempArg): 22(ptr) Variable Function
+ 123(tempArg): 17(ptr) Variable Function
+ 137(tempArg): 22(ptr) Variable Function
+ 166(tempArg): 17(ptr) Variable Function
+ 193: 12(ptr) Variable Function
+ Store 8(resident) 9
+ Store 13(texel) 15
+ Store 18(itexel) 19
+ Store 23(utexel) 25
+ 30: 27 Load 29(s2D)
+ 34: 31(fvec2) Load 33(c2)
+ 36: 35(ResType) ImageSparseSampleImplicitLod 30 34
+ 37: 11(fvec4) CompositeExtract 36 1
+ Store 13(texel) 37
+ 38: 6(int) CompositeExtract 36 0
+ 39: 6(int) Load 8(resident)
+ 40: 6(int) BitwiseOr 39 38
+ Store 8(resident) 40
+ 47: 44 Load 46(is2D)
+ 48: 31(fvec2) Load 33(c2)
+ 51: 50(ResType) ImageSparseSampleImplicitLod 47 48 SignExtend
+ 52: 16(ivec4) CompositeExtract 51 1
+ Store 49(tempArg) 52
+ 53: 6(int) CompositeExtract 51 0
+ Store 42(tempReturn) 53
+ 54: 16(ivec4) Load 49(tempArg)
+ 55: 11(fvec4) ConvertSToF 54
+ Store 13(texel) 55
+ 56: 6(int) Load 42(tempReturn)
+ 57: 6(int) Load 8(resident)
+ 58: 6(int) BitwiseOr 57 56
+ Store 8(resident) 58
+ 64: 61 Load 63(us2D)
+ 65: 31(fvec2) Load 33(c2)
+ 68: 67(ResType) ImageSparseSampleImplicitLod 64 65 ZeroExtend
+ 69: 21(ivec4) CompositeExtract 68 1
+ Store 66(tempArg) 69
+ 70: 6(int) CompositeExtract 68 0
+ Store 59(tempReturn) 70
+ 71: 21(ivec4) Load 66(tempArg)
+ 72: 11(fvec4) ConvertUToF 71
+ Store 13(texel) 72
+ 73: 6(int) Load 59(tempReturn)
+ 74: 6(int) Load 8(resident)
+ 75: 6(int) BitwiseOr 74 73
+ Store 8(resident) 75
+ 76: 27 Load 29(s2D)
+ 77: 31(fvec2) Load 33(c2)
+ 79: 35(ResType) ImageSparseSampleExplicitLod 76 77 Lod 78
+ 80: 11(fvec4) CompositeExtract 79 1
+ Store 13(texel) 80
+ 81: 6(int) CompositeExtract 79 0
+ 82: 6(int) Load 8(resident)
+ 83: 6(int) BitwiseOr 82 81
+ Store 8(resident) 83
+ 85: 44 Load 46(is2D)
+ 86: 31(fvec2) Load 33(c2)
+ 88: 50(ResType) ImageSparseSampleExplicitLod 85 86 Lod SignExtend 78
+ 89: 16(ivec4) CompositeExtract 88 1
+ Store 87(tempArg) 89
+ 90: 6(int) CompositeExtract 88 0
+ Store 84(tempReturn) 90
+ 91: 16(ivec4) Load 87(tempArg)
+ 92: 11(fvec4) ConvertSToF 91
+ Store 13(texel) 92
+ 93: 6(int) Load 84(tempReturn)
+ 94: 6(int) Load 8(resident)
+ 95: 6(int) BitwiseOr 94 93
+ Store 8(resident) 95
+ 97: 61 Load 63(us2D)
+ 98: 31(fvec2) Load 33(c2)
+ 100: 67(ResType) ImageSparseSampleExplicitLod 97 98 Lod ZeroExtend 78
+ 101: 21(ivec4) CompositeExtract 100 1
+ Store 99(tempArg) 101
+ 102: 6(int) CompositeExtract 100 0
+ Store 96(tempReturn) 102
+ 103: 21(ivec4) Load 99(tempArg)
+ 104: 11(fvec4) ConvertUToF 103
+ Store 13(texel) 104
+ 105: 6(int) Load 96(tempReturn)
+ 106: 6(int) Load 8(resident)
+ 107: 6(int) BitwiseOr 106 105
+ Store 8(resident) 107
+ 108: 27 Load 29(s2D)
+ 109: 31(fvec2) Load 33(c2)
+ 111: 110(ivec2) ConvertFToS 109
+ 113: 26 Image 108
+ 114: 35(ResType) ImageSparseFetch 113 111 Lod 112
+ 115: 11(fvec4) CompositeExtract 114 1
+ Store 13(texel) 115
+ 116: 6(int) CompositeExtract 114 0
+ 117: 6(int) Load 8(resident)
+ 118: 6(int) BitwiseOr 117 116
+ Store 8(resident) 118
+ 120: 44 Load 46(is2D)
+ 121: 31(fvec2) Load 33(c2)
+ 122: 110(ivec2) ConvertFToS 121
+ 124: 43 Image 120
+ 125: 50(ResType) ImageSparseFetch 124 122 Lod SignExtend 112
+ 126: 16(ivec4) CompositeExtract 125 1
+ Store 123(tempArg) 126
+ 127: 6(int) CompositeExtract 125 0
+ Store 119(tempReturn) 127
+ 128: 16(ivec4) Load 123(tempArg)
+ 129: 11(fvec4) ConvertSToF 128
+ Store 13(texel) 129
+ 130: 6(int) Load 119(tempReturn)
+ 131: 6(int) Load 8(resident)
+ 132: 6(int) BitwiseOr 131 130
+ Store 8(resident) 132
+ 134: 61 Load 63(us2D)
+ 135: 31(fvec2) Load 33(c2)
+ 136: 110(ivec2) ConvertFToS 135
+ 138: 60 Image 134
+ 139: 67(ResType) ImageSparseFetch 138 136 Lod ZeroExtend 112
+ 140: 21(ivec4) CompositeExtract 139 1
+ Store 137(tempArg) 140
+ 141: 6(int) CompositeExtract 139 0
+ Store 133(tempReturn) 141
+ 142: 21(ivec4) Load 137(tempArg)
+ 143: 11(fvec4) ConvertUToF 142
+ Store 13(texel) 143
+ 144: 6(int) Load 133(tempReturn)
+ 145: 6(int) Load 8(resident)
+ 146: 6(int) BitwiseOr 145 144
+ Store 8(resident) 146
+ 150: 147 Load 149(i2D)
+ 153: 110(ivec2) Load 152(ic2)
+ 154: 35(ResType) ImageSparseRead 150 153
+ 155: 11(fvec4) CompositeExtract 154 1
+ Store 13(texel) 155
+ 156: 6(int) CompositeExtract 154 0
+ 157: 6(int) Load 8(resident)
+ 158: 6(int) BitwiseOr 157 156
+ Store 8(resident) 158
+ 163: 160 Load 162(ii2DMS)
+ 164: 110(ivec2) Load 152(ic2)
+ 167: 50(ResType) ImageSparseRead 163 164 Sample SignExtend 165
+ 168: 16(ivec4) CompositeExtract 167 1
+ Store 166(tempArg) 168
+ 169: 6(int) CompositeExtract 167 0
+ Store 159(tempReturn) 169
+ 170: 16(ivec4) Load 166(tempArg)
+ 171: 11(fvec4) ConvertSToF 170
+ Store 13(texel) 171
+ 172: 6(int) Load 159(tempReturn)
+ 173: 6(int) Load 8(resident)
+ 174: 6(int) BitwiseOr 173 172
+ Store 8(resident) 174
+ 178: 175 Load 177(ui3D)
+ 182: 179(ivec3) Load 181(ic3)
+ 183: 67(ResType) ImageSparseRead 178 182 ZeroExtend
+ 184: 21(ivec4) CompositeExtract 183 1
+ Store 23(utexel) 184
+ 185: 6(int) CompositeExtract 183 0
+ 186: 6(int) Load 8(resident)
+ 187: 6(int) BitwiseOr 186 185
+ Store 8(resident) 187
+ 190: 6(int) Load 8(resident)
+ 192: 191(bool) ImageSparseTexelsResident 190
+ SelectionMerge 195 None
+ BranchConditional 192 194 197
+ 194: Label
+ 196: 11(fvec4) Load 13(texel)
+ Store 193 196
+ Branch 195
+ 197: Label
+ 198: 16(ivec4) Load 18(itexel)
+ 199: 11(fvec4) ConvertSToF 198
+ 200: 21(ivec4) Load 23(utexel)
+ 201: 11(fvec4) ConvertUToF 200
+ 202: 11(fvec4) FAdd 199 201
+ Store 193 202
+ Branch 195
+ 195: Label
+ 203: 11(fvec4) Load 193
+ Store 189(outColor) 203
+ Return
+ FunctionEnd
diff --git a/Test/baseResults/spv.1.4.texture.frag.out b/Test/baseResults/spv.1.4.texture.frag.out
new file mode 100755
index 0000000..3186db4
--- /dev/null
+++ b/Test/baseResults/spv.1.4.texture.frag.out
@@ -0,0 +1,116 @@
+spv.1.4.texture.frag
+Validation failed
+// Module Version 10400
+// Generated by (magic number): 80007
+// Id's are bound by 79
+
+ Capability Shader
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Fragment 4 "main" 15 19 28 40 51 54 76 78
+ ExecutionMode 4 OriginUpperLeft
+ Source GLSL 450
+ Name 4 "main"
+ Name 9 "color"
+ Name 15 "texSampler2D"
+ Name 19 "coords2D"
+ Name 28 "itexSampler2D"
+ Name 40 "utexSampler2D"
+ Name 51 "iCoords2D"
+ Name 54 "iLod"
+ Name 76 "t"
+ Name 78 "color"
+ Decorate 15(texSampler2D) DescriptorSet 0
+ Decorate 15(texSampler2D) Binding 0
+ Decorate 28(itexSampler2D) DescriptorSet 0
+ Decorate 28(itexSampler2D) Binding 0
+ Decorate 40(utexSampler2D) DescriptorSet 0
+ Decorate 40(utexSampler2D) Binding 0
+ Decorate 51(iCoords2D) Flat
+ Decorate 54(iLod) Flat
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeFloat 32
+ 7: TypeVector 6(float) 4
+ 8: TypePointer Function 7(fvec4)
+ 10: 6(float) Constant 0
+ 11: 7(fvec4) ConstantComposite 10 10 10 10
+ 12: TypeImage 6(float) 2D sampled format:Unknown
+ 13: TypeSampledImage 12
+ 14: TypePointer UniformConstant 13
+15(texSampler2D): 14(ptr) Variable UniformConstant
+ 17: TypeVector 6(float) 2
+ 18: TypePointer Input 17(fvec2)
+ 19(coords2D): 18(ptr) Variable Input
+ 24: TypeInt 32 1
+ 25: TypeImage 24(int) 2D sampled format:Unknown
+ 26: TypeSampledImage 25
+ 27: TypePointer UniformConstant 26
+28(itexSampler2D): 27(ptr) Variable UniformConstant
+ 31: TypeVector 24(int) 4
+ 36: TypeInt 32 0
+ 37: TypeImage 36(int) 2D sampled format:Unknown
+ 38: TypeSampledImage 37
+ 39: TypePointer UniformConstant 38
+40(utexSampler2D): 39(ptr) Variable UniformConstant
+ 43: TypeVector 36(int) 4
+ 49: TypeVector 24(int) 2
+ 50: TypePointer Input 49(ivec2)
+ 51(iCoords2D): 50(ptr) Variable Input
+ 53: TypePointer Input 24(int)
+ 54(iLod): 53(ptr) Variable Input
+ 76(t): 18(ptr) Variable Input
+ 77: TypePointer Output 7(fvec4)
+ 78(color): 77(ptr) Variable Output
+ 4(main): 2 Function None 3
+ 5: Label
+ 9(color): 8(ptr) Variable Function
+ Store 9(color) 11
+ 16: 13 Load 15(texSampler2D)
+ 20: 17(fvec2) Load 19(coords2D)
+ 21: 7(fvec4) ImageSampleImplicitLod 16 20
+ 22: 7(fvec4) Load 9(color)
+ 23: 7(fvec4) FAdd 22 21
+ Store 9(color) 23
+ 29: 26 Load 28(itexSampler2D)
+ 30: 17(fvec2) Load 19(coords2D)
+ 32: 31(ivec4) ImageSampleImplicitLod 29 30 SignExtend
+ 33: 7(fvec4) ConvertSToF 32
+ 34: 7(fvec4) Load 9(color)
+ 35: 7(fvec4) FAdd 34 33
+ Store 9(color) 35
+ 41: 38 Load 40(utexSampler2D)
+ 42: 17(fvec2) Load 19(coords2D)
+ 44: 43(ivec4) ImageSampleImplicitLod 41 42 ZeroExtend
+ 45: 7(fvec4) ConvertUToF 44
+ 46: 7(fvec4) Load 9(color)
+ 47: 7(fvec4) FAdd 46 45
+ Store 9(color) 47
+ 48: 13 Load 15(texSampler2D)
+ 52: 49(ivec2) Load 51(iCoords2D)
+ 55: 24(int) Load 54(iLod)
+ 56: 12 Image 48
+ 57: 7(fvec4) ImageFetch 56 52 Lod 55
+ 58: 7(fvec4) Load 9(color)
+ 59: 7(fvec4) FAdd 58 57
+ Store 9(color) 59
+ 60: 26 Load 28(itexSampler2D)
+ 61: 49(ivec2) Load 51(iCoords2D)
+ 62: 24(int) Load 54(iLod)
+ 63: 25 Image 60
+ 64: 31(ivec4) ImageFetch 63 61 Lod SignExtend 62
+ 65: 7(fvec4) ConvertSToF 64
+ 66: 7(fvec4) Load 9(color)
+ 67: 7(fvec4) FAdd 66 65
+ Store 9(color) 67
+ 68: 38 Load 40(utexSampler2D)
+ 69: 49(ivec2) Load 51(iCoords2D)
+ 70: 24(int) Load 54(iLod)
+ 71: 37 Image 68
+ 72: 43(ivec4) ImageFetch 71 69 Lod ZeroExtend 70
+ 73: 7(fvec4) ConvertUToF 72
+ 74: 7(fvec4) Load 9(color)
+ 75: 7(fvec4) FAdd 74 73
+ Store 9(color) 75
+ Return
+ FunctionEnd
diff --git a/Test/spv.1.4.image.frag b/Test/spv.1.4.image.frag
new file mode 100644
index 0000000..a835e3c
--- /dev/null
+++ b/Test/spv.1.4.image.frag
@@ -0,0 +1,38 @@
+#version 450
+
+layout(rgba32f, binding = 1) uniform image2D i2D;
+layout(r32i, binding = 12) uniform iimage2D ii2D;
+layout(r32ui, binding = 12) uniform uimage2D ui2D;
+
+layout(rgba32f, binding = 9) uniform image2DMS i2DMS;
+layout(r32i, binding = 13) uniform iimage2DMS ii2DMS;
+layout(r32ui, binding = 13) uniform uimage2DMS ui2DMS;
+
+flat in ivec2 ic2D;
+flat in uint value;
+
+out vec4 fragData;
+
+void main()
+{
+ vec4 v = vec4(0.0);
+ ivec4 iv = ivec4(0.0);
+ uvec4 uv = uvec4(0.0);
+
+ v += imageLoad(i2D, ic2D);
+ imageStore(i2D, ic2D, v);
+ v += imageLoad(ii2D, ic2D);
+ imageStore(ii2D, ic2D, iv);
+ v += imageLoad(ui2D, ic2D);
+ imageStore(ui2D, ic2D, uv);
+
+ v += imageLoad(i2DMS, ic2D, 1);
+ imageStore(i2DMS, ic2D, 2, v);
+ v += imageLoad(ii2DMS, ic2D, 1);
+ imageStore(ii2DMS, ic2D, 2, iv);
+ v += imageLoad(ui2DMS, ic2D, 1);
+ imageStore(ui2DMS, ic2D, 2, uv);
+
+ fragData = v;
+}
+
diff --git a/Test/spv.1.4.sparseTexture.frag b/Test/spv.1.4.sparseTexture.frag
new file mode 100644
index 0000000..fcddbeb
--- /dev/null
+++ b/Test/spv.1.4.sparseTexture.frag
@@ -0,0 +1,47 @@
+#version 450
+#extension GL_ARB_sparse_texture2: enable
+
+uniform sampler2D s2D;
+uniform isampler2D is2D;
+uniform usampler2D us2D;
+
+layout(rgba32f) uniform image2D i2D;
+layout(rgba32i) uniform iimage2DMS ii2DMS;
+layout(rgba32ui) uniform uimage3D ui3D;
+
+in vec2 c2;
+in vec3 c3;
+in vec4 c4;
+
+in flat ivec2 ic2;
+in flat ivec3 ic3;
+
+in flat ivec2 offsets[4];
+
+out vec4 outColor;
+
+void main()
+{
+ int resident = 0;
+ vec4 texel = vec4(0.0);
+ ivec4 itexel = ivec4(0);
+ uvec4 utexel = uvec4(0);
+
+ resident |= sparseTextureARB(s2D, c2, texel);
+ resident |= sparseTextureARB(is2D, c2, texel);
+ resident |= sparseTextureARB(us2D, c2, texel);
+
+ resident |= sparseTextureLodARB( s2D, c2, 2.0, texel);
+ resident |= sparseTextureLodARB(is2D, c2, 2.0, texel);
+ resident |= sparseTextureLodARB(us2D, c2, 2.0, texel);
+
+ resident |= sparseTexelFetchARB( s2D, ivec2(c2), 2, texel);
+ resident |= sparseTexelFetchARB(is2D, ivec2(c2), 2, texel);
+ resident |= sparseTexelFetchARB(us2D, ivec2(c2), 2, texel);
+
+ resident |= sparseImageLoadARB(i2D, ic2, texel);
+ resident |= sparseImageLoadARB(ii2DMS, ic2, 3, texel);
+ resident |= sparseImageLoadARB(ui3D, ic3, utexel);
+
+ outColor = sparseTexelsResidentARB(resident) ? texel : vec4(itexel) + vec4(utexel);
+}
\ No newline at end of file
diff --git a/Test/spv.1.4.texture.frag b/Test/spv.1.4.texture.frag
new file mode 100644
index 0000000..cd98dd5
--- /dev/null
+++ b/Test/spv.1.4.texture.frag
@@ -0,0 +1,26 @@
+#version 450
+
+uniform sampler2D texSampler2D;
+uniform isampler2D itexSampler2D;
+uniform usampler2D utexSampler2D;
+
+in vec2 t;
+in vec2 coords2D;
+flat in ivec2 iCoords2D;
+
+out vec4 color;
+
+flat in int iLod;
+
+void main()
+{
+ vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
+
+ color += texture( texSampler2D, coords2D);
+ color += texture(itexSampler2D, coords2D);
+ color += texture(utexSampler2D, coords2D);
+
+ color += texelFetch( texSampler2D, iCoords2D, iLod);
+ color += texelFetch(itexSampler2D, iCoords2D, iLod);
+ color += texelFetch(utexSampler2D, iCoords2D, iLod);
+}
\ No newline at end of file
diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp
index 308bab6..4438ba3 100755
--- a/gtests/Spv.FromFile.cpp
+++ b/gtests/Spv.FromFile.cpp
@@ -472,6 +472,9 @@
"spv.1.4.OpCopyLogical.comp",
"spv.1.4.OpCopyLogicalBool.comp",
"spv.1.4.OpCopyLogical.funcall.frag",
+ "spv.1.4.image.frag",
+ "spv.1.4.sparseTexture.frag",
+ "spv.1.4.texture.frag",
})),
FileNameAsCustomTestSuffix
);