Interpreter: Add radians and normalize builtins
Change-Id: I2c76d8cbcfc3f36448127de5a3e1a22f76eda863 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/229489 Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
efc7205c14
commit
b380e71cfe
@ -137,6 +137,7 @@ static const uint8_t* disassemble_instruction(const uint8_t* ip) {
|
||||
VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
|
||||
VECTOR_MATRIX_DISASSEMBLE(kNegateF, "negatef")
|
||||
VECTOR_DISASSEMBLE(kNegateI, "negatei")
|
||||
VECTOR_DISASSEMBLE(kNormalize, "normalize")
|
||||
case ByteCodeInstruction::kNotB: printf("notb"); break;
|
||||
case ByteCodeInstruction::kOrB: printf("orb"); break;
|
||||
VECTOR_MATRIX_DISASSEMBLE(kPop, "pop")
|
||||
@ -786,6 +787,22 @@ static bool innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
|
||||
case ByteCodeInstruction::kNegateI : sp[ 0] = -sp[ 0].fSigned;
|
||||
break;
|
||||
|
||||
case ByteCodeInstruction::kNormalize:
|
||||
case ByteCodeInstruction::kNormalize2:
|
||||
case ByteCodeInstruction::kNormalize3:
|
||||
case ByteCodeInstruction::kNormalize4: {
|
||||
int count = (int)inst - (int)ByteCodeInstruction::kNormalize + 1;
|
||||
F32 len = sp[0].fFloat * sp[0].fFloat;
|
||||
for (int i = 1; i < count; ++i) {
|
||||
len = skvx::mad(sp[-i].fFloat, sp[-i].fFloat, len);
|
||||
}
|
||||
F32 invLen = 1.0f / skvx::sqrt(len);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
sp[-i].fFloat *= invLen;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ByteCodeInstruction::kPop4: POP();
|
||||
case ByteCodeInstruction::kPop3: POP();
|
||||
case ByteCodeInstruction::kPop2: POP();
|
||||
|
@ -83,6 +83,7 @@ enum class ByteCodeInstruction : uint16_t {
|
||||
VECTOR(kMix),
|
||||
VECTOR_MATRIX(kMultiplyF),
|
||||
VECTOR(kMultiplyI),
|
||||
VECTOR(kNormalize),
|
||||
kNotB,
|
||||
kOrB,
|
||||
VECTOR_MATRIX(kPop),
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
@ -17,14 +17,16 @@ ByteCodeGenerator::ByteCodeGenerator(const Context* context, const Program* prog
|
||||
, fContext(*context)
|
||||
, fOutput(output)
|
||||
, fIntrinsics {
|
||||
{ "cos", ByteCodeInstruction::kCos },
|
||||
{ "cross", ByteCodeInstruction::kCross },
|
||||
{ "dot", SpecialIntrinsic::kDot },
|
||||
{ "inverse", ByteCodeInstruction::kInverse2x2 },
|
||||
{ "sin", ByteCodeInstruction::kSin },
|
||||
{ "sqrt", ByteCodeInstruction::kSqrt },
|
||||
{ "tan", ByteCodeInstruction::kTan },
|
||||
{ "mix", ByteCodeInstruction::kMix },
|
||||
{ "cos", ByteCodeInstruction::kCos },
|
||||
{ "cross", ByteCodeInstruction::kCross },
|
||||
{ "dot", SpecialIntrinsic::kDot },
|
||||
{ "inverse", ByteCodeInstruction::kInverse2x2 },
|
||||
{ "normalize", ByteCodeInstruction::kNormalize },
|
||||
{ "radians", SpecialIntrinsic::kRadians },
|
||||
{ "sin", ByteCodeInstruction::kSin },
|
||||
{ "sqrt", ByteCodeInstruction::kSqrt },
|
||||
{ "tan", ByteCodeInstruction::kTan },
|
||||
{ "mix", ByteCodeInstruction::kMix },
|
||||
} {}
|
||||
|
||||
|
||||
@ -197,6 +199,7 @@ int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
|
||||
VECTOR_UNARY_OP(kConvertUtoF)
|
||||
|
||||
VECTOR_UNARY_OP(kCos)
|
||||
VECTOR_UNARY_OP(kNormalize)
|
||||
VECTOR_UNARY_OP(kSin)
|
||||
VECTOR_UNARY_OP(kSqrt)
|
||||
VECTOR_UNARY_OP(kTan)
|
||||
@ -879,17 +882,34 @@ void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
|
||||
}
|
||||
int count = SlotCount(c.fArguments[0]->fType);
|
||||
if (found->second.fIsSpecial) {
|
||||
SkASSERT(found->second.fValue.fSpecial == SpecialIntrinsic::kDot);
|
||||
SkASSERT(c.fArguments.size() == 2);
|
||||
SkASSERT(count == SlotCount(c.fArguments[1]->fType));
|
||||
this->write((ByteCodeInstruction)((int)ByteCodeInstruction::kMultiplyF + count - 1));
|
||||
for (int i = count; i > 1; --i) {
|
||||
this->write(ByteCodeInstruction::kAddF);
|
||||
SpecialIntrinsic special = found->second.fValue.fSpecial;
|
||||
switch (special) {
|
||||
case SpecialIntrinsic::kDot: {
|
||||
SkASSERT(c.fArguments.size() == 2);
|
||||
SkASSERT(count == SlotCount(c.fArguments[1]->fType));
|
||||
this->write((ByteCodeInstruction)((int)ByteCodeInstruction::kMultiplyF + count-1));
|
||||
for (int i = count; i > 1; --i) {
|
||||
this->write(ByteCodeInstruction::kAddF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SpecialIntrinsic::kRadians: {
|
||||
this->write(ByteCodeInstruction::kPushImmediate);
|
||||
this->write32(float_to_bits(0.0174532925f)); // π/180
|
||||
for (int i = count; i > 1; --i) {
|
||||
this->write(ByteCodeInstruction::kDup);
|
||||
}
|
||||
this->write((ByteCodeInstruction)((int)ByteCodeInstruction::kMultiplyF + count-1));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SkASSERT(false);
|
||||
}
|
||||
} else {
|
||||
switch (found->second.fValue.fInstruction) {
|
||||
case ByteCodeInstruction::kCos:
|
||||
case ByteCodeInstruction::kMix:
|
||||
case ByteCodeInstruction::kNormalize:
|
||||
case ByteCodeInstruction::kSin:
|
||||
case ByteCodeInstruction::kSqrt:
|
||||
case ByteCodeInstruction::kTan:
|
||||
@ -910,7 +930,8 @@ void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
|
||||
default: SkASSERT(false);
|
||||
}
|
||||
this->write(op);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SkASSERT(false);
|
||||
}
|
||||
|
@ -139,6 +139,7 @@ private:
|
||||
// Intrinsics which do not simply map to a single opcode
|
||||
enum class SpecialIntrinsic {
|
||||
kDot,
|
||||
kRadians,
|
||||
};
|
||||
|
||||
struct Intrinsic {
|
||||
|
@ -1,16 +1,22 @@
|
||||
STRINGIFY(
|
||||
$genType cos($genType y);
|
||||
$genHType cos($genHType y);
|
||||
float3 cross(float3 x, float3 y);
|
||||
float dot($genType x, $genType y);
|
||||
$genType mix($genType x, $genType y, float t);
|
||||
float2x2 inverse(float2x2 m);
|
||||
float3x3 inverse(float3x3 m);
|
||||
float4x4 inverse(float4x4 m);
|
||||
$genType sin($genType x);
|
||||
$genHType sin($genHType x);
|
||||
$genType sqrt($genType x);
|
||||
$genHType sqrt($genHType x);
|
||||
$genType tan($genType x);
|
||||
$genHType tan($genHType x);
|
||||
|
||||
$genType cos($genType y);
|
||||
$genHType cos($genHType y);
|
||||
float3 cross(float3 x, float3 y);
|
||||
float dot($genType x, $genType y);
|
||||
$genType mix($genType x, $genType y, float t);
|
||||
float2x2 inverse(float2x2 m);
|
||||
float3x3 inverse(float3x3 m);
|
||||
float4x4 inverse(float4x4 m);
|
||||
$genType normalize($genType x);
|
||||
$genHType normalize($genHType x);
|
||||
$genType radians($genType degrees);
|
||||
$genHType radians($genHType degrees);
|
||||
$genType sin($genType x);
|
||||
$genHType sin($genHType x);
|
||||
$genType sqrt($genType x);
|
||||
$genHType sqrt($genHType x);
|
||||
$genType tan($genType x);
|
||||
$genHType tan($genHType x);
|
||||
|
||||
)
|
||||
|
@ -730,17 +730,24 @@ DEF_TEST(SkSLInterpreterOutParams, r) {
|
||||
}
|
||||
|
||||
DEF_TEST(SkSLInterpreterMathFunctions, r) {
|
||||
float value, expected;
|
||||
float value[4], expected[4];
|
||||
|
||||
value = 0.0f; expected = 0.0f;
|
||||
test(r, "float main(float x) { return sin(x); }", &value, 1, &expected);
|
||||
test(r, "float main(float x) { return tan(x); }", &value, 1, &expected);
|
||||
value[0] = 0.0f; expected[0] = 0.0f;
|
||||
test(r, "float main(float x) { return sin(x); }", value, 1, expected);
|
||||
test(r, "float main(float x) { return tan(x); }", value, 1, expected);
|
||||
|
||||
value = 0.0f; expected = 1.0f;
|
||||
test(r, "float main(float x) { return cos(x); }", &value, 1, &expected);
|
||||
value[0] = 0.0f; expected[0] = 1.0f;
|
||||
test(r, "float main(float x) { return cos(x); }", value, 1, expected);
|
||||
|
||||
value = 25.0f; expected = 5.0f;
|
||||
test(r, "float main(float x) { return sqrt(x); }", &value, 1, &expected);
|
||||
value[0] = 25.0f; expected[0] = 5.0f;
|
||||
test(r, "float main(float x) { return sqrt(x); }", value, 1, expected);
|
||||
|
||||
value[0] = 90.0f; expected[0] = sk_float_degrees_to_radians(value[0]);
|
||||
test(r, "float main(float x) { return radians(x); }", value, 1, expected);
|
||||
|
||||
value[0] = 1.0f; value[1] = -1.0f;
|
||||
expected[0] = 1.0f / SK_FloatSqrt2; expected[1] = -1.0f / SK_FloatSqrt2;
|
||||
test(r, "float2 main(float2 x) { return normalize(x); }", value, 2, expected);
|
||||
}
|
||||
|
||||
DEF_TEST(SkSLInterpreterVoidFunction, r) {
|
||||
|
Loading…
Reference in New Issue
Block a user