[spirv] Support Load methods that take Status arg. (#905)

This commit is contained in:
Ehsan 2017-12-12 17:38:30 -05:00 коммит произвёл GitHub
Родитель 674aa26115
Коммит 1d4509f35d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 375 добавлений и 99 удалений

Просмотреть файл

@ -1611,6 +1611,8 @@ Since Buffers are represented as ``OpTypeImage`` with ``Sampled`` set to 1
operation. The return value of ``OpImageFetch`` is always a four-component
vector; so proper additional instructions are generated to truncate the vector
and return the desired number of elements.
If an output unsigned integer ``status`` argument is present, ``OpImageSparseFetch``
is used instead. The resulting SPIR-V ``Residency Code`` will be written to ``status``.
``operator[]``
++++++++++++++
@ -1628,7 +1630,8 @@ Since Buffers are represented as ``OpTypeImage`` with dimension of ``Buffer``,
+++++++++++
Since RWBuffers are represented as ``OpTypeImage`` with ``Sampled`` set to 2
(meaning to be used without a sampler), ``OpImageRead`` is used to perform this
operation.
operation. If an output unsigned integer ``status`` argument is present, ``OpImageSparseRead``
is used instead. The resulting SPIR-V ``Residency Code`` will be written to ``status``.
``operator[]``
++++++++++++++
@ -1780,8 +1783,8 @@ for that texture type.
Common texture methods
~~~~~~~~~~~~~~~~~~~~~~
``.Sample(sampler, location[, offset])``
++++++++++++++++++++++++++++++++++++++++
``.Sample(sampler, location[, offset][, clamp][, Status])``
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Not available to ``Texture2DMS`` and ``Texture2DMSArray``.
@ -1790,12 +1793,15 @@ since texture types are represented as ``OpTypeImage``. An ``OpSampledImage`` is
created based on the ``sampler`` passed to the function. The resulting sampled
image and the ``location`` passed to the function are used as arguments to
``OpImageSampleImplicitLod``, with the optional ``offset`` tranlated into
addtional SPIR-V image operands ``ConstOffset`` or ``Offset`` on it.
addtional SPIR-V image operands ``ConstOffset`` or ``Offset`` on it. The optional
``clamp`` argument will be translated to the ``MinLod`` image operand.
The overload with the status parameter are not supported.
If an output unsigned integer ``status`` argument is present,
``OpImageSparseSampleImplicitLod`` is used instead. The resulting SPIR-V
``Residency Code`` will be written to ``status``.
``.SampleLevel(sampler, location, lod[, offset])``
++++++++++++++++++++++++++++++++++++++++++++++++++
``.SampleLevel(sampler, location, lod[, offset][, Status])``
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Not available to ``Texture2DMS`` and ``Texture2DMSArray``.
@ -1807,21 +1813,26 @@ is attached to the instruction as an SPIR-V image operands ``Lod``. The optional
``offset`` is also tranlated into addtional SPIR-V image operands ``ConstOffset``
or ``Offset`` on it.
The overload with the status parameter are not supported.
If an output unsigned integer ``status`` argument is present,
``OpImageSparseSampleExplicitLod`` is used instead. The resulting SPIR-V
``Residency Code`` will be written to ``status``.
``.SampleGrad(sampler, location, ddx, ddy[, offset])``
++++++++++++++++++++++++++++++++++++++++++++++++++++++
``.SampleGrad(sampler, location, ddx, ddy[, offset][, clamp][, Status])``
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Not available to ``Texture2DMS`` and ``Texture2DMSArray``.
Similarly to ``.SampleLevel``, the ``ddx`` and ``ddy`` parameter are attached to
the ``OpImageSampleExplicitLod`` instruction as an SPIR-V image operands
``Grad``.
``Grad``. The optional ``clamp`` argument will be translated into the ``MinLod``
image operand.
The overload with the status parameter are not supported.
If an output unsigned integer ``status`` argument is present,
``OpImageSparseSampleExplicitLod`` is used instead. The resulting SPIR-V
``Residency Code`` will be written to ``status``.
``.SampleBias(sampler, location, bias[, offset])``
++++++++++++++++++++++++++++++++++++++++++++++++++
``.SampleBias(sampler, location, bias[, offset][, clamp][, Status])``
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Not available to ``Texture2DMS`` and ``Texture2DMSArray``.
@ -1829,18 +1840,24 @@ The translation is similar to ``.Sample()``, with the ``bias`` parameter
attached to the ``OpImageSampleImplicitLod`` instruction as an SPIR-V image
operands ``Bias``.
The overload with the status parameter are not supported.
If an output unsigned integer ``status`` argument is present,
``OpImageSparseSampleImplicitLod`` is used instead. The resulting SPIR-V
``Residency Code`` will be written to ``status``.
``.SampleCmp(sampler, location, comparator[, offset])``
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
``.SampleCmp(sampler, location, comparator[, offset][, clamp][, Status])``
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Not available to ``Texture3D``, ``Texture2DMS``, and ``Texture2DMSArray``.
The translation is similar to ``.Sample()``, but the
``OpImageSampleDrefImplicitLod`` instruction are used.
``.SampleCmpLevelZero(sampler, location, comparator[, offset])``
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
If an output unsigned integer ``status`` argument is present,
``OpImageSparseSampleDrefImplicitLod`` is used instead. The resulting SPIR-V
``Residency Code`` will be written to ``status``.
``.SampleCmpLevelZero(sampler, location, comparator[, offset][, Status])``
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Not available to ``Texture3D``, ``Texture2DMS``, and ``Texture2DMSArray``.
@ -1848,6 +1865,10 @@ The translation is similar to ``.Sample()``, but the
``OpImageSampleDrefExplicitLod`` instruction are used, with the additional
``Lod`` image operands set to 0.0.
If an output unsigned integer ``status`` argument is present,
``OpImageSparseSampleDrefExplicitLod`` is used instead. The resulting SPIR-V
``Residency Code`` will be written to ``status``.
``.Gather()``
+++++++++++++
@ -1857,7 +1878,9 @@ Available to ``Texture2D``, ``Texture2DArray``, ``TextureCube``, and
The translation is similar to ``.Sample()``, but the ``OpImageGather``
instruction is used, with component setting to 0.
The overload with the status parameter are not supported.
If an output unsigned integer ``status`` argument is present,
``OpImageSparseGather`` is used instead. The resulting SPIR-V
``Residency Code`` will be written to ``status``.
``.GatherRed()``, ``.GatherGreen()``, ``.GatherBlue()``, ``.GatherAlpha()``
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@ -1873,7 +1896,9 @@ There are a few overloads for these functions:
- For those overloads taking 4 offset parameters, those offset parameters will
be conveyed as an additional ``ConstOffsets`` image operands to the
instruction. So those offset parameters must all be constant values.
- Those overloads with the status parameter are not supported.
- For those overloads with the ``status`` parameter, ``OpImageSparseGather``
is used instead, and the resulting SPIR-V ``Residency Code`` will be
written to ``status``.
``.GatherCmp()``
++++++++++++++++
@ -1884,7 +1909,10 @@ Available to ``Texture2D``, ``Texture2DArray``, ``TextureCube``, and
The translation is similar to ``.Sample()``, but the ``OpImageDrefGather``
instruction is used.
The overload with the status parameter are not supported.
For the overload with the output unsigned integer ``status`` argument,
``OpImageSparseDrefGather`` is used instead. The resulting SPIR-V
``Residency Code`` will be written to ``status``.
``.GatherCmpRed()``
+++++++++++++++++++
@ -1894,8 +1922,6 @@ Available to ``Texture2D``, ``Texture2DArray``, ``TextureCube``, and
The translation is the same as ``.GatherCmp()``.
The overload with the status parameter are not supported.
``.Load(location[, sampleIndex][, offset])``
++++++++++++++++++++++++++++++++++++++++++++
@ -1908,7 +1934,9 @@ The return value of ``OpImageFetch`` is always a four-component vector; so
proper additional instructions are generated to truncate the vector and return
the desired number of elements.
The overload with the status parameter are not supported.
For the overload with the output unsigned integer ``status`` argument,
``OpImageSparseFetch`` is used instead. The resulting SPIR-V
``Residency Code`` will be written to ``status``.
``operator[]``
++++++++++++++
@ -2034,6 +2062,10 @@ Since read-write texture types are represented as ``OpTypeImage`` with
``Sampled`` set to 2 (meaning to be used without a sampler), ``OpImageRead`` is
used to perform this operation.
For the overload with the output unsigned integer ``status`` argument,
``OpImageSparseRead`` is used instead. The resulting SPIR-V
``Residency Code`` will be written to ``status``.
``operator[]``
++++++++++++++
Using ``operator[]`` for reading is handled similarly as ``.Load()``, while for
@ -2299,3 +2331,7 @@ either because of no Vulkan equivalents at the moment, or because of deprecation
sample currently being processed.) The compiler will emit an error.
* ``SV_InnerCoverage`` semantic does not have a Vulkan equivalent. The compiler
will emit an error.
* Since ``StructuredBuffer``, ``RWStructuredBuffer``, ``ByteAddressBuffer``, and
``RWByteAddressBuffer`` are not represented as image types in SPIR-V, using the
output unsigned integer ``status`` argument in their ``Load*`` methods is not
supported. Using these methods with the ``status`` argument will cause a compiler error.

Просмотреть файл

@ -865,6 +865,14 @@ public:
llvm::Optional<spv::ImageOperandsMask> image_operands,
bool is_explicit, bool is_sparse);
// All-in-one method for creating different types of
// OpImageRead*/OpImageFetch*.
InstBuilder &
opImageFetchRead(uint32_t result_type, uint32_t result_id, uint32_t image,
uint32_t coordinate,
llvm::Optional<spv::ImageOperandsMask> image_operands,
bool is_fetch, bool is_sparse);
// Methods for supplying additional parameters.
InstBuilder &fPFastMathMode(spv::FPFastMathModeMask);
InstBuilder &fPRoundingMode(spv::FPRoundingMode);

Просмотреть файл

@ -191,11 +191,16 @@ public:
/// doImageFetch is true, OpImageFetch is used. OpImageRead is used otherwise.
/// OpImageFetch should be used for sampled images. OpImageRead should be used
/// for images without a sampler.
///
/// If residencyCodeId is not zero, the sparse version of the instructions
/// will be used, and the SPIR-V instruction for storing the resulting
/// residency code will also be emitted.
uint32_t createImageFetchOrRead(bool doImageFetch, uint32_t texelType,
QualType imageType, uint32_t image,
uint32_t coordinate, uint32_t lod,
uint32_t constOffset, uint32_t varOffset,
uint32_t constOffsets, uint32_t sample);
uint32_t constOffsets, uint32_t sample,
uint32_t residencyCodeId);
/// \brief Creates SPIR-V instructions for writing to the given image.
void createImageWrite(QualType imageType, uint32_t imageId, uint32_t coordId,

Просмотреть файл

@ -112,6 +112,28 @@ InstBuilder &InstBuilder::opImageSample(
return *this;
}
InstBuilder &InstBuilder::opImageFetchRead(
uint32_t result_type, uint32_t result_id, uint32_t image,
uint32_t coordinate, llvm::Optional<spv::ImageOperandsMask> image_operands,
bool is_fetch, bool is_sparse) {
spv::Op op =
is_fetch
? (is_sparse ? spv::Op::OpImageSparseFetch : spv::Op::OpImageFetch)
: (is_sparse ? spv::Op::OpImageSparseRead : spv::Op::OpImageRead);
TheInst.emplace_back(static_cast<uint32_t>(op));
TheInst.emplace_back(result_type);
TheInst.emplace_back(result_id);
TheInst.emplace_back(image);
TheInst.emplace_back(coordinate);
if (image_operands.hasValue()) {
const auto &val = image_operands.getValue();
encodeImageOperands(val);
}
return *this;
}
void InstBuilder::encodeString(std::string value) {
const auto &words = string::encodeSPIRVString(value);
TheInst.insert(TheInst.end(), words.begin(), words.end());

Просмотреть файл

@ -429,30 +429,44 @@ void ModuleBuilder::createImageWrite(QualType imageType, uint32_t imageId,
uint32_t ModuleBuilder::createImageFetchOrRead(
bool doImageFetch, uint32_t texelType, QualType imageType, uint32_t image,
uint32_t coordinate, uint32_t lod, uint32_t constOffset, uint32_t varOffset,
uint32_t constOffsets, uint32_t sample) {
uint32_t constOffsets, uint32_t sample, uint32_t residencyCodeId) {
assert(insertPoint && "null insert point");
// TODO: Update ImageFetch/ImageRead to accept minLod if necessary.
llvm::SmallVector<uint32_t, 2> params;
const auto mask =
llvm::Optional<spv::ImageOperandsMask>(composeImageOperandsMask(
/*bias*/ 0, lod, std::make_pair(0, 0), constOffset, varOffset,
constOffsets, sample, /*minLod*/ 0, &params));
const uint32_t texelId = theContext.takeNextId();
if (doImageFetch) {
instBuilder.opImageFetch(texelType, texelId, image, coordinate, mask);
} else {
const bool isSparse = (residencyCodeId != 0);
uint32_t retType = texelType;
if (isSparse) {
requireCapability(spv::Capability::SparseResidency);
retType = getSparseResidencyStructType(texelType);
}
if (!doImageFetch) {
requireCapability(
TypeTranslator::getCapabilityForStorageImageReadWrite(imageType));
instBuilder.opImageRead(texelType, texelId, image, coordinate, mask);
}
uint32_t texelId = theContext.takeNextId();
instBuilder.opImageFetchRead(retType, texelId, image, coordinate, mask,
doImageFetch, isSparse);
for (const auto param : params)
instBuilder.idRef(param);
instBuilder.x();
insertPoint->appendInstruction(std::move(constructSite));
if (isSparse) {
// Write the Residency Code
const auto status = createCompositeExtract(getUint32Type(), texelId, {0});
createStore(residencyCodeId, status);
// Extract the real result from the struct
texelId = createCompositeExtract(texelType, texelId, {1});
}
return texelId;
}

Просмотреть файл

@ -2350,11 +2350,9 @@ uint32_t SPIRVEmitter::processTextureGatherCmp(const CXXMemberCallExpr *expr) {
/*sampleNumber*/ 0, status);
}
SpirvEvalInfo SPIRVEmitter::processBufferTextureLoad(const Expr *object,
const uint32_t locationId,
uint32_t constOffset,
uint32_t varOffset,
uint32_t lod) {
SpirvEvalInfo SPIRVEmitter::processBufferTextureLoad(
const Expr *object, const uint32_t locationId, uint32_t constOffset,
uint32_t varOffset, uint32_t lod, uint32_t residencyCode) {
// Loading for Buffer and RWBuffer translates to an OpImageFetch.
// The result type of an OpImageFetch must be a vec4 of float or int.
const auto type = object->getType();
@ -2393,10 +2391,9 @@ SpirvEvalInfo SPIRVEmitter::processBufferTextureLoad(const Expr *object,
// OpImageFetch and OpImageRead can only fetch a vector of 4 elements.
const uint32_t texelTypeId = theBuilder.getVecType(elemTypeId, 4u);
const uint32_t texel =
theBuilder.createImageFetchOrRead(doFetch, texelTypeId, type, objectId,
locationId, lod, constOffset, varOffset,
/*constOffsets*/ 0, sampleNumber);
const uint32_t texel = theBuilder.createImageFetchOrRead(
doFetch, texelTypeId, type, objectId, locationId, lod, constOffset,
varOffset, /*constOffsets*/ 0, sampleNumber, residencyCode);
uint32_t retVal = texel;
// If the result type is a vec1, vec2, or vec3, some extra processing
@ -2436,7 +2433,7 @@ SpirvEvalInfo SPIRVEmitter::processByteAddressBufferLoadStore(
typeTranslator.isByteAddressBuffer(type));
if (expr->getNumArgs() == 2) {
emitError(
"(RW)ByteAddressBuffer::Load(in address, out status) unimplemented",
"(RW)ByteAddressBuffer::Load(in address, out status) not supported",
expr->getExprLoc());
return 0;
}
@ -2512,8 +2509,9 @@ SpirvEvalInfo SPIRVEmitter::processByteAddressBufferLoadStore(
SpirvEvalInfo
SPIRVEmitter::processStructuredBufferLoad(const CXXMemberCallExpr *expr) {
if (expr->getNumArgs() == 2) {
emitError("(RW)StructuredBuffer::Load(int, int) unimplemented",
expr->getExprLoc());
emitError(
"(RW)StructuredBuffer::Load(in location, out status) not supported",
expr->getExprLoc());
return 0;
}
@ -2644,19 +2642,6 @@ void SPIRVEmitter::handleOffsetInMethodCall(const CXXMemberCallExpr *expr,
*varOffset = doExpr(expr->getArg(index));
};
void SPIRVEmitter::handleOptionalOffsetInMethodCall(
const CXXMemberCallExpr *expr, uint32_t index, uint32_t *constOffset,
uint32_t *varOffset) {
*constOffset = *varOffset = 0; // Initialize both first
if (expr->getNumArgs() == index + 1) { // Has offset argument
if (*constOffset = tryToEvaluateAsConst(expr->getArg(index)))
return; // Constant offset
else
*varOffset = doExpr(expr->getArg(index));
}
}
SpirvEvalInfo
SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
hlsl::IntrinsicOp opcode) {
@ -3074,12 +3059,38 @@ SPIRVEmitter::processTextureSampleCmpCmpLevelZero(const CXXMemberCallExpr *expr,
SpirvEvalInfo
SPIRVEmitter::processBufferTextureLoad(const CXXMemberCallExpr *expr) {
// Signature:
// For Texture1D, Texture1DArray, Texture2D, Texture2DArray, Texture3D:
// ret Object.Load(int Location
// [, int Offset]
// [, uint status]);
//
// For Texture2DMS and Texture2DMSArray, there is one additional argument:
// ret Object.Load(int Location
// [, int SampleIndex]
// [, int Offset]);
// [, int Offset]
// [, uint status]);
//
// For (RW)Buffer, RWTexture1D, RWTexture1DArray, RWTexture2D,
// RWTexture2DArray, RWTexture3D:
// ret Object.Load (int Location
// [, uint status]);
//
// Note: (RW)ByteAddressBuffer and (RW)StructuredBuffer types also have Load
// methods that take an additional Status argument. However, since these types
// are not represented as OpTypeImage in SPIR-V, we don't have a way of
// figuring out the Residency Code for them. Therefore having the Status
// argument for these types is not supported.
//
// For (RW)ByteAddressBuffer:
// ret Object.{Load,Load2,Load3,Load4} (int Location
// [, uint status]);
//
// For (RW)StructuredBuffer:
// ret Object.Load (int Location
// [, uint status]);
//
const auto *object = expr->getImplicitObjectArgument();
const auto *location = expr->getArg(0);
const auto objectType = object->getType();
if (typeTranslator.isRWByteAddressBuffer(objectType) ||
@ -3089,10 +3100,23 @@ SPIRVEmitter::processBufferTextureLoad(const CXXMemberCallExpr *expr) {
if (TypeTranslator::isStructuredBuffer(objectType))
return processStructuredBufferLoad(expr);
const auto numArgs = expr->getNumArgs();
const auto *location = expr->getArg(0);
const bool isTextureMS = TypeTranslator::isTextureMS(objectType);
const bool hasStatusArg =
expr->getArg(numArgs - 1)->getType()->isUnsignedIntegerType();
const auto status = hasStatusArg ? doExpr(expr->getArg(numArgs - 1)) : 0;
if (TypeTranslator::isBuffer(objectType) ||
TypeTranslator::isRWBuffer(objectType) ||
TypeTranslator::isRWTexture(objectType))
return processBufferTextureLoad(object, doExpr(location));
TypeTranslator::isRWBuffer(objectType) ||
TypeTranslator::isRWTexture(objectType))
return processBufferTextureLoad(object, doExpr(location), /*constOffset*/ 0,
/*varOffset*/ 0, /*lod*/ 0,
/*residencyCode*/ status);
// Subtract 1 for status (if it exists), and 1 for sampleIndex (if it exists),
// and 1 for location.
const bool hasOffsetArg = numArgs - hasStatusArg - isTextureMS - 1 > 0;
if (TypeTranslator::isTexture(objectType)) {
// .Load() has a second optional paramter for offset.
@ -3100,12 +3124,13 @@ SPIRVEmitter::processBufferTextureLoad(const CXXMemberCallExpr *expr) {
uint32_t constOffset = 0, varOffset = 0;
uint32_t coordinate = locationId, lod = 0;
if (TypeTranslator::isTextureMS(objectType)) {
if (isTextureMS) {
// SampleIndex is only available when the Object is of Texture2DMS or
// Texture2DMSArray types. Under those cases, Offset will be the third
// parameter (index 2).
lod = doExpr(expr->getArg(1));
handleOptionalOffsetInMethodCall(expr, 2, &constOffset, &varOffset);
if(hasOffsetArg)
handleOffsetInMethodCall(expr, 2, &constOffset, &varOffset);
} else {
// For Texture Load() functions, the location parameter is a vector
// that consists of both the coordinate and the mipmap level (via the
@ -3114,11 +3139,12 @@ SPIRVEmitter::processBufferTextureLoad(const CXXMemberCallExpr *expr) {
splitVecLastElement(location->getType(), locationId, &coordinate, &lod);
// For textures other than Texture2DMS(Array), offset should be the
// second parameter (index 1).
handleOptionalOffsetInMethodCall(expr, 1, &constOffset, &varOffset);
if(hasOffsetArg)
handleOffsetInMethodCall(expr, 1, &constOffset, &varOffset);
}
return processBufferTextureLoad(object, coordinate, constOffset, varOffset,
lod);
lod, status);
}
emitError("Load() of the given object type unimplemented",
object->getExprLoc());
@ -3158,13 +3184,15 @@ SPIRVEmitter::doCXXOperatorCallExpr(const CXXOperatorCallExpr *expr) {
? theBuilder.getConstantUint32(0)
: 0;
return processBufferTextureLoad(baseExpr, doExpr(indexExpr),
/*constOffset*/ 0, /*varOffset*/ 0, lod);
/*constOffset*/ 0, /*varOffset*/ 0, lod,
/*residencyCode*/ 0);
}
// .mips[][] or .sample[][] must use the correct slice.
if (isTextureMipsSampleIndexing(expr, &baseExpr, &indexExpr, &lodExpr)) {
const uint32_t lod = doExpr(lodExpr);
return processBufferTextureLoad(baseExpr, doExpr(indexExpr),
/*constOffset*/ 0, /*varOffset*/ 0, lod);
/*constOffset*/ 0, /*varOffset*/ 0, lod,
/*residencyCode*/ 0);
}
}

Просмотреть файл

@ -576,14 +576,6 @@ private:
void processSwitchStmtUsingIfStmts(const SwitchStmt *switchStmt);
private:
/// Handles the optional offset argument in the given method call at the given
/// argument index.
/// If there exists an offset argument, writes the <result-id> to either
/// *constOffset or *varOffset, depending on the constantness of the offset.
void handleOptionalOffsetInMethodCall(const CXXMemberCallExpr *expr,
uint32_t index, uint32_t *constOffset,
uint32_t *varOffset);
/// Handles the offset argument in the given method call at the given argument
/// index. Panics if the argument at the given index does not exist. Writes
/// the <result-id> to either *constOffset or *varOffset, depending on the
@ -598,10 +590,12 @@ private:
/// \brief Loads one element from the given Buffer/RWBuffer/Texture object at
/// the given location. The type of the loaded element matches the type in the
/// declaration for the Buffer/Texture object.
/// If residencyCodeId is not zero, the SPIR-V instruction for storing the
/// resulting residency code will also be emitted.
SpirvEvalInfo processBufferTextureLoad(const Expr *object, uint32_t location,
uint32_t constOffset = 0,
uint32_t varOffst = 0,
uint32_t lod = 0);
uint32_t constOffset,
uint32_t varOffset, uint32_t lod,
uint32_t residencyCode);
/// \brief Processes .Sample() and .Gather() method calls for texture objects.
uint32_t processTextureSampleGather(const CXXMemberCallExpr *expr,

Просмотреть файл

@ -15,66 +15,93 @@ RWBuffer<int4> int4buf;
RWBuffer<uint4> uint4buf;
RWBuffer<float4> float4buf;
// CHECK: OpCapability SparseResidency
// CHECK: %SparseResidencyStruct = OpTypeStruct %uint %v4float
void main() {
int address;
// CHECK: [[img1:%\d+]] = OpLoad %type_buffer_image %intbuf
// CHECK: [[f1:%\d+]] = OpImageFetch %v4int [[img1]] {{%\d+}} None
// CHECK-NEXT: {{%\d+}} = OpCompositeExtract %int [[f1]] 0
int int1 = intbuf.Load(address);
int i1 = intbuf.Load(address);
// CHECK: [[img2:%\d+]] = OpLoad %type_buffer_image_0 %uintbuf
// CHECK: [[f2:%\d+]] = OpImageFetch %v4uint [[img2]] {{%\d+}} None
// CHECK-NEXT: {{%\d+}} = OpCompositeExtract %uint [[f2]] 0
uint uint1 = uintbuf.Load(address);
uint u1 = uintbuf.Load(address);
// CHECK: [[img3:%\d+]] = OpLoad %type_buffer_image_1 %floatbuf
// CHECK: [[f3:%\d+]] = OpImageFetch %v4float [[img3]] {{%\d+}} None
// CHECK-NEXT: {{%\d+}} = OpCompositeExtract %float [[f3]] 0
float float1 = floatbuf.Load(address);
float f1 = floatbuf.Load(address);
// CHECK: [[img4:%\d+]] = OpLoad %type_buffer_image_2 %int2buf
// CHECK: [[f4:%\d+]] = OpImageRead %v4int [[img4]] {{%\d+}} None
// CHECK-NEXT: {{%\d+}} = OpVectorShuffle %v2int [[f4]] [[f4]] 0 1
int2 int2 = int2buf.Load(address);
int2 i2 = int2buf.Load(address);
// CHECK: [[img5:%\d+]] = OpLoad %type_buffer_image_3 %uint2buf
// CHECK: [[f5:%\d+]] = OpImageRead %v4uint [[img5]] {{%\d+}} None
// CHECK-NEXT: {{%\d+}} = OpVectorShuffle %v2uint [[f5]] [[f5]] 0 1
uint2 uint2 = uint2buf.Load(address);
uint2 u2 = uint2buf.Load(address);
// CHECK: [[img6:%\d+]] = OpLoad %type_buffer_image_4 %float2buf
// CHECK: [[f6:%\d+]] = OpImageRead %v4float [[img6]] {{%\d+}} None
// CHECK-NEXT: {{%\d+}} = OpVectorShuffle %v2float [[f6]] [[f6]] 0 1
float2 float2 = float2buf.Load(address);
float2 f2 = float2buf.Load(address);
// CHECK: [[img7:%\d+]] = OpLoad %type_buffer_image_5 %int3buf
// CHECK: [[f7:%\d+]] = OpImageFetch %v4int [[img7]] {{%\d+}} None
// CHECK-NEXT: {{%\d+}} = OpVectorShuffle %v3int [[f7]] [[f7]] 0 1 2
int3 int3 = int3buf.Load(address);
int3 i3 = int3buf.Load(address);
// CHECK: [[img8:%\d+]] = OpLoad %type_buffer_image_6 %uint3buf
// CHECK: [[f8:%\d+]] = OpImageFetch %v4uint [[img8]] {{%\d+}} None
// CHECK-NEXT: {{%\d+}} = OpVectorShuffle %v3uint [[f8]] [[f8]] 0 1 2
uint3 uint3 = uint3buf.Load(address);
uint3 u3 = uint3buf.Load(address);
// CHECK: [[img9:%\d+]] = OpLoad %type_buffer_image_7 %float3buf
// CHECK: [[f9:%\d+]] = OpImageFetch %v4float [[img9]] {{%\d+}} None
// CHECK-NEXT: {{%\d+}} = OpVectorShuffle %v3float [[f9]] [[f9]] 0 1 2
float3 float3 = float3buf.Load(address);
float3 f3 = float3buf.Load(address);
// CHECK: [[img10:%\d+]] = OpLoad %type_buffer_image_8 %int4buf
// CHECK: {{%\d+}} = OpImageRead %v4int [[img10]] {{%\d+}} None
// CHECK-NEXT: OpStore %int4 {{%\d+}}
int4 int4 = int4buf.Load(address);
// CHECK-NEXT: OpStore %i4 {{%\d+}}
int4 i4 = int4buf.Load(address);
// CHECK: [[img11:%\d+]] = OpLoad %type_buffer_image_9 %uint4buf
// CHECK: {{%\d+}} = OpImageRead %v4uint [[img11]] {{%\d+}} None
// CHECK-NEXT: OpStore %uint4 {{%\d+}}
uint4 uint4 = uint4buf.Load(address);
// CHECK-NEXT: OpStore %u4 {{%\d+}}
uint4 u4 = uint4buf.Load(address);
// CHECK: [[img12:%\d+]] = OpLoad %type_buffer_image_10 %float4buf
// CHECK: {{%\d+}} = OpImageRead %v4float [[img12]] {{%\d+}} None
// CHECK-NEXT: OpStore %float4 {{%\d+}}
float4 float4 = float4buf.Load(address);
// CHECK-NEXT: OpStore %f4 {{%\d+}}
float4 f4 = float4buf.Load(address);
///////////////////////////////
// Using the Status argument //
///////////////////////////////
uint status;
// CHECK: [[img3:%\d+]] = OpLoad %type_buffer_image_1 %floatbuf
// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseFetch %SparseResidencyStruct [[img3]] {{%\d+}} None
// CHECK-NEXT: [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
// CHECK-NEXT: OpStore %status [[status]]
// CHECK-NEXT: [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
// CHECK-NEXT: [[result:%\d+]] = OpCompositeExtract %float [[v4result]] 0
// CHECK-NEXT: OpStore %r1 [[result]]
float r1 = floatbuf.Load(address, status); // Test for Buffer
// CHECK: [[img6:%\d+]] = OpLoad %type_buffer_image_4 %float2buf
// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseRead %SparseResidencyStruct [[img6]] {{%\d+}} None
// CHECK-NEXT: [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
// CHECK-NEXT: OpStore %status [[status]]
// CHECK-NEXT: [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
// CHECK-NEXT: [[result:%\d+]] = OpVectorShuffle %v2float [[v4result]] [[v4result]] 0 1
// CHECK-NEXT: OpStore %r2 [[result]]
float2 r2 = float2buf.Load(address, status); // Test for RWBuffer
}

Просмотреть файл

@ -6,6 +6,12 @@ RWTexture3D<float3> float3buf;
RWTexture1DArray<float4> float4buf;
RWTexture2DArray<int3> int3buf;
// CHECK: OpCapability SparseResidency
// CHECK: %SparseResidencyStruct = OpTypeStruct %uint %v4int
// CHECK: %SparseResidencyStruct_0 = OpTypeStruct %uint %v4uint
// CHECK: %SparseResidencyStruct_1 = OpTypeStruct %uint %v4float
void main() {
// CHECK: [[img1:%\d+]] = OpLoad %type_1d_image %intbuf
@ -36,4 +42,49 @@ void main() {
// CHECK-NEXT: [[r5:%\d+]] = OpVectorShuffle %v3int [[ret5]] [[ret5]] 0 1 2
// CHECK-NEXT: OpStore %e [[r5]]
int3 e = int3buf.Load(0);
uint status;
// CHECK: [[img1:%\d+]] = OpLoad %type_1d_image %intbuf
// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseRead %SparseResidencyStruct [[img1]] %int_0 None
// CHECK-NEXT: [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
// CHECK-NEXT: OpStore %status [[status]]
// CHECK-NEXT: [[v4result:%\d+]] = OpCompositeExtract %v4int [[structResult]] 1
// CHECK-NEXT: [[result:%\d+]] = OpCompositeExtract %int [[v4result]] 0
// CHECK-NEXT: OpStore %a2 [[result]]
int a2 = intbuf.Load(0, status);
// CHECK: [[img2:%\d+]] = OpLoad %type_2d_image %uint2buf
// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseRead %SparseResidencyStruct_0 [[img2]] {{%\d+}} None
// CHECK-NEXT: [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
// CHECK-NEXT: OpStore %status [[status]]
// CHECK-NEXT: [[v4result:%\d+]] = OpCompositeExtract %v4uint [[structResult]] 1
// CHECK-NEXT: [[result:%\d+]] = OpVectorShuffle %v2uint [[v4result]] [[v4result]] 0 1
// CHECK-NEXT: OpStore %b2 [[result]]
uint2 b2 = uint2buf.Load(0, status);
// CHECK: [[img3:%\d+]] = OpLoad %type_3d_image %float3buf
// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseRead %SparseResidencyStruct_1 [[img3]] {{%\d+}} None
// CHECK-NEXT: [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
// CHECK-NEXT: OpStore %status [[status]]
// CHECK-NEXT: [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
// CHECK-NEXT: [[result:%\d+]] = OpVectorShuffle %v3float [[v4result]] [[v4result]] 0 1 2
// CHECK-NEXT: OpStore %c2 [[result]]
float3 c2 = float3buf.Load(0, status);
// CHECK: [[img4:%\d+]] = OpLoad %type_1d_image_array %float4buf
// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseRead %SparseResidencyStruct_1 [[img4]] {{%\d+}} None
// CHECK-NEXT: [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
// CHECK-NEXT: OpStore %status [[status]]
// CHECK-NEXT: [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
// CHECK-NEXT: OpStore %d2 [[v4result]]
float4 d2 = float4buf.Load(0, status);
// CHECK: [[img5:%\d+]] = OpLoad %type_2d_image_array %int3buf
// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseRead %SparseResidencyStruct [[img5]] {{%\d+}} None
// CHECK-NEXT: [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
// CHECK-NEXT: OpStore %status [[status]]
// CHECK-NEXT: [[v4result:%\d+]] = OpCompositeExtract %v4int [[structResult]] 1
// CHECK-NEXT: [[result:%\d+]] = OpVectorShuffle %v3int [[v4result]] [[v4result]] 0 1 2
// CHECK-NEXT: OpStore %e2 [[result]]
int3 e2 = int3buf.Load(0, status);
}

Просмотреть файл

@ -4,7 +4,12 @@ Texture1DArray <float4> t1 : register(t1);
Texture2DArray <float4> t2 : register(t2);
// .Load() does not support TextureCubeArray.
// CHECK: OpCapability SparseResidency
// CHECK: %SparseResidencyStruct = OpTypeStruct %uint %v4float
// CHECK: [[v3ic:%\d+]] = OpConstantComposite %v3int %int_1 %int_2 %int_3
// CHECK: [[v2ic:%\d+]] = OpConstantComposite %v2int %int_1 %int_2
float4 main(int4 location: A) : SV_Target {
@ -21,9 +26,27 @@ float4 main(int4 location: A) : SV_Target {
// CHECK-NEXT: {{%\d+}} = OpImageFetch %v4float [[t2]] [[coord]] Lod [[lod]]
float4 val2 = t2.Load(location);
uint status;
// CHECK: [[coord:%\d+]] = OpVectorShuffle %v2int [[v3ic]] [[v3ic]] 0 1
// CHECK-NEXT: [[lod:%\d+]] = OpCompositeExtract %int [[v3ic]] 2
// CHECK-NEXT: [[t1:%\d+]] = OpLoad %type_1d_image_array %t1
// CHECK-NEXT:[[structResult:%\d+]] = OpImageSparseFetch %SparseResidencyStruct [[t1]] [[coord]] Lod|ConstOffset [[lod]] %int_10
// CHECK-NEXT: [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
// CHECK-NEXT: OpStore %status [[status]]
// CHECK-NEXT: [[result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
// CHECK-NEXT: OpStore %val3 [[result]]
float4 val3 = t1.Load(int3(1, 2, 3), 10, status);
// CHECK: [[loc:%\d+]] = OpLoad %v4int %location
// CHECK-NEXT: [[coord:%\d+]] = OpVectorShuffle %v3int [[loc]] [[loc]] 0 1 2
// CHECK-NEXT: [[lod:%\d+]] = OpCompositeExtract %int [[loc]] 3
// CHECK-NEXT: [[t2:%\d+]] = OpLoad %type_2d_image_array %t2
// CHECK-NEXT:[[structResult:%\d+]] = OpImageSparseFetch %SparseResidencyStruct [[t2]] [[coord]] Lod|ConstOffset [[lod]] [[v2ic]]
// CHECK-NEXT: [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
// CHECK-NEXT: OpStore %status [[status]]
// CHECK-NEXT: [[result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
// CHECK-NEXT: OpStore %val4 [[result]]
float4 val4 = t2.Load(location, int2(1, 2), status);
return 1.0;
}

Просмотреть файл

@ -13,12 +13,18 @@ Texture2DMS <float> t7 : register(t7);
Texture2DMSArray<float3> t8 : register(t8);
// CHECK: OpCapability ImageGatherExtended
// CHECK: OpCapability SparseResidency
// CHECK: %SparseResidencyStruct = OpTypeStruct %uint %v4float
// CHECK: %SparseResidencyStruct_0 = OpTypeStruct %uint %v4int
// CHECK: %SparseResidencyStruct_1 = OpTypeStruct %uint %v4uint
// CHECK: [[v2ic:%\d+]] = OpConstantComposite %v2int %int_1 %int_2
// CHECK: [[v4ic:%\d+]] = OpConstantComposite %v4int %int_1 %int_2 %int_3 %int_4
// CHECK: [[v3ic:%\d+]] = OpConstantComposite %v3int %int_3 %int_3 %int_3
float4 main(int3 location: A, int offset: B) : SV_Target {
uint status;
// CHECK: [[coord:%\d+]] = OpCompositeExtract %int [[v2ic]] 0
// CHECK-NEXT: [[lod:%\d+]] = OpCompositeExtract %int [[v2ic]] 1
@ -88,5 +94,67 @@ float4 main(int3 location: A, int offset: B) : SV_Target {
// CHECK-NEXT: {{%\d+}} = OpVectorShuffle %v3float [[f81]] [[f81]] 0 1 2
val8 = t8.Load(pos3, sampleIndex, int2(1,2));
/////////////////////////////////
/// Using the Status argument ///
/////////////////////////////////
// CHECK: [[coord:%\d+]] = OpCompositeExtract %int [[v2ic]] 0
// CHECK-NEXT: [[lod:%\d+]] = OpCompositeExtract %int [[v2ic]] 1
// CHECK-NEXT: [[offset:%\d+]] = OpLoad %int %offset
// CHECK-NEXT: [[t4:%\d+]] = OpLoad %type_1d_image %t4
// CHECK-NEXT:[[structResult:%\d+]] = OpImageSparseFetch %SparseResidencyStruct [[t4]] [[coord]] Lod|Offset [[lod]] [[offset]]
// CHECK-NEXT: [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
// CHECK-NEXT: OpStore %status [[status]]
// CHECK-NEXT: [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
// CHECK-NEXT: [[result:%\d+]] = OpCompositeExtract %float [[v4result]] 0
// CHECK-NEXT: OpStore %val14 [[result]]
float val14 = t4.Load(int2(1,2), offset, status);
// CHECK: [[loc:%\d+]] = OpLoad %v3int %location
// CHECK-NEXT: [[coord:%\d+]] = OpVectorShuffle %v2int [[loc]] [[loc]] 0 1
// CHECK-NEXT: [[lod:%\d+]] = OpCompositeExtract %int [[loc]] 2
// CHECK-NEXT: [[t5:%\d+]] = OpLoad %type_2d_image_0 %t5
// CHECK-NEXT:[[structResult:%\d+]] = OpImageSparseFetch %SparseResidencyStruct_0 [[t5]] [[coord]] Lod|ConstOffset [[lod]] [[v2ic]]
// CHECK-NEXT: [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
// CHECK-NEXT: OpStore %status [[status]]
// CHECK-NEXT: [[v4result:%\d+]] = OpCompositeExtract %v4int [[structResult]] 1
// CHECK-NEXT: [[result:%\d+]] = OpVectorShuffle %v2int [[v4result]] [[v4result]] 0 1
// CHECK-NEXT: OpStore %val15 [[result]]
int2 val15 = t5.Load(location, int2(1,2), status);
// CHECK: [[coord:%\d+]] = OpVectorShuffle %v3int [[v4ic]] [[v4ic]] 0 1 2
// CHECK-NEXT: [[lod:%\d+]] = OpCompositeExtract %int [[v4ic]] 3
// CHECK-NEXT: [[t6:%\d+]] = OpLoad %type_3d_image_0 %t6
// CHECK-NEXT:[[structResult:%\d+]] = OpImageSparseFetch %SparseResidencyStruct_1 [[t6]] [[coord]] Lod|ConstOffset [[lod]] [[v3ic]]
// CHECK-NEXT: [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
// CHECK-NEXT: OpStore %status [[status]]
// CHECK-NEXT: [[v4result:%\d+]] = OpCompositeExtract %v4uint [[structResult]] 1
// CHECK-NEXT: [[result:%\d+]] = OpVectorShuffle %v3uint [[v4result]] [[v4result]] 0 1 2
// CHECK-NEXT: OpStore %val16 [[result]]
uint3 val16 = t6.Load(int4(1, 2, 3, 4), 3, status);
// CHECK: [[pos1:%\d+]] = OpLoad %v2int %pos2
// CHECK-NEXT: [[si1:%\d+]] = OpLoad %int %sampleIndex
// CHECK-NEXT: [[offset2:%\d+]] = OpLoad %v2int %offset2
// CHECK-NEXT: [[t71:%\d+]] = OpLoad %type_2d_image_1 %t7
// CHECK-NEXT:[[structResult:%\d+]] = OpImageSparseFetch %SparseResidencyStruct [[t71]] [[pos1]] Offset|Sample [[offset2]] [[si1]]
// CHECK-NEXT: [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
// CHECK-NEXT: OpStore %status [[status]]
// CHECK-NEXT: [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
// CHECK-NEXT: [[result:%\d+]] = OpCompositeExtract %float [[v4result]] 0
// CHECK-NEXT: OpStore %val17 [[result]]
float val17 = t7.Load(pos2, sampleIndex, offset2, status);
// CHECK: [[pos3:%\d+]] = OpLoad %v3int %pos3
// CHECK-NEXT: [[si3:%\d+]] = OpLoad %int %sampleIndex
// CHECK-NEXT: [[t81:%\d+]] = OpLoad %type_2d_image_array %t8
// CHECK-NEXT:[[structResult:%\d+]] = OpImageSparseFetch %SparseResidencyStruct [[t81]] [[pos3]] ConstOffset|Sample [[v2ic]] [[si3]]
// CHECK-NEXT: [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
// CHECK-NEXT: OpStore %status [[status]]
// CHECK-NEXT: [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
// CHECK-NEXT: [[result:%\d+]] = OpVectorShuffle %v3float [[v4result]] [[v4result]] 0 1 2
// CHECK-NEXT: OpStore %val18 [[result]]
float3 val18 = t8.Load(pos3, sampleIndex, int2(1,2), status);
return 1.0;
}