Reland "SkSL: Test/implement "geometric" intrinsics"
This is a reland of 0d5d956f7b
Original change's description:
> SkSL: Test/implement "geometric" intrinsics
>
> Bug: skia:10913
> Change-Id: Ie82354b05db141c8ab90b1a615ddfada4f71a98b
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/335049
> Commit-Queue: Brian Osman <brianosman@google.com>
> Reviewed-by: John Stiles <johnstiles@google.com>
Bug: skia:10913
Change-Id: I103dd2efbbab0efeac2be786d7e8f913d5c4b22a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/338158
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
This commit is contained in:
parent
748db70156
commit
9ba7a24bdd
@ -29,7 +29,8 @@ static constexpr int kLabelHeight = 15;
|
||||
produce a single float. It can reference:
|
||||
|
||||
'x' : float in [xMin, xMax]
|
||||
'p' : float2 in [xMin, xMax] (helpful for intrinsics with a mix of scalar/vector params)
|
||||
'p' : float2 in [xMin, xMax] Lerps from (xMax, xMin) to (xMin, xMax)
|
||||
(helpful for intrinsics with a mix of scalar/vector params)
|
||||
'v1' : float2(1)
|
||||
'v2' : float2(2)
|
||||
*/
|
||||
@ -40,7 +41,7 @@ static SkString make_unary_sksl_1d(const char* fn) {
|
||||
"half4 main(float2 p) {"
|
||||
" float2 v1 = float2(1);"
|
||||
" float2 v2 = float2(2);"
|
||||
" p = p * xScale + xBias;"
|
||||
" p = float2(p.x, 1 - p.x) * xScale + xBias;"
|
||||
" float x = p.x;"
|
||||
" float y = %s * yScale + yBias;"
|
||||
" return y.xxx1;"
|
||||
@ -233,3 +234,38 @@ DEF_SIMPLE_GM_BG(runtime_intrinsics_common,
|
||||
plot(canvas, "smoothstep(1, 2, p).x", 0.5f, 2.5f, -0.5f, 1.5f, "smooth(mixed)" ); col(canvas);
|
||||
plot(canvas, "smoothstep(v1, v2, p).x", 0.5f, 2.5f, -0.5f, 1.5f, "smooth(vector)"); row(canvas);
|
||||
}
|
||||
|
||||
// The OpenGL ES Shading Language, Version 1.00, Section 8.4
|
||||
DEF_SIMPLE_GM_BG(runtime_intrinsics_geometric,
|
||||
canvas,
|
||||
columns_to_width(4),
|
||||
rows_to_height(5),
|
||||
SK_ColorWHITE) {
|
||||
canvas->translate(kPadding, kPadding);
|
||||
canvas->save();
|
||||
|
||||
plot(canvas, "length(x)", -1.0f, 1.0f, -0.5f, 1.5f); col(canvas);
|
||||
plot(canvas, "length(p)", 0.0f, 1.0f, 0.5f, 1.5f); col(canvas);
|
||||
|
||||
plot(canvas, "distance(x, 0)", -1.0f, 1.0f, -0.5f, 1.5f); col(canvas);
|
||||
plot(canvas, "distance(p, v1)", 0.0f, 1.0f, 0.5f, 1.5f); row(canvas);
|
||||
|
||||
plot(canvas, "dot(x, 2)", -1.0f, 1.0f, -2.5f, 2.5f); col(canvas);
|
||||
plot(canvas, "dot(p, p.y1)", -1.0f, 1.0f, -2.5f, 0.5f); row(canvas);
|
||||
|
||||
plot(canvas, "cross(p.xy1, p.y1x).x", 0.0f, 1.0f, -1.0f, 1.0f); col(canvas);
|
||||
plot(canvas, "cross(p.xy1, p.y1x).y", 0.0f, 1.0f, -1.0f, 1.0f); col(canvas);
|
||||
plot(canvas, "cross(p.xy1, p.y1x).z", 0.0f, 1.0f, -1.0f, 1.0f); row(canvas);
|
||||
|
||||
plot(canvas, "normalize(x)", -2.0f, 2.0f, -1.5f, 1.5f); col(canvas);
|
||||
plot(canvas, "normalize(p).x", 0.0f, 2.0f, 0.0f, 1.0f); col(canvas);
|
||||
plot(canvas, "normalize(p).y", 0.0f, 2.0f, 0.0f, 1.0f); col(canvas);
|
||||
|
||||
plot(canvas, "faceforward(v1, p.x0, v1.x0).x", -1.0f, 1.0f, -1.5f, 1.5f, "faceforward"); row(canvas);
|
||||
|
||||
plot(canvas, "reflect(p.x1, v1.0x).x", -1.0f, 1.0f, -1.0f, 1.0f, "reflect(horiz)"); col(canvas);
|
||||
plot(canvas, "reflect(p.x1, normalize(v1)).y", -1.0f, 1.0f, -1.0f, 1.0f, "reflect(diag)" ); col(canvas);
|
||||
|
||||
plot(canvas, "refract(v1.x0, v1.0x, x).x", 0.0f, 1.0f, -1.0f, 1.0f, "refract().x"); col(canvas);
|
||||
plot(canvas, "refract(v1.x0, v1.0x, x).y", 0.0f, 1.0f, -1.0f, 1.0f, "refract().y"); row(canvas);
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ ByteCodeGenerator::ByteCodeGenerator(const Context* context, const Program* prog
|
||||
{ "ceil", ByteCodeInstruction::kCeil },
|
||||
{ "clamp", SpecialIntrinsic::kClamp },
|
||||
{ "cos", ByteCodeInstruction::kCos },
|
||||
{ "distance", SpecialIntrinsic::kDistance },
|
||||
{ "dot", SpecialIntrinsic::kDot },
|
||||
{ "exp", ByteCodeInstruction::kExp },
|
||||
{ "exp2", ByteCodeInstruction::kExp2 },
|
||||
@ -1248,6 +1249,19 @@ void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
|
||||
}
|
||||
|
||||
if (intrin.is_special) {
|
||||
auto doDotProduct = [count, this] {
|
||||
this->write(ByteCodeInstruction::kMultiplyF, count);
|
||||
for (int i = count - 1; i-- > 0;) {
|
||||
this->write(ByteCodeInstruction::kAddF, 1);
|
||||
}
|
||||
};
|
||||
|
||||
auto doLength = [count, this, &doDotProduct] {
|
||||
this->write(ByteCodeInstruction::kDup, count);
|
||||
doDotProduct();
|
||||
this->write(ByteCodeInstruction::kSqrt, 1);
|
||||
};
|
||||
|
||||
switch (intrin.special) {
|
||||
case SpecialIntrinsic::kAll: {
|
||||
for (int i = count-1; i --> 0;) {
|
||||
@ -1268,23 +1282,20 @@ void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
|
||||
count);
|
||||
} break;
|
||||
|
||||
case SpecialIntrinsic::kDistance: {
|
||||
SkASSERT(nargs == 2 && count == SlotCount(args[1]->type()));
|
||||
this->write(ByteCodeInstruction::kSubtractF, count);
|
||||
doLength();
|
||||
} break;
|
||||
|
||||
case SpecialIntrinsic::kDot: {
|
||||
SkASSERT(nargs == 2);
|
||||
SkASSERT(count == SlotCount(args[1]->type()));
|
||||
this->write(ByteCodeInstruction::kMultiplyF, count);
|
||||
for (int i = count-1; i --> 0;) {
|
||||
this->write(ByteCodeInstruction::kAddF, 1);
|
||||
}
|
||||
SkASSERT(nargs == 2 && count == SlotCount(args[1]->type()));
|
||||
doDotProduct();
|
||||
} break;
|
||||
|
||||
case SpecialIntrinsic::kLength: {
|
||||
SkASSERT(nargs == 1);
|
||||
this->write(ByteCodeInstruction::kDup, count);
|
||||
this->write(ByteCodeInstruction::kMultiplyF, count);
|
||||
for (int i = count-1; i --> 0;) {
|
||||
this->write(ByteCodeInstruction::kAddF, 1);
|
||||
}
|
||||
this->write(ByteCodeInstruction::kSqrt, 1);
|
||||
doLength();
|
||||
} break;
|
||||
|
||||
case SpecialIntrinsic::kMax:
|
||||
@ -1334,12 +1345,7 @@ void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
|
||||
case SpecialIntrinsic::kNormalize: {
|
||||
SkASSERT(nargs == 1);
|
||||
this->write(ByteCodeInstruction::kDup, count);
|
||||
this->write(ByteCodeInstruction::kDup, count);
|
||||
this->write(ByteCodeInstruction::kMultiplyF, count);
|
||||
for (int i = count-1; i --> 0;) {
|
||||
this->write(ByteCodeInstruction::kAddF, 1);
|
||||
}
|
||||
this->write(ByteCodeInstruction::kSqrt, 1);
|
||||
doLength();
|
||||
dupSmallerType(1);
|
||||
this->write(ByteCodeInstruction::kDivideF, count);
|
||||
} break;
|
||||
|
@ -140,6 +140,7 @@ private:
|
||||
kAny,
|
||||
kATan,
|
||||
kClamp,
|
||||
kDistance,
|
||||
kDot,
|
||||
kLength,
|
||||
kMax,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -93,15 +93,12 @@ $genHType smoothstep(half edge0, half edge1, $genHType x);
|
||||
// 8.4 : Geometric Functions
|
||||
float length($genType x);
|
||||
half length($genHType x);
|
||||
|
||||
float distance(float2 a, float2 b) { return length(a - b); }
|
||||
float distance(float3 a, float3 b) { return length(a - b); }
|
||||
float distance(float4 a, float4 b) { return length(a - b); }
|
||||
|
||||
float distance($genType p0, $genType p1);
|
||||
half distance($genHType p0, $genHType p1);
|
||||
float dot($genType x, $genType y);
|
||||
half dot($genHType x, $genHType y);
|
||||
|
||||
float3 cross(float3 a, float3 b) {
|
||||
inline float3 cross(float3 a, float3 b) {
|
||||
return float3(a.y * b.z - a.z * b.y,
|
||||
a.z * b.x - a.x * b.z,
|
||||
a.x * b.y - a.y * b.x);
|
||||
@ -109,9 +106,37 @@ float3 cross(float3 a, float3 b) {
|
||||
|
||||
$genType normalize($genType x);
|
||||
$genHType normalize($genHType x);
|
||||
// TODO: faceforward(N, I, Nref)
|
||||
// TODO: reflect(I, N)
|
||||
// TODO: refract(I, N, eta)
|
||||
|
||||
inline float faceforward(float N, float I, float Nref) { return dot(Nref, I) < 0 ? N : -N; }
|
||||
inline float2 faceforward(float2 N, float2 I, float2 Nref) { return dot(Nref, I) < 0 ? N : -N; }
|
||||
inline float3 faceforward(float3 N, float3 I, float3 Nref) { return dot(Nref, I) < 0 ? N : -N; }
|
||||
inline float4 faceforward(float4 N, float4 I, float4 Nref) { return dot(Nref, I) < 0 ? N : -N; }
|
||||
|
||||
inline float reflect(float I, float N) { return I - 2 * dot(N, I) * N; }
|
||||
inline float2 reflect(float2 I, float2 N) { return I - 2 * dot(N, I) * N; }
|
||||
inline float3 reflect(float3 I, float3 N) { return I - 2 * dot(N, I) * N; }
|
||||
inline float4 reflect(float4 I, float4 N) { return I - 2 * dot(N, I) * N; }
|
||||
|
||||
inline float refract(float I, float N, float eta) {
|
||||
float k = 1 - eta * eta * (1 - dot(N, I) * dot(N, I));
|
||||
return k < 0 ? float(0)
|
||||
: eta * I - (eta * dot(N, I) + sqrt(k)) * N;
|
||||
}
|
||||
inline float2 refract(float2 I, float2 N, float eta) {
|
||||
float k = 1 - eta * eta * (1 - dot(N, I) * dot(N, I));
|
||||
return k < 0 ? float2(0)
|
||||
: eta * I - (eta * dot(N, I) + sqrt(k)) * N;
|
||||
}
|
||||
inline float3 refract(float3 I, float3 N, float eta) {
|
||||
float k = 1 - eta * eta * (1 - dot(N, I) * dot(N, I));
|
||||
return k < 0 ? float3(0)
|
||||
: eta * I - (eta * dot(N, I) + sqrt(k)) * N;
|
||||
}
|
||||
inline float4 refract(float4 I, float4 N, float eta) {
|
||||
float k = 1 - eta * eta * (1 - dot(N, I) * dot(N, I));
|
||||
return k < 0 ? float4(0)
|
||||
: eta * I - (eta * dot(N, I) + sqrt(k)) * N;
|
||||
}
|
||||
|
||||
// 8.5 : Matrix Functions
|
||||
// TODO: matrixCompMult(x, y)
|
||||
|
Loading…
Reference in New Issue
Block a user