SPV 1.4: Emit SignExtend and ZeroExtend for integer image reads/writes.

This commit is contained in:
John Kessenich 2019-03-31 10:51:57 -06:00
parent 61a5ce190a
commit f43c739ac5
11 changed files with 766 additions and 20 deletions

View file

@ -4182,15 +4182,26 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
// 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::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
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 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
#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 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
}
#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 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
#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 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
}
#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 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
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 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
#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 TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
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 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
}
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())

View file

@ -1808,7 +1808,7 @@ Id Builder::createBuiltinCall(Id resultType, Id builtins, int entryPoint, const
// 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 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse,
//
// 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 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse,
if (parameters.volatil) {
mask = mask | ImageOperandsVolatileTexelKHRMask;
}
mask = mask | signExtensionMask;
if (mask == ImageOperandsMaskNone)
--numArgs; // undo speculative reservation for the mask argument
else

View file

@ -416,7 +416,8 @@ public:
};
// 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.

View file

@ -575,7 +575,7 @@ const char* ImageChannelDataTypeString(int type)
}
}
const int ImageOperandsCeiling = 12;
const int ImageOperandsCeiling = 14;
const char* ImageOperandsString(int format)
{
@ -592,6 +592,8 @@ const char* ImageOperandsString(int format)
case ImageOperandsMakeTexelVisibleKHRShift: return "MakeTexelVisibleKHR";
case ImageOperandsNonPrivateTexelKHRShift: return "NonPrivateTexelKHR";
case ImageOperandsVolatileTexelKHRShift: return "VolatileTexelKHR";
case ImageOperandsSignExtendShift: return "SignExtend";
case ImageOperandsZeroExtendShift: return "ZeroExtend";
case ImageOperandsCeiling:
default: