blob: 9977cf8dcf8c53ff0b673169d43c3820f67d703d [file] [log] [blame]
* Copyright 2016 Google Inc.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
#include <stack>
#include <tuple>
#include <unordered_map>
#include "src/sksl/SkSLCodeGenerator.h"
#include "src/sksl/SkSLStringStream.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLBoolLiteral.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLDoStatement.h"
#include "src/sksl/ir/SkSLExtension.h"
#include "src/sksl/ir/SkSLFieldAccess.h"
#include "src/sksl/ir/SkSLFloatLiteral.h"
#include "src/sksl/ir/SkSLForStatement.h"
#include "src/sksl/ir/SkSLFunctionCall.h"
#include "src/sksl/ir/SkSLFunctionDeclaration.h"
#include "src/sksl/ir/SkSLFunctionDefinition.h"
#include "src/sksl/ir/SkSLIfStatement.h"
#include "src/sksl/ir/SkSLIndexExpression.h"
#include "src/sksl/ir/SkSLIntLiteral.h"
#include "src/sksl/ir/SkSLInterfaceBlock.h"
#include "src/sksl/ir/SkSLPostfixExpression.h"
#include "src/sksl/ir/SkSLPrefixExpression.h"
#include "src/sksl/ir/SkSLProgramElement.h"
#include "src/sksl/ir/SkSLReturnStatement.h"
#include "src/sksl/ir/SkSLSetting.h"
#include "src/sksl/ir/SkSLStatement.h"
#include "src/sksl/ir/SkSLSwitchStatement.h"
#include "src/sksl/ir/SkSLSwizzle.h"
#include "src/sksl/ir/SkSLTernaryExpression.h"
#include "src/sksl/ir/SkSLVarDeclarations.h"
#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
#include "src/sksl/ir/SkSLVariableReference.h"
#include "src/sksl/ir/SkSLWhileStatement.h"
namespace SkSL {
#define kLast_Capability SpvCapabilityMultiViewport
* Converts a Program into GLSL code.
class GLSLCodeGenerator : public CodeGenerator {
enum Precedence {
kParentheses_Precedence = 1,
kPostfix_Precedence = 2,
kPrefix_Precedence = 3,
kMultiplicative_Precedence = 4,
kAdditive_Precedence = 5,
kShift_Precedence = 6,
kRelational_Precedence = 7,
kEquality_Precedence = 8,
kBitwiseAnd_Precedence = 9,
kBitwiseXor_Precedence = 10,
kBitwiseOr_Precedence = 11,
kLogicalAnd_Precedence = 12,
kLogicalXor_Precedence = 13,
kLogicalOr_Precedence = 14,
kTernary_Precedence = 15,
kAssignment_Precedence = 16,
kSequence_Precedence = 17,
kTopLevel_Precedence = kSequence_Precedence
GLSLCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
OutputStream* out)
: INHERITED(program, errors, out)
, fLineEnding("\n")
, fContext(*context)
, fProgramKind(program->fKind) {}
bool generateCode() override;
enum class SwizzleOrder {
void write(const char* s);
void writeLine();
void writeLine(const char* s);
void write(const String& s);
void write(StringFragment s);
void writeLine(const String& s);
virtual void writeHeader();
virtual bool usesPrecisionModifiers() const;
virtual String getTypeName(const Type& type);
void writeType(const Type& type);
void writeExtension(const String& name);
void writeExtension(const String& name, bool require);
void writeInterfaceBlock(const InterfaceBlock& intf);
void writeFunctionStart(const FunctionDeclaration& f);
void writeFunctionDeclaration(const FunctionDeclaration& f);
virtual void writeFunction(const FunctionDefinition& f);
void writeLayout(const Layout& layout);
void writeModifiers(const Modifiers& modifiers, bool globalContext);
virtual void writeInputVars();
virtual void writeVarInitializer(const Variable& var, const Expression& value);
const char* getTypePrecision(const Type& type);
void writeTypePrecision(const Type& type);
void writeVarDeclarations(const VarDeclarations& decl, bool global);
void writeFragCoord();
virtual void writeVariableReference(const VariableReference& ref);
void writeExpression(const Expression& expr, Precedence parentPrecedence);
void writeIntrinsicCall(const FunctionCall& c);
void writeMinAbsHack(Expression& absExpr, Expression& otherExpr);
void writeDeterminantHack(const Expression& mat);
void writeInverseHack(const Expression& mat);
void writeTransposeHack(const Expression& mat);
void writeInverseSqrtHack(const Expression& x);
virtual void writeFunctionCall(const FunctionCall& c);
void writeConstructor(const Constructor& c, Precedence parentPrecedence);
virtual void writeFieldAccess(const FieldAccess& f);
void writeConstantSwizzle(const Swizzle& swizzle, const String& constants);
void writeSwizzleMask(const Swizzle& swizzle, const String& mask);
void writeSwizzleConstructor(const Swizzle& swizzle, const String& constants,
const String& mask, SwizzleOrder order);
void writeSwizzleConstructor(const Swizzle& swizzle, const String& constants,
const String& mask, const String& reswizzle);
virtual void writeSwizzle(const Swizzle& swizzle);
static Precedence GetBinaryPrecedence(Token::Kind op);
virtual void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence);
void writeShortCircuitWorkaroundExpression(const BinaryExpression& b,
Precedence parentPrecedence);
void writeTernaryExpression(const TernaryExpression& t, Precedence parentPrecedence);
virtual void writeIndexExpression(const IndexExpression& expr);
void writePrefixExpression(const PrefixExpression& p, Precedence parentPrecedence);
void writePostfixExpression(const PostfixExpression& p, Precedence parentPrecedence);
void writeBoolLiteral(const BoolLiteral& b);
virtual void writeIntLiteral(const IntLiteral& i);
void writeFloatLiteral(const FloatLiteral& f);
virtual void writeSetting(const Setting& s);
void writeStatement(const Statement& s);
void writeStatements(const std::vector<std::unique_ptr<Statement>>& statements);
void writeBlock(const Block& b);
virtual void writeIfStatement(const IfStatement& stmt);
void writeForStatement(const ForStatement& f);
void writeWhileStatement(const WhileStatement& w);
void writeDoStatement(const DoStatement& d);
virtual void writeSwitchStatement(const SwitchStatement& s);
virtual void writeReturnStatement(const ReturnStatement& r);
virtual void writeProgramElement(const ProgramElement& e);
const char* fLineEnding;
const Context& fContext;
StringStream fExtensions;
StringStream fGlobals;
StringStream fExtraFunctions;
String fFunctionHeader;
Program::Kind fProgramKind;
int fVarCount = 0;
int fIndentation = 0;
bool fAtLineStart = false;
// Keeps track of which struct types we have written. Given that we are unlikely to ever write
// more than one or two structs per shader, a simple linear search will be faster than anything
// fancier.
std::vector<const Type*> fWrittenStructs;
std::set<String> fWrittenIntrinsics;
// true if we have run into usages of dFdx / dFdy
bool fFoundDerivatives = false;
bool fFoundExternalSamplerDecl = false;
bool fFoundRectSamplerDecl = false;
bool fFoundGSInvocations = false;
bool fSetupFragPositionGlobal = false;
bool fSetupFragPositionLocal = false;
bool fSetupFragCoordWorkaround = false;
// if non-empty, replace all texture / texture2D / textureProj / etc. calls with this name
String fTextureFunctionOverride;
// We map function names to function class so we can quickly deal with function calls that need
// extra processing
enum class FunctionClass {
static std::unordered_map<StringFragment, FunctionClass>* fFunctionClasses;
typedef CodeGenerator INHERITED;