diff options
Diffstat (limited to 'source/slang')
| -rw-r--r-- | source/slang/slang-check-shader.cpp | 47 | ||||
| -rw-r--r-- | source/slang/slang-compiler.cpp | 50 | ||||
| -rw-r--r-- | source/slang/slang-compiler.h | 21 | ||||
| -rw-r--r-- | source/slang/slang-ir-serialize.cpp | 32 | ||||
| -rw-r--r-- | source/slang/slang-ir-serialize.h | 4 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 6 | ||||
| -rw-r--r-- | source/slang/slang-options.cpp | 14 | ||||
| -rw-r--r-- | source/slang/slang-parameter-binding.cpp | 39 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 39 |
9 files changed, 204 insertions, 48 deletions
diff --git a/source/slang/slang-check-shader.cpp b/source/slang/slang-check-shader.cpp index 4917cc067..2ac449e83 100644 --- a/source/slang/slang-check-shader.cpp +++ b/source/slang/slang-check-shader.cpp @@ -1382,6 +1382,19 @@ static bool doesParameterMatch( } } + // Also consider entry points that were introduced via adding + // a library reference... + // + for( auto extraEntryPoint : compileRequest->m_extraEntryPoints ) + { + auto entryPoint = EntryPoint::createDummyForDeserialize( + linkage, + extraEntryPoint.name, + extraEntryPoint.profile, + extraEntryPoint.mangledName); + allComponentTypes.add(entryPoint); + } + if(allComponentTypes.getCount() > 1) { auto composite = CompositeComponentType::create( @@ -1998,9 +2011,29 @@ static bool doesParameterMatch( allComponentTypes.add(specializedGlobalComponentType); auto unspecializedGlobalAndEntryPointsComponentType = endToEndReq->getUnspecializedGlobalAndEntryPointsComponentType(); - auto entryPointCount = unspecializedGlobalAndEntryPointsComponentType->getEntryPointCount(); - for(Index ii = 0; ii < entryPointCount; ++ii) + // It is possible that there were entry points other than those specified + // vai the original end-to-end compile request. In particular: + // + // * It is possible to compile with *no* entry points specified, in which + // case the current compiler behavior is to use any entry points marked + // via `[shader(...)]` attributes in the AST. + // + // * It is possible for entry points to come into play via serialized libraries + // loaded with `-r` on the command line (or the equivalent API). + // + // We will thus draw a distinction between the "specified" entry points, + // and the "found" entry points. + // + auto specifiedEntryPointCount = endToEndReq->entryPoints.getCount(); + auto foundEntryPointCount = unspecializedGlobalAndEntryPointsComponentType->getEntryPointCount(); + + SLANG_ASSERT(foundEntryPointCount >= specifiedEntryPointCount); + + // For any entry points that were specified, we can use the specialization + // argument information provided via API or command line. + // + for(Index ii = 0; ii < specifiedEntryPointCount; ++ii) { auto& entryPointInfo = endToEndReq->entryPoints[ii]; auto unspecializedEntryPoint = unspecializedGlobalAndEntryPointsComponentType->getEntryPoint(ii); @@ -2011,6 +2044,16 @@ static bool doesParameterMatch( outSpecializedEntryPoints.add(specializedEntryPoint); } + // Any entry points beyond those that were specified up front will be + // assumed to not need/want specialization. + // + for( Index ii = specifiedEntryPointCount; ii < foundEntryPointCount; ++ii ) + { + auto unspecializedEntryPoint = unspecializedGlobalAndEntryPointsComponentType->getEntryPoint(ii); + allComponentTypes.add(unspecializedEntryPoint); + outSpecializedEntryPoints.add(unspecializedEntryPoint); + } + RefPtr<ComponentType> composed = CompositeComponentType::create(endToEndReq->getLinkage(), allComponentTypes); return composed; } diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 74075bb51..ba2ad1dd8 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -250,6 +250,7 @@ namespace Slang funcDeclRef.GetName(), profile, funcDeclRef); + entryPoint->m_mangledName = getMangledName(funcDeclRef); return entryPoint; } @@ -266,6 +267,21 @@ namespace Slang return entryPoint; } + RefPtr<EntryPoint> EntryPoint::createDummyForDeserialize( + Linkage* linkage, + Name* name, + Profile profile, + String mangledName) + { + RefPtr<EntryPoint> entryPoint = new EntryPoint( + linkage, + name, + profile, + DeclRef<FuncDecl>()); + entryPoint->m_mangledName = mangledName; + return entryPoint; + } + EntryPoint::EntryPoint( Linkage* linkage, Name* name, @@ -338,16 +354,7 @@ namespace Slang SLANG_UNUSED(index); SLANG_ASSERT(index == 0); - // Note: this routine might get called on the "dummy" - // `EntryPoint` objects we create when doing pass-through - // compilation, in which case there won't be any - // function decl to be referenced and thus have - // its mangled name computed. - // - if(auto funcDeclRef = getFuncDeclRef()) - return getMangledName(funcDeclRef); - else - return String(); + return m_mangledName; } void EntryPoint::acceptVisitor(ComponentTypeVisitor* visitor, SpecializationInfo* specializationInfo) @@ -2255,6 +2262,29 @@ SlangResult dissassembleDXILUsingDXC( SLANG_RETURN_ON_FAIL(writer.write(irModule, sourceManager, optionFlags, &serialData)); SLANG_RETURN_ON_FAIL(IRSerialWriter::writeContainer(serialData, compressionType, &container)); } + + auto entryPointCount = program->getEntryPointCount(); + for( Index ii = 0; ii < entryPointCount; ++ii ) + { + auto entryPoint = program->getEntryPoint(ii); + auto entryPointMangledName = program->getEntryPointMangledName(ii); + + RiffContainer::ScopeChunk entryPointScope(&container, RiffContainer::Chunk::Kind::Data, IRSerialBinary::kEntryPointFourCc); + + auto writeString = [&](String const& str) + { + uint32_t length = (uint32_t) str.getLength(); + container.write(&length, sizeof(length)); + container.write(str.getBuffer(), length+1); + }; + + writeString(entryPoint->getName()->text); + + Profile profile = entryPoint->getProfile(); + container.write(&profile, sizeof(profile)); + + writeString(entryPointMangledName); + } } // We now write the RiffContainer to the stream diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 2819269b5..e3fbf57f6 100644 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -695,6 +695,13 @@ namespace Slang Name* name, Profile profile); + /// Create a dummy `EntryPoint` that stands in for a serialized entry point + static RefPtr<EntryPoint> createDummyForDeserialize( + Linkage* linkage, + Name* name, + Profile profile, + String mangledName); + /// Get the number of existential type parameters for the entry point. Index getSpecializationParamCount() SLANG_OVERRIDE; @@ -752,6 +759,9 @@ namespace Slang // DeclRef<FuncDecl> m_funcDeclRef; + /// The mangled name of the entry point function + String m_mangledName; + SpecializationParams m_genericSpecializationParams; SpecializationParams m_existentialSpecializationParams; @@ -1445,6 +1455,17 @@ namespace Slang Name* m_defaultModuleName = nullptr; + /// An "extra" entry point that was added via a library reference + struct ExtraEntryPointInfo + { + Name* name; + Profile profile; + String mangledName; + }; + + /// A list of "extra" entry points added via a library reference + List<ExtraEntryPointInfo> m_extraEntryPoints; + private: /// A component type that includes only the global scopes of the translation unit(s) that were compiled. RefPtr<ComponentType> m_globalComponentType; diff --git a/source/slang/slang-ir-serialize.cpp b/source/slang/slang-ir-serialize.cpp index 5c16f70f3..fcde8dcda 100644 --- a/source/slang/slang-ir-serialize.cpp +++ b/source/slang/slang-ir-serialize.cpp @@ -1357,19 +1357,25 @@ 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<RefPtr<IRModule>>& outModules) +// TODO: The following function isn't really part of the IR serialization system, but rather +// a layered "container" format, and as such probably belongs in a higher-level system that +// simply calls into the `IRSerialReader` rather than being part of it... +// +/* static */Result IRSerialReader::readStreamModules(Stream* stream, Session* session, SourceManager* sourceManager, List<RefPtr<IRModule>>& outModules, List<FrontEndCompileRequest::ExtraEntryPointInfo>& outEntryPoints) { // Load up the module RiffContainer container; SLANG_RETURN_ON_FAIL(RiffUtil::read(stream, container)); List<RiffContainer::ListChunk*> moduleChunks; + List<RiffContainer::DataChunk*> entryPointChunks; // First try to find a list { RiffContainer::ListChunk* listChunk = container.getRoot()->findListRec(IRSerialBinary::kSlangModuleListFourCc); if (listChunk) { listChunk->findContained(IRSerialBinary::kSlangModuleFourCc, moduleChunks); + listChunk->findContained(IRSerialBinary::kEntryPointFourCc, entryPointChunks); } else { @@ -1399,6 +1405,30 @@ static int _calcFixSourceLoc(const IRSerialData::DebugSourceInfo& info, SourceVi outModules.add(irModule); } + for( auto entryPointChunk : entryPointChunks ) + { + auto reader = entryPointChunk->asReadHelper(); + + auto readString = [&]() + { + uint32_t length = 0; + reader.read(length); + + char* begin = (char*) reader.getData(); + reader.skip(length+1); + + return UnownedStringSlice(begin, begin + length); + }; + + FrontEndCompileRequest::ExtraEntryPointInfo entryPointInfo; + + entryPointInfo.name = session->getNamePool()->getName(readString()); + reader.read(entryPointInfo.profile); + entryPointInfo.mangledName = readString(); + + outEntryPoints.add(entryPointInfo); + } + return SLANG_OK; } diff --git a/source/slang/slang-ir-serialize.h b/source/slang/slang-ir-serialize.h index d1f78d5f8..644e533ae 100644 --- a/source/slang/slang-ir-serialize.h +++ b/source/slang/slang-ir-serialize.h @@ -383,6 +383,8 @@ struct IRSerialBinary static const FourCC kDebugSourceInfoFourCc = SLANG_FOUR_CC('S', 'd', 's', 'o'); static const FourCC kDebugSourceLocRunFourCc = SLANG_FOUR_CC('S', 'd', 's', 'r'); + static const FourCC kEntryPointFourCc = SLANG_FOUR_CC('E', 'P', 'n', 't'); + struct ModuleHeader { uint32_t compressionType; ///< Holds the compression type used (if used at all) @@ -504,7 +506,7 @@ struct IRSerialReader static Result readStream(Stream* stream, IRSerialData* dataOut); /// Read potentially multiple modules from a stream - static Result readStreamModules(Stream* stream, Session* session, SourceManager* manager, List<RefPtr<IRModule>>& outModules); + static Result readStreamModules(Stream* stream, Session* session, SourceManager* manager, List<RefPtr<IRModule>>& outModules, List<FrontEndCompileRequest::ExtraEntryPointInfo>& outEntryPoints); /// Read a stream to fill in dataOut IRSerialData static Result readContainer(RiffContainer::ListChunk* module, IRSerialData* outData); diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index f50bd8be1..f9d39993a 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -7265,6 +7265,12 @@ RefPtr<IRModule> TargetProgram::createIRModuleForLayout(DiagnosticSink* sink) { auto funcDeclRef = entryPointLayout->entryPoint; + // HACK: skip over entry points that came from deserialization, + // and thus don't have AST-level information for us to work with. + // + if(!funcDeclRef) + continue; + auto irFuncType = lowerType(context, getFuncType(session, funcDeclRef)); auto irFunc = getSimpleVal(context, emitDeclRef(context, funcDeclRef, irFuncType)); diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index 915bea726..082973947 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -19,6 +19,8 @@ namespace Slang { +SlangResult _addLibraryReference(EndToEndCompileRequest* req, Stream* stream); + SlangResult tryReadCommandLineArgumentRaw(DiagnosticSink* sink, char const* option, char const* const**ioCursor, char const* const*end, char const** argOut) { *argOut = nullptr; @@ -917,17 +919,9 @@ struct OptionsParser // We need to deserialize and add the modules FileStream fileStream(referenceModuleName, FileMode::Open, FileAccess::Read, FileShare::ReadWrite); - List<RefPtr<IRModule>> irModules; - if (SLANG_FAILED(IRSerialReader::readStreamModules(&fileStream, asInternal(session), requestImpl->getFrontEndReq()->getSourceManager(), irModules))) - { - sink->diagnose(SourceLoc(), Diagnostics::unableToReadModuleContainer, referenceModuleName); - return SLANG_FAIL; - } + // TODO: probalby near an error when we can't open the file? - // 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()); + _addLibraryReference(requestImpl, &fileStream); } else if (argStr == "-v") { diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp index a2353824c..33ad32918 100644 --- a/source/slang/slang-parameter-binding.cpp +++ b/source/slang/slang-parameter-binding.cpp @@ -2161,8 +2161,37 @@ static RefPtr<EntryPointLayout> collectEntryPointParameters( EntryPoint* entryPoint, EntryPoint::EntryPointSpecializationInfo* specializationInfo) { + // We will take responsibility for creating and filling in + // the `EntryPointLayout` object here. + // + RefPtr<EntryPointLayout> entryPointLayout = new EntryPointLayout(); + entryPointLayout->profile = entryPoint->getProfile(); + + // The entry point layout must be added to the output + // program layout so that it can be accessed by reflection. + // + context->shared->programLayout->entryPoints.add(entryPointLayout); + DeclRef<FuncDecl> entryPointFuncDeclRef = entryPoint->getFuncDeclRef(); + // HACK: We might have an `EntryPoint` that has been deserialized, in + // which case we don't currently have access to its AST-level information, + // and as a result we cannot collect parameter information from it. + // + if( !entryPointFuncDeclRef ) + { + // TODO: figure out what fields we absolutely need to fill in. + + RefPtr<StructTypeLayout> paramsTypeLayout = new StructTypeLayout(); + + RefPtr<VarLayout> paramsLayout = new VarLayout(); + paramsLayout->typeLayout = paramsTypeLayout; + + entryPointLayout->parametersLayout = paramsLayout; + + return entryPointLayout; + } + // If specialization was applied to the entry point, then the side-band // information that was generated will have a more specialized reference // to the entry point with generic parameters filled in. We should @@ -2173,18 +2202,8 @@ static RefPtr<EntryPointLayout> collectEntryPointParameters( auto entryPointType = DeclRefType::Create(context->getLinkage()->getSessionImpl(), entryPointFuncDeclRef); - // We will take responsibility for creating and filling in - // the `EntryPointLayout` object here. - // - RefPtr<EntryPointLayout> entryPointLayout = new EntryPointLayout(); - entryPointLayout->profile = entryPoint->getProfile(); entryPointLayout->entryPoint = entryPointFuncDeclRef; - // The entry point layout must be added to the output - // program layout so that it can be accessed by reflection. - // - context->shared->programLayout->entryPoints.add(entryPointLayout); - // For the duration of our parameter collection work we will // establish this entry point as the current one in the context. // diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index ab1b0e489..6632f2fa3 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -3041,21 +3041,14 @@ SLANG_API void spSetDefaultModuleName( frontEndReq->m_defaultModuleName = namePool->getName(defaultModuleName); } - -SLANG_API SlangResult spAddLibraryReference( - SlangCompileRequest* request, - const void* libData, - size_t libDataSize) +namespace Slang +{ +SlangResult _addLibraryReference(EndToEndCompileRequest* req, Stream* stream) { - using namespace Slang; - auto req = Slang::asInternal(request); - - // We need to deserialize and add the modules - MemoryStreamBase fileStream(FileAccess::Read, libData, libDataSize); - // Read all of the contained modules List<RefPtr<IRModule>> irModules; - if (SLANG_FAILED(IRSerialReader::readStreamModules(&fileStream, req->getSession(), req->getFrontEndReq()->getSourceManager(), irModules))) + List<FrontEndCompileRequest::ExtraEntryPointInfo> entryPointMangledNames; + if (SLANG_FAILED(IRSerialReader::readStreamModules(stream, req->getSession(), req->getFrontEndReq()->getSourceManager(), irModules, entryPointMangledNames))) { req->getSink()->diagnose(SourceLoc(), Diagnostics::unableToAddReferenceToModuleContainer); return SLANG_FAIL; @@ -3064,10 +3057,28 @@ SLANG_API SlangResult spAddLibraryReference( // TODO(JS): May be better to have a ITypeComponent that encapsulates a collection of modules // For now just add to the linkage auto linkage = req->getLinkage(); - linkage->m_libModules.addRange(irModules.getBuffer(), irModules.getCount()); + linkage->m_libModules.addRange(irModules); + + req->getFrontEndReq()->m_extraEntryPoints.addRange(entryPointMangledNames); return SLANG_OK; } +} + + +SLANG_API SlangResult spAddLibraryReference( + SlangCompileRequest* request, + const void* libData, + size_t libDataSize) +{ + using namespace Slang; + auto req = Slang::asInternal(request); + + // We need to deserialize and add the modules + MemoryStreamBase fileStream(FileAccess::Read, libData, libDataSize); + + return _addLibraryReference(req, &fileStream); +} SLANG_API void spTranslationUnit_addPreprocessorDefine( SlangCompileRequest* request, @@ -3417,7 +3428,7 @@ SLANG_API void const* spGetEntryPointCode( if(entryPointIndex < 0) return nullptr; - if(Index(entryPointIndex) >= req->entryPoints.getCount()) return nullptr; + if(Index(entryPointIndex) >= program->getEntryPointCount()) return nullptr; auto entryPoint = program->getEntryPoint(entryPointIndex); auto targetProgram = program->getTargetProgram(targetReq); |
