From 1378fffd9da094beb41b2db89b96f556c23ab6cb Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Wed, 10 Aug 2022 10:04:06 -0400 Subject: Artifact and ICastable (#2351) * #include an absolute path didn't work - because paths were taken to always be relative. * WIP with hierarchical enums. * Some small fixes and improvements around artifact desc related types. * Improvements around hierarchical enum. * Fixes to get Artifact types refactor to be able to execute tests. * Attempt to better categorize PTX. * Work around for potentially unused function warning. * Typo fix. * Simplify Artifact header. * Small improvements around Artifact kind/payload/style. * Added IDestroyable/ICastable * Add IArtifactList. * First impl of IArtifactUtil. * Use the ICastable interface for IArtifactRepresentation. * Added IArtifactRepresentation & IArtifactAssociated. * Add SLANG_OVERRIDE to avoid gcc/clang warning. * Fix calling convention issue on win32. * Fix missing SLANG_OVERRIDE. * First attempt at file abstraction around Artifact. * Added creation of lock file. * Move functionality for determining file paths to the IArtifactUtil. Add casting to ICastable. * Added some casting/finding mechanisms. * Simplify IArtifact interface, and use Items for file reps. * Fix problem with libraries on DXIL. * Split out ArtifactRepresentation. * Move ArtifactDesc functionality to ArtifactDescUtil. ArtifactInfoUtil becomes ArtifactDescUtil. * Split implementations from the interfaces for Artifact. * Use TypeTextUtil for target name outputting. * Add artifact impls. * Add ICastableList * Added UnknownCastableAdapter * Make ISlangSharedLibrary derive from ICastable, and remain backwards compatible with slang-llvm. * Refactor Representation on Artifact. * Make our ISlangBlobs also derive from ICastable. Make ISlangBlob atomic ref counted. * Fix typo. --- source/compiler-core/slang-artifact-desc-util.cpp | 4 +- source/compiler-core/slang-artifact-impl.cpp | 515 ++++++++++++++++++--- source/compiler-core/slang-artifact-impl.h | 103 ++++- source/compiler-core/slang-artifact-util.cpp | 10 +- source/compiler-core/slang-artifact.h | 100 ++-- source/compiler-core/slang-downstream-compiler.cpp | 2 +- source/compiler-core/slang-glslang-compiler.cpp | 2 +- source/compiler-core/slang-nvrtc-compiler.cpp | 2 +- 8 files changed, 597 insertions(+), 141 deletions(-) (limited to 'source/compiler-core') diff --git a/source/compiler-core/slang-artifact-desc-util.cpp b/source/compiler-core/slang-artifact-desc-util.cpp index e382ca08c..413858c32 100644 --- a/source/compiler-core/slang-artifact-desc-util.cpp +++ b/source/compiler-core/slang-artifact-desc-util.cpp @@ -618,7 +618,7 @@ UnownedStringSlice ArtifactDescUtil::getDefaultExtension(const ArtifactDesc& des /* static */String ArtifactDescUtil::getBaseName(IArtifact* artifact) { - if (auto fileRep = findItem(artifact)) + if (auto fileRep = findRepresentation(artifact)) { return getBaseName(artifact->getDesc(), fileRep); } @@ -634,7 +634,7 @@ UnownedStringSlice ArtifactDescUtil::getDefaultExtension(const ArtifactDesc& des /* static */String ArtifactDescUtil::getParentPath(IArtifact* artifact) { - if (auto fileRep = findItem(artifact)) + if (auto fileRep = findRepresentation(artifact)) { return getParentPath(fileRep); } diff --git a/source/compiler-core/slang-artifact-impl.cpp b/source/compiler-core/slang-artifact-impl.cpp index 8dbae063b..d57edd2c8 100644 --- a/source/compiler-core/slang-artifact-impl.cpp +++ b/source/compiler-core/slang-artifact-impl.cpp @@ -7,6 +7,367 @@ namespace Slang { +/* +If we use LazyCastableList for Items, it means we'll have to use the +UnknownCastableAdapter for ISharedLibrary, IBlob etc. + +That means when we look for an item in the list, we will always do a query interface on those types, +although it will always fail (so no atomic ref count). + +That doesn't seem wholey unreasonable. + +Note that we *can* derive from ICastable for *our* implementations of ISlangBlob, ISharedLibrary. So the +kludge is only needed for types that really do require adaption. For Blob we'll require multiple interface inheritance. +*/ + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! LazyCastableList !!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void LazyCastableList::removeAt(Index index) +{ + SLANG_ASSERT(index >= 0 && index < getCount()); + + if (auto list = as(m_castable)) + { + list->removeAt(index); + } + else + { + SLANG_ASSERT(index == 0); + m_castable.setNull(); + } +} + +void LazyCastableList::clear() +{ + if (m_castable) + { + if (auto list = as(m_castable)) + { + list->clear(); + } + else + { + m_castable.setNull(); + } + } +} + +void LazyCastableList::clearAndDeallocate() +{ + m_castable.setNull(); +} + +Count LazyCastableList::getCount() const +{ + if (m_castable) + { + if (auto list = as(m_castable)) + { + return list->getCount(); + } + return 1; + } + return 0; +} + +void LazyCastableList::add(ICastable* castable) +{ + SLANG_ASSERT(castable); + SLANG_ASSERT(castable != m_castable); + + if (m_castable) + { + if (auto list = as(m_castable)) + { + // Shouldn't be in the list + SLANG_ASSERT(list->indexOf(castable) < 0); + list->add(castable); + } + else + { + list = new CastableList; + list->add(m_castable); + m_castable = list; + list->add(castable); + } + } + else + { + m_castable = castable; + } +} + +ICastableList* LazyCastableList::requireList() +{ + if (m_castable) + { + if (auto list = as(m_castable)) + { + return list; + } + else + { + // Promote to a list with the element in it + list = new CastableList; + list->add(m_castable); + m_castable = list; + return list; + } + } + else + { + // Create an empty list + ICastableList* list = new CastableList; + m_castable = list; + return list; + } +} + +ICastableList* LazyCastableList::getList() +{ + return (m_castable == nullptr) ? nullptr : requireList(); +} + +void* LazyCastableList::find(const Guid& guid) +{ + if (!m_castable) + { + return nullptr; + } + if (auto list = as(m_castable)) + { + return list->find(guid); + } + else + { + return m_castable->castAs(guid); + } +} + +ConstArrayView LazyCastableList::getView() const +{ + if (!m_castable) + { + // Empty + return ConstArrayView(); + } + + if (auto list = as(m_castable)) + { + const auto count = list->getCount(); + const auto buffer = list->getBuffer(); + + return ConstArrayView(buffer, count); + } + else + { + return ConstArrayView((ICastable*const*)&m_castable, 1); + } +} + +Index LazyCastableList::indexOf(ICastable* castable) const +{ + return getView().indexOf(castable); +} + +Index LazyCastableList::indexOfUnknown(ISlangUnknown* unk) const +{ + { + ComPtr castable; + if (SLANG_SUCCEEDED(unk->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable) + { + return indexOf(castable); + } + } + + // It's not derived from ICastable, so can only be in list via an adapter + const auto view = getView(); + + const Count count = view.getCount(); + for (Index i = 0; i < count; ++i) + { + auto adapter = as(view[i]); + if (adapter && adapter->getContained() == unk) + { + return i; + } + } + + return -1; +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! UnknownCastableAdapter !!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void* UnknownCastableAdapter::castAs(const Guid& guid) +{ + if (auto intf = getInterface(guid)) + { + return intf; + } + if (auto obj = getObject(guid)) + { + return obj; + } + + if (m_found && guid == m_foundGuid) + { + return m_found; + } + + ComPtr cast; + if (SLANG_SUCCEEDED(m_contained->queryInterface(guid, (void**)cast.writeRef())) && cast) + { + // Save the interface in the cache + m_found = cast; + m_foundGuid = guid; + + return cast; + } + return nullptr; +} + +void* UnknownCastableAdapter::getInterface(const Guid& guid) +{ + if (guid == ISlangUnknown::getTypeGuid() || + guid == ICastable::getTypeGuid()) + { + return static_cast(this); + } + return nullptr; +} + +void* UnknownCastableAdapter::getObject(const Guid& guid) +{ + SLANG_UNUSED(guid); + return nullptr; +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CastableList !!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +CastableList::~CastableList() +{ + for (auto castable : m_list) + { + castable->release(); + } +} + +void* CastableList::castAs(const Guid& guid) +{ + if (auto intf = getInterface(guid)) + { + return intf; + } + return getObject(guid); +} + +void* CastableList::getInterface(const Guid& guid) +{ + if (guid == ISlangUnknown::getTypeGuid() || + guid == ICastable::getTypeGuid() || + guid == ICastableList::getTypeGuid()) + { + return static_cast(this); + } + return nullptr; +} + +void* CastableList::getObject(const Guid& guid) +{ + SLANG_UNUSED(guid); + return nullptr; +} + +void* CastableList::find(const Guid& guid) +{ + for (ICastable* castable : m_list) + { + if (auto ptr = castable->castAs(guid)) + { + return ptr; + } + } + return nullptr; +} + +Index CastableList::indexOf(ICastable* castable) +{ + const Count count = m_list.getCount(); + for (Index i = 0; i < count; ++i) + { + ICastable* cur = m_list[i]; + if (cur == castable) + { + return i; + } + } + return -1; +} + +void CastableList::add(ICastable* castable) +{ + SLANG_ASSERT(castable); + castable->addRef(); + m_list.add(castable); +} + +void CastableList::removeAt(Index i) +{ + auto castable = m_list[i]; + m_list.removeAt(i); + castable->release(); +} + +void CastableList::clear() +{ + for (auto castable : m_list) + { + castable->release(); + } + m_list.clear(); +} + +void CastableList::addUnknown(ISlangUnknown* unk) +{ + // If it has ICastable interface we can just add as that + { + ComPtr castable; + if (SLANG_SUCCEEDED(unk->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable) + { + return add(castable); + } + } + + // Wrap it in an adapter + IUnknownCastableAdapter* adapter = new UnknownCastableAdapter(unk); + add(adapter); +} + +Index CastableList::indexOfUnknown(ISlangUnknown* unk) +{ + SLANG_ASSERT(unk); + // If it has a castable interface we can just look for that + { + ComPtr castable; + if (SLANG_SUCCEEDED(unk->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable) + { + return indexOf(castable); + } + } + + // It's not derived from ICastable, so can only be in list via an adapter + const Count count = m_list.getCount(); + for (Index i = 0; i < count; ++i) + { + auto adapter = as(m_list[i]); + if (adapter && adapter->getContained() == unk) + { + return i; + } + } + return -1; +} + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactList !!!!!!!!!!!!!!!!!!!!!!!!!!! */ void* ArtifactList::getInterface(const Guid& guid) @@ -91,86 +452,24 @@ void* Artifact::getInterface(const Guid& uuid) bool Artifact::exists() { - for (ISlangUnknown* item : m_items) + for (auto rep : m_representations.getView()) { - ComPtr castable; - - if (SLANG_SUCCEEDED(item->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable) + if (auto artifactRep = as(rep)) { - auto rep = as(castable); - if (rep) + // It is an artifact rep and it exists, we are done + if (artifactRep->exists()) { - // It is a rep and it exists - if (rep->exists()) - { - return true; - } - continue; - } - // Associated types don't encapsulate an artifact representation, so don't signal existance - if (as(castable)) - { - continue; + return true; } } - - // It can't be IArtifactRepresentation or IArtifactAssociated, so we assume means it exists - return true; - } - - return false; -} - -void Artifact::addItem(ISlangUnknown* intf) -{ - SLANG_ASSERT(intf); - // Can't already be in there - SLANG_ASSERT(m_items.indexOf(intf) < 0); - // Add it - m_items.add(ComPtr(intf)); -} - -void Artifact::removeItemAt(Index i) -{ - m_items.removeAt(i); -} - -void* Artifact::findItemInterface(const Guid& guid) -{ - for (ISlangUnknown* intf : m_items) - { - ISlangUnknown* cast = nullptr; - if (SLANG_SUCCEEDED(intf->queryInterface(guid, (void**)&cast)) && cast) + else { - // NOTE! This assumes we *DONT* need to ref count to keep an interface in scope - // (as strict COM requires so as to allow on demand interfaces). - cast->release(); - return cast; + // If it's *not* IArtifactRepresentation derived, it's existance *is* a representation + return true; } } - return nullptr; -} - -void* Artifact::findItemObject(const Guid& classGuid) -{ - for (ISlangUnknown* intf : m_items) - { - ComPtr castable; - if (SLANG_SUCCEEDED(intf->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable) - { - void* obj = castable->castAs(classGuid); - // NOTE! This assumes we *DONT* need to ref count to keep an interface in scope - // (as strict COM requires so as to allow on demand interfaces). - - // If could cast return the result - if (obj) - { - return obj; - } - } - } - return nullptr; + return false; } SlangResult Artifact::requireFile(Keep keep, IFileArtifactRepresentation** outFileRep) @@ -182,7 +481,7 @@ SlangResult Artifact::requireFile(Keep keep, IFileArtifactRepresentation** outFi SlangResult Artifact::loadBlob(Keep keep, ISlangBlob** outBlob) { // If we have a blob just return it - if (auto blob = findItem(this)) + if (auto blob = (ISlangBlob*)findRepresentation(ISlangBlob::getTypeGuid())) { blob->addRef(); *outBlob = blob; @@ -192,12 +491,11 @@ SlangResult Artifact::loadBlob(Keep keep, ISlangBlob** outBlob) ComPtr blob; // Look for a representation that we can serialize into a blob - for (ISlangUnknown* intf : m_items) + for (auto rep : m_representations.getView()) { - ComPtr rep; - if (SLANG_SUCCEEDED(intf->queryInterface(IArtifactRepresentation::getTypeGuid(), (void**)rep.writeRef())) && rep) + if (auto artifactRep = as(rep)) { - SlangResult res = rep->writeToBlob(blob.writeRef()); + SlangResult res = artifactRep->writeToBlob(blob.writeRef()); if (SLANG_SUCCEEDED(res) && blob) { break; @@ -214,11 +512,74 @@ SlangResult Artifact::loadBlob(Keep keep, ISlangBlob** outBlob) // Put in cache if (canKeep(keep)) { - addItem(blob); + addRepresentationUnknown(blob); } *outBlob = blob.detach(); return SLANG_OK; } +void Artifact::addAssociated(ICastable* castable) +{ + SLANG_ASSERT(castable); + m_associated.add(castable); +} + +void* Artifact::findAssociated(const Guid& guid) +{ + return m_associated.find(guid); +} + +ICastableList* Artifact::getAssociated() +{ + return m_associated.requireList(); +} + +void Artifact::addRepresentation(IArtifactRepresentation* rep) +{ + SLANG_ASSERT(rep); + if (m_representations.indexOf(rep) >= 0) + { + SLANG_ASSERT_FAILURE("Already have this representation"); + return; + } + m_representations.add(rep); +} + +void Artifact::addRepresentationUnknown(ISlangUnknown* unk) +{ + SLANG_ASSERT(unk); + if (m_representations.indexOfUnknown(unk) >= 0) + { + SLANG_ASSERT_FAILURE("Already have this representation"); + return; + } + + ComPtr castable; + if (SLANG_SUCCEEDED(unk->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable) + { + if (m_representations.indexOf(castable) >= 0) + { + SLANG_ASSERT_FAILURE("Already have this representation"); + return; + } + m_representations.add(castable); + } + else + { + UnknownCastableAdapter* adapter = new UnknownCastableAdapter(unk); + m_representations.add(adapter); + } +} + +void* Artifact::findRepresentation(const Guid& guid) +{ + return m_representations.find(guid); +} + +ICastableList* Artifact::getRepresentations() +{ + return m_representations.requireList(); +} + } // namespace Slang diff --git a/source/compiler-core/slang-artifact-impl.h b/source/compiler-core/slang-artifact-impl.h index 35dbe5f98..79aad3b64 100644 --- a/source/compiler-core/slang-artifact-impl.h +++ b/source/compiler-core/slang-artifact-impl.h @@ -12,6 +12,89 @@ namespace Slang { +/* An adapter such that types which aren't derived from ICastable, can be used as such. + +With the following caveats. +* the interfaces/objects of the adapter are checked *first*, so IUnknown will always be for the adapter +* assumes when doing a queryInterface on the contained item +*/ +class UnknownCastableAdapter : public ComBaseObject, public IUnknownCastableAdapter +{ +public: + SLANG_COM_BASE_IUNKNOWN_ALL + + // ICastable + SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; + + // IUnknownCastableAdapter + virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getContained() SLANG_OVERRIDE { return m_contained; } + + UnknownCastableAdapter(ISlangUnknown* unk): + m_contained(unk) + { + SLANG_ASSERT(unk); + } + +protected: + void* getInterface(const Guid& guid); + void* getObject(const Guid& guid); + + ComPtr m_contained; + + // We hold a cache for a single lookup to make things a little faster + void* m_found = nullptr; + Guid m_foundGuid; +}; + +class CastableList : public ComBaseObject, public ICastableList +{ +public: + SLANG_COM_BASE_IUNKNOWN_ALL + + // ICastable + SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; + + // ICastableList + virtual Count SLANG_MCALL getCount() SLANG_OVERRIDE { return m_list.getCount(); } + virtual ICastable* SLANG_MCALL getAt(Index i) SLANG_OVERRIDE { return m_list[i]; } + virtual void SLANG_MCALL add(ICastable* castable) SLANG_OVERRIDE; + virtual void SLANG_MCALL addUnknown(ISlangUnknown* unk) SLANG_OVERRIDE; + virtual void SLANG_MCALL removeAt(Index i) SLANG_OVERRIDE; + virtual void SLANG_MCALL clear() SLANG_OVERRIDE; + virtual Index SLANG_MCALL indexOf(ICastable* castable) SLANG_OVERRIDE; + virtual Index SLANG_MCALL indexOfUnknown(ISlangUnknown* unk) SLANG_OVERRIDE; + virtual void* SLANG_MCALL find(const Guid& guid) SLANG_OVERRIDE; + virtual ICastable* const* SLANG_MCALL getBuffer() SLANG_OVERRIDE { return m_list.getBuffer(); } + + virtual ~CastableList(); + +protected: + void* getInterface(const Guid& guid); + void* getObject(const Guid& guid); + + List m_list; +}; + +class LazyCastableList +{ +public: + void add(ICastable* castable); + Count getCount() const; + void removeAt(Index index); + void clear(); + void clearAndDeallocate(); + void* find(const Guid& guid); + ConstArrayView getView() const; + Index indexOf(ICastable* castable) const; + Index indexOfUnknown(ISlangUnknown* unk) const; + + ICastableList* requireList(); + ICastableList* getList(); + +protected: + ComPtr m_castable; +}; + class ArtifactList : public ComBaseObject, public IArtifactList { public: @@ -86,12 +169,15 @@ public: virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadBlob(Keep keep, ISlangBlob** outBlob) SLANG_OVERRIDE; virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFile(Keep keep, IFileArtifactRepresentation** outFileRep) SLANG_OVERRIDE; virtual SLANG_NO_THROW const char* SLANG_MCALL getName() SLANG_OVERRIDE { return m_name.getBuffer(); } - virtual SLANG_NO_THROW void* SLANG_MCALL findItemInterface(const Guid& uuid) SLANG_OVERRIDE; - virtual SLANG_NO_THROW void* SLANG_MCALL findItemObject(const Guid& classGuid) SLANG_OVERRIDE; - virtual SLANG_NO_THROW void SLANG_MCALL addItem(ISlangUnknown* intf) SLANG_OVERRIDE; - virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getItemAt(Index i) SLANG_OVERRIDE { return m_items[i]; } - virtual SLANG_NO_THROW void SLANG_MCALL removeItemAt(Index i) SLANG_OVERRIDE; - virtual SLANG_NO_THROW Index SLANG_MCALL getItemCount() SLANG_OVERRIDE { return m_items.getCount(); } + + virtual SLANG_NO_THROW void SLANG_MCALL addAssociated(ICastable* castable) SLANG_OVERRIDE; + virtual void* SLANG_MCALL SLANG_MCALL findAssociated(const Guid& unk) SLANG_OVERRIDE; + virtual ICastableList* SLANG_MCALL getAssociated() SLANG_OVERRIDE; + + virtual SLANG_NO_THROW void SLANG_MCALL addRepresentation(IArtifactRepresentation* rep) SLANG_OVERRIDE; + virtual SLANG_NO_THROW void SLANG_MCALL addRepresentationUnknown(ISlangUnknown* rep) SLANG_OVERRIDE; + virtual void* SLANG_MCALL SLANG_MCALL findRepresentation(const Guid& guid) SLANG_OVERRIDE; + virtual ICastableList* SLANG_MCALL getRepresentations() SLANG_OVERRIDE; /// Ctor Artifact(const Desc& desc, const String& name) : @@ -108,7 +194,10 @@ protected: String m_name; ///< Name of this artifact - List> m_items; ///< Associated items + LazyCastableList m_associated; ///< Associated items + LazyCastableList m_representations; ///< Representations + + ComPtr m_children; ///< The children to this artifact }; } // namespace Slang diff --git a/source/compiler-core/slang-artifact-util.cpp b/source/compiler-core/slang-artifact-util.cpp index 9a8194969..7f69a0464 100644 --- a/source/compiler-core/slang-artifact-util.cpp +++ b/source/compiler-core/slang-artifact-util.cpp @@ -93,20 +93,16 @@ SlangResult ArtifactUtilImpl::createLockFile(const char* inNameBase, ISlangMutab SlangResult ArtifactUtilImpl::calcArtifactPath(const ArtifactDesc& desc, const char* inBasePath, ISlangBlob** outPath) { UnownedStringSlice basePath(inBasePath); - StringBuilder path; SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, basePath, path)); - - auto blob = new StringBlob(path); - blob->addRef(); - *outPath = blob; + *outPath = StringBlob::create(path).detach(); return SLANG_OK; } SlangResult ArtifactUtilImpl::requireFileDefaultImpl(IArtifact* artifact, ArtifactKeep keep, IFileArtifactRepresentation** outFile) { // See if we already have it - if (auto fileRep = findItem(artifact)) + if (auto fileRep = findRepresentation(artifact)) { fileRep->addRef(); *outFile = fileRep; @@ -143,7 +139,7 @@ SlangResult ArtifactUtilImpl::requireFileDefaultImpl(IArtifact* artifact, Artifa IFileArtifactRepresentation* fileRep = new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Owned, path, lockFile, nullptr); if (canKeep(keep)) { - artifact->addItem(fileRep); + artifact->addRepresentation(fileRep); } // Return it diff --git a/source/compiler-core/slang-artifact.h b/source/compiler-core/slang-artifact.h index 86b08dbb9..3c991b7b6 100644 --- a/source/compiler-core/slang-artifact.h +++ b/source/compiler-core/slang-artifact.h @@ -201,6 +201,7 @@ inline /* static */ArtifactDesc ArtifactDesc::make(Packed inPacked) // Forward declare class IFileArtifactRepresentation; +class IArtifactRepresentation; // Controls what items can be kept. enum class ArtifactKeep @@ -217,6 +218,40 @@ SLANG_INLINE bool canKeep(ArtifactKeep keep) { return Index(keep) >= Index(Artif /// Returns the keep type for an intermediate SLANG_INLINE ArtifactKeep getIntermediateKeep(ArtifactKeep keep) { return (keep == ArtifactKeep::All) ? ArtifactKeep::All : ArtifactKeep::No; } +/* A useful interface for handling lists of castable interfaces. Cannot hold nullptr */ +class ICastableList : public ICastable +{ + SLANG_COM_INTERFACE(0x335f3d40, 0x934c, 0x40dc, { 0xb5, 0xe1, 0xf7, 0x6e, 0x40, 0x3, 0x62, 0x5 }) + + /// Get the count of all interfaces held in the list + virtual Count SLANG_MCALL getCount() = 0; + /// Get the interface at the specified index + virtual ICastable* SLANG_MCALL getAt(Index i) = 0; + /// Add an item to the list + virtual void SLANG_MCALL add(ICastable* unk) = 0; + /// Add IUnknown, will cast to ICastable and if that's not possible will wrap + virtual void SLANG_MCALL addUnknown(ISlangUnknown* unk) = 0; + /// Remove item at index, remaining items stay in the same order + virtual void SLANG_MCALL removeAt(Index i) = 0; + /// Clear the list + virtual void SLANG_MCALL clear() = 0; + /// Find the first index of castable, or -1 if not found + virtual Index SLANG_MCALL indexOf(ICastable* castable) = 0; + /// Find the index interface (handling wrapping if necessary) + virtual Index SLANG_MCALL indexOfUnknown(ISlangUnknown* unk) = 0; + /// Find the first item that casts to non null + virtual void* SLANG_MCALL find(const Guid& guid) = 0; + /// Access the internal buffer (any mutation can invalidate this value) + virtual ICastable*const* SLANG_MCALL getBuffer() = 0; +}; + +// Simply finding things in a ICastableList +template +SLANG_FORCE_INLINE T* find(ICastableList* list) +{ + return reinterpret_cast(list->find(T::getTypeGuid())); +} + /* The IArtifact interface is designed to represent some Artifact of compilation. It could be input to or output from a compilation. An abstraction is desirable here, because depending on the compiler the artifact/s could be @@ -286,19 +321,22 @@ public: /// Get the name of the artifact. This can be empty. virtual SLANG_NO_THROW const char* SLANG_MCALL getName() = 0; - /// Find an item by casting it's interface - virtual SLANG_NO_THROW void* SLANG_MCALL findItemInterface(const Guid& uuid) = 0; - /// Only works on ICastable derived items. Can find interfaces or objects. - virtual SLANG_NO_THROW void* SLANG_MCALL findItemObject(const Guid& classGuid) = 0; - - /// Add a representation - virtual SLANG_NO_THROW void SLANG_MCALL addItem(ISlangUnknown* item) = 0; - /// Get the item at the index - virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getItemAt(Index i) = 0; - /// Remove the element at the specified index. - virtual SLANG_NO_THROW void SLANG_MCALL removeItemAt(Index i) = 0; - /// Get the amount of elements - virtual SLANG_NO_THROW Index SLANG_MCALL getItemCount() = 0; + /// Add data associated with this artifact + virtual SLANG_NO_THROW void SLANG_MCALL addAssociated(ICastable* castable) = 0; + /// Find an associated item + virtual void* SLANG_MCALL SLANG_MCALL findAssociated(const Guid& unk) = 0; + /// TODO(JS): We may want this to return nullptr if it's empty. + /// Get the list of associated items + virtual ICastableList* SLANG_MCALL getAssociated() = 0; + + /// Add a representation that derives from IArtifactRepresentation + virtual SLANG_NO_THROW void SLANG_MCALL addRepresentation(IArtifactRepresentation* rep) = 0; + /// Add a representation that doesn't derive from IArtifactRepresentation + virtual SLANG_NO_THROW void SLANG_MCALL addRepresentationUnknown(ISlangUnknown* rep) = 0; + /// Find representation + virtual void* SLANG_MCALL SLANG_MCALL findRepresentation(const Guid& guid) = 0; + /// Get the list of all representations + virtual ICastableList* SLANG_MCALL getRepresentations() = 0; }; /* A list of artifacts. */ @@ -336,44 +374,16 @@ class IArtifactRepresentation : public ICastable /// Convert the instance into a serializable blob. /// Returns SLANG_E_NOT_IMPLEMENTED if an implementation doesn't implement - virtual SLANG_NO_THROW SlangResult SLANG_MCALL writeToBlob(ISlangBlob** blob) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL writeToBlob(ISlangBlob** blob) = 0; - /// Returns true if this representation exists and is available for use. + /// Returns true if this representation exists and is available for use. virtual SLANG_NO_THROW bool SLANG_MCALL exists() = 0; }; -/* Interface for types that are associated with an artifact, but aren't a representation, or are -only part of a representation. */ -class IArtifactAssociated : public ICastable -{ - SLANG_COM_INTERFACE(0xafc0e4db, 0x16d4, 0x4d7a, { 0x93, 0x5f, 0x3e, 0x47, 0x7a, 0x23, 0x2a, 0x7f }) -}; - - -// Helper template to make finding an item more simple -// There isn't a problem if we only have a forward declaration, because in that case T::getTypeGuid can't work. -SLANG_FORCE_INLINE void* _findItemImpl(IArtifact* artifact, const Guid& guid, const ISlangUnknown* intf) -{ - SLANG_UNUSED(intf); - return artifact->findItemInterface(guid); -} - -SLANG_FORCE_INLINE void* _findItemImpl(IArtifact* artifact, const Guid& guid, const ICastable* castable) -{ - SLANG_UNUSED(castable); - return artifact->findItemObject(guid); -} - -SLANG_FORCE_INLINE void* _findItemImpl(IArtifact* artifact, const Guid& guid, const void* other) -{ - SLANG_UNUSED(other); - return artifact->findItemObject(guid); -} - template -SLANG_FORCE_INLINE T* findItem(IArtifact* artifact) +SLANG_FORCE_INLINE T* findRepresentation(IArtifact* artifact) { - return (T*)_findItemImpl(artifact, T::getTypeGuid(), (T*)nullptr); + return reinterpret_cast(artifact->findRepresentation(T::getTypeGuid())); } } // namespace Slang diff --git a/source/compiler-core/slang-downstream-compiler.cpp b/source/compiler-core/slang-downstream-compiler.cpp index 2e30c23bc..c492b6dd7 100644 --- a/source/compiler-core/slang-downstream-compiler.cpp +++ b/source/compiler-core/slang-downstream-compiler.cpp @@ -387,7 +387,7 @@ SlangResult CommandLineDownstreamCompileResult::getBinary(ComPtr& ou // Read the contents of the binary SLANG_RETURN_ON_FAIL(File::readAllBytes(m_moduleFilePath, contents)); - m_binaryBlob = new ScopeRefObjectBlob(ListBlob::moveCreate(contents), m_temporaryFiles); + m_binaryBlob = ScopeRefObjectBlob::create(ListBlob::moveCreate(contents), m_temporaryFiles); outBlob = m_binaryBlob; return SLANG_OK; } diff --git a/source/compiler-core/slang-glslang-compiler.cpp b/source/compiler-core/slang-glslang-compiler.cpp index fc8beaa48..70743f9d9 100644 --- a/source/compiler-core/slang-glslang-compiler.cpp +++ b/source/compiler-core/slang-glslang-compiler.cpp @@ -205,7 +205,7 @@ SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& options, Re return SLANG_OK; } - RefPtr spirvBlob = ListBlob::moveCreate(spirv); + ComPtr spirvBlob = ListBlob::moveCreate(spirv); outResult = new BlobDownstreamCompileResult(diagnostics, spirvBlob); return SLANG_OK; diff --git a/source/compiler-core/slang-nvrtc-compiler.cpp b/source/compiler-core/slang-nvrtc-compiler.cpp index 11ef746f6..3f285ada2 100644 --- a/source/compiler-core/slang-nvrtc-compiler.cpp +++ b/source/compiler-core/slang-nvrtc-compiler.cpp @@ -833,7 +833,7 @@ SlangResult NVRTCDownstreamCompiler::compile(const CompileOptions& options, RefP res = m_nvrtcCompileProgram(program, int(dstOptions.getCount()), dstOptions.getBuffer()); - RefPtr blob; + ComPtr blob; DownstreamDiagnostics diagnostics; diagnostics.result = _asResult(res); -- cgit v1.2.3