Add support for input attachments in SkSL spirv
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=5115
Change-Id: I3e03a465a10c9aff62491d0f6e71105d1b650dab
Reviewed-on: https://skia-review.googlesource.com/5115
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 62e5fa7..003f154 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -113,6 +113,9 @@
ADD_TYPE(Image2D);
ADD_TYPE(IImage2D);
+ ADD_TYPE(SubpassInput);
+ ADD_TYPE(SubpassInputMS);
+
ADD_TYPE(GSampler1D);
ADD_TYPE(GSampler2D);
ADD_TYPE(GSampler3D);
diff --git a/src/sksl/SkSLContext.h b/src/sksl/SkSLContext.h
index 9289ede..6284c21 100644
--- a/src/sksl/SkSLContext.h
+++ b/src/sksl/SkSLContext.h
@@ -88,6 +88,13 @@
, fImage2D_Type(new Type(SkString("image2D"), SpvDim2D, false, false, false, true))
, fIImage2D_Type(new Type(SkString("iimage2D"), SpvDim2D, false, false, false, true))
+ // FIXME express these as "gsubpassInput" that expand to subpassInput, isubpassInput,
+ // and usubpassInput.
+ , fSubpassInput_Type(new Type(SkString("subpassInput"), SpvDimSubpassData, false, false,
+ false, false))
+ , fSubpassInputMS_Type(new Type(SkString("subpassInputMS"), SpvDimSubpassData, false, false,
+ true, false))
+
// FIXME figure out what we're supposed to do with the gsampler et al. types)
, fGSampler1D_Type(new Type(SkString("$gsampler1D"), static_type(*fSampler1D_Type)))
, fGSampler2D_Type(new Type(SkString("$gsampler2D"), static_type(*fSampler2D_Type)))
@@ -137,7 +144,7 @@
, fDefined_Expression(new Defined(*fInvalid_Type)) {}
static std::vector<const Type*> static_type(const Type& t) {
- return { &t, &t, &t, &t };
+ return { &t, &t, &t, &t };
}
const std::unique_ptr<Type> fInvalid_Type;
@@ -214,6 +221,9 @@
const std::unique_ptr<Type> fImage2D_Type;
const std::unique_ptr<Type> fIImage2D_Type;
+ const std::unique_ptr<Type> fSubpassInput_Type;
+ const std::unique_ptr<Type> fSubpassInputMS_Type;
+
const std::unique_ptr<Type> fGSampler1D_Type;
const std::unique_ptr<Type> fGSampler2D_Type;
const std::unique_ptr<Type> fGSampler3D_Type;
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index 5536261..e4aec92 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -4,7 +4,7 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-
+
#include "SkSLGLSLCodeGenerator.h"
#include "string.h"
@@ -392,7 +392,7 @@
this->write(SkString((const char*) data->data(), data->size()));
}
-void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers,
+void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers,
bool globalContext) {
if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) {
this->write("noperspective ");
@@ -404,7 +404,7 @@
if (layout.size()) {
this->write(layout + " ");
}
- if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
+ if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
(modifiers.fFlags & Modifiers::kOut_Flag)) {
this->write("inout ");
} else if (modifiers.fFlags & Modifiers::kIn_Flag) {
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index 03d0d33..58ec750 100644
--- a/src/sksl/SkSLParser.cpp
+++ b/src/sksl/SkSLParser.cpp
@@ -535,7 +535,7 @@
return -1;
}
-/* LAYOUT LPAREN IDENTIFIER EQ INT_LITERAL (COMMA IDENTIFIER EQ INT_LITERAL)*
+/* LAYOUT LPAREN IDENTIFIER EQ INT_LITERAL (COMMA IDENTIFIER EQ INT_LITERAL)*
RPAREN */
ASTLayout Parser::layout() {
int location = -1;
@@ -543,6 +543,7 @@
int index = -1;
int set = -1;
int builtin = -1;
+ int inputAttachmentIndex = -1;
bool originUpperLeft = false;
bool overrideCoverage = false;
bool blendSupportAllEquations = false;
@@ -550,8 +551,8 @@
if (this->peek().fKind == Token::LAYOUT) {
this->nextToken();
if (!this->expect(Token::LPAREN, "'('")) {
- return ASTLayout(location, binding, index, set, builtin, originUpperLeft,
- overrideCoverage, blendSupportAllEquations, format);
+ return ASTLayout(location, binding, index, set, builtin, inputAttachmentIndex,
+ originUpperLeft, overrideCoverage, blendSupportAllEquations, format);
}
for (;;) {
Token t = this->nextToken();
@@ -565,6 +566,8 @@
set = this->layoutInt();
} else if (t.fText == "builtin") {
builtin = this->layoutInt();
+ } else if (t.fText == "input_attachment_index") {
+ inputAttachmentIndex = this->layoutInt();
} else if (t.fText == "origin_upper_left") {
originUpperLeft = true;
} else if (t.fText == "override_coverage") {
@@ -574,7 +577,7 @@
} else if (ASTLayout::ReadFormat(t.fText, &format)) {
// AST::ReadFormat stored the result in 'format'.
} else {
- this->error(t.fPosition, ("'" + t.fText +
+ this->error(t.fPosition, ("'" + t.fText +
"' is not a valid layout qualifier").c_str());
}
if (this->peek().fKind == Token::RPAREN) {
@@ -586,8 +589,8 @@
}
}
}
- return ASTLayout(location, binding, index, set, builtin, originUpperLeft, overrideCoverage,
- blendSupportAllEquations, format);
+ return ASTLayout(location, binding, index, set, builtin, inputAttachmentIndex, originUpperLeft,
+ overrideCoverage, blendSupportAllEquations, format);
}
/* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE)* */
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp
index b5cd54a..300d3c5 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp
@@ -106,9 +106,11 @@
fIntrinsicMap[SkString("texture2D")] = SPECIAL(Texture2D);
fIntrinsicMap[SkString("textureProj")] = SPECIAL(TextureProj);
- fIntrinsicMap[SkString("any")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpUndef,
+ fIntrinsicMap[SkString("subpassLoad")] = SPECIAL(SubpassLoad);
+
+ fIntrinsicMap[SkString("any")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpUndef,
SpvOpUndef, SpvOpUndef, SpvOpAny);
- fIntrinsicMap[SkString("all")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpUndef,
+ fIntrinsicMap[SkString("all")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpUndef,
SpvOpUndef, SpvOpUndef, SpvOpAll);
fIntrinsicMap[SkString("equal")] = std::make_tuple(kSPIRV_IntrinsicKind,
SpvOpFOrdEqual, SpvOpIEqual,
@@ -121,18 +123,18 @@
SpvOpSLessThan, SpvOpULessThan,
SpvOpFOrdLessThan, SpvOpUndef);
fIntrinsicMap[SkString("lessThanEqual")] = std::make_tuple(kSPIRV_IntrinsicKind,
- SpvOpSLessThanEqual,
+ SpvOpSLessThanEqual,
SpvOpULessThanEqual,
SpvOpFOrdLessThanEqual,
SpvOpUndef);
fIntrinsicMap[SkString("greaterThan")] = std::make_tuple(kSPIRV_IntrinsicKind,
- SpvOpSGreaterThan,
+ SpvOpSGreaterThan,
SpvOpUGreaterThan,
- SpvOpFOrdGreaterThan,
+ SpvOpFOrdGreaterThan,
SpvOpUndef);
- fIntrinsicMap[SkString("greaterThanEqual")] = std::make_tuple(kSPIRV_IntrinsicKind,
- SpvOpSGreaterThanEqual,
- SpvOpUGreaterThanEqual,
+ fIntrinsicMap[SkString("greaterThanEqual")] = std::make_tuple(kSPIRV_IntrinsicKind,
+ SpvOpSGreaterThanEqual,
+ SpvOpUGreaterThanEqual,
SpvOpFOrdGreaterThanEqual,
SpvOpUndef);
@@ -869,7 +871,7 @@
}
-void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, const char* string,
+void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, const char* string,
SkWStream& out) {
int32_t length = (int32_t) strlen(string);
this->writeOpCode(opCode, 2 + (length + 4) / 4, out);
@@ -877,7 +879,7 @@
this->writeString(string, out);
}
-void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
+void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
const char* string, SkWStream& out) {
int32_t length = (int32_t) strlen(string);
this->writeOpCode(opCode, 3 + (length + 4) / 4, out);
@@ -886,14 +888,14 @@
this->writeString(string, out);
}
-void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
+void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
SkWStream& out) {
this->writeOpCode(opCode, 3, out);
this->writeWord(word1, out);
this->writeWord(word2, out);
}
-void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
+void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
int32_t word3, SkWStream& out) {
this->writeOpCode(opCode, 4, out);
this->writeWord(word1, out);
@@ -901,7 +903,7 @@
this->writeWord(word3, out);
}
-void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
+void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
int32_t word3, int32_t word4, SkWStream& out) {
this->writeOpCode(opCode, 5, out);
this->writeWord(word1, out);
@@ -910,8 +912,8 @@
this->writeWord(word4, out);
}
-void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
- int32_t word3, int32_t word4, int32_t word5,
+void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
+ int32_t word3, int32_t word4, int32_t word5,
SkWStream& out) {
this->writeOpCode(opCode, 6, out);
this->writeWord(word1, out);
@@ -921,7 +923,7 @@
this->writeWord(word5, out);
}
-void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
+void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
int32_t word3, int32_t word4, int32_t word5,
int32_t word6, SkWStream& out) {
this->writeOpCode(opCode, 7, out);
@@ -933,7 +935,7 @@
this->writeWord(word6, out);
}
-void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
+void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
int32_t word3, int32_t word4, int32_t word5,
int32_t word6, int32_t word7, SkWStream& out) {
this->writeOpCode(opCode, 8, out);
@@ -946,7 +948,7 @@
this->writeWord(word7, out);
}
-void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
+void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
int32_t word3, int32_t word4, int32_t word5,
int32_t word6, int32_t word7, int32_t word8,
SkWStream& out) {
@@ -998,13 +1000,13 @@
fNameBuffer);
this->writeLayout(type.fields()[i].fModifiers.fLayout, resultId, i);
if (type.fields()[i].fModifiers.fLayout.fBuiltin < 0) {
- this->writeInstruction(SpvOpMemberDecorate, resultId, (SpvId) i, SpvDecorationOffset,
+ this->writeInstruction(SpvOpMemberDecorate, resultId, (SpvId) i, SpvDecorationOffset,
(SpvId) offset, fDecorationBuffer);
}
if (type.fields()[i].fType->kind() == Type::kMatrix_Kind) {
- this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorationColMajor,
+ this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorationColMajor,
fDecorationBuffer);
- this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorationMatrixStride,
+ this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorationMatrixStride,
(SpvId) type.fields()[i].fType->stride(), fDecorationBuffer);
}
offset += size;
@@ -1036,13 +1038,13 @@
}
break;
case Type::kVector_Kind:
- this->writeInstruction(SpvOpTypeVector, result,
+ this->writeInstruction(SpvOpTypeVector, result,
this->getType(type.componentType()),
type.columns(), fConstantBuffer);
break;
case Type::kMatrix_Kind:
- this->writeInstruction(SpvOpTypeMatrix, result,
- this->getType(index_type(fContext, type)),
+ this->writeInstruction(SpvOpTypeMatrix, result,
+ this->getType(index_type(fContext, type)),
type.columns(), fConstantBuffer);
break;
case Type::kStruct_Kind:
@@ -1051,25 +1053,30 @@
case Type::kArray_Kind: {
if (type.columns() > 0) {
IntLiteral count(fContext, Position(), type.columns());
- this->writeInstruction(SpvOpTypeArray, result,
- this->getType(type.componentType()),
+ this->writeInstruction(SpvOpTypeArray, result,
+ this->getType(type.componentType()),
this->writeIntLiteral(count), fConstantBuffer);
- this->writeInstruction(SpvOpDecorate, result, SpvDecorationArrayStride,
+ this->writeInstruction(SpvOpDecorate, result, SpvDecorationArrayStride,
(int32_t) type.stride(), fDecorationBuffer);
} else {
ABORT("runtime-sized arrays are not yet supported");
- this->writeInstruction(SpvOpTypeRuntimeArray, result,
+ this->writeInstruction(SpvOpTypeRuntimeArray, result,
this->getType(type.componentType()), fConstantBuffer);
}
break;
}
case Type::kSampler_Kind: {
- SpvId image = this->nextId();
- this->writeInstruction(SpvOpTypeImage, image, this->getType(*fContext.fFloat_Type),
+ SpvId image = result;
+ if (SpvDimSubpassData != type.dimensions()) {
+ image = this->nextId();
+ }
+ this->writeInstruction(SpvOpTypeImage, image, this->getType(*fContext.fFloat_Type),
type.dimensions(), type.isDepth(), type.isArrayed(),
- type.isMultisampled(), type.isSampled(),
+ type.isMultisampled(), type.isSampled() ? 1 : 2,
SpvImageFormatUnknown, fConstantBuffer);
- this->writeInstruction(SpvOpTypeSampledImage, result, image, fConstantBuffer);
+ if (SpvDimSubpassData != type.dimensions()) {
+ this->writeInstruction(SpvOpTypeSampledImage, result, image, fConstantBuffer);
+ }
break;
}
default:
@@ -1101,26 +1108,26 @@
SpvId returnType = this->getType(function.fReturnType);
std::vector<SpvId> parameterTypes;
for (size_t i = 0; i < function.fParameters.size(); i++) {
- // glslang seems to treat all function arguments as pointers whether they need to be or
- // not. I was initially puzzled by this until I ran bizarre failures with certain
- // patterns of function calls and control constructs, as exemplified by this minimal
+ // glslang seems to treat all function arguments as pointers whether they need to be or
+ // not. I was initially puzzled by this until I ran bizarre failures with certain
+ // patterns of function calls and control constructs, as exemplified by this minimal
// failure case:
//
// void sphere(float x) {
// }
- //
+ //
// void map() {
// sphere(1.0);
// }
- //
+ //
// void main() {
// for (int i = 0; i < 1; i++) {
// map();
// }
// }
//
- // As of this writing, compiling this in the "obvious" way (with sphere taking a float)
- // crashes. Making it take a float* and storing the argument in a temporary variable,
+ // As of this writing, compiling this in the "obvious" way (with sphere taking a float)
+ // crashes. Making it take a float* and storing the argument in a temporary variable,
// as glslang does, fixes it. It's entirely possible I simply missed whichever part of
// the spec makes this make sense.
// if (is_out(function->fParameters[i])) {
@@ -1142,13 +1149,13 @@
return entry->second;
}
-SpvId SPIRVCodeGenerator::getPointerType(const Type& type,
+SpvId SPIRVCodeGenerator::getPointerType(const Type& type,
SpvStorageClass_ storageClass) {
SkString key = type.description() + "*" + to_string(storageClass);
auto entry = fTypeMap.find(key);
if (entry == fTypeMap.end()) {
SpvId result = this->nextId();
- this->writeInstruction(SpvOpTypePointer, result, storageClass,
+ this->writeInstruction(SpvOpTypePointer, result, storageClass,
this->getType(type), fConstantBuffer);
fTypeMap[key] = result;
return result;
@@ -1245,7 +1252,7 @@
}
}
-SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(const FunctionCall& c, SpecialIntrinsic kind,
+SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(const FunctionCall& c, SpecialIntrinsic kind,
SkWStream& out) {
SpvId result = this->nextId();
switch (kind) {
@@ -1262,7 +1269,7 @@
for (SpvId id : arguments) {
this->writeWord(id, out);
}
- return result;
+ return result;
}
case kTexture_SpecialIntrinsic: {
SpvId type = this->getType(c.fType);
@@ -1290,7 +1297,7 @@
out);
} else {
ASSERT(c.fArguments.size() == 2);
- this->writeInstruction(SpvOpImageSampleProjImplicitLod, type, result, sampler, uv,
+ this->writeInstruction(SpvOpImageSampleProjImplicitLod, type, result, sampler, uv,
out);
}
break;
@@ -1300,12 +1307,40 @@
SpvId coords = this->writeExpression(*c.fArguments[1], out);
this->writeInstruction(SpvOpImageSampleImplicitLod,
this->getType(c.fType),
- result,
+ result,
img,
coords,
out);
break;
}
+ case kSubpassLoad_SpecialIntrinsic: {
+ SpvId img = this->writeExpression(*c.fArguments[0], out);
+ std::vector<std::unique_ptr<Expression>> args;
+ args.emplace_back(new FloatLiteral(fContext, Position(), 0.0));
+ args.emplace_back(new FloatLiteral(fContext, Position(), 0.0));
+ Constructor ctor(Position(), *fContext.fVec2_Type, std::move(args));
+ SpvId coords = this->writeConstantVector(ctor);
+ if (1 == c.fArguments.size()) {
+ this->writeInstruction(SpvOpImageRead,
+ this->getType(c.fType),
+ result,
+ img,
+ coords,
+ out);
+ } else {
+ SkASSERT(2 == c.fArguments.size());
+ SpvId sample = this->writeExpression(*c.fArguments[1], out);
+ this->writeInstruction(SpvOpImageRead,
+ this->getType(c.fType),
+ result,
+ img,
+ coords,
+ SpvImageOperandsSampleMask,
+ sample,
+ out);
+ }
+ break;
+ }
}
return result;
}
@@ -1319,7 +1354,7 @@
std::vector<std::tuple<SpvId, SpvId, std::unique_ptr<LValue>>> lvalues;
std::vector<SpvId> arguments;
for (size_t i = 0; i < c.fArguments.size(); i++) {
- // id of temporary variable that we will use to hold this argument, or 0 if it is being
+ // id of temporary variable that we will use to hold this argument, or 0 if it is being
// passed directly
SpvId tmpVar;
// if we need a temporary var to store this argument, this is the value to store in the var
@@ -1344,10 +1379,10 @@
tmpValueId = this->writeExpression(*c.fArguments[i], out);
tmpVar = this->nextId();
}
- this->writeInstruction(SpvOpVariable,
- this->getPointerType(c.fArguments[i]->fType,
+ this->writeInstruction(SpvOpVariable,
+ this->getPointerType(c.fArguments[i]->fType,
SpvStorageClassFunction),
- tmpVar,
+ tmpVar,
SpvStorageClassFunction,
fVariableBuffer);
this->writeInstruction(SpvOpStore, tmpVar, tmpValueId, out);
@@ -1388,7 +1423,7 @@
this->writeWord(arguments[0], fConstantBuffer);
}
} else {
- this->writeOpCode(SpvOpConstantComposite, 3 + (int32_t) c.fArguments.size(),
+ this->writeOpCode(SpvOpConstantComposite, 3 + (int32_t) c.fArguments.size(),
fConstantBuffer);
this->writeWord(type, fConstantBuffer);
this->writeWord(result, fConstantBuffer);
@@ -1406,10 +1441,10 @@
SpvId result = this->nextId();
SpvId parameter = this->writeExpression(*c.fArguments[0], out);
if (c.fArguments[0]->fType == *fContext.fInt_Type) {
- this->writeInstruction(SpvOpConvertSToF, this->getType(c.fType), result, parameter,
+ this->writeInstruction(SpvOpConvertSToF, this->getType(c.fType), result, parameter,
out);
} else if (c.fArguments[0]->fType == *fContext.fUInt_Type) {
- this->writeInstruction(SpvOpConvertUToF, this->getType(c.fType), result, parameter,
+ this->writeInstruction(SpvOpConvertUToF, this->getType(c.fType), result, parameter,
out);
} else if (c.fArguments[0]->fType == *fContext.fFloat_Type) {
return parameter;
@@ -1424,10 +1459,10 @@
SpvId result = this->nextId();
SpvId parameter = this->writeExpression(*c.fArguments[0], out);
if (c.fArguments[0]->fType == *fContext.fFloat_Type) {
- this->writeInstruction(SpvOpConvertFToS, this->getType(c.fType), result, parameter,
+ this->writeInstruction(SpvOpConvertFToS, this->getType(c.fType), result, parameter,
out);
} else if (c.fArguments[0]->fType == *fContext.fUInt_Type) {
- this->writeInstruction(SpvOpSatConvertUToS, this->getType(c.fType), result, parameter,
+ this->writeInstruction(SpvOpSatConvertUToS, this->getType(c.fType), result, parameter,
out);
} else if (c.fArguments[0]->fType == *fContext.fInt_Type) {
return parameter;
@@ -1448,16 +1483,16 @@
int columns = c.fType.columns();
// FIXME this won't work to create a matrix from another matrix
if (arguments.size() == 1) {
- // with a single argument, a matrix will have all of its diagonal entries equal to the
+ // with a single argument, a matrix will have all of its diagonal entries equal to the
// argument and its other values equal to zero
// FIXME this won't work for int matrices
FloatLiteral zero(fContext, Position(), 0);
SpvId zeroId = this->writeFloatLiteral(zero);
std::vector<SpvId> columnIds;
for (int column = 0; column < columns; column++) {
- this->writeOpCode(SpvOpCompositeConstruct, 3 + c.fType.rows(),
+ this->writeOpCode(SpvOpCompositeConstruct, 3 + c.fType.rows(),
out);
- this->writeWord(this->getType(c.fType.componentType().toCompound(fContext, rows, 1)),
+ this->writeWord(this->getType(c.fType.componentType().toCompound(fContext, rows, 1)),
out);
SpvId columnId = this->nextId();
this->writeWord(columnId, out);
@@ -1466,7 +1501,7 @@
this->writeWord(row == column ? arguments[0] : zeroId, out);
}
}
- this->writeOpCode(SpvOpCompositeConstruct, 3 + columns,
+ this->writeOpCode(SpvOpCompositeConstruct, 3 + columns,
out);
this->writeWord(this->getType(c.fType), out);
this->writeWord(result, out);
@@ -1485,8 +1520,8 @@
ASSERT(c.fArguments[i]->fType.kind() == Type::kScalar_Kind);
if (currentCount == 0) {
this->writeOpCode(SpvOpCompositeConstruct, 3 + c.fType.rows(), out);
- this->writeWord(this->getType(c.fType.componentType().toCompound(fContext, rows,
- 1)),
+ this->writeWord(this->getType(c.fType.componentType().toCompound(fContext, rows,
+ 1)),
out);
SpvId id = this->nextId();
this->writeWord(id, out);
@@ -1602,7 +1637,7 @@
class PointerLValue : public SPIRVCodeGenerator::LValue {
public:
- PointerLValue(SPIRVCodeGenerator& gen, SpvId pointer, SpvId type)
+ PointerLValue(SPIRVCodeGenerator& gen, SpvId pointer, SpvId type)
: fGen(gen)
, fPointer(pointer)
, fType(type) {}
@@ -1629,7 +1664,7 @@
class SwizzleLValue : public SPIRVCodeGenerator::LValue {
public:
- SwizzleLValue(SPIRVCodeGenerator& gen, SpvId vecPointer, const std::vector<int>& components,
+ SwizzleLValue(SPIRVCodeGenerator& gen, SpvId vecPointer, const std::vector<int>& components,
const Type& baseType, const Type& swizzleType)
: fGen(gen)
, fVecPointer(vecPointer)
@@ -1659,12 +1694,12 @@
virtual void store(SpvId value, SkWStream& out) override {
// use OpVectorShuffle to mix and match the vector components. We effectively create
// a virtual vector out of the concatenation of the left and right vectors, and then
- // select components from this virtual vector to make the result vector. For
+ // select components from this virtual vector to make the result vector. For
// instance, given:
// vec3 L = ...;
// vec3 R = ...;
// L.xz = R.xy;
- // we end up with the virtual vector (L.x, L.y, L.z, R.x, R.y, R.z). Then we want
+ // we end up with the virtual vector (L.x, L.y, L.z, R.x, R.y, R.z). Then we want
// our result vector to look like (R.x, L.y, R.y), so we need to select indices
// (3, 1, 4).
SpvId base = fGen.nextId();
@@ -1682,7 +1717,7 @@
// check to see if we are writing this component
for (size_t j = 0; j < fComponents.size(); j++) {
if (fComponents[j] == i) {
- // we're writing to this component, so adjust the offset to pull from
+ // we're writing to this component, so adjust the offset to pull from
// the correct component of the right side instead of preserving the
// value from the left
offset = (int) (j + fBaseType.columns());
@@ -1702,7 +1737,7 @@
const Type& fSwizzleType;
};
-std::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const Expression& expr,
+std::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const Expression& expr,
SkWStream& out) {
switch (expr.fKind) {
case Expression::kVariableReference_Kind: {
@@ -1711,7 +1746,7 @@
ASSERT(entry != fVariableMap.end());
return std::unique_ptr<SPIRVCodeGenerator::LValue>(new PointerLValue(
*this,
- entry->second,
+ entry->second,
this->getType(expr.fType)));
}
case Expression::kIndex_Kind: // fall through
@@ -1719,14 +1754,14 @@
std::vector<SpvId> chain = this->getAccessChain(expr, out);
SpvId member = this->nextId();
this->writeOpCode(SpvOpAccessChain, (SpvId) (3 + chain.size()), out);
- this->writeWord(this->getPointerType(expr.fType, get_storage_class(expr)), out);
+ this->writeWord(this->getPointerType(expr.fType, get_storage_class(expr)), out);
this->writeWord(member, out);
for (SpvId idx : chain) {
this->writeWord(idx, out);
}
return std::unique_ptr<SPIRVCodeGenerator::LValue>(new PointerLValue(
*this,
- member,
+ member,
this->getType(expr.fType)));
}
@@ -1739,21 +1774,21 @@
IntLiteral index(fContext, Position(), swizzle.fComponents[0]);
SpvId member = this->nextId();
this->writeInstruction(SpvOpAccessChain,
- this->getPointerType(swizzle.fType,
- get_storage_class(*swizzle.fBase)),
- member,
- base,
- this->writeIntLiteral(index),
+ this->getPointerType(swizzle.fType,
+ get_storage_class(*swizzle.fBase)),
+ member,
+ base,
+ this->writeIntLiteral(index),
out);
return std::unique_ptr<SPIRVCodeGenerator::LValue>(new PointerLValue(
*this,
- member,
+ member,
this->getType(expr.fType)));
} else {
return std::unique_ptr<SPIRVCodeGenerator::LValue>(new SwizzleLValue(
- *this,
- base,
- swizzle.fComponents,
+ *this,
+ base,
+ swizzle.fComponents,
swizzle.fBase->fType,
expr.fType));
}
@@ -1761,7 +1796,7 @@
default:
// expr isn't actually an lvalue, create a dummy variable for it. This case happens due
- // to the need to store values in temporary variables during function calls (see
+ // to the need to store values in temporary variables during function calls (see
// comments in getFunctionType); erroneous uses of rvalues as lvalues should have been
// caught by IRGenerator
SpvId result = this->nextId();
@@ -1771,7 +1806,7 @@
this->writeInstruction(SpvOpStore, result, this->writeExpression(expr, out), out);
return std::unique_ptr<SPIRVCodeGenerator::LValue>(new PointerLValue(
*this,
- result,
+ result,
this->getType(expr.fType)));
}
}
@@ -1798,8 +1833,8 @@
SpvId result = this->nextId();
size_t count = swizzle.fComponents.size();
if (count == 1) {
- this->writeInstruction(SpvOpCompositeExtract, this->getType(swizzle.fType), result, base,
- swizzle.fComponents[0], out);
+ this->writeInstruction(SpvOpCompositeExtract, this->getType(swizzle.fType), result, base,
+ swizzle.fComponents[0], out);
} else {
this->writeOpCode(SpvOpVectorShuffle, 5 + (int32_t) count, out);
this->writeWord(this->getType(swizzle.fType), out);
@@ -1813,9 +1848,9 @@
return result;
}
-SpvId SPIRVCodeGenerator::writeBinaryOperation(const Type& resultType,
- const Type& operandType, SpvId lhs,
- SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt,
+SpvId SPIRVCodeGenerator::writeBinaryOperation(const Type& resultType,
+ const Type& operandType, SpvId lhs,
+ SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt,
SpvOp_ ifUInt, SpvOp_ ifBool, SkWStream& out) {
SpvId result = this->nextId();
if (is_float(fContext, operandType)) {
@@ -1887,7 +1922,7 @@
// IR allows mismatched types in expressions (e.g. vec2 * float), but they need special handling
// in SPIR-V
if (b.fLeft->fType != b.fRight->fType) {
- if (b.fLeft->fType.kind() == Type::kVector_Kind &&
+ if (b.fLeft->fType.kind() == Type::kVector_Kind &&
b.fRight->fType.isNumber()) {
// promote number to vector
SpvId vec = this->nextId();
@@ -1899,7 +1934,7 @@
}
rhs = vec;
operandType = &b.fRight->fType;
- } else if (b.fRight->fType.kind() == Type::kVector_Kind &&
+ } else if (b.fRight->fType.kind() == Type::kVector_Kind &&
b.fLeft->fType.isNumber()) {
// promote number to vector
SpvId vec = this->nextId();
@@ -1933,11 +1968,11 @@
} else if (b.fRight->fType.kind() == Type::kMatrix_Kind) {
SpvId result = this->nextId();
if (b.fLeft->fType.kind() == Type::kVector_Kind) {
- this->writeInstruction(SpvOpVectorTimesMatrix, this->getType(b.fType), result,
+ this->writeInstruction(SpvOpVectorTimesMatrix, this->getType(b.fType), result,
lhs, rhs, out);
} else {
ASSERT(b.fLeft->fType.kind() == Type::kScalar_Kind);
- this->writeInstruction(SpvOpMatrixTimesScalar, this->getType(b.fType), result, rhs,
+ this->writeInstruction(SpvOpMatrixTimesScalar, this->getType(b.fType), result, rhs,
lhs, out);
}
if (b.fOperator == Token::STAREQ) {
@@ -1956,40 +1991,40 @@
switch (b.fOperator) {
case Token::EQEQ:
ASSERT(resultType == *fContext.fBool_Type);
- return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFOrdEqual,
+ return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFOrdEqual,
SpvOpIEqual, SpvOpIEqual, SpvOpLogicalEqual, out);
case Token::NEQ:
ASSERT(resultType == *fContext.fBool_Type);
- return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFOrdNotEqual,
- SpvOpINotEqual, SpvOpINotEqual, SpvOpLogicalNotEqual,
+ return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFOrdNotEqual,
+ SpvOpINotEqual, SpvOpINotEqual, SpvOpLogicalNotEqual,
out);
case Token::GT:
ASSERT(resultType == *fContext.fBool_Type);
- return this->writeBinaryOperation(resultType, *operandType, lhs, rhs,
- SpvOpFOrdGreaterThan, SpvOpSGreaterThan,
+ return this->writeBinaryOperation(resultType, *operandType, lhs, rhs,
+ SpvOpFOrdGreaterThan, SpvOpSGreaterThan,
SpvOpUGreaterThan, SpvOpUndef, out);
case Token::LT:
ASSERT(resultType == *fContext.fBool_Type);
- return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFOrdLessThan,
+ return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFOrdLessThan,
SpvOpSLessThan, SpvOpULessThan, SpvOpUndef, out);
case Token::GTEQ:
ASSERT(resultType == *fContext.fBool_Type);
- return this->writeBinaryOperation(resultType, *operandType, lhs, rhs,
- SpvOpFOrdGreaterThanEqual, SpvOpSGreaterThanEqual,
+ return this->writeBinaryOperation(resultType, *operandType, lhs, rhs,
+ SpvOpFOrdGreaterThanEqual, SpvOpSGreaterThanEqual,
SpvOpUGreaterThanEqual, SpvOpUndef, out);
case Token::LTEQ:
ASSERT(resultType == *fContext.fBool_Type);
- return this->writeBinaryOperation(resultType, *operandType, lhs, rhs,
- SpvOpFOrdLessThanEqual, SpvOpSLessThanEqual,
+ return this->writeBinaryOperation(resultType, *operandType, lhs, rhs,
+ SpvOpFOrdLessThanEqual, SpvOpSLessThanEqual,
SpvOpULessThanEqual, SpvOpUndef, out);
case Token::PLUS:
- return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFAdd,
+ return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFAdd,
SpvOpIAdd, SpvOpIAdd, SpvOpUndef, out);
case Token::MINUS:
- return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFSub,
+ return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFSub,
SpvOpISub, SpvOpISub, SpvOpUndef, out);
case Token::STAR:
- if (b.fLeft->fType.kind() == Type::kMatrix_Kind &&
+ if (b.fLeft->fType.kind() == Type::kMatrix_Kind &&
b.fRight->fType.kind() == Type::kMatrix_Kind) {
// matrix multiply
SpvId result = this->nextId();
@@ -1997,27 +2032,27 @@
lhs, rhs, out);
return result;
}
- return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFMul,
+ return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFMul,
SpvOpIMul, SpvOpIMul, SpvOpUndef, out);
case Token::SLASH:
- return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFDiv,
+ return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFDiv,
SpvOpSDiv, SpvOpUDiv, SpvOpUndef, out);
case Token::PLUSEQ: {
- SpvId result = this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFAdd,
+ SpvId result = this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFAdd,
SpvOpIAdd, SpvOpIAdd, SpvOpUndef, out);
ASSERT(lvalue);
lvalue->store(result, out);
return result;
}
case Token::MINUSEQ: {
- SpvId result = this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFSub,
+ SpvId result = this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFSub,
SpvOpISub, SpvOpISub, SpvOpUndef, out);
ASSERT(lvalue);
lvalue->store(result, out);
return result;
}
case Token::STAREQ: {
- if (b.fLeft->fType.kind() == Type::kMatrix_Kind &&
+ if (b.fLeft->fType.kind() == Type::kMatrix_Kind &&
b.fRight->fType.kind() == Type::kMatrix_Kind) {
// matrix multiply
SpvId result = this->nextId();
@@ -2027,14 +2062,14 @@
lvalue->store(result, out);
return result;
}
- SpvId result = this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFMul,
+ SpvId result = this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFMul,
SpvOpIMul, SpvOpIMul, SpvOpUndef, out);
ASSERT(lvalue);
lvalue->store(result, out);
return result;
}
case Token::SLASHEQ: {
- SpvId result = this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFDiv,
+ SpvId result = this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFDiv,
SpvOpSDiv, SpvOpUDiv, SpvOpUndef, out);
ASSERT(lvalue);
lvalue->store(result, out);
@@ -2062,7 +2097,7 @@
this->writeInstruction(SpvOpBranch, end, out);
this->writeLabel(end, out);
SpvId result = this->nextId();
- this->writeInstruction(SpvOpPhi, this->getType(*fContext.fBool_Type), result, falseConstant,
+ this->writeInstruction(SpvOpPhi, this->getType(*fContext.fBool_Type), result, falseConstant,
lhsBlock, rhs, rhsBlock, out);
return result;
}
@@ -2083,7 +2118,7 @@
this->writeInstruction(SpvOpBranch, end, out);
this->writeLabel(end, out);
SpvId result = this->nextId();
- this->writeInstruction(SpvOpPhi, this->getType(*fContext.fBool_Type), result, trueConstant,
+ this->writeInstruction(SpvOpPhi, this->getType(*fContext.fBool_Type), result, trueConstant,
lhsBlock, rhs, rhsBlock, out);
return result;
}
@@ -2095,14 +2130,14 @@
SpvId result = this->nextId();
SpvId trueId = this->writeExpression(*t.fIfTrue, out);
SpvId falseId = this->writeExpression(*t.fIfFalse, out);
- this->writeInstruction(SpvOpSelect, this->getType(t.fType), result, test, trueId, falseId,
+ this->writeInstruction(SpvOpSelect, this->getType(t.fType), result, test, trueId, falseId,
out);
return result;
}
- // was originally using OpPhi to choose the result, but for some reason that is crashing on
+ // was originally using OpPhi to choose the result, but for some reason that is crashing on
// Adreno. Switched to storing the result in a temp variable as glslang does.
SpvId var = this->nextId();
- this->writeInstruction(SpvOpVariable, this->getPointerType(t.fType, SpvStorageClassFunction),
+ this->writeInstruction(SpvOpVariable, this->getPointerType(t.fType, SpvStorageClassFunction),
var, SpvStorageClassFunction, fVariableBuffer);
SpvId trueLabel = this->nextId();
SpvId falseLabel = this->nextId();
@@ -2152,8 +2187,8 @@
case Token::PLUSPLUS: {
std::unique_ptr<LValue> lv = this->getLValue(*p.fOperand, out);
SpvId one = this->writeExpression(*create_literal_1(fContext, p.fType), out);
- SpvId result = this->writeBinaryOperation(p.fType, p.fType, lv->load(out), one,
- SpvOpFAdd, SpvOpIAdd, SpvOpIAdd, SpvOpUndef,
+ SpvId result = this->writeBinaryOperation(p.fType, p.fType, lv->load(out), one,
+ SpvOpFAdd, SpvOpIAdd, SpvOpIAdd, SpvOpUndef,
out);
lv->store(result, out);
return result;
@@ -2161,8 +2196,8 @@
case Token::MINUSMINUS: {
std::unique_ptr<LValue> lv = this->getLValue(*p.fOperand, out);
SpvId one = this->writeExpression(*create_literal_1(fContext, p.fType), out);
- SpvId result = this->writeBinaryOperation(p.fType, p.fType, lv->load(out), one,
- SpvOpFSub, SpvOpISub, SpvOpISub, SpvOpUndef,
+ SpvId result = this->writeBinaryOperation(p.fType, p.fType, lv->load(out), one,
+ SpvOpFSub, SpvOpISub, SpvOpISub, SpvOpUndef,
out);
lv->store(result, out);
return result;
@@ -2191,13 +2226,13 @@
SpvId one = this->writeExpression(*create_literal_1(fContext, p.fType), out);
switch (p.fOperator) {
case Token::PLUSPLUS: {
- SpvId temp = this->writeBinaryOperation(p.fType, p.fType, result, one, SpvOpFAdd,
+ SpvId temp = this->writeBinaryOperation(p.fType, p.fType, result, one, SpvOpFAdd,
SpvOpIAdd, SpvOpIAdd, SpvOpUndef, out);
lv->store(temp, out);
return result;
}
case Token::MINUSMINUS: {
- SpvId temp = this->writeBinaryOperation(p.fType, p.fType, result, one, SpvOpFSub,
+ SpvId temp = this->writeBinaryOperation(p.fType, p.fType, result, one, SpvOpFSub,
SpvOpISub, SpvOpISub, SpvOpUndef, out);
lv->store(temp, out);
return result;
@@ -2211,14 +2246,14 @@
if (b.fValue) {
if (fBoolTrue == 0) {
fBoolTrue = this->nextId();
- this->writeInstruction(SpvOpConstantTrue, this->getType(b.fType), fBoolTrue,
+ this->writeInstruction(SpvOpConstantTrue, this->getType(b.fType), fBoolTrue,
fConstantBuffer);
}
return fBoolTrue;
} else {
if (fBoolFalse == 0) {
fBoolFalse = this->nextId();
- this->writeInstruction(SpvOpConstantFalse, this->getType(b.fType), fBoolFalse,
+ this->writeInstruction(SpvOpConstantFalse, this->getType(b.fType), fBoolFalse,
fConstantBuffer);
}
return fBoolFalse;
@@ -2230,7 +2265,7 @@
auto entry = fIntConstants.find(i.fValue);
if (entry == fIntConstants.end()) {
SpvId result = this->nextId();
- this->writeInstruction(SpvOpConstant, this->getType(i.fType), result, (SpvId) i.fValue,
+ this->writeInstruction(SpvOpConstant, this->getType(i.fType), result, (SpvId) i.fValue,
fConstantBuffer);
fIntConstants[i.fValue] = result;
return result;
@@ -2241,7 +2276,7 @@
auto entry = fUIntConstants.find(i.fValue);
if (entry == fUIntConstants.end()) {
SpvId result = this->nextId();
- this->writeInstruction(SpvOpConstant, this->getType(i.fType), result, (SpvId) i.fValue,
+ this->writeInstruction(SpvOpConstant, this->getType(i.fType), result, (SpvId) i.fValue,
fConstantBuffer);
fUIntConstants[i.fValue] = result;
return result;
@@ -2259,7 +2294,7 @@
uint32_t bits;
ASSERT(sizeof(bits) == sizeof(value));
memcpy(&bits, &value, sizeof(bits));
- this->writeInstruction(SpvOpConstant, this->getType(f.fType), result, bits,
+ this->writeInstruction(SpvOpConstant, this->getType(f.fType), result, bits,
fConstantBuffer);
fFloatConstants[value] = result;
return result;
@@ -2273,7 +2308,7 @@
uint64_t bits;
ASSERT(sizeof(bits) == sizeof(f.fValue));
memcpy(&bits, &f.fValue, sizeof(bits));
- this->writeInstruction(SpvOpConstant, this->getType(f.fType), result,
+ this->writeInstruction(SpvOpConstant, this->getType(f.fType), result,
bits & 0xffffffff, bits >> 32, fConstantBuffer);
fDoubleConstants[f.fValue] = result;
return result;
@@ -2284,7 +2319,7 @@
SpvId SPIRVCodeGenerator::writeFunctionStart(const FunctionDeclaration& f, SkWStream& out) {
SpvId result = fFunctionMap[&f];
- this->writeInstruction(SpvOpFunction, this->getType(f.fReturnType), result,
+ this->writeInstruction(SpvOpFunction, this->getType(f.fReturnType), result,
SpvFunctionControlMaskNone, this->getFunctionType(f), out);
this->writeInstruction(SpvOpName, result, f.fName.c_str(), fNameBuffer);
for (size_t i = 0; i < f.fParameters.size(); i++) {
@@ -2316,46 +2351,54 @@
void SPIRVCodeGenerator::writeLayout(const Layout& layout, SpvId target) {
if (layout.fLocation >= 0) {
- this->writeInstruction(SpvOpDecorate, target, SpvDecorationLocation, layout.fLocation,
+ this->writeInstruction(SpvOpDecorate, target, SpvDecorationLocation, layout.fLocation,
fDecorationBuffer);
}
if (layout.fBinding >= 0) {
- this->writeInstruction(SpvOpDecorate, target, SpvDecorationBinding, layout.fBinding,
+ this->writeInstruction(SpvOpDecorate, target, SpvDecorationBinding, layout.fBinding,
fDecorationBuffer);
}
if (layout.fIndex >= 0) {
- this->writeInstruction(SpvOpDecorate, target, SpvDecorationIndex, layout.fIndex,
+ this->writeInstruction(SpvOpDecorate, target, SpvDecorationIndex, layout.fIndex,
fDecorationBuffer);
}
if (layout.fSet >= 0) {
- this->writeInstruction(SpvOpDecorate, target, SpvDecorationDescriptorSet, layout.fSet,
+ this->writeInstruction(SpvOpDecorate, target, SpvDecorationDescriptorSet, layout.fSet,
fDecorationBuffer);
}
+ if (layout.fInputAttachmentIndex >= 0) {
+ this->writeInstruction(SpvOpDecorate, target, SpvDecorationInputAttachmentIndex,
+ layout.fInputAttachmentIndex, fDecorationBuffer);
+ }
if (layout.fBuiltin >= 0 && layout.fBuiltin != SK_FRAGCOLOR_BUILTIN) {
- this->writeInstruction(SpvOpDecorate, target, SpvDecorationBuiltIn, layout.fBuiltin,
+ this->writeInstruction(SpvOpDecorate, target, SpvDecorationBuiltIn, layout.fBuiltin,
fDecorationBuffer);
}
}
void SPIRVCodeGenerator::writeLayout(const Layout& layout, SpvId target, int member) {
if (layout.fLocation >= 0) {
- this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationLocation,
+ this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationLocation,
layout.fLocation, fDecorationBuffer);
}
if (layout.fBinding >= 0) {
- this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationBinding,
+ this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationBinding,
layout.fBinding, fDecorationBuffer);
}
if (layout.fIndex >= 0) {
- this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationIndex,
+ this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationIndex,
layout.fIndex, fDecorationBuffer);
}
if (layout.fSet >= 0) {
- this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationDescriptorSet,
+ this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationDescriptorSet,
layout.fSet, fDecorationBuffer);
}
+ if (layout.fInputAttachmentIndex >= 0) {
+ this->writeInstruction(SpvOpDecorate, target, member, SpvDecorationInputAttachmentIndex,
+ layout.fInputAttachmentIndex, fDecorationBuffer);
+ }
if (layout.fBuiltin >= 0) {
- this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationBuiltIn,
+ this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationBuiltIn,
layout.fBuiltin, fDecorationBuffer);
}
}
@@ -2374,7 +2417,7 @@
}
#define BUILTIN_IGNORE 9999
-void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclarations& decl,
+void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclarations& decl,
SkWStream& out) {
for (size_t i = 0; i < decl.fVars.size(); i++) {
const VarDeclaration& varDecl = decl.fVars[i];
@@ -2414,9 +2457,9 @@
this->writeInstruction(SpvOpVariable, type, id, storageClass, fConstantBuffer);
this->writeInstruction(SpvOpName, id, var->fName.c_str(), fNameBuffer);
if (var->fType.kind() == Type::kMatrix_Kind) {
- this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecorationColMajor,
+ this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecorationColMajor,
fDecorationBuffer);
- this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecorationMatrixStride,
+ this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecorationMatrixStride,
(SpvId) var->fType.stride(), fDecorationBuffer);
}
if (varDecl.fValue) {
@@ -2453,7 +2496,7 @@
case Statement::kExpression_Kind:
this->writeExpression(*((ExpressionStatement&) s).fExpression, out);
break;
- case Statement::kReturn_Kind:
+ case Statement::kReturn_Kind:
this->writeReturnStatement((ReturnStatement&) s, out);
break;
case Statement::kVarDeclarations_Kind:
@@ -2553,7 +2596,7 @@
void SPIRVCodeGenerator::writeReturnStatement(const ReturnStatement& r, SkWStream& out) {
if (r.fExpression) {
- this->writeInstruction(SpvOpReturnValue, this->writeExpression(*r.fExpression, out),
+ this->writeInstruction(SpvOpReturnValue, this->writeExpression(*r.fExpression, out),
out);
} else {
this->writeInstruction(SpvOpReturn, out);
@@ -2583,7 +2626,7 @@
}
for (size_t i = 0; i < program.fElements.size(); i++) {
if (program.fElements[i]->fKind == ProgramElement::kVar_Kind) {
- this->writeGlobalVars(program.fKind, ((VarDeclarations&) *program.fElements[i]),
+ this->writeGlobalVars(program.fKind, ((VarDeclarations&) *program.fElements[i]),
body);
}
}
@@ -2601,7 +2644,7 @@
ASSERT(main);
for (auto entry : fVariableMap) {
const Variable* var = entry.first;
- if (var->fStorage == Variable::kGlobal_Storage &&
+ if (var->fStorage == Variable::kGlobal_Storage &&
((var->fModifiers.fFlags & Modifiers::kIn_Flag) ||
(var->fModifiers.fFlags & Modifiers::kOut_Flag))) {
interfaceVars.push_back(entry.second);
@@ -2610,7 +2653,7 @@
this->writeCapabilities(out);
this->writeInstruction(SpvOpExtInstImport, fGLSLExtendedInstructions, "GLSL.std.450", out);
this->writeInstruction(SpvOpMemoryModel, SpvAddressingModelLogical, SpvMemoryModelGLSL450, out);
- this->writeOpCode(SpvOpEntryPoint, (SpvId) (3 + (strlen(main->fName.c_str()) + 4) / 4) +
+ this->writeOpCode(SpvOpEntryPoint, (SpvId) (3 + (strlen(main->fName.c_str()) + 4) / 4) +
(int32_t) interfaceVars.size(), out);
switch (program.fKind) {
case Program::kVertex_Kind:
@@ -2626,19 +2669,19 @@
this->writeWord(var, out);
}
if (program.fKind == Program::kFragment_Kind) {
- this->writeInstruction(SpvOpExecutionMode,
- fFunctionMap[main],
+ this->writeInstruction(SpvOpExecutionMode,
+ fFunctionMap[main],
SpvExecutionModeOriginUpperLeft,
out);
}
for (size_t i = 0; i < program.fElements.size(); i++) {
if (program.fElements[i]->fKind == ProgramElement::kExtension_Kind) {
- this->writeInstruction(SpvOpSourceExtension,
- ((Extension&) *program.fElements[i]).fName.c_str(),
+ this->writeInstruction(SpvOpSourceExtension,
+ ((Extension&) *program.fElements[i]).fName.c_str(),
out);
}
}
-
+
write_data(*fNameBuffer.detachAsData(), out);
write_data(*fDecorationBuffer.detachAsData(), out);
write_data(*fConstantBuffer.detachAsData(), out);
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h
index 84c582e..b791945 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.h
+++ b/src/sksl/SkSLSPIRVCodeGenerator.h
@@ -51,7 +51,7 @@
class LValue {
public:
virtual ~LValue() {}
-
+
// returns a pointer to the lvalue, if possible. If the lvalue cannot be directly referenced
// by a pointer (e.g. vector swizzles), returns 0.
virtual SpvId getPointer() = 0;
@@ -84,7 +84,8 @@
kAtan_SpecialIntrinsic,
kTexture_SpecialIntrinsic,
kTexture2D_SpecialIntrinsic,
- kTextureProj_SpecialIntrinsic
+ kTextureProj_SpecialIntrinsic,
+ kSubpassLoad_SpecialIntrinsic,
};
void setupIntrinsics();
diff --git a/src/sksl/ast/SkSLASTLayout.h b/src/sksl/ast/SkSLASTLayout.h
index cb7f3c1..a77e838 100644
--- a/src/sksl/ast/SkSLASTLayout.h
+++ b/src/sksl/ast/SkSLASTLayout.h
@@ -78,13 +78,15 @@
}
// For int parameters, a -1 means no value
- ASTLayout(int location, int binding, int index, int set, int builtin, bool originUpperLeft,
- bool overrideCoverage, bool blendSupportAllEquations, Format format)
+ ASTLayout(int location, int binding, int index, int set, int builtin, int inputAttachmentIndex,
+ bool originUpperLeft, bool overrideCoverage, bool blendSupportAllEquations,
+ Format format)
: fLocation(location)
, fBinding(binding)
, fIndex(index)
, fSet(set)
, fBuiltin(builtin)
+ , fInputAttachmentIndex(inputAttachmentIndex)
, fOriginUpperLeft(originUpperLeft)
, fOverrideCoverage(overrideCoverage)
, fBlendSupportAllEquations(blendSupportAllEquations)
@@ -113,6 +115,10 @@
result += separator + "builtin = " + to_string(fBuiltin);
separator = ", ";
}
+ if (fInputAttachmentIndex >= 0) {
+ result += separator + "input_attachment_index = " + to_string(fBuiltin);
+ separator = ", ";
+ }
if (fOriginUpperLeft) {
result += separator + "origin_upper_left";
separator = ", ";
@@ -140,6 +146,7 @@
const int fIndex;
const int fSet;
const int fBuiltin;
+ const int fInputAttachmentIndex;
const bool fOriginUpperLeft;
const bool fOverrideCoverage;
const bool fBlendSupportAllEquations;
diff --git a/src/sksl/ir/SkSLConstructor.h b/src/sksl/ir/SkSLConstructor.h
index 92f7580..63c692b 100644
--- a/src/sksl/ir/SkSLConstructor.h
+++ b/src/sksl/ir/SkSLConstructor.h
@@ -4,7 +4,7 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-
+
#ifndef SKSL_CONSTRUCTOR
#define SKSL_CONSTRUCTOR
@@ -16,7 +16,7 @@
* Represents the construction of a compound type, such as "vec2(x, y)".
*/
struct Constructor : public Expression {
- Constructor(Position position, const Type& type,
+ Constructor(Position position, const Type& type,
std::vector<std::unique_ptr<Expression>> arguments)
: INHERITED(position, kConstructor_Kind, type)
, fArguments(std::move(arguments)) {}
diff --git a/src/sksl/ir/SkSLLayout.h b/src/sksl/ir/SkSLLayout.h
index 7359262..c5753e0 100644
--- a/src/sksl/ir/SkSLLayout.h
+++ b/src/sksl/ir/SkSLLayout.h
@@ -22,29 +22,33 @@
, fIndex(layout.fIndex)
, fSet(layout.fSet)
, fBuiltin(layout.fBuiltin)
+ , fInputAttachmentIndex(layout.fInputAttachmentIndex)
, fOriginUpperLeft(layout.fOriginUpperLeft)
, fOverrideCoverage(layout.fOverrideCoverage)
, fBlendSupportAllEquations(layout.fBlendSupportAllEquations)
, fFormat(layout.fFormat) {}
- Layout(int location, int binding, int index, int set, int builtin, bool originUpperLeft,
- bool overrideCoverage, bool blendSupportAllEquations, ASTLayout::Format format)
+ Layout(int location, int binding, int index, int set, int builtin, int inputAttachmentIndex,
+ bool originUpperLeft, bool overrideCoverage, bool blendSupportAllEquations,
+ ASTLayout::Format format)
: fLocation(location)
, fBinding(binding)
, fIndex(index)
, fSet(set)
, fBuiltin(builtin)
+ , fInputAttachmentIndex(inputAttachmentIndex)
, fOriginUpperLeft(originUpperLeft)
, fOverrideCoverage(overrideCoverage)
, fBlendSupportAllEquations(blendSupportAllEquations)
, fFormat(format) {}
- Layout()
+ Layout()
: fLocation(-1)
, fBinding(-1)
, fIndex(-1)
, fSet(-1)
, fBuiltin(-1)
+ , fInputAttachmentIndex(-1)
, fOriginUpperLeft(false)
, fOverrideCoverage(false)
, fBlendSupportAllEquations(false)
@@ -73,6 +77,10 @@
result += separator + "builtin = " + to_string(fBuiltin);
separator = ", ";
}
+ if (fInputAttachmentIndex >= 0) {
+ result += separator + "input_attachment_index = " + to_string(fBuiltin);
+ separator = ", ";
+ }
if (fOriginUpperLeft) {
result += separator + "origin_upper_left";
separator = ", ";
@@ -101,6 +109,7 @@
fIndex == other.fIndex &&
fSet == other.fSet &&
fBuiltin == other.fBuiltin &&
+ fInputAttachmentIndex == other.fInputAttachmentIndex &&
fOriginUpperLeft == other.fOriginUpperLeft &&
fOverrideCoverage == other.fOverrideCoverage &&
fBlendSupportAllEquations == other.fBlendSupportAllEquations &&
@@ -111,13 +120,16 @@
return !(*this == other);
}
- // everything but builtin is in the GLSL spec; builtin comes from SPIR-V and identifies which
- // particular builtin value this object represents.
int fLocation;
int fBinding;
int fIndex;
int fSet;
+ // builtin comes from SPIR-V and identifies which particular builtin value this object
+ // represents.
int fBuiltin;
+ // input_attachment_index comes from Vulkan/SPIR-V to connect a shader variable to the a
+ // corresponding attachment on the subpass in which the shader is being used.
+ int fInputAttachmentIndex;
bool fOriginUpperLeft;
bool fOverrideCoverage;
bool fBlendSupportAllEquations;
diff --git a/src/sksl/ir/SkSLType.h b/src/sksl/ir/SkSLType.h
index 4174c72..81ec13a 100644
--- a/src/sksl/ir/SkSLType.h
+++ b/src/sksl/ir/SkSLType.h
@@ -4,7 +4,7 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-
+
#ifndef SKIASL_TYPE
#define SKIASL_TYPE
@@ -51,14 +51,14 @@
kOther_Kind
};
- // Create an "other" (special) type with the given name. These types cannot be directly
+ // Create an "other" (special) type with the given name. These types cannot be directly
// referenced from user code.
Type(SkString name)
: INHERITED(Position(), kType_Kind, std::move(name))
, fTypeKind(kOther_Kind) {}
- // Create a generic type which maps to the listed types. As currently implemented, there are
- // always exactly four coercion targets, mapping to the scalar, vec2, vec3, and vec4 versions of
+ // Create a generic type which maps to the listed types. As currently implemented, there are
+ // always exactly four coercion targets, mapping to the scalar, vec2, vec3, and vec4 versions of
// a type.
Type(SkString name, std::vector<const Type*> types)
: INHERITED(Position(), kType_Kind, std::move(name))
@@ -100,7 +100,7 @@
, fTypeKind(kind)
, fComponentType(&componentType)
, fColumns(columns)
- , fRows(1)
+ , fRows(1)
, fDimensions(SpvDim1D) {}
// Create a matrix type.
@@ -109,12 +109,12 @@
, fTypeKind(kMatrix_Kind)
, fComponentType(&componentType)
, fColumns(columns)
- , fRows(rows)
+ , fRows(rows)
, fDimensions(SpvDim1D) {}
// Create a sampler type.
- Type(SkString name, SpvDim_ dimensions, bool isDepth, bool isArrayed, bool isMultisampled,
- bool isSampled)
+ Type(SkString name, SpvDim_ dimensions, bool isDepth, bool isArrayed, bool isMultisampled,
+ bool isSampled)
: INHERITED(Position(), kType_Kind, std::move(name))
, fTypeKind(kSampler_Kind)
, fDimensions(dimensions)
@@ -154,7 +154,7 @@
}
/**
- * Returns true if an instance of this type can be freely coerced (implicitly converted) to
+ * Returns true if an instance of this type can be freely coerced (implicitly converted) to
* another type.
*/
bool canCoerceTo(const Type& other) const {
@@ -164,8 +164,8 @@
/**
* Determines the "cost" of coercing (implicitly converting) this type to another type. The cost
- * is a number with no particular meaning other than that lower costs are preferable to higher
- * costs. Returns true if a conversion is possible, false otherwise. The value of the out
+ * is a number with no particular meaning other than that lower costs are preferable to higher
+ * costs. Returns true if a conversion is possible, false otherwise. The value of the out
* parameter is undefined if false is returned.
*/
bool determineCoercionCost(const Type& other, int* outCost) const;
@@ -181,11 +181,11 @@
/**
* For matrices and vectors, returns the number of columns (e.g. both mat3 and vec3 return 3).
- * For scalars, returns 1. For arrays, returns either the size of the array (if known) or -1.
+ * For scalars, returns 1. For arrays, returns either the size of the array (if known) or -1.
* For all other types, causes an assertion failure.
*/
int columns() const {
- ASSERT(fTypeKind == kScalar_Kind || fTypeKind == kVector_Kind ||
+ ASSERT(fTypeKind == kScalar_Kind || fTypeKind == kVector_Kind ||
fTypeKind == kMatrix_Kind || fTypeKind == kArray_Kind);
return fColumns;
}
@@ -214,27 +214,27 @@
}
int dimensions() const {
- ASSERT(fTypeKind == kSampler_Kind);
+ ASSERT(kSampler_Kind == fTypeKind);
return fDimensions;
}
bool isDepth() const {
- ASSERT(fTypeKind == kSampler_Kind);
+ ASSERT(kSampler_Kind == fTypeKind);
return fIsDepth;
}
bool isArrayed() const {
- ASSERT(fTypeKind == kSampler_Kind);
+ ASSERT(kSampler_Kind == fTypeKind);
return fIsArrayed;
}
bool isMultisampled() const {
- ASSERT(fTypeKind == kSampler_Kind);
+ ASSERT(kSampler_Kind == fTypeKind);
return fIsMultisampled;
}
bool isSampled() const {
- ASSERT(fTypeKind == kSampler_Kind);
+ ASSERT(kSampler_Kind == fTypeKind);
return fIsSampled;
}
@@ -320,7 +320,7 @@
}
/**
- * Returns the corresponding vector or matrix type with the specified number of columns and
+ * Returns the corresponding vector or matrix type with the specified number of columns and
* rows.
*/
const Type& toCompound(const Context& context, int columns, int rows) const;
diff --git a/src/sksl/sksl.include b/src/sksl/sksl.include
index 83c6aed..d7b6326 100644
--- a/src/sksl/sksl.include
+++ b/src/sksl/sksl.include
@@ -286,6 +286,15 @@
float texture(sampler2DRectShadow sampler, vec3 P);
float texture($gsamplerCubeArrayShadow sampler, vec4 P, float compare);
*/
+
+// Currently we do not support the generic types of loading subpassInput so we have some explicit
+// versions that we currently use
+vec4 subpassLoad(subpassInput subpass);
+vec4 subpassLoad(subpassInputMS subpass, int sample);
+/*
+$gvec4 subpassLoad(gsubpassInput subpass);
+$gvec4 subpassLoad(gsubpassInputMS subpass, int sample);
+*/
)
// split into multiple chunks, as MSVC++ complains if a single string is too long