[spirv] Support Clamp argument in Sample methods. (#887)

This commit is contained in:
Ehsan 2017-12-06 14:37:29 -05:00 коммит произвёл GitHub
Родитель ea76fa189e
Коммит 4d4c4efd66
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 318 добавлений и 41 удалений

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

@ -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, &params);
const auto mask =
composeImageOperandsMask(bias, lod, grad, constOffset, varOffset,
constOffsets, sample, minLod, &params);
// 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, &params));
constOffsets, sample, /*minLod*/ 0, &params));
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, &params));
constOffsets, sample, /*minLod*/ 0, &params));
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;
}