Rearrange SkSL pre-include modules to hide things

This makes numerous internal and GLSL types or intrinsics hidden from
public (runtime effect) SkSL. In particular:

- Only core numeric types are visible to all program types. GLSL types
  involving images, textures, and sampling are restricted to internal use.
- sk_Caps is no longer visible to runtime effects.
- The set of intrinsics available to runtime effects is now a separate,
  curated list in sksl_public.sksl. It exactly matches the GLSL ES 1.00
  spec order.
- The blend intrinsics are no longer visible, which also fixes a bug.
  These are nice, but we're not going to offer them yet - they involve
  enums, which creates complications.

Bug: skia:10680
Bug: skia:10709
Bug: skia:10913

Change-Id: I8fa1c94f6e4899f38530bb9cff33d147f6983ab3
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/332597
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
This commit is contained in:
Brian Osman 2020-11-05 09:26:01 -05:00 committed by Skia Commit-Bot
parent f8f23b2030
commit bea0dc67f4
10 changed files with 1568 additions and 1485 deletions

View File

@ -604,6 +604,7 @@ if (skia_compile_processors || skia_compile_sksl_tests) {
"src/sksl/sksl_gpu.sksl",
"src/sksl/sksl_interp.sksl",
"src/sksl/sksl_pipeline.sksl",
"src/sksl/sksl_public.sksl",
"src/sksl/sksl_vert.sksl",
]
outputs = [ "$root_out_dir/{{source_file_part}}" ]

View File

@ -9,6 +9,9 @@ Milestone 88
* <insert new release notes here>
* Limit the types and intrinsics supported in SkRuntimeEffect to GLSL ES 1.00
https://review.skia.org/332597
* Image filters with perspective, for saveLayer and draws, are now drawn correctly. Performance
and quality is highest if user bounds are provided to saveLayer.
https://review.skia.org/328376

View File

@ -43,9 +43,9 @@ ByteCodeGenerator::ByteCodeGenerator(const Context* context, const Program* prog
: INHERITED(program, errors, nullptr)
, fContext(*context)
, fOutput(output)
// If you're adding new intrinsics here, ensure that they're declared in sksl_interp.inc, so
// they're available to "generic" interpreter programs (eg particles).
// You can probably copy the declarations from sksl_gpu.inc.
// If you're adding new intrinsics here, ensure that they're declared in sksl_interp.sksl or
// sksl_public.sksl, so they're available to "generic" interpreter programs (eg particles).
// You can probably copy the declarations from sksl_gpu.sksl.
, fIntrinsics {
{ "abs", ByteCodeInstruction::kAbs },
{ "atan", ByteCodeInstruction::kATan },

View File

@ -61,6 +61,7 @@
#include "src/sksl/generated/sksl_gpu.dehydrated.sksl"
#include "src/sksl/generated/sksl_interp.dehydrated.sksl"
#include "src/sksl/generated/sksl_pipeline.dehydrated.sksl"
#include "src/sksl/generated/sksl_public.dehydrated.sksl"
#include "src/sksl/generated/sksl_vert.dehydrated.sksl"
#define MODULE_DATA(name) MakeModuleData(SKSL_INCLUDE_sksl_##name,\
@ -89,142 +90,93 @@ Compiler::Compiler(const ShaderCapsClass* caps, Flags flags)
, fContext(std::make_shared<Context>())
, fErrorCount(0) {
fRootSymbolTable = std::make_shared<SymbolTable>(this, /*builtin=*/true);
fPrivateSymbolTable = std::make_shared<SymbolTable>(fRootSymbolTable, /*builtin=*/true);
fIRGenerator = std::make_unique<IRGenerator>(fContext.get(), &fInliner, *this);
#define ADD_TYPE(t) fRootSymbolTable->addWithoutOwnership(fContext->f##t##_Type.get())
ADD_TYPE(Void);
ADD_TYPE(Float);
ADD_TYPE(Float2);
ADD_TYPE(Float3);
ADD_TYPE(Float4);
ADD_TYPE(Half);
ADD_TYPE(Half2);
ADD_TYPE(Half3);
ADD_TYPE(Half4);
ADD_TYPE(Int);
ADD_TYPE(Int2);
ADD_TYPE(Int3);
ADD_TYPE(Int4);
ADD_TYPE(UInt);
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(Byte);
ADD_TYPE(Byte2);
ADD_TYPE(Byte3);
ADD_TYPE(Byte4);
ADD_TYPE(UByte);
ADD_TYPE(UByte2);
ADD_TYPE(UByte3);
ADD_TYPE(UByte4);
ADD_TYPE(Bool);
ADD_TYPE(Bool2);
ADD_TYPE(Bool3);
ADD_TYPE(Bool4);
ADD_TYPE(Float2x2);
ADD_TYPE(Float2x3);
ADD_TYPE(Float2x4);
ADD_TYPE(Float3x2);
ADD_TYPE(Float3x3);
ADD_TYPE(Float3x4);
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(GenType);
ADD_TYPE(GenHType);
ADD_TYPE(GenIType);
ADD_TYPE(GenUType);
ADD_TYPE(GenBType);
ADD_TYPE(Mat);
ADD_TYPE(Vec);
ADD_TYPE(GVec);
ADD_TYPE(GVec2);
ADD_TYPE(GVec3);
ADD_TYPE(GVec4);
ADD_TYPE(HVec);
ADD_TYPE(IVec);
ADD_TYPE(UVec);
ADD_TYPE(SVec);
ADD_TYPE(USVec);
ADD_TYPE(ByteVec);
ADD_TYPE(UByteVec);
ADD_TYPE(BVec);
ADD_TYPE(Sampler1D);
ADD_TYPE(Sampler2D);
ADD_TYPE(Sampler3D);
ADD_TYPE(SamplerExternalOES);
ADD_TYPE(SamplerCube);
ADD_TYPE(Sampler2DRect);
ADD_TYPE(Sampler1DArray);
ADD_TYPE(Sampler2DArray);
ADD_TYPE(SamplerCubeArray);
ADD_TYPE(SamplerBuffer);
ADD_TYPE(Sampler2DMS);
ADD_TYPE(Sampler2DMSArray);
#define TYPE(t) fContext->f##t##_Type.get()
ADD_TYPE(ISampler2D);
const SkSL::Symbol* rootTypes[] = {
TYPE(Void),
ADD_TYPE(Image2D);
ADD_TYPE(IImage2D);
TYPE( Float), TYPE( Float2), TYPE( Float3), TYPE( Float4),
TYPE( Half), TYPE( Half2), TYPE( Half3), TYPE( Half4),
TYPE( Int), TYPE( Int2), TYPE( Int3), TYPE( Int4),
TYPE( UInt), TYPE( UInt2), TYPE( UInt3), TYPE( UInt4),
TYPE( Short), TYPE( Short2), TYPE( Short3), TYPE( Short4),
TYPE(UShort), TYPE(UShort2), TYPE(UShort3), TYPE(UShort4),
TYPE( Byte), TYPE( Byte2), TYPE( Byte3), TYPE( Byte4),
TYPE( UByte), TYPE( UByte2), TYPE( UByte3), TYPE( UByte4),
TYPE( Bool), TYPE( Bool2), TYPE( Bool3), TYPE( Bool4),
ADD_TYPE(SubpassInput);
ADD_TYPE(SubpassInputMS);
TYPE(Float2x2), TYPE(Float2x3), TYPE(Float2x4),
TYPE(Float3x2), TYPE(Float3x3), TYPE(Float3x4),
TYPE(Float4x2), TYPE(Float4x3), TYPE(Float4x4),
ADD_TYPE(GSampler1D);
ADD_TYPE(GSampler2D);
ADD_TYPE(GSampler3D);
ADD_TYPE(GSamplerCube);
ADD_TYPE(GSampler2DRect);
ADD_TYPE(GSampler1DArray);
ADD_TYPE(GSampler2DArray);
ADD_TYPE(GSamplerCubeArray);
ADD_TYPE(GSamplerBuffer);
ADD_TYPE(GSampler2DMS);
ADD_TYPE(GSampler2DMSArray);
TYPE(Half2x2), TYPE(Half2x3), TYPE(Half2x4),
TYPE(Half3x2), TYPE(Half3x3), TYPE(Half3x4),
TYPE(Half4x2), TYPE(Half4x3), TYPE(Half4x4),
ADD_TYPE(Sampler1DShadow);
ADD_TYPE(Sampler2DShadow);
ADD_TYPE(SamplerCubeShadow);
ADD_TYPE(Sampler2DRectShadow);
ADD_TYPE(Sampler1DArrayShadow);
ADD_TYPE(Sampler2DArrayShadow);
ADD_TYPE(SamplerCubeArrayShadow);
ADD_TYPE(GSampler2DArrayShadow);
ADD_TYPE(GSamplerCubeArrayShadow);
ADD_TYPE(FragmentProcessor);
ADD_TYPE(Sampler);
ADD_TYPE(Texture2D);
TYPE(GenType), TYPE(GenHType), TYPE(GenIType), TYPE(GenUType), TYPE(GenBType),
TYPE(Mat), TYPE(Vec),
TYPE(GVec), TYPE(GVec2), TYPE(GVec3), TYPE(GVec4),
TYPE(HVec), TYPE(IVec), TYPE(UVec), TYPE(SVec), TYPE(USVec),
TYPE(ByteVec), TYPE(UByteVec), TYPE(BVec),
TYPE(FragmentProcessor),
};
const SkSL::Symbol* privateTypes[] = {
TYPE(Sampler1D), TYPE(Sampler2D), TYPE(Sampler3D),
TYPE(SamplerExternalOES),
TYPE(SamplerCube),
TYPE(Sampler2DRect),
TYPE(Sampler1DArray), TYPE(Sampler2DArray), TYPE(SamplerCubeArray),
TYPE(SamplerBuffer),
TYPE(Sampler2DMS), TYPE(Sampler2DMSArray),
TYPE(ISampler2D),
TYPE(Image2D), TYPE(IImage2D),
TYPE(SubpassInput), TYPE(SubpassInputMS),
TYPE(GSampler1D), TYPE(GSampler2D), TYPE(GSampler3D),
TYPE(GSamplerCube),
TYPE(GSampler2DRect),
TYPE(GSampler1DArray), TYPE(GSampler2DArray), TYPE(GSamplerCubeArray),
TYPE(GSamplerBuffer),
TYPE(GSampler2DMS), TYPE(GSampler2DMSArray),
TYPE(Sampler1DShadow), TYPE(Sampler2DShadow), TYPE(SamplerCubeShadow),
TYPE(Sampler2DRectShadow),
TYPE(Sampler1DArrayShadow), TYPE(Sampler2DArrayShadow), TYPE(SamplerCubeArrayShadow),
TYPE(GSampler2DArrayShadow), TYPE(GSamplerCubeArrayShadow),
TYPE(Sampler),
TYPE(Texture2D),
};
for (const SkSL::Symbol* type : rootTypes) {
fRootSymbolTable->addWithoutOwnership(type);
}
for (const SkSL::Symbol* type : privateTypes) {
fPrivateSymbolTable->addWithoutOwnership(type);
}
#undef TYPE
// sk_Caps is "builtin", but all references to it are resolved to Settings, so we don't need to
// treat it as builtin (ie, no need to clone it into the Program).
StringFragment skCapsName("sk_Caps");
fRootSymbolTable->add(std::make_unique<Variable>(/*offset=*/-1,
fIRGenerator->fModifiers->handle(Modifiers()),
skCapsName,
fContext->fSkCaps_Type.get(),
/*builtin=*/false,
Variable::Storage::kGlobal));
fPrivateSymbolTable->add(
std::make_unique<Variable>(/*offset=*/-1,
fIRGenerator->fModifiers->handle(Modifiers()),
"sk_Caps",
fContext->fSkCaps_Type.get(),
/*builtin=*/false,
Variable::Storage::kGlobal));
fRootModule = {fRootSymbolTable, /*fIntrinsics=*/nullptr};
fPrivateModule = {fPrivateSymbolTable, /*fIntrinsics=*/nullptr};
fGPUModule = this->parseModule(Program::kFragment_Kind, MODULE_DATA(gpu), fRootModule);
fGPUModule = this->parseModule(Program::kFragment_Kind, MODULE_DATA(gpu), fPrivateModule);
fVertexModule = this->parseModule(Program::kVertex_Kind, MODULE_DATA(vert), fGPUModule);
fFragmentModule = this->parseModule(Program::kFragment_Kind, MODULE_DATA(frag), fGPUModule);
}
@ -246,10 +198,17 @@ const ParsedModule& Compiler::loadFPModule() {
return fFPModule;
}
const ParsedModule& Compiler::loadPublicModule() {
if (!fPublicModule.fSymbols) {
fPublicModule = this->parseModule(Program::kGeneric_Kind, MODULE_DATA(public), fRootModule);
}
return fPublicModule;
}
const ParsedModule& Compiler::loadPipelineModule() {
if (!fPipelineModule.fSymbols) {
fPipelineModule =
this->parseModule(Program::kPipelineStage_Kind, MODULE_DATA(pipeline), fGPUModule);
fPipelineModule = this->parseModule(Program::kPipelineStage_Kind, MODULE_DATA(pipeline),
this->loadPublicModule());
// Add some aliases to the pipeline module so that it's friendlier, and more like GLSL
fPipelineModule.fSymbols->addAlias("shader", fContext->fFragmentProcessor_Type.get());
@ -283,8 +242,8 @@ const ParsedModule& Compiler::loadPipelineModule() {
const ParsedModule& Compiler::loadInterpreterModule() {
if (!fInterpreterModule.fSymbols) {
fInterpreterModule =
this->parseModule(Program::kGeneric_Kind, MODULE_DATA(interp), fRootModule);
fInterpreterModule = this->parseModule(Program::kGeneric_Kind, MODULE_DATA(interp),
this->loadPublicModule());
}
return fInterpreterModule;
}
@ -305,7 +264,13 @@ LoadedModule Compiler::loadModule(Program::Kind kind,
ModuleData data,
std::shared_ptr<SymbolTable> base) {
if (!base) {
base = fRootSymbolTable;
// NOTE: This is a workaround. The only time 'base' is null is when dehydrating includes.
// In that case, skslc doesn't know which module it's preparing, nor what the correct base
// module is. We can't use 'Root', because many GPU intrinsics reference private types,
// like samplers or textures. Today, 'Private' does contain the union of all known types,
// so this is safe. If we ever have types that only exist in 'Public' (for example), this
// logic needs to be smarter (by choosing the correct base for the module we're compiling).
base = fPrivateSymbolTable;
}
#if defined(SKSL_STANDALONE)

View File

@ -221,6 +221,7 @@ public:
private:
const ParsedModule& loadFPModule();
const ParsedModule& loadGeometryModule();
const ParsedModule& loadPublicModule();
const ParsedModule& loadInterpreterModule();
const ParsedModule& loadPipelineModule();
@ -266,15 +267,20 @@ private:
const ShaderCapsClass* fCaps = nullptr;
std::shared_ptr<SymbolTable> fRootSymbolTable;
std::shared_ptr<SymbolTable> fPrivateSymbolTable;
ParsedModule fRootModule;
ParsedModule fGPUModule;
ParsedModule fInterpreterModule;
ParsedModule fVertexModule;
ParsedModule fFragmentModule;
ParsedModule fGeometryModule;
ParsedModule fPipelineModule;
ParsedModule fFPModule;
ParsedModule fRootModule; // Core types
ParsedModule fPrivateModule; // [Root] + Internal types
ParsedModule fGPUModule; // [Private] + GPU intrinsics, helper functions
ParsedModule fVertexModule; // [GPU] + Vertex stage decls
ParsedModule fFragmentModule; // [GPU] + Fragment stage decls
ParsedModule fGeometryModule; // [GPU] + Geometry stage decls
ParsedModule fFPModule; // [GPU] + FP features
ParsedModule fPublicModule; // [Root] + Public features
ParsedModule fInterpreterModule; // [Public] + Interpreter-only decls
ParsedModule fPipelineModule; // [Public] + Runtime effect decls
// holds ModifiersPools belonging to the core includes for lifetime purposes
std::vector<std::unique_ptr<ModifiersPool>> fModifiers;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,108 +1,27 @@
$genType atan($genType y_over_x);
$genHType atan($genHType y_over_x);
$genType cos($genType y);
$genHType cos($genHType y);
float dot($genType x, $genType y);
half dot($genHType x, $genHType y);
$genType fract($genType x);
$genHType fract($genHType x);
float2x2 inverse(float2x2 m);
float3x3 inverse(float3x3 m);
float4x4 inverse(float4x4 m);
half2x2 inverse(half2x2 m);
half3x3 inverse(half3x3 m);
half4x4 inverse(half4x4 m);
float length($genType x);
half length($genHType x);
$genType normalize($genType x);
$genHType normalize($genHType x);
$genType pow($genType x, $genType y);
$genHType pow($genHType x, $genHType y);
$genType sin($genType x);
$genHType sin($genHType x);
$genType sqrt($genType x);
$genHType sqrt($genHType x);
$genType tan($genType x);
$genHType tan($genHType x);
// Certain useful GLSL intrinsics (or integer versions of those) that aren't in GLSL ES 1.00,
// but are supported by the ByteCode interpreter.
$genType min($genType x, $genType y);
$genType min($genType x, float y);
$genHType min($genHType x, $genHType y);
$genHType min($genHType x, half y);
$genIType min($genIType x, $genIType y);
$genIType min($genIType x, int y);
$genType max($genType x, $genType y);
$genType max($genType x, float y);
$genHType max($genHType x, $genHType y);
$genHType max($genHType x, half y);
$genIType min($genIType x, int y);
$genIType max($genIType x, $genIType y);
$genIType max($genIType x, int y);
$genType clamp($genType x, $genType minVal, $genType maxVal);
$genType clamp($genType x, float minVal, float maxVal);
$genHType clamp($genHType x, $genHType minVal, $genHType maxVal);
$genHType clamp($genHType x, half minVal, half maxVal);
$genIType max($genIType x, int y);
$genIType clamp($genIType x, $genIType minVal, $genIType maxVal);
$genIType clamp($genIType x, int minVal, int maxVal);
$genType saturate($genType x);
$genHType saturate($genHType x);
$genIType clamp($genIType x, int minVal, int maxVal);
$genType mix($genType x, $genType y, $genBType a);
$genHType mix($genHType x, $genHType y, $genBType a);
$genIType mix($genIType x, $genIType y, $genBType a);
$genBType mix($genBType x, $genBType y, $genBType a);
$genType mix($genType x, $genType y, $genType a);
$genType mix($genType x, $genType y, float a);
$genHType mix($genHType x, $genHType y, $genHType a);
$genHType mix($genHType x, $genHType y, half a);
$bvec lessThan($vec x, $vec y);
$bvec lessThan($hvec x, $hvec y);
$bvec lessThan($ivec x, $ivec y);
$bvec lessThan($uvec x, $uvec y);
$bvec lessThanEqual($vec x, $vec y);
$bvec lessThanEqual($hvec x, $hvec y);
$bvec lessThanEqual($ivec x, $ivec y);
$bvec lessThanEqual($uvec x, $uvec y);
$bvec greaterThan($vec x, $vec y);
$bvec greaterThan($hvec x, $hvec y);
$bvec greaterThan($ivec x, $ivec y);
$bvec greaterThan($uvec x, $uvec y);
$bvec greaterThanEqual($vec x, $vec y);
$bvec greaterThanEqual($hvec x, $hvec y);
$bvec greaterThanEqual($ivec x, $ivec y);
$bvec greaterThanEqual($uvec x, $uvec y);
$bvec equal($vec x, $vec y);
$bvec equal($hvec x, $hvec y);
$bvec equal($ivec x, $ivec y);
$bvec equal($uvec x, $uvec y);
$bvec equal($bvec x, $bvec y);
$bvec notEqual($vec x, $vec y);
$bvec notEqual($hvec x, $hvec y);
$bvec notEqual($ivec x, $ivec y);
$bvec notEqual($uvec x, $uvec y);
$bvec notEqual($bvec x, $bvec y);
bool any($bvec x);
bool all($bvec x);
$bvec not($bvec x);
float degrees(float rad) { return rad * 57.2957795; }
float2 degrees(float2 rad) { return rad * 57.2957795; }
float3 degrees(float3 rad) { return rad * 57.2957795; }
float4 degrees(float4 rad) { return rad * 57.2957795; }
float radians(float deg) { return deg * 0.0174532925; }
float2 radians(float2 deg) { return deg * 0.0174532925; }
float3 radians(float3 deg) { return deg * 0.0174532925; }
float4 radians(float4 deg) { return deg * 0.0174532925; }
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); }
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);
}

133
src/sksl/sksl_public.sksl Normal file
View File

@ -0,0 +1,133 @@
// Reduced set of intrinsics that are available to public SkSL (RuntimeEffect and Interpreter)
// See "The OpenGL ES Shading Language, Version 1.00, Section 8"
// For all of the TODO comments, refer to skbug.com/10913
// 8.1 : Angle and Trigonometry Functions
float radians(float deg) { return deg * 0.0174532925; }
float2 radians(float2 deg) { return deg * 0.0174532925; }
float3 radians(float3 deg) { return deg * 0.0174532925; }
float4 radians(float4 deg) { return deg * 0.0174532925; }
float degrees(float rad) { return rad * 57.2957795; }
float2 degrees(float2 rad) { return rad * 57.2957795; }
float3 degrees(float3 rad) { return rad * 57.2957795; }
float4 degrees(float4 rad) { return rad * 57.2957795; }
$genType sin($genType angle);
$genHType sin($genHType angle);
$genType cos($genType angle);
$genHType cos($genHType angle);
$genType tan($genType angle);
$genHType tan($genHType angle);
// TODO: asin(x)
// TODO: acos(y)
// TODO: atan(y, x)
$genType atan($genType y_over_x);
$genHType atan($genHType y_over_x);
// 8.2 : Exponential Functions
$genType pow($genType x, $genType y);
$genHType pow($genHType x, $genHType y);
// TODO: exp
// TODO: log
// TODO: exp2
// TODO: log2
$genType sqrt($genType x);
$genHType sqrt($genHType x);
// TODO: inversesqrt
// 8.3 : Common Functions
$genType abs($genType x);
$genHType abs($genHType x);
// TODO: sign(x)
$genType floor($genType x);
$genHType floor($genHType x);
$genType ceil($genType x);
$genHType ceil($genHType x);
$genType fract($genType x);
$genHType fract($genHType x);
// TODO: mod(x, y)
$genType min($genType x, $genType y);
$genType min($genType x, float y);
$genHType min($genHType x, $genHType y);
$genHType min($genHType x, half y);
$genType max($genType x, $genType y);
$genType max($genType x, float y);
$genHType max($genHType x, $genHType y);
$genHType max($genHType x, half y);
$genType clamp($genType x, $genType minVal, $genType maxVal);
$genType clamp($genType x, float minVal, float maxVal);
$genHType clamp($genHType x, $genHType minVal, $genHType maxVal);
$genHType clamp($genHType x, half minVal, half maxVal);
$genType mix($genType x, $genType y, $genType a);
$genType mix($genType x, $genType y, float a);
$genHType mix($genHType x, $genHType y, $genHType a);
$genHType mix($genHType x, $genHType y, half a);
// TODO: step(edge, x)
// TODO: smoothstep(edge0, edge1, x)
// SkSL Extension to GLSL:
$genType saturate($genType x);
$genHType saturate($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 dot($genType x, $genType y);
half dot($genHType x, $genHType y);
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);
}
$genType normalize($genType x);
$genHType normalize($genHType x);
// TODO: faceforward(N, I, Nref)
// TODO: reflect(I, N)
// TODO: refract(I, N, eta)
// 8.5 : Matrix Functions
// TODO: matrixCompMult(x, y)
// Not supported until GLSL 1.40. Poly-filled by SkSL:
float2x2 inverse(float2x2 m);
float3x3 inverse(float3x3 m);
float4x4 inverse(float4x4 m);
half2x2 inverse(half2x2 m);
half3x3 inverse(half3x3 m);
half4x4 inverse(half4x4 m);
// 8.6 : Vector Relational Functions
$bvec lessThan($vec x, $vec y);
$bvec lessThan($hvec x, $hvec y);
$bvec lessThanEqual($vec x, $vec y);
$bvec lessThanEqual($hvec x, $hvec y);
$bvec greaterThan($vec x, $vec y);
$bvec greaterThan($hvec x, $hvec y);
$bvec greaterThanEqual($vec x, $vec y);
$bvec greaterThanEqual($hvec x, $hvec y);
$bvec equal($vec x, $vec y);
$bvec equal($hvec x, $hvec y);
$bvec equal($bvec x, $bvec y);
$bvec notEqual($vec x, $vec y);
$bvec notEqual($hvec x, $hvec y);
$bvec notEqual($bvec x, $bvec y);
bool any($bvec x);
bool all($bvec x);
$bvec not($bvec x);
// Miscellaneous SkSL intrinsics that are not part of GLSL:
// The max() guards against division by zero when the incoming color is transparent black
half4 unpremul (half4 color) { return half4 (color.rgb / max(color.a, 0.0001), color.a); }
float4 unpremul_float(float4 color) { return float4(color.rgb / max(color.a, 0.0001), color.a); }

View File

@ -39,8 +39,11 @@ DEF_TEST(SkRuntimeEffectInvalid, r) {
test("in bool Flag; layout(when=Flag) uniform float Input;", "", "when");
test("layout(tracked) uniform float Input;", "", "tracked");
// Runtime SkSL supports a limited set of uniform types. No samplers, bool, or int, for example:
test("uniform sampler2D s;", "", "uniform");
// GLSL types like sampler2D and texture2D are not allowed anywhere:
test("uniform sampler2D s;", "", "no type named 'sampler2D'");
test("uniform texture2D s;", "", "no type named 'texture2D'");
// Runtime SkSL supports a limited set of uniform types. No bool, or int, for example:
test("uniform bool b;", "", "uniform");
test("uniform int i;", "", "uniform");
@ -75,6 +78,9 @@ DEF_TEST(SkRuntimeEffectInvalid, r) {
"half4 color = sample(p.x > 10 ? child1 : child2);",
"expression");
// sk_Caps is an internal system. It should not be visible to runtime effects
test("", "if (sk_Caps.integerSupport) { p = p.yx; }", "unknown identifier 'sk_Caps'");
// Errors that aren't caught until later in the compilation process (during optimize())
test("", "return half4(1);", "unreachable");
test("half badFunc() { }", "", "without returning");