[spirv] Intrinsic ddx and ddy. (#707)

Also:
* ddx_coarse, ddx_fine
* ddy_coarse, ddy_fine
This commit is contained in:
Ehsan 2017-10-16 10:11:29 -04:00 коммит произвёл GitHub
Родитель 1608deb16a
Коммит 8afee2994c
10 изменённых файлов: 152 добавлений и 4 удалений

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

@ -1086,6 +1086,12 @@ The following intrinsic HLSL functions are currently supported:
- ``reversebits``: Reverses the order of the bits, per component. Uses SPIR-V ``OpBitReverse``.
- ``clip``: Discards the current pixel if the specified value is less than zero. Uses conditional
control flow as well as SPIR-V ``OpKill``.
- ``ddx``: Partial derivative with respect to the screen-space x-coordinate. Uses SIR-V ``OpDPdx``.
- ``ddy``: Partial derivative with respect to the screen-space y-coordinate. Uses SIR-V ``OpDPdy``.
- ``ddx_coarse``: Low precision partial derivative with respect to the screen-space x-coordinate. Uses SIR-V ``OpDPdxCoarse``.
- ``ddy_coarse``: Low precision partial derivative with respect to the screen-space y-coordinate. Uses SIR-V ``OpDPdyCoarse``.
- ``ddx_fine``: High precision partial derivative with respect to the screen-space x-coordinate. Uses SIR-V ``OpDPdxFine``.
- ``ddy_fine``: High precision partial derivative with respect to the screen-space y-coordinate. Uses SIR-V ``OpDPdyFine``.
Using GLSL extended instructions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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

@ -3674,6 +3674,13 @@ uint32_t SPIRVEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
GLSLstd450 glslOpcode = GLSLstd450Bad;
#define INTRINSIC_SPIRV_OP_WITH_CAP_CASE(intrinsicOp, spirvOp, doEachVec, cap) \
case hlsl::IntrinsicOp::IOP_##intrinsicOp: { \
theBuilder.requireCapability(cap); \
return processIntrinsicUsingSpirvInst(callExpr, spv::Op::Op##spirvOp, \
doEachVec); \
} break
#define INTRINSIC_SPIRV_OP_CASE(intrinsicOp, spirvOp, doEachVec) \
case hlsl::IntrinsicOp::IOP_##intrinsicOp: { \
return processIntrinsicUsingSpirvInst(callExpr, spv::Op::Op##spirvOp, \
@ -3756,6 +3763,16 @@ uint32_t SPIRVEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
return processIntrinsicLog10(callExpr);
}
INTRINSIC_SPIRV_OP_CASE(transpose, Transpose, false);
INTRINSIC_SPIRV_OP_CASE(ddx, DPdx, true);
INTRINSIC_SPIRV_OP_WITH_CAP_CASE(ddx_coarse, DPdxCoarse, false,
spv::Capability::DerivativeControl);
INTRINSIC_SPIRV_OP_WITH_CAP_CASE(ddx_fine, DPdxFine, false,
spv::Capability::DerivativeControl);
INTRINSIC_SPIRV_OP_CASE(ddy, DPdy, true);
INTRINSIC_SPIRV_OP_WITH_CAP_CASE(ddy_coarse, DPdyCoarse, false,
spv::Capability::DerivativeControl);
INTRINSIC_SPIRV_OP_WITH_CAP_CASE(ddy_fine, DPdyFine, false,
spv::Capability::DerivativeControl);
INTRINSIC_SPIRV_OP_CASE(countbits, BitCount, false);
INTRINSIC_SPIRV_OP_CASE(isinf, IsInf, true);
INTRINSIC_SPIRV_OP_CASE(isnan, IsNan, true);

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

@ -0,0 +1,17 @@
// Run: %dxc -T ps_6_0 -E main
// CHECK: OpCapability DerivativeControl
void main() {
float a;
float4 b;
// CHECK: [[a:%\d+]] = OpLoad %float %a
// CHECK-NEXT: {{%\d+}} = OpDPdxCoarse %float [[a]]
float da = ddx_coarse(a);
// CHECK: [[b:%\d+]] = OpLoad %v4float %b
// CHECK-NEXT: {{%\d+}} = OpDPdxCoarse %v4float [[b]]
float4 db = ddx_coarse(b);
}

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

@ -0,0 +1,17 @@
// Run: %dxc -T ps_6_0 -E main
// CHECK: OpCapability DerivativeControl
void main() {
float a;
float4 b;
// CHECK: [[a:%\d+]] = OpLoad %float %a
// CHECK-NEXT: {{%\d+}} = OpDPdxFine %float [[a]]
float da = ddx_fine(a);
// CHECK: [[b:%\d+]] = OpLoad %v4float %b
// CHECK-NEXT: {{%\d+}} = OpDPdxFine %v4float [[b]]
float4 db = ddx_fine(b);
}

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

@ -0,0 +1,24 @@
// Run: %dxc -T ps_6_0 -E main
void main() {
float a;
float2 b;
float2x3 c;
// CHECK: [[a:%\d+]] = OpLoad %float %a
// CHECK-NEXT: {{%\d+}} = OpDPdx %float [[a]]
float da = ddx(a);
// CHECK: [[b:%\d+]] = OpLoad %v2float %b
// CHECK-NEXT: {{%\d+}} = OpDPdx %v2float [[b]]
float2 db = ddx(b);
// CHECK: [[c:%\d+]] = OpLoad %mat2v3float %c
// CHECK-NEXT: [[c0:%\d+]] = OpCompositeExtract %v3float [[c]] 0
// CHECK-NEXT: [[dc0:%\d+]] = OpDPdx %v3float [[c0]]
// CHECK-NEXT: [[c1:%\d+]] = OpCompositeExtract %v3float [[c]] 1
// CHECK-NEXT: [[dc1:%\d+]] = OpDPdx %v3float [[c1]]
// CHECK-NEXT: {{%\d+}} = OpCompositeConstruct %mat2v3float [[dc0]] [[dc1]]
float2x3 dc = ddx(c);
}

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

@ -0,0 +1,17 @@
// Run: %dxc -T ps_6_0 -E main
// CHECK: OpCapability DerivativeControl
void main() {
float a;
float4 b;
// CHECK: [[a:%\d+]] = OpLoad %float %a
// CHECK-NEXT: {{%\d+}} = OpDPdyCoarse %float [[a]]
float da = ddy_coarse(a);
// CHECK: [[b:%\d+]] = OpLoad %v4float %b
// CHECK-NEXT: {{%\d+}} = OpDPdyCoarse %v4float [[b]]
float4 db = ddy_coarse(b);
}

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

@ -0,0 +1,17 @@
// Run: %dxc -T ps_6_0 -E main
// CHECK: OpCapability DerivativeControl
void main() {
float a;
float4 b;
// CHECK: [[a:%\d+]] = OpLoad %float %a
// CHECK-NEXT: {{%\d+}} = OpDPdyFine %float [[a]]
float da = ddy_fine(a);
// CHECK: [[b:%\d+]] = OpLoad %v4float %b
// CHECK-NEXT: {{%\d+}} = OpDPdyFine %v4float [[b]]
float4 db = ddy_fine(b);
}

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

@ -0,0 +1,25 @@
// Run: %dxc -T ps_6_0 -E main
void main() {
float a;
float2 b;
float2x3 c;
// CHECK: [[a:%\d+]] = OpLoad %float %a
// CHECK-NEXT: {{%\d+}} = OpDPdy %float [[a]]
float da = ddy(a);
// CHECK: [[b:%\d+]] = OpLoad %v2float %b
// CHECK-NEXT: {{%\d+}} = OpDPdy %v2float [[b]]
float2 db = ddy(b);
// CHECK: [[c:%\d+]] = OpLoad %mat2v3float %c
// CHECK-NEXT: [[c0:%\d+]] = OpCompositeExtract %v3float [[c]] 0
// CHECK-NEXT: [[dc0:%\d+]] = OpDPdy %v3float [[c0]]
// CHECK-NEXT: [[c1:%\d+]] = OpCompositeExtract %v3float [[c]] 1
// CHECK-NEXT: [[dc1:%\d+]] = OpDPdy %v3float [[c1]]
// CHECK-NEXT: {{%\d+}} = OpCompositeConstruct %mat2v3float [[dc0]] [[dc1]]
float2x3 dc = ddy(c);
}

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

@ -1,7 +1,7 @@
// Run: %dxc -T ps_6_0 -E main
// Since OpIsFinite needs the Kernel capability, translation is done using OpIsNan and OpIsInf.
// isFinite = !isNan && !isInf.
// isFinite = !(isNan || isInf)
void main() {
float a;

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

@ -518,6 +518,16 @@ TEST_F(FileTest, IntrinsicsDistance) {
runFileTest("intrinsics.distance.hlsl");
}
TEST_F(FileTest, IntrinsicsRadians) { runFileTest("intrinsics.radians.hlsl"); }
TEST_F(FileTest, IntrinsicsDdx) { runFileTest("intrinsics.ddx.hlsl"); }
TEST_F(FileTest, IntrinsicsDdy) { runFileTest("intrinsics.ddy.hlsl"); }
TEST_F(FileTest, IntrinsicsDdxCoarse) {
runFileTest("intrinsics.ddx-coarse.hlsl");
}
TEST_F(FileTest, IntrinsicsDdyCoarse) {
runFileTest("intrinsics.ddy-coarse.hlsl");
}
TEST_F(FileTest, IntrinsicsDdxFine) { runFileTest("intrinsics.ddx-fine.hlsl"); }
TEST_F(FileTest, IntrinsicsDdyFine) { runFileTest("intrinsics.ddy-fine.hlsl"); }
TEST_F(FileTest, IntrinsicsDeterminant) {
runFileTest("intrinsics.determinant.hlsl");
}
@ -696,9 +706,7 @@ TEST_F(FileTest, VulkanLayoutConsumeSBufferStd430) {
}
// For different Patch Constant Functions (for Hull shaders)
TEST_F(FileTest, HullShaderPCFVoid) {
runFileTest("hull.pcf.void.hlsl");
}
TEST_F(FileTest, HullShaderPCFVoid) { runFileTest("hull.pcf.void.hlsl"); }
TEST_F(FileTest, HullShaderPCFTakesInputPatch) {
runFileTest("hull.pcf.input-patch.hlsl");
}