From dfbfc738a9edfff7a9804253175e380c230f3d21 Mon Sep 17 00:00:00 2001 From: Ethan Nicholas Date: Mon, 18 Jun 2018 14:14:13 -0400 Subject: added GrSkSLFP and converted DitherEffect to use it Bug: skia: Change-Id: I84b71165eab1712355f3c7669cee2d33d259f3df Reviewed-on: https://skia-review.googlesource.com/124504 Commit-Queue: Ethan Nicholas Reviewed-by: Brian Salomon --- src/sksl/SkSLCodeGenerator.h | 4 +- src/sksl/SkSLCompiler.cpp | 113 ++++++++--- src/sksl/SkSLCompiler.h | 29 ++- src/sksl/SkSLContext.h | 4 + src/sksl/SkSLGLSLCodeGenerator.cpp | 61 +++--- src/sksl/SkSLIRGenerator.cpp | 46 +++-- src/sksl/SkSLIRGenerator.h | 7 +- src/sksl/SkSLJIT.cpp | 291 +++++++++++++++++++++++----- src/sksl/SkSLJIT.h | 16 +- src/sksl/SkSLMain.cpp | 4 +- src/sksl/SkSLPipelineStageCodeGenerator.cpp | 167 ++++++++++++++++ src/sksl/SkSLPipelineStageCodeGenerator.h | 65 +++++++ src/sksl/SkSLSPIRVCodeGenerator.cpp | 4 +- src/sksl/SkSLString.cpp | 16 +- src/sksl/ir/SkSLAppendStage.h | 21 +- src/sksl/ir/SkSLBinaryExpression.h | 5 + src/sksl/ir/SkSLBlock.h | 8 + src/sksl/ir/SkSLBoolLiteral.h | 9 + src/sksl/ir/SkSLBreakStatement.h | 4 + src/sksl/ir/SkSLConstructor.h | 11 +- src/sksl/ir/SkSLContinueStatement.h | 4 + src/sksl/ir/SkSLDiscardStatement.h | 4 + src/sksl/ir/SkSLDoStatement.h | 5 + src/sksl/ir/SkSLEnum.h | 4 + src/sksl/ir/SkSLExpression.h | 2 + src/sksl/ir/SkSLExpressionStatement.h | 4 + src/sksl/ir/SkSLExtension.h | 4 + src/sksl/ir/SkSLFieldAccess.h | 5 + src/sksl/ir/SkSLFloatLiteral.h | 13 +- src/sksl/ir/SkSLForStatement.h | 6 + src/sksl/ir/SkSLFunctionCall.h | 9 + src/sksl/ir/SkSLFunctionDefinition.h | 5 + src/sksl/ir/SkSLFunctionReference.h | 11 +- src/sksl/ir/SkSLIfStatement.h | 5 + src/sksl/ir/SkSLIndexExpression.h | 12 ++ src/sksl/ir/SkSLIntLiteral.h | 12 +- src/sksl/ir/SkSLInterfaceBlock.h | 11 ++ src/sksl/ir/SkSLLayout.h | 3 + src/sksl/ir/SkSLModifiersDeclaration.h | 6 +- src/sksl/ir/SkSLNop.h | 4 + src/sksl/ir/SkSLPostfixExpression.h | 4 + src/sksl/ir/SkSLPrefixExpression.h | 4 + src/sksl/ir/SkSLProgram.h | 9 +- src/sksl/ir/SkSLProgramElement.h | 2 + src/sksl/ir/SkSLReturnStatement.h | 7 + src/sksl/ir/SkSLSection.h | 4 + src/sksl/ir/SkSLSetting.cpp | 10 +- src/sksl/ir/SkSLSetting.h | 4 + src/sksl/ir/SkSLStatement.h | 2 + src/sksl/ir/SkSLSwitchCase.h | 10 + src/sksl/ir/SkSLSwitchStatement.h | 9 + src/sksl/ir/SkSLSwizzle.h | 14 ++ src/sksl/ir/SkSLTernaryExpression.h | 6 + src/sksl/ir/SkSLTypeReference.h | 13 +- src/sksl/ir/SkSLVarDeclarations.h | 25 ++- src/sksl/ir/SkSLVarDeclarationsStatement.h | 7 +- src/sksl/ir/SkSLVariableReference.cpp | 5 + src/sksl/ir/SkSLVariableReference.h | 4 + src/sksl/ir/SkSLWhileStatement.h | 5 + src/sksl/sksl_cpu.inc | 12 -- src/sksl/sksl_pipeline.inc | 19 ++ 61 files changed, 1017 insertions(+), 172 deletions(-) create mode 100644 src/sksl/SkSLPipelineStageCodeGenerator.cpp create mode 100644 src/sksl/SkSLPipelineStageCodeGenerator.h delete mode 100644 src/sksl/sksl_cpu.inc create mode 100644 src/sksl/sksl_pipeline.inc (limited to 'src/sksl') diff --git a/src/sksl/SkSLCodeGenerator.h b/src/sksl/SkSLCodeGenerator.h index 1f577b58b1..737b5dd6aa 100644 --- a/src/sksl/SkSLCodeGenerator.h +++ b/src/sksl/SkSLCodeGenerator.h @@ -22,7 +22,9 @@ public: CodeGenerator(const Program* program, ErrorReporter* errors, OutputStream* out) : fProgram(*program) , fErrors(*errors) - , fOut(out) {} + , fOut(out) { + SkASSERT(program->fIsOptimized); + } virtual ~CodeGenerator() {} diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp index 0cf55c26d0..b1006e8dd5 100644 --- a/src/sksl/SkSLCompiler.cpp +++ b/src/sksl/SkSLCompiler.cpp @@ -13,6 +13,7 @@ #include "SkSLHCodeGenerator.h" #include "SkSLIRGenerator.h" #include "SkSLMetalCodeGenerator.h" +#include "SkSLPipelineStageCodeGenerator.h" #include "SkSLSPIRVCodeGenerator.h" #include "ir/SkSLEnum.h" #include "ir/SkSLExpression.h" @@ -55,8 +56,8 @@ static const char* SKSL_FP_INCLUDE = #include "sksl_fp.inc" ; -static const char* SKSL_CPU_INCLUDE = -#include "sksl_cpu.inc" +static const char* SKSL_PIPELINE_STAGE_INCLUDE = +#include "sksl_pipeline.inc" ; namespace SkSL { @@ -221,21 +222,18 @@ Compiler::Compiler(Flags flags) strlen(SKSL_VERT_INCLUDE), *fTypes, &fVertexInclude); fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); fVertexSymbolTable = fIRGenerator->fSymbolTable; - fIRGenerator->finish(); fIRGenerator->start(&settings, nullptr); fIRGenerator->convertProgram(Program::kVertex_Kind, SKSL_FRAG_INCLUDE, strlen(SKSL_FRAG_INCLUDE), *fTypes, &fFragmentInclude); fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); fFragmentSymbolTable = fIRGenerator->fSymbolTable; - fIRGenerator->finish(); fIRGenerator->start(&settings, nullptr); fIRGenerator->convertProgram(Program::kGeometry_Kind, SKSL_GEOM_INCLUDE, strlen(SKSL_GEOM_INCLUDE), *fTypes, &fGeometryInclude); fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); fGeometrySymbolTable = fIRGenerator->fSymbolTable; - fIRGenerator->finish(); } Compiler::~Compiler() { @@ -1233,11 +1231,11 @@ std::unique_ptr Compiler::convertProgram(Program::Kind kind, String tex &elements); fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); break; - case Program::kCPU_Kind: + case Program::kPipelineStage_Kind: inherited = nullptr; fIRGenerator->start(&settings, nullptr); - fIRGenerator->convertProgram(kind, SKSL_CPU_INCLUDE, strlen(SKSL_CPU_INCLUDE), - *fTypes, &elements); + fIRGenerator->convertProgram(kind, SKSL_PIPELINE_STAGE_INCLUDE, + strlen(SKSL_PIPELINE_STAGE_INCLUDE), *fTypes, &elements); fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); break; } @@ -1249,13 +1247,6 @@ std::unique_ptr Compiler::convertProgram(Program::Kind kind, String tex std::unique_ptr textPtr(new String(std::move(text))); fSource = textPtr.get(); fIRGenerator->convertProgram(kind, textPtr->c_str(), textPtr->size(), *fTypes, &elements); - if (!fErrorCount) { - for (auto& element : elements) { - if (element->fKind == ProgramElement::kFunction_Kind) { - this->scanCFG((FunctionDefinition&) *element); - } - } - } auto result = std::unique_ptr(new Program(kind, std::move(textPtr), settings, @@ -1264,16 +1255,55 @@ std::unique_ptr Compiler::convertProgram(Program::Kind kind, String tex std::move(elements), fIRGenerator->fSymbolTable, fIRGenerator->fInputs)); - fIRGenerator->finish(); - fSource = nullptr; - this->writeErrorCount(); if (fErrorCount) { return nullptr; } return result; } -bool Compiler::toSPIRV(const Program& program, OutputStream& out) { +bool Compiler::optimize(Program& program) { + SkASSERT(!fErrorCount); + if (!program.fIsOptimized) { + program.fIsOptimized = true; + fIRGenerator->fKind = program.fKind; + fIRGenerator->fSettings = &program.fSettings; + for (auto& element : program) { + if (element.fKind == ProgramElement::kFunction_Kind) { + this->scanCFG((FunctionDefinition&) element); + } + } + fSource = nullptr; + } + return fErrorCount == 0; +} + +std::unique_ptr Compiler::specialize( + Program& program, + const std::unordered_map& inputs) { + std::vector> elements; + for (const auto& e : program) { + elements.push_back(e.clone()); + } + Program::Settings settings; + settings.fCaps = program.fSettings.fCaps; + for (auto iter = inputs.begin(); iter != inputs.end(); ++iter) { + settings.fArgs.insert(*iter); + } + std::unique_ptr result(new Program(program.fKind, + nullptr, + settings, + program.fContext, + program.fInheritedElements, + std::move(elements), + program.fSymbols, + program.fInputs)); + return result; +} + +bool Compiler::toSPIRV(Program& program, OutputStream& out) { + if (!this->optimize(program)) { + return false; + } #ifdef SK_ENABLE_SPIRV_VALIDATION StringStream buffer; fSource = program.fSource.get(); @@ -1299,11 +1329,10 @@ bool Compiler::toSPIRV(const Program& program, OutputStream& out) { bool result = cg.generateCode(); fSource = nullptr; #endif - this->writeErrorCount(); return result; } -bool Compiler::toSPIRV(const Program& program, String* out) { +bool Compiler::toSPIRV(Program& program, String* out) { StringStream buffer; bool result = this->toSPIRV(program, buffer); if (result) { @@ -1312,16 +1341,18 @@ bool Compiler::toSPIRV(const Program& program, String* out) { return result; } -bool Compiler::toGLSL(const Program& program, OutputStream& out) { +bool Compiler::toGLSL(Program& program, OutputStream& out) { + if (!this->optimize(program)) { + return false; + } fSource = program.fSource.get(); GLSLCodeGenerator cg(fContext.get(), &program, this, &out); bool result = cg.generateCode(); fSource = nullptr; - this->writeErrorCount(); return result; } -bool Compiler::toGLSL(const Program& program, String* out) { +bool Compiler::toGLSL(Program& program, String* out) { StringStream buffer; bool result = this->toGLSL(program, buffer); if (result) { @@ -1330,28 +1361,48 @@ bool Compiler::toGLSL(const Program& program, String* out) { return result; } -bool Compiler::toMetal(const Program& program, OutputStream& out) { +bool Compiler::toMetal(Program& program, OutputStream& out) { + if (!this->optimize(program)) { + return false; + } MetalCodeGenerator cg(fContext.get(), &program, this, &out); bool result = cg.generateCode(); - this->writeErrorCount(); return result; } -bool Compiler::toCPP(const Program& program, String name, OutputStream& out) { +bool Compiler::toCPP(Program& program, String name, OutputStream& out) { + if (!this->optimize(program)) { + return false; + } fSource = program.fSource.get(); CPPCodeGenerator cg(fContext.get(), &program, this, name, &out); bool result = cg.generateCode(); fSource = nullptr; - this->writeErrorCount(); return result; } -bool Compiler::toH(const Program& program, String name, OutputStream& out) { +bool Compiler::toH(Program& program, String name, OutputStream& out) { + if (!this->optimize(program)) { + return false; + } fSource = program.fSource.get(); HCodeGenerator cg(fContext.get(), &program, this, name, &out); bool result = cg.generateCode(); fSource = nullptr; - this->writeErrorCount(); + return result; +} + +bool Compiler::toPipelineStage(const Program& program, String* out, + std::vector* outFormatArgs) { + SkASSERT(program.fIsOptimized); + fSource = program.fSource.get(); + StringStream buffer; + PipelineStageCodeGenerator cg(fContext.get(), &program, this, &buffer, outFormatArgs); + bool result = cg.generateCode(); + fSource = nullptr; + if (result) { + *out = buffer.str(); + } return result; } @@ -1446,6 +1497,8 @@ void Compiler::error(int offset, String msg) { } String Compiler::errorText() { + this->writeErrorCount(); + fErrorCount = 0; String result = fErrorText; return result; } diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h index 2c8c78687a..b054eed4d5 100644 --- a/src/sksl/SkSLCompiler.h +++ b/src/sksl/SkSLCompiler.h @@ -26,6 +26,8 @@ #define SK_TEXTURESAMPLERS_BUILTIN 10006 #define SK_OUT_BUILTIN 10007 #define SK_LASTFRAGCOLOR_BUILTIN 10008 +#define SK_MAIN_X_BUILTIN 10009 +#define SK_MAIN_Y_BUILTIN 10010 #define SK_FRAGCOORD_BUILTIN 15 #define SK_VERTEXID_BUILTIN 42 #define SK_INSTANCEID_BUILTIN 43 @@ -58,6 +60,11 @@ public: kPermitInvalidStaticTests_Flag = 1, }; + enum class FormatArg { + kInput, + kOutput + }; + Compiler(Flags flags = kNone_Flags); ~Compiler() override; @@ -65,19 +72,27 @@ public: std::unique_ptr convertProgram(Program::Kind kind, String text, const Program::Settings& settings); - bool toSPIRV(const Program& program, OutputStream& out); + bool optimize(Program& program); + + std::unique_ptr specialize(Program& program, + const std::unordered_map& inputs); + + bool toSPIRV(Program& program, OutputStream& out); + + bool toSPIRV(Program& program, String* out); - bool toSPIRV(const Program& program, String* out); + bool toGLSL(Program& program, OutputStream& out); - bool toGLSL(const Program& program, OutputStream& out); + bool toGLSL(Program& program, String* out); - bool toGLSL(const Program& program, String* out); + bool toMetal(Program& program, OutputStream& out); - bool toMetal(const Program& program, OutputStream& out); + bool toCPP(Program& program, String name, OutputStream& out); - bool toCPP(const Program& program, String name, OutputStream& out); + bool toH(Program& program, String name, OutputStream& out); - bool toH(const Program& program, String name, OutputStream& out); + bool toPipelineStage(const Program& program, String* out, + std::vector* outFormatArgs); void error(int offset, String msg) override; diff --git a/src/sksl/SkSLContext.h b/src/sksl/SkSLContext.h index 61dd8042e4..e42890eeda 100644 --- a/src/sksl/SkSLContext.h +++ b/src/sksl/SkSLContext.h @@ -355,6 +355,10 @@ private: return ""; } + std::unique_ptr clone() const override { + return std::unique_ptr(new Defined(fType)); + } + typedef Expression INHERITED; }; }; diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp index aa4f8252d0..82178d948d 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.cpp +++ b/src/sksl/SkSLGLSLCodeGenerator.cpp @@ -871,41 +871,44 @@ void GLSLCodeGenerator::writeSetting(const Setting& s) { } void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { - this->writeTypePrecision(f.fDeclaration.fReturnType); - this->writeType(f.fDeclaration.fReturnType); - this->write(" " + f.fDeclaration.fName + "("); - const char* separator = ""; - for (const auto& param : f.fDeclaration.fParameters) { - this->write(separator); - separator = ", "; - this->writeModifiers(param->fModifiers, false); - std::vector sizes; - const Type* type = ¶m->fType; - while (type->kind() == Type::kArray_Kind) { - sizes.push_back(type->columns()); - type = &type->componentType(); - } - this->writeTypePrecision(*type); - this->writeType(*type); - this->write(" " + param->fName); - for (int s : sizes) { - if (s <= 0) { - this->write("[]"); - } else { - this->write("[" + to_string(s) + "]"); + if (fProgramKind != Program::kPipelineStage_Kind) { + this->writeTypePrecision(f.fDeclaration.fReturnType); + this->writeType(f.fDeclaration.fReturnType); + this->write(" " + f.fDeclaration.fName + "("); + const char* separator = ""; + for (const auto& param : f.fDeclaration.fParameters) { + this->write(separator); + separator = ", "; + this->writeModifiers(param->fModifiers, false); + std::vector sizes; + const Type* type = ¶m->fType; + while (type->kind() == Type::kArray_Kind) { + sizes.push_back(type->columns()); + type = &type->componentType(); + } + this->writeTypePrecision(*type); + this->writeType(*type); + this->write(" " + param->fName); + for (int s : sizes) { + if (s <= 0) { + this->write("[]"); + } else { + this->write("[" + to_string(s) + "]"); + } } } + this->writeLine(") {"); + fIndentation++; } - this->writeLine(") {"); - fFunctionHeader = ""; OutputStream* oldOut = fOut; StringStream buffer; fOut = &buffer; - fIndentation++; this->writeStatements(((Block&) *f.fBody).fStatements); - fIndentation--; - this->writeLine("}"); + if (fProgramKind != Program::kPipelineStage_Kind) { + fIndentation--; + this->writeLine("}"); + } fOut = oldOut; this->write(fFunctionHeader); @@ -1331,7 +1334,9 @@ bool GLSLCodeGenerator::generateCode() { OutputStream* rawOut = fOut; fOut = &fHeader; fProgramKind = fProgram.fKind; - this->writeHeader(); + if (fProgramKind != Program::kPipelineStage_Kind) { + this->writeHeader(); + } if (Program::kGeometry_Kind == fProgramKind && fProgram.fSettings.fCaps->geometryShaderExtensionString()) { fHeader.writeText("#extension "); diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index 5a54b07333..144708bbae 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -144,10 +144,16 @@ static void fill_caps(const SKSL_CAPS_CLASS& caps, void IRGenerator::start(const Program::Settings* settings, std::vector>* inherited) { + if (fStarted) { + this->popSymbolTable(); + } fSettings = settings; fCapsMap.clear(); if (settings->fCaps) { fill_caps(*settings->fCaps, &fCapsMap); + } else { + fCapsMap.insert(std::make_pair(String("integerSupport"), + Program::Settings::Value(true))); } this->pushSymbolTable(); fInvocations = -1; @@ -168,11 +174,6 @@ void IRGenerator::start(const Program::Settings* settings, } } -void IRGenerator::finish() { - this->popSymbolTable(); - fSettings = nullptr; -} - std::unique_ptr IRGenerator::convertExtension(const ASTExtension& extension) { return std::unique_ptr(new Extension(extension.fOffset, extension.fName)); } @@ -682,6 +683,26 @@ void IRGenerator::convertFunction(const ASTFunction& f) { parameters.push_back(var); } + if (f.fName == "main") { + if (fKind == Program::kPipelineStage_Kind) { + bool valid = parameters.size() == 3 && + parameters[0]->fType == *fContext.fInt_Type && + parameters[0]->fModifiers.fFlags == 0 && + parameters[1]->fType == *fContext.fInt_Type && + parameters[1]->fModifiers.fFlags == 0 && + parameters[2]->fType == *fContext.fHalf4_Type && + parameters[2]->fModifiers.fFlags == (Modifiers::kIn_Flag | + Modifiers::kOut_Flag); + if (!valid) { + fErrors.error(f.fOffset, "pipeline stage 'main' must be declared main(int, " + "int, inout half4)"); + return; + } + } else if (parameters.size()) { + fErrors.error(f.fOffset, "shader 'main' must have zero parameters"); + } + } + // find existing declaration const FunctionDeclaration* decl = nullptr; auto entry = (*fSymbolTable)[f.fName]; @@ -752,6 +773,11 @@ void IRGenerator::convertFunction(const ASTFunction& f) { decl->fDefined = true; std::shared_ptr old = fSymbolTable; AutoSymbolTable table(this); + if (f.fName == "main" && fKind == Program::kPipelineStage_Kind) { + parameters[0]->fModifiers.fLayout.fBuiltin = SK_MAIN_X_BUILTIN; + parameters[1]->fModifiers.fLayout.fBuiltin = SK_MAIN_Y_BUILTIN; + parameters[2]->fModifiers.fLayout.fBuiltin = SK_OUTCOLOR_BUILTIN; + } for (size_t i = 0; i < parameters.size(); i++) { fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]); } @@ -1644,17 +1670,15 @@ std::unique_ptr IRGenerator::convertNumberConstructor( } if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kFloatLiteral_Kind) { double value = ((FloatLiteral&) *args[0]).fValue; - return std::unique_ptr(new FloatLiteral(fContext, offset, value, &type)); + return std::unique_ptr(new FloatLiteral(offset, value, &type)); } if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kIntLiteral_Kind) { int64_t value = ((IntLiteral&) *args[0]).fValue; - return std::unique_ptr(new FloatLiteral(fContext, offset, (double) value, - &type)); + return std::unique_ptr(new FloatLiteral(offset, (double) value, &type)); } if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type || type == *fContext.fUInt_Type)) { - return std::unique_ptr(new IntLiteral(fContext, - offset, + return std::unique_ptr(new IntLiteral(offset, ((IntLiteral&) *args[0]).fValue, &type)); } @@ -1952,7 +1976,7 @@ std::unique_ptr IRGenerator::getCap(int offset, String name) { found->second.literal(fContext, offset))); } -std::unique_ptr IRGenerator::getArg(int offset, String name) { +std::unique_ptr IRGenerator::getArg(int offset, String name) const { auto found = fSettings->fArgs.find(name); if (found == fSettings->fArgs.end()) { fErrors.error(offset, "unknown argument '" + name + "'"); diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h index 2a52e04b54..f456915877 100644 --- a/src/sksl/SkSLIRGenerator.h +++ b/src/sksl/SkSLIRGenerator.h @@ -77,9 +77,13 @@ public: std::unique_ptr constantFold(const Expression& left, Token::Kind op, const Expression& right) const; + + std::unique_ptr getArg(int offset, String name) const; + Program::Inputs fInputs; const Program::Settings* fSettings; const Context& fContext; + Program::Kind fKind; private: /** @@ -148,7 +152,6 @@ private: std::unique_ptr convertReturn(const ASTReturnStatement& r); std::unique_ptr
convertSection(const ASTSection& e); std::unique_ptr getCap(int offset, String name); - std::unique_ptr getArg(int offset, String name); std::unique_ptr convertSuffixExpression(const ASTSuffixExpression& expression); std::unique_ptr convertTypeField(int offset, const Type& type, StringFragment field); @@ -169,7 +172,6 @@ private: void setRefKind(const Expression& expr, VariableReference::RefKind kind); void getConstantInt(const Expression& value, int64_t* out); - Program::Kind fKind; const FunctionDeclaration* fCurrentFunction; std::unordered_map fCapsMap; std::shared_ptr fRootSymbolTable; @@ -187,6 +189,7 @@ private: Variable* fRTAdjust; Variable* fRTAdjustInterfaceBlock; int fRTAdjustFieldIndex; + bool fStarted = false; friend class AutoSymbolTable; friend class AutoLoopLevel; diff --git a/src/sksl/SkSLJIT.cpp b/src/sksl/SkSLJIT.cpp index 57286b53fb..b5d21d23c2 100644 --- a/src/sksl/SkSLJIT.cpp +++ b/src/sksl/SkSLJIT.cpp @@ -14,11 +14,13 @@ #include "SkCpu.h" #include "SkRasterPipeline.h" #include "../jumper/SkJumper.h" +#include "ir/SkSLAppendStage.h" #include "ir/SkSLExpressionStatement.h" #include "ir/SkSLFunctionCall.h" #include "ir/SkSLFunctionReference.h" #include "ir/SkSLIndexExpression.h" #include "ir/SkSLProgram.h" +#include "ir/SkSLUnresolvedFunction.h" #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" static constexpr int MAX_VECTOR_COUNT = 16; @@ -37,6 +39,27 @@ extern "C" void sksl_debug_print(float f) { printf("Debug: %f\n", f); } +extern "C" float sksl_clamp1(float f, float min, float max) { + return SkTPin(f, min, max); +} + +using float2 = __attribute__((vector_size(8))) float; +using float3 = __attribute__((vector_size(16))) float; +using float4 = __attribute__((vector_size(16))) float; + +extern "C" float2 sksl_clamp2(float2 f, float min, float max) { + return float2 { SkTPin(f[0], min, max), SkTPin(f[1], min, max) }; +} + +extern "C" float3 sksl_clamp3(float3 f, float min, float max) { + return float3 { SkTPin(f[0], min, max), SkTPin(f[1], min, max), SkTPin(f[2], min, max) }; +} + +extern "C" float4 sksl_clamp4(float4 f, float min, float max) { + return float4 { SkTPin(f[0], min, max), SkTPin(f[1], min, max), SkTPin(f[2], min, max), + SkTPin(f[3], min, max) }; +} + namespace SkSL { static constexpr int STAGE_PARAM_COUNT = 12; @@ -78,6 +101,10 @@ JIT::JIT(Compiler* compiler) fContext = LLVMContextCreate(); fVoidType = LLVMVoidTypeInContext(fContext); fInt1Type = LLVMInt1TypeInContext(fContext); + fInt1VectorType = LLVMVectorType(fInt1Type, fVectorCount); + fInt1Vector2Type = LLVMVectorType(fInt1Type, 2); + fInt1Vector3Type = LLVMVectorType(fInt1Type, 3); + fInt1Vector4Type = LLVMVectorType(fInt1Type, 4); fInt8Type = LLVMInt8TypeInContext(fContext); fInt8PtrType = LLVMPointerType(fInt8Type, 0); fInt32Type = LLVMInt32TypeInContext(fContext); @@ -101,6 +128,7 @@ JIT::~JIT() { void JIT::addBuiltinFunction(const char* ourName, const char* realName, LLVMTypeRef returnType, std::vector parameters) { + bool found = false; for (const auto& pair : *fProgram->fSymbols) { if (Symbol::kFunctionDeclaration_Kind == pair.second->fKind) { const FunctionDeclaration& f = (const FunctionDeclaration&) *pair.second; @@ -117,9 +145,31 @@ void JIT::addBuiltinFunction(const char* ourName, const char* realName, LLVMType parameters.data(), parameters.size(), false)); + found = true; + } + if (Symbol::kUnresolvedFunction_Kind == pair.second->fKind) { + // FIXME consolidate this with the code above + for (const auto& f : ((const UnresolvedFunction&) *pair.second).fFunctions) { + if (pair.first != ourName || returnType != this->getType(f->fReturnType) || + parameters.size() != f->fParameters.size()) { + continue; + } + for (size_t i = 0; i < parameters.size(); ++i) { + if (parameters[i] != this->getType(f->fParameters[i]->fType)) { + goto next; + } + } + fFunctions[f] = LLVMAddFunction(fModule, realName, LLVMFunctionType( + returnType, + parameters.data(), + parameters.size(), + false)); + found = true; + } } next:; } + SkASSERT(found); } void JIT::loadBuiltinFunctions() { @@ -128,6 +178,18 @@ void JIT::loadBuiltinFunctions() { this->addBuiltinFunction("cos", "cosf", fFloat32Type, { fFloat32Type }); this->addBuiltinFunction("tan", "tanf", fFloat32Type, { fFloat32Type }); this->addBuiltinFunction("sqrt", "sqrtf", fFloat32Type, { fFloat32Type }); + this->addBuiltinFunction("clamp", "sksl_clamp1", fFloat32Type, { fFloat32Type, + fFloat32Type, + fFloat32Type }); + this->addBuiltinFunction("clamp", "sksl_clamp2", fFloat32Vector2Type, { fFloat32Vector2Type, + fFloat32Type, + fFloat32Type }); + this->addBuiltinFunction("clamp", "sksl_clamp3", fFloat32Vector3Type, { fFloat32Vector3Type, + fFloat32Type, + fFloat32Type }); + this->addBuiltinFunction("clamp", "sksl_clamp4", fFloat32Vector4Type, { fFloat32Vector4Type, + fFloat32Type, + fFloat32Type }); this->addBuiltinFunction("print", "sksl_debug_print", fVoidType, { fFloat32Type }); } @@ -138,6 +200,14 @@ uint64_t JIT::resolveSymbol(const char* name, JIT* jit) { result = (uint64_t) &sksl_pipeline_append; } else if (!strcmp(name, "_sksl_pipeline_append_callback")) { result = (uint64_t) &sksl_pipeline_append_callback; + } else if (!strcmp(name, "_sksl_clamp1")) { + result = (uint64_t) &sksl_clamp1; + } else if (!strcmp(name, "_sksl_clamp2")) { + result = (uint64_t) &sksl_clamp2; + } else if (!strcmp(name, "_sksl_clamp3")) { + result = (uint64_t) &sksl_clamp3; + } else if (!strcmp(name, "_sksl_clamp4")) { + result = (uint64_t) &sksl_clamp4; } else if (!strcmp(name, "_sksl_debug_print")) { result = (uint64_t) &sksl_debug_print; } else { @@ -406,7 +476,7 @@ JIT::TypeKind JIT::typeKind(const Type& type) { return JIT::kInt_TypeKind; } else if (type.fName == "uint" || type.fName == "ushort") { return JIT::kUInt_TypeKind; - } else if (type.fName == "float" || type.fName == "double") { + } else if (type.fName == "float" || type.fName == "double" || type.fName == "half") { return JIT::kFloat_TypeKind; } ABORT("unsupported type: %s\n", type.description().c_str()); @@ -441,7 +511,7 @@ LLVMValueRef JIT::compileBinary(LLVMBuilderRef builder, const BinaryExpression& LLVMValueRef left = this->compileExpression(builder, *b.fLeft); \ LLVMValueRef right = this->compileExpression(builder, *b.fRight); \ this->vectorize(builder, b, &left, &right); \ - switch (this->typeKind(b.fLeft->fType)) { \ + switch (this->typeKind(b.fLeft->fType)) { \ case kInt_TypeKind: \ return SFunc(builder, left, right, "binary"); \ case kUInt_TypeKind: \ @@ -449,7 +519,7 @@ LLVMValueRef JIT::compileBinary(LLVMBuilderRef builder, const BinaryExpression& case kFloat_TypeKind: \ return FFunc(builder, left, right, "binary"); \ default: \ - ABORT("unsupported typeKind"); \ + ABORT("unsupported typeKind"); \ } \ } #define COMPOUND(SFunc, UFunc, FFunc) { \ @@ -458,7 +528,7 @@ LLVMValueRef JIT::compileBinary(LLVMBuilderRef builder, const BinaryExpression& LLVMValueRef right = this->compileExpression(builder, *b.fRight); \ this->vectorize(builder, b, &left, &right); \ LLVMValueRef result; \ - switch (this->typeKind(b.fLeft->fType)) { \ + switch (this->typeKind(b.fLeft->fType)) { \ case kInt_TypeKind: \ result = SFunc(builder, left, right, "binary"); \ break; \ @@ -469,7 +539,7 @@ LLVMValueRef JIT::compileBinary(LLVMBuilderRef builder, const BinaryExpression& result = FFunc(builder, left, right, "binary"); \ break; \ default: \ - ABORT("unsupported typeKind"); \ + ABORT("unsupported typeKind"); \ } \ lvalue->store(builder, result); \ return result; \ @@ -510,6 +580,10 @@ LLVMValueRef JIT::compileBinary(LLVMBuilderRef builder, const BinaryExpression& BINARY(LLVMBuildAnd, LLVMBuildAnd, LLVMBuildAnd); case Token::BITWISEOR: BINARY(LLVMBuildOr, LLVMBuildOr, LLVMBuildOr); + case Token::SHL: + BINARY(LLVMBuildShl, LLVMBuildShl, LLVMBuildShl); + case Token::SHR: + BINARY(LLVMBuildAShr, LLVMBuildLShr, LLVMBuildAShr); case Token::PLUSEQ: COMPOUND(LLVMBuildAdd, LLVMBuildAdd, LLVMBuildFAdd); case Token::MINUSEQ: @@ -523,13 +597,83 @@ LLVMValueRef JIT::compileBinary(LLVMBuilderRef builder, const BinaryExpression& case Token::BITWISEOREQ: COMPOUND(LLVMBuildOr, LLVMBuildOr, LLVMBuildOr); case Token::EQEQ: - COMPARE(LLVMBuildICmp, LLVMIntEQ, - LLVMBuildICmp, LLVMIntEQ, - LLVMBuildFCmp, LLVMRealOEQ); + switch (b.fLeft->fType.kind()) { + case Type::kScalar_Kind: + COMPARE(LLVMBuildICmp, LLVMIntEQ, + LLVMBuildICmp, LLVMIntEQ, + LLVMBuildFCmp, LLVMRealOEQ); + case Type::kVector_Kind: { + LLVMValueRef left = this->compileExpression(builder, *b.fLeft); + LLVMValueRef right = this->compileExpression(builder, *b.fRight); + this->vectorize(builder, b, &left, &right); + LLVMValueRef value; + switch (this->typeKind(b.fLeft->fType)) { + case kInt_TypeKind: + value = LLVMBuildICmp(builder, LLVMIntEQ, left, right, "binary"); + break; + case kUInt_TypeKind: + value = LLVMBuildICmp(builder, LLVMIntEQ, left, right, "binary"); + break; + case kFloat_TypeKind: + value = LLVMBuildFCmp(builder, LLVMRealOEQ, left, right, "binary"); + break; + default: + ABORT("unsupported typeKind"); + } + LLVMValueRef args[1] = { value }; + LLVMValueRef func; + switch (b.fLeft->fType.columns()) { + case 2: func = fFoldAnd2Func; break; + case 3: func = fFoldAnd3Func; break; + case 4: func = fFoldAnd4Func; break; + default: + SkASSERT(false); + func = fFoldAnd2Func; + } + return LLVMBuildCall(builder, func, args, 1, "all"); + } + default: + SkASSERT(false); + } case Token::NEQ: - COMPARE(LLVMBuildICmp, LLVMIntNE, - LLVMBuildICmp, LLVMIntNE, - LLVMBuildFCmp, LLVMRealONE); + switch (b.fLeft->fType.kind()) { + case Type::kScalar_Kind: + COMPARE(LLVMBuildICmp, LLVMIntNE, + LLVMBuildICmp, LLVMIntNE, + LLVMBuildFCmp, LLVMRealONE); + case Type::kVector_Kind: { + LLVMValueRef left = this->compileExpression(builder, *b.fLeft); + LLVMValueRef right = this->compileExpression(builder, *b.fRight); + this->vectorize(builder, b, &left, &right); + LLVMValueRef value; + switch (this->typeKind(b.fLeft->fType)) { + case kInt_TypeKind: + value = LLVMBuildICmp(builder, LLVMIntNE, left, right, "binary"); + break; + case kUInt_TypeKind: + value = LLVMBuildICmp(builder, LLVMIntNE, left, right, "binary"); + break; + case kFloat_TypeKind: + value = LLVMBuildFCmp(builder, LLVMRealONE, left, right, "binary"); + break; + default: + ABORT("unsupported typeKind"); + } + LLVMValueRef args[1] = { value }; + LLVMValueRef func; + switch (b.fLeft->fType.columns()) { + case 2: func = fFoldOr2Func; break; + case 3: func = fFoldOr3Func; break; + case 4: func = fFoldOr4Func; break; + default: + SkASSERT(false); + func = fFoldOr2Func; + } + return LLVMBuildCall(builder, func, args, 1, "all"); + } + default: + SkASSERT(false); + } case Token::LT: COMPARE(LLVMBuildICmp, LLVMIntSLT, LLVMBuildICmp, LLVMIntULT, @@ -583,6 +727,7 @@ LLVMValueRef JIT::compileBinary(LLVMBuilderRef builder, const BinaryExpression& return phi; } default: + printf("%s\n", b.description().c_str()); ABORT("unsupported binary operator"); } } @@ -702,9 +847,9 @@ void JIT::appendStage(LLVMBuilderRef builder, const AppendStage& a) { const FunctionDeclaration& functionDecl = *((FunctionReference&) *a.fArguments[1]).fFunctions[0]; bool found = false; - for (const auto& pe : fProgram->fElements) { - if (ProgramElement::kFunction_Kind == pe->fKind) { - const FunctionDefinition& def = (const FunctionDefinition&) *pe; + for (const auto& pe : *fProgram) { + if (ProgramElement::kFunction_Kind == pe.fKind) { + const FunctionDefinition& def = (const FunctionDefinition&) pe; if (&def.fDeclaration == &functionDecl) { LLVMValueRef fn = this->compileStageFunction(def); LLVMValueRef args[2] = { @@ -747,49 +892,74 @@ LLVMValueRef JIT::compileConstructor(LLVMBuilderRef builder, const Constructor& TypeKind from = this->typeKind(c.fArguments[0]->fType); TypeKind to = this->typeKind(c.fType); LLVMValueRef base = this->compileExpression(builder, *c.fArguments[0]); - if (kFloat_TypeKind == to) { - if (kInt_TypeKind == from) { - return LLVMBuildSIToFP(builder, base, this->getType(c.fType), "cast"); - } - if (kUInt_TypeKind == from) { - return LLVMBuildUIToFP(builder, base, this->getType(c.fType), "cast"); - } - } - if (kInt_TypeKind == to) { - if (kFloat_TypeKind == from) { - return LLVMBuildFPToSI(builder, base, this->getType(c.fType), "cast"); - } - if (kUInt_TypeKind == from) { - return base; - } - } - if (kUInt_TypeKind == to) { - if (kFloat_TypeKind == from) { - return LLVMBuildFPToUI(builder, base, this->getType(c.fType), "cast"); - } - if (kInt_TypeKind == from) { - return base; - } + switch (to) { + case kFloat_TypeKind: + switch (from) { + case kInt_TypeKind: + return LLVMBuildSIToFP(builder, base, this->getType(c.fType), "cast"); + case kUInt_TypeKind: + return LLVMBuildUIToFP(builder, base, this->getType(c.fType), "cast"); + case kFloat_TypeKind: + return base; + case kBool_TypeKind: + SkASSERT(false); + } + case kInt_TypeKind: + switch (from) { + case kInt_TypeKind: + return base; + case kUInt_TypeKind: + return base; + case kFloat_TypeKind: + return LLVMBuildFPToSI(builder, base, this->getType(c.fType), "cast"); + case kBool_TypeKind: + SkASSERT(false); + } + case kUInt_TypeKind: + switch (from) { + case kInt_TypeKind: + return base; + case kUInt_TypeKind: + return base; + case kFloat_TypeKind: + return LLVMBuildFPToUI(builder, base, this->getType(c.fType), "cast"); + case kBool_TypeKind: + SkASSERT(false); + } + case kBool_TypeKind: + SkASSERT(false); } - ABORT("unsupported constructor"); } case Type::kVector_Kind: { LLVMValueRef vec = LLVMGetUndef(this->getType(c.fType)); - if (c.fArguments.size() == 1) { + if (c.fArguments.size() == 1 && c.fArguments[0]->fType.kind() == Type::kScalar_Kind) { LLVMValueRef value = this->compileExpression(builder, *c.fArguments[0]); for (int i = 0; i < c.fType.columns(); ++i) { vec = LLVMBuildInsertElement(builder, vec, value, LLVMConstInt(fInt32Type, i, false), - "vec build"); + "vec build 1"); } } else { - SkASSERT(c.fArguments.size() == (size_t) c.fType.columns()); - for (int i = 0; i < c.fType.columns(); ++i) { - vec = LLVMBuildInsertElement(builder, vec, - this->compileExpression(builder, - *c.fArguments[i]), - LLVMConstInt(fInt32Type, i, false), - "vec build"); + int index = 0; + for (const auto& arg : c.fArguments) { + LLVMValueRef value = this->compileExpression(builder, *arg); + if (arg->fType.kind() == Type::kVector_Kind) { + for (int i = 0; i < arg->fType.columns(); ++i) { + LLVMValueRef column = LLVMBuildExtractElement(builder, + vec, + LLVMConstInt(fInt32Type, + i, + false), + "construct extract"); + vec = LLVMBuildInsertElement(builder, vec, column, + LLVMConstInt(fInt32Type, index++, false), + "vec build 2"); + } + } else { + vec = LLVMBuildInsertElement(builder, vec, value, + LLVMConstInt(fInt32Type, index++, false), + "vec build 3"); + } } } return vec; @@ -1460,7 +1630,6 @@ bool JIT::compileVectorExpression(LLVMBuilderRef builder, const Expression& expr return this->compileVectorVariableReference(builder, (const VariableReference&) expr, out); default: - printf("failed expression: %s\n", expr.description().c_str()); return false; } } @@ -1480,7 +1649,6 @@ bool JIT::compileVectorStatement(LLVMBuilderRef builder, const Statement& stmt) *((const ExpressionStatement&) stmt).fExpression, &result); default: - printf("failed statement: %s\n", stmt.description().c_str()); return false; } } @@ -1582,7 +1750,7 @@ bool JIT::hasStageSignature(const FunctionDeclaration& f) { f.fParameters[0]->fModifiers.fFlags == 0 && f.fParameters[1]->fType == *fProgram->fContext->fInt_Type && f.fParameters[1]->fModifiers.fFlags == 0 && - f.fParameters[2]->fType == *fProgram->fContext->fFloat4_Type && + f.fParameters[2]->fType == *fProgram->fContext->fHalf4_Type && f.fParameters[2]->fModifiers.fFlags == (Modifiers::kIn_Flag | Modifiers::kOut_Flag); } @@ -1639,6 +1807,21 @@ void JIT::createModule() { fPromotedParameters.clear(); fModule = LLVMModuleCreateWithNameInContext("skslmodule", fContext); this->loadBuiltinFunctions(); + LLVMTypeRef fold2Params[1] = { fInt1Vector2Type }; + fFoldAnd2Func = LLVMAddFunction(fModule, "llvm.experimental.vector.reduce.and.i1.v2i1", + LLVMFunctionType(fInt1Type, fold2Params, 1, false)); + fFoldOr2Func = LLVMAddFunction(fModule, "llvm.experimental.vector.reduce.or.i1.v2i1", + LLVMFunctionType(fInt1Type, fold2Params, 1, false)); + LLVMTypeRef fold3Params[1] = { fInt1Vector3Type }; + fFoldAnd3Func = LLVMAddFunction(fModule, "llvm.experimental.vector.reduce.and.i1.v3i1", + LLVMFunctionType(fInt1Type, fold3Params, 1, false)); + fFoldOr3Func = LLVMAddFunction(fModule, "llvm.experimental.vector.reduce.or.i1.v3i1", + LLVMFunctionType(fInt1Type, fold3Params, 1, false)); + LLVMTypeRef fold4Params[1] = { fInt1Vector4Type }; + fFoldAnd4Func = LLVMAddFunction(fModule, "llvm.experimental.vector.reduce.and.i1.v4i1", + LLVMFunctionType(fInt1Type, fold4Params, 1, false)); + fFoldOr4Func = LLVMAddFunction(fModule, "llvm.experimental.vector.reduce.or.i1.v4i1", + LLVMFunctionType(fInt1Type, fold4Params, 1, false)); // LLVM doesn't do void*, have to declare it as int8* LLVMTypeRef appendParams[3] = { fInt8PtrType, fInt32Type, fInt8PtrType }; fAppendFunc = LLVMAddFunction(fModule, "sksl_pipeline_append", LLVMFunctionType(fVoidType, @@ -1656,13 +1839,15 @@ void JIT::createModule() { 1, false)); - for (const auto& e : fProgram->fElements) { - SkASSERT(e->fKind == ProgramElement::kFunction_Kind); - this->compileFunction((FunctionDefinition&) *e); + for (const auto& e : *fProgram) { + if (e.fKind == ProgramElement::kFunction_Kind) { + this->compileFunction((FunctionDefinition&) e); + } } } std::unique_ptr JIT::compile(std::unique_ptr program) { + fCompiler.optimize(*program); fProgram = std::move(program); this->createModule(); this->optimize(); diff --git a/src/sksl/SkSLJIT.h b/src/sksl/SkSLJIT.h index b23e31237f..54f6254e9c 100644 --- a/src/sksl/SkSLJIT.h +++ b/src/sksl/SkSLJIT.h @@ -10,7 +10,6 @@ #ifdef SK_LLVM_AVAILABLE -#include "ir/SkSLAppendStage.h" #include "ir/SkSLBinaryExpression.h" #include "ir/SkSLBreakStatement.h" #include "ir/SkSLContinueStatement.h" @@ -45,6 +44,8 @@ class SkRasterPipeline; namespace SkSL { +struct AppendStage; + /** * A just-in-time compiler for SkSL code which uses an LLVM backend. Only available when the * skia_llvm_path gn arg is set. @@ -54,7 +55,8 @@ namespace SkSL { * #ifdef SK_LLVM_AVAILABLE * SkSL::Compiler compiler; * SkSL::Program::Settings settings; - * std::unique_ptr program = compiler.convertProgram(SkSL::Program::kCPU_Kind, + * std::unique_ptr program = compiler.convertProgram( + SkSL::Program::kPipelineStage_Kind, * "void swap(int x, int y, inout float4 color) {" * " color.rb = color.br;" * "}", @@ -304,6 +306,10 @@ private: LLVMBasicBlockRef fCurrentBlock; LLVMTypeRef fVoidType; LLVMTypeRef fInt1Type; + LLVMTypeRef fInt1VectorType; + LLVMTypeRef fInt1Vector2Type; + LLVMTypeRef fInt1Vector3Type; + LLVMTypeRef fInt1Vector4Type; LLVMTypeRef fInt8Type; LLVMTypeRef fInt8PtrType; LLVMTypeRef fInt32Type; @@ -332,6 +338,12 @@ private: std::vector fBreakTarget; std::vector fContinueTarget; + LLVMValueRef fFoldAnd2Func; + LLVMValueRef fFoldOr2Func; + LLVMValueRef fFoldAnd3Func; + LLVMValueRef fFoldOr3Func; + LLVMValueRef fFoldAnd4Func; + LLVMValueRef fFoldOr4Func; LLVMValueRef fAppendFunc; LLVMValueRef fAppendCallbackFunc; LLVMValueRef fDebugFunc; diff --git a/src/sksl/SkSLMain.cpp b/src/sksl/SkSLMain.cpp index 8ba0933f8c..3da90dfbe2 100644 --- a/src/sksl/SkSLMain.cpp +++ b/src/sksl/SkSLMain.cpp @@ -45,8 +45,10 @@ int main(int argc, const char** argv) { kind = SkSL::Program::kGeometry_Kind; } else if (input.endsWith(".fp")) { kind = SkSL::Program::kFragmentProcessor_Kind; + } else if (input.endsWith(".stage")) { + kind = SkSL::Program::kPipelineStage_Kind; } else { - printf("input filename must end in '.vert', '.frag', '.geom', or '.fp'\n"); + printf("input filename must end in '.vert', '.frag', '.geom', '.fp', or '.stage'\n"); exit(1); } diff --git a/src/sksl/SkSLPipelineStageCodeGenerator.cpp b/src/sksl/SkSLPipelineStageCodeGenerator.cpp new file mode 100644 index 0000000000..aceb75e3ee --- /dev/null +++ b/src/sksl/SkSLPipelineStageCodeGenerator.cpp @@ -0,0 +1,167 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkSLPipelineStageCodeGenerator.h" + +#include "SkSLCompiler.h" +#include "SkSLHCodeGenerator.h" + +namespace SkSL { + +PipelineStageCodeGenerator::PipelineStageCodeGenerator( + const Context* context, + const Program* program, + ErrorReporter* errors, + OutputStream* out, + std::vector* outFormatArgs) +: INHERITED(context, program, errors, out) +, fName("Temp") +, fFullName(String::printf("Gr%s", fName.c_str())) +, fSectionAndParameterHelper(*program, *errors) +, fFormatArgs(outFormatArgs) {} + +void PipelineStageCodeGenerator::writef(const char* s, va_list va) { + static constexpr int BUFFER_SIZE = 1024; + va_list copy; + va_copy(copy, va); + char buffer[BUFFER_SIZE]; + int length = vsnprintf(buffer, BUFFER_SIZE, s, va); + if (length < BUFFER_SIZE) { + fOut->write(buffer, length); + } else { + std::unique_ptr heap(new char[length + 1]); + vsprintf(heap.get(), s, copy); + fOut->write(heap.get(), length); + } +} + +void PipelineStageCodeGenerator::writef(const char* s, ...) { + va_list va; + va_start(va, s); + this->writef(s, va); + va_end(va); +} + +void PipelineStageCodeGenerator::writeHeader() { +} + +bool PipelineStageCodeGenerator::usesPrecisionModifiers() const { + return false; +} + +String PipelineStageCodeGenerator::getTypeName(const Type& type) { + return type.name(); +} + +void PipelineStageCodeGenerator::writeBinaryExpression(const BinaryExpression& b, + Precedence parentPrecedence) { + if (b.fOperator == Token::PERCENT) { + // need to use "%%" instead of "%" b/c the code will be inside of a printf + Precedence precedence = GetBinaryPrecedence(b.fOperator); + if (precedence >= parentPrecedence) { + this->write("("); + } + this->writeExpression(*b.fLeft, precedence); + this->write(" %% "); + this->writeExpression(*b.fRight, precedence); + if (precedence >= parentPrecedence) { + this->write(")"); + } + } else { + INHERITED::writeBinaryExpression(b, parentPrecedence); + } +} + +void PipelineStageCodeGenerator::writeIntLiteral(const IntLiteral& i) { + this->write(to_string((int32_t) i.fValue)); +} + +void PipelineStageCodeGenerator::writeVariableReference(const VariableReference& ref) { + switch (ref.fVariable.fModifiers.fLayout.fBuiltin) { + case SK_INCOLOR_BUILTIN: + this->write("%s"); + fFormatArgs->push_back(Compiler::FormatArg::kInput); + break; + case SK_OUTCOLOR_BUILTIN: + this->write("%s"); + fFormatArgs->push_back(Compiler::FormatArg::kOutput); + break; + case SK_MAIN_X_BUILTIN: + this->write("sk_FragCoord.x"); + break; + case SK_MAIN_Y_BUILTIN: + this->write("sk_FragCoord.y"); + break; + default: + this->write(ref.fVariable.fName); + } +} + +void PipelineStageCodeGenerator::writeIfStatement(const IfStatement& s) { + if (s.fIsStatic) { + this->write("@"); + } + INHERITED::writeIfStatement(s); +} + +void PipelineStageCodeGenerator::writeSwitchStatement(const SwitchStatement& s) { + if (s.fIsStatic) { + this->write("@"); + } + INHERITED::writeSwitchStatement(s); +} + +void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) { + if (f.fDeclaration.fName == "main") { + fFunctionHeader = ""; + OutputStream* oldOut = fOut; + StringStream buffer; + fOut = &buffer; + this->write("%s = %s;\n"); + fFormatArgs->push_back(Compiler::FormatArg::kOutput); + fFormatArgs->push_back(Compiler::FormatArg::kInput); + for (const auto& s : ((Block&) *f.fBody).fStatements) { + this->writeStatement(*s); + this->writeLine(); + } + + fOut = oldOut; + this->write(fFunctionHeader); + this->writef("%s", buffer.str().c_str()); + } else { + INHERITED::writeFunction(f); + } +} + +bool PipelineStageCodeGenerator::writeSection(const char* name, const char* prefix) { + const Section* s = fSectionAndParameterHelper.getSection(name); + if (s) { + this->writef("%s%s", prefix, s->fText.c_str()); + return true; + } + return false; +} + +void PipelineStageCodeGenerator::writeProgramElement(const ProgramElement& p) { + if (p.fKind == ProgramElement::kSection_Kind) { + return; + } + if (p.fKind == ProgramElement::kVar_Kind) { + const VarDeclarations& decls = (const VarDeclarations&) p; + if (!decls.fVars.size()) { + return; + } + const Variable& var = *((VarDeclaration&) *decls.fVars[0]).fVar; + if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) || + -1 != var.fModifiers.fLayout.fBuiltin) { + return; + } + } + INHERITED::writeProgramElement(p); +} + +} // namespace diff --git a/src/sksl/SkSLPipelineStageCodeGenerator.h b/src/sksl/SkSLPipelineStageCodeGenerator.h new file mode 100644 index 0000000000..09b40ce731 --- /dev/null +++ b/src/sksl/SkSLPipelineStageCodeGenerator.h @@ -0,0 +1,65 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SKSL_PIPELINESTAGECODEGENERATOR +#define SKSL_PIPELINESTAGECODEGENERATOR + +#include "SkSLGLSLCodeGenerator.h" +#include "SkSLSectionAndParameterHelper.h" + +#include + +namespace SkSL { + +class PipelineStageCodeGenerator : public GLSLCodeGenerator { +public: + PipelineStageCodeGenerator(const Context* context, const Program* program, + ErrorReporter* errors, OutputStream* out, + std::vector* outFormatArgs); + +private: + void writef(const char* s, va_list va) SKSL_PRINTF_LIKE(2, 0); + + void writef(const char* s, ...) SKSL_PRINTF_LIKE(2, 3); + + bool writeSection(const char* name, const char* prefix = ""); + + void writeHeader() override; + + bool usesPrecisionModifiers() const override; + + String getTypeName(const Type& type) override; + + void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence) override; + + void writeIntLiteral(const IntLiteral& i) override; + + void writeVariableReference(const VariableReference& ref) override; + + void writeIfStatement(const IfStatement& s) override; + + void writeSwitchStatement(const SwitchStatement& s) override; + + void writeFunction(const FunctionDefinition& f) override; + + void writeProgramElement(const ProgramElement& p) override; + + bool writeEmitCode(std::vector& uniforms); + + String fName; + String fFullName; + SectionAndParameterHelper fSectionAndParameterHelper; + String fExtraEmitCodeCode; + std::set fWrittenTransformedCoords; + std::vector* fFormatArgs; + + typedef GLSLCodeGenerator INHERITED; +}; + +} + +#endif diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp index fcee9aeee0..237a226029 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.cpp +++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp @@ -2242,10 +2242,10 @@ SpvId SPIRVCodeGenerator::writeTernaryExpression(const TernaryExpression& t, Out std::unique_ptr create_literal_1(const Context& context, const Type& type) { if (type.isInteger()) { - return std::unique_ptr(new IntLiteral(context, -1, 1, &type)); + return std::unique_ptr(new IntLiteral(-1, 1, &type)); } else if (type.isFloat()) { - return std::unique_ptr(new FloatLiteral(context, -1, 1.0, &type)); + return std::unique_ptr(new FloatLiteral(-1, 1.0, &type)); } else { ABORT("math is unsupported on type '%s'", type.name().c_str()); } diff --git a/src/sksl/SkSLString.cpp b/src/sksl/SkSLString.cpp index 125dabb335..292cef5159 100644 --- a/src/sksl/SkSLString.cpp +++ b/src/sksl/SkSLString.cpp @@ -210,10 +210,22 @@ String to_string(double value) { #endif #define MAX_DOUBLE_CHARS 25 char buffer[MAX_DOUBLE_CHARS]; - SkDEBUGCODE(int len = )SNPRINTF(buffer, sizeof(buffer), "%.17g", value); + int len = SNPRINTF(buffer, sizeof(buffer), "%.17g", value); SkASSERT(len < MAX_DOUBLE_CHARS); + bool needsDotZero = true; + for (int i = 0; i < len; ++i) { + char c = buffer[i]; + if (c == ',') { + buffer[i] = '.'; + needsDotZero = false; + break; + } else if (c == '.' || c == 'e') { + needsDotZero = false; + break; + } + } String result(buffer); - if (!strchr(buffer, '.') && !strchr(buffer, 'e')) { + if (needsDotZero) { result += ".0"; } return result; diff --git a/src/sksl/ir/SkSLAppendStage.h b/src/sksl/ir/SkSLAppendStage.h index 87a8210a83..268ae979d2 100644 --- a/src/sksl/ir/SkSLAppendStage.h +++ b/src/sksl/ir/SkSLAppendStage.h @@ -23,7 +23,16 @@ struct AppendStage : public Expression { , fStage(stage) , fArguments(std::move(arguments)) {} - String description() const { + std::unique_ptr clone() const override { + std::vector> cloned; + for (const auto& arg : fArguments) { + cloned.push_back(arg->clone()); + } + return std::unique_ptr(new AppendStage(fOffset, fStage, std::move(cloned), + &fType)); + } + + String description() const override { String result = "append("; const char* separator = ""; for (const auto& a : fArguments) { @@ -35,7 +44,7 @@ struct AppendStage : public Expression { return result; } - bool hasSideEffects() const { + bool hasSideEffects() const override { return true; } @@ -44,6 +53,14 @@ struct AppendStage : public Expression { std::vector> fArguments; typedef Expression INHERITED; + +private: + AppendStage(int offset, SkRasterPipeline::StockStage stage, + std::vector> arguments, const Type* type) + : INHERITED(offset, kAppendStage_Kind, *type) + , fStage(stage) + , fArguments(std::move(arguments)) {} + }; } // namespace diff --git a/src/sksl/ir/SkSLBinaryExpression.h b/src/sksl/ir/SkSLBinaryExpression.h index c26994edf2..ed1a5cc181 100644 --- a/src/sksl/ir/SkSLBinaryExpression.h +++ b/src/sksl/ir/SkSLBinaryExpression.h @@ -38,6 +38,11 @@ struct BinaryExpression : public Expression { fRight->hasSideEffects(); } + std::unique_ptr clone() const override { + return std::unique_ptr(new BinaryExpression(fOffset, fLeft->clone(), fOperator, + fRight->clone(), fType)); + } + String description() const override { return "(" + fLeft->description() + " " + Compiler::OperatorName(fOperator) + " " + fRight->description() + ")"; diff --git a/src/sksl/ir/SkSLBlock.h b/src/sksl/ir/SkSLBlock.h index af1975396e..0a03654488 100644 --- a/src/sksl/ir/SkSLBlock.h +++ b/src/sksl/ir/SkSLBlock.h @@ -32,6 +32,14 @@ struct Block : public Statement { return true; } + std::unique_ptr clone() const override { + std::vector> cloned; + for (const auto& s : fStatements) { + cloned.push_back(s->clone()); + } + return std::unique_ptr(new Block(fOffset, std::move(cloned), fSymbols)); + } + String description() const override { String result("{"); for (size_t i = 0; i < fStatements.size(); i++) { diff --git a/src/sksl/ir/SkSLBoolLiteral.h b/src/sksl/ir/SkSLBoolLiteral.h index 9a69f0f138..d979ed3939 100644 --- a/src/sksl/ir/SkSLBoolLiteral.h +++ b/src/sksl/ir/SkSLBoolLiteral.h @@ -38,9 +38,18 @@ struct BoolLiteral : public Expression { return fValue == b.fValue; } + std::unique_ptr clone() const override { + return std::unique_ptr(new BoolLiteral(fOffset, fValue, &fType)); + } + const bool fValue; typedef Expression INHERITED; + +private: + BoolLiteral(int offset, bool value, const Type* type) + : INHERITED(offset, kBoolLiteral_Kind, *type) + , fValue(value) {} }; } // namespace diff --git a/src/sksl/ir/SkSLBreakStatement.h b/src/sksl/ir/SkSLBreakStatement.h index da392f5960..272deb65cd 100644 --- a/src/sksl/ir/SkSLBreakStatement.h +++ b/src/sksl/ir/SkSLBreakStatement.h @@ -20,6 +20,10 @@ struct BreakStatement : public Statement { BreakStatement(int offset) : INHERITED(offset, kBreak_Kind) {} + std::unique_ptr clone() const override { + return std::unique_ptr(new BreakStatement(fOffset)); + } + String description() const override { return String("break;"); } diff --git a/src/sksl/ir/SkSLConstructor.h b/src/sksl/ir/SkSLConstructor.h index 5e7c3d0d79..145e117453 100644 --- a/src/sksl/ir/SkSLConstructor.h +++ b/src/sksl/ir/SkSLConstructor.h @@ -43,8 +43,7 @@ struct Constructor : public Expression { fType == *irGenerator.fContext.fUShort_Type) { // promote uint(1) to 1u int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue; - return std::unique_ptr(new IntLiteral(irGenerator.fContext, - fOffset, + return std::unique_ptr(new IntLiteral(fOffset, intValue, &fType)); } @@ -61,6 +60,14 @@ struct Constructor : public Expression { return false; } + std::unique_ptr clone() const override { + std::vector> cloned; + for (const auto& arg : fArguments) { + cloned.push_back(arg->clone()); + } + return std::unique_ptr(new Constructor(fOffset, fType, std::move(cloned))); + } + String description() const override { String result = fType.description() + "("; String separator; diff --git a/src/sksl/ir/SkSLContinueStatement.h b/src/sksl/ir/SkSLContinueStatement.h index 6ed40c404f..9977fbecaf 100644 --- a/src/sksl/ir/SkSLContinueStatement.h +++ b/src/sksl/ir/SkSLContinueStatement.h @@ -20,6 +20,10 @@ struct ContinueStatement : public Statement { ContinueStatement(int offset) : INHERITED(offset, kContinue_Kind) {} + std::unique_ptr clone() const override { + return std::unique_ptr(new ContinueStatement(fOffset)); + } + String description() const override { return String("continue;"); } diff --git a/src/sksl/ir/SkSLDiscardStatement.h b/src/sksl/ir/SkSLDiscardStatement.h index b62530e6f3..8c406e9353 100644 --- a/src/sksl/ir/SkSLDiscardStatement.h +++ b/src/sksl/ir/SkSLDiscardStatement.h @@ -20,6 +20,10 @@ struct DiscardStatement : public Statement { DiscardStatement(int offset) : INHERITED(offset, kDiscard_Kind) {} + std::unique_ptr clone() const override { + return std::unique_ptr(new DiscardStatement(fOffset)); + } + String description() const override { return String("discard;"); } diff --git a/src/sksl/ir/SkSLDoStatement.h b/src/sksl/ir/SkSLDoStatement.h index 3abec550eb..af0fc5951b 100644 --- a/src/sksl/ir/SkSLDoStatement.h +++ b/src/sksl/ir/SkSLDoStatement.h @@ -23,6 +23,11 @@ struct DoStatement : public Statement { , fStatement(std::move(statement)) , fTest(std::move(test)) {} + std::unique_ptr clone() const override { + return std::unique_ptr(new DoStatement(fOffset, fStatement->clone(), + fTest->clone())); + } + String description() const override { return "do " + fStatement->description() + " while (" + fTest->description() + ");"; } diff --git a/src/sksl/ir/SkSLEnum.h b/src/sksl/ir/SkSLEnum.h index 6c44a67678..eea7e5c3a5 100644 --- a/src/sksl/ir/SkSLEnum.h +++ b/src/sksl/ir/SkSLEnum.h @@ -17,6 +17,10 @@ struct Enum : public ProgramElement { , fTypeName(typeName) , fSymbols(std::move(symbols)) {} + std::unique_ptr clone() const override { + return std::unique_ptr(new Enum(fOffset, fTypeName, fSymbols)); + } + String description() const override { String result = "enum class " + fTypeName + " {\n"; String separator; diff --git a/src/sksl/ir/SkSLExpression.h b/src/sksl/ir/SkSLExpression.h index c8ad1380e7..ddeed448a2 100644 --- a/src/sksl/ir/SkSLExpression.h +++ b/src/sksl/ir/SkSLExpression.h @@ -106,6 +106,8 @@ struct Expression : public IRNode { return fType.coercionCost(target); } + virtual std::unique_ptr clone() const = 0; + const Kind fKind; const Type& fType; diff --git a/src/sksl/ir/SkSLExpressionStatement.h b/src/sksl/ir/SkSLExpressionStatement.h index 215763b8fd..90aa5415cc 100644 --- a/src/sksl/ir/SkSLExpressionStatement.h +++ b/src/sksl/ir/SkSLExpressionStatement.h @@ -21,6 +21,10 @@ struct ExpressionStatement : public Statement { : INHERITED(expression->fOffset, kExpression_Kind) , fExpression(std::move(expression)) {} + std::unique_ptr clone() const override { + return std::unique_ptr(new ExpressionStatement(fExpression->clone())); + } + String description() const override { return fExpression->description() + ";"; } diff --git a/src/sksl/ir/SkSLExtension.h b/src/sksl/ir/SkSLExtension.h index b5a48b94ab..3a103a63c6 100644 --- a/src/sksl/ir/SkSLExtension.h +++ b/src/sksl/ir/SkSLExtension.h @@ -20,6 +20,10 @@ struct Extension : public ProgramElement { : INHERITED(offset, kExtension_Kind) , fName(std::move(name)) {} + std::unique_ptr clone() const override { + return std::unique_ptr(new Extension(fOffset, fName)); + } + String description() const override { return "#extension " + fName + " : enable"; } diff --git a/src/sksl/ir/SkSLFieldAccess.h b/src/sksl/ir/SkSLFieldAccess.h index 0f66dec5a4..b3bd05096e 100644 --- a/src/sksl/ir/SkSLFieldAccess.h +++ b/src/sksl/ir/SkSLFieldAccess.h @@ -35,6 +35,11 @@ struct FieldAccess : public Expression { return fBase->hasSideEffects(); } + std::unique_ptr clone() const override { + return std::unique_ptr(new FieldAccess(fBase->clone(), fFieldIndex, + fOwnerKind)); + } + String description() const override { return fBase->description() + "." + fBase->fType.fields()[fFieldIndex].fName; } diff --git a/src/sksl/ir/SkSLFloatLiteral.h b/src/sksl/ir/SkSLFloatLiteral.h index 82c15c032b..e995e4c6e1 100644 --- a/src/sksl/ir/SkSLFloatLiteral.h +++ b/src/sksl/ir/SkSLFloatLiteral.h @@ -17,9 +17,12 @@ namespace SkSL { * A literal floating point number. */ struct FloatLiteral : public Expression { - FloatLiteral(const Context& context, int offset, double value, - const Type* type = nullptr) - : INHERITED(offset, kFloatLiteral_Kind, type ? *type : *context.fFloat_Type) + FloatLiteral(const Context& context, int offset, double value) + : INHERITED(offset, kFloatLiteral_Kind, *context.fFloat_Type) + , fValue(value) {} + + FloatLiteral(int offset, double value, const Type* type) + : INHERITED(offset, kFloatLiteral_Kind, *type) , fValue(value) {} String description() const override { @@ -43,6 +46,10 @@ struct FloatLiteral : public Expression { return fValue; } + std::unique_ptr clone() const override { + return std::unique_ptr(new FloatLiteral(fOffset, fValue, &fType)); + } + const double fValue; typedef Expression INHERITED; diff --git a/src/sksl/ir/SkSLForStatement.h b/src/sksl/ir/SkSLForStatement.h index 6896ceb902..220be9855b 100644 --- a/src/sksl/ir/SkSLForStatement.h +++ b/src/sksl/ir/SkSLForStatement.h @@ -28,6 +28,12 @@ struct ForStatement : public Statement { , fNext(std::move(next)) , fStatement(std::move(statement)) {} + std::unique_ptr clone() const override { + return std::unique_ptr(new ForStatement(fOffset, fInitializer->clone(), + fTest->clone(), fNext->clone(), + fStatement->clone(), fSymbols)); + } + String description() const override { String result("for ("); if (fInitializer) { diff --git a/src/sksl/ir/SkSLFunctionCall.h b/src/sksl/ir/SkSLFunctionCall.h index 115281d63d..7047c37067 100644 --- a/src/sksl/ir/SkSLFunctionCall.h +++ b/src/sksl/ir/SkSLFunctionCall.h @@ -32,6 +32,15 @@ struct FunctionCall : public Expression { return fFunction.fModifiers.fFlags & Modifiers::kHasSideEffects_Flag; } + std::unique_ptr clone() const override { + std::vector> cloned; + for (const auto& arg : fArguments) { + cloned.push_back(arg->clone()); + } + return std::unique_ptr(new FunctionCall(fOffset, fType, fFunction, + std::move(cloned))); + } + String description() const override { String result = String(fFunction.fName) + "("; String separator; diff --git a/src/sksl/ir/SkSLFunctionDefinition.h b/src/sksl/ir/SkSLFunctionDefinition.h index e0dabc5791..4ec559756c 100644 --- a/src/sksl/ir/SkSLFunctionDefinition.h +++ b/src/sksl/ir/SkSLFunctionDefinition.h @@ -24,6 +24,11 @@ struct FunctionDefinition : public ProgramElement { , fDeclaration(declaration) , fBody(std::move(body)) {} + std::unique_ptr clone() const override { + return std::unique_ptr(new FunctionDefinition(fOffset, fDeclaration, + fBody->clone())); + } + String description() const override { return fDeclaration.description() + " " + fBody->description(); } diff --git a/src/sksl/ir/SkSLFunctionReference.h b/src/sksl/ir/SkSLFunctionReference.h index 58fefce801..4c7f7670d0 100644 --- a/src/sksl/ir/SkSLFunctionReference.h +++ b/src/sksl/ir/SkSLFunctionReference.h @@ -28,6 +28,10 @@ struct FunctionReference : public Expression { return false; } + std::unique_ptr clone() const override { + return std::unique_ptr(new FunctionReference(fOffset, fFunctions, &fType)); + } + String description() const override { return String(""); } @@ -35,7 +39,12 @@ struct FunctionReference : public Expression { const std::vector fFunctions; typedef Expression INHERITED; -}; + +private: + FunctionReference(int offset, std::vector function, + const Type* type) + : INHERITED(offset, kFunctionReference_Kind, *type) + , fFunctions(function) {}}; } // namespace diff --git a/src/sksl/ir/SkSLIfStatement.h b/src/sksl/ir/SkSLIfStatement.h index 4c2ca0b1fa..9d35fe8f7d 100644 --- a/src/sksl/ir/SkSLIfStatement.h +++ b/src/sksl/ir/SkSLIfStatement.h @@ -25,6 +25,11 @@ struct IfStatement : public Statement { , fIfTrue(std::move(ifTrue)) , fIfFalse(std::move(ifFalse)) {} + std::unique_ptr clone() const override { + return std::unique_ptr(new IfStatement(fOffset, fIsStatic, fTest->clone(), + fIfTrue->clone(), fIfFalse ? fIfFalse->clone() : nullptr)); + } + String description() const override { String result; if (fIsStatic) { diff --git a/src/sksl/ir/SkSLIndexExpression.h b/src/sksl/ir/SkSLIndexExpression.h index de44b1adb2..74288e5171 100644 --- a/src/sksl/ir/SkSLIndexExpression.h +++ b/src/sksl/ir/SkSLIndexExpression.h @@ -62,6 +62,11 @@ struct IndexExpression : public Expression { return fBase->hasSideEffects() || fIndex->hasSideEffects(); } + std::unique_ptr clone() const override { + return std::unique_ptr(new IndexExpression(fBase->clone(), fIndex->clone(), + &fType)); + } + String description() const override { return fBase->description() + "[" + fIndex->description() + "]"; } @@ -70,6 +75,13 @@ struct IndexExpression : public Expression { std::unique_ptr fIndex; typedef Expression INHERITED; + +private: + IndexExpression(std::unique_ptr base, std::unique_ptr index, + const Type* type) + : INHERITED(base->fOffset, kIndex_Kind, *type) + , fBase(std::move(base)) + , fIndex(std::move(index)) {} }; } // namespace diff --git a/src/sksl/ir/SkSLIntLiteral.h b/src/sksl/ir/SkSLIntLiteral.h index 50337bfe6f..116796c16d 100644 --- a/src/sksl/ir/SkSLIntLiteral.h +++ b/src/sksl/ir/SkSLIntLiteral.h @@ -19,8 +19,12 @@ namespace SkSL { struct IntLiteral : public Expression { // FIXME: we will need to revisit this if/when we add full support for both signed and unsigned // 64-bit integers, but for right now an int64_t will hold every value we care about - IntLiteral(const Context& context, int offset, int64_t value, const Type* type = nullptr) - : INHERITED(offset, kIntLiteral_Kind, type ? *type : *context.fInt_Type) + IntLiteral(const Context& context, int offset, int64_t value) + : INHERITED(offset, kIntLiteral_Kind, *context.fInt_Type) + , fValue(value) {} + + IntLiteral(int offset, int64_t value, const Type* type = nullptr) + : INHERITED(offset, kIntLiteral_Kind, *type) , fValue(value) {} String description() const override { @@ -51,6 +55,10 @@ struct IntLiteral : public Expression { return fValue; } + std::unique_ptr clone() const override { + return std::unique_ptr(new IntLiteral(fOffset, fValue, &fType)); + } + const int64_t fValue; typedef Expression INHERITED; diff --git a/src/sksl/ir/SkSLInterfaceBlock.h b/src/sksl/ir/SkSLInterfaceBlock.h index 4a7bf9307b..08bf9d0f75 100644 --- a/src/sksl/ir/SkSLInterfaceBlock.h +++ b/src/sksl/ir/SkSLInterfaceBlock.h @@ -35,6 +35,17 @@ struct InterfaceBlock : public ProgramElement { , fSizes(std::move(sizes)) , fTypeOwner(typeOwner) {} + std::unique_ptr clone() const override { + std::vector> sizesClone; + for (const auto& s : fSizes) { + sizesClone.push_back(s->clone()); + } + return std::unique_ptr(new InterfaceBlock(fOffset, &fVariable, fTypeName, + fInstanceName, + std::move(sizesClone), + fTypeOwner)); + } + String description() const override { String result = fVariable.fModifiers.description() + fTypeName + " {\n"; const Type* structType = &fVariable.fType; diff --git a/src/sksl/ir/SkSLLayout.h b/src/sksl/ir/SkSLLayout.h index 3082b34133..5c99807ab5 100644 --- a/src/sksl/ir/SkSLLayout.h +++ b/src/sksl/ir/SkSLLayout.h @@ -311,6 +311,9 @@ struct Layout { if (result.size() > 0) { result = "layout (" + result + ")"; } + if (fKey) { + result += "/* key */"; + } return result; } diff --git a/src/sksl/ir/SkSLModifiersDeclaration.h b/src/sksl/ir/SkSLModifiersDeclaration.h index 5c9608f02f..1f31926a30 100644 --- a/src/sksl/ir/SkSLModifiersDeclaration.h +++ b/src/sksl/ir/SkSLModifiersDeclaration.h @@ -23,7 +23,11 @@ struct ModifiersDeclaration : public ProgramElement { : INHERITED(-1, kModifiers_Kind) , fModifiers(modifiers) {} - String description() const { + std::unique_ptr clone() const override { + return std::unique_ptr(new ModifiersDeclaration(fModifiers)); + } + + String description() const override { return fModifiers.description() + ";"; } diff --git a/src/sksl/ir/SkSLNop.h b/src/sksl/ir/SkSLNop.h index e7aae9b7b8..954fedb13b 100644 --- a/src/sksl/ir/SkSLNop.h +++ b/src/sksl/ir/SkSLNop.h @@ -28,6 +28,10 @@ struct Nop : public Statement { return String(";"); } + std::unique_ptr clone() const override { + return std::unique_ptr(new Nop()); + } + typedef Statement INHERITED; }; diff --git a/src/sksl/ir/SkSLPostfixExpression.h b/src/sksl/ir/SkSLPostfixExpression.h index c53f1de507..dd20efd3e7 100644 --- a/src/sksl/ir/SkSLPostfixExpression.h +++ b/src/sksl/ir/SkSLPostfixExpression.h @@ -26,6 +26,10 @@ struct PostfixExpression : public Expression { return true; } + std::unique_ptr clone() const override { + return std::unique_ptr(new PostfixExpression(fOperand->clone(), fOperator)); + } + String description() const override { return fOperand->description() + Compiler::OperatorName(fOperator); } diff --git a/src/sksl/ir/SkSLPrefixExpression.h b/src/sksl/ir/SkSLPrefixExpression.h index d5d97b2517..366f714fa3 100644 --- a/src/sksl/ir/SkSLPrefixExpression.h +++ b/src/sksl/ir/SkSLPrefixExpression.h @@ -45,6 +45,10 @@ struct PrefixExpression : public Expression { return nullptr; } + std::unique_ptr clone() const override { + return std::unique_ptr(new PrefixExpression(fOperator, fOperand->clone())); + } + String description() const override { return Compiler::OperatorName(fOperator) + fOperand->description(); } diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h index 9f140877b7..59c91229f8 100644 --- a/src/sksl/ir/SkSLProgram.h +++ b/src/sksl/ir/SkSLProgram.h @@ -39,6 +39,10 @@ struct Program { : fKind(kInt_Kind) , fValue(i) {} + Value(unsigned int i) + : fKind(kInt_Kind) + , fValue(i) {} + std::unique_ptr literal(const Context& context, int offset) const { switch (fKind) { case Program::Settings::Value::kBool_Kind: @@ -192,7 +196,7 @@ struct Program { kVertex_Kind, kGeometry_Kind, kFragmentProcessor_Kind, - kCPU_Kind + kPipelineStage_Kind }; Program(Kind kind, @@ -252,10 +256,13 @@ struct Program { // because destroying elements can modify reference counts in symbols std::shared_ptr fSymbols; Inputs fInputs; + bool fIsOptimized = false; private: std::vector>* fInheritedElements; std::vector> fElements; + + friend class Compiler; }; } // namespace diff --git a/src/sksl/ir/SkSLProgramElement.h b/src/sksl/ir/SkSLProgramElement.h index 9d1bdfe885..b14836ffb1 100644 --- a/src/sksl/ir/SkSLProgramElement.h +++ b/src/sksl/ir/SkSLProgramElement.h @@ -32,6 +32,8 @@ struct ProgramElement : public IRNode { Kind fKind; + virtual std::unique_ptr clone() const = 0; + typedef IRNode INHERITED; }; diff --git a/src/sksl/ir/SkSLReturnStatement.h b/src/sksl/ir/SkSLReturnStatement.h index 1b479b8097..774d803011 100644 --- a/src/sksl/ir/SkSLReturnStatement.h +++ b/src/sksl/ir/SkSLReturnStatement.h @@ -24,6 +24,13 @@ struct ReturnStatement : public Statement { : INHERITED(expression->fOffset, kReturn_Kind) , fExpression(std::move(expression)) {} + std::unique_ptr clone() const override { + if (fExpression) { + return std::unique_ptr(new ReturnStatement(fExpression->clone())); + } + return std::unique_ptr(new ReturnStatement(fOffset)); + } + String description() const override { if (fExpression) { return "return " + fExpression->description() + ";"; diff --git a/src/sksl/ir/SkSLSection.h b/src/sksl/ir/SkSLSection.h index 96c257b1f8..d06b979c17 100644 --- a/src/sksl/ir/SkSLSection.h +++ b/src/sksl/ir/SkSLSection.h @@ -22,6 +22,10 @@ struct Section : public ProgramElement { , fArgument(std::move(arg)) , fText(std::move(text)) {} + std::unique_ptr clone() const override { + return std::unique_ptr(new Section(fOffset, fName, fArgument, fText)); + } + String description() const override { String result = "@" + fName; if (fArgument.size()) { diff --git a/src/sksl/ir/SkSLSetting.cpp b/src/sksl/ir/SkSLSetting.cpp index 2d4a8ba151..9885a2873f 100644 --- a/src/sksl/ir/SkSLSetting.cpp +++ b/src/sksl/ir/SkSLSetting.cpp @@ -13,10 +13,10 @@ namespace SkSL { std::unique_ptr Setting::constantPropagate(const IRGenerator& irGenerator, const DefinitionMap& definitions) { - if (irGenerator.fSettings->fReplaceSettings) { - return VariableReference::copy_constant(irGenerator, fValue.get()); - } - return nullptr; + if (irGenerator.fSettings->fReplaceSettings) { + return VariableReference::copy_constant(irGenerator, fValue.get()); } -} // namespace + return nullptr; +} +} // namespace diff --git a/src/sksl/ir/SkSLSetting.h b/src/sksl/ir/SkSLSetting.h index 1396099102..cc1c551077 100644 --- a/src/sksl/ir/SkSLSetting.h +++ b/src/sksl/ir/SkSLSetting.h @@ -28,6 +28,10 @@ struct Setting : public Expression { std::unique_ptr constantPropagate(const IRGenerator& irGenerator, const DefinitionMap& definitions) override; + std::unique_ptr clone() const override { + return std::unique_ptr(new Setting(fOffset, fName, fValue->clone())); + } + String description() const override { return fName; } diff --git a/src/sksl/ir/SkSLStatement.h b/src/sksl/ir/SkSLStatement.h index a116cc1c4c..99aab19208 100644 --- a/src/sksl/ir/SkSLStatement.h +++ b/src/sksl/ir/SkSLStatement.h @@ -43,6 +43,8 @@ struct Statement : public IRNode { return false; } + virtual std::unique_ptr clone() const = 0; + const Kind fKind; typedef IRNode INHERITED; diff --git a/src/sksl/ir/SkSLSwitchCase.h b/src/sksl/ir/SkSLSwitchCase.h index c33224bdbb..b9e52180f3 100644 --- a/src/sksl/ir/SkSLSwitchCase.h +++ b/src/sksl/ir/SkSLSwitchCase.h @@ -23,6 +23,16 @@ struct SwitchCase : public Statement { , fValue(std::move(value)) , fStatements(std::move(statements)) {} + std::unique_ptr clone() const override { + std::vector> cloned; + for (const auto& s : fStatements) { + cloned.push_back(s->clone()); + } + return std::unique_ptr(new SwitchCase(fOffset, + fValue ? fValue->clone() : nullptr, + std::move(cloned))); + } + String description() const override { String result; if (fValue) { diff --git a/src/sksl/ir/SkSLSwitchStatement.h b/src/sksl/ir/SkSLSwitchStatement.h index 68d0ef02df..2c48bad1ba 100644 --- a/src/sksl/ir/SkSLSwitchStatement.h +++ b/src/sksl/ir/SkSLSwitchStatement.h @@ -26,6 +26,15 @@ struct SwitchStatement : public Statement { , fSymbols(std::move(symbols)) , fCases(std::move(cases)) {} + std::unique_ptr clone() const override { + std::vector> cloned; + for (const auto& s : fCases) { + cloned.push_back(std::unique_ptr((SwitchCase*) s->clone().release())); + } + return std::unique_ptr(new SwitchStatement(fOffset, fIsStatic, fValue->clone(), + std::move(cloned), fSymbols)); + } + String description() const override { String result; if (fIsStatic) { diff --git a/src/sksl/ir/SkSLSwizzle.h b/src/sksl/ir/SkSLSwizzle.h index b90b78d916..6ed29cfcc0 100644 --- a/src/sksl/ir/SkSLSwizzle.h +++ b/src/sksl/ir/SkSLSwizzle.h @@ -115,6 +115,10 @@ struct Swizzle : public Expression { return fBase->hasSideEffects(); } + std::unique_ptr clone() const override { + return std::unique_ptr(new Swizzle(fType, fBase->clone(), fComponents)); + } + String description() const override { String result = fBase->description() + "."; for (int x : fComponents) { @@ -127,6 +131,16 @@ struct Swizzle : public Expression { const std::vector fComponents; typedef Expression INHERITED; + +private: + Swizzle(const Type& type, std::unique_ptr base, std::vector components) + : INHERITED(base->fOffset, kSwizzle_Kind, type) + , fBase(std::move(base)) + , fComponents(std::move(components)) { + SkASSERT(fComponents.size() >= 1 && fComponents.size() <= 4); + } + + }; } // namespace diff --git a/src/sksl/ir/SkSLTernaryExpression.h b/src/sksl/ir/SkSLTernaryExpression.h index b77e0e07f2..f7e4ea0be6 100644 --- a/src/sksl/ir/SkSLTernaryExpression.h +++ b/src/sksl/ir/SkSLTernaryExpression.h @@ -30,6 +30,12 @@ struct TernaryExpression : public Expression { return fTest->hasSideEffects() || fIfTrue->hasSideEffects() || fIfFalse->hasSideEffects(); } + std::unique_ptr clone() const override { + return std::unique_ptr(new TernaryExpression(fOffset, fTest->clone(), + fIfTrue->clone(), + fIfFalse->clone())); + } + String description() const override { return "(" + fTest->description() + " ? " + fIfTrue->description() + " : " + fIfFalse->description() + ")"; diff --git a/src/sksl/ir/SkSLTypeReference.h b/src/sksl/ir/SkSLTypeReference.h index f7065b7c3f..df3dc15abd 100644 --- a/src/sksl/ir/SkSLTypeReference.h +++ b/src/sksl/ir/SkSLTypeReference.h @@ -18,9 +18,9 @@ namespace SkSL { * always eventually replaced by Constructors in valid programs. */ struct TypeReference : public Expression { - TypeReference(const Context& context, int offset, const Type& type) + TypeReference(const Context& context, int offset, const Type& value) : INHERITED(offset, kTypeReference_Kind, *context.fInvalid_Type) - , fValue(type) {} + , fValue(value) {} bool hasSideEffects() const override { return false; @@ -30,9 +30,18 @@ struct TypeReference : public Expression { return String(fValue.fName); } + std::unique_ptr clone() const override { + return std::unique_ptr(new TypeReference(fOffset, fValue, &fType)); + } + const Type& fValue; typedef Expression INHERITED; + +private: + TypeReference(int offset, const Type& value, const Type* type) + : INHERITED(offset, kTypeReference_Kind, *type) + , fValue(value) {} }; } // namespace diff --git a/src/sksl/ir/SkSLVarDeclarations.h b/src/sksl/ir/SkSLVarDeclarations.h index 707715f6dc..b98e959ff0 100644 --- a/src/sksl/ir/SkSLVarDeclarations.h +++ b/src/sksl/ir/SkSLVarDeclarations.h @@ -29,7 +29,20 @@ struct VarDeclaration : public Statement { , fSizes(std::move(sizes)) , fValue(std::move(value)) {} - String description() const { + std::unique_ptr clone() const override { + std::vector> sizesClone; + for (const auto& s : fSizes) { + if (s) { + sizesClone.push_back(s->clone()); + } else { + sizesClone.push_back(nullptr); + } + } + return std::unique_ptr(new VarDeclaration(fVar, std::move(sizesClone), + fValue ? fValue->clone() : nullptr)); + } + + String description() const override { String result = fVar->fName; for (const auto& size : fSizes) { if (size) { @@ -64,6 +77,16 @@ struct VarDeclarations : public ProgramElement { } } + std::unique_ptr clone() const override { + std::vector> cloned; + for (const auto& v : fVars) { + cloned.push_back(std::unique_ptr( + (VarDeclaration*) v->clone().release())); + } + return std::unique_ptr(new VarDeclarations(fOffset, &fBaseType, + std::move(cloned))); + } + String description() const override { if (!fVars.size()) { return String(); diff --git a/src/sksl/ir/SkSLVarDeclarationsStatement.h b/src/sksl/ir/SkSLVarDeclarationsStatement.h index 0258e66c6e..c9c1df175b 100644 --- a/src/sksl/ir/SkSLVarDeclarationsStatement.h +++ b/src/sksl/ir/SkSLVarDeclarationsStatement.h @@ -30,11 +30,16 @@ struct VarDeclarationsStatement : public Statement { return true; } + std::unique_ptr clone() const override { + std::unique_ptr cloned((VarDeclarations*) fDeclaration->clone().release()); + return std::unique_ptr(new VarDeclarationsStatement(std::move(cloned))); + } + String description() const override { return fDeclaration->description() + ";"; } - std::shared_ptr fDeclaration; + std::unique_ptr fDeclaration; typedef Statement INHERITED; }; diff --git a/src/sksl/ir/SkSLVariableReference.cpp b/src/sksl/ir/SkSLVariableReference.cpp index fa23e4749b..e6092c940c 100644 --- a/src/sksl/ir/SkSLVariableReference.cpp +++ b/src/sksl/ir/SkSLVariableReference.cpp @@ -93,6 +93,11 @@ std::unique_ptr VariableReference::constantPropagate(const IRGenerat if (fRefKind != kRead_RefKind) { return nullptr; } + if (irGenerator.fKind == Program::kPipelineStage_Kind && + fVariable.fStorage == Variable::kGlobal_Storage && + (fVariable.fModifiers.fFlags & Modifiers::kIn_Flag)) { + return irGenerator.getArg(fOffset, fVariable.fName); + } if ((fVariable.fModifiers.fFlags & Modifiers::kConst_Flag) && fVariable.fInitialValue && fVariable.fInitialValue->isConstant()) { return copy_constant(irGenerator, fVariable.fInitialValue); diff --git a/src/sksl/ir/SkSLVariableReference.h b/src/sksl/ir/SkSLVariableReference.h index 14ddf796ff..405a5d1f55 100644 --- a/src/sksl/ir/SkSLVariableReference.h +++ b/src/sksl/ir/SkSLVariableReference.h @@ -49,6 +49,10 @@ struct VariableReference : public Expression { return 0 != (fVariable.fModifiers.fFlags & Modifiers::kConst_Flag); } + std::unique_ptr clone() const override { + return std::unique_ptr(new VariableReference(fOffset, fVariable, fRefKind)); + } + String description() const override { return fVariable.fName; } diff --git a/src/sksl/ir/SkSLWhileStatement.h b/src/sksl/ir/SkSLWhileStatement.h index aed6494999..6695875c03 100644 --- a/src/sksl/ir/SkSLWhileStatement.h +++ b/src/sksl/ir/SkSLWhileStatement.h @@ -23,6 +23,11 @@ struct WhileStatement : public Statement { , fTest(std::move(test)) , fStatement(std::move(statement)) {} + std::unique_ptr clone() const override { + return std::unique_ptr(new WhileStatement(fOffset, fTest->clone(), + fStatement->clone())); + } + String description() const override { return "while (" + fTest->description() + ") " + fStatement->description(); } diff --git a/src/sksl/sksl_cpu.inc b/src/sksl/sksl_cpu.inc deleted file mode 100644 index 479450bd33..0000000000 --- a/src/sksl/sksl_cpu.inc +++ /dev/null @@ -1,12 +0,0 @@ -STRINGIFY( - // special-cased within the compiler - append takes various arguments depending on what kind of - // stage is being appended - sk_has_side_effects void append(); - - float abs(float x); - float sin(float x); - float cos(float x); - float tan(float x); - float sqrt(float x); - sk_has_side_effects void print(float x); -) diff --git a/src/sksl/sksl_pipeline.inc b/src/sksl/sksl_pipeline.inc new file mode 100644 index 0000000000..f0a2221607 --- /dev/null +++ b/src/sksl/sksl_pipeline.inc @@ -0,0 +1,19 @@ +STRINGIFY( + // special-cased within the compiler - append takes various arguments depending on what kind of + // stage is being appended + sk_has_side_effects void append(); + + float abs(float x); + float sin(float x); + float cos(float y); + float tan(float x); + float sqrt(float x); + float clamp(float x, float min, float max); + float2 clamp(float2 x, float min, float max); + float3 clamp(float3 x, float min, float max); + float4 clamp(float4 x, float min, float max); + sk_has_side_effects void print(float x); + layout(builtin=10009) int sk_x; + layout(builtin=10010) int sk_y; + layout(builtin=10004) out half4 sk_OutColor; +) -- cgit v1.2.3