[spirv] Add support for texture .GatherCmpRed() method (#700)
This commit is contained in:
Родитель
2419dbba86
Коммит
2e1ea68d6c
|
@ -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");
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче