diff options
author | Timothy Liang <timliang@google.com> | 2018-05-24 15:33:31 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-05-24 20:01:49 +0000 |
commit | a06f215a7ddab3ce002a69d5b3187e628077c200 (patch) | |
tree | e980319a3b017aa67564d080fb43f4eaec01a7c4 /src/sksl | |
parent | 7cd740790180438d87c80be2a7eec1e71485c2b0 (diff) |
added interface block, vector comparison intrinsics, and mvk integration for metal sksl backend
Bug: skia:
Change-Id: Ia6984ba73482ec377f0890eb79f6ff92ff736749
Reviewed-on: https://skia-review.googlesource.com/129654
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.cpp | 134 | ||||
-rw-r--r-- | src/sksl/SkSLMetalCodeGenerator.h | 21 |
2 files changed, 119 insertions, 36 deletions
diff --git a/src/sksl/SkSLMetalCodeGenerator.cpp b/src/sksl/SkSLMetalCodeGenerator.cpp index 2f801a8d88..7140dbaa9c 100644 --- a/src/sksl/SkSLMetalCodeGenerator.cpp +++ b/src/sksl/SkSLMetalCodeGenerator.cpp @@ -15,18 +15,23 @@ #include "ir/SkSLNop.h" #include "ir/SkSLVariableReference.h" +static const uint32_t MVKMagicNum = 0x19960412; // FIXME - remove when decoupled from MVK + namespace SkSL { void MetalCodeGenerator::setupIntrinsics() { +#define METAL(x) std::make_tuple(kMetal_IntrinsicKind, k ## x ## _MetalIntrinsic, \ + k ## x ## _MetalIntrinsic, k ## x ## _MetalIntrinsic, \ + k ## x ## _MetalIntrinsic) #define SPECIAL(x) std::make_tuple(kSpecial_IntrinsicKind, k ## x ## _SpecialIntrinsic, \ k ## x ## _SpecialIntrinsic, k ## x ## _SpecialIntrinsic, \ k ## x ## _SpecialIntrinsic) - - fIntrinsicMap[String("texture")] = SPECIAL(Texture); -} - -MetalCodeGenerator::TextureId MetalCodeGenerator::nextTextureId() { - return fCurrentTextureId++; +// FIXME - tuple probably doesn't need this many fields, will fix when all intrinsics written + fIntrinsicMap[String("texture")] = SPECIAL(Texture); + fIntrinsicMap[String("lessThan")] = METAL(LessThan); + fIntrinsicMap[String("lessThanEqual")] = METAL(LessThanEqual); + fIntrinsicMap[String("greaterThan")] = METAL(GreaterThan); + fIntrinsicMap[String("greaterThanEqual")] = METAL(GreaterThanEqual); } void MetalCodeGenerator::write(const char* s) { @@ -161,6 +166,27 @@ void MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c) { switch (std::get<0>(intrinsic->second)) { case kSpecial_IntrinsicKind: return this->writeSpecialIntrinsic(c, (SpecialIntrinsic) intrinsicId); + break; + case kMetal_IntrinsicKind: + this->writeExpression(*c.fArguments[0], kSequence_Precedence); + switch ((MetalIntrinsic) intrinsicId) { + case kLessThan_MetalIntrinsic: + this->write(" < "); + break; + case kLessThanEqual_MetalIntrinsic: + this->write(" <= "); + break; + case kGreaterThan_MetalIntrinsic: + this->write(" > "); + break; + case kGreaterThanEqual_MetalIntrinsic: + this->write(" >= "); + break; + default: + ABORT("unsupported metal intrinsic kind"); + } + this->writeExpression(*c.fArguments[1], kSequence_Precedence); + break; default: ABORT("unsupported intrinsic kind"); } @@ -174,6 +200,10 @@ void MetalCodeGenerator::writeFunctionCall(const FunctionCall& c) { } if (c.fFunction.fBuiltin && "atan" == c.fFunction.fName && 2 == c.fArguments.size()) { this->write("atan2"); + } else if (c.fFunction.fBuiltin && "inversesqrt" == c.fFunction.fName) { + this->write("rsqrt"); + } else if (c.fFunction.fBuiltin && "mod" == c.fFunction.fName) { + this->write("fmod"); } else { this->write(c.fFunction.fName); } @@ -214,7 +244,10 @@ void MetalCodeGenerator::writeSpecialIntrinsic(const FunctionCall & c, SpecialIn switch (kind) { case kTexture_SpecialIntrinsic: this->writeExpression(*c.fArguments[0], kSequence_Precedence); - this->write(".sample(_globals->colorSampler, "); + this->write(".sample("); + this->writeExpression(*c.fArguments[0], kSequence_Precedence); + this->write(SAMPLER_SUFFIX); + this->write(", "); this->writeExpression(*c.fArguments[1], kSequence_Precedence); if (c.fArguments[1]->fType == *fContext.fFloat3_Type) { this->write(".xy)"); // FIXME - add projection functionality @@ -273,7 +306,8 @@ void MetalCodeGenerator::writeVariableReference(const VariableReference& ref) { this->write("_in."); } else if (ref.fVariable.fModifiers.fFlags & Modifiers::kOut_Flag) { this->write("_out->"); - } else if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) { + } else if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag && + ref.fVariable.fType.kind() != Type::kSampler_Kind) { this->write("_uniforms."); } else { this->write("_globals->"); @@ -303,6 +337,11 @@ void MetalCodeGenerator::writeFieldAccess(const FieldAccess& f) { this->write("_out->position"); break; default: + if (FieldAccess::kAnonymousInterfaceBlock_OwnerKind == f.fOwnerKind) { + this->write(fInterfaceBlockNameMap[ + fInterfaceBlockMap[&f.fBase->fType.fields()[f.fFieldIndex]]]); + this->write("."); + } this->write(f.fBase->fType.fields()[f.fFieldIndex].fName); } } @@ -458,10 +497,10 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) { if ("main" == f.fDeclaration.fName) { switch (fProgram.fKind) { case Program::kFragment_Kind: - this->write("fragment half4 _frag"); + this->write("fragment half4 main0"); // FIXME - named main0 for MVK integration break; case Program::kVertex_Kind: - this->write("vertex Outputs _vert"); + this->write("vertex Outputs main0"); break; default: ASSERT(false); @@ -483,10 +522,28 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) { 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(to_string(var.fVar->fModifiers.fLayout.fBinding)); + this->write(")]]"); + this->write(", sampler "); + this->write(var.fVar->fName); + this->write(SAMPLER_SUFFIX); + this->write("[[sampler("); + this->write(to_string(var.fVar->fModifiers.fLayout.fBinding)); this->write(")]]"); } } + } else if (ProgramElement::kInterfaceBlock_Kind == e.fKind) { + InterfaceBlock& intf = (InterfaceBlock&) e; + if ("sk_PerVertex" == intf.fTypeName) { + continue; + } + this->write(", constant "); + this->writeType(intf.fVariable.fType); + this->write("& " ); + this->write(fInterfaceBlockNameMap[&intf]); + this->write(" [[buffer("); + this->write(to_string(intf.fVariable.fModifiers.fLayout.fBinding)); + this->write(")]]"); } } separator = ", "; @@ -544,22 +601,25 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) { if (fNeedsGlobalStructInit) { this->writeLine(" Globals globalStruct;"); this->writeLine(" thread Globals* _globals = &globalStruct;"); - for (const auto var: fInitNonConstGlobalVars) { + 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) { + for (const auto& texture: fTextures) { + this->write(" _globals->"); + this->write(texture->fName); + this->write(" = "); + this->write(texture->fName); + this->write(";\n"); this->write(" _globals->"); - this->write(texture.first); + this->write(texture->fName); + this->write(SAMPLER_SUFFIX); this->write(" = "); - this->write(texture.first); + this->write(texture->fName); + this->write(SAMPLER_SUFFIX); this->write(";\n"); } } @@ -568,7 +628,8 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) { this->writeLine(" half4 sk_FragColor;"); break; case Program::kVertex_Kind: - this->writeLine(" Outputs _out;"); + this->writeLine(" Outputs _outputStruct;"); + this->writeLine(" thread Outputs* _out = &_outputStruct;"); break; default: ASSERT(false); @@ -586,7 +647,8 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) { this->writeLine("return sk_FragColor;"); break; case Program::kVertex_Kind: - this->writeLine("return _out;"); + this->writeLine("_out->position.y = -_out->position.y;"); + this->writeLine("return *_out;"); // FIXME - detect if function already has return break; default: ASSERT(false); @@ -614,10 +676,12 @@ void MetalCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { if ("sk_PerVertex" == intf.fTypeName) { return; } + this->write("struct "); this->writeModifiers(intf.fVariable.fModifiers, true); this->writeLine(intf.fTypeName + " {"); fIndentation++; const Type* structType = &intf.fVariable.fType; + fWrittenStructs.push_back(structType); while (Type::kArray_Kind == structType->kind()) { structType = &structType->componentType(); } @@ -625,6 +689,7 @@ void MetalCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { this->writeModifiers(f.fModifiers, false); this->writeType(*f.fType); this->writeLine(" " + f.fName + ";"); + fInterfaceBlockMap[&f] = &intf; } fIndentation--; this->write("}"); @@ -638,6 +703,9 @@ void MetalCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { } this->write("]"); } + fInterfaceBlockNameMap[&intf] = intf.fInstanceName; + } else { + fInterfaceBlockNameMap[&intf] = "_AnonInterface" + to_string(fAnonInterfaceCount++); } this->writeLine(";"); } @@ -725,7 +793,7 @@ void MetalCodeGenerator::writeStatement(const Statement& s) { this->write("continue;"); break; case Statement::kDiscard_Kind: - this->write("discard;"); + this->write("discard_fragment();"); break; case Statement::kNop_Kind: this->write(";"); @@ -843,7 +911,8 @@ void MetalCodeGenerator::writeUniformStruct() { continue; } const Variable& first = *((VarDeclaration&) *decls.fVars[0]).fVar; - if (first.fModifiers.fFlags & Modifiers::kUniform_Flag) { + if (first.fModifiers.fFlags & Modifiers::kUniform_Flag && + first.fType.kind() != Type::kSampler_Kind) { if (-1 == fUniformBuffer) { this->write("struct Uniforms {\n"); fUniformBuffer = first.fModifiers.fLayout.fSet; @@ -938,7 +1007,8 @@ void MetalCodeGenerator::writeGlobalStruct() { continue; } const Variable& first = *((VarDeclaration&) *decls.fVars[0]).fVar; - if (!first.fModifiers.fFlags && -1 == first.fModifiers.fLayout.fBuiltin) { + if ((!first.fModifiers.fFlags && -1 == first.fModifiers.fLayout.fBuiltin) || + first.fType.kind() == Type::kSampler_Kind) { if (!wroteStructDecl) { this->write("struct Globals {\n"); wroteStructDecl = true; @@ -949,10 +1019,14 @@ void MetalCodeGenerator::writeGlobalStruct() { this->write(" "); for (const auto& stmt : decls.fVars) { VarDeclaration& var = (VarDeclaration&) *stmt; + this->write(var.fVar->fName); if (var.fVar->fType.kind() == Type::kSampler_Kind) { - fTextureMap[var.fVar->fName] = this->nextTextureId(); + fTextures.push_back(var.fVar); + this->write(";\n"); + this->write(" sampler "); + this->write(var.fVar->fName); + this->write(SAMPLER_SUFFIX); } - this->write(var.fVar->fName); if (var.fValue) { fInitNonConstGlobalVars.push_back(&var); } @@ -961,9 +1035,6 @@ void MetalCodeGenerator::writeGlobalStruct() { } } } - if (!fTextureMap.empty()) { - this->writeLine(" sampler colorSampler;"); - } if (wroteStructDecl) { this->write("};\n"); } @@ -1052,7 +1123,8 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Expressi result = kInputs_Requirement; } else if (v.fVariable.fModifiers.fFlags & Modifiers::kOut_Flag) { result = kOutputs_Requirement; - } else if (v.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) { + } else if (v.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag && + v.fVariable.fType.kind() != Type::kSampler_Kind) { result = kUniforms_Requirement; } else { result = kGlobals_Requirement; @@ -1144,6 +1216,7 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Function bool MetalCodeGenerator::generateCode() { OutputStream* rawOut = fOut; fOut = &fHeader; + fOut->write((const char*) &MVKMagicNum, sizeof(MVKMagicNum)); // FIXME - for MVK integration fProgramKind = fProgram.fKind; this->writeHeader(); this->writeUniformStruct(); @@ -1161,6 +1234,7 @@ bool MetalCodeGenerator::generateCode() { write_stringstream(fHeader, *rawOut); write_stringstream(body, *rawOut); + this->write("\0"); // FIXME - for MVK integration return true; } diff --git a/src/sksl/SkSLMetalCodeGenerator.h b/src/sksl/SkSLMetalCodeGenerator.h index a0a0cae986..517f9f655b 100644 --- a/src/sksl/SkSLMetalCodeGenerator.h +++ b/src/sksl/SkSLMetalCodeGenerator.h @@ -52,6 +52,8 @@ namespace SkSL { */ class MetalCodeGenerator : public CodeGenerator { public: + static constexpr const char* SAMPLER_SUFFIX = "Smplr"; + enum Precedence { kParentheses_Precedence = 1, kPostfix_Precedence = 2, @@ -85,7 +87,6 @@ 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; @@ -93,16 +94,22 @@ protected: static constexpr Requirements kGlobals_Requirement = 1 << 3; enum IntrinsicKind { - kSpecial_IntrinsicKind + kSpecial_IntrinsicKind, + kMetal_IntrinsicKind, }; enum SpecialIntrinsic { kTexture_SpecialIntrinsic, }; - void setupIntrinsics(); + enum MetalIntrinsic { + kLessThan_MetalIntrinsic, + kLessThanEqual_MetalIntrinsic, + kGreaterThan_MetalIntrinsic, + kGreaterThanEqual_MetalIntrinsic, + }; - TextureId nextTextureId(); + void setupIntrinsics(); void write(const char* s); @@ -217,8 +224,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; + std::vector<const Variable*> fTextures; + std::unordered_map<const Type::Field*, const InterfaceBlock*> fInterfaceBlockMap; + std::unordered_map<const InterfaceBlock*, String> fInterfaceBlockNameMap; + int fAnonInterfaceCount = 0; bool fNeedsGlobalStructInit = false; const char* fLineEnding; const Context& fContext; |