Migrate Graphite shader code into sksl_graphite_frag.

This allows us to pre-parse and analyze the code once at startup,
instead of every time a shader is assembled.

In order to make changes to `sksl_graphite_frag.sksl`, please set
`skia_compile_modules = true` in your GN args. This will cause the
dehydrated code to be regenerated at build time. This should not slow
down normal builds; it only rebuilds when dirty.

Change-Id: I08f2005399ea3a12726946db1e3f2c39f9c24df8
Bug: skia:13110
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/532398
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
John Stiles 2022-04-21 15:18:39 -04:00 committed by SkCQ
parent d3ecfb3bb8
commit b6cd339d9c
3 changed files with 1261 additions and 133 deletions

View File

@ -285,32 +285,8 @@ static constexpr SkUniform kGradientUniforms[kNumGradientUniforms] = {
{ "padding", SkSLType::kFloat2 } // TODO: add automatic uniform padding
};
static const char *kLinearGradient4Name = "linear_grad_4_shader";
static const char *kLinearGradient4SkSL =
// TODO: This should use local coords
"half4 linear_grad_4_shader(float4 colorsParam[4],\n"
" float offsetsParam[4],\n"
" float2 point0Param,\n"
" float2 point1Param,\n"
" float radius0Param,\n"
" float radius1Param,\n"
" float2 padding) {\n"
" float2 pos = sk_FragCoord.xy;\n"
" float2 delta = point1Param - point0Param;\n"
" float2 pt = pos - point0Param;\n"
" float t = dot(pt, delta) / dot(delta, delta);\n"
" float4 result = colorsParam[0];\n"
" result = mix(result, colorsParam[1],\n"
" clamp((t-offsetsParam[0])/(offsetsParam[1]-offsetsParam[0]),\n"
" 0, 1));\n"
" result = mix(result, colorsParam[2],\n"
" clamp((t-offsetsParam[1])/(offsetsParam[2]-offsetsParam[1]),\n"
" 0, 1));\n"
" result = mix(result, colorsParam[3],\n"
" clamp((t-offsetsParam[2])/(offsetsParam[3]-offsetsParam[2]),\n"
" 0, 1));\n"
" return half4(result);\n"
"}\n";
static constexpr char kLinearGradient4Name[] = "sk_linear_grad_4_shader";
static constexpr char kLinearGradient4SkSL[] = "";
//--------------------------------------------------------------------------------------------------
static constexpr int kNumSolidShaderUniforms = 1;
@ -318,11 +294,8 @@ static constexpr SkUniform kSolidShaderUniforms[kNumSolidShaderUniforms] = {
{ "color", SkSLType::kFloat4 }
};
static const char* kSolidShaderName = "solid_shader";
static const char* kSolidShaderSkSL =
"half4 solid_shader(float4 colorParam) {\n"
" return half4(colorParam);\n"
"}\n";
static constexpr char kSolidShaderName[] = "sk_solid_shader";
static constexpr char kSolidShaderSkSL[] = "";
//--------------------------------------------------------------------------------------------------
static constexpr int kNumImageShaderUniforms = 5;
@ -344,33 +317,8 @@ static_assert(1 == static_cast<int>(SkTileMode::kRepeat), "ImageShader code depe
static_assert(2 == static_cast<int>(SkTileMode::kMirror), "ImageShader code depends on SkTileMode");
static_assert(3 == static_cast<int>(SkTileMode::kDecal), "ImageShader code depends on SkTileMode");
static const char* kImageShaderName = "compute_coords";
static const char* kImageShaderSkSL =
"const int kClamp = 0;\n"
"const int kRepeat = 1;\n"
"const int kMirrorRepeat = 2;\n"
"const int kClampToBorder = 3;\n"
"\n"
"float tile(int tm, float f, float origin, float length) {\n"
" if (tm == kClamp) {\n"
" return clamp(f, origin, origin+length) / length;"
" } else if (tm == kRepeat) {\n"
" return mod(f - origin, length) / length;\n"
" } else if (tm == kMirrorRepeat) {\n"
" // for now, just repeat\n"
" return mod(f - origin, length) / length;\n"
" } else { // kClampToBorder\n"
" // For now, just clamp\n"
" return clamp(f, origin, origin+length) / length;"
" }\n"
"}\n"
"\n"
"float2 compute_coords(float4 subset, int tmX, int tmY) {\n"
" float2 subsetWH = (subset.zw - subset.xy);\n"
" float2 coords = float2(tile(tmX, sk_FragCoord.x, subset.x, subsetWH.x),\n"
" tile(tmY, sk_FragCoord.y, subset.y, subsetWH.y));\n"
" return coords;\n"
"}\n";
static constexpr char kImageShaderName[] = "sk_compute_coords";
static constexpr char kImageShaderSkSL[] = "";
static constexpr int kNumImageShaderFields = 1;
static constexpr DataPayloadField kImageShaderFields[kNumImageShaderFields] = {
@ -426,74 +374,8 @@ static constexpr SkUniform kBlendShaderUniforms[kNumBlendShaderUniforms] = {
static constexpr int kNumBlendShaderChildren = 2;
// Note: we're counting on the compiler to inline this code and trim it down to just the used
// branch(es) in the blend-mode case. In the blend-shader case it should remain un-inlined.
static const char* kBlendHelperName = "blend";
static const char* kBlendHelperSkSL =
"const int kClear = 0;\n"
"const int kSrc = 1;\n"
"const int kDst = 2;\n"
"const int kSrcOver = 3;\n"
"const int kDstOver = 4;\n"
"const int kSrcIn = 5;\n"
"const int kDstIn = 6;\n"
"const int kSrcOut = 7;\n"
"const int kDstOut = 8;\n"
"const int kSrcATop = 9;\n"
"const int kDstATop = 10;\n"
"const int kXor = 11;\n"
"const int kPlus = 12;\n"
"const int kModulate = 13;\n"
"const int kScreen = 14;\n"
"const int kOverlay = 15;\n"
"const int kDarken = 16;\n"
"const int kLighten = 17;\n"
"const int kColorDodge = 18;\n"
"const int kColorBurn = 19;\n"
"const int kHardLight = 20;\n"
"const int kSoftLight = 21;\n"
"const int kDifference = 22;\n"
"const int kExclusion = 23;\n"
"const int kMultiply = 24;\n"
"const int kHue = 25;\n"
"const int kSaturation = 26;\n"
"const int kColor = 27;\n"
"const int kLuminosity = 28;\n"
"\n"
"half4 blend(int mode, half4 src, half4 dst) {\n"
" switch (mode) {\n"
" case kClear: { return blend_clear(src, dst); }\n"
" case kSrc: { return blend_src(src, dst); }\n"
" case kDst: { return blend_dst(src, dst); }\n"
" case kSrcOver: { return blend_src_over(src, dst); }\n"
" case kDstOver: { return blend_dst_over(src, dst); }\n"
" case kSrcIn: { return blend_src_in(src, dst); }\n"
" case kDstIn: { return blend_dst_in(src, dst); }\n"
" case kSrcOut: { return blend_src_out(src, dst); }\n"
" case kDstOut: { return blend_dst_out(src, dst); }\n"
" case kSrcATop: { return blend_src_atop(src, dst); }\n"
" case kDstATop: { return blend_dst_atop(src, dst); }\n"
" case kXor: { return blend_xor(src, dst); }\n"
" case kPlus: { return blend_plus(src, dst); }\n"
" case kModulate: { return blend_modulate(src, dst); }\n"
" case kScreen: { return blend_screen(src, dst); }\n"
" case kOverlay: { return blend_overlay(src, dst); }\n"
" case kDarken: { return blend_darken(src, dst); }\n"
" case kLighten: { return blend_lighten(src, dst); }\n"
" case kColorDodge: { return blend_color_dodge(src, dst); }\n"
" case kColorBurn: { return blend_color_burn(src, dst); }\n"
" case kHardLight: { return blend_hard_light(src, dst); }\n"
" case kSoftLight: { return blend_soft_light(src, dst); }\n"
" case kDifference: { return blend_difference(src, dst); }\n"
" case kExclusion: { return blend_exclusion(src, dst); }\n"
" case kMultiply: { return blend_multiply(src, dst); }\n"
" case kHue: { return blend_hue(src, dst); }\n"
" case kSaturation: { return blend_saturation(src, dst); }\n"
" case kColor: { return blend_color(src, dst); }\n"
" case kLuminosity: { return blend_luminosity(src, dst); }\n"
" default: return half4(0); // Avoids 'blend can exit without returning a value' error\n"
" }\n"
"}\n";
static constexpr char kBlendHelperName[] = "sk_blend";
static constexpr char kBlendHelperSkSL[] = "";
std::string GenerateBlendShaderGlueCode(const std::string& resultName,
int entryIndex,
@ -520,11 +402,8 @@ std::string GenerateBlendShaderGlueCode(const std::string& resultName,
}
//--------------------------------------------------------------------------------------------------
static const char* kErrorName = "error";
static const char* kErrorSkSL =
"half4 error() {\n"
" return half4(1.0, 0.0, 1.0, 1.0);\n"
"}\n";
static constexpr char kErrorName[] = "sk_error";
static constexpr char kErrorSkSL[] = "";
//--------------------------------------------------------------------------------------------------
static constexpr int kNumFixedFunctionBlenderFields = 1;

File diff suppressed because it is too large Load Diff

View File

@ -1 +1,124 @@
// Graphite-specific fragment shader code
half4 sk_error() {
return half4(1.0, 0.0, 1.0, 1.0);
}
half4 sk_solid_shader(float4 colorParam) {
return half4(colorParam);
}
float $tile(int tm, float f, float origin, float length) {
const int kClamp = 0;
const int kRepeat = 1;
const int kMirrorRepeat = 2;
const int kClampToBorder = 3;
if (tm == kClamp) {
return clamp(f, origin, origin+length) / length;
} else if (tm == kRepeat) {
return mod(f - origin, length) / length;
} else if (tm == kMirrorRepeat) {
// For now, just repeat.
return mod(f - origin, length) / length;
} else { // kClampToBorder
// For now, just clamp.
return clamp(f, origin, origin+length) / length;
}
}
float2 sk_compute_coords(float4 subset, int tmX, int tmY) {
float2 subsetWH = (subset.zw - subset.xy);
return float2($tile(tmX, sk_FragCoord.x, subset.x, subsetWH.x),
$tile(tmY, sk_FragCoord.y, subset.y, subsetWH.y));
}
half4 sk_linear_grad_4_shader(float4 colorsParam[4],
float offsetsParam[4],
float2 point0Param,
float2 point1Param,
float radius0Param,
float radius1Param,
float2 padding) {
// TODO: This should use local coords
float2 pos = sk_FragCoord.xy;
float2 delta = point1Param - point0Param;
float2 pt = pos - point0Param;
float t = dot(pt, delta) / dot(delta, delta);
float4 result = colorsParam[0];
result = mix(result, colorsParam[1],
clamp((t-offsetsParam[0])/(offsetsParam[1]-offsetsParam[0]),
0, 1));
result = mix(result, colorsParam[2],
clamp((t-offsetsParam[1])/(offsetsParam[2]-offsetsParam[1]),
0, 1));
result = mix(result, colorsParam[3],
clamp((t-offsetsParam[2])/(offsetsParam[3]-offsetsParam[2]),
0, 1));
return half4(result);
}
half4 sk_blend(int mode, half4 src, half4 dst) {
const int kClear = 0;
const int kSrc = 1;
const int kDst = 2;
const int kSrcOver = 3;
const int kDstOver = 4;
const int kSrcIn = 5;
const int kDstIn = 6;
const int kSrcOut = 7;
const int kDstOut = 8;
const int kSrcATop = 9;
const int kDstATop = 10;
const int kXor = 11;
const int kPlus = 12;
const int kModulate = 13;
const int kScreen = 14;
const int kOverlay = 15;
const int kDarken = 16;
const int kLighten = 17;
const int kColorDodge = 18;
const int kColorBurn = 19;
const int kHardLight = 20;
const int kSoftLight = 21;
const int kDifference = 22;
const int kExclusion = 23;
const int kMultiply = 24;
const int kHue = 25;
const int kSaturation = 26;
const int kColor = 27;
const int kLuminosity = 28;
switch (mode) {
case kClear: { return blend_clear(src, dst); }
case kSrc: { return blend_src(src, dst); }
case kDst: { return blend_dst(src, dst); }
case kSrcOver: { return blend_porter_duff(src, dst, half4(1, 0, 0, -1)); }
case kDstOver: { return blend_porter_duff(src, dst, half4(0, 1, -1, 0)); }
case kSrcIn: { return blend_porter_duff(src, dst, half4(0, 0, 1, 0)); }
case kDstIn: { return blend_porter_duff(src, dst, half4(0, 0, 0, 1)); }
case kSrcOut: { return blend_porter_duff(src, dst, half4(0, 0, -1, 0)); }
case kDstOut: { return blend_porter_duff(src, dst, half4(0, 0, 0, -1)); }
case kSrcATop: { return blend_porter_duff(src, dst, half4(0, 0, 1, -1)); }
case kDstATop: { return blend_porter_duff(src, dst, half4(0, 0, -1, 1)); }
case kXor: { return blend_porter_duff(src, dst, half4(0, 0, -1, -1)); }
case kPlus: { return blend_porter_duff(src, dst, half4(1, 1, 0, 0)); }
case kModulate: { return blend_modulate(src, dst); }
case kScreen: { return blend_screen(src, dst); }
case kOverlay: { return blend_overlay(src, dst, /*flip=*/false); }
case kDarken: { return blend_darken(src, dst, /*mode=*/1); }
case kLighten: { return blend_darken(src, dst, /*mode=*/-1); }
case kColorDodge: { return blend_color_dodge(src, dst); }
case kColorBurn: { return blend_color_burn(src, dst); }
case kHardLight: { return blend_overlay(src, dst, /*flip=*/true); }
case kSoftLight: { return blend_soft_light(src, dst); }
case kDifference: { return blend_difference(src, dst); }
case kExclusion: { return blend_exclusion(src, dst); }
case kMultiply: { return blend_multiply(src, dst); }
case kHue: { return blend_hslc(src, dst, /*flip=*/false, /*saturate=*/true); }
case kSaturation: { return blend_hslc(src, dst, /*flip=*/true, /*saturate=*/true); }
case kColor: { return blend_hslc(src, dst, /*flip=*/false, /*saturate=*/false); }
case kLuminosity: { return blend_hslc(src, dst, /*flip=*/true, /*saturate=*/false); }
default: return half4(0); // Avoids 'blend can exit without returning a value' error
}
}