[spirv] Support Load methods that take Status arg. (#905)
This commit is contained in:
Родитель
674aa26115
Коммит
1d4509f35d
|
@ -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, ¶ms));
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче