OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkSLSPIRVCodeGenerator.h" | 8 #include "SkSLSPIRVCodeGenerator.h" |
9 | 9 |
10 #include "string.h" | 10 #include "string.h" |
(...skipping 950 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
961 if (fCapabilities & bit) { | 961 if (fCapabilities & bit) { |
962 this->writeInstruction(SpvOpCapability, (SpvId) i, out); | 962 this->writeInstruction(SpvOpCapability, (SpvId) i, out); |
963 } | 963 } |
964 } | 964 } |
965 } | 965 } |
966 | 966 |
967 SpvId SPIRVCodeGenerator::nextId() { | 967 SpvId SPIRVCodeGenerator::nextId() { |
968 return fIdCount++; | 968 return fIdCount++; |
969 } | 969 } |
970 | 970 |
971 void SPIRVCodeGenerator::writeStruct(const Type& type, SpvId resultId) { | 971 void SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& layou t, SpvId resultId) { |
972 this->writeInstruction(SpvOpName, resultId, type.name().c_str(), fNameBuffer ); | 972 this->writeInstruction(SpvOpName, resultId, type.name().c_str(), fNameBuffer ); |
973 // go ahead and write all of the field types, so we don't inadvertently writ e them while we're | 973 // go ahead and write all of the field types, so we don't inadvertently writ e them while we're |
974 // in the middle of writing the struct instruction | 974 // in the middle of writing the struct instruction |
975 std::vector<SpvId> types; | 975 std::vector<SpvId> types; |
976 for (const auto& f : type.fields()) { | 976 for (const auto& f : type.fields()) { |
977 types.push_back(this->getType(*f.fType)); | 977 types.push_back(this->getType(*f.fType, layout)); |
978 } | 978 } |
979 this->writeOpCode(SpvOpTypeStruct, 2 + (int32_t) types.size(), fConstantBuff er); | 979 this->writeOpCode(SpvOpTypeStruct, 2 + (int32_t) types.size(), fConstantBuff er); |
980 this->writeWord(resultId, fConstantBuffer); | 980 this->writeWord(resultId, fConstantBuffer); |
981 for (SpvId id : types) { | 981 for (SpvId id : types) { |
982 this->writeWord(id, fConstantBuffer); | 982 this->writeWord(id, fConstantBuffer); |
983 } | 983 } |
984 size_t offset = 0; | 984 size_t offset = 0; |
985 for (int32_t i = 0; i < (int32_t) type.fields().size(); i++) { | 985 for (int32_t i = 0; i < (int32_t) type.fields().size(); i++) { |
986 size_t size = type.fields()[i].fType->size(); | 986 size_t size = layout.size(*type.fields()[i].fType); |
987 size_t alignment = type.fields()[i].fType->alignment(); | 987 size_t alignment = layout.alignment(*type.fields()[i].fType); |
988 size_t mod = offset % alignment; | 988 size_t mod = offset % alignment; |
989 if (mod != 0) { | 989 if (mod != 0) { |
990 offset += alignment - mod; | 990 offset += alignment - mod; |
991 } | 991 } |
992 this->writeInstruction(SpvOpMemberName, resultId, i, type.fields()[i].fN ame.c_str(), | 992 this->writeInstruction(SpvOpMemberName, resultId, i, type.fields()[i].fN ame.c_str(), |
993 fNameBuffer); | 993 fNameBuffer); |
994 this->writeLayout(type.fields()[i].fModifiers.fLayout, resultId, i); | 994 this->writeLayout(type.fields()[i].fModifiers.fLayout, resultId, i); |
995 if (type.fields()[i].fModifiers.fLayout.fBuiltin < 0) { | 995 if (type.fields()[i].fModifiers.fLayout.fBuiltin < 0) { |
996 this->writeInstruction(SpvOpMemberDecorate, resultId, (SpvId) i, Spv DecorationOffset, | 996 this->writeInstruction(SpvOpMemberDecorate, resultId, (SpvId) i, Spv DecorationOffset, |
997 (SpvId) offset, fDecorationBuffer); | 997 (SpvId) offset, fDecorationBuffer); |
998 } | 998 } |
999 if (type.fields()[i].fType->kind() == Type::kMatrix_Kind) { | 999 if (type.fields()[i].fType->kind() == Type::kMatrix_Kind) { |
1000 this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorati onColMajor, | 1000 this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorati onColMajor, |
1001 fDecorationBuffer); | 1001 fDecorationBuffer); |
1002 this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorati onMatrixStride, | 1002 this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorati onMatrixStride, |
1003 (SpvId) type.fields()[i].fType->stride(), fDe corationBuffer); | 1003 (SpvId) layout.stride(*type.fields()[i].fType ), |
1004 fDecorationBuffer); | |
1004 } | 1005 } |
1005 offset += size; | 1006 offset += size; |
1006 Type::Kind kind = type.fields()[i].fType->kind(); | 1007 Type::Kind kind = type.fields()[i].fType->kind(); |
1007 if ((kind == Type::kArray_Kind || kind == Type::kStruct_Kind) && offset % alignment != 0) { | 1008 if ((kind == Type::kArray_Kind || kind == Type::kStruct_Kind) && offset % alignment != 0) { |
1008 offset += alignment - offset % alignment; | 1009 offset += alignment - offset % alignment; |
1009 } | 1010 } |
1010 ASSERT(offset % alignment == 0); | 1011 ASSERT(offset % alignment == 0); |
1011 } | 1012 } |
1012 } | 1013 } |
1013 | 1014 |
1014 SpvId SPIRVCodeGenerator::getType(const Type& type) { | 1015 SpvId SPIRVCodeGenerator::getType(const Type& type) { |
1015 auto entry = fTypeMap.find(type.name()); | 1016 return this->getType(type, fDefaultLayout); |
1017 } | |
1018 | |
1019 SpvId SPIRVCodeGenerator::getType(const Type& type, const MemoryLayout& layout) { | |
1020 std::string key = type.name() + to_string((int) layout.fStd); | |
1021 auto entry = fTypeMap.find(key); | |
1016 if (entry == fTypeMap.end()) { | 1022 if (entry == fTypeMap.end()) { |
1017 SpvId result = this->nextId(); | 1023 SpvId result = this->nextId(); |
1018 switch (type.kind()) { | 1024 switch (type.kind()) { |
1019 case Type::kScalar_Kind: | 1025 case Type::kScalar_Kind: |
1020 if (type == *fContext.fBool_Type) { | 1026 if (type == *fContext.fBool_Type) { |
1021 this->writeInstruction(SpvOpTypeBool, result, fConstantBuffe r); | 1027 this->writeInstruction(SpvOpTypeBool, result, fConstantBuffe r); |
1022 } else if (type == *fContext.fInt_Type) { | 1028 } else if (type == *fContext.fInt_Type) { |
1023 this->writeInstruction(SpvOpTypeInt, result, 32, 1, fConstan tBuffer); | 1029 this->writeInstruction(SpvOpTypeInt, result, 32, 1, fConstan tBuffer); |
1024 } else if (type == *fContext.fUInt_Type) { | 1030 } else if (type == *fContext.fUInt_Type) { |
1025 this->writeInstruction(SpvOpTypeInt, result, 32, 0, fConstan tBuffer); | 1031 this->writeInstruction(SpvOpTypeInt, result, 32, 0, fConstan tBuffer); |
1026 } else if (type == *fContext.fFloat_Type) { | 1032 } else if (type == *fContext.fFloat_Type) { |
1027 this->writeInstruction(SpvOpTypeFloat, result, 32, fConstant Buffer); | 1033 this->writeInstruction(SpvOpTypeFloat, result, 32, fConstant Buffer); |
1028 } else if (type == *fContext.fDouble_Type) { | 1034 } else if (type == *fContext.fDouble_Type) { |
1029 this->writeInstruction(SpvOpTypeFloat, result, 64, fConstant Buffer); | 1035 this->writeInstruction(SpvOpTypeFloat, result, 64, fConstant Buffer); |
1030 } else { | 1036 } else { |
1031 ASSERT(false); | 1037 ASSERT(false); |
1032 } | 1038 } |
1033 break; | 1039 break; |
1034 case Type::kVector_Kind: | 1040 case Type::kVector_Kind: |
1035 this->writeInstruction(SpvOpTypeVector, result, | 1041 this->writeInstruction(SpvOpTypeVector, result, |
1036 this->getType(type.componentType()), | 1042 this->getType(type.componentType(), layou t), |
1037 type.columns(), fConstantBuffer); | 1043 type.columns(), fConstantBuffer); |
1038 break; | 1044 break; |
1039 case Type::kMatrix_Kind: | 1045 case Type::kMatrix_Kind: |
1040 this->writeInstruction(SpvOpTypeMatrix, result, | 1046 this->writeInstruction(SpvOpTypeMatrix, result, |
1041 this->getType(index_type(fContext, type)) , | 1047 this->getType(index_type(fContext, type), layout), |
1042 type.columns(), fConstantBuffer); | 1048 type.columns(), fConstantBuffer); |
1043 break; | 1049 break; |
1044 case Type::kStruct_Kind: | 1050 case Type::kStruct_Kind: |
1045 this->writeStruct(type, result); | 1051 this->writeStruct(type, layout, result); |
1046 break; | 1052 break; |
1047 case Type::kArray_Kind: { | 1053 case Type::kArray_Kind: { |
1048 if (type.columns() > 0) { | 1054 if (type.columns() > 0) { |
1049 IntLiteral count(fContext, Position(), type.columns()); | 1055 IntLiteral count(fContext, Position(), type.columns()); |
1050 this->writeInstruction(SpvOpTypeArray, result, | 1056 this->writeInstruction(SpvOpTypeArray, result, |
1051 this->getType(type.componentType()), | 1057 this->getType(type.componentType(), l ayout), |
1052 this->writeIntLiteral(count), fConsta ntBuffer); | 1058 this->writeIntLiteral(count), fConsta ntBuffer); |
1053 this->writeInstruction(SpvOpDecorate, result, SpvDecorationA rrayStride, | 1059 this->writeInstruction(SpvOpDecorate, result, SpvDecorationA rrayStride, |
1054 (int32_t) type.stride(), fDecorationB uffer); | 1060 (int32_t) layout.stride(type), |
1061 fDecorationBuffer); | |
1055 } else { | 1062 } else { |
1056 ABORT("runtime-sized arrays are not yet supported"); | 1063 ABORT("runtime-sized arrays are not yet supported"); |
1057 this->writeInstruction(SpvOpTypeRuntimeArray, result, | 1064 this->writeInstruction(SpvOpTypeRuntimeArray, result, |
1058 this->getType(type.componentType()), fConstantBuffer); | 1065 this->getType(type.componentType(), l ayout), |
1066 fConstantBuffer); | |
1059 } | 1067 } |
1060 break; | 1068 break; |
1061 } | 1069 } |
1062 case Type::kSampler_Kind: { | 1070 case Type::kSampler_Kind: { |
1063 SpvId image = this->nextId(); | 1071 SpvId image = this->nextId(); |
1064 this->writeInstruction(SpvOpTypeImage, image, this->getType(*fCo ntext.fFloat_Type), | 1072 this->writeInstruction(SpvOpTypeImage, image, |
1073 this->getType(*fContext.fFloat_Type, layo ut), | |
1065 type.dimensions(), type.isDepth(), type.i sArrayed(), | 1074 type.dimensions(), type.isDepth(), type.i sArrayed(), |
1066 type.isMultisampled(), type.isSampled(), | 1075 type.isMultisampled(), type.isSampled(), |
1067 SpvImageFormatUnknown, fConstantBuffer); | 1076 SpvImageFormatUnknown, fConstantBuffer); |
1068 this->writeInstruction(SpvOpTypeSampledImage, result, image, fCo nstantBuffer); | 1077 this->writeInstruction(SpvOpTypeSampledImage, result, image, fCo nstantBuffer); |
1069 break; | 1078 break; |
1070 } | 1079 } |
1071 default: | 1080 default: |
1072 if (type == *fContext.fVoid_Type) { | 1081 if (type == *fContext.fVoid_Type) { |
1073 this->writeInstruction(SpvOpTypeVoid, result, fConstantBuffe r); | 1082 this->writeInstruction(SpvOpTypeVoid, result, fConstantBuffe r); |
1074 } else { | 1083 } else { |
1075 ABORT("invalid type: %s", type.description().c_str()); | 1084 ABORT("invalid type: %s", type.description().c_str()); |
1076 } | 1085 } |
1077 } | 1086 } |
1078 fTypeMap[type.name()] = result; | 1087 fTypeMap[key] = result; |
1079 return result; | 1088 return result; |
1080 } | 1089 } |
1081 return entry->second; | 1090 return entry->second; |
1082 } | 1091 } |
1083 | 1092 |
1084 SpvId SPIRVCodeGenerator::getFunctionType(const FunctionDeclaration& function) { | 1093 SpvId SPIRVCodeGenerator::getFunctionType(const FunctionDeclaration& function) { |
1085 std::string key = function.fReturnType.description() + "("; | 1094 std::string key = function.fReturnType.description() + "("; |
1086 std::string separator = ""; | 1095 std::string separator = ""; |
1087 for (size_t i = 0; i < function.fParameters.size(); i++) { | 1096 for (size_t i = 0; i < function.fParameters.size(); i++) { |
1088 key += separator; | 1097 key += separator; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1131 this->writeWord(returnType, fConstantBuffer); | 1140 this->writeWord(returnType, fConstantBuffer); |
1132 for (SpvId id : parameterTypes) { | 1141 for (SpvId id : parameterTypes) { |
1133 this->writeWord(id, fConstantBuffer); | 1142 this->writeWord(id, fConstantBuffer); |
1134 } | 1143 } |
1135 fTypeMap[key] = result; | 1144 fTypeMap[key] = result; |
1136 return result; | 1145 return result; |
1137 } | 1146 } |
1138 return entry->second; | 1147 return entry->second; |
1139 } | 1148 } |
1140 | 1149 |
1141 SpvId SPIRVCodeGenerator::getPointerType(const Type& type, | 1150 SpvId SPIRVCodeGenerator::getPointerType(const Type& type, SpvStorageClass_ stor ageClass) { |
1151 return this->getPointerType(type, fDefaultLayout, storageClass); | |
1152 } | |
1153 | |
1154 SpvId SPIRVCodeGenerator::getPointerType(const Type& type, const MemoryLayout& l ayout, | |
1142 SpvStorageClass_ storageClass) { | 1155 SpvStorageClass_ storageClass) { |
1143 std::string key = type.description() + "*" + to_string(storageClass); | 1156 std::string key = type.description() + "*" + to_string(layout.fStd) + to_str ing(storageClass); |
1144 auto entry = fTypeMap.find(key); | 1157 auto entry = fTypeMap.find(key); |
1145 if (entry == fTypeMap.end()) { | 1158 if (entry == fTypeMap.end()) { |
1146 SpvId result = this->nextId(); | 1159 SpvId result = this->nextId(); |
1147 this->writeInstruction(SpvOpTypePointer, result, storageClass, | 1160 this->writeInstruction(SpvOpTypePointer, result, storageClass, |
1148 this->getType(type), fConstantBuffer); | 1161 this->getType(type), fConstantBuffer); |
1149 fTypeMap[key] = result; | 1162 fTypeMap[key] = result; |
1150 return result; | 1163 return result; |
1151 } | 1164 } |
1152 return entry->second; | 1165 return entry->second; |
1153 } | 1166 } |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1544 return this->writeVectorConstructor(c, out); | 1557 return this->writeVectorConstructor(c, out); |
1545 case Type::kMatrix_Kind: | 1558 case Type::kMatrix_Kind: |
1546 return this->writeMatrixConstructor(c, out); | 1559 return this->writeMatrixConstructor(c, out); |
1547 default: | 1560 default: |
1548 ABORT("unsupported constructor: %s", c.description().c_str()); | 1561 ABORT("unsupported constructor: %s", c.description().c_str()); |
1549 } | 1562 } |
1550 } | 1563 } |
1551 | 1564 |
1552 SpvStorageClass_ get_storage_class(const Modifiers& modifiers) { | 1565 SpvStorageClass_ get_storage_class(const Modifiers& modifiers) { |
1553 if (modifiers.fFlags & Modifiers::kIn_Flag) { | 1566 if (modifiers.fFlags & Modifiers::kIn_Flag) { |
1567 ASSERT(!modifiers.fLayout.fPushConstant); | |
1554 return SpvStorageClassInput; | 1568 return SpvStorageClassInput; |
1555 } else if (modifiers.fFlags & Modifiers::kOut_Flag) { | 1569 } else if (modifiers.fFlags & Modifiers::kOut_Flag) { |
1570 ASSERT(!modifiers.fLayout.fPushConstant); | |
1556 return SpvStorageClassOutput; | 1571 return SpvStorageClassOutput; |
1557 } else if (modifiers.fFlags & Modifiers::kUniform_Flag) { | 1572 } else if (modifiers.fFlags & Modifiers::kUniform_Flag) { |
1573 if (modifiers.fLayout.fPushConstant) { | |
1574 return SpvStorageClassPushConstant; | |
1575 } | |
1558 return SpvStorageClassUniform; | 1576 return SpvStorageClassUniform; |
1559 } else { | 1577 } else { |
1560 return SpvStorageClassFunction; | 1578 return SpvStorageClassFunction; |
1561 } | 1579 } |
1562 } | 1580 } |
1563 | 1581 |
1564 SpvStorageClass_ get_storage_class(const Expression& expr) { | 1582 SpvStorageClass_ get_storage_class(const Expression& expr) { |
1565 switch (expr.fKind) { | 1583 switch (expr.fKind) { |
1566 case Expression::kVariableReference_Kind: | 1584 case Expression::kVariableReference_Kind: |
1567 return get_storage_class(((VariableReference&) expr).fVariable.fModi fiers); | 1585 return get_storage_class(((VariableReference&) expr).fVariable.fModi fiers); |
(...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2351 this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecoratio nDescriptorSet, | 2369 this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecoratio nDescriptorSet, |
2352 layout.fSet, fDecorationBuffer); | 2370 layout.fSet, fDecorationBuffer); |
2353 } | 2371 } |
2354 if (layout.fBuiltin >= 0) { | 2372 if (layout.fBuiltin >= 0) { |
2355 this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecoratio nBuiltIn, | 2373 this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecoratio nBuiltIn, |
2356 layout.fBuiltin, fDecorationBuffer); | 2374 layout.fBuiltin, fDecorationBuffer); |
2357 } | 2375 } |
2358 } | 2376 } |
2359 | 2377 |
2360 SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { | 2378 SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { |
2361 SpvId type = this->getType(intf.fVariable.fType); | 2379 MemoryLayout layout = intf.fVariable.fModifiers.fLayout.fPushConstant ? |
2380 MemoryLayout(MemoryLayout::k430_Standard) : | |
2381 fDefaultLayout; | |
2382 SpvId type = this->getType(intf.fVariable.fType, layout); | |
2362 SpvId result = this->nextId(); | 2383 SpvId result = this->nextId(); |
2363 this->writeInstruction(SpvOpDecorate, type, SpvDecorationBlock, fDecorationB uffer); | 2384 this->writeInstruction(SpvOpDecorate, type, SpvDecorationBlock, fDecorationB uffer); |
2364 SpvStorageClass_ storageClass = get_storage_class(intf.fVariable.fModifiers) ; | 2385 SpvStorageClass_ storageClass = get_storage_class(intf.fVariable.fModifiers) ; |
2365 SpvId ptrType = this->nextId(); | 2386 SpvId ptrType = this->nextId(); |
2366 this->writeInstruction(SpvOpTypePointer, ptrType, storageClass, type, fConst antBuffer); | 2387 this->writeInstruction(SpvOpTypePointer, ptrType, storageClass, type, fConst antBuffer); |
2367 this->writeInstruction(SpvOpVariable, ptrType, result, storageClass, fConsta ntBuffer); | 2388 this->writeInstruction(SpvOpVariable, ptrType, result, storageClass, fConsta ntBuffer); |
2368 this->writeLayout(intf.fVariable.fModifiers.fLayout, result); | 2389 this->writeLayout(intf.fVariable.fModifiers.fLayout, result); |
2369 fVariableMap[&intf.fVariable] = result; | 2390 fVariableMap[&intf.fVariable] = result; |
2370 return result; | 2391 return result; |
2371 } | 2392 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2407 } | 2428 } |
2408 SpvId id = this->nextId(); | 2429 SpvId id = this->nextId(); |
2409 fVariableMap[var] = id; | 2430 fVariableMap[var] = id; |
2410 SpvId type = this->getPointerType(var->fType, storageClass); | 2431 SpvId type = this->getPointerType(var->fType, storageClass); |
2411 this->writeInstruction(SpvOpVariable, type, id, storageClass, fConstantB uffer); | 2432 this->writeInstruction(SpvOpVariable, type, id, storageClass, fConstantB uffer); |
2412 this->writeInstruction(SpvOpName, id, var->fName.c_str(), fNameBuffer); | 2433 this->writeInstruction(SpvOpName, id, var->fName.c_str(), fNameBuffer); |
2413 if (var->fType.kind() == Type::kMatrix_Kind) { | 2434 if (var->fType.kind() == Type::kMatrix_Kind) { |
2414 this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecora tionColMajor, | 2435 this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecora tionColMajor, |
2415 fDecorationBuffer); | 2436 fDecorationBuffer); |
2416 this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecora tionMatrixStride, | 2437 this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecora tionMatrixStride, |
2417 (SpvId) var->fType.stride(), fDecorationBuffe r); | 2438 (SpvId) fDefaultLayout.stride(var->fType), |
egdaniel
2016/11/14 18:48:35
extra whitespace
| |
2439 fDecorationBuffer); | |
2418 } | 2440 } |
2419 if (varDecl.fValue) { | 2441 if (varDecl.fValue) { |
2420 ASSERT(!fCurrentBlock); | 2442 ASSERT(!fCurrentBlock); |
2421 fCurrentBlock = -1; | 2443 fCurrentBlock = -1; |
2422 SpvId value = this->writeExpression(*varDecl.fValue, fGlobalInitiali zersBuffer); | 2444 SpvId value = this->writeExpression(*varDecl.fValue, fGlobalInitiali zersBuffer); |
2423 this->writeInstruction(SpvOpStore, id, value, fGlobalInitializersBuf fer); | 2445 this->writeInstruction(SpvOpStore, id, value, fGlobalInitializersBuf fer); |
2424 fCurrentBlock = 0; | 2446 fCurrentBlock = 0; |
2425 } | 2447 } |
2426 this->writeLayout(var->fModifiers.fLayout, id); | 2448 this->writeLayout(var->fModifiers.fLayout, id); |
2427 } | 2449 } |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2648 this->writeWord(SpvVersion, out); | 2670 this->writeWord(SpvVersion, out); |
2649 this->writeWord(SKSL_MAGIC, out); | 2671 this->writeWord(SKSL_MAGIC, out); |
2650 std::stringstream buffer; | 2672 std::stringstream buffer; |
2651 this->writeInstructions(program, buffer); | 2673 this->writeInstructions(program, buffer); |
2652 this->writeWord(fIdCount, out); | 2674 this->writeWord(fIdCount, out); |
2653 this->writeWord(0, out); // reserved, always zero | 2675 this->writeWord(0, out); // reserved, always zero |
2654 out << buffer.str(); | 2676 out << buffer.str(); |
2655 } | 2677 } |
2656 | 2678 |
2657 } | 2679 } |
OLD | NEW |