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: