[spirv] Add support for texture .GatherCmpRed() method (#700)

This commit is contained in:
Lei Zhang 2017-10-13 11:21:38 -04:00 коммит произвёл GitHub
Родитель 2419dbba86
Коммит 2e1ea68d6c
7 изменённых файлов: 160 добавлений и 24 удалений

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

@ -1440,6 +1440,16 @@ instruction is used.
The overload with the status parameter are not supported.
``.GatherCmpRed()``
+++++++++++++++++++
Available to ``Texture2D``, ``Texture2DArray``, ``TextureCube``, and
``TextureCubeArray``.
The translation is the same as ``.GatherCmp()``.
The overload with the status parameter are not supported.
``.Load(location[, sampleIndex][, offset])``
++++++++++++++++++++++++++++++++++++++++++++

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

@ -189,7 +189,10 @@ public:
/// \brief Creates SPIR-V instructions for writing to the given image.
void createImageWrite(uint32_t imageId, uint32_t coordId, uint32_t texelId);
/// \brief Creates SPIR-V instructions for sampling the given image.
/// \brief Creates SPIR-V instructions for gathering the given image.
///
/// If compareVal is given a non-zero value, OpImageDrefGather will be
/// generated; otherwise, OpImageGather will be generated.
uint32_t createImageGather(uint32_t texelType, uint32_t imageType,
uint32_t image, uint32_t sampler,
uint32_t coordinate, uint32_t component,

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

@ -1722,20 +1722,31 @@ SPIRVEmitter::processTextureLevelOfDetail(const CXXMemberCallExpr *expr) {
{0});
}
uint32_t SPIRVEmitter::processTextureGatherRGBA(const CXXMemberCallExpr *expr,
const uint32_t component) {
// Parameters for .Gather{Red|Green|Blue|Alpha}() are one of the following two
// sets:
uint32_t SPIRVEmitter::processTextureGatherRGBACmpRGBA(
const CXXMemberCallExpr *expr, const bool isCmp, const uint32_t component) {
// Parameters for .Gather{Red|Green|Blue|Alpha}() are one of the following
// two sets:
// * SamplerState s, float2 location, int2 offset
// * SamplerState s, float2 location, int2 offset0, int2 offset1,
// int offset2, int2 offset3
//
// An additional out uint status parameter can appear in both of the above,
// which we does not support yet.
//
// Parameters for .GatherCmp{Red|Green|Blue|Alpha}() are one of the following
// two sets:
// * SamplerState s, float2 location, int2 offset
// * SamplerState s, float2 location, int2 offset0, int2 offset1,
// int offset2, int2 offset3
//
// An additional out uint status parameter can appear in both of the above,
// which we does not support yet.
//
// Return type is always a 4-component vector.
const FunctionDecl *callee = expr->getDirectCallee();
const auto numArgs = expr->getNumArgs();
if (numArgs != 3 && numArgs != 6) {
if (numArgs != 3 + isCmp && numArgs != 6 + isCmp) {
emitError("unsupported '%0' method call with status parameter",
expr->getExprLoc())
<< callee->getName() << expr->getSourceRange();
@ -1747,17 +1758,18 @@ uint32_t SPIRVEmitter::processTextureGatherRGBA(const CXXMemberCallExpr *expr,
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 = isCmp ? doExpr(expr->getArg(2)) : 0;
uint32_t constOffset = 0, varOffset = 0, constOffsets = 0;
if (numArgs == 3) {
if (numArgs == 3 + isCmp) {
// One offset parameter
handleOptionalOffsetInMethodCall(expr, 2, &constOffset, &varOffset);
handleOptionalOffsetInMethodCall(expr, 2 + isCmp, &constOffset, &varOffset);
} else {
// Four offset parameters
const auto offset0 = tryToEvaluateAsConst(expr->getArg(2));
const auto offset1 = tryToEvaluateAsConst(expr->getArg(3));
const auto offset2 = tryToEvaluateAsConst(expr->getArg(4));
const auto offset3 = tryToEvaluateAsConst(expr->getArg(5));
const auto offset0 = tryToEvaluateAsConst(expr->getArg(2 + isCmp));
const auto offset1 = tryToEvaluateAsConst(expr->getArg(3 + isCmp));
const auto offset2 = tryToEvaluateAsConst(expr->getArg(4 + isCmp));
const auto offset3 = tryToEvaluateAsConst(expr->getArg(5 + isCmp));
// Make sure we can generate the ConstOffsets image operands in SPIR-V.
if (!offset0 || !offset1 || !offset2 || !offset3) {
@ -1778,7 +1790,7 @@ uint32_t SPIRVEmitter::processTextureGatherRGBA(const CXXMemberCallExpr *expr,
return theBuilder.createImageGather(
retType, imageType, image, sampler, coordinate,
theBuilder.getConstantInt32(component), /*compareVal*/ 0, constOffset,
theBuilder.getConstantInt32(component), compareVal, constOffset,
varOffset, constOffsets, /*sampleNumber*/ 0);
}
@ -2108,15 +2120,17 @@ SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
case IntrinsicOp::MOP_SampleCmpLevelZero:
return processTextureSampleCmpCmpLevelZero(expr, /*isCmp=*/false);
case IntrinsicOp::MOP_GatherRed:
return processTextureGatherRGBA(expr, 0);
return processTextureGatherRGBACmpRGBA(expr, /*isCmp=*/false, 0);
case IntrinsicOp::MOP_GatherGreen:
return processTextureGatherRGBA(expr, 1);
return processTextureGatherRGBACmpRGBA(expr, /*isCmp=*/false, 1);
case IntrinsicOp::MOP_GatherBlue:
return processTextureGatherRGBA(expr, 2);
return processTextureGatherRGBACmpRGBA(expr, /*isCmp=*/false, 2);
case IntrinsicOp::MOP_GatherAlpha:
return processTextureGatherRGBA(expr, 3);
return processTextureGatherRGBACmpRGBA(expr, /*isCmp=*/false, 3);
case IntrinsicOp::MOP_GatherCmp:
return processTextureGatherCmp(expr);
case IntrinsicOp::MOP_GatherCmpRed:
return processTextureGatherRGBACmpRGBA(expr, /*isCmp=*/true, 0);
case IntrinsicOp::MOP_Load:
return processBufferTextureLoad(expr);
case IntrinsicOp::MOP_Load2:
@ -2187,16 +2201,14 @@ uint32_t SPIRVEmitter::processTextureSampleGather(const CXXMemberCallExpr *expr,
if (isSample) {
return theBuilder.createImageSample(
retType, imageType, image, sampler, coordinate, /*compareVal*/ 0,
/*bias*/ 0,
/*lod*/ 0, std::make_pair(0, 0), constOffset, varOffset,
/*bias*/ 0, /*lod*/ 0, std::make_pair(0, 0), constOffset, varOffset,
/*constOffsets*/ 0, /*sampleNumber*/ 0);
} else {
return theBuilder.createImageGather(
retType, imageType, image, sampler, coordinate,
// .Gather() doc says we return four components of red data.
theBuilder.getConstantInt32(0), /*compareVal*/ 0, constOffset,
varOffset,
/*constOffsets*/ 0, /*sampleNumber*/ 0);
varOffset, /*constOffsets*/ 0, /*sampleNumber*/ 0);
}
}

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

@ -537,9 +537,10 @@ private:
uint32_t processTextureSampleCmpCmpLevelZero(const CXXMemberCallExpr *expr,
bool isCmp);
/// \brief Handles .Gather{Red|Green|Blue|Alpha}() calls on texture types.
uint32_t processTextureGatherRGBA(const CXXMemberCallExpr *expr,
uint32_t component);
/// \brief Handles .Gather{|Cmp}{Red|Green|Blue|Alpha}() calls on texture
/// types.
uint32_t processTextureGatherRGBACmpRGBA(const CXXMemberCallExpr *expr,
bool isCmp, uint32_t component);
/// \brief Handles .GatherCmp() calls on texture types.
uint32_t processTextureGatherCmp(const CXXMemberCallExpr *expr);

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

@ -0,0 +1,52 @@
// Run: %dxc -T ps_6_0 -E main
SamplerComparisonState gSampler : register(s1);
Texture2DArray<float4> t2f4 : register(t1);
Texture2DArray<uint> t2u1 : register(t2);
// .GatherCmpRed() does not support Texture1DArray.
// .GatherCmpRed() for TextureCubeArray only has one signature that takes the status parameter.
// CHECK: [[c12:%\d+]] = OpConstantComposite %v2int %int_1 %int_2
// CHECK: [[c34:%\d+]] = OpConstantComposite %v2int %int_3 %int_4
// CHECK: [[c56:%\d+]] = OpConstantComposite %v2int %int_5 %int_6
// CHECK: [[c78:%\d+]] = OpConstantComposite %v2int %int_7 %int_8
// CHECK: [[c1to8:%\d+]] = OpConstantComposite %_arr_v2int_uint_4 [[c12]] [[c34]] [[c56]] [[c78]]
float4 main(float3 location: A, float comparator: B) : SV_Target {
// CHECK: [[t2f4:%\d+]] = OpLoad %type_2d_image_array %t2f4
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
// CHECK-NEXT: [[loc:%\d+]] = OpLoad %v3float %location
// CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
// CHECK-NEXT: [[res:%\d+]] = OpImageDrefGather %v4float [[sampledImg]] [[loc]] [[comparator]] ConstOffset [[c12]]
// CHECK-NEXT: OpStore %a [[res]]
float4 a = t2f4.GatherCmpRed(gSampler, location, comparator, int2(1, 2));
// CHECK: [[t2f4:%\d+]] = OpLoad %type_2d_image_array %t2f4
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
// CHECK-NEXT: [[loc:%\d+]] = OpLoad %v3float %location
// CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
// CHECK-NEXT: [[res:%\d+]] = OpImageDrefGather %v4float [[sampledImg]] [[loc]] [[comparator]] ConstOffsets [[c1to8]]
// CHECK-NEXT: OpStore %b [[res]]
float4 b = t2f4.GatherCmpRed(gSampler, location, comparator, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
// CHECK: [[t2u1:%\d+]] = OpLoad %type_2d_image_array_0 %t2u1
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
// CHECK-NEXT: [[loc:%\d+]] = OpLoad %v3float %location
// CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2u1]] [[gSampler]]
// CHECK-NEXT: [[res:%\d+]] = OpImageDrefGather %v4uint [[sampledImg]] [[loc]] [[comparator]] ConstOffset [[c12]]
// CHECK-NEXT: OpStore %c [[res]]
uint4 c = t2u1.GatherCmpRed(gSampler, location, comparator, int2(1, 2));
// CHECK: [[t2u1:%\d+]] = OpLoad %type_2d_image_array_0 %t2u1
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
// CHECK-NEXT: [[loc:%\d+]] = OpLoad %v3float %location
// CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2u1]] [[gSampler]]
// CHECK-NEXT: [[res:%\d+]] = OpImageDrefGather %v4uint [[sampledImg]] [[loc]] [[comparator]] ConstOffsets [[c1to8]]
// CHECK-NEXT: OpStore %d [[res]]
uint4 d = t2u1.GatherCmpRed(gSampler, location, comparator, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
return 1.0;
}

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

@ -0,0 +1,52 @@
// Run: %dxc -T ps_6_0 -E main
SamplerComparisonState gSampler : register(s1);
Texture2D<float4> t2f4 : register(t1);
Texture2D<uint> t2u1 : register(t2);
// .GatherCmpRed() does not support Texture1D and Texture3D.
// .GatherCmpRed() for TextureCube only has one signature that takes the status parameter.
// CHECK: [[c12:%\d+]] = OpConstantComposite %v2int %int_1 %int_2
// CHECK: [[c34:%\d+]] = OpConstantComposite %v2int %int_3 %int_4
// CHECK: [[c56:%\d+]] = OpConstantComposite %v2int %int_5 %int_6
// CHECK: [[c78:%\d+]] = OpConstantComposite %v2int %int_7 %int_8
// CHECK: [[c1to8:%\d+]] = OpConstantComposite %_arr_v2int_uint_4 [[c12]] [[c34]] [[c56]] [[c78]]
float4 main(float2 location: A, float comparator: B) : SV_Target {
// CHECK: [[t2f4:%\d+]] = OpLoad %type_2d_image %t2f4
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
// CHECK-NEXT: [[loc:%\d+]] = OpLoad %v2float %location
// CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
// CHECK-NEXT: [[res:%\d+]] = OpImageDrefGather %v4float [[sampledImg]] [[loc]] [[comparator]] ConstOffset [[c12]]
// CHECK-NEXT: OpStore %a [[res]]
float4 a = t2f4.GatherCmpRed(gSampler, location, comparator, int2(1, 2));
// CHECK: [[t2f4:%\d+]] = OpLoad %type_2d_image %t2f4
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
// CHECK-NEXT: [[loc:%\d+]] = OpLoad %v2float %location
// CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
// CHECK-NEXT: [[res:%\d+]] = OpImageDrefGather %v4float [[sampledImg]] [[loc]] [[comparator]] ConstOffsets [[c1to8]]
// CHECK-NEXT: OpStore %b [[res]]
float4 b = t2f4.GatherCmpRed(gSampler, location, comparator, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
// CHECK: [[t2u1:%\d+]] = OpLoad %type_2d_image_0 %t2u1
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
// CHECK-NEXT: [[loc:%\d+]] = OpLoad %v2float %location
// CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2u1]] [[gSampler]]
// CHECK-NEXT: [[res:%\d+]] = OpImageDrefGather %v4uint [[sampledImg]] [[loc]] [[comparator]] ConstOffset [[c12]]
// CHECK-NEXT: OpStore %c [[res]]
uint4 c = t2u1.GatherCmpRed(gSampler, location, comparator, int2(1, 2));
// CHECK: [[t2u1:%\d+]] = OpLoad %type_2d_image_0 %t2u1
// CHECK-NEXT: [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
// CHECK-NEXT: [[loc:%\d+]] = OpLoad %v2float %location
// CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2u1]] [[gSampler]]
// CHECK-NEXT: [[res:%\d+]] = OpImageDrefGather %v4uint [[sampledImg]] [[loc]] [[comparator]] ConstOffsets [[c1to8]]
// CHECK-NEXT: OpStore %d [[res]]
uint4 d = t2u1.GatherCmpRed(gSampler, location, comparator, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
return 1.0;
}

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

@ -418,6 +418,12 @@ TEST_F(FileTest, TextureGatherCmp) { runFileTest("texture.gather-cmp.hlsl"); }
TEST_F(FileTest, TextureArrayGatherCmp) {
runFileTest("texture.array.gather-cmp.hlsl");
}
TEST_F(FileTest, TextureGatherCmpRed) {
runFileTest("texture.gather-cmp-red.hlsl");
}
TEST_F(FileTest, TextureArrayGatherCmpRed) {
runFileTest("texture.array.gather-cmp-red.hlsl");
}
TEST_F(FileTest, TextureSampleLevel) {
runFileTest("texture.sample-level.hlsl");
}