From: Chris Forbes Date: Wed, 20 Mar 2019 21:50:24 +0000 (-0700) Subject: Add support for derivative instructions X-Git-Tag: android-x86-9.0-r1~109 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=aff2dd06;p=android-x86%2Fexternal-swiftshader.git 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/+/27689 Tested-by: Chris Forbes Presubmit-Ready: Chris Forbes Reviewed-by: Nicolas Capens Kokoro-Presubmit: kokoro --- diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp index f348c03cc..212a0ae2a 100644 --- a/src/Pipeline/SpirvShader.cpp +++ b/src/Pipeline/SpirvShader.cpp @@ -401,6 +401,15 @@ namespace sw case spv::OpIsNan: case spv::OpAny: 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 { Type::ID typeId = insn.word(1); @@ -1229,6 +1238,15 @@ namespace sw case spv::OpBitcast: case spv::OpIsInf: 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); break; @@ -1764,6 +1782,58 @@ namespace sw case spv::OpIsNan: dst.emplace(i, IsNan(src.Float(i))); 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: UNIMPLEMENTED("Unhandled unary operator %s", OpcodeName(insn.opcode()).c_str()); }