aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/gpu/effects/GrDitherEffect.cpp12
-rw-r--r--src/gpu/effects/GrDitherEffect.fp4
-rw-r--r--src/sksl/SkSLCPPCodeGenerator.cpp4
-rw-r--r--src/sksl/SkSLCPPCodeGenerator.h2
-rw-r--r--src/sksl/SkSLCompiler.cpp34
-rw-r--r--src/sksl/SkSLContext.h108
-rw-r--r--src/sksl/SkSLGLSLCodeGenerator.cpp51
-rw-r--r--src/sksl/SkSLGLSLCodeGenerator.h4
-rw-r--r--src/sksl/SkSLIRGenerator.cpp58
-rw-r--r--src/sksl/SkSLIRGenerator.h6
-rw-r--r--src/sksl/ir/SkSLExpression.h4
-rw-r--r--src/sksl/ir/SkSLIntLiteral.h7
-rw-r--r--src/sksl/ir/SkSLType.cpp30
-rw-r--r--src/sksl/ir/SkSLType.h66
-rw-r--r--src/sksl/sksl.include50
-rw-r--r--tests/SkSLGLSLTest.cpp151
16 files changed, 497 insertions, 94 deletions
diff --git a/src/gpu/effects/GrDitherEffect.cpp b/src/gpu/effects/GrDitherEffect.cpp
index 3b70493338..17b94ff087 100644
--- a/src/gpu/effects/GrDitherEffect.cpp
+++ b/src/gpu/effects/GrDitherEffect.cpp
@@ -28,12 +28,12 @@ public:
"0.0039215686274509803;\n break;\n case 1:\n range = "
"0.015873015873015872;\n break;\n default:\n range = "
"0.0083333333333333332;\n break;\n}\n@if (sk_Caps.integerSupport) {\n "
- "int x = int(sk_FragCoord.x);\n int y = int(sk_FragCoord.y);\n uint m = "
- "uint((((((y & 1) << 5 | (x & 1) << 4) | (y & 2) << 2) | (x & 2) << 1) | (y & 4) "
- ">> 1) | (x & 4) >> 2);\n value = float(m) / 64.0 - 0.4921875;\n} else {\n "
- "value = fract(sin(dot(sk_FragCoord.xy, float2(12.989800000000001, "
- "78.233000000000004))) * 43758.545299999998) - 0.5;\n}\n%s = float4(clamp(%s.xyz + "
- "value * range, 0.0, %s.w), %s.w);\n",
+ "uint x = uint(sk_FragCoord.x);\n uint y = uint(sk_FragCoord.y);\n uint m = "
+ "(((((y & 1) << 5 | (x & 1) << 4) | (y & 2) << 2) | (x & 2) << 1) | (y & 4) >> 1) "
+ "| (x & 4) >> 2;\n value = float(m) / 64.0 - 0.4921875;\n} else {\n value = "
+ "fract(sin(dot(sk_FragCoord.xy, float2(12.989800000000001, 78.233000000000004))) * "
+ "43758.545299999998) - 0.5;\n}\n%s = float4(clamp(%s.xyz + value * range, 0.0, "
+ "%s.w), %s.w);\n",
_outer.rangeType(), args.fOutputColor,
args.fInputColor ? args.fInputColor : "float4(1)",
args.fInputColor ? args.fInputColor : "float4(1)",
diff --git a/src/gpu/effects/GrDitherEffect.fp b/src/gpu/effects/GrDitherEffect.fp
index f983702f2b..308e02ed43 100644
--- a/src/gpu/effects/GrDitherEffect.fp
+++ b/src/gpu/effects/GrDitherEffect.fp
@@ -48,8 +48,8 @@ void main() {
}
@if (sk_Caps.integerSupport) {
// This ordered-dither code is lifted from the cpu backend.
- int x = int(sk_FragCoord.x);
- int y = int(sk_FragCoord.y);
+ uint x = uint(sk_FragCoord.x);
+ uint y = uint(sk_FragCoord.y);
uint m = (y & 1) << 5 | (x & 1) << 4 |
(y & 2) << 2 | (x & 2) << 1 |
(y & 4) >> 1 | (x & 4) >> 2;
diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp
index 2276ce372e..76faef9aae 100644
--- a/src/sksl/SkSLCPPCodeGenerator.cpp
+++ b/src/sksl/SkSLCPPCodeGenerator.cpp
@@ -181,6 +181,10 @@ String CPPCodeGenerator::getSamplerHandle(const Variable& var) {
ABORT("should have found sampler in parameters\n");
}
+void CPPCodeGenerator::writeIntLiteral(const IntLiteral& i) {
+ this->write(to_string((int32_t) i.fValue));
+}
+
void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
case SK_INCOLOR_BUILTIN:
diff --git a/src/sksl/SkSLCPPCodeGenerator.h b/src/sksl/SkSLCPPCodeGenerator.h
index b4f31ba1b0..27b434a0ca 100644
--- a/src/sksl/SkSLCPPCodeGenerator.h
+++ b/src/sksl/SkSLCPPCodeGenerator.h
@@ -39,6 +39,8 @@ private:
void writeIndexExpression(const IndexExpression& i) override;
+ void writeIntLiteral(const IntLiteral& i) override;
+
void writeVariableReference(const VariableReference& ref) override;
String getSamplerHandle(const Variable& var);
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index d96515cd88..4ea956ce0f 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -68,6 +68,10 @@ Compiler::Compiler(Flags flags)
ADD_TYPE(Float2);
ADD_TYPE(Float3);
ADD_TYPE(Float4);
+ ADD_TYPE(Half);
+ ADD_TYPE(Half2);
+ ADD_TYPE(Half3);
+ ADD_TYPE(Half4);
ADD_TYPE(Double);
ADD_TYPE(Double2);
ADD_TYPE(Double3);
@@ -80,6 +84,14 @@ Compiler::Compiler(Flags flags)
ADD_TYPE(UInt2);
ADD_TYPE(UInt3);
ADD_TYPE(UInt4);
+ ADD_TYPE(Short);
+ ADD_TYPE(Short2);
+ ADD_TYPE(Short3);
+ ADD_TYPE(Short4);
+ ADD_TYPE(UShort);
+ ADD_TYPE(UShort2);
+ ADD_TYPE(UShort3);
+ ADD_TYPE(UShort4);
ADD_TYPE(Bool);
ADD_TYPE(Bool2);
ADD_TYPE(Bool3);
@@ -93,7 +105,26 @@ Compiler::Compiler(Flags flags)
ADD_TYPE(Float4x2);
ADD_TYPE(Float4x3);
ADD_TYPE(Float4x4);
+ ADD_TYPE(Half2x2);
+ ADD_TYPE(Half2x3);
+ ADD_TYPE(Half2x4);
+ ADD_TYPE(Half3x2);
+ ADD_TYPE(Half3x3);
+ ADD_TYPE(Half3x4);
+ ADD_TYPE(Half4x2);
+ ADD_TYPE(Half4x3);
+ ADD_TYPE(Half4x4);
+ ADD_TYPE(Double2x2);
+ ADD_TYPE(Double2x3);
+ ADD_TYPE(Double2x4);
+ ADD_TYPE(Double3x2);
+ ADD_TYPE(Double3x3);
+ ADD_TYPE(Double3x4);
+ ADD_TYPE(Double4x2);
+ ADD_TYPE(Double4x3);
+ ADD_TYPE(Double4x4);
ADD_TYPE(GenType);
+ ADD_TYPE(GenHType);
ADD_TYPE(GenDType);
ADD_TYPE(GenIType);
ADD_TYPE(GenUType);
@@ -104,9 +135,12 @@ Compiler::Compiler(Flags flags)
ADD_TYPE(GVec2);
ADD_TYPE(GVec3);
ADD_TYPE(GVec4);
+ ADD_TYPE(HVec);
ADD_TYPE(DVec);
ADD_TYPE(IVec);
ADD_TYPE(UVec);
+ ADD_TYPE(SVec);
+ ADD_TYPE(USVec);
ADD_TYPE(BVec);
ADD_TYPE(Sampler1D);
diff --git a/src/sksl/SkSLContext.h b/src/sksl/SkSLContext.h
index 2de584fab2..b132cec33d 100644
--- a/src/sksl/SkSLContext.h
+++ b/src/sksl/SkSLContext.h
@@ -21,45 +21,65 @@ public:
Context()
: fInvalid_Type(new Type(String("<INVALID>")))
, fVoid_Type(new Type(String("void")))
- , fDouble_Type(new Type(String("double"), true))
+ , fDouble_Type(new Type(String("double"), Type::kFloat_NumberKind))
, fDouble2_Type(new Type(String("double2"), *fDouble_Type, 2))
, fDouble3_Type(new Type(String("double3"), *fDouble_Type, 3))
, fDouble4_Type(new Type(String("double4"), *fDouble_Type, 4))
- , fFloat_Type(new Type(String("float"), true, { fDouble_Type.get() }))
+ , fFloat_Type(new Type(String("float"), Type::kFloat_NumberKind))
, fFloat2_Type(new Type(String("float2"), *fFloat_Type, 2))
, fFloat3_Type(new Type(String("float3"), *fFloat_Type, 3))
, fFloat4_Type(new Type(String("float4"), *fFloat_Type, 4))
- , fUInt_Type(new Type(String("uint"), true, { fFloat_Type.get(), fDouble_Type.get() }))
+ , fHalf_Type(new Type(String("half"), Type::kFloat_NumberKind))
+ , fHalf2_Type(new Type(String("half2"), *fHalf_Type, 2))
+ , fHalf3_Type(new Type(String("half3"), *fHalf_Type, 3))
+ , fHalf4_Type(new Type(String("half4"), *fHalf_Type, 4))
+ , fUInt_Type(new Type(String("uint"), Type::kUnsigned_NumberKind))
, fUInt2_Type(new Type(String("uint2"), *fUInt_Type, 2))
, fUInt3_Type(new Type(String("uint3"), *fUInt_Type, 3))
, fUInt4_Type(new Type(String("uint4"), *fUInt_Type, 4))
- , fInt_Type(new Type(String("int"), true, { fUInt_Type.get(), fFloat_Type.get(),
- fDouble_Type.get() }))
+ , fInt_Type(new Type(String("int"), Type::kSigned_NumberKind))
, fInt2_Type(new Type(String("int2"), *fInt_Type, 2))
, fInt3_Type(new Type(String("int3"), *fInt_Type, 3))
, fInt4_Type(new Type(String("int4"), *fInt_Type, 4))
- , fBool_Type(new Type(String("bool"), false))
+ , fUShort_Type(new Type(String("ushort"), Type::kUnsigned_NumberKind))
+ , fUShort2_Type(new Type(String("ushort2"), *fUShort_Type, 2))
+ , fUShort3_Type(new Type(String("ushort3"), *fUShort_Type, 3))
+ , fUShort4_Type(new Type(String("ushort4"), *fUShort_Type, 4))
+ , fShort_Type(new Type(String("short"), Type::kSigned_NumberKind))
+ , fShort2_Type(new Type(String("short2"), *fShort_Type, 2))
+ , fShort3_Type(new Type(String("short3"), *fShort_Type, 3))
+ , fShort4_Type(new Type(String("short4"), *fShort_Type, 4))
+ , fBool_Type(new Type(String("bool"), Type::kNonnumeric_NumberKind))
, fBool2_Type(new Type(String("bool2"), *fBool_Type, 2))
, fBool3_Type(new Type(String("bool3"), *fBool_Type, 3))
, fBool4_Type(new Type(String("bool4"), *fBool_Type, 4))
- , fFloat2x2_Type(new Type(String("float2x2"), *fFloat_Type, 2, 2))
+ , fFloat2x2_Type(new Type(String("float2x2"), *fFloat_Type, 2, 2))
, fFloat2x3_Type(new Type(String("float2x3"), *fFloat_Type, 2, 3))
, fFloat2x4_Type(new Type(String("float2x4"), *fFloat_Type, 2, 4))
, fFloat3x2_Type(new Type(String("float3x2"), *fFloat_Type, 3, 2))
- , fFloat3x3_Type(new Type(String("float3x3"), *fFloat_Type, 3, 3))
+ , fFloat3x3_Type(new Type(String("float3x3"), *fFloat_Type, 3, 3))
, fFloat3x4_Type(new Type(String("float3x4"), *fFloat_Type, 3, 4))
, fFloat4x2_Type(new Type(String("float4x2"), *fFloat_Type, 4, 2))
, fFloat4x3_Type(new Type(String("float4x3"), *fFloat_Type, 4, 3))
- , fFloat4x4_Type(new Type(String("float4x4"), *fFloat_Type, 4, 4))
- , fDouble2x2_Type(new Type(String("double2x2"), *fFloat_Type, 2, 2))
- , fDouble2x3_Type(new Type(String("double2x3"), *fFloat_Type, 2, 3))
- , fDouble2x4_Type(new Type(String("double2x4"), *fFloat_Type, 2, 4))
- , fDouble3x2_Type(new Type(String("double3x2"), *fFloat_Type, 3, 2))
- , fDouble3x3_Type(new Type(String("double3x3"), *fFloat_Type, 3, 3))
- , fDouble3x4_Type(new Type(String("double3x4"), *fFloat_Type, 3, 4))
- , fDouble4x2_Type(new Type(String("double4x2"), *fFloat_Type, 4, 2))
- , fDouble4x3_Type(new Type(String("double4x3"), *fFloat_Type, 4, 3))
- , fDouble4x4_Type(new Type(String("double4x4"), *fFloat_Type, 4, 4))
+ , fFloat4x4_Type(new Type(String("float4x4"), *fFloat_Type, 4, 4))
+ , fHalf2x2_Type(new Type(String("half2x2"), *fHalf_Type, 2, 2))
+ , fHalf2x3_Type(new Type(String("half2x3"), *fHalf_Type, 2, 3))
+ , fHalf2x4_Type(new Type(String("half2x4"), *fHalf_Type, 2, 4))
+ , fHalf3x2_Type(new Type(String("half3x2"), *fHalf_Type, 3, 2))
+ , fHalf3x3_Type(new Type(String("half3x3"), *fHalf_Type, 3, 3))
+ , fHalf3x4_Type(new Type(String("half3x4"), *fHalf_Type, 3, 4))
+ , fHalf4x2_Type(new Type(String("half4x2"), *fHalf_Type, 4, 2))
+ , fHalf4x3_Type(new Type(String("half4x3"), *fHalf_Type, 4, 3))
+ , fHalf4x4_Type(new Type(String("half4x4"), *fHalf_Type, 4, 4))
+ , fDouble2x2_Type(new Type(String("double2x2"), *fDouble_Type, 2, 2))
+ , fDouble2x3_Type(new Type(String("double2x3"), *fDouble_Type, 2, 3))
+ , fDouble2x4_Type(new Type(String("double2x4"), *fDouble_Type, 2, 4))
+ , fDouble3x2_Type(new Type(String("double3x2"), *fDouble_Type, 3, 2))
+ , fDouble3x3_Type(new Type(String("double3x3"), *fDouble_Type, 3, 3))
+ , fDouble3x4_Type(new Type(String("double3x4"), *fDouble_Type, 3, 4))
+ , fDouble4x2_Type(new Type(String("double4x2"), *fDouble_Type, 4, 2))
+ , fDouble4x3_Type(new Type(String("double4x3"), *fDouble_Type, 4, 3))
+ , fDouble4x4_Type(new Type(String("double4x4"), *fDouble_Type, 4, 4))
, fSampler1D_Type(new Type(String("sampler1D"), SpvDim1D, false, false, false, true))
, fSampler2D_Type(new Type(String("sampler2D"), SpvDim2D, false, false, false, true))
, fSampler3D_Type(new Type(String("sampler3D"), SpvDim3D, false, false, false, true))
@@ -118,6 +138,8 @@ public:
static_type(*fSamplerCubeArrayShadow_Type)))
, fGenType_Type(new Type(String("$genType"), { fFloat_Type.get(), fFloat2_Type.get(),
fFloat3_Type.get(), fFloat4_Type.get() }))
+ , fGenHType_Type(new Type(String("$genHType"), { fHalf_Type.get(), fHalf2_Type.get(),
+ fHalf3_Type.get(), fHalf4_Type.get() }))
, fGenDType_Type(new Type(String("$genDType"), { fDouble_Type.get(), fDouble2_Type.get(),
fDouble3_Type.get(), fDouble4_Type.get() }))
, fGenIType_Type(new Type(String("$genIType"), { fInt_Type.get(), fInt2_Type.get(),
@@ -130,23 +152,34 @@ public:
fFloat2x4_Type.get(), fFloat3x2_Type.get(),
fFloat3x3_Type.get(), fFloat3x4_Type.get(),
fFloat4x2_Type.get(), fFloat4x3_Type.get(),
- fFloat4x4_Type.get(), fDouble2x2_Type.get(),
- fDouble2x3_Type.get(), fDouble2x4_Type.get(),
- fDouble3x2_Type.get(), fDouble3x3_Type.get(),
- fDouble3x4_Type.get(), fDouble4x2_Type.get(),
- fDouble4x3_Type.get(), fDouble4x4_Type.get() }))
+ fFloat4x4_Type.get(), fHalf2x2_Type.get(),
+ fHalf2x3_Type.get(), fHalf2x4_Type.get(),
+ fHalf3x2_Type.get(), fHalf3x3_Type.get(),
+ fHalf3x4_Type.get(), fHalf4x2_Type.get(),
+ fHalf4x3_Type.get(), fHalf4x4_Type.get(),
+ fDouble2x2_Type.get(), fDouble2x3_Type.get(),
+ fDouble2x4_Type.get(), fDouble3x2_Type.get(),
+ fDouble3x3_Type.get(), fDouble3x4_Type.get(),
+ fDouble4x2_Type.get(), fDouble4x3_Type.get(),
+ fDouble4x4_Type.get() }))
, fVec_Type(new Type(String("$vec"), { fInvalid_Type.get(), fFloat2_Type.get(),
fFloat3_Type.get(), fFloat4_Type.get() }))
, fGVec_Type(new Type(String("$gvec")))
, fGVec2_Type(new Type(String("$gfloat2")))
, fGVec3_Type(new Type(String("$gfloat3")))
, fGVec4_Type(new Type(String("$gfloat4"), static_type(*fFloat4_Type)))
+ , fHVec_Type(new Type(String("$hvec"), { fInvalid_Type.get(), fHalf2_Type.get(),
+ fHalf3_Type.get(), fHalf4_Type.get() }))
, fDVec_Type(new Type(String("$dvec"), { fInvalid_Type.get(), fDouble2_Type.get(),
fDouble3_Type.get(), fDouble4_Type.get() }))
, fIVec_Type(new Type(String("$ivec"), { fInvalid_Type.get(), fInt2_Type.get(),
fInt3_Type.get(), fInt4_Type.get() }))
, fUVec_Type(new Type(String("$uvec"), { fInvalid_Type.get(), fUInt2_Type.get(),
fUInt3_Type.get(), fUInt4_Type.get() }))
+ , fSVec_Type(new Type(String("$svec"), { fInvalid_Type.get(), fShort2_Type.get(),
+ fShort3_Type.get(), fShort4_Type.get() }))
+ , fUSVec_Type(new Type(String("$usvec"), { fInvalid_Type.get(), fUShort2_Type.get(),
+ fUShort3_Type.get(), fUShort4_Type.get() }))
, fBVec_Type(new Type(String("$bvec"), { fInvalid_Type.get(), fBool2_Type.get(),
fBool3_Type.get(), fBool4_Type.get() }))
, fSkCaps_Type(new Type(String("$sk_Caps")))
@@ -171,6 +204,11 @@ public:
const std::unique_ptr<Type> fFloat3_Type;
const std::unique_ptr<Type> fFloat4_Type;
+ const std::unique_ptr<Type> fHalf_Type;
+ const std::unique_ptr<Type> fHalf2_Type;
+ const std::unique_ptr<Type> fHalf3_Type;
+ const std::unique_ptr<Type> fHalf4_Type;
+
const std::unique_ptr<Type> fUInt_Type;
const std::unique_ptr<Type> fUInt2_Type;
const std::unique_ptr<Type> fUInt3_Type;
@@ -181,6 +219,16 @@ public:
const std::unique_ptr<Type> fInt3_Type;
const std::unique_ptr<Type> fInt4_Type;
+ const std::unique_ptr<Type> fUShort_Type;
+ const std::unique_ptr<Type> fUShort2_Type;
+ const std::unique_ptr<Type> fUShort3_Type;
+ const std::unique_ptr<Type> fUShort4_Type;
+
+ const std::unique_ptr<Type> fShort_Type;
+ const std::unique_ptr<Type> fShort2_Type;
+ const std::unique_ptr<Type> fShort3_Type;
+ const std::unique_ptr<Type> fShort4_Type;
+
const std::unique_ptr<Type> fBool_Type;
const std::unique_ptr<Type> fBool2_Type;
const std::unique_ptr<Type> fBool3_Type;
@@ -196,6 +244,16 @@ public:
const std::unique_ptr<Type> fFloat4x3_Type;
const std::unique_ptr<Type> fFloat4x4_Type;
+ const std::unique_ptr<Type> fHalf2x2_Type;
+ const std::unique_ptr<Type> fHalf2x3_Type;
+ const std::unique_ptr<Type> fHalf2x4_Type;
+ const std::unique_ptr<Type> fHalf3x2_Type;
+ const std::unique_ptr<Type> fHalf3x3_Type;
+ const std::unique_ptr<Type> fHalf3x4_Type;
+ const std::unique_ptr<Type> fHalf4x2_Type;
+ const std::unique_ptr<Type> fHalf4x3_Type;
+ const std::unique_ptr<Type> fHalf4x4_Type;
+
const std::unique_ptr<Type> fDouble2x2_Type;
const std::unique_ptr<Type> fDouble2x3_Type;
const std::unique_ptr<Type> fDouble2x4_Type;
@@ -249,6 +307,7 @@ public:
const std::unique_ptr<Type> fGSamplerCubeArrayShadow_Type;
const std::unique_ptr<Type> fGenType_Type;
+ const std::unique_ptr<Type> fGenHType_Type;
const std::unique_ptr<Type> fGenDType_Type;
const std::unique_ptr<Type> fGenIType_Type;
const std::unique_ptr<Type> fGenUType_Type;
@@ -262,9 +321,12 @@ public:
const std::unique_ptr<Type> fGVec2_Type;
const std::unique_ptr<Type> fGVec3_Type;
const std::unique_ptr<Type> fGVec4_Type;
+ const std::unique_ptr<Type> fHVec_Type;
const std::unique_ptr<Type> fDVec_Type;
const std::unique_ptr<Type> fIVec_Type;
const std::unique_ptr<Type> fUVec_Type;
+ const std::unique_ptr<Type> fSVec_Type;
+ const std::unique_ptr<Type> fUSVec_Type;
const std::unique_ptr<Type> fBVec_Type;
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index 330f14517d..69d3028298 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -68,6 +68,7 @@ void GLSLCodeGenerator::writeType(const Type& type) {
fIndentation++;
for (const auto& f : type.fields()) {
this->writeModifiers(f.fModifiers, false);
+ this->writeTypePrecision(*f.fType);
// sizes (which must be static in structs) are part of the type name here
this->writeType(*f.fType);
this->writeLine(" " + f.fName + ";");
@@ -78,32 +79,38 @@ void GLSLCodeGenerator::writeType(const Type& type) {
switch (type.kind()) {
case Type::kVector_Kind: {
Type component = type.componentType();
- if (component == *fContext.fFloat_Type) {
+ if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) {
this->write("vec");
}
else if (component == *fContext.fDouble_Type) {
this->write("dvec");
}
- else if (component == *fContext.fInt_Type) {
+ else if (component == *fContext.fInt_Type || component == *fContext.fShort_Type) {
this->write("ivec");
}
- else if (component == *fContext.fUInt_Type) {
+ else if (component == *fContext.fUInt_Type || component == *fContext.fUShort_Type) {
this->write("uvec");
}
else if (component == *fContext.fBool_Type) {
this->write("bvec");
}
+ else {
+ ABORT("unsupported vector type");
+ }
this->write(to_string(type.columns()));
break;
}
case Type::kMatrix_Kind: {
Type component = type.componentType();
- if (component == *fContext.fFloat_Type) {
+ if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) {
this->write("mat");
}
else if (component == *fContext.fDouble_Type) {
this->write("dmat");
}
+ else {
+ ABORT("unsupported matrix type");
+ }
this->write(to_string(type.columns()));
if (type.columns() != type.rows()) {
this->write("x");
@@ -120,6 +127,21 @@ void GLSLCodeGenerator::writeType(const Type& type) {
this->write("]");
break;
}
+ case Type::kScalar_Kind: {
+ if (type == *fContext.fHalf_Type) {
+ this->write("float");
+ }
+ else if (type == *fContext.fShort_Type) {
+ this->write("int");
+ }
+ else if (type == *fContext.fUShort_Type) {
+ this->write("uint");
+ }
+ else {
+ this->write(type.name());
+ }
+ break;
+ }
default:
this->write(type.name());
}
@@ -653,6 +675,7 @@ void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
}
for (const auto& f : structType->fields()) {
this->writeModifiers(f.fModifiers, false);
+ this->writeTypePrecision(*f.fType);
this->writeType(*f.fType);
this->writeLine(" " + f.fName + ";");
}
@@ -676,6 +699,25 @@ void GLSLCodeGenerator::writeVarInitializer(const Variable& var, const Expressio
this->writeExpression(value, kTopLevel_Precedence);
}
+void GLSLCodeGenerator::writeTypePrecision(const Type& type) {
+ if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
+ switch (type.kind()) {
+ case Type::kScalar_Kind:
+ if (type == *fContext.fHalf_Type || type == *fContext.fShort_Type ||
+ type == *fContext.fUShort_Type) {
+ this->write("mediump ");
+ }
+ break;
+ case Type::kVector_Kind: // fall through
+ case Type::kMatrix_Kind:
+ this->writeTypePrecision(type.componentType());
+ break;
+ default:
+ break;
+ }
+ }
+}
+
void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) {
ASSERT(decl.fVars.size() > 0);
bool wroteType = false;
@@ -685,6 +727,7 @@ void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool g
this->write(", ");
} else {
this->writeModifiers(var.fVar->fModifiers, global);
+ this->writeTypePrecision(decl.fBaseType);
this->writeType(decl.fBaseType);
this->write(" ");
wroteType = true;
diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h
index 115d89ab28..e10299aa14 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.h
+++ b/src/sksl/SkSLGLSLCodeGenerator.h
@@ -116,6 +116,8 @@ protected:
virtual void writeVarInitializer(const Variable& var, const Expression& value);
+ void writeTypePrecision(const Type& type);
+
void writeVarDeclarations(const VarDeclarations& decl, bool global);
void writeFragCoord();
@@ -150,7 +152,7 @@ protected:
void writeBoolLiteral(const BoolLiteral& b);
- void writeIntLiteral(const IntLiteral& i);
+ virtual void writeIntLiteral(const IntLiteral& i);
void writeFloatLiteral(const FloatLiteral& f);
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 3604cd91d8..a46a9312c1 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -910,7 +910,7 @@ std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr
if (expr->fType == *fContext.fInvalid_Type) {
return nullptr;
}
- if (!expr->fType.canCoerceTo(type)) {
+ if (expr->coercionCost(type) == INT_MAX) {
fErrors.error(expr->fPosition, "expected '" + type.description() + "', but found '" +
expr->fType.description() + "'");
return nullptr;
@@ -1213,8 +1213,20 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
const Type* leftType;
const Type* rightType;
const Type* resultType;
- if (!determine_binary_type(fContext, expression.fOperator, left->fType, right->fType, &leftType,
- &rightType, &resultType,
+ const Type* rawLeftType;
+ if (left->fKind == Expression::kIntLiteral_Kind && right->fType.isInteger()) {
+ rawLeftType = &right->fType;
+ } else {
+ rawLeftType = &left->fType;
+ }
+ const Type* rawRightType;
+ if (right->fKind == Expression::kIntLiteral_Kind && left->fType.isInteger()) {
+ rawRightType = &left->fType;
+ } else {
+ rawRightType = &right->fType;
+ }
+ if (!determine_binary_type(fContext, expression.fOperator, *rawLeftType, *rawRightType,
+ &leftType, &rightType, &resultType,
!Token::IsAssignment(expression.fOperator))) {
fErrors.error(expression.fPosition, "type mismatch: '" +
Token::OperatorName(expression.fOperator) +
@@ -1367,32 +1379,30 @@ std::unique_ptr<Expression> IRGenerator::call(Position position,
}
/**
- * Determines the cost of coercing the arguments of a function to the required types. Returns true
- * if the cost could be computed, false if the call is not valid. Cost has no particular meaning
- * other than "lower costs are preferred".
+ * Determines the cost of coercing the arguments of a function to the required types. Cost has no
+ * particular meaning other than "lower costs are preferred". Returns INT_MAX if the call is not
+ * valid.
*/
-bool IRGenerator::determineCallCost(const FunctionDeclaration& function,
- const std::vector<std::unique_ptr<Expression>>& arguments,
- int* outCost) {
+int IRGenerator::callCost(const FunctionDeclaration& function,
+ const std::vector<std::unique_ptr<Expression>>& arguments) {
if (function.fParameters.size() != arguments.size()) {
- return false;
+ return INT_MAX;
}
int total = 0;
std::vector<const Type*> types;
const Type* ignored;
if (!function.determineFinalTypes(arguments, &types, &ignored)) {
- return false;
+ return INT_MAX;
}
for (size_t i = 0; i < arguments.size(); i++) {
- int cost;
- if (arguments[i]->fType.determineCoercionCost(*types[i], &cost)) {
+ int cost = arguments[i]->coercionCost(*types[i]);
+ if (cost != INT_MAX) {
total += cost;
} else {
- return false;
+ return INT_MAX;
}
}
- *outCost = total;
- return true;
+ return total;
}
std::unique_ptr<Expression> IRGenerator::applyColorSpace(std::unique_ptr<Expression> texture,
@@ -1436,8 +1446,8 @@ std::unique_ptr<Expression> IRGenerator::call(Position position,
const FunctionDeclaration* best = nullptr;
if (ref->fFunctions.size() > 1) {
for (const auto& f : ref->fFunctions) {
- int cost;
- if (this->determineCallCost(*f, arguments, &cost) && cost < bestCost) {
+ int cost = this->callCost(*f, arguments);
+ if (cost < bestCost) {
bestCost = cost;
best = f;
}
@@ -1470,8 +1480,16 @@ std::unique_ptr<Expression> IRGenerator::convertNumberConstructor(
to_string((uint64_t) args.size()) + ")");
return nullptr;
}
- if (type == *fContext.fFloat_Type && args.size() == 1 &&
- args[0]->fKind == Expression::kIntLiteral_Kind) {
+ if (type.isFloat() && args[0]->fType.isFloat()) {
+ return std::move(args[0]);
+ }
+ if (type.isSigned() && args[0]->fType.isSigned()) {
+ return std::move(args[0]);
+ }
+ if (type.isUnsigned() && args[0]->fType.isUnsigned()) {
+ return std::move(args[0]);
+ }
+ if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kIntLiteral_Kind) {
int64_t value = ((IntLiteral&) *args[0]).fValue;
return std::unique_ptr<Expression>(new FloatLiteral(fContext, position, (double) value));
}
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index 70416c5379..0a1bae4f64 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -106,11 +106,11 @@ private:
std::unique_ptr<Expression> call(Position position,
const FunctionDeclaration& function,
std::vector<std::unique_ptr<Expression>> arguments);
- bool determineCallCost(const FunctionDeclaration& function,
- const std::vector<std::unique_ptr<Expression>>& arguments,
- int* outCost);
+ int callCost(const FunctionDeclaration& function,
+ const std::vector<std::unique_ptr<Expression>>& arguments);
std::unique_ptr<Expression> call(Position position, std::unique_ptr<Expression> function,
std::vector<std::unique_ptr<Expression>> arguments);
+ int coercionCost(const Expression& expr, const Type& type);
std::unique_ptr<Expression> coerce(std::unique_ptr<Expression> expr, const Type& type);
std::unique_ptr<Block> convertBlock(const ASTBlock& block);
std::unique_ptr<Statement> convertBreak(const ASTBreakStatement& b);
diff --git a/src/sksl/ir/SkSLExpression.h b/src/sksl/ir/SkSLExpression.h
index 89a1a1e84a..286610f078 100644
--- a/src/sksl/ir/SkSLExpression.h
+++ b/src/sksl/ir/SkSLExpression.h
@@ -85,6 +85,10 @@ struct Expression : public IRNode {
return nullptr;
}
+ virtual int coercionCost(const Type& target) const {
+ return fType.coercionCost(target);
+ }
+
const Kind fKind;
const Type& fType;
diff --git a/src/sksl/ir/SkSLIntLiteral.h b/src/sksl/ir/SkSLIntLiteral.h
index d8eba5573a..6199f96610 100644
--- a/src/sksl/ir/SkSLIntLiteral.h
+++ b/src/sksl/ir/SkSLIntLiteral.h
@@ -40,6 +40,13 @@ struct IntLiteral : public Expression {
return fValue == i.fValue;
}
+ int coercionCost(const Type& target) const override {
+ if (target.isUnsigned()) {
+ return 0;
+ }
+ return INHERITED::coercionCost(target);
+ }
+
const int64_t fValue;
typedef Expression INHERITED;
diff --git a/src/sksl/ir/SkSLType.cpp b/src/sksl/ir/SkSLType.cpp
index 60d40cd867..1fdc9bb68a 100644
--- a/src/sksl/ir/SkSLType.cpp
+++ b/src/sksl/ir/SkSLType.cpp
@@ -10,31 +10,37 @@
namespace SkSL {
-bool Type::determineCoercionCost(const Type& other, int* outCost) const {
+int Type::coercionCost(const Type& other) const {
if (*this == other) {
- *outCost = 0;
- return true;
+ return 0;
}
if (this->kind() == kVector_Kind && other.kind() == kVector_Kind) {
if (this->columns() == other.columns()) {
- return this->componentType().determineCoercionCost(other.componentType(), outCost);
+ return this->componentType().coercionCost(other.componentType());
}
- return false;
+ return INT_MAX;
}
if (this->kind() == kMatrix_Kind) {
- if (this->columns() == other.columns() &&
- this->rows() == other.rows()) {
- return this->componentType().determineCoercionCost(other.componentType(), outCost);
+ if (this->columns() == other.columns() && this->rows() == other.rows()) {
+ return this->componentType().coercionCost(other.componentType());
}
- return false;
+ return INT_MAX;
+ }
+ if (this->isNumber() && other.isFloat()) {
+ return 1;
+ }
+ if (this->isSigned() && other.isSigned()) {
+ return 1;
+ }
+ if (this->isUnsigned() && other.isUnsigned()) {
+ return 1;
}
for (size_t i = 0; i < fCoercibleTypes.size(); i++) {
if (*fCoercibleTypes[i] == other) {
- *outCost = (int) i + 1;
- return true;
+ return (int) i + 1;
}
}
- return false;
+ return INT_MAX;
}
const Type& Type::toCompound(const Context& context, int columns, int rows) const {
diff --git a/src/sksl/ir/SkSLType.h b/src/sksl/ir/SkSLType.h
index 9d122635c2..1f793da2d9 100644
--- a/src/sksl/ir/SkSLType.h
+++ b/src/sksl/ir/SkSLType.h
@@ -51,37 +51,47 @@ public:
kOther_Kind
};
+ enum NumberKind {
+ kFloat_NumberKind,
+ kSigned_NumberKind,
+ kUnsigned_NumberKind,
+ kNonnumeric_NumberKind
+ };
+
// Create an "other" (special) type with the given name. These types cannot be directly
// referenced from user code.
Type(String name)
: INHERITED(Position(), kType_Kind, std::move(name))
- , fTypeKind(kOther_Kind) {}
+ , fTypeKind(kOther_Kind)
+ , fNumberKind(kNonnumeric_NumberKind) {}
// Create a generic type which maps to the listed types.
Type(String name, std::vector<const Type*> types)
: INHERITED(Position(), kType_Kind, std::move(name))
, fTypeKind(kGeneric_Kind)
+ , fNumberKind(kNonnumeric_NumberKind)
, fCoercibleTypes(std::move(types)) {}
// Create a struct type with the given fields.
Type(Position position, String name, std::vector<Field> fields)
: INHERITED(position, kType_Kind, std::move(name))
, fTypeKind(kStruct_Kind)
+ , fNumberKind(kNonnumeric_NumberKind)
, fFields(std::move(fields)) {}
// Create a scalar type.
- Type(String name, bool isNumber)
+ Type(String name, NumberKind numberKind)
: INHERITED(Position(), kType_Kind, std::move(name))
, fTypeKind(kScalar_Kind)
- , fIsNumber(isNumber)
+ , fNumberKind(numberKind)
, fColumns(1)
, fRows(1) {}
// Create a scalar type which can be coerced to the listed types.
- Type(String name, bool isNumber, std::vector<const Type*> coercibleTypes)
+ Type(String name, NumberKind numberKind, std::vector<const Type*> coercibleTypes)
: INHERITED(Position(), kType_Kind, std::move(name))
, fTypeKind(kScalar_Kind)
- , fIsNumber(isNumber)
+ , fNumberKind(numberKind)
, fCoercibleTypes(std::move(coercibleTypes))
, fColumns(1)
, fRows(1) {}
@@ -94,6 +104,7 @@ public:
Type(String name, Kind kind, const Type& componentType, int columns)
: INHERITED(Position(), kType_Kind, std::move(name))
, fTypeKind(kind)
+ , fNumberKind(kNonnumeric_NumberKind)
, fComponentType(&componentType)
, fColumns(columns)
, fRows(1)
@@ -103,6 +114,7 @@ public:
Type(String name, const Type& componentType, int columns, int rows)
: INHERITED(Position(), kType_Kind, std::move(name))
, fTypeKind(kMatrix_Kind)
+ , fNumberKind(kNonnumeric_NumberKind)
, fComponentType(&componentType)
, fColumns(columns)
, fRows(rows)
@@ -113,13 +125,14 @@ public:
bool isSampled)
: INHERITED(Position(), kType_Kind, std::move(name))
, fTypeKind(kSampler_Kind)
+ , fNumberKind(kNonnumeric_NumberKind)
, fDimensions(dimensions)
, fIsDepth(isDepth)
, fIsArrayed(isArrayed)
, fIsMultisampled(isMultisampled)
, fIsSampled(isSampled) {}
- String name() const {
+ const String& name() const {
return fName;
}
@@ -146,7 +159,35 @@ public:
* Returns true if this is a numeric scalar type.
*/
bool isNumber() const {
- return fIsNumber;
+ return fNumberKind != kNonnumeric_NumberKind;
+ }
+
+ /**
+ * Returns true if this is a floating-point scalar type (float, half, or double).
+ */
+ bool isFloat() const {
+ return fNumberKind == kFloat_NumberKind;
+ }
+
+ /**
+ * Returns true if this is a signed scalar type (int or short).
+ */
+ bool isSigned() const {
+ return fNumberKind == kSigned_NumberKind;
+ }
+
+ /**
+ * Returns true if this is an unsigned scalar type (uint or ushort).
+ */
+ bool isUnsigned() const {
+ return fNumberKind == kUnsigned_NumberKind;
+ }
+
+ /**
+ * Returns true if this is a signed or unsigned integer.
+ */
+ bool isInteger() const {
+ return isSigned() || isUnsigned();
}
/**
@@ -154,17 +195,15 @@ public:
* another type.
*/
bool canCoerceTo(const Type& other) const {
- int cost;
- return determineCoercionCost(other, &cost);
+ return coercionCost(other) != INT_MAX;
}
/**
* Determines the "cost" of coercing (implicitly converting) this type to another type. The cost
* is a number with no particular meaning other than that lower costs are preferable to higher
- * costs. Returns true if a conversion is possible, false otherwise. The value of the out
- * parameter is undefined if false is returned.
+ * costs. Returns INT_MAX if the coercion is not possible.
*/
- bool determineCoercionCost(const Type& other, int* outCost) const;
+ int coercionCost(const Type& other) const;
/**
* For matrices and vectors, returns the type of individual cells (e.g. mat2 has a component
@@ -244,7 +283,8 @@ private:
typedef Symbol INHERITED;
const Kind fTypeKind;
- const bool fIsNumber = false;
+ // always kNonnumeric_NumberKind for non-scalar values
+ const NumberKind fNumberKind;
const Type* fComponentType = nullptr;
const std::vector<const Type*> fCoercibleTypes;
const int fColumns = -1;
diff --git a/src/sksl/sksl.include b/src/sksl/sksl.include
index 5d905e3435..7b738d5845 100644
--- a/src/sksl/sksl.include
+++ b/src/sksl/sksl.include
@@ -99,6 +99,8 @@ $genIType floatBitsToInt($genType value);
$genType intBitsToFloat($genIType value);
$genType uintBitsToFloat($genUType value);
$genType fma($genType a, $genType b, $genType c);
+$genHType fma($genHType a, $genHType b, $genHType c);
+$genDType fma($genDType a, $genDType b, $genDType c);
//$genDType fma($genDType a, $genDType b, $genDType c);
$genType frexp($genType x, out $genIType exp);
//$genDType frexp($genDType x, out $genIType exp);
@@ -117,22 +119,30 @@ uint2 unpackDouble2x32(double v);
uint packHalf2x16(float2 v);
float2 unpackHalf2x16(uint v);
float length($genType x);
-//double length($genDType x);
+half length($genHType x);
+double length($genDType x);
float distance($genType p0, $genType p1);
-//double distance($genDType p0, $genDType p1);
+half distance($genHType p0, $genHType p1);
+double distance($genDType p0, $genDType p1);
float dot($genType x, $genType y);
-//double dot($genDType x, $genDType y);
+half dot($genHType x, $genHType y);
+double dot($genDType x, $genDType y);
float3 cross(float3 x, float3 y);
-//double3 cross(double3 x, double3 y);
+half3 cross(half3 x, half3 y);
+double3 cross(double3 x, double3 y);
$genType normalize($genType x);
-//$genDType normalize($genDType x);
+$genHType normalize($genHType x);
+$genDType normalize($genDType x);
float4 ftransform();
$genType faceforward($genType N, $genType I, $genType Nref);
-//$genDType faceforward($genDType N, $genDType I, $genDType Nref);
+$genHType faceforward($genHType N, $genHType I, $genHType Nref);
+$genDType faceforward($genDType N, $genDType I, $genDType Nref);
$genType reflect($genType I, $genType N);
-//$genDType reflect($genDType I, $genDType N);
+$genHType reflect($genHType I, $genHType N);
+$genDType reflect($genDType I, $genDType N);
$genType refract($genType I, $genType N, float eta);
-//$genDType refract($genDType I, $genDType N, float eta);
+$genHType refract($genHType I, $genHType N, float eta);
+$genDType refract($genDType I, $genDType N, float eta);
$mat matrixCompMult($mat x, $mat y);
float2x2 outerProduct(float2 c, float2 r);
float3x3 outerProduct(float3 c, float3 r);
@@ -159,24 +169,48 @@ float2x2 inverse(float2x2 m);
float3x3 inverse(float3x3 m);
float4x4 inverse(float4x4 m);
$bvec lessThan($vec x, $vec y);
+$bvec lessThan($hvec x, $hvec y);
+$bvec lessThan($dvec x, $dvec y);
$bvec lessThan($ivec x, $ivec y);
+$bvec lessThan($svec x, $svec y);
+$bvec lessThan($usvec x, $usvec y);
$bvec lessThan($uvec x, $uvec y);
$bvec lessThanEqual($vec x, $vec y);
+$bvec lessThanEqual($hvec x, $hvec y);
+$bvec lessThanEqual($dvec x, $dvec y);
$bvec lessThanEqual($ivec x, $ivec y);
$bvec lessThanEqual($uvec x, $uvec y);
+$bvec lessThanEqual($svec x, $svec y);
+$bvec lessThanEqual($usvec x, $usvec y);
$bvec greaterThan($vec x, $vec y);
+$bvec greaterThan($hvec x, $hvec y);
+$bvec greaterThan($dvec x, $dvec y);
$bvec greaterThan($ivec x, $ivec y);
$bvec greaterThan($uvec x, $uvec y);
+$bvec greaterThan($svec x, $svec y);
+$bvec greaterThan($usvec x, $usvec y);
$bvec greaterThanEqual($vec x, $vec y);
+$bvec greaterThanEqual($hvec x, $hvec y);
+$bvec greaterThanEqual($dvec x, $dvec y);
$bvec greaterThanEqual($ivec x, $ivec y);
$bvec greaterThanEqual($uvec x, $uvec y);
+$bvec greaterThanEqual($svec x, $svec y);
+$bvec greaterThanEqual($usvec x, $usvec y);
$bvec equal($vec x, $vec y);
+$bvec equal($hvec x, $hvec y);
+$bvec equal($dvec x, $dvec y);
$bvec equal($ivec x, $ivec y);
$bvec equal($uvec x, $uvec y);
+$bvec equal($svec x, $svec y);
+$bvec equal($usvec x, $usvec y);
$bvec equal($bvec x, $bvec y);
$bvec notEqual($vec x, $vec y);
+$bvec notEqual($hvec x, $hvec y);
+$bvec notEqual($dvec x, $dvec y);
$bvec notEqual($ivec x, $ivec y);
$bvec notEqual($uvec x, $uvec y);
+$bvec notEqual($svec x, $svec y);
+$bvec notEqual($usvec x, $usvec y);
$bvec notEqual($bvec x, $bvec y);
bool any($bvec x);
bool all($bvec x);
diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp
index de002c7e81..80727d9804 100644
--- a/tests/SkSLGLSLTest.cpp
+++ b/tests/SkSLGLSLTest.cpp
@@ -316,7 +316,7 @@ DEF_TEST(SkSLUsesPrecisionModifiers, r) {
" sk_FragColor.xy = vec2(x, y);\n"
"}\n");
test(r,
- "void main() { float x = 0.75; highp float y = 1; x++; y++;"
+ "void main() { float x = 0.75; half y = 1; x++; y++;"
"sk_FragColor.rg = float2(x, y); }",
*SkSL::ShaderCapsFactory::UsesPrecisionModifiers(),
"#version 400\n"
@@ -324,7 +324,7 @@ DEF_TEST(SkSLUsesPrecisionModifiers, r) {
"out mediump vec4 sk_FragColor;\n"
"void main() {\n"
" float x = 0.75;\n"
- " highp float y = 1.0;\n"
+ " mediump float y = 1.0;\n"
" x++;\n"
" y++;\n"
" sk_FragColor.xy = vec2(x, y);\n"
@@ -1432,4 +1432,151 @@ DEF_TEST(SkSLInvocations, r) {
SkSL::Program::kGeometry_Kind);
}
+DEF_TEST(SkSLTypePrecision, r) {
+ test(r,
+ "float f = 1;"
+ "half h = 2;"
+ "double d = 3;"
+ "float2 f2 = float2(1, 2);"
+ "half3 h3 = half3(1, 2, 3);"
+ "double4 d4 = double4(1, 2, 3, 4);"
+ "float2x2 f22 = float2x2(1, 2, 3, 4);"
+ "half2x4 h24 = half2x4(1, 2, 3, 4, 5, 6, 7, 8);"
+ "double4x2 d42 = double4x2(1, 2, 3, 4, 5, 6, 7, 8);",
+ *SkSL::ShaderCapsFactory::Default(),
+ "#version 400\n"
+ "out vec4 sk_FragColor;\n"
+ "float f = 1.0;\n"
+ "float h = 2.0;\n"
+ "double d = 3.0;\n"
+ "vec2 f2 = vec2(1.0, 2.0);\n"
+ "vec3 h3 = vec3(1.0, 2.0, 3.0);\n"
+ "dvec4 d4 = dvec4(1.0, 2.0, 3.0, 4.0);\n"
+ "mat2 f22 = mat2(1.0, 2.0, 3.0, 4.0);\n"
+ "mat2x4 h24 = mat2x4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);\n"
+ "dmat4x2 d42 = dmat4x2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);\n");
+ test(r,
+ "float f = 1;"
+ "half h = 2;"
+ "float2 f2 = float2(1, 2);"
+ "half3 h3 = half3(1, 2, 3);"
+ "float2x2 f22 = float2x2(1, 2, 3, 4);"
+ "half2x4 h24 = half2x4(1, 2, 3, 4, 5, 6, 7, 8);",
+ *SkSL::ShaderCapsFactory::UsesPrecisionModifiers(),
+ "#version 400\n"
+ "precision highp float;\n"
+ "out mediump vec4 sk_FragColor;\n"
+ "float f = 1.0;\n"
+ "mediump float h = 2.0;\n"
+ "vec2 f2 = vec2(1.0, 2.0);\n"
+ "mediump vec3 h3 = vec3(1.0, 2.0, 3.0);\n"
+ "mat2 f22 = mat2(1.0, 2.0, 3.0, 4.0);\n"
+ "mediump mat2x4 h24 = mat2x4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);\n");
+}
+
+DEF_TEST(SkSLNumberConversions, r) {
+ test(r,
+ "short s = short(sqrt(1));"
+ "int i = int(sqrt(1));"
+ "ushort us = ushort(sqrt(1));"
+ "uint ui = uint(sqrt(1));"
+ "half h = sqrt(1);"
+ "float f = sqrt(1);"
+ "double d = sqrt(1);"
+ "short s2s = s;"
+ "short i2s = i;"
+ "short us2s = short(us);"
+ "short ui2s = short(ui);"
+ "short h2s = short(h);"
+ "short f2s = short(f);"
+ "short d2fs = short(d);"
+ "int s2i = s;"
+ "int i2i = i;"
+ "int us2i = int(us);"
+ "int ui2i = int(ui);"
+ "int h2i = int(h);"
+ "int f2i = int(f);"
+ "int d2fi = int(d);"
+ "ushort s2us = ushort(s);"
+ "ushort i2us = ushort(i);"
+ "ushort us2us = us;"
+ "ushort ui2us = ui;"
+ "ushort h2us = ushort(h);"
+ "ushort f2us = ushort(f);"
+ "ushort d2fus = ushort(d);"
+ "uint s2ui = uint(s);"
+ "uint i2ui = uint(i);"
+ "uint us2ui = us;"
+ "uint ui2ui = ui;"
+ "uint h2ui = uint(h);"
+ "uint f2ui = uint(f);"
+ "uint d2fui = uint(d);"
+ "float s2f = s;"
+ "float i2f = i;"
+ "float us2f = us;"
+ "float ui2f = ui;"
+ "float h2f = h;"
+ "float f2f = f;"
+ "float d2f = d;"
+ "double s2d = s;"
+ "double i2d = i;"
+ "double us2d = us;"
+ "double ui2d = ui;"
+ "double h2d = h;"
+ "double f2d = f;"
+ "double d2d = d;",
+ *SkSL::ShaderCapsFactory::Default(),
+ "#version 400\n"
+ "out vec4 sk_FragColor;\n"
+ "int s = int(sqrt(1.0));\n"
+ "int i = int(sqrt(1.0));\n"
+ "uint us = uint(sqrt(1.0));\n"
+ "uint ui = uint(sqrt(1.0));\n"
+ "float h = sqrt(1.0);\n"
+ "float f = sqrt(1.0);\n"
+ "double d = sqrt(1.0);\n"
+ "int s2s = s;\n"
+ "int i2s = i;\n"
+ "int us2s = int(us);\n"
+ "int ui2s = int(ui);\n"
+ "int h2s = int(h);\n"
+ "int f2s = int(f);\n"
+ "int d2fs = int(d);\n"
+ "int s2i = s;\n"
+ "int i2i = i;\n"
+ "int us2i = int(us);\n"
+ "int ui2i = int(ui);\n"
+ "int h2i = int(h);\n"
+ "int f2i = int(f);\n"
+ "int d2fi = int(d);\n"
+ "uint s2us = uint(s);\n"
+ "uint i2us = uint(i);\n"
+ "uint us2us = us;\n"
+ "uint ui2us = ui;\n"
+ "uint h2us = uint(h);\n"
+ "uint f2us = uint(f);\n"
+ "uint d2fus = uint(d);\n"
+ "uint s2ui = uint(s);\n"
+ "uint i2ui = uint(i);\n"
+ "uint us2ui = us;\n"
+ "uint ui2ui = ui;\n"
+ "uint h2ui = uint(h);\n"
+ "uint f2ui = uint(f);\n"
+ "uint d2fui = uint(d);\n"
+ "float s2f = float(s);\n"
+ "float i2f = float(i);\n"
+ "float us2f = float(us);\n"
+ "float ui2f = float(ui);\n"
+ "float h2f = h;\n"
+ "float f2f = f;\n"
+ "float d2f = d;\n"
+ "double s2d = double(s);\n"
+ "double i2d = double(i);\n"
+ "double us2d = double(us);\n"
+ "double ui2d = double(ui);\n"
+ "double h2d = h;\n"
+ "double f2d = f;\n"
+ "double d2d = d;\n");
+}
+
#endif