aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sksl
diff options
context:
space:
mode:
authorGravatar Timothy Liang <timliang@google.com>2018-05-18 14:38:19 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-05-18 19:05:44 +0000
commitee84fe1e6484d8fb7b9b1549d9d68c9dbabe3737 (patch)
treed079e0f230c359fc3873b1e092b9e4873174b941 /src/sksl
parentab0795c4dd2c138c3037a4f22d2b762b449ec460 (diff)
added global variable and multi-texture support to metal sksl backend
Bug: skia: Change-Id: If676774ec0a30c5b536ccffbff2220d180b7fa59 Reviewed-on: https://skia-review.googlesource.com/129187 Commit-Queue: Timothy Liang <timliang@google.com> Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Diffstat (limited to 'src/sksl')
-rw-r--r--src/sksl/SkSLMetalCodeGenerator.cpp128
-rw-r--r--src/sksl/SkSLMetalCodeGenerator.h10
2 files changed, 114 insertions, 24 deletions
diff --git a/src/sksl/SkSLMetalCodeGenerator.cpp b/src/sksl/SkSLMetalCodeGenerator.cpp
index b8fdc1c193..2f801a8d88 100644
--- a/src/sksl/SkSLMetalCodeGenerator.cpp
+++ b/src/sksl/SkSLMetalCodeGenerator.cpp
@@ -17,7 +17,7 @@
namespace SkSL {
-void MetalCodeGenerator::setupIntrinsics(){
+void MetalCodeGenerator::setupIntrinsics() {
#define SPECIAL(x) std::make_tuple(kSpecial_IntrinsicKind, k ## x ## _SpecialIntrinsic, \
k ## x ## _SpecialIntrinsic, k ## x ## _SpecialIntrinsic, \
k ## x ## _SpecialIntrinsic)
@@ -25,6 +25,10 @@ void MetalCodeGenerator::setupIntrinsics(){
fIntrinsicMap[String("texture")] = SPECIAL(Texture);
}
+MetalCodeGenerator::TextureId MetalCodeGenerator::nextTextureId() {
+ return fCurrentTextureId++;
+}
+
void MetalCodeGenerator::write(const char* s) {
if (!s[0]) {
return;
@@ -86,6 +90,9 @@ void MetalCodeGenerator::writeType(const Type& type) {
this->writeType(type.componentType());
this->write(to_string(type.columns()));
break;
+ case Type::kSampler_Kind:
+ this->write("texture2d<half> "); //FIXME - support other texture types;
+ break;
default:
this->write(type.name());
}
@@ -186,6 +193,11 @@ void MetalCodeGenerator::writeFunctionCall(const FunctionCall& c) {
this->write("_uniforms");
separator = ", ";
}
+ if (this->requirements(c.fFunction) & kGlobals_Requirement) {
+ this->write(separator);
+ this->write("_globals");
+ separator = ", ";
+ }
for (size_t i = 0; i < c.fArguments.size(); ++i) {
const Expression& arg = *c.fArguments[i];
this->write(separator);
@@ -201,9 +213,15 @@ void MetalCodeGenerator::writeFunctionCall(const FunctionCall& c) {
void MetalCodeGenerator::writeSpecialIntrinsic(const FunctionCall & c, SpecialIntrinsic kind) {
switch (kind) {
case kTexture_SpecialIntrinsic:
- this->write("_colorMap.sample($colorSampler, ");
+ this->writeExpression(*c.fArguments[0], kSequence_Precedence);
+ this->write(".sample(_globals->colorSampler, ");
this->writeExpression(*c.fArguments[1], kSequence_Precedence);
- this->write(".xy)"); // FIXME - dimension checking
+ if (c.fArguments[1]->fType == *fContext.fFloat3_Type) {
+ this->write(".xy)"); // FIXME - add projection functionality
+ } else {
+ ASSERT(c.fArguments[1]->fType == *fContext.fFloat2_Type);
+ this->write(")");
+ }
break;
default:
ABORT("unsupported special intrinsic kind");
@@ -254,12 +272,11 @@ void MetalCodeGenerator::writeVariableReference(const VariableReference& ref) {
if (ref.fVariable.fModifiers.fFlags & Modifiers::kIn_Flag) {
this->write("_in.");
} else if (ref.fVariable.fModifiers.fFlags & Modifiers::kOut_Flag) {
- this->write("_out.");
+ this->write("_out->");
} else if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) {
this->write("_uniforms.");
} else {
- fErrors.error(ref.fVariable.fOffset, "Metal backend does not support global "
- "variables");
+ this->write("_globals->");
}
}
this->write(ref.fVariable.fName);
@@ -283,7 +300,7 @@ void MetalCodeGenerator::writeFieldAccess(const FieldAccess& f) {
this->write("gl_ClipDistance");
break;
case SK_POSITION_BUILTIN:
- this->write("_out.position");
+ this->write("_out->position");
break;
default:
this->write(f.fBase->fType.fields()[f.fFieldIndex].fName);
@@ -437,7 +454,6 @@ void MetalCodeGenerator::writeSetting(const Setting& s) {
}
void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
- bool needColorSampler = false;
const char* separator = "";
if ("main" == f.fDeclaration.fName) {
switch (fProgram.fKind) {
@@ -461,12 +477,15 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
if (!decls.fVars.size()) {
continue;
}
- for(const auto& stmt: decls.fVars){
+ for (const auto& stmt: decls.fVars) {
VarDeclaration& var = (VarDeclaration&) *stmt;
- if(var.fVar->fType == *fContext.fSampler2D_Type){
- needColorSampler = true;
- this->write(", texture2d<half> _colorMap [[texture(TextureIndexColor)]]");
- } // FIXME may require textureindexcolor field, hardcoded for now
+ if (var.fVar->fType.kind() == Type::kSampler_Kind) {
+ this->write(", texture2d<half> "); // FIXME - support other texture types
+ this->write(var.fVar->fName);
+ this->write("[[texture(");
+ this->write(to_string(fTextureMap[var.fVar->fName]));
+ this->write(")]]");
+ }
}
}
}
@@ -480,7 +499,7 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
}
if (this->requirements(f.fDeclaration) & kOutputs_Requirement) {
this->write(separator);
- this->write("thread Outputs& _out");
+ this->write("thread Outputs* _out");
separator = ", ";
}
if (this->requirements(f.fDeclaration) & kUniforms_Requirement) {
@@ -488,6 +507,11 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
this->write("Uniforms _uniforms");
separator = ", ";
}
+ if (this->requirements(f.fDeclaration) & kGlobals_Requirement) {
+ this->write(separator);
+ this->write("thread Globals* _globals");
+ separator = ", ";
+ }
}
for (const auto& param : f.fDeclaration.fParameters) {
this->write(separator);
@@ -517,9 +541,27 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
ASSERT(!fProgram.fSettings.fFragColorIsInOut);
if ("main" == f.fDeclaration.fName) {
- if (needColorSampler) {
- this->writeLine(" constexpr sampler "
- "$colorSampler(mip_filter::linear, mag_filter::linear, min_filter::linear);");
+ if (fNeedsGlobalStructInit) {
+ this->writeLine(" Globals globalStruct;");
+ this->writeLine(" thread Globals* _globals = &globalStruct;");
+ for (const auto var: fInitNonConstGlobalVars) {
+ this->write(" _globals->");
+ this->write(var->fVar->fName);
+ this->write(" = ");
+ this->writeVarInitializer(*var->fVar, *var->fValue);
+ this->writeLine(";");
+ }
+ }
+ if (!fTextureMap.empty()) {
+ this->writeLine(" _globals->colorSampler = sampler(mip_filter::linear, "
+ "mag_filter::linear, min_filter::linear);"); // FIXME - support other samplers
+ for (const auto& texture: fTextureMap) {
+ this->write(" _globals->");
+ this->write(texture.first);
+ this->write(" = ");
+ this->write(texture.first);
+ this->write(";\n");
+ }
}
switch (fProgram.fKind) {
case Program::kFragment_Kind:
@@ -564,7 +606,7 @@ void MetalCodeGenerator::writeModifiers(const Modifiers& modifiers,
this->write("thread ");
}
if (modifiers.fFlags & Modifiers::kConst_Flag) {
- this->write("const ");
+ this->write("constant ");
}
}
@@ -609,14 +651,9 @@ void MetalCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool
bool wroteType = false;
for (const auto& stmt : decl.fVars) {
VarDeclaration& var = (VarDeclaration&) *stmt;
- if (var.fVar->fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kOut_Flag |
- Modifiers::kUniform_Flag)) {
- ASSERT(global);
+ if (global && !(var.fVar->fModifiers.fFlags & Modifiers::kConst_Flag)) {
continue;
}
- if (var.fVar->fType == *fContext.fSampler2D_Type){
- continue; // FIXME - temporarily ignoring global sampler2Ds
- }
if (wroteType) {
this->write(", ");
} else {
@@ -892,6 +929,46 @@ void MetalCodeGenerator::writeOutputStruct() {
} this->write("};\n");
}
+void MetalCodeGenerator::writeGlobalStruct() {
+ bool wroteStructDecl = false;
+ for (const auto& e : fProgram) {
+ if (ProgramElement::kVar_Kind == e.fKind) {
+ VarDeclarations& decls = (VarDeclarations&) e;
+ if (!decls.fVars.size()) {
+ continue;
+ }
+ const Variable& first = *((VarDeclaration&) *decls.fVars[0]).fVar;
+ if (!first.fModifiers.fFlags && -1 == first.fModifiers.fLayout.fBuiltin) {
+ if (!wroteStructDecl) {
+ this->write("struct Globals {\n");
+ wroteStructDecl = true;
+ }
+ fNeedsGlobalStructInit = true;
+ this->write(" ");
+ this->writeType(first.fType);
+ this->write(" ");
+ for (const auto& stmt : decls.fVars) {
+ VarDeclaration& var = (VarDeclaration&) *stmt;
+ if (var.fVar->fType.kind() == Type::kSampler_Kind) {
+ fTextureMap[var.fVar->fName] = this->nextTextureId();
+ }
+ this->write(var.fVar->fName);
+ if (var.fValue) {
+ fInitNonConstGlobalVars.push_back(&var);
+ }
+ }
+ this->write(";\n");
+ }
+ }
+ }
+ if (!fTextureMap.empty()) {
+ this->writeLine(" sampler colorSampler;");
+ }
+ if (wroteStructDecl) {
+ this->write("};\n");
+ }
+}
+
void MetalCodeGenerator::writeProgramElement(const ProgramElement& e) {
switch (e.fKind) {
case ProgramElement::kExtension_Kind:
@@ -977,6 +1054,8 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Expressi
result = kOutputs_Requirement;
} else if (v.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) {
result = kUniforms_Requirement;
+ } else {
+ result = kGlobals_Requirement;
}
}
return result;
@@ -1072,6 +1151,7 @@ bool MetalCodeGenerator::generateCode() {
if (Program::kVertex_Kind == fProgram.fKind) {
this->writeOutputStruct();
}
+ this->writeGlobalStruct();
StringStream body;
fOut = &body;
for (const auto& e : fProgram) {
diff --git a/src/sksl/SkSLMetalCodeGenerator.h b/src/sksl/SkSLMetalCodeGenerator.h
index 6f8933c381..a0a0cae986 100644
--- a/src/sksl/SkSLMetalCodeGenerator.h
+++ b/src/sksl/SkSLMetalCodeGenerator.h
@@ -85,10 +85,12 @@ public:
protected:
typedef int Requirements;
+ typedef unsigned int TextureId;
static constexpr Requirements kNo_Requirements = 0;
static constexpr Requirements kInputs_Requirement = 1 << 0;
static constexpr Requirements kOutputs_Requirement = 1 << 1;
static constexpr Requirements kUniforms_Requirement = 1 << 2;
+ static constexpr Requirements kGlobals_Requirement = 1 << 3;
enum IntrinsicKind {
kSpecial_IntrinsicKind
@@ -100,6 +102,8 @@ protected:
void setupIntrinsics();
+ TextureId nextTextureId();
+
void write(const char* s);
void writeLine();
@@ -118,6 +122,8 @@ protected:
void writeOutputStruct();
+ void writeGlobalStruct();
+
void writePrecisionModifier();
void writeType(const Type& type);
@@ -210,6 +216,10 @@ protected:
typedef std::tuple<IntrinsicKind, int32_t, int32_t, int32_t, int32_t> Intrinsic;
std::unordered_map<String, Intrinsic> fIntrinsicMap;
+ std::vector<const VarDeclaration*> fInitNonConstGlobalVars;
+ TextureId fCurrentTextureId = 0;
+ std::unordered_map<String, TextureId> fTextureMap;
+ bool fNeedsGlobalStructInit = false;
const char* fLineEnding;
const Context& fContext;
StringStream fHeader;