Added support for the 'inline' hint on SkSL functions
Change-Id: Ib78e0ad9fd1cc15e7afeb2a9ddd6b1249828fbe7 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/311603 Commit-Queue: Ethan Nicholas <ethannicholas@google.com> Reviewed-by: John Stiles <johnstiles@google.com>
This commit is contained in:
parent
7f1117e886
commit
338e57d4b1
@ -63,6 +63,8 @@ Differences from GLSL
|
||||
* All texture functions are named "sample", e.g. sample(sampler2D, float3) is
|
||||
equivalent to GLSL's textureProj(sampler2D, float3).
|
||||
* Render target width and height are available via sk_Width and sk_Height
|
||||
* Functions support the 'inline' modifier, which causes the compiler to ignore
|
||||
its normal inlining heuristics and inline the function if at all possible
|
||||
* some built-in functions and one or two rarely-used language features are not
|
||||
yet supported (sorry!)
|
||||
|
||||
|
@ -874,6 +874,7 @@ void IRGenerator::checkModifiers(int offset, const Modifiers& modifiers, int per
|
||||
CHECK(Modifiers::kPLSIn_Flag, "__pixel_local_inEXT")
|
||||
CHECK(Modifiers::kPLSOut_Flag, "__pixel_local_outEXT")
|
||||
CHECK(Modifiers::kVarying_Flag, "varying")
|
||||
CHECK(Modifiers::kInline_Flag, "inline")
|
||||
SkASSERT(flags == 0);
|
||||
}
|
||||
|
||||
@ -900,7 +901,8 @@ void IRGenerator::convertFunction(const ASTNode& f) {
|
||||
return;
|
||||
}
|
||||
const ASTNode::FunctionData& fd = f.getFunctionData();
|
||||
this->checkModifiers(f.fOffset, fd.fModifiers, Modifiers::kHasSideEffects_Flag);
|
||||
this->checkModifiers(f.fOffset, fd.fModifiers, Modifiers::kHasSideEffects_Flag |
|
||||
Modifiers::kInline_Flag);
|
||||
std::vector<const Variable*> parameters;
|
||||
for (size_t i = 0; i < fd.fParameterCount; ++i) {
|
||||
const ASTNode& param = *(iter++);
|
||||
@ -2390,8 +2392,9 @@ bool IRGenerator::isSafeToInline(const FunctionDefinition& functionDef) {
|
||||
// Inlining has been explicitly disabled by the IR generator.
|
||||
return false;
|
||||
}
|
||||
if (functionDef.inlinedFunctionSize() >= fSettings->fInlineThreshold) {
|
||||
// The function exceeds our maximum inline size.
|
||||
if (!(functionDef.fDeclaration.fModifiers.fFlags & Modifiers::kInline_Flag) &&
|
||||
functionDef.inlinedFunctionSize() >= fSettings->fInlineThreshold) {
|
||||
// The function exceeds our maximum inline size and is not flagged 'inline'.
|
||||
return false;
|
||||
}
|
||||
if (!fSettings->fCaps || !fSettings->fCaps->canUseDoLoops()) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -48,6 +48,7 @@ struct Token {
|
||||
TK_VOLATILE,
|
||||
TK_RESTRICT,
|
||||
TK_BUFFER,
|
||||
TK_INLINE,
|
||||
TK_HASSIDEEFFECTS,
|
||||
TK_PLS,
|
||||
TK_PLSIN,
|
||||
|
@ -936,7 +936,7 @@ Layout Parser::layout() {
|
||||
|
||||
/* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE |
|
||||
READONLY | WRITEONLY | COHERENT | VOLATILE | RESTRICT | BUFFER | PLS | PLSIN |
|
||||
PLSOUT | VARYING)* */
|
||||
PLSOUT | VARYING | INLINE)* */
|
||||
Modifiers Parser::modifiers() {
|
||||
Layout layout = this->layout();
|
||||
int flags = 0;
|
||||
@ -1016,6 +1016,10 @@ Modifiers Parser::modifiers() {
|
||||
this->nextToken();
|
||||
flags |= Modifiers::kVarying_Flag;
|
||||
break;
|
||||
case Token::Kind::TK_INLINE:
|
||||
this->nextToken();
|
||||
flags |= Modifiers::kInline_Flag;
|
||||
break;
|
||||
default:
|
||||
return Modifiers(layout, flags);
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -35,6 +35,7 @@ struct Modifiers {
|
||||
kPLSIn_Flag = 1 << 14,
|
||||
kPLSOut_Flag = 1 << 15,
|
||||
kVarying_Flag = 1 << 16,
|
||||
kInline_Flag = 1 << 17,
|
||||
};
|
||||
|
||||
Modifiers()
|
||||
|
@ -178,6 +178,12 @@ void process(const char* inPath, const char* lexer, const char* token, const cha
|
||||
std::string line;
|
||||
std::ifstream in(inPath);
|
||||
while (std::getline(in, line)) {
|
||||
if (line.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
if (line.length() >= 2 && line[0] == '/' && line[1] == '/') {
|
||||
continue;
|
||||
}
|
||||
std::istringstream split(line);
|
||||
std::string name, delimiter, pattern;
|
||||
if (split >> name >> delimiter >> pattern) {
|
||||
|
@ -1,3 +1,14 @@
|
||||
// *****************
|
||||
// *** IMPORTANT ***
|
||||
// *****************
|
||||
//
|
||||
// 1. This file is only used when gn arg sksl_lex is set to true. It is used to regenerate the
|
||||
// SkSLLexer.h and SkSLLexer.cpp files.
|
||||
// 2. Since token IDs are used to identify operators and baked into the .dehydrated.sksl files,
|
||||
// after modifying this file it is likely everything will break until you update the dehydrated
|
||||
// binaries. If things break after updating the lexer, set REHYDRATE in SkSLCompiler.cpp to 0,
|
||||
// rebuild, and then set it back to 1.
|
||||
|
||||
FLOAT_LITERAL = [0-9]*\.[0-9]+([eE][+-]?[0-9]+)?|[0-9]+\.[0-9]*([eE][+-]?[0-9]+)?|[0-9]+([eE][+-]?[0-9]+)
|
||||
INT_LITERAL = [0-9]+|0x[0-9a-fA-F]+
|
||||
TRUE_LITERAL = "true"
|
||||
@ -30,6 +41,7 @@ COHERENT = "coherent"
|
||||
VOLATILE = "volatile"
|
||||
RESTRICT = "restrict"
|
||||
BUFFER = "buffer"
|
||||
INLINE = "inline"
|
||||
HASSIDEEFFECTS = "sk_has_side_effects"
|
||||
PLS = "__pixel_localEXT"
|
||||
PLSIN = "__pixel_local_inEXT"
|
||||
|
@ -126,6 +126,83 @@ DEF_TEST(SkSLFunctions, r) {
|
||||
"}\n");
|
||||
}
|
||||
|
||||
DEF_TEST(SkSLFunctionInlineThreshold, r) {
|
||||
test(r,
|
||||
"void tooBig(inout int x) {"
|
||||
" ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x;"
|
||||
" ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x;"
|
||||
"}"
|
||||
"void main() { int x = 0; tooBig(x); }",
|
||||
*SkSL::ShaderCapsFactory::Default(),
|
||||
"#version 400\n"
|
||||
"void tooBig(inout int x) {\n"
|
||||
" ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n"
|
||||
" ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n"
|
||||
" ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n"
|
||||
" ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n"
|
||||
" ++x;\n ++x;\n"
|
||||
"}\n"
|
||||
"void main() {\n"
|
||||
" int x = 0;\n"
|
||||
" tooBig(x);\n"
|
||||
"}\n"
|
||||
);
|
||||
test(r,
|
||||
"inline void tooBig(inout int x) {"
|
||||
" ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x;"
|
||||
" ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x;"
|
||||
"}"
|
||||
"void main() { int x = 0; tooBig(x); }",
|
||||
*SkSL::ShaderCapsFactory::Default(),
|
||||
"#version 400\n"
|
||||
"void main() {\n"
|
||||
" int x = 0;\n"
|
||||
" int _inlineArgvoidtooBigint0_0 = x;\n"
|
||||
" {\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" ++_inlineArgvoidtooBigint0_0;\n ++_inlineArgvoidtooBigint0_0;\n"
|
||||
" }\n"
|
||||
" x = _inlineArgvoidtooBigint0_0;\n"
|
||||
"\n"
|
||||
"}\n"
|
||||
);
|
||||
test(r,
|
||||
"inline void cantActuallyInline(inout int x) {"
|
||||
" for (;;) {"
|
||||
" ++x;"
|
||||
" if (x > 10) return;"
|
||||
" }"
|
||||
"}"
|
||||
"void main() { int x = 0; cantActuallyInline(x); }",
|
||||
*SkSL::ShaderCapsFactory::Default(),
|
||||
"#version 400\n"
|
||||
"void cantActuallyInline(inout int x) {\n"
|
||||
" for (; ; ) {\n"
|
||||
" ++x;\n"
|
||||
" if (x > 10) return;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"void main() {\n"
|
||||
" int x = 0;\n"
|
||||
" cantActuallyInline(x);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
DEF_TEST(SkSLOperators, r) {
|
||||
test(r,
|
||||
"void main() {"
|
||||
|
Loading…
Reference in New Issue
Block a user