diff options
-rw-r--r-- | gn/tests.gni | 1 | ||||
-rw-r--r-- | src/sksl/SkSLMemoryLayout.h | 128 | ||||
-rw-r--r-- | src/sksl/SkSLParser.cpp | 11 | ||||
-rw-r--r-- | src/sksl/SkSLSPIRVCodeGenerator.cpp | 57 | ||||
-rw-r--r-- | src/sksl/SkSLSPIRVCodeGenerator.h | 10 | ||||
-rw-r--r-- | src/sksl/ast/SkSLASTLayout.h | 10 | ||||
-rw-r--r-- | src/sksl/ir/SkSLLayout.h | 16 | ||||
-rw-r--r-- | src/sksl/ir/SkSLType.h | 81 | ||||
-rw-r--r-- | tests/SkSLMemoryLayoutTest.cpp | 176 |
9 files changed, 380 insertions, 110 deletions
diff --git a/gn/tests.gni b/gn/tests.gni index 2cf9d330fc..98980ec0f6 100644 --- a/gn/tests.gni +++ b/gn/tests.gni @@ -204,6 +204,7 @@ tests_sources = [ "$_tests/SkSharedMutexTest.cpp", "$_tests/SkSLErrorTest.cpp", "$_tests/SkSLGLSLTest.cpp", + "$_tests/SkSLMemoryLayoutTest.cpp", "$_tests/SmallAllocatorTest.cpp", "$_tests/SortTest.cpp", "$_tests/SpecialImageTest.cpp", diff --git a/src/sksl/SkSLMemoryLayout.h b/src/sksl/SkSLMemoryLayout.h new file mode 100644 index 0000000000..95a292f9d9 --- /dev/null +++ b/src/sksl/SkSLMemoryLayout.h @@ -0,0 +1,128 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SKIASL_MEMORYLAYOUT +#define SKIASL_MEMORYLAYOUT + +#include "ir/SkSLType.h" + +namespace SkSL { + +class MemoryLayout { +public: + enum Standard { + k140_Standard, + k430_Standard + }; + + MemoryLayout(Standard std) + : fStd(std) {} + + static size_t vector_alignment(size_t componentSize, int columns) { + return componentSize * (columns + columns % 2); + } + + /** + * Rounds up to the nearest multiple of 16 if in std140, otherwise returns the parameter + * unchanged (std140 requires various things to be rounded up to the nearest multiple of 16, + * std430 does not). + */ + size_t roundUpIfNeeded(size_t raw) const { + switch (fStd) { + case k140_Standard: return (raw + 15) & ~15; + case k430_Standard: return raw; + } + ABORT("unreachable"); + } + + /** + * Returns a type's required alignment when used as a standalone variable. + */ + size_t alignment(const Type& type) const { + // See OpenGL Spec 7.6.2.2 Standard Uniform Block Layout + switch (type.kind()) { + case Type::kScalar_Kind: + return this->size(type); + case Type::kVector_Kind: + return vector_alignment(this->size(type.componentType()), type.columns()); + case Type::kMatrix_Kind: + return this->roundUpIfNeeded(vector_alignment(this->size(type.componentType()), + type.rows())); + case Type::kArray_Kind: + return this->roundUpIfNeeded(this->alignment(type.componentType())); + case Type::kStruct_Kind: { + size_t result = 0; + for (const auto& f : type.fields()) { + size_t alignment = this->alignment(*f.fType); + if (alignment > result) { + result = alignment; + } + } + return this->roundUpIfNeeded(result); + } + default: + ABORT(("cannot determine size of type " + type.name()).c_str()); + } + } + + /** + * For matrices and arrays, returns the number of bytes from the start of one entry (row, in + * the case of matrices) to the start of the next. + */ + size_t stride(const Type& type) const { + switch (type.kind()) { + case Type::kMatrix_Kind: // fall through + case Type::kArray_Kind: + return this->alignment(type); + default: + ABORT("type does not have a stride"); + } + } + + /** + * Returns the size of a type in bytes. + */ + size_t size(const Type& type) const { + switch (type.kind()) { + case Type::kScalar_Kind: + if (type.name() == "bool") { + return 1; + } + // FIXME need to take precision into account, once we figure out how we want to + // handle it... + return 4; + case Type::kVector_Kind: + return type.columns() * this->size(type.componentType()); + case Type::kMatrix_Kind: // fall through + case Type::kArray_Kind: + return type.columns() * this->stride(type); + case Type::kStruct_Kind: { + size_t total = 0; + for (const auto& f : type.fields()) { + size_t alignment = this->alignment(*f.fType); + if (total % alignment != 0) { + total += alignment - total % alignment; + } + ASSERT(total % alignment == 0); + total += this->size(*f.fType); + } + size_t alignment = this->alignment(type); + ASSERT(!type.fields().size() || + (0 == alignment % this->alignment(*type.fields()[0].fType))); + return (total + alignment - 1) & ~(alignment - 1); + } + default: + ABORT(("cannot determine size of type " + type.name()).c_str()); + } + } + + const Standard fStd; +}; + +} // namespace + +#endif diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp index 58ec750168..80ef870a48 100644 --- a/src/sksl/SkSLParser.cpp +++ b/src/sksl/SkSLParser.cpp @@ -535,8 +535,7 @@ int Parser::layoutInt() { return -1; } -/* LAYOUT LPAREN IDENTIFIER EQ INT_LITERAL (COMMA IDENTIFIER EQ INT_LITERAL)* - RPAREN */ +/* LAYOUT LPAREN IDENTIFIER (EQ INT_LITERAL)? (COMMA IDENTIFIER (EQ INT_LITERAL)?)* RPAREN */ ASTLayout Parser::layout() { int location = -1; int binding = -1; @@ -548,11 +547,13 @@ ASTLayout Parser::layout() { bool overrideCoverage = false; bool blendSupportAllEquations = false; ASTLayout::Format format = ASTLayout::Format::kUnspecified; + bool pushConstant = false; if (this->peek().fKind == Token::LAYOUT) { this->nextToken(); if (!this->expect(Token::LPAREN, "'('")) { return ASTLayout(location, binding, index, set, builtin, inputAttachmentIndex, - originUpperLeft, overrideCoverage, blendSupportAllEquations, format); + originUpperLeft, overrideCoverage, blendSupportAllEquations, format, + pushConstant); } for (;;) { Token t = this->nextToken(); @@ -576,6 +577,8 @@ ASTLayout Parser::layout() { blendSupportAllEquations = true; } else if (ASTLayout::ReadFormat(t.fText, &format)) { // AST::ReadFormat stored the result in 'format'. + } else if (t.fText == "push_constant") { + pushConstant = true; } else { this->error(t.fPosition, ("'" + t.fText + "' is not a valid layout qualifier").c_str()); @@ -590,7 +593,7 @@ ASTLayout Parser::layout() { } } return ASTLayout(location, binding, index, set, builtin, inputAttachmentIndex, originUpperLeft, - overrideCoverage, blendSupportAllEquations, format); + overrideCoverage, blendSupportAllEquations, format, pushConstant); } /* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE)* */ diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp index 300d3c5d66..ecde11509d 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.cpp +++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp @@ -975,13 +975,13 @@ SpvId SPIRVCodeGenerator::nextId() { return fIdCount++; } -void SPIRVCodeGenerator::writeStruct(const Type& type, SpvId resultId) { +void SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& layout, SpvId resultId) { this->writeInstruction(SpvOpName, resultId, type.name().c_str(), fNameBuffer); // go ahead and write all of the field types, so we don't inadvertently write them while we're // in the middle of writing the struct instruction std::vector<SpvId> types; for (const auto& f : type.fields()) { - types.push_back(this->getType(*f.fType)); + types.push_back(this->getType(*f.fType, layout)); } this->writeOpCode(SpvOpTypeStruct, 2 + (int32_t) types.size(), fConstantBuffer); this->writeWord(resultId, fConstantBuffer); @@ -990,8 +990,8 @@ void SPIRVCodeGenerator::writeStruct(const Type& type, SpvId resultId) { } size_t offset = 0; for (int32_t i = 0; i < (int32_t) type.fields().size(); i++) { - size_t size = type.fields()[i].fType->size(); - size_t alignment = type.fields()[i].fType->alignment(); + size_t size = layout.size(*type.fields()[i].fType); + size_t alignment = layout.alignment(*type.fields()[i].fType); size_t mod = offset % alignment; if (mod != 0) { offset += alignment - mod; @@ -1007,7 +1007,8 @@ void SPIRVCodeGenerator::writeStruct(const Type& type, SpvId resultId) { this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorationColMajor, fDecorationBuffer); this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorationMatrixStride, - (SpvId) type.fields()[i].fType->stride(), fDecorationBuffer); + (SpvId) layout.stride(*type.fields()[i].fType), + fDecorationBuffer); } offset += size; Type::Kind kind = type.fields()[i].fType->kind(); @@ -1018,7 +1019,12 @@ void SPIRVCodeGenerator::writeStruct(const Type& type, SpvId resultId) { } SpvId SPIRVCodeGenerator::getType(const Type& type) { - auto entry = fTypeMap.find(type.name()); + return this->getType(type, fDefaultLayout); +} + +SpvId SPIRVCodeGenerator::getType(const Type& type, const MemoryLayout& layout) { + SkString key = type.name() + to_string((int) layout.fStd); + auto entry = fTypeMap.find(key); if (entry == fTypeMap.end()) { SpvId result = this->nextId(); switch (type.kind()) { @@ -1039,29 +1045,31 @@ SpvId SPIRVCodeGenerator::getType(const Type& type) { break; case Type::kVector_Kind: this->writeInstruction(SpvOpTypeVector, result, - this->getType(type.componentType()), + this->getType(type.componentType(), layout), type.columns(), fConstantBuffer); break; case Type::kMatrix_Kind: this->writeInstruction(SpvOpTypeMatrix, result, - this->getType(index_type(fContext, type)), + this->getType(index_type(fContext, type), layout), type.columns(), fConstantBuffer); break; case Type::kStruct_Kind: - this->writeStruct(type, result); + this->writeStruct(type, layout, result); break; case Type::kArray_Kind: { if (type.columns() > 0) { IntLiteral count(fContext, Position(), type.columns()); this->writeInstruction(SpvOpTypeArray, result, - this->getType(type.componentType()), + this->getType(type.componentType(), layout), this->writeIntLiteral(count), fConstantBuffer); this->writeInstruction(SpvOpDecorate, result, SpvDecorationArrayStride, - (int32_t) type.stride(), fDecorationBuffer); + (int32_t) layout.stride(type), + fDecorationBuffer); } else { ABORT("runtime-sized arrays are not yet supported"); this->writeInstruction(SpvOpTypeRuntimeArray, result, - this->getType(type.componentType()), fConstantBuffer); + this->getType(type.componentType(), layout), + fConstantBuffer); } break; } @@ -1070,7 +1078,8 @@ SpvId SPIRVCodeGenerator::getType(const Type& type) { if (SpvDimSubpassData != type.dimensions()) { image = this->nextId(); } - this->writeInstruction(SpvOpTypeImage, image, this->getType(*fContext.fFloat_Type), + this->writeInstruction(SpvOpTypeImage, image, + this->getType(*fContext.fFloat_Type, layout), type.dimensions(), type.isDepth(), type.isArrayed(), type.isMultisampled(), type.isSampled() ? 1 : 2, SpvImageFormatUnknown, fConstantBuffer); @@ -1086,7 +1095,7 @@ SpvId SPIRVCodeGenerator::getType(const Type& type) { ABORT("invalid type: %s", type.description().c_str()); } } - fTypeMap[type.name()] = result; + fTypeMap[key] = result; return result; } return entry->second; @@ -1149,9 +1158,13 @@ SpvId SPIRVCodeGenerator::getFunctionType(const FunctionDeclaration& function) { return entry->second; } -SpvId SPIRVCodeGenerator::getPointerType(const Type& type, +SpvId SPIRVCodeGenerator::getPointerType(const Type& type, SpvStorageClass_ storageClass) { + return this->getPointerType(type, fDefaultLayout, storageClass); +} + +SpvId SPIRVCodeGenerator::getPointerType(const Type& type, const MemoryLayout& layout, SpvStorageClass_ storageClass) { - SkString key = type.description() + "*" + to_string(storageClass); + SkString key = type.description() + "*" + to_string(layout.fStd) + to_string(storageClass); auto entry = fTypeMap.find(key); if (entry == fTypeMap.end()) { SpvId result = this->nextId(); @@ -1590,10 +1603,15 @@ SpvId SPIRVCodeGenerator::writeConstructor(const Constructor& c, SkWStream& out) SpvStorageClass_ get_storage_class(const Modifiers& modifiers) { if (modifiers.fFlags & Modifiers::kIn_Flag) { + ASSERT(!modifiers.fLayout.fPushConstant); return SpvStorageClassInput; } else if (modifiers.fFlags & Modifiers::kOut_Flag) { + ASSERT(!modifiers.fLayout.fPushConstant); return SpvStorageClassOutput; } else if (modifiers.fFlags & Modifiers::kUniform_Flag) { + if (modifiers.fLayout.fPushConstant) { + return SpvStorageClassPushConstant; + } return SpvStorageClassUniform; } else { return SpvStorageClassFunction; @@ -2404,7 +2422,10 @@ void SPIRVCodeGenerator::writeLayout(const Layout& layout, SpvId target, int mem } SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { - SpvId type = this->getType(intf.fVariable.fType); + MemoryLayout layout = intf.fVariable.fModifiers.fLayout.fPushConstant ? + MemoryLayout(MemoryLayout::k430_Standard) : + fDefaultLayout; + SpvId type = this->getType(intf.fVariable.fType, layout); SpvId result = this->nextId(); this->writeInstruction(SpvOpDecorate, type, SpvDecorationBlock, fDecorationBuffer); SpvStorageClass_ storageClass = get_storage_class(intf.fVariable.fModifiers); @@ -2460,7 +2481,7 @@ void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclaratio this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecorationColMajor, fDecorationBuffer); this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecorationMatrixStride, - (SpvId) var->fType.stride(), fDecorationBuffer); + (SpvId) fDefaultLayout.stride(var->fType), fDecorationBuffer); } if (varDecl.fValue) { ASSERT(!fCurrentBlock); diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h index b79194500a..c885ffc3ff 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.h +++ b/src/sksl/SkSLSPIRVCodeGenerator.h @@ -14,6 +14,7 @@ #include "SkStream.h" #include "SkSLCodeGenerator.h" +#include "SkSLMemoryLayout.h" #include "ir/SkSLBinaryExpression.h" #include "ir/SkSLBoolLiteral.h" #include "ir/SkSLConstructor.h" @@ -63,6 +64,7 @@ public: SPIRVCodeGenerator(const Context* context) : fContext(*context) + , fDefaultLayout(MemoryLayout::k140_Standard) , fCapabilities(1 << SpvCapabilityShader) , fIdCount(1) , fBoolTrue(0) @@ -94,17 +96,22 @@ private: SpvId getType(const Type& type); + SpvId getType(const Type& type, const MemoryLayout& layout); + SpvId getFunctionType(const FunctionDeclaration& function); SpvId getPointerType(const Type& type, SpvStorageClass_ storageClass); + SpvId getPointerType(const Type& type, const MemoryLayout& layout, + SpvStorageClass_ storageClass); + std::vector<SpvId> getAccessChain(const Expression& expr, SkWStream& out); void writeLayout(const Layout& layout, SpvId target); void writeLayout(const Layout& layout, SpvId target, int member); - void writeStruct(const Type& type, SpvId resultId); + void writeStruct(const Type& type, const MemoryLayout& layout, SpvId resultId); void writeProgramElement(const ProgramElement& pe, SkWStream& out); @@ -230,6 +237,7 @@ private: SkWStream& out); const Context& fContext; + const MemoryLayout fDefaultLayout; uint64_t fCapabilities; SpvId fIdCount; diff --git a/src/sksl/ast/SkSLASTLayout.h b/src/sksl/ast/SkSLASTLayout.h index a77e8388ed..4c36af46a1 100644 --- a/src/sksl/ast/SkSLASTLayout.h +++ b/src/sksl/ast/SkSLASTLayout.h @@ -80,7 +80,7 @@ struct ASTLayout : public ASTNode { // For int parameters, a -1 means no value ASTLayout(int location, int binding, int index, int set, int builtin, int inputAttachmentIndex, bool originUpperLeft, bool overrideCoverage, bool blendSupportAllEquations, - Format format) + Format format, bool pushConstant) : fLocation(location) , fBinding(binding) , fIndex(index) @@ -90,7 +90,8 @@ struct ASTLayout : public ASTNode { , fOriginUpperLeft(originUpperLeft) , fOverrideCoverage(overrideCoverage) , fBlendSupportAllEquations(blendSupportAllEquations) - , fFormat(format) {} + , fFormat(format) + , fPushConstant(pushConstant) {} SkString description() const { SkString result; @@ -135,6 +136,10 @@ struct ASTLayout : public ASTNode { result += separator + FormatToStr(fFormat); separator = ", "; } + if (fPushConstant) { + result += separator + "push_constant"; + separator = ", "; + } if (result.size() > 0) { result = "layout (" + result + ")"; } @@ -151,6 +156,7 @@ struct ASTLayout : public ASTNode { const bool fOverrideCoverage; const bool fBlendSupportAllEquations; const Format fFormat; + const bool fPushConstant; }; } // namespace diff --git a/src/sksl/ir/SkSLLayout.h b/src/sksl/ir/SkSLLayout.h index c5753e010c..f433614da9 100644 --- a/src/sksl/ir/SkSLLayout.h +++ b/src/sksl/ir/SkSLLayout.h @@ -26,11 +26,12 @@ struct Layout { , fOriginUpperLeft(layout.fOriginUpperLeft) , fOverrideCoverage(layout.fOverrideCoverage) , fBlendSupportAllEquations(layout.fBlendSupportAllEquations) - , fFormat(layout.fFormat) {} + , fFormat(layout.fFormat) + , fPushConstant(layout.fPushConstant) {} Layout(int location, int binding, int index, int set, int builtin, int inputAttachmentIndex, bool originUpperLeft, bool overrideCoverage, bool blendSupportAllEquations, - ASTLayout::Format format) + ASTLayout::Format format, bool pushconstant) : fLocation(location) , fBinding(binding) , fIndex(index) @@ -40,7 +41,8 @@ struct Layout { , fOriginUpperLeft(originUpperLeft) , fOverrideCoverage(overrideCoverage) , fBlendSupportAllEquations(blendSupportAllEquations) - , fFormat(format) {} + , fFormat(format) + , fPushConstant(pushconstant) {} Layout() : fLocation(-1) @@ -52,7 +54,8 @@ struct Layout { , fOriginUpperLeft(false) , fOverrideCoverage(false) , fBlendSupportAllEquations(false) - , fFormat(ASTLayout::Format::kUnspecified) {} + , fFormat(ASTLayout::Format::kUnspecified) + , fPushConstant(false) {} SkString description() const { SkString result; @@ -97,6 +100,10 @@ struct Layout { result += separator + ASTLayout::FormatToStr(fFormat); separator = ", "; } + if (fPushConstant) { + result += separator + "push_constant"; + separator = ", "; + } if (result.size() > 0) { result = "layout (" + result + ")"; } @@ -134,6 +141,7 @@ struct Layout { bool fOverrideCoverage; bool fBlendSupportAllEquations; ASTLayout::Format fFormat; + bool fPushConstant; }; } // namespace diff --git a/src/sksl/ir/SkSLType.h b/src/sksl/ir/SkSLType.h index 81ec13ab44..a4632061ae 100644 --- a/src/sksl/ir/SkSLType.h +++ b/src/sksl/ir/SkSLType.h @@ -238,87 +238,6 @@ public: return fIsSampled; } - static size_t vector_alignment(size_t componentSize, int columns) { - return componentSize * (columns + columns % 2); - } - - /** - * Returns the type's required alignment (when putting this type into a struct, the offset must - * be a multiple of the alignment). - */ - size_t alignment() const { - // See OpenGL Spec 7.6.2.2 Standard Uniform Block Layout - switch (fTypeKind) { - case kScalar_Kind: - return this->size(); - case kVector_Kind: - return vector_alignment(fComponentType->size(), fColumns); - case kMatrix_Kind: - return (vector_alignment(fComponentType->size(), fRows) + 15) & ~15; - case kArray_Kind: - // round up to next multiple of 16 - return (fComponentType->alignment() + 15) & ~15; - case kStruct_Kind: { - size_t result = 16; - for (size_t i = 0; i < fFields.size(); i++) { - size_t alignment = fFields[i].fType->alignment(); - if (alignment > result) { - result = alignment; - } - } - } - default: - ABORT(("cannot determine size of type " + fName).c_str()); - } - } - - /** - * For matrices and arrays, returns the number of bytes from the start of one entry (row, in - * the case of matrices) to the start of the next. - */ - size_t stride() const { - switch (fTypeKind) { - case kMatrix_Kind: // fall through - case kArray_Kind: - return this->alignment(); - default: - ABORT("type does not have a stride"); - } - } - - /** - * Returns the size of this type in bytes. - */ - size_t size() const { - switch (fTypeKind) { - case kScalar_Kind: - // FIXME need to take precision into account, once we figure out how we want to - // handle it... - return 4; - case kVector_Kind: - return fColumns * fComponentType->size(); - case kMatrix_Kind: - return vector_alignment(fComponentType->size(), fRows) * fColumns; - case kArray_Kind: - return fColumns * this->stride(); - case kStruct_Kind: { - size_t total = 0; - for (size_t i = 0; i < fFields.size(); i++) { - size_t alignment = fFields[i].fType->alignment(); - if (total % alignment != 0) { - total += alignment - total % alignment; - } - ASSERT(false); - ASSERT(total % alignment == 0); - total += fFields[i].fType->size(); - } - return total; - } - default: - ABORT(("cannot determine size of type " + fName).c_str()); - } - } - /** * Returns the corresponding vector or matrix type with the specified number of columns and * rows. diff --git a/tests/SkSLMemoryLayoutTest.cpp b/tests/SkSLMemoryLayoutTest.cpp new file mode 100644 index 0000000000..336d8aa477 --- /dev/null +++ b/tests/SkSLMemoryLayoutTest.cpp @@ -0,0 +1,176 @@ +/* + * 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 "SkSLContext.h" +#include "SkSLMemoryLayout.h" + +#include "Test.h" + +#if SK_SUPPORT_GPU + +DEF_TEST(SkSLMemoryLayout140Test, r) { + SkSL::Context context; + SkSL::MemoryLayout layout(SkSL::MemoryLayout::k140_Standard); + + // basic types + REPORTER_ASSERT(r, 4 == layout.size(*context.fFloat_Type)); + REPORTER_ASSERT(r, 8 == layout.size(*context.fVec2_Type)); + REPORTER_ASSERT(r, 12 == layout.size(*context.fVec3_Type)); + REPORTER_ASSERT(r, 16 == layout.size(*context.fVec4_Type)); + REPORTER_ASSERT(r, 4 == layout.size(*context.fInt_Type)); + REPORTER_ASSERT(r, 8 == layout.size(*context.fIVec2_Type)); + REPORTER_ASSERT(r, 12 == layout.size(*context.fIVec3_Type)); + REPORTER_ASSERT(r, 16 == layout.size(*context.fIVec4_Type)); + REPORTER_ASSERT(r, 1 == layout.size(*context.fBool_Type)); + REPORTER_ASSERT(r, 2 == layout.size(*context.fBVec2_Type)); + REPORTER_ASSERT(r, 3 == layout.size(*context.fBVec3_Type)); + REPORTER_ASSERT(r, 4 == layout.size(*context.fBVec4_Type)); + REPORTER_ASSERT(r, 32 == layout.size(*context.fMat2x2_Type)); + REPORTER_ASSERT(r, 32 == layout.size(*context.fMat2x4_Type)); + REPORTER_ASSERT(r, 48 == layout.size(*context.fMat3x3_Type)); + REPORTER_ASSERT(r, 64 == layout.size(*context.fMat4x2_Type)); + REPORTER_ASSERT(r, 64 == layout.size(*context.fMat4x4_Type)); + REPORTER_ASSERT(r, 4 == layout.alignment(*context.fFloat_Type)); + REPORTER_ASSERT(r, 8 == layout.alignment(*context.fVec2_Type)); + REPORTER_ASSERT(r, 16 == layout.alignment(*context.fVec3_Type)); + REPORTER_ASSERT(r, 16 == layout.alignment(*context.fVec4_Type)); + REPORTER_ASSERT(r, 4 == layout.alignment(*context.fInt_Type)); + REPORTER_ASSERT(r, 8 == layout.alignment(*context.fIVec2_Type)); + REPORTER_ASSERT(r, 16 == layout.alignment(*context.fIVec3_Type)); + REPORTER_ASSERT(r, 16 == layout.alignment(*context.fIVec4_Type)); + REPORTER_ASSERT(r, 1 == layout.alignment(*context.fBool_Type)); + REPORTER_ASSERT(r, 2 == layout.alignment(*context.fBVec2_Type)); + REPORTER_ASSERT(r, 4 == layout.alignment(*context.fBVec3_Type)); + REPORTER_ASSERT(r, 4 == layout.alignment(*context.fBVec4_Type)); + REPORTER_ASSERT(r, 16 == layout.alignment(*context.fMat2x2_Type)); + REPORTER_ASSERT(r, 16 == layout.alignment(*context.fMat2x4_Type)); + REPORTER_ASSERT(r, 16 == layout.alignment(*context.fMat3x3_Type)); + REPORTER_ASSERT(r, 16 == layout.alignment(*context.fMat4x2_Type)); + REPORTER_ASSERT(r, 16 == layout.alignment(*context.fMat4x4_Type)); + + // struct 1 + std::vector<SkSL::Type::Field> fields1; + fields1.emplace_back(SkSL::Modifiers(), SkString("a"), context.fVec3_Type.get()); + SkSL::Type s1(SkString("s1"), fields1); + REPORTER_ASSERT(r, 16 == layout.size(s1)); + REPORTER_ASSERT(r, 16 == layout.alignment(s1)); + + fields1.emplace_back(SkSL::Modifiers(), SkString("b"), context.fFloat_Type.get()); + SkSL::Type s2(SkString("s2"), fields1); + REPORTER_ASSERT(r, 16 == layout.size(s2)); + REPORTER_ASSERT(r, 16 == layout.alignment(s2)); + + fields1.emplace_back(SkSL::Modifiers(), SkString("c"), context.fBool_Type.get()); + SkSL::Type s3(SkString("s3"), fields1); + REPORTER_ASSERT(r, 32 == layout.size(s3)); + REPORTER_ASSERT(r, 16 == layout.alignment(s3)); + + // struct 2 + std::vector<SkSL::Type::Field> fields2; + fields2.emplace_back(SkSL::Modifiers(), SkString("a"), context.fInt_Type.get()); + SkSL::Type s4(SkString("s4"), fields2); + REPORTER_ASSERT(r, 16 == layout.size(s4)); + REPORTER_ASSERT(r, 16 == layout.alignment(s4)); + + fields2.emplace_back(SkSL::Modifiers(), SkString("b"), context.fVec3_Type.get()); + SkSL::Type s5(SkString("s5"), fields2); + REPORTER_ASSERT(r, 32 == layout.size(s5)); + REPORTER_ASSERT(r, 16 == layout.alignment(s5)); + + // arrays + SkSL::Type array1(SkString("float[4]"), SkSL::Type::kArray_Kind, *context.fFloat_Type, 4); + REPORTER_ASSERT(r, 64 == layout.size(array1)); + REPORTER_ASSERT(r, 16 == layout.alignment(array1)); + REPORTER_ASSERT(r, 16 == layout.stride(array1)); + + SkSL::Type array2(SkString("vec4[4]"), SkSL::Type::kArray_Kind, *context.fVec4_Type, 4); + REPORTER_ASSERT(r, 64 == layout.size(array2)); + REPORTER_ASSERT(r, 16 == layout.alignment(array2)); + REPORTER_ASSERT(r, 16 == layout.stride(array2)); +} + +DEF_TEST(SkSLMemoryLayout430Test, r) { + SkSL::Context context; + SkSL::MemoryLayout layout(SkSL::MemoryLayout::k430_Standard); + + // basic types + REPORTER_ASSERT(r, 4 == layout.size(*context.fFloat_Type)); + REPORTER_ASSERT(r, 8 == layout.size(*context.fVec2_Type)); + REPORTER_ASSERT(r, 12 == layout.size(*context.fVec3_Type)); + REPORTER_ASSERT(r, 16 == layout.size(*context.fVec4_Type)); + REPORTER_ASSERT(r, 4 == layout.size(*context.fInt_Type)); + REPORTER_ASSERT(r, 8 == layout.size(*context.fIVec2_Type)); + REPORTER_ASSERT(r, 12 == layout.size(*context.fIVec3_Type)); + REPORTER_ASSERT(r, 16 == layout.size(*context.fIVec4_Type)); + REPORTER_ASSERT(r, 1 == layout.size(*context.fBool_Type)); + REPORTER_ASSERT(r, 2 == layout.size(*context.fBVec2_Type)); + REPORTER_ASSERT(r, 3 == layout.size(*context.fBVec3_Type)); + REPORTER_ASSERT(r, 4 == layout.size(*context.fBVec4_Type)); + REPORTER_ASSERT(r, 16 == layout.size(*context.fMat2x2_Type)); + REPORTER_ASSERT(r, 32 == layout.size(*context.fMat2x4_Type)); + REPORTER_ASSERT(r, 48 == layout.size(*context.fMat3x3_Type)); + REPORTER_ASSERT(r, 32 == layout.size(*context.fMat4x2_Type)); + REPORTER_ASSERT(r, 64 == layout.size(*context.fMat4x4_Type)); + REPORTER_ASSERT(r, 4 == layout.alignment(*context.fFloat_Type)); + REPORTER_ASSERT(r, 8 == layout.alignment(*context.fVec2_Type)); + REPORTER_ASSERT(r, 16 == layout.alignment(*context.fVec3_Type)); + REPORTER_ASSERT(r, 16 == layout.alignment(*context.fVec4_Type)); + REPORTER_ASSERT(r, 4 == layout.alignment(*context.fInt_Type)); + REPORTER_ASSERT(r, 8 == layout.alignment(*context.fIVec2_Type)); + REPORTER_ASSERT(r, 16 == layout.alignment(*context.fIVec3_Type)); + REPORTER_ASSERT(r, 16 == layout.alignment(*context.fIVec4_Type)); + REPORTER_ASSERT(r, 1 == layout.alignment(*context.fBool_Type)); + REPORTER_ASSERT(r, 2 == layout.alignment(*context.fBVec2_Type)); + REPORTER_ASSERT(r, 4 == layout.alignment(*context.fBVec3_Type)); + REPORTER_ASSERT(r, 4 == layout.alignment(*context.fBVec4_Type)); + REPORTER_ASSERT(r, 8 == layout.alignment(*context.fMat2x2_Type)); + REPORTER_ASSERT(r, 16 == layout.alignment(*context.fMat2x4_Type)); + REPORTER_ASSERT(r, 16 == layout.alignment(*context.fMat3x3_Type)); + REPORTER_ASSERT(r, 8 == layout.alignment(*context.fMat4x2_Type)); + REPORTER_ASSERT(r, 16 == layout.alignment(*context.fMat4x4_Type)); + + // struct 1 + std::vector<SkSL::Type::Field> fields1; + fields1.emplace_back(SkSL::Modifiers(), SkString("a"), context.fVec3_Type.get()); + SkSL::Type s1(SkString("s1"), fields1); + REPORTER_ASSERT(r, 16 == layout.size(s1)); + REPORTER_ASSERT(r, 16 == layout.alignment(s1)); + + fields1.emplace_back(SkSL::Modifiers(), SkString("b"), context.fFloat_Type.get()); + SkSL::Type s2(SkString("s2"), fields1); + REPORTER_ASSERT(r, 16 == layout.size(s2)); + REPORTER_ASSERT(r, 16 == layout.alignment(s2)); + + fields1.emplace_back(SkSL::Modifiers(), SkString("c"), context.fBool_Type.get()); + SkSL::Type s3(SkString("s3"), fields1); + REPORTER_ASSERT(r, 32 == layout.size(s3)); + REPORTER_ASSERT(r, 16 == layout.alignment(s3)); + + // struct 2 + std::vector<SkSL::Type::Field> fields2; + fields2.emplace_back(SkSL::Modifiers(), SkString("a"), context.fInt_Type.get()); + SkSL::Type s4(SkString("s4"), fields2); + REPORTER_ASSERT(r, 4 == layout.size(s4)); + REPORTER_ASSERT(r, 4 == layout.alignment(s4)); + + fields2.emplace_back(SkSL::Modifiers(), SkString("b"), context.fVec3_Type.get()); + SkSL::Type s5(SkString("s5"), fields2); + REPORTER_ASSERT(r, 32 == layout.size(s5)); + REPORTER_ASSERT(r, 16 == layout.alignment(s5)); + + // arrays + SkSL::Type array1(SkString("float[4]"), SkSL::Type::kArray_Kind, *context.fFloat_Type, 4); + REPORTER_ASSERT(r, 16 == layout.size(array1)); + REPORTER_ASSERT(r, 4 == layout.alignment(array1)); + REPORTER_ASSERT(r, 4 == layout.stride(array1)); + + SkSL::Type array2(SkString("vec4[4]"), SkSL::Type::kArray_Kind, *context.fVec4_Type, 4); + REPORTER_ASSERT(r, 64 == layout.size(array2)); + REPORTER_ASSERT(r, 16 == layout.alignment(array2)); + REPORTER_ASSERT(r, 16 == layout.stride(array2)); +} +#endif |