From 72f86c8273b196d204213f02e73ba772201f903d Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Wed, 30 Oct 2019 17:28:55 -0400 Subject: WIP: Simple separate IR module linkage working (#1100) * Added RiffReadHelper * Move type to fourCC in Chunk simplifies some code. * Make MemoryArena able to track external blocks. Allow ownership of Data to vary. Changed IR serialization to use moved allocations to avoid copies. As it turns out all of the array writes could use unowned data, but doing so requires the IRData to stay in scope longer than IRSerialData, which it does at the moment - but perhaps needs better naming or a control for the feature. * Write out slang-module container. * WIP on -r option. Loading modules - with -r. * Making the serialized-module run (without using imported module). * Split compiling module from the test. * Separate module compilation with a function working. * Remove serialization test as not used. * Fix warning on gcc. * Updated test to have types across module boundary. --- source/core/slang-riff.cpp | 13 ++++ source/core/slang-riff.h | 3 + source/slang/slang-compiler.cpp | 69 ++++++++++++++------ source/slang/slang-compiler.h | 4 ++ source/slang/slang-diagnostic-defs.h | 1 + source/slang/slang-ir-link.cpp | 23 +++++-- source/slang/slang-ir-serialize.cpp | 73 +++++++++++++++++----- source/slang/slang-ir-serialize.h | 47 ++++++++------ source/slang/slang-options.cpp | 21 +++++++ tests/serialization/serialized-module-test.slang | 35 +++++++++++ .../serialized-module-test.slang.expected.txt | 4 ++ tests/serialization/serialized-module.slang | 15 +++++ 12 files changed, 248 insertions(+), 60 deletions(-) create mode 100644 tests/serialization/serialized-module-test.slang create mode 100644 tests/serialization/serialized-module-test.slang.expected.txt create mode 100644 tests/serialization/serialized-module.slang diff --git a/source/core/slang-riff.cpp b/source/core/slang-riff.cpp index 3a3722bb8..2e633f2e7 100644 --- a/source/core/slang-riff.cpp +++ b/source/core/slang-riff.cpp @@ -535,6 +535,19 @@ RiffContainer::Chunk* RiffContainer::ListChunk::findContained(FourCC fourCC) con return nullptr; } +void RiffContainer::ListChunk::findContained(FourCC type, List& out) +{ + Chunk* chunk = m_containedChunks; + while (chunk) + { + if (chunk->m_fourCC == type && chunk->m_kind == Chunk::Kind::List) + { + out.add(static_cast(chunk)); + } + chunk = chunk->m_next; + } +} + RiffContainer::Data* RiffContainer::ListChunk::findContainedData(FourCC type) const { Chunk* found = findContained(type); diff --git a/source/core/slang-riff.h b/source/core/slang-riff.h index 4d23e45c1..99d078625 100644 --- a/source/core/slang-riff.h +++ b/source/core/slang-riff.h @@ -245,6 +245,9 @@ public: template T* findContainedData(FourCC type) const { return (T*)findContainedData(type, sizeof(T)); } + /// Find all contained that match the type + void findContained(FourCC type, List& out); + /// Find the list (including self) that matches subtype recursively ListChunk* findListRec(FourCC subType); diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 87a5e01a8..705b4ed59 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -5,6 +5,7 @@ #include "../core/slang-io.h" #include "../core/slang-string-util.h" #include "../core/slang-hex-dump-util.h" +#include "../core/slang-riff.h" #include "slang-check.h" #include "slang-compiler.h" @@ -18,6 +19,8 @@ #include "slang-reflection.h" #include "slang-emit.h" +#include "slang-ir-serialize.h" + // Enable calling through to `fxc` or `dxc` to // generate code on Windows. #ifdef _WIN32 @@ -2187,38 +2190,64 @@ SlangResult dissassembleDXILUsingDXC( EndToEndCompileRequest* endToEndReq, Stream* stream) { - SLANG_UNUSED(stream); + RiffContainer container; - auto linkage = endToEndReq->getLinkage(); - auto sink = endToEndReq->getSink(); - auto frontEndReq = endToEndReq->getFrontEndReq(); + // TODO(JS): We may want a switch to control is we use compression and/or we may just want compressed by default. + // For now uncompressed is fine. + const auto compressionType = IRSerialBinary::CompressionType::None; - for (auto translationUnit : frontEndReq->translationUnits) { - auto module = translationUnit->module; - auto irModule = module->getIRModule(); + // Module list + RiffContainer::ScopeChunk listScope(&container, RiffContainer::Chunk::Kind::List, IRSerialBinary::kSlangModuleListFourCc); - SLANG_UNUSED(irModule); + auto linkage = endToEndReq->getLinkage(); + auto sink = endToEndReq->getSink(); + auto frontEndReq = endToEndReq->getFrontEndReq(); - // Okay, we need to serialize this module to our container file, - // including both its name and generated IR code. - } + IRSerialWriter::OptionFlags optionFlags = 0; - auto program = endToEndReq->getSpecializedGlobalAndEntryPointsComponentType(); + if (linkage->debugInfoLevel != DebugInfoLevel::None) + { + optionFlags |= IRSerialWriter::OptionFlag::DebugInfo; + } - + SourceManager* sourceManager = frontEndReq->getSourceManager(); - // TODO: in the case where we have specialization, we might need - // to serialize IR related to `program`... + for (auto translationUnit : frontEndReq->translationUnits) + { + auto module = translationUnit->module; + auto irModule = module->getIRModule(); - for (auto target : linkage->targets) - { - auto targetProgram = program->getTargetProgram(target); - auto irModule = targetProgram->getOrCreateIRModuleForLayout(sink); + // Okay, we need to serialize this module to our container file. + // We currently don't serialize it's name..., but support for that could be added. - // Okay, we need to serialize this target program and its IR too... + IRSerialData serialData; + IRSerialWriter writer; + SLANG_RETURN_ON_FAIL(writer.write(irModule, sourceManager, optionFlags, &serialData)); + SLANG_RETURN_ON_FAIL(IRSerialWriter::writeContainer(serialData, compressionType, &container)); + } + + auto program = endToEndReq->getSpecializedGlobalAndEntryPointsComponentType(); + + // TODO: in the case where we have specialization, we might need + // to serialize IR related to `program`... + + for (auto target : linkage->targets) + { + auto targetProgram = program->getTargetProgram(target); + auto irModule = targetProgram->getOrCreateIRModuleForLayout(sink); + + // Okay, we need to serialize this target program and its IR too... + IRSerialData serialData; + IRSerialWriter writer; + SLANG_RETURN_ON_FAIL(writer.write(irModule, sourceManager, optionFlags, &serialData)); + SLANG_RETURN_ON_FAIL(IRSerialWriter::writeContainer(serialData, compressionType, &container)); + } } + // We now write the RiffContainer to the stream + SLANG_RETURN_ON_FAIL(RiffUtil::write(container.getRoot(), true, stream)); + return SLANG_OK; } diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index a527d3a31..cd99c4079 100644 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -1260,6 +1260,9 @@ namespace Slang bool m_requireCacheFileSystem = false; bool m_useFalcorCustomSharedKeywordSemantics = false; + // Modules that have been read in with the -r option + List> m_libModules; + private: Session* m_session = nullptr; @@ -1299,6 +1302,7 @@ namespace Slang bool isBeingImported(Module* module); List> m_specializedTypes; + }; /// Shared functionality between front- and back-end compile requests. diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 6623b7195..405590111 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -111,6 +111,7 @@ DIAGNOSTIC( 80, Error, duplicateOutputPathsForEntryPointAndTarget, "multiple DIAGNOSTIC( 81, Error, parametersAfterLoadReproIgnored, "parameters after -load-repro [file] are ignored") DIAGNOSTIC( 82, Error, unableToWriteReproFile, "unable to write repro file '%0'"); DIAGNOSTIC( 83, Error, unableToWriteModuleContainer, "unable to write module container '%0'"); +DIAGNOSTIC( 84, Error, unableToReadModuleContainer, "unable to read module container '%0'"); // // 1xxxx - Lexical anaylsis diff --git a/source/slang/slang-ir-link.cpp b/source/slang/slang-ir-link.cpp index 1cdc2cfc9..1102ecb3e 100644 --- a/source/slang/slang-ir-link.cpp +++ b/source/slang/slang-ir-link.cpp @@ -1339,15 +1339,26 @@ LinkedIR linkIR( state->irModule = sharedContext->module; + auto linkage = compileRequest->getLinkage(); + // We need to be able to look up IR definitions for any symbols in // modules that the program depends on (transitively). To // accelerate lookup, we will create a symbol table for looking // up IR definitions by their mangled name. // + + List irModules; program->enumerateIRModules([&](IRModule* irModule) { - insertGlobalValueSymbols(sharedContext, irModule); + irModules.add(irModule); }); + irModules.addRange(linkage->m_libModules.getBuffer()->readRef(), linkage->m_libModules.getCount()); + + // Add any modules that were loaded as libraries + for (IRModule* irModule : irModules) + { + insertGlobalValueSymbols(sharedContext, irModule); + } // We will also insert the IR global symbols from the IR module // attached to the `TargetProgram`, since this module is @@ -1374,7 +1385,6 @@ LinkedIR linkIR( cloneGlobalValue(context, (IRWitnessTable*)sym.Value->irGlobalValue); } - // Next, we make sure to clone the global value for // the entry point function itself, and rely on // this step to recursively copy over anything else @@ -1401,17 +1411,18 @@ LinkedIR linkIR( // In the long run we do not want to *ever* iterate over all the // instructions in all the input modules. // - program->enumerateIRModules([&](IRModule* irModule) + + for (IRModule* irModule : irModules) { - for(auto inst : irModule->getGlobalInsts()) + for (auto inst : irModule->getGlobalInsts()) { auto bindInst = as(inst); - if(!bindInst) + if (!bindInst) continue; cloneValue(context, bindInst); } - }); + } // TODO: *technically* we should consider the case where // we have global variables with initializers, since diff --git a/source/slang/slang-ir-serialize.cpp b/source/slang/slang-ir-serialize.cpp index 97b070f9c..5c16f70f3 100644 --- a/source/slang/slang-ir-serialize.cpp +++ b/source/slang/slang-ir-serialize.cpp @@ -809,7 +809,7 @@ static Result _writeArrayChunk(IRSerialBinary::CompressionType compressionType, { ScopeChunk scope(container, Chunk::Kind::Data, chunkId); Bin::ArrayHeader header; - header.m_numEntries = uint32_t(numEntries); + header.numEntries = uint32_t(numEntries); container->write(&header, sizeof(header)); container->write(data, typeSize * numEntries); @@ -823,8 +823,8 @@ static Result _writeArrayChunk(IRSerialBinary::CompressionType compressionType, ByteEncodeUtil::encodeLiteUInt32((const uint32_t*)data, numCompressedEntries, compressedPayload); Bin::CompressedArrayHeader header; - header.m_numEntries = uint32_t(numEntries); - header.m_numCompressedEntries = uint32_t(numCompressedEntries); + header.numEntries = uint32_t(numEntries); + header.numCompressedEntries = uint32_t(numCompressedEntries); container->write(&header, sizeof(header)); @@ -961,8 +961,8 @@ Result _writeInstArrayChunk(IRSerialBinary::CompressionType compressionType, uin ScopeChunk scope(container, Chunk::Kind::Data, SLANG_MAKE_COMPRESSED_FOUR_CC(chunkId)); Bin::CompressedArrayHeader header; - header.m_numEntries = uint32_t(array.getCount()); - header.m_numCompressedEntries = 0; + header.numEntries = uint32_t(array.getCount()); + header.numCompressedEntries = 0; container->write(&header, sizeof(header)); @@ -986,7 +986,7 @@ Result _writeInstArrayChunk(IRSerialBinary::CompressionType compressionType, uin // Write the header { Bin::ModuleHeader moduleHeader; - moduleHeader.m_compressionType = uint32_t(Bin::CompressionType::VariableByteLite); + moduleHeader.compressionType = uint32_t(Bin::CompressionType::VariableByteLite); ScopeChunk scopeHeader(container, Chunk::Kind::Data, Bin::kSlangModuleHeaderFourCc); container->write(&moduleHeader, sizeof(moduleHeader)); } @@ -1065,11 +1065,11 @@ static Result _readArrayChunk(IRSerialBinary::CompressionType compressionType, R Bin::CompressedArrayHeader header; SLANG_RETURN_ON_FAIL(read.read(header)); - void* dst = listOut.setSize(header.m_numEntries); - SLANG_ASSERT(header.m_numCompressedEntries == uint32_t((header.m_numEntries * typeSize) / sizeof(uint32_t))); + void* dst = listOut.setSize(header.numEntries); + SLANG_ASSERT(header.numCompressedEntries == uint32_t((header.numEntries * typeSize) / sizeof(uint32_t))); // Decode.. - ByteEncodeUtil::decodeLiteUInt32(read.getData(), header.m_numCompressedEntries, (uint32_t*)dst); + ByteEncodeUtil::decodeLiteUInt32(read.getData(), header.numCompressedEntries, (uint32_t*)dst); break; } case Bin::CompressionType::None: @@ -1077,9 +1077,9 @@ static Result _readArrayChunk(IRSerialBinary::CompressionType compressionType, R // Read uncompressed Bin::ArrayHeader header; SLANG_RETURN_ON_FAIL(read.read(header)); - const size_t payloadSize = header.m_numEntries * typeSize; + const size_t payloadSize = header.numEntries * typeSize; SLANG_ASSERT(payloadSize == read.getRemainingSize()); - void* dst = listOut.setSize(header.m_numEntries); + void* dst = listOut.setSize(header.numEntries); ::memcpy(dst, read.getData(), payloadSize); break; } @@ -1097,7 +1097,7 @@ static Result _readArrayChunk(const IRSerialBinary::ModuleHeader* header, RiffCo if (dataChunk->m_fourCC == SLANG_MAKE_COMPRESSED_FOUR_CC(dataChunk->m_fourCC)) { // If it has compression, use the compression type set in the header - compressionType = Bin::CompressionType(header->m_compressionType); + compressionType = Bin::CompressionType(header->compressionType); } ListResizerForType resizer(arrayOut); return _readArrayChunk(compressionType, dataChunk, resizer); @@ -1191,7 +1191,7 @@ static Result _readInstArrayChunk(const IRSerialBinary::ModuleHeader* moduleHead Bin::CompressionType compressionType = Bin::CompressionType::None; if (chunk->m_fourCC == SLANG_MAKE_COMPRESSED_FOUR_CC(chunk->m_fourCC)) { - compressionType = Bin::CompressionType(moduleHeader->m_compressionType); + compressionType = Bin::CompressionType(moduleHeader->compressionType); } switch (compressionType) @@ -1208,7 +1208,7 @@ static Result _readInstArrayChunk(const IRSerialBinary::ModuleHeader* moduleHead Bin::CompressedArrayHeader header; SLANG_RETURN_ON_FAIL(read.read(header)); - arrayOut.setCount(header.m_numEntries); + arrayOut.setCount(header.numEntries); SLANG_RETURN_ON_FAIL(_decodeInsts(compressionType, read.getData(), read.getRemainingSize(), arrayOut)); break; @@ -1357,6 +1357,51 @@ static int _calcFixSourceLoc(const IRSerialData::DebugSourceInfo& info, SourceVi return int(sourceView->getRange().begin.getRaw()) - int(info.m_startSourceLoc); } +/* static */Result IRSerialReader::readStreamModules(Stream* stream, Session* session, SourceManager* sourceManager, List>& outModules) +{ + // Load up the module + RiffContainer container; + SLANG_RETURN_ON_FAIL(RiffUtil::read(stream, container)); + + List moduleChunks; + // First try to find a list + { + RiffContainer::ListChunk* listChunk = container.getRoot()->findListRec(IRSerialBinary::kSlangModuleListFourCc); + if (listChunk) + { + listChunk->findContained(IRSerialBinary::kSlangModuleFourCc, moduleChunks); + } + else + { + // Maybe its just a single module + RiffContainer::ListChunk* moduleChunk = container.getRoot()->findListRec(IRSerialBinary::kSlangModuleFourCc); + if (!moduleChunk) + { + // Couldn't find any modules + return SLANG_FAIL; + } + moduleChunks.add(moduleChunk); + } + } + + // Okay, we need to decode into ir modules + for (auto moduleChunk : moduleChunks) + { + IRSerialData serialData; + + SLANG_RETURN_ON_FAIL(IRSerialReader::readContainer(moduleChunk, &serialData)); + + // Construct into a module + RefPtr irModule; + IRSerialReader reader; + SLANG_RETURN_ON_FAIL(reader.read(serialData, session, sourceManager, irModule)); + + outModules.add(irModule); + } + + return SLANG_OK; +} + /* static */Result IRSerialReader::read(const IRSerialData& data, Session* session, SourceManager* sourceManager, RefPtr& moduleOut) { typedef Ser::Inst::PayloadType PayloadType; diff --git a/source/slang/slang-ir-serialize.h b/source/slang/slang-ir-serialize.h index ed9441874..d1f78d5f8 100644 --- a/source/slang/slang-ir-serialize.h +++ b/source/slang/slang-ir-serialize.h @@ -357,42 +357,44 @@ struct IRSerialBinary VariableByteLite, }; - static const uint32_t kRiffFourCc = RiffFourCC::kRiff; + static const FourCC kRiffFourCc = RiffFourCC::kRiff; - static const uint32_t kSlangModuleFourCc = SLANG_FOUR_CC('S', 'L', 'm', 'd'); ///< Holds all the slang specific chunks + static const FourCC kSlangModuleListFourCc = SLANG_FOUR_CC('S', 'L', 'm', 'l'); - static const uint32_t kSlangModuleHeaderFourCc = SLANG_FOUR_CC('S', 'L', 'h', 'd'); + static const FourCC kSlangModuleFourCc = SLANG_FOUR_CC('S', 'L', 'm', 'd'); ///< Holds all the slang specific chunks - static const uint32_t kInstFourCc = SLANG_FOUR_CC('S', 'L', 'i', 'n'); - static const uint32_t kChildRunFourCc = SLANG_FOUR_CC('S', 'L', 'c', 'r'); - static const uint32_t kExternalOperandsFourCc = SLANG_FOUR_CC('S', 'L', 'e', 'o'); + static const FourCC kSlangModuleHeaderFourCc = SLANG_FOUR_CC('S', 'L', 'h', 'd'); - static const uint32_t kCompressedInstFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kInstFourCc); - static const uint32_t kCompressedChildRunFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kChildRunFourCc); - static const uint32_t kCompressedExternalOperandsFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kExternalOperandsFourCc); + static const FourCC kInstFourCc = SLANG_FOUR_CC('S', 'L', 'i', 'n'); + static const FourCC kChildRunFourCc = SLANG_FOUR_CC('S', 'L', 'c', 'r'); + static const FourCC kExternalOperandsFourCc = SLANG_FOUR_CC('S', 'L', 'e', 'o'); - static const uint32_t kStringFourCc = SLANG_FOUR_CC('S', 'L', 's', 't'); + static const FourCC kCompressedInstFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kInstFourCc); + static const FourCC kCompressedChildRunFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kChildRunFourCc); + static const FourCC kCompressedExternalOperandsFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kExternalOperandsFourCc); - static const uint32_t kUInt32SourceLocFourCc = SLANG_FOUR_CC('S', 'r', 's', '4'); + static const FourCC kStringFourCc = SLANG_FOUR_CC('S', 'L', 's', 't'); - static const uint32_t kDebugStringFourCc = SLANG_FOUR_CC('S', 'd', 's', 't'); - static const uint32_t kDebugLineInfoFourCc = SLANG_FOUR_CC('S', 'd', 'l', 'n'); - static const uint32_t kDebugAdjustedLineInfoFourCc = SLANG_FOUR_CC('S', 'd', 'a', 'l'); - static const uint32_t kDebugSourceInfoFourCc = SLANG_FOUR_CC('S', 'd', 's', 'o'); - static const uint32_t kDebugSourceLocRunFourCc = SLANG_FOUR_CC('S', 'd', 's', 'r'); + static const FourCC kUInt32SourceLocFourCc = SLANG_FOUR_CC('S', 'r', 's', '4'); + + static const FourCC kDebugStringFourCc = SLANG_FOUR_CC('S', 'd', 's', 't'); + static const FourCC kDebugLineInfoFourCc = SLANG_FOUR_CC('S', 'd', 'l', 'n'); + static const FourCC kDebugAdjustedLineInfoFourCc = SLANG_FOUR_CC('S', 'd', 'a', 'l'); + static const FourCC kDebugSourceInfoFourCc = SLANG_FOUR_CC('S', 'd', 's', 'o'); + static const FourCC kDebugSourceLocRunFourCc = SLANG_FOUR_CC('S', 'd', 's', 'r'); struct ModuleHeader { - uint32_t m_compressionType; ///< Holds the compression type used (if used at all) + uint32_t compressionType; ///< Holds the compression type used (if used at all) }; struct ArrayHeader { - uint32_t m_numEntries; + uint32_t numEntries; }; struct CompressedArrayHeader { - uint32_t m_numEntries; ///< The number of entries - uint32_t m_numCompressedEntries; ///< The amount of compressed entries + uint32_t numEntries; ///< The number of entries + uint32_t numCompressedEntries; ///< The amount of compressed entries }; }; @@ -501,12 +503,17 @@ struct IRSerialReader /// Read a stream to fill in dataOut IRSerialData static Result readStream(Stream* stream, IRSerialData* dataOut); + /// Read potentially multiple modules from a stream + static Result readStreamModules(Stream* stream, Session* session, SourceManager* manager, List>& outModules); + /// Read a stream to fill in dataOut IRSerialData static Result readContainer(RiffContainer::ListChunk* module, IRSerialData* outData); /// Read a module from serial data Result read(const IRSerialData& data, Session* session, SourceManager* sourceManager, RefPtr& moduleOut); + + /// Get the representation cache StringRepresentationCache& getStringRepresentationCache() { return m_stringRepresentationCache; } diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index e9a8e7e04..76ebcca52 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -11,6 +11,7 @@ #include "slang-file-system.h" #include "slang-state-serialize.h" +#include "slang-ir-serialize.h" #include @@ -857,6 +858,26 @@ struct OptionsParser return SLANG_FAIL; } } + else if (argStr == "-r") + { + String moduleName; + SLANG_RETURN_ON_FAIL(tryReadCommandLineArgument(sink, arg, &argCursor, argEnd, moduleName)); + + // We need to deserialize and add the modules + FileStream fileStream(moduleName, FileMode::Open, FileAccess::Read, FileShare::ReadWrite); + + List> irModules; + if (SLANG_FAILED(IRSerialReader::readStreamModules(&fileStream, asInternal(session), requestImpl->getFrontEndReq()->getSourceManager(), irModules))) + { + sink->diagnose(SourceLoc(), Diagnostics::unableToReadModuleContainer, moduleName); + return SLANG_FAIL; + } + + // TODO(JS): May be better to have a ITypeComponent that encapsulates a collection of modules + // For now just add to the linkage + auto linkage = requestImpl->getLinkage(); + linkage->m_libModules.addRange(irModules.getBuffer(), irModules.getCount()); + } else if (argStr == "-v") { sink->diagnoseRaw(Severity::Note, session->getBuildTagString()); diff --git a/tests/serialization/serialized-module-test.slang b/tests/serialization/serialized-module-test.slang new file mode 100644 index 000000000..63c31e039 --- /dev/null +++ b/tests/serialization/serialized-module-test.slang @@ -0,0 +1,35 @@ +// serialized-module-test.slang + +// A test to try out the basics of module +// serialization. + +//TEST:SIMPLE_EX: tests/serialization/serialized-module.slang -o tests/serialization/serialized-module.slang-module +//TEST:COMPARE_COMPUTE_EX:-slang -compute -xslang -r -xslang tests/serialization/serialized-module.slang-module + +//import serialized_module; + +// This is fragile - needs match the definition in serialized_module +struct Thing +{ + int a; + int b; +}; + +// TODO: need to get the name mangling to line up! +int foo(Thing thing); + +//TEST_INPUT:ubuffer(data=[0 0 0 0 ], stride=4):dxbinding(0),glbinding(0),out,name outputBuffer +RWStructuredBuffer outputBuffer; + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + Thing thing; + + int index = (int)dispatchThreadID.x; + + thing.a = index; + thing.b = -index; + + outputBuffer[index] = foo(thing); +} diff --git a/tests/serialization/serialized-module-test.slang.expected.txt b/tests/serialization/serialized-module-test.slang.expected.txt new file mode 100644 index 000000000..bc856dafa --- /dev/null +++ b/tests/serialization/serialized-module-test.slang.expected.txt @@ -0,0 +1,4 @@ +0 +1 +2 +3 diff --git a/tests/serialization/serialized-module.slang b/tests/serialization/serialized-module.slang new file mode 100644 index 000000000..e94edf8d4 --- /dev/null +++ b/tests/serialization/serialized-module.slang @@ -0,0 +1,15 @@ +//TEST_IGNORE_FILE: + +// serialized-module.slang + +struct Thing +{ + int a; + int b; +}; + +int foo(Thing thing) +{ + return (thing.a + thing.b) - thing.b; +} + -- cgit v1.2.3