diff options
-rw-r--r-- | gn/tests.gni | 1 | ||||
-rw-r--r-- | src/sksl/SkSLMemoryLayout.h | 128 | ||||
-rw-r--r-- | src/sksl/SkSLParser.cpp | 10 | ||||
-rw-r--r-- | src/sksl/SkSLSPIRVCodeGenerator.cpp | 62 | ||||
-rw-r--r-- | src/sksl/SkSLSPIRVCodeGenerator.h | 10 | ||||
-rw-r--r-- | src/sksl/SkSLUtil.h | 9 | ||||
-rw-r--r-- | src/sksl/ast/SkSLASTLayout.h | 12 | ||||
-rw-r--r-- | src/sksl/ir/SkSLLayout.h | 27 | ||||
-rw-r--r-- | src/sksl/ir/SkSLModifiers.h | 4 | ||||
-rw-r--r-- | src/sksl/ir/SkSLType.h | 81 | ||||
-rw-r--r-- | tests/SkSLErrorTest.cpp | 2 | ||||
-rw-r--r-- | tests/SkSLGLSLTest.cpp | 2 | ||||
-rw-r--r-- | tests/SkSLMemoryLayoutTest.cpp | 176 |
13 files changed, 401 insertions, 123 deletions
diff --git a/gn/tests.gni b/gn/tests.gni index d828297b5b..647160f53c 100644 --- a/gn/tests.gni +++ b/gn/tests.gni @@ -203,6 +203,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 324bd41c86..154989fe84 100644 --- a/src/sksl/SkSLParser.cpp +++ b/src/sksl/SkSLParser.cpp @@ -526,8 +526,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; @@ -537,11 +536,12 @@ ASTLayout Parser::layout() { bool originUpperLeft = false; bool overrideCoverage = false; bool blendSupportAllEquations = false; + bool pushConstant = false; if (this->peek().fKind == Token::LAYOUT) { this->nextToken(); if (!this->expect(Token::LPAREN, "'('")) { return ASTLayout(location, binding, index, set, builtin, originUpperLeft, - overrideCoverage, blendSupportAllEquations); + overrideCoverage, blendSupportAllEquations, pushConstant); } for (;;) { Token t = this->nextToken(); @@ -561,6 +561,8 @@ ASTLayout Parser::layout() { overrideCoverage = true; } else if (t.fText == "blend_support_all_equations") { blendSupportAllEquations = true; + } else if (t.fText == "push_constant") { + pushConstant = true; } else { this->error(t.fPosition, ("'" + t.fText + "' is not a valid layout qualifier").c_str()); @@ -575,7 +577,7 @@ ASTLayout Parser::layout() { } } return ASTLayout(location, binding, index, set, builtin, originUpperLeft, overrideCoverage, - blendSupportAllEquations); + blendSupportAllEquations, 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 a491968674..b899e4fcbd 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.cpp +++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp @@ -968,13 +968,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); @@ -983,8 +983,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; @@ -1000,7 +1000,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(); @@ -1012,7 +1013,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) { + std::string key = type.name() + to_string((int) layout.fStd); + auto entry = fTypeMap.find(key); if (entry == fTypeMap.end()) { SpvId result = this->nextId(); switch (type.kind()) { @@ -1033,35 +1039,38 @@ 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; } case Type::kSampler_Kind: { SpvId 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(), SpvImageFormatUnknown, fConstantBuffer); @@ -1075,7 +1084,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; @@ -1138,9 +1147,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) { - std::string key = type.description() + "*" + to_string(storageClass); + std::string key = type.description() + "*" + to_string(layout.fStd) + to_string(storageClass); auto entry = fTypeMap.find(key); if (entry == fTypeMap.end()) { SpvId result = this->nextId(); @@ -1551,10 +1564,15 @@ SpvId SPIRVCodeGenerator::writeConstructor(const Constructor& c, std::ostream& o 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; @@ -2358,7 +2376,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); @@ -2411,10 +2432,11 @@ void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclaratio 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, + (SpvId) fDefaultLayout.stride(var->fType), fDecorationBuffer); - this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecorationMatrixStride, - (SpvId) var->fType.stride(), fDecorationBuffer); } if (varDecl.fValue) { ASSERT(!fCurrentBlock); diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h index e6fc28ee0c..6459e5bcf5 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.h +++ b/src/sksl/SkSLSPIRVCodeGenerator.h @@ -14,6 +14,7 @@ #include <unordered_map> #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) @@ -93,17 +95,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, std::ostream& 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, std::ostream& out); @@ -229,6 +236,7 @@ private: std::ostream& out); const Context& fContext; + const MemoryLayout fDefaultLayout; uint64_t fCapabilities; SpvId fIdCount; diff --git a/src/sksl/SkSLUtil.h b/src/sksl/SkSLUtil.h index ede21830e5..c648152bf2 100644 --- a/src/sksl/SkSLUtil.h +++ b/src/sksl/SkSLUtil.h @@ -100,13 +100,8 @@ NORETURN void sksl_abort(); } // namespace -#ifdef DEBUG -#define ASSERT(x) assert(x) -#define ASSERT_RESULT(x) ASSERT(x); -#else -#define ASSERT(x) -#define ASSERT_RESULT(x) x -#endif +#define ASSERT(x) SkASSERT(x) +#define ASSERT_RESULT(x) SkAssertResult(x); #ifdef SKIA #define ABORT(...) { SkDebugf(__VA_ARGS__); sksl_abort(); } diff --git a/src/sksl/ast/SkSLASTLayout.h b/src/sksl/ast/SkSLASTLayout.h index 515eb2bdbb..2aec31e4df 100644 --- a/src/sksl/ast/SkSLASTLayout.h +++ b/src/sksl/ast/SkSLASTLayout.h @@ -19,9 +19,9 @@ namespace SkSL { * layout (location = 0) int x; */ struct ASTLayout : public ASTNode { - // For all parameters, a -1 means no value + // 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) + bool overrideCoverage, bool blendSupportAllEquations, bool pushConstant) : fLocation(location) , fBinding(binding) , fIndex(index) @@ -29,7 +29,8 @@ struct ASTLayout : public ASTNode { , fBuiltin(builtin) , fOriginUpperLeft(originUpperLeft) , fOverrideCoverage(overrideCoverage) - , fBlendSupportAllEquations(blendSupportAllEquations) {} + , fBlendSupportAllEquations(blendSupportAllEquations) + , fPushConstant(pushConstant) {} std::string description() const { std::string result; @@ -66,6 +67,10 @@ struct ASTLayout : public ASTNode { result += separator + "blend_support_all_equations"; separator = ", "; } + if (fPushConstant) { + result += separator + "push_constant"; + separator = ", "; + } if (result.length() > 0) { result = "layout (" + result + ")"; } @@ -80,6 +85,7 @@ struct ASTLayout : public ASTNode { const bool fOriginUpperLeft; const bool fOverrideCoverage; const bool fBlendSupportAllEquations; + const bool fPushConstant; }; } // namespace diff --git a/src/sksl/ir/SkSLLayout.h b/src/sksl/ir/SkSLLayout.h index 24087d0612..dfa396758b 100644 --- a/src/sksl/ir/SkSLLayout.h +++ b/src/sksl/ir/SkSLLayout.h @@ -24,10 +24,11 @@ struct Layout { , fBuiltin(layout.fBuiltin) , fOriginUpperLeft(layout.fOriginUpperLeft) , fOverrideCoverage(layout.fOverrideCoverage) - , fBlendSupportAllEquations(layout.fBlendSupportAllEquations) {} + , fBlendSupportAllEquations(layout.fBlendSupportAllEquations) + , fPushConstant(layout.fPushConstant) {} Layout(int location, int binding, int index, int set, int builtin, bool originUpperLeft, - bool overrideCoverage, bool blendSupportAllEquations) + bool overrideCoverage, bool blendSupportAllEquations, bool pushconstant) : fLocation(location) , fBinding(binding) , fIndex(index) @@ -35,7 +36,19 @@ struct Layout { , fBuiltin(builtin) , fOriginUpperLeft(originUpperLeft) , fOverrideCoverage(overrideCoverage) - , fBlendSupportAllEquations(blendSupportAllEquations) {} + , fBlendSupportAllEquations(blendSupportAllEquations) + , fPushConstant(pushconstant) {} + + Layout() + : fLocation(-1) + , fBinding(-1) + , fIndex(-1) + , fSet(-1) + , fBuiltin(-1) + , fOriginUpperLeft(false) + , fOverrideCoverage(false) + , fBlendSupportAllEquations(false) + , fPushConstant(false) {} std::string description() const { std::string result; @@ -72,6 +85,10 @@ struct Layout { result += separator + "blend_support_all_equations"; separator = ", "; } + if (fPushConstant) { + result += separator + "push_constant"; + separator = ", "; + } if (result.length() > 0) { result = "layout (" + result + ")"; } @@ -93,16 +110,16 @@ struct Layout { 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; int fBuiltin; + int fOffset; bool fOriginUpperLeft; bool fOverrideCoverage; bool fBlendSupportAllEquations; + bool fPushConstant; }; } // namespace diff --git a/src/sksl/ir/SkSLModifiers.h b/src/sksl/ir/SkSLModifiers.h index f39e92959f..5e3c0fd29f 100644 --- a/src/sksl/ir/SkSLModifiers.h +++ b/src/sksl/ir/SkSLModifiers.h @@ -38,6 +38,10 @@ struct Modifiers { : fLayout(layout) , fFlags(flags) {} + Modifiers() + : fLayout(Layout()) + , fFlags(0) {} + std::string description() const { std::string result = fLayout.description(); if (fFlags & kUniform_Flag) { diff --git a/src/sksl/ir/SkSLType.h b/src/sksl/ir/SkSLType.h index afd00d8b2a..3c31b6b53d 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/SkSLErrorTest.cpp b/tests/SkSLErrorTest.cpp index e9e05c18d2..9a97a8c04a 100644 --- a/tests/SkSLErrorTest.cpp +++ b/tests/SkSLErrorTest.cpp @@ -9,7 +9,7 @@ #include "Test.h" -#if SKIA_SUPPORT_GPU +#if SK_SUPPORT_GPU static void test_failure(skiatest::Reporter* r, const char* src, const char* error) { SkSL::Compiler compiler; diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp index b01aad83d6..3cff1c2c28 100644 --- a/tests/SkSLGLSLTest.cpp +++ b/tests/SkSLGLSLTest.cpp @@ -9,7 +9,7 @@ #include "Test.h" -#if SKIA_SUPPORT_GPU +#if SK_SUPPORT_GPU static void test(skiatest::Reporter* r, const char* src, const GrGLSLCaps& caps, const char* expected) { diff --git a/tests/SkSLMemoryLayoutTest.cpp b/tests/SkSLMemoryLayoutTest.cpp new file mode 100644 index 0000000000..142ee9e56f --- /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(), "a", context.fVec3_Type.get()); + SkSL::Type s1("s1", fields1); + REPORTER_ASSERT(r, 16 == layout.size(s1)); + REPORTER_ASSERT(r, 16 == layout.alignment(s1)); + + fields1.emplace_back(SkSL::Modifiers(), "b", context.fFloat_Type.get()); + SkSL::Type s2("s2", fields1); + REPORTER_ASSERT(r, 16 == layout.size(s2)); + REPORTER_ASSERT(r, 16 == layout.alignment(s2)); + + fields1.emplace_back(SkSL::Modifiers(), "c", context.fBool_Type.get()); + SkSL::Type s3("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(), "a", context.fInt_Type.get()); + SkSL::Type s4("s4", fields2); + REPORTER_ASSERT(r, 16 == layout.size(s4)); + REPORTER_ASSERT(r, 16 == layout.alignment(s4)); + + fields2.emplace_back(SkSL::Modifiers(), "b", context.fVec3_Type.get()); + SkSL::Type s5("s5", fields2); + REPORTER_ASSERT(r, 32 == layout.size(s5)); + REPORTER_ASSERT(r, 16 == layout.alignment(s5)); + + // arrays + SkSL::Type array1("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("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(), "a", context.fVec3_Type.get()); + SkSL::Type s1("s1", fields1); + REPORTER_ASSERT(r, 16 == layout.size(s1)); + REPORTER_ASSERT(r, 16 == layout.alignment(s1)); + + fields1.emplace_back(SkSL::Modifiers(), "b", context.fFloat_Type.get()); + SkSL::Type s2("s2", fields1); + REPORTER_ASSERT(r, 16 == layout.size(s2)); + REPORTER_ASSERT(r, 16 == layout.alignment(s2)); + + fields1.emplace_back(SkSL::Modifiers(), "c", context.fBool_Type.get()); + SkSL::Type s3("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(), "a", context.fInt_Type.get()); + SkSL::Type s4("s4", fields2); + REPORTER_ASSERT(r, 4 == layout.size(s4)); + REPORTER_ASSERT(r, 4 == layout.alignment(s4)); + + fields2.emplace_back(SkSL::Modifiers(), "b", context.fVec3_Type.get()); + SkSL::Type s5("s5", fields2); + REPORTER_ASSERT(r, 32 == layout.size(s5)); + REPORTER_ASSERT(r, 16 == layout.alignment(s5)); + + // arrays + SkSL::Type array1("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("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 |