[spirv] Support Clamp argument in Sample methods. (#887)
This commit is contained in:
Родитель
ea76fa189e
Коммит
4d4c4efd66
|
@ -180,7 +180,8 @@ public:
|
|||
uint32_t compareVal, uint32_t lod,
|
||||
std::pair<uint32_t, uint32_t> grad,
|
||||
uint32_t constOffset, uint32_t varOffset,
|
||||
uint32_t constOffsets, uint32_t sample);
|
||||
uint32_t constOffsets, uint32_t sample,
|
||||
uint32_t minLod);
|
||||
|
||||
/// \brief Creates SPIR-V instructions for reading a texel from an image. If
|
||||
/// doImageFetch is true, OpImageFetch is used. OpImageRead is used otherwise.
|
||||
|
@ -403,7 +404,8 @@ private:
|
|||
spv::ImageOperandsMask composeImageOperandsMask(
|
||||
uint32_t bias, uint32_t lod, const std::pair<uint32_t, uint32_t> &grad,
|
||||
uint32_t constOffset, uint32_t varOffset, uint32_t constOffsets,
|
||||
uint32_t sample, llvm::SmallVectorImpl<uint32_t> *orderedParams);
|
||||
uint32_t sample, uint32_t minLod,
|
||||
llvm::SmallVectorImpl<uint32_t> *orderedParams);
|
||||
|
||||
SPIRVContext &theContext; ///< The SPIR-V context.
|
||||
SPIRVModule theModule; ///< The module under building.
|
||||
|
|
|
@ -284,7 +284,8 @@ uint32_t ModuleBuilder::createAtomicCompareExchange(
|
|||
spv::ImageOperandsMask ModuleBuilder::composeImageOperandsMask(
|
||||
uint32_t bias, uint32_t lod, const std::pair<uint32_t, uint32_t> &grad,
|
||||
uint32_t constOffset, uint32_t varOffset, uint32_t constOffsets,
|
||||
uint32_t sample, llvm::SmallVectorImpl<uint32_t> *orderedParams) {
|
||||
uint32_t sample, uint32_t minLod,
|
||||
llvm::SmallVectorImpl<uint32_t> *orderedParams) {
|
||||
using spv::ImageOperandsMask;
|
||||
// SPIR-V Image Operands from least significant bit to most significant bit
|
||||
// Bias, Lod, Grad, ConstOffset, Offset, ConstOffsets, Sample, MinLod
|
||||
|
@ -329,6 +330,12 @@ spv::ImageOperandsMask ModuleBuilder::composeImageOperandsMask(
|
|||
orderedParams->push_back(sample);
|
||||
}
|
||||
|
||||
if (minLod) {
|
||||
requireCapability(spv::Capability::MinLod);
|
||||
mask = mask | ImageOperandsMask::MinLod;
|
||||
orderedParams->push_back(minLod);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
@ -348,9 +355,18 @@ uint32_t ModuleBuilder::createImageSample(
|
|||
uint32_t texelType, uint32_t imageType, uint32_t image, uint32_t sampler,
|
||||
uint32_t coordinate, uint32_t compareVal, uint32_t bias, uint32_t lod,
|
||||
std::pair<uint32_t, uint32_t> grad, uint32_t constOffset,
|
||||
uint32_t varOffset, uint32_t constOffsets, uint32_t sample) {
|
||||
uint32_t varOffset, uint32_t constOffsets, uint32_t sample, uint32_t minLod) {
|
||||
assert(insertPoint && "null insert point");
|
||||
|
||||
// The Lod and Grad image operands requires explicit-lod instructions.
|
||||
// Otherwise we use implicit-lod instructions.
|
||||
const bool mustUseExplicitInstr = lod || (grad.first && grad.second);
|
||||
|
||||
// minLod is only valid with Implicit instructions and Grad instructions.
|
||||
// This means that we cannot have Lod and minLod together because Lod requires
|
||||
// explicit insturctions. So either lod or minLod or both must be zero.
|
||||
assert(lod == 0 || minLod == 0);
|
||||
|
||||
// An OpSampledImage is required to do the image sampling.
|
||||
const uint32_t sampledImgId = theContext.takeNextId();
|
||||
const uint32_t sampledImgTy = getSampledImageType(imageType);
|
||||
|
@ -359,15 +375,14 @@ uint32_t ModuleBuilder::createImageSample(
|
|||
|
||||
const uint32_t texelId = theContext.takeNextId();
|
||||
llvm::SmallVector<uint32_t, 4> params;
|
||||
const auto mask = composeImageOperandsMask(
|
||||
bias, lod, grad, constOffset, varOffset, constOffsets, sample, ¶ms);
|
||||
const auto mask =
|
||||
composeImageOperandsMask(bias, lod, grad, constOffset, varOffset,
|
||||
constOffsets, sample, minLod, ¶ms);
|
||||
|
||||
// If depth-comparison is needed when sampling, we use the OpImageSampleDref*
|
||||
// instructions.
|
||||
if (compareVal) {
|
||||
// The Lod and Grad image operands requires explicit-lod instructions.
|
||||
// Otherwise we use implicit-lod instructions.
|
||||
if (lod || (grad.first && grad.second)) {
|
||||
if (mustUseExplicitInstr) {
|
||||
instBuilder.opImageSampleDrefExplicitLod(texelType, texelId, sampledImgId,
|
||||
coordinate, compareVal, mask);
|
||||
} else {
|
||||
|
@ -376,9 +391,7 @@ uint32_t ModuleBuilder::createImageSample(
|
|||
llvm::Optional<spv::ImageOperandsMask>(mask));
|
||||
}
|
||||
} else {
|
||||
// The Lod and Grad image operands requires explicit-lod instructions.
|
||||
// Otherwise we use implicit-lod instructions.
|
||||
if (lod || (grad.first && grad.second)) {
|
||||
if (mustUseExplicitInstr) {
|
||||
instBuilder.opImageSampleExplicitLod(texelType, texelId, sampledImgId,
|
||||
coordinate, mask);
|
||||
} else {
|
||||
|
@ -411,11 +424,12 @@ uint32_t ModuleBuilder::createImageFetchOrRead(
|
|||
uint32_t constOffsets, uint32_t sample) {
|
||||
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, ¶ms));
|
||||
constOffsets, sample, /*minLod*/ 0, ¶ms));
|
||||
|
||||
const uint32_t texelId = theContext.takeNextId();
|
||||
if (doImageFetch) {
|
||||
|
@ -455,10 +469,11 @@ uint32_t ModuleBuilder::createImageGather(
|
|||
|
||||
llvm::SmallVector<uint32_t, 2> params;
|
||||
|
||||
// TODO: Update ImageGather to accept minLod if necessary.
|
||||
const auto mask =
|
||||
llvm::Optional<spv::ImageOperandsMask>(composeImageOperandsMask(
|
||||
/*bias*/ 0, /*lod*/ 0, std::make_pair(0, 0), constOffset, varOffset,
|
||||
constOffsets, sample, ¶ms));
|
||||
constOffsets, sample, /*minLod*/ 0, ¶ms));
|
||||
uint32_t texelId = theContext.takeNextId();
|
||||
|
||||
if (compareVal) {
|
||||
|
|
|
@ -2781,9 +2781,18 @@ SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
|
|||
uint32_t SPIRVEmitter::processTextureSampleGather(const CXXMemberCallExpr *expr,
|
||||
const bool isSample) {
|
||||
// Signatures:
|
||||
// For Texture1D, Texture1DArray, Texture2D, Texture2DArray, Texture3D:
|
||||
// DXGI_FORMAT Object.Sample(sampler_state S,
|
||||
// float Location
|
||||
// [, int Offset]);
|
||||
// [, int Offset]
|
||||
// [, float Clamp]
|
||||
// [, out uint Status]);
|
||||
//
|
||||
// For TextureCube and TextureCubeArray:
|
||||
// DXGI_FORMAT Object.Sample(sampler_state S,
|
||||
// float Location
|
||||
// [, float Clamp]
|
||||
// [, out uint Status]);
|
||||
//
|
||||
// For Texture2D/Texture2DArray:
|
||||
// <Template Type>4 Object.Gather(sampler_state S,
|
||||
|
@ -2801,10 +2810,18 @@ uint32_t SPIRVEmitter::processTextureSampleGather(const CXXMemberCallExpr *expr,
|
|||
const auto numArgs = expr->getNumArgs();
|
||||
const bool hasStatusArg =
|
||||
expr->getArg(numArgs - 1)->getType()->isUnsignedIntegerType();
|
||||
|
||||
uint32_t clamp = 0;
|
||||
if (numArgs > 2 && expr->getArg(2)->getType()->isFloatingType())
|
||||
clamp = doExpr(expr->getArg(2));
|
||||
else if(numArgs > 3 && expr->getArg(3)->getType()->isFloatingType())
|
||||
clamp = doExpr(expr->getArg(3));
|
||||
const bool hasClampArg = (clamp != 0);
|
||||
const auto status = hasStatusArg ? doExpr(expr->getArg(numArgs - 1)) : 0;
|
||||
|
||||
// Subtract 1 for status (if it exists), and 2 for sampler_state and location.
|
||||
const bool hasOffsetArg = numArgs - hasStatusArg - 2 > 0;
|
||||
// Subtract 1 for status (if it exists), subtract 1 for clamp (if it exists),
|
||||
// and subtract 2 for sampler_state and location.
|
||||
const bool hasOffsetArg = numArgs - hasStatusArg - hasClampArg - 2 > 0;
|
||||
|
||||
const auto *imageExpr = expr->getImplicitObjectArgument();
|
||||
const uint32_t imageType = typeTranslator.translateType(imageExpr->getType());
|
||||
|
@ -2824,7 +2841,7 @@ uint32_t SPIRVEmitter::processTextureSampleGather(const CXXMemberCallExpr *expr,
|
|||
return theBuilder.createImageSample(
|
||||
retType, imageType, image, sampler, coordinate, /*compareVal*/ 0,
|
||||
/*bias*/ 0, /*lod*/ 0, std::make_pair(0, 0), constOffset, varOffset,
|
||||
/*constOffsets*/ 0, /*sampleNumber*/ 0);
|
||||
/*constOffsets*/ 0, /*sampleNumber*/ 0, /*minLod*/ clamp);
|
||||
} else {
|
||||
return theBuilder.createImageGather(
|
||||
retType, imageType, image, sampler, coordinate,
|
||||
|
@ -2838,19 +2855,54 @@ uint32_t
|
|||
SPIRVEmitter::processTextureSampleBiasLevel(const CXXMemberCallExpr *expr,
|
||||
const bool isBias) {
|
||||
// Signatures:
|
||||
// For Texture1D, Texture1DArray, Texture2D, Texture2DArray, and Texture3D:
|
||||
// DXGI_FORMAT Object.SampleBias(sampler_state S,
|
||||
// float Location,
|
||||
// float Bias
|
||||
// [, int Offset]);
|
||||
// [, int Offset]
|
||||
// [, float clamp]
|
||||
// [, out uint Status]);
|
||||
//
|
||||
// For TextureCube and TextureCubeArray:
|
||||
// DXGI_FORMAT Object.SampleBias(sampler_state S,
|
||||
// float Location,
|
||||
// float Bias
|
||||
// [, float clamp]
|
||||
// [, out uint Status]);
|
||||
//
|
||||
// For Texture1D, Texture1DArray, Texture2D, Texture2DArray, and Texture3D:
|
||||
// DXGI_FORMAT Object.SampleLevel(sampler_state S,
|
||||
// float Location,
|
||||
// float LOD
|
||||
// [, int Offset]);
|
||||
// [, int Offset]
|
||||
// [, out uint Status]);
|
||||
//
|
||||
// For TextureCube and TextureCubeArray:
|
||||
// DXGI_FORMAT Object.SampleLevel(sampler_state S,
|
||||
// float Location,
|
||||
// float LOD
|
||||
// [, out uint Status]);
|
||||
|
||||
const auto numArgs = expr->getNumArgs();
|
||||
const bool hasStatusArg =
|
||||
expr->getArg(numArgs - 1)->getType()->isUnsignedIntegerType();
|
||||
|
||||
uint32_t clamp = 0;
|
||||
// The .SampleLevel() methods do not take the clamp argument.
|
||||
if (isBias) {
|
||||
if (numArgs > 3 && expr->getArg(3)->getType()->isFloatingType())
|
||||
clamp = doExpr(expr->getArg(3));
|
||||
else if (numArgs > 4 && expr->getArg(4)->getType()->isFloatingType())
|
||||
clamp = doExpr(expr->getArg(4));
|
||||
}
|
||||
const bool hasClampArg = clamp != 0;
|
||||
|
||||
// Subtract 1 for clamp (if it exists), 1 for status (if it exists),
|
||||
// and 3 for sampler_state, location, and Bias/LOD.
|
||||
const bool hasOffsetArg = numArgs - hasClampArg - hasStatusArg - 3 > 0;
|
||||
|
||||
const auto *imageExpr = expr->getImplicitObjectArgument();
|
||||
|
||||
const uint32_t imageType = typeTranslator.translateType(imageExpr->getType());
|
||||
|
||||
const uint32_t image = loadIfGLValue(imageExpr);
|
||||
const uint32_t sampler = doExpr(expr->getArg(0));
|
||||
const uint32_t coordinate = doExpr(expr->getArg(1));
|
||||
|
@ -2861,9 +2913,10 @@ SPIRVEmitter::processTextureSampleBiasLevel(const CXXMemberCallExpr *expr,
|
|||
} else {
|
||||
lod = doExpr(expr->getArg(2));
|
||||
}
|
||||
// .Bias()/.SampleLevel() has a fourth optional paramter for offset.
|
||||
// If offset is present in .Bias()/.SampleLevel(), it is the fourth argument.
|
||||
uint32_t constOffset = 0, varOffset = 0;
|
||||
handleOptionalOffsetInMethodCall(expr, 3, &constOffset, &varOffset);
|
||||
if(hasOffsetArg)
|
||||
handleOffsetInMethodCall(expr, 3, &constOffset, &varOffset);
|
||||
|
||||
const auto retType =
|
||||
typeTranslator.translateType(expr->getDirectCallee()->getReturnType());
|
||||
|
@ -2871,29 +2924,54 @@ SPIRVEmitter::processTextureSampleBiasLevel(const CXXMemberCallExpr *expr,
|
|||
return theBuilder.createImageSample(
|
||||
retType, imageType, image, sampler, coordinate, /*compareVal*/ 0, bias,
|
||||
lod, std::make_pair(0, 0), constOffset, varOffset, /*constOffsets*/ 0,
|
||||
/*sampleNumber*/ 0);
|
||||
/*sampleNumber*/ 0, /*minLod*/ clamp);
|
||||
}
|
||||
|
||||
uint32_t SPIRVEmitter::processTextureSampleGrad(const CXXMemberCallExpr *expr) {
|
||||
// Signature:
|
||||
// For Texture1D, Texture1DArray, Texture2D, Texture2DArray, and Texture3D:
|
||||
// DXGI_FORMAT Object.SampleGrad(sampler_state S,
|
||||
// float Location,
|
||||
// float DDX,
|
||||
// float DDY
|
||||
// [, int Offset]);
|
||||
// [, int Offset]
|
||||
// [, float Clamp]
|
||||
// [, out uint Status]);
|
||||
//
|
||||
// For TextureCube and TextureCubeArray:
|
||||
// DXGI_FORMAT Object.SampleGrad(sampler_state S,
|
||||
// float Location,
|
||||
// float DDX,
|
||||
// float DDY
|
||||
// [, float Clamp]
|
||||
// [, out uint Status]);
|
||||
|
||||
const auto numArgs = expr->getNumArgs();
|
||||
const bool hasStatusArg =
|
||||
expr->getArg(numArgs - 1)->getType()->isUnsignedIntegerType();
|
||||
|
||||
uint32_t clamp = 0;
|
||||
if (numArgs > 4 && expr->getArg(4)->getType()->isFloatingType())
|
||||
clamp = doExpr(expr->getArg(4));
|
||||
else if (numArgs > 5 && expr->getArg(5)->getType()->isFloatingType())
|
||||
clamp = doExpr(expr->getArg(5));
|
||||
const bool hasClampArg = clamp != 0;
|
||||
|
||||
// Subtract 1 for clamp (if it exists), 1 for status (if it exists),
|
||||
// and 4 for sampler_state, location, DDX, and DDY;
|
||||
const bool hasOffsetArg = numArgs - hasClampArg - hasStatusArg - 4 > 0;
|
||||
|
||||
const auto *imageExpr = expr->getImplicitObjectArgument();
|
||||
|
||||
const uint32_t imageType = typeTranslator.translateType(imageExpr->getType());
|
||||
|
||||
const uint32_t image = loadIfGLValue(imageExpr);
|
||||
const uint32_t sampler = doExpr(expr->getArg(0));
|
||||
const uint32_t coordinate = doExpr(expr->getArg(1));
|
||||
const uint32_t ddx = doExpr(expr->getArg(2));
|
||||
const uint32_t ddy = doExpr(expr->getArg(3));
|
||||
// .SampleGrad() has a fifth optional paramter for offset.
|
||||
// If offset is present in .SampleGrad(), it is the fifth argument.
|
||||
uint32_t constOffset = 0, varOffset = 0;
|
||||
handleOptionalOffsetInMethodCall(expr, 4, &constOffset, &varOffset);
|
||||
if (hasOffsetArg)
|
||||
handleOffsetInMethodCall(expr, 4, &constOffset, &varOffset);
|
||||
|
||||
const auto retType =
|
||||
typeTranslator.translateType(expr->getDirectCallee()->getReturnType());
|
||||
|
@ -2901,8 +2979,7 @@ uint32_t SPIRVEmitter::processTextureSampleGrad(const CXXMemberCallExpr *expr) {
|
|||
return theBuilder.createImageSample(
|
||||
retType, imageType, image, sampler, coordinate, /*compareVal*/ 0,
|
||||
/*bias*/ 0, /*lod*/ 0, std::make_pair(ddx, ddy), constOffset, varOffset,
|
||||
/*constOffsets*/ 0,
|
||||
/*sampleNumber*/ 0);
|
||||
/*constOffsets*/ 0, /*sampleNumber*/ 0, /*minLod*/ clamp);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
@ -2910,23 +2987,75 @@ SPIRVEmitter::processTextureSampleCmpCmpLevelZero(const CXXMemberCallExpr *expr,
|
|||
const bool isCmp) {
|
||||
// .SampleCmp() Signature:
|
||||
//
|
||||
// For Texture1D, Texture1DArray, Texture2D, Texture2DArray:
|
||||
// float Object.SampleCmp(
|
||||
// SamplerComparisonState S,
|
||||
// float Location,
|
||||
// float CompareValue,
|
||||
// [int Offset]
|
||||
// float CompareValue
|
||||
// [, int Offset]
|
||||
// [, float Clamp]
|
||||
// [, out uint Status]
|
||||
// );
|
||||
//
|
||||
// For TextureCube and TextureCubeArray:
|
||||
// float Object.SampleCmp(
|
||||
// SamplerComparisonState S,
|
||||
// float Location,
|
||||
// float CompareValue
|
||||
// [, float Clamp]
|
||||
// [, out uint Status]
|
||||
// );
|
||||
//
|
||||
// .SampleCmpLevelZero() is identical to .SampleCmp() on mipmap level 0 only.
|
||||
const auto *imageExpr = expr->getImplicitObjectArgument();
|
||||
// It never takes a clamp argument, which is good because lod and clamp may
|
||||
// not be used together.
|
||||
//
|
||||
// .SampleCmpLevelZero() Signature:
|
||||
//
|
||||
// For Texture1D, Texture1DArray, Texture2D, Texture2DArray:
|
||||
// float Object.SampleCmpLevelZero(
|
||||
// SamplerComparisonState S,
|
||||
// float Location,
|
||||
// float CompareValue
|
||||
// [, int Offset]
|
||||
// [, out uint Status]
|
||||
// );
|
||||
//
|
||||
// For TextureCube and TextureCubeArray:
|
||||
// float Object.SampleCmpLevelZero(
|
||||
// SamplerComparisonState S,
|
||||
// float Location,
|
||||
// float CompareValue
|
||||
// [, out uint Status]
|
||||
// );
|
||||
|
||||
const auto numArgs = expr->getNumArgs();
|
||||
const bool hasStatusArg =
|
||||
expr->getArg(numArgs - 1)->getType()->isUnsignedIntegerType();
|
||||
|
||||
uint32_t clamp = 0;
|
||||
// The .SampleCmpLevelZero() methods do not take the clamp argument.
|
||||
if (isCmp) {
|
||||
if (numArgs > 3 && expr->getArg(3)->getType()->isFloatingType())
|
||||
clamp = doExpr(expr->getArg(3));
|
||||
else if (numArgs > 4 && expr->getArg(4)->getType()->isFloatingType())
|
||||
clamp = doExpr(expr->getArg(4));
|
||||
}
|
||||
const bool hasClampArg = clamp != 0;
|
||||
|
||||
// Subtract 1 for clamp (if it exists), 1 for status (if it exists),
|
||||
// and 3 for sampler_state, location, and compare_value.
|
||||
const bool hasOffsetArg = numArgs - hasClampArg - hasStatusArg - 3 > 0;
|
||||
|
||||
const auto *imageExpr = expr->getImplicitObjectArgument();
|
||||
const uint32_t image = loadIfGLValue(imageExpr);
|
||||
const uint32_t sampler = doExpr(expr->getArg(0));
|
||||
const uint32_t coordinate = doExpr(expr->getArg(1));
|
||||
const uint32_t compareVal = doExpr(expr->getArg(2));
|
||||
// .SampleCmp() has a fourth optional paramter for offset.
|
||||
// If offset is present in .SampleCmp(), it will be the fourth argument.
|
||||
uint32_t constOffset = 0, varOffset = 0;
|
||||
handleOptionalOffsetInMethodCall(expr, 3, &constOffset, &varOffset);
|
||||
if(hasOffsetArg)
|
||||
handleOffsetInMethodCall(expr, 3, &constOffset, &varOffset);
|
||||
const uint32_t lod = isCmp ? 0 : theBuilder.getConstantFloat32(0);
|
||||
|
||||
const auto retType =
|
||||
|
@ -2935,8 +3064,8 @@ SPIRVEmitter::processTextureSampleCmpCmpLevelZero(const CXXMemberCallExpr *expr,
|
|||
|
||||
return theBuilder.createImageSample(
|
||||
retType, imageType, image, sampler, coordinate, compareVal, /*bias*/ 0,
|
||||
lod, std::make_pair(0, 0), constOffset, varOffset,
|
||||
/*constOffsets*/ 0, /*sampleNumber*/ 0);
|
||||
lod, std::make_pair(0, 0), constOffset, varOffset, /*constOffsets*/ 0,
|
||||
/*sampleNumber*/ 0, /*minLod*/ clamp);
|
||||
}
|
||||
|
||||
SpirvEvalInfo
|
||||
|
|
|
@ -9,6 +9,7 @@ Texture2DArray <float4> t2 : register(t2);
|
|||
TextureCubeArray <float4> t3 : register(t3);
|
||||
|
||||
// CHECK: OpCapability ImageGatherExtended
|
||||
// CHECK: OpCapability MinLod
|
||||
|
||||
// CHECK: %type_sampled_image = OpTypeSampledImage %type_1d_image_array
|
||||
// CHECK: %type_sampled_image_0 = OpTypeSampledImage %type_2d_image_array
|
||||
|
@ -38,5 +39,19 @@ float4 main(int2 offset : A) : SV_Target {
|
|||
// CHECK-NEXT: {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v4fc]] Bias %float_0_5
|
||||
float4 val3 = t3.SampleBias(gSampler, float4(0.1, 0.2, 0.3, 1), 0.5);
|
||||
|
||||
float clamp;
|
||||
// CHECK: [[clamp:%\d+]] = OpLoad %float %clamp
|
||||
// CHECK-NEXT: [[t1:%\d+]] = OpLoad %type_1d_image_array %t1
|
||||
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
|
||||
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t1]] [[gSampler]]
|
||||
// CHECK-NEXT: {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v2fc]] Bias|ConstOffset|MinLod %float_0_5 %int_1 [[clamp]]
|
||||
float4 val4 = t1.SampleBias(gSampler, float2(0.1, 1), 0.5, 1, clamp);
|
||||
|
||||
// CHECK: [[t3:%\d+]] = OpLoad %type_cube_image_array %t3
|
||||
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
|
||||
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_1 [[t3]] [[gSampler]]
|
||||
// CHECK-NEXT: {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v4fc]] Bias|MinLod %float_0_5 %float_2_5
|
||||
float4 val5 = t3.SampleBias(gSampler, float4(0.1, 0.2, 0.3, 1), 0.5, /*clamp*/ 2.5f);
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ Texture1DArray <float4> t1 : register(t1);
|
|||
Texture2DArray <float3> t2 : register(t2);
|
||||
TextureCubeArray <float> t3 : register(t3);
|
||||
|
||||
// CHECK: OpCapability MinLod
|
||||
|
||||
// CHECK: [[v2fc:%\d+]] = OpConstantComposite %v2float %float_0_1 %float_1
|
||||
// CHECK: [[v3fc:%\d+]] = OpConstantComposite %v3float %float_0_1 %float_0_2 %float_1
|
||||
// CHECK: [[v4fc:%\d+]] = OpConstantComposite %v4float %float_0_1 %float_0_2 %float_0_3 %float_1
|
||||
|
@ -33,5 +35,22 @@ float4 main(int2 offset: A, float comparator: B) : SV_Target {
|
|||
// CHECK-NEXT: {{%\d+}} = OpImageSampleDrefImplicitLod %float [[sampledImg]] [[v4fc]] [[comparator]]
|
||||
float val3 = t3.SampleCmp(gSampler, float4(0.1, 0.2, 0.3, 1), comparator);
|
||||
|
||||
float clamp;
|
||||
// CHECK: [[clamp:%\d+]] = OpLoad %float %clamp
|
||||
// CHECK-NEXT: [[t2:%\d+]] = OpLoad %type_2d_image_array %t2
|
||||
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
|
||||
// CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
|
||||
// CHECK-NEXT: [[offset:%\d+]] = OpLoad %v2int %offset
|
||||
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
|
||||
// CHECK-NEXT: {{%\d+}} = OpImageSampleDrefImplicitLod %float [[sampledImg]] [[v3fc]] [[comparator]] Offset|MinLod [[offset]] [[clamp]]
|
||||
float val4 = t2.SampleCmp(gSampler, float3(0.1, 0.2, 1), comparator, offset, clamp);
|
||||
|
||||
// CHECK: [[t3:%\d+]] = OpLoad %type_cube_image_array %t3
|
||||
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
|
||||
// CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
|
||||
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_1 [[t3]] [[gSampler]]
|
||||
// CHECK-NEXT: {{%\d+}} = OpImageSampleDrefImplicitLod %float [[sampledImg]] [[v4fc]] [[comparator]] MinLod %float_1_5
|
||||
float val5 = t3.SampleCmp(gSampler, float4(0.1, 0.2, 0.3, 1), comparator, /*clamp*/ 1.5);
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ Texture2DArray <float4> t2 : register(t2);
|
|||
TextureCubeArray <float4> t3 : register(t3);
|
||||
|
||||
// CHECK: OpCapability ImageGatherExtended
|
||||
// CHECK: OpCapability MinLod
|
||||
|
||||
// CHECK: %type_sampled_image = OpTypeSampledImage %type_1d_image
|
||||
// CHECK: %type_sampled_image_0 = OpTypeSampledImage %type_2d_image
|
||||
|
@ -42,5 +43,20 @@ float4 main(int2 offset : A) : SV_Target {
|
|||
// CHECK-NEXT: {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v4f_0_1]] Grad [[v3f_0_2]] [[v3f_0_3]]
|
||||
float4 val3 = t3.SampleGrad(gSampler, float4(0.1, 0.1, 0.1, 0.1), float3(0.2, 0.2, 0.2), float3(0.3, 0.3, 0.3));
|
||||
|
||||
// CHECK: [[t2:%\d+]] = OpLoad %type_2d_image_array %t2
|
||||
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
|
||||
// CHECK-NEXT: [[offset:%\d+]] = OpLoad %v2int %offset
|
||||
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
|
||||
// CHECK-NEXT: {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v3f_0_1]] Grad|Offset|MinLod [[v2f_0_2]] [[v2f_0_3]] [[offset]] %float_2_5
|
||||
float4 val4 = t2.SampleGrad(gSampler, float3(0.1, 0.1, 0.1), float2(0.2, 0.2), float2(0.3, 0.3), offset, /*clamp*/2.5);
|
||||
|
||||
float clamp;
|
||||
// CHECK: [[clamp:%\d+]] = OpLoad %float %clamp
|
||||
// CHECK-NEXT: [[t3:%\d+]] = OpLoad %type_cube_image_array %t3
|
||||
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
|
||||
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_1 [[t3]] [[gSampler]]
|
||||
// CHECK-NEXT: {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v4f_0_1]] Grad|MinLod [[v3f_0_2]] [[v3f_0_3]] [[clamp]]
|
||||
float4 val5 = t3.SampleGrad(gSampler, float4(0.1, 0.1, 0.1, 0.1), float3(0.2, 0.2, 0.2), float3(0.3, 0.3, 0.3), clamp);
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ Texture1DArray <float4> t1 : register(t1);
|
|||
Texture2DArray <float4> t2 : register(t2);
|
||||
TextureCubeArray <float4> t3 : register(t3);
|
||||
|
||||
// CHECK: OpCapability MinLod
|
||||
|
||||
// CHECK: %type_sampled_image = OpTypeSampledImage %type_1d_image_array
|
||||
// CHECK: %type_sampled_image_0 = OpTypeSampledImage %type_2d_image_array
|
||||
// CHECK: %type_sampled_image_1 = OpTypeSampledImage %type_cube_image_array
|
||||
|
@ -35,5 +37,19 @@ float4 main() : SV_Target {
|
|||
// CHECK-NEXT: {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v4fc]]
|
||||
float4 val3 = t3.Sample(gSampler, float4(0.1, 0.2, 0.3, 1));
|
||||
|
||||
float clamp;
|
||||
// CHECK: [[clamp:%\d+]] = OpLoad %float %clamp
|
||||
// CHECK-NEXT: [[t1:%\d+]] = OpLoad %type_1d_image_array %t1
|
||||
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
|
||||
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t1]] [[gSampler]]
|
||||
// CHECK-NEXT: {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v2fc]] ConstOffset|MinLod %int_1 [[clamp]]
|
||||
float4 val4 = t1.Sample(gSampler, float2(0.1, 1), 1, clamp);
|
||||
|
||||
// CHECK: [[t3:%\d+]] = OpLoad %type_cube_image_array %t3
|
||||
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
|
||||
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_1 [[t3]] [[gSampler]]
|
||||
// CHECK-NEXT: {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v4fc]] MinLod %float_1_5
|
||||
float4 val5 = t3.Sample(gSampler, float4(0.1, 0.2, 0.3, 1), /*clamp*/ 1.5);
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ Texture3D <float4> t3 : register(t3);
|
|||
TextureCube <float4> t4 : register(t4);
|
||||
|
||||
// CHECK: OpCapability ImageGatherExtended
|
||||
// CHECK: OpCapability MinLod
|
||||
|
||||
// CHECK: %type_sampled_image = OpTypeSampledImage %type_1d_image
|
||||
// CHECK: %type_sampled_image_0 = OpTypeSampledImage %type_2d_image
|
||||
|
@ -46,7 +47,20 @@ float4 main(int3 offset: A) : SV_Target {
|
|||
// CHECK-NEXT: {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v3fc]] Bias %float_0_5
|
||||
float4 val4 = t4.SampleBias(gSampler, float3(0.1, 0.2, 0.3), 0.5);
|
||||
|
||||
float clamp;
|
||||
// CHECK: [[clamp:%\d+]] = OpLoad %float %clamp
|
||||
// CHECK-NEXT: [[t3:%\d+]] = OpLoad %type_3d_image %t3
|
||||
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
|
||||
// CHECK-NEXT: [[offset:%\d+]] = OpLoad %v3int %offset
|
||||
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_1 [[t3]] [[gSampler]]
|
||||
// CHECK-NEXT: {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v3fc]] Bias|Offset|MinLod %float_0_5 [[offset]] [[clamp]]
|
||||
float4 val5 = t3.SampleBias(gSampler, float3(0.1, 0.2, 0.3), 0.5, offset, clamp);
|
||||
|
||||
// CHECK: [[t4:%\d+]] = OpLoad %type_cube_image %t4
|
||||
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
|
||||
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_2 [[t4]] [[gSampler]]
|
||||
// CHECK-NEXT: {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v3fc]] Bias|MinLod %float_0_5 %float_2_5
|
||||
float4 val6 = t4.SampleBias(gSampler, float3(0.1, 0.2, 0.3), 0.5, /*clamp*/ 2.5);
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@ Texture2D <float2> t2 : register(t2);
|
|||
TextureCube <float> t4 : register(t4);
|
||||
// No .SampleCmp() for Texture3D.
|
||||
|
||||
// CHECK: OpCapability MinLod
|
||||
|
||||
// CHECK: [[v2fc:%\d+]] = OpConstantComposite %v2float %float_0_1 %float_0_2
|
||||
// CHECK: [[v3fc:%\d+]] = OpConstantComposite %v3float %float_0_1 %float_0_2 %float_0_3
|
||||
|
||||
|
@ -33,5 +35,22 @@ float4 main(int2 offset: A, float comparator: B) : SV_Target {
|
|||
// CHECK-NEXT: {{%\d+}} = OpImageSampleDrefImplicitLod %float [[sampledImg]] [[v3fc]] [[comparator]]
|
||||
float val4 = t4.SampleCmp(gSampler, float3(0.1, 0.2, 0.3), comparator);
|
||||
|
||||
float clamp;
|
||||
// CHECK: [[clamp:%\d+]] = OpLoad %float %clamp
|
||||
// CHECK-NEXT: [[t2:%\d+]] = OpLoad %type_2d_image %t2
|
||||
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
|
||||
// CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
|
||||
// CHECK-NEXT: [[offset:%\d+]] = OpLoad %v2int %offset
|
||||
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
|
||||
// CHECK-NEXT: {{%\d+}} = OpImageSampleDrefImplicitLod %float [[sampledImg]] [[v2fc]] [[comparator]] Offset|MinLod [[offset]] [[clamp]]
|
||||
float val5 = t2.SampleCmp(gSampler, float2(0.1, 0.2), comparator, offset, clamp);
|
||||
|
||||
// CHECK: [[t4:%\d+]] = OpLoad %type_cube_image %t4
|
||||
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
|
||||
// CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
|
||||
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_1 [[t4]] [[gSampler]]
|
||||
// CHECK-NEXT: {{%\d+}} = OpImageSampleDrefImplicitLod %float [[sampledImg]] [[v3fc]] [[comparator]] MinLod %float_2_5
|
||||
float val6 = t4.SampleCmp(gSampler, float3(0.1, 0.2, 0.3), comparator, /*clamp*/2.5);
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ Texture3D <float4> t3 : register(t3);
|
|||
TextureCube <float4> t4 : register(t4);
|
||||
|
||||
// CHECK: OpCapability ImageGatherExtended
|
||||
// CHECK: OpCapability MinLod
|
||||
|
||||
// CHECK: %type_sampled_image = OpTypeSampledImage %type_1d_image
|
||||
// CHECK: %type_sampled_image_0 = OpTypeSampledImage %type_2d_image
|
||||
|
@ -50,5 +51,20 @@ float4 main(int2 offset : A) : SV_Target {
|
|||
// CHECK-NEXT: {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v3f_0_1]] Grad [[v3f_0_2]] [[v3f_0_3]]
|
||||
float4 val4 = t4.SampleGrad(gSampler, float3(0.1, 0.1, 0.1), float3(0.2, 0.2, 0.2), float3(0.3, 0.3, 0.3));
|
||||
|
||||
float clamp;
|
||||
// CHECK: [[clamp:%\d+]] = OpLoad %float %clamp
|
||||
// CHECK-NEXT: [[t2:%\d+]] = OpLoad %type_2d_image %t2
|
||||
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
|
||||
// CHECK-NEXT: [[offset:%\d+]] = OpLoad %v2int %offset
|
||||
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
|
||||
// CHECK-NEXT: {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v2f_0_1]] Grad|Offset|MinLod [[v2f_0_2]] [[v2f_0_3]] [[offset]] [[clamp]]
|
||||
float4 val5 = t2.SampleGrad(gSampler, float2(0.1, 0.1), float2(0.2, 0.2), float2(0.3, 0.3), offset, clamp);
|
||||
|
||||
// CHECK: [[t4:%\d+]] = OpLoad %type_cube_image %t4
|
||||
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
|
||||
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_2 [[t4]] [[gSampler]]
|
||||
// CHECK-NEXT: {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v3f_0_1]] Grad|MinLod [[v3f_0_2]] [[v3f_0_3]] %float_3_5
|
||||
float4 val6 = t4.SampleGrad(gSampler, float3(0.1, 0.1, 0.1), float3(0.2, 0.2, 0.2), float3(0.3, 0.3, 0.3), /*clamp*/3.5);
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ Texture3D <float4> t3 : register(t3);
|
|||
TextureCube <float4> t4 : register(t4);
|
||||
|
||||
// CHECK: OpCapability ImageGatherExtended
|
||||
// CHECK: OpCapability MinLod
|
||||
|
||||
// CHECK: %type_sampled_image = OpTypeSampledImage %type_1d_image
|
||||
// CHECK: %type_sampled_image_0 = OpTypeSampledImage %type_2d_image
|
||||
|
@ -46,5 +47,20 @@ float4 main(int2 offset: A) : SV_Target {
|
|||
// CHECK-NEXT: {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v3fc]]
|
||||
float4 val4 = t4.Sample(gSampler, float3(0.1, 0.2, 0.3));
|
||||
|
||||
float clamp;
|
||||
// CHECK: [[clamp:%\d+]] = OpLoad %float %clamp
|
||||
// CHECK-NEXT: [[t2:%\d+]] = OpLoad %type_2d_image %t2
|
||||
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
|
||||
// CHECK-NEXT: [[offset:%\d+]] = OpLoad %v2int %offset
|
||||
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
|
||||
// CHECK-NEXT: {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v2fc]] Offset|MinLod [[offset]] [[clamp]]
|
||||
float4 val5 = t2.Sample(gSampler, float2(0.1, 0.2), offset, clamp);
|
||||
|
||||
// CHECK: [[t4:%\d+]] = OpLoad %type_cube_image %t4
|
||||
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
|
||||
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_2 [[t4]] [[gSampler]]
|
||||
// CHECK-NEXT: {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v3fc]] MinLod %float_2
|
||||
float4 val6 = t4.Sample(gSampler, float3(0.1, 0.2, 0.3), /*clamp*/ 2.0f);
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче