Commit aff2dd06 by Chris Forbes

Add support for derivative instructions

- OpDPdx - OpDPdy - OpFwidth - OpDPdxCoarse - OpDPdyCoarse - OpFwidthCoarse - OpDPdxFine - OpDPdyFine - OpFwidthFine We have flexibility in how we implement the OpDPdx, OpDPdy and OpFwidth instructions; they can return either coarse or fine derivatives. I have chosen to make them equivalent to the coarse derivatives since those are slightly cheaper to compute. Added a static assert to ensure we revisit these when considering other vector widths. Bug: b/129002115 Test: dEQP-VK.glsl.derivate.* Change-Id: I75224c1e77c1eefac4f219be5662836daa86a098 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/27689Tested-by: 's avatarChris Forbes <chrisforbes@google.com> Presubmit-Ready: Chris Forbes <chrisforbes@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
parent c2968064
...@@ -401,6 +401,15 @@ namespace sw ...@@ -401,6 +401,15 @@ namespace sw
case spv::OpIsNan: case spv::OpIsNan:
case spv::OpAny: case spv::OpAny:
case spv::OpAll: case spv::OpAll:
case spv::OpDPdx:
case spv::OpDPdxCoarse:
case spv::OpDPdy:
case spv::OpDPdyCoarse:
case spv::OpFwidth:
case spv::OpFwidthCoarse:
case spv::OpDPdxFine:
case spv::OpDPdyFine:
case spv::OpFwidthFine:
// Instructions that yield an intermediate value // Instructions that yield an intermediate value
{ {
Type::ID typeId = insn.word(1); Type::ID typeId = insn.word(1);
...@@ -1229,6 +1238,15 @@ namespace sw ...@@ -1229,6 +1238,15 @@ namespace sw
case spv::OpBitcast: case spv::OpBitcast:
case spv::OpIsInf: case spv::OpIsInf:
case spv::OpIsNan: case spv::OpIsNan:
case spv::OpDPdx:
case spv::OpDPdxCoarse:
case spv::OpDPdy:
case spv::OpDPdyCoarse:
case spv::OpFwidth:
case spv::OpFwidthCoarse:
case spv::OpDPdxFine:
case spv::OpDPdyFine:
case spv::OpFwidthFine:
EmitUnaryOp(insn, routine); EmitUnaryOp(insn, routine);
break; break;
...@@ -1764,6 +1782,58 @@ namespace sw ...@@ -1764,6 +1782,58 @@ namespace sw
case spv::OpIsNan: case spv::OpIsNan:
dst.emplace(i, IsNan(src.Float(i))); dst.emplace(i, IsNan(src.Float(i)));
break; break;
case spv::OpDPdx:
case spv::OpDPdxCoarse:
// Derivative instructions: FS invocations are laid out like so:
// 0 1
// 2 3
static_assert(SIMD::Width == 4, "All cross-lane instructions will need care when using a different width");
dst.emplace(i, SIMD::Float(Extract(src.Float(i), 1) - Extract(src.Float(i), 0)));
break;
case spv::OpDPdy:
case spv::OpDPdyCoarse:
dst.emplace(i, SIMD::Float(Extract(src.Float(i), 2) - Extract(src.Float(i), 0)));
break;
case spv::OpFwidth:
case spv::OpFwidthCoarse:
dst.emplace(i, SIMD::Float(Abs(Extract(src.Float(i), 1) - Extract(src.Float(i), 0))
+ Abs(Extract(src.Float(i), 2) - Extract(src.Float(i), 0))));
break;
case spv::OpDPdxFine:
{
auto firstRow = Extract(src.Float(i), 1) - Extract(src.Float(i), 0);
auto secondRow = Extract(src.Float(i), 3) - Extract(src.Float(i), 2);
SIMD::Float v = SIMD::Float(firstRow);
v = Insert(v, secondRow, 2);
v = Insert(v, secondRow, 3);
dst.emplace(i, v);
break;
}
case spv::OpDPdyFine:
{
auto firstColumn = Extract(src.Float(i), 2) - Extract(src.Float(i), 0);
auto secondColumn = Extract(src.Float(i), 3) - Extract(src.Float(i), 1);
SIMD::Float v = SIMD::Float(firstColumn);
v = Insert(v, secondColumn, 1);
v = Insert(v, secondColumn, 3);
dst.emplace(i, v);
break;
}
case spv::OpFwidthFine:
{
auto firstRow = Extract(src.Float(i), 1) - Extract(src.Float(i), 0);
auto secondRow = Extract(src.Float(i), 3) - Extract(src.Float(i), 2);
SIMD::Float dpdx = SIMD::Float(firstRow);
dpdx = Insert(dpdx, secondRow, 2);
dpdx = Insert(dpdx, secondRow, 3);
auto firstColumn = Extract(src.Float(i), 2) - Extract(src.Float(i), 0);
auto secondColumn = Extract(src.Float(i), 3) - Extract(src.Float(i), 1);
SIMD::Float dpdy = SIMD::Float(firstColumn);
dpdy = Insert(dpdy, secondColumn, 1);
dpdy = Insert(dpdy, secondColumn, 3);
dst.emplace(i, Abs(dpdx) + Abs(dpdy));
break;
}
default: default:
UNIMPLEMENTED("Unhandled unary operator %s", OpcodeName(insn.opcode()).c_str()); UNIMPLEMENTED("Unhandled unary operator %s", OpcodeName(insn.opcode()).c_str());
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment