diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2018-11-06 14:28:25 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-11-06 14:28:25 -0500 |
| commit | 1185bd464092f372430cbfaa15a7be4dcaa90752 (patch) | |
| tree | b3b68f2d9de00c0845f4912a797f10b27741031f | |
| parent | 453331951b0df2a612f9bc0d68eab2ad786ec5bf (diff) | |
Feature/shared library refactor (#712)
* * Added ISlangSharedLibraryLoader and ISlangSharedLibrary
* Implemented default implementations
* Added slang API function to get/set the ISlangSharedLibraryLoader on the session
* Put function caching onto the Session - so that if the loader is chaged, its easy to reset the shared libraries, and functions
* Run premake.
* Fix problem with setting null, would cause an unnecessary function/shared lib flush.
* * Unload SharedLibrary when DefaultSharedLibrary is deleted.
* Make SharedLibrary handle unload safely if already unloaded.
* Refactor SharedLibrary, such that it becomes a utility class - simplifying it's semantics.
* Simplified ISlangSharedLibrary such that doesn't have unload and isLoaded so easier to implement.
Use updated SharedLibrary impl.
* Disable aarch64 on windows
* Premake windows files without aarch64 build.
* Moved slang-shared-library to core (so can be used in code outside of main slang)
Fixed problem in premake5 where on windows projects were incorrectly constructed
* Allowed RefObject to base class of com types
Added ConfigurableSharedLibraryLoader
Added -dxc-path -fxc-path -glslang-path
Fix problem with dxc-path not honoring it's path when loading dxil
* Added documentation for command line control of dll loading paths.
* Remove some tabbing issues.
* Change name of include guard.
| -rw-r--r-- | docs/command-line-slangc.md | 12 | ||||
| -rw-r--r-- | premake5.lua | 10 | ||||
| -rw-r--r-- | slang-com-helper.h | 23 | ||||
| -rw-r--r-- | slang.h | 49 | ||||
| -rw-r--r-- | source/core/core.vcxproj | 2 | ||||
| -rw-r--r-- | source/core/core.vcxproj.filters | 6 | ||||
| -rw-r--r-- | source/core/platform.cpp | 144 | ||||
| -rw-r--r-- | source/core/platform.h | 56 | ||||
| -rw-r--r-- | source/core/slang-shared-library.cpp | 115 | ||||
| -rw-r--r-- | source/core/slang-shared-library.h | 122 | ||||
| -rw-r--r-- | source/core/slang-string-util.h | 11 | ||||
| -rw-r--r-- | source/core/smart-pointer.h | 12 | ||||
| -rw-r--r-- | source/slang/check.cpp | 78 | ||||
| -rw-r--r-- | source/slang/compiler.cpp | 136 | ||||
| -rw-r--r-- | source/slang/compiler.h | 29 | ||||
| -rw-r--r-- | source/slang/diagnostic-defs.h | 2 | ||||
| -rw-r--r-- | source/slang/dxc-support.cpp | 98 | ||||
| -rw-r--r-- | source/slang/options.cpp | 36 | ||||
| -rw-r--r-- | source/slang/slang-file-system.h | 5 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 50 |
20 files changed, 722 insertions, 274 deletions
diff --git a/docs/command-line-slangc.md b/docs/command-line-slangc.md index a37b3138e..8d59526d4 100644 --- a/docs/command-line-slangc.md +++ b/docs/command-line-slangc.md @@ -136,6 +136,18 @@ For completeness, here are the options that `slangc` currently accepts: * `--`: Stop parsing options, and treat the rest of the command line as input paths +### Specifying where dlls/shared libraries are loaded from + +On windows if you want a dll loaded from a specific path, the path must be specified absolutely. See the *'LoadLibrary'* documentation for more details. A relative path will cause Windows to check all locations along it's search procedure. + +On linux it's similar, but any path (relative or not) will override the regular search mechanism. See *'dlopen'* for more details. + +* `-dxc-path`: Sets the path where dxc dlls are loaded from (dxcompiler.dll & dxil). + +* `-fxc-path`: Sets the path where fxc dll is loaded from (d3dcompiler_47.dll). + +* `-glslang-path`: Sets where the slang specific 'slang-glslang' is loaded from + Limitations ----------- diff --git a/premake5.lua b/premake5.lua index e0b76fc85..8e02d433f 100644 --- a/premake5.lua +++ b/premake5.lua @@ -82,8 +82,12 @@ targetName = "%{cfg.system}-%{cfg.platform:lower()}" workspace "slang" -- We will support debug/release configuration and x86/x64 builds. configurations { "Debug", "Release" } - platforms { "x86", "x64", "aarch64" } - + platforms { "x86", "x64"} + + if os.target() == "linux" then + platforms {"aarch64" } + end + if buildLocation then location(buildLocation) end @@ -107,7 +111,7 @@ workspace "slang" architecture "x64" filter { "platforms:x86" } architecture "x86" - filter { "platforms:aarch64" } + filter { "platforms:aarch64"} architecture "ARM" filter { "toolset:clang or gcc*" } diff --git a/slang-com-helper.h b/slang-com-helper.h index 054e109fa..245c800b6 100644 --- a/slang-com-helper.h +++ b/slang-com-helper.h @@ -105,6 +105,29 @@ SLANG_NO_THROW uint32_t SLANG_MCALL release() \ SLANG_IUNKNOWN_ADD_REF \ SLANG_IUNKNOWN_RELEASE +// ------------------------ RefObject IUnknown ----------------------------- + +#define SLANG_REF_OBJECT_IUNKNOWN_QUERY_INTERFACE \ +SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) \ +{ \ + ISlangUnknown* intf = getInterface(uuid); \ + if (intf) \ + { \ + addReference(); \ + *outObject = intf; \ + return SLANG_OK;\ + } \ + return SLANG_E_NO_INTERFACE;\ +} + +#define SLANG_REF_OBJECT_IUNKNOWN_ADD_REF SLANG_NO_THROW uint32_t SLANG_MCALL addRef() { return (uint32_t)addReference(); } +#define SLANG_REF_OBJECT_IUNKNOWN_RELEASE SLANG_NO_THROW uint32_t SLANG_MCALL release() { return (uint32_t)releaseReference(); } + +#define SLANG_REF_OBJECT_IUNKNOWN_ALL \ + SLANG_REF_OBJECT_IUNKNOWN_QUERY_INTERFACE \ + SLANG_REF_OBJECT_IUNKNOWN_ADD_REF \ + SLANG_REF_OBJECT_IUNKNOWN_RELEASE + #endif // defined(__cplusplus) #endif @@ -431,13 +431,13 @@ extern "C" SLANG_COMPILE_FLAG_NO_MANGLING = 1 << 3, /* Skip code generation step, just check the code and generate layout */ - SLANG_COMPILE_FLAG_NO_CODEGEN = 1 << 4, + SLANG_COMPILE_FLAG_NO_CODEGEN = 1 << 4, /* Deprecated flags: kept around to allow existing applications to compile. Note that the relevant features will still be left in their default state. */ - SLANG_COMPILE_FLAG_NO_CHECKING = 0, - SLANG_COMPILE_FLAG_SPLIT_MIXED_TYPES = 0, + SLANG_COMPILE_FLAG_NO_CHECKING = 0, + SLANG_COMPILE_FLAG_SPLIT_MIXED_TYPES = 0, }; /*! @@ -517,6 +517,7 @@ extern "C" SLANG_STAGE_PIXEL = SLANG_STAGE_FRAGMENT, }; + /** A result code for a Slang API operation. This type is generally compatible with the Windows API `HRESULT` type. In particular, negative values indicate @@ -713,6 +714,32 @@ extern "C" }; #define SLANG_UUID_ISlangFileSystem { 0x003A09FC, 0x3A4D, 0x4BA0, 0xAD, 0x60, 0x1F, 0xD8, 0x63, 0xA9, 0x15, 0xAB } + + typedef void(*SlangFuncPtr)(void); + + /** An interface that can be used to encapsulate access to a shared library. An implementaion + does not have to implement the library as a shared library. + */ + struct ISlangSharedLibrary: public ISlangUnknown + { + public: + /** Get a function by name. If the library is unloaded will only return nullptr. + @param name The name of the function + @return The function pointer related to the name or nullptr if not found + */ + virtual SLANG_NO_THROW SlangFuncPtr SLANG_MCALL findFuncByName(char const* name) = 0; + }; + #define SLANG_UUID_ISlangSharedLibrary { 0x9c9d5bc5, 0xeb61, 0x496f,{ 0x80, 0xd7, 0xd1, 0x47, 0xc4, 0xa2, 0x37, 0x30 } }; + + struct ISlangSharedLibraryLoader: public ISlangUnknown + { + public: + virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadSharedLibrary( + const char* path, + ISlangSharedLibrary** sharedLibraryOut) = 0; + }; + #define SLANG_UUID_ISlangSharedLibraryLoader { 0x6264ab2b, 0xa3e8, 0x4a06,{ 0x97, 0xf1, 0x49, 0xbc, 0x2d, 0x2a, 0xb1, 0x4d } }; + /* Type that identifies how a path should be interpreted */ typedef unsigned int SlangPathType; enum @@ -801,6 +828,22 @@ extern "C" SLANG_API void spDestroySession( SlangSession* session); + /*! + @brief Set the session shared library loader. If this changes the loader, it may cause shared libraries to be unloaded + @param session Session to set the loader on + @param loader The loader to set. Setting nullptr sets the default loader. + */ + SLANG_API void spSessionSetSharedLibraryLoader( + SlangSession* session, + ISlangSharedLibraryLoader* loader); + + /*! + @brief Gets the currently set shared library loader + @param session Session to get the loader from + @return Gets the currently set loader. If returns nullptr, it's the default loader + */ + SLANG_API ISlangSharedLibraryLoader* spSessionGetSharedLibraryLoader( + SlangSession* session); /*! @brief Add new builtin declarations to be used in subsequent compiles. diff --git a/source/core/core.vcxproj b/source/core/core.vcxproj index f3e89b518..97dc19d66 100644 --- a/source/core/core.vcxproj +++ b/source/core/core.vcxproj @@ -190,6 +190,7 @@ <ClInclude Include="slang-memory-arena.h" /> <ClInclude Include="slang-object-scope-manager.h" /> <ClInclude Include="slang-random-generator.h" /> + <ClInclude Include="slang-shared-library.h" /> <ClInclude Include="slang-string-slice-pool.h" /> <ClInclude Include="slang-string-util.h" /> <ClInclude Include="slang-string.h" /> @@ -207,6 +208,7 @@ <ClCompile Include="slang-memory-arena.cpp" /> <ClCompile Include="slang-object-scope-manager.cpp" /> <ClCompile Include="slang-random-generator.cpp" /> + <ClCompile Include="slang-shared-library.cpp" /> <ClCompile Include="slang-string-slice-pool.cpp" /> <ClCompile Include="slang-string-util.cpp" /> <ClCompile Include="slang-string.cpp" /> diff --git a/source/core/core.vcxproj.filters b/source/core/core.vcxproj.filters index 5031e67e7..b470f9b43 100644 --- a/source/core/core.vcxproj.filters +++ b/source/core/core.vcxproj.filters @@ -69,6 +69,9 @@ <ClInclude Include="slang-random-generator.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="slang-shared-library.h"> + <Filter>Header Files</Filter> + </ClInclude> <ClInclude Include="slang-string-slice-pool.h"> <Filter>Header Files</Filter> </ClInclude> @@ -116,6 +119,9 @@ <ClCompile Include="slang-random-generator.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="slang-shared-library.cpp"> + <Filter>Source Files</Filter> + </ClCompile> <ClCompile Include="slang-string-slice-pool.cpp"> <Filter>Source Files</Filter> </ClCompile> diff --git a/source/core/platform.cpp b/source/core/platform.cpp index 374606e4a..b96240def 100644 --- a/source/core/platform.cpp +++ b/source/core/platform.cpp @@ -1,6 +1,8 @@ // platform.cpp #include "platform.h" +#include "common.h" + #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #define NOMINMAX @@ -16,72 +18,102 @@ namespace Slang { // SharedLibrary - SharedLibrary SharedLibrary::load(char const* name) - { - SharedLibrary result; - result.handle = nullptr; +/* static */SlangResult SharedLibrary::load(const char* filename, SharedLibrary::Handle& handleOut) +{ + StringBuilder builder; + appendPlatformFileName(UnownedStringSlice(filename), builder); + return loadWithPlatformFilename(builder.begin(), handleOut); +} #ifdef _WIN32 - { - HMODULE h = LoadLibraryA(name); - result.handle = (Handle) h; - } -#else - { - String fullName; - fullName.append("lib"); - fullName.append(name); - fullName.append(".so"); - - void* h = dlopen(fullName.Buffer(), RTLD_NOW|RTLD_LOCAL); - if(!h) - { - if(auto msg = dlerror()) - { - fprintf(stderr, "error: %s\n", msg); - } - } - result.handle = (Handle) h; - } -#endif +/* static */SlangResult SharedLibrary::loadWithPlatformFilename(char const* platformFileName, SharedLibrary::Handle& handleOut) +{ + handleOut = nullptr; + // https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-loadlibrarya + const HMODULE h = LoadLibraryA(platformFileName); + if (!h) + { + const DWORD lastError = GetLastError(); + switch (lastError) + { + case ERROR_MOD_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + case ERROR_FILE_NOT_FOUND: + { + return SLANG_E_NOT_FOUND; + } + case ERROR_INVALID_ACCESS: + case ERROR_ACCESS_DENIED: + case ERROR_INVALID_DATA: + { + return SLANG_E_CANNOT_OPEN; + } + default: break; + } + // Turn to Result, if not one of the well known errors + return HRESULT_FROM_WIN32(lastError); + } + handleOut = (Handle)h; + return SLANG_OK; +} - return result; - } +/* static */void SharedLibrary::unload(Handle handle) +{ + SLANG_ASSERT(handle); + ::FreeLibrary((HMODULE)handle); +} + +/* static */SharedLibrary::FuncPtr SharedLibrary::findFuncByName(Handle handle, char const* name) +{ + SLANG_ASSERT(handle); + return (FuncPtr)GetProcAddress((HMODULE)handle, name); +} + +/* static */void SharedLibrary::appendPlatformFileName(const UnownedStringSlice& name, StringBuilder& dst) +{ + // Windows doesn't need the extension or any prefix to work + dst.Append(name); +} + +#else // _WIN32 + +/* static */SlangResult SharedLibrary::loadWithPlatformFilename(char const* platformFileName, Handle& handleOut) +{ + handleOut = nullptr; - void SharedLibrary::unload() + void* h = dlopen(platformFileName, RTLD_NOW | RTLD_LOCAL); + if(!h) { -#ifdef _WIN32 + if(auto msg = dlerror()) { - FreeLibrary( - (HMODULE) handle); + fprintf(stderr, "error: %s\n", msg); } -#else - { - dlclose(handle); - } -#endif - + return SLANG_FAIL; } + handleOut = (Handle)h; + return SLANG_OK; +} - SharedLibrary::FuncPtr SharedLibrary::findFuncByName(char const* name) - { - FuncPtr funcPtr = nullptr; +/* static */void SharedLibrary::unload(Handle handle) +{ + SLANG_ASSERT(handle); + dlclose(handle); +} -#ifdef _WIN32 - { - funcPtr = (FuncPtr) GetProcAddress( - (HMODULE) handle, - name); - } -#else - { - funcPtr = (FuncPtr) dlsym( - (void*) handle, - name); - } -#endif +/* static */SharedLibrary::FuncPtr SharedLibrary::findFuncByName(Handle handle, char const* name) +{ + SLANG_ASSERT(handle); + return (FuncPtr)dlsym((void*)handle, name); +} + +/* static */void SharedLibrary::appendPlatformFileName(const UnownedStringSlice& name, StringBuilder& dst) +{ + dst.Append("lib"); + dst.Append(name); + dst.Append(".so"); +} + +#endif // _WIN32 - return funcPtr; - } }
\ No newline at end of file diff --git a/source/core/platform.h b/source/core/platform.h index fef698e6f..a545d139d 100644 --- a/source/core/platform.h +++ b/source/core/platform.h @@ -2,30 +2,50 @@ #ifndef SLANG_CORE_PLATFORM_H_INCLUDED #define SLANG_CORE_PLATFORM_H_INCLUDED +#include "../../slang.h" +#include "../core/slang-string.h" + namespace Slang { // Interface for working with shared libraries - // in a platfomr-independent fashion. + // in a platform-independent fashion. struct SharedLibrary { typedef struct SharedLibraryImpl* Handle; - Handle handle; - - // Attempt to load a shared library for - // the current platform. - static SharedLibrary load(char const* name); - - // If this refers to a valid loaded library, - // then attempt to unload it - void unload(); - - typedef void (*FuncPtr)(void); - - FuncPtr findFuncByName(char const* name); - - - operator Handle() { return handle; } - }; + + typedef void(*FuncPtr)(void); + + /// Load via an unadorned filename + /// + /// @param the unadorned filename + /// @return Returns a non null handle for the shared library on success. nullptr indicated failure + static SlangResult load(const char* filename, Handle& handleOut); + + /// Attempt to load a shared library for + /// the current platform. Returns null handle on failure + /// The platform specific filename can be generated from a call to appendPlatformFileName + /// + /// @param platformFileName the platform specific file name. + /// @return Returns a non null handle for the shared library on success. nullptr indicated failure + static SlangResult loadWithPlatformFilename(char const* platformFileName, Handle& handleOut); + + /// Unload the library that was returned from load as handle + /// @param The valid handle returned from load + static void unload(Handle handle); + + /// Given a shared library handle and a name, return the associated function + /// Return nullptr if function is not found + /// @param The shared library handle as returned by loadPlatformLibrary + static FuncPtr findFuncByName(Handle handle, char const* name); + + /// Append to the end of dst, the name, with any platform specific additions + /// The input name should be unadorned with any 'lib' prefix or extension + static void appendPlatformFileName(const UnownedStringSlice& name, StringBuilder& dst); + + private: + /// Not constructible! + SharedLibrary(); + }; #ifndef _MSC_VER #define _fileno fileno diff --git a/source/core/slang-shared-library.cpp b/source/core/slang-shared-library.cpp new file mode 100644 index 000000000..716f570c4 --- /dev/null +++ b/source/core/slang-shared-library.cpp @@ -0,0 +1,115 @@ +#include "slang-shared-library.h" + +#include "../../slang-com-ptr.h" +#include "../core/slang-io.h" +#include "../core/slang-string-util.h" + +namespace Slang +{ + +// Allocate static const storage for the various interface IDs that the Slang API needs to expose +static const Guid IID_ISlangUnknown = SLANG_UUID_ISlangUnknown; +static const Guid IID_ISlangSharedLibrary = SLANG_UUID_ISlangSharedLibrary; +static const Guid IID_ISlangSharedLibraryLoader = SLANG_UUID_ISlangSharedLibraryLoader; + +/* !!!!!!!!!!!!!!!!!!!!!!!!!! DefaultSharedLibraryLoader !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ + +/* static */const char* DefaultSharedLibraryLoader::s_libraryNames[int(SharedLibraryType::CountOf)] = +{ + nullptr, // SharedLibraryType::Unknown + "dxcompiler", // SharedLibraryType::Dxc + "d3dcompiler_47", // SharedLibraryType::Fxc + "slang-glslang", // SharedLibraryType::Glslang + "dxil", // SharedLibraryType::Dxil +}; + +/* static */DefaultSharedLibraryLoader DefaultSharedLibraryLoader::s_singleton; + +/* static */SharedLibraryType DefaultSharedLibraryLoader::getSharedLibraryTypeFromName(const UnownedStringSlice& name) +{ + // Start from 1 to skip Unknown + for (int i = 1; i < SLANG_COUNT_OF(s_libraryNames); ++i) + { + if (name == s_libraryNames[i]) + { + return SharedLibraryType(i); + } + } + return SharedLibraryType::Unknown; +} + +ISlangUnknown* DefaultSharedLibraryLoader::getInterface(const Guid& guid) +{ + return (guid == IID_ISlangUnknown || guid == IID_ISlangSharedLibraryLoader) ? static_cast<ISlangSharedLibraryLoader*>(this) : nullptr; +} + +SlangResult DefaultSharedLibraryLoader::loadSharedLibrary(const char* path, ISlangSharedLibrary** sharedLibraryOut) +{ + *sharedLibraryOut = nullptr; + // Try loading + SharedLibrary::Handle handle; + SLANG_RETURN_ON_FAIL(SharedLibrary::load(path, handle)); + *sharedLibraryOut = ComPtr<ISlangSharedLibrary>(new DefaultSharedLibrary(handle)).detach(); + return SLANG_OK; +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!! DefaultSharedLibrary !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ + +ISlangUnknown* DefaultSharedLibrary::getInterface(const Guid& guid) +{ + return (guid == IID_ISlangUnknown || guid == IID_ISlangSharedLibrary) ? static_cast<ISlangSharedLibrary*>(this) : nullptr; +} + +DefaultSharedLibrary::~DefaultSharedLibrary() +{ + SharedLibrary::unload(m_sharedLibraryHandle); +} + +SlangFuncPtr DefaultSharedLibrary::findFuncByName(char const* name) +{ + return SharedLibrary::findFuncByName(m_sharedLibraryHandle, name); +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!! ConfigurableSharedLibraryLoader !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ + +ISlangUnknown* ConfigurableSharedLibraryLoader::getInterface(const Guid& guid) +{ + return (guid == IID_ISlangUnknown || guid == IID_ISlangSharedLibraryLoader) ? static_cast<ISlangSharedLibraryLoader*>(this) : nullptr; +} + +SlangResult ConfigurableSharedLibraryLoader::loadSharedLibrary(const char* path, ISlangSharedLibrary** sharedLibraryOut) +{ + Entry* entry = m_entryMap.TryGetValue(String(path)); + if (entry) + { + SharedLibrary::Handle handle; + SLANG_RETURN_ON_FAIL(entry->func(path, entry->entryString, handle)); + SLANG_ASSERT(handle); + + ComPtr<ISlangSharedLibrary> sharedLib(new DefaultSharedLibrary(handle)); + *sharedLibraryOut = sharedLib.detach(); + return SLANG_OK; + } + + return DefaultSharedLibraryLoader::getSingleton()->loadSharedLibrary(path, sharedLibraryOut); +} + +/* static */Result ConfigurableSharedLibraryLoader::replace(const char* pathIn, const String& entryString, SharedLibrary::Handle& handleOut) +{ + SLANG_UNUSED(pathIn); + // The replacement is the *whole* string + return SharedLibrary::loadWithPlatformFilename(entryString.begin(), handleOut); +} + +/* static */Result ConfigurableSharedLibraryLoader::changePath(const char* pathIn, const String& entryString, SharedLibrary::Handle& handleOut ) +{ + // Okay we need to reconstruct the name and insert the path + StringBuilder builder; + SharedLibrary::appendPlatformFileName(UnownedStringSlice(pathIn), builder); + String path = Path::Combine(entryString, builder); + + return SharedLibrary::loadWithPlatformFilename(path.begin(), handleOut); +} + + +}
\ No newline at end of file diff --git a/source/core/slang-shared-library.h b/source/core/slang-shared-library.h new file mode 100644 index 000000000..62d15b6b4 --- /dev/null +++ b/source/core/slang-shared-library.h @@ -0,0 +1,122 @@ +#ifndef SLANG_SHARED_LIBRARY_H_INCLUDED +#define SLANG_SHARED_LIBRARY_H_INCLUDED + +#include "../../slang.h" +#include "../../slang-com-helper.h" +#include "../../slang-com-ptr.h" + +#include "../core/platform.h" +#include "../core/common.h" +#include "../core/dictionary.h" + +namespace Slang +{ + +/* NOTE! Do not change this enum without making the appropriate changes to DefaultSharedLibraryLoader::s_libraryNames */ +enum class SharedLibraryType +{ + Unknown, ///< Unknown compiler + Dxc, ///< Dxc compiler + Fxc, ///< Fxc compiler + Glslang, ///< Slang specific glslang compiler + Dxil, ///< Dxil is used with dxc + CountOf, +}; + +class DefaultSharedLibraryLoader : public ISlangSharedLibraryLoader +{ +public: + + // ISlangUnknown + // override ref counting, as DefaultSharedLibraryLoader is singleton + SLANG_IUNKNOWN_QUERY_INTERFACE + SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } + SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } + + // ISlangSharedLibraryLoader + virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadSharedLibrary(const char* path, + ISlangSharedLibrary** sharedLibraryOut) SLANG_OVERRIDE; + + /// Get the singleton + static DefaultSharedLibraryLoader* getSingleton() { return &s_singleton; } + + /// Get the type from the name + static SharedLibraryType getSharedLibraryTypeFromName(const UnownedStringSlice& name); + + /// Get the name from the type, or nullptr if not known + static const char* getSharedLibraryNameFromType(SharedLibraryType type) { return s_libraryNames[int(type)]; } + + /// Make a shared library to it's name + static const char* s_libraryNames[int(SharedLibraryType::CountOf)]; + +private: + /// Make so not constructible + DefaultSharedLibraryLoader() {} + virtual ~DefaultSharedLibraryLoader() {} + + ISlangUnknown* getInterface(const Guid& guid); + + static DefaultSharedLibraryLoader s_singleton; +}; + +class DefaultSharedLibrary : public ISlangSharedLibrary, public RefObject +{ + public: + // ISlangUnknown + SLANG_REF_OBJECT_IUNKNOWN_ALL + + // ISlangSharedLibrary + virtual SLANG_NO_THROW SlangFuncPtr SLANG_MCALL findFuncByName(char const* name) SLANG_OVERRIDE; + + /// Ctor. + DefaultSharedLibrary(const SharedLibrary::Handle sharedLibraryHandle): + m_sharedLibraryHandle(sharedLibraryHandle) + { + SLANG_ASSERT(sharedLibraryHandle); + } + + /// Need virtual dtor to keep delete this happy + virtual ~DefaultSharedLibrary(); + + protected: + ISlangUnknown* getInterface(const Guid& guid); + + SharedLibrary::Handle m_sharedLibraryHandle = nullptr; +}; + +class ConfigurableSharedLibraryLoader: public ISlangSharedLibraryLoader, public RefObject +{ +public: + typedef Result (*Func)(const char* pathIn, const String& entryString, SharedLibrary::Handle& handleOut); + + // IUnknown + SLANG_REF_OBJECT_IUNKNOWN_ALL + + // ISlangSharedLibraryLoader + virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadSharedLibrary(const char* path, ISlangSharedLibrary** sharedLibraryOut) SLANG_OVERRIDE; + + /// Function to replace the the path with entryString + static Result replace(const char* pathIn, const String& entryString, SharedLibrary::Handle& handleOut); + /// Function to change the path using the entryStrinct + static Result changePath(const char* pathIn, const String& entryString, SharedLibrary::Handle& handleOut); + + void addEntry(const String& libName, Func func, const String& entryString) { m_entryMap.Add(libName, Entry{ func, entryString} ); } + void addEntry(SharedLibraryType libType, Func func, const String& entryString) { m_entryMap.Add(DefaultSharedLibraryLoader::getSharedLibraryNameFromType(libType), Entry { func, entryString} ); } + + virtual ~ConfigurableSharedLibraryLoader() {} + protected: + + struct Entry + { + Func func; + String entryString; + }; + + ISlangUnknown* getInterface(const Guid& guid); + + Dictionary<String, Entry> m_entryMap; +}; + +} + +#endif // SLANG_SHARED_LIBRARY_H_INCLUDED
\ No newline at end of file diff --git a/source/core/slang-string-util.h b/source/core/slang-string-util.h index 47d92f2fe..b365b6cf5 100644 --- a/source/core/slang-string-util.h +++ b/source/core/slang-string-util.h @@ -13,11 +13,11 @@ namespace Slang { /** A blob that uses a `String` for its storage. */ -class StringBlob : public ISlangBlob +class StringBlob : public ISlangBlob, public RefObject { public: // ISlangUnknown - SLANG_IUNKNOWN_ALL + SLANG_REF_OBJECT_IUNKNOWN_ALL // ISlangBlob SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_string.Buffer(); } @@ -30,15 +30,9 @@ public: : m_string(string) {} - /// Need virtual dtor, because BlobBase is derived from and release impl used is the one in the base class (that doesn't know the derived type) - /// Alternatively could be implemented by always using SLANG_IUNKNOWN_RELEASE in derived types - this would make derived types slightly smaller/faster - virtual ~StringBlob() {} - protected: ISlangUnknown* getInterface(const Guid& guid); - String m_string; - uint32_t m_refCount = 0; }; struct StringUtil @@ -62,7 +56,6 @@ struct StringUtil /// Create a blob from a string static ComPtr<ISlangBlob> createStringBlob(const String& string); - }; } // namespace Slang diff --git a/source/core/smart-pointer.h b/source/core/smart-pointer.h index abd7763ee..dd00acabd 100644 --- a/source/core/smart-pointer.h +++ b/source/core/smart-pointer.h @@ -32,23 +32,25 @@ namespace Slang virtual ~RefObject() {} - void addReference() + UInt addReference() { - referenceCount++; + return ++referenceCount; } - void decreaseReference() + UInt decreaseReference() { - --referenceCount; + return --referenceCount; } - void releaseReference() + UInt releaseReference() { SLANG_ASSERT(referenceCount != 0); if(--referenceCount == 0) { delete this; + return 0; } + return referenceCount; } bool isUniquelyReferenced() diff --git a/source/slang/check.cpp b/source/slang/check.cpp index dbf2b294c..00c6f6dd0 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -274,6 +274,84 @@ namespace Slang typeCheckingCache = nullptr; } + namespace { // anonymous + struct FunctionInfo + { + const char* name; + SharedLibraryType libraryType; + }; + } // anonymous + + static FunctionInfo _getFunctionInfo(Session::SharedLibraryFuncType funcType) + { + typedef Session::SharedLibraryFuncType FuncType; + typedef SharedLibraryType LibType; + + switch (funcType) + { + case FuncType::Glslang_Compile: return { "glslang_compile", LibType::Glslang } ; + case FuncType::Fxc_D3DCompile: return { "D3DCompile", LibType::Fxc }; + case FuncType::Fxc_D3DDisassemble: return { "D3DDisassemble", LibType::Fxc }; + case FuncType::Dxc_DxcCreateInstance: return { "DxcCreateInstance", LibType::Dxc }; + default: return { nullptr, LibType::Unknown }; + } + } + + ISlangSharedLibrary* Session::getOrLoadSharedLibrary(SharedLibraryType type, DiagnosticSink* sink) + { + // If not loaded, try loading it + if (!sharedLibraries[int(type)]) + { + // Try to preload dxil first, if loading dxc + if (type == SharedLibraryType::Dxc) + { + getOrLoadSharedLibrary(SharedLibraryType::Dxil, sink); + } + + const char* libName = DefaultSharedLibraryLoader::getSharedLibraryNameFromType(type); + if (SLANG_FAILED(sharedLibraryLoader->loadSharedLibrary(libName, sharedLibraries[int(type)].writeRef()))) + { + sink->diagnose(SourceLoc(), Diagnostics::failedToLoadDynamicLibrary, libName); + return nullptr; + } + } + return sharedLibraries[int(type)]; + } + + SlangFuncPtr Session::getSharedLibraryFunc(SharedLibraryFuncType type, DiagnosticSink* sink) + { + if (sharedLibraryFunctions[int(type)]) + { + return sharedLibraryFunctions[int(type)]; + } + // do we have the library + FunctionInfo info = _getFunctionInfo(type); + if (info.name == nullptr) + { + return nullptr; + } + // Try loading the library + ISlangSharedLibrary* sharedLib = getOrLoadSharedLibrary(info.libraryType, sink); + if (!sharedLib) + { + return nullptr; + } + + // Okay now access the func + SlangFuncPtr func = sharedLib->findFuncByName(info.name); + if (!func) + { + const char* libName = DefaultSharedLibraryLoader::getSharedLibraryNameFromType(info.libraryType); + sink->diagnose(SourceLoc(), Diagnostics::failedToFindFunctionInSharedLibrary, info.name, libName); + return nullptr; + } + + // Store in the function cache + sharedLibraryFunctions[int(type)] = func; + return func; + } + + enum class CheckingPhase { Header, Body diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp index 52a31645c..6b5043fa8 100644 --- a/source/slang/compiler.cpp +++ b/source/slang/compiler.cpp @@ -359,38 +359,17 @@ namespace Slang } #if SLANG_ENABLE_DXBC_SUPPORT - HMODULE loadD3DCompilerDLL(CompileRequest* request) - { - char const* libraryName = "d3dcompiler_47"; - HMODULE d3dCompiler = LoadLibraryA(libraryName); - if (!d3dCompiler) - { - request->mSink.diagnose(SourceLoc(), Diagnostics::failedToLoadDynamicLibrary, libraryName); - } - return d3dCompiler; - } - - HMODULE getD3DCompilerDLL(CompileRequest* request) - { - // TODO(tfoley): let user specify version of d3dcompiler DLL to use. - static HMODULE d3dCompiler = loadD3DCompilerDLL(request); - return d3dCompiler; - } - + List<uint8_t> EmitDXBytecodeForEntryPoint( EntryPointRequest* entryPoint, TargetRequest* targetReq) { - static pD3DCompile D3DCompile_ = nullptr; - if (!D3DCompile_) - { - HMODULE d3dCompiler = getD3DCompilerDLL(entryPoint->compileRequest); - if (!d3dCompiler) - return List<uint8_t>(); + auto session = entryPoint->compileRequest->mSession; - D3DCompile_ = (pD3DCompile)GetProcAddress(d3dCompiler, "D3DCompile"); - if (!D3DCompile_) - return List<uint8_t>(); + auto compileFunc = (pD3DCompile)session->getSharedLibraryFunc(Session::SharedLibraryFuncType::Fxc_D3DCompile, &entryPoint->compileRequest->mSink); + if (!compileFunc) + { + return List<uint8_t>(); } auto hlslCode = emitHLSLForEntryPoint(entryPoint, targetReq); @@ -442,7 +421,7 @@ namespace Slang ID3DBlob* codeBlob; ID3DBlob* diagnosticsBlob; - HRESULT hr = D3DCompile_( + HRESULT hr = compileFunc( hlslCode.begin(), hlslCode.Length(), "slang", @@ -488,35 +467,29 @@ namespace Slang return data; } - String dissassembleDXBC( + SlangResult dissassembleDXBC( CompileRequest* compileRequest, void const* data, - size_t size) + size_t size, + String& stringOut) { - static pD3DDisassemble D3DDisassemble_ = nullptr; - if (!D3DDisassemble_) - { - HMODULE d3dCompiler = getD3DCompilerDLL(compileRequest); - if (!d3dCompiler) - return String(); + stringOut = String(); - D3DDisassemble_ = (pD3DDisassemble)GetProcAddress(d3dCompiler, "D3DDisassemble"); - if (!D3DDisassemble_) - return String(); + auto session = compileRequest->mSession; + + auto disassembleFunc = (pD3DDisassemble)session->getSharedLibraryFunc(Session::SharedLibraryFuncType::Fxc_D3DDisassemble, &compileRequest->mSink); + if (!disassembleFunc) + { + return SLANG_E_NOT_FOUND; } if (!data || !size) { - return String(); + return SLANG_FAIL; } - ID3DBlob* codeBlob; - HRESULT hr = D3DDisassemble_( - data, - size, - 0, - nullptr, - &codeBlob); + ComPtr<ID3DBlob> codeBlob; + SlangResult res = disassembleFunc(data, size, 0, nullptr, codeBlob.writeRef()); String result; if (codeBlob) @@ -524,13 +497,13 @@ namespace Slang char const* codeBegin = (char const*)codeBlob->GetBufferPointer(); char const* codeEnd = codeBegin + codeBlob->GetBufferSize() - 1; result.append(codeBegin, codeEnd); - codeBlob->Release(); } - if (FAILED(hr)) + if (FAILED(res)) { // TODO(tfoley): need to figure out what to diagnose here... } - return result; + + return res; } String EmitDXBytecodeAssemblyForEntryPoint( @@ -544,7 +517,8 @@ namespace Slang return String(); } - String result = dissassembleDXBC(entryPoint->compileRequest, dxbc.Buffer(), dxbc.Count()); + String result; + dissassembleDXBC(entryPoint->compileRequest, dxbc.Buffer(), dxbc.Count(), result); return result; } @@ -559,50 +533,25 @@ int emitDXILForEntryPointUsingDXC( TargetRequest* targetReq, List<uint8_t>& outCode); -String dissassembleDXILUsingDXC( +SlangResult dissassembleDXILUsingDXC( CompileRequest* compileRequest, void const* data, - size_t size); + size_t size, + String& stringOut); #endif #if SLANG_ENABLE_GLSLANG_SUPPORT - - SharedLibrary loadGLSLCompilerDLL(CompileRequest* request) - { - char const* libraryName = "slang-glslang"; - // TODO(tfoley): let user specify version of glslang DLL to use. - - SharedLibrary glslCompiler = SharedLibrary::load(libraryName); - if (!glslCompiler) - { - request->mSink.diagnose(SourceLoc(), Diagnostics::failedToLoadDynamicLibrary, libraryName); - } - return glslCompiler; - } - - SharedLibrary getGLSLCompilerDLL(CompileRequest* request) - { - static SharedLibrary glslCompiler = loadGLSLCompilerDLL(request); - return glslCompiler; - } - - int invokeGLSLCompiler( CompileRequest* slangCompileRequest, glslang_CompileRequest& request) { + Session* session = slangCompileRequest->mSession; - static glslang_CompileFunc glslang_compile = nullptr; + auto glslang_compile = (glslang_CompileFunc)session->getSharedLibraryFunc(Session::SharedLibraryFuncType::Glslang_Compile, &slangCompileRequest->mSink); if (!glslang_compile) { - SharedLibrary glslCompiler = getGLSLCompilerDLL(slangCompileRequest); - if (!glslCompiler) - return 1; - - glslang_compile = (glslang_CompileFunc) glslCompiler.findFuncByName("glslang_compile"); - if (!glslang_compile) - return 1; + return 1; } String diagnosticOutput; @@ -769,10 +718,12 @@ String dissassembleDXILUsingDXC( int err = emitDXILForEntryPointUsingDXC(entryPoint, targetReq, code); if (!err) { - String assembly = dissassembleDXILUsingDXC( + String assembly; + dissassembleDXILUsingDXC( compileRequest, code.Buffer(), - code.Count()); + code.Count(), + assembly); maybeDumpIntermediate(compileRequest, assembly.Buffer(), target); @@ -935,9 +886,10 @@ String dissassembleDXILUsingDXC( #if SLANG_ENABLE_DXBC_SUPPORT case CodeGenTarget::DXBytecode: { - String assembly = dissassembleDXBC(compileRequest, + String assembly; + dissassembleDXBC(compileRequest, data.begin(), - data.end() - data.begin()); + data.end() - data.begin(), assembly); writeOutputToConsole(compileRequest, assembly); } break; @@ -946,9 +898,11 @@ String dissassembleDXILUsingDXC( #if SLANG_ENABLE_DXIL_SUPPORT case CodeGenTarget::DXIL: { - String assembly = dissassembleDXILUsingDXC(compileRequest, + String assembly; + dissassembleDXILUsingDXC(compileRequest, data.begin(), - data.end() - data.begin()); + data.end() - data.begin(), + assembly); writeOutputToConsole(compileRequest, assembly); } break; @@ -1194,7 +1148,8 @@ String dissassembleDXILUsingDXC( case CodeGenTarget::DXBytecode: dumpIntermediateBinary(compileRequest, data, size, ".dxbc"); { - String dxbcAssembly = dissassembleDXBC(compileRequest, data, size); + String dxbcAssembly; + dissassembleDXBC(compileRequest, data, size, dxbcAssembly); dumpIntermediateText(compileRequest, dxbcAssembly.begin(), dxbcAssembly.Length(), ".dxbc.asm"); } break; @@ -1208,7 +1163,8 @@ String dissassembleDXILUsingDXC( case CodeGenTarget::DXIL: dumpIntermediateBinary(compileRequest, data, size, ".dxil"); { - String dxilAssembly = dissassembleDXILUsingDXC(compileRequest, data, size); + String dxilAssembly; + dissassembleDXILUsingDXC(compileRequest, data, size, dxilAssembly); dumpIntermediateText(compileRequest, dxilAssembly.begin(), dxilAssembly.Length(), ".dxil.asm"); } break; diff --git a/source/slang/compiler.h b/source/slang/compiler.h index 1f4a4736a..c8c242568 100644 --- a/source/slang/compiler.h +++ b/source/slang/compiler.h @@ -1,7 +1,9 @@ -#ifndef RASTER_SHADER_COMPILER_H -#define RASTER_SHADER_COMPILER_H +#ifndef SLANG_COMPILER_H_INCLUDED +#define SLANG_COMPILER_H_INCLUDED #include "../core/basic.h" +#include "../core/slang-shared-library.h" + #include "../../slang-com-ptr.h" #include "diagnostics.h" @@ -77,7 +79,7 @@ namespace Slang // When storing the layout for a matrix-type // value, we need to know whether it has been - // laid ot with row-major or column-major + // laid out with row-major or column-major // storage. // enum MatrixLayoutMode @@ -503,6 +505,15 @@ namespace Slang class Session { public: + enum class SharedLibraryFuncType + { + Glslang_Compile, + Fxc_D3DCompile, + Fxc_D3DDisassemble, + Dxc_DxcCreateInstance, + CountOf, + }; + // RefPtr<Scope> baseLanguageScope; @@ -544,6 +555,10 @@ namespace Slang RefPtr<Type> constExprRate; RefPtr<Type> irBasicBlockType; + ComPtr<ISlangSharedLibraryLoader> sharedLibraryLoader; ///< The shared library loader (never null) + ComPtr<ISlangSharedLibrary> sharedLibraries[int(SharedLibraryType::CountOf)]; ///< The loaded shared libraries + SlangFuncPtr sharedLibraryFunctions[int(SharedLibraryFuncType::CountOf)]; + Dictionary<int, RefPtr<Type>> builtinTypes; Dictionary<String, Decl*> magicDecls; @@ -602,6 +617,14 @@ namespace Slang void destroyTypeCheckingCache(); // + /// Will try to load the library by specified name (using the set loader), if not one already available. + ISlangSharedLibrary* getOrLoadSharedLibrary(SharedLibraryType type, DiagnosticSink* sink); + + /// Gets a shared library by type, or null if not loaded + ISlangSharedLibrary* getSharedLibrary(SharedLibraryType type) const { return sharedLibraries[int(type)]; } + + SlangFuncPtr getSharedLibraryFunc(SharedLibraryFuncType type, DiagnosticSink* sink); + Session(); void addBuiltinSource( diff --git a/source/slang/diagnostic-defs.h b/source/slang/diagnostic-defs.h index 277e9a48f..f28666522 100644 --- a/source/slang/diagnostic-defs.h +++ b/source/slang/diagnostic-defs.h @@ -96,6 +96,8 @@ DIAGNOSTIC( 50, Error, duplicateTargets, "the target '$0' has been specified DIAGNOSTIC( 60, Error, cannotDeduceOutputFormatFromPath, "cannot infer an output format from the output path '$0'") DIAGNOSTIC( 61, Error, cannotMatchOutputFileToTarget, "no specified '-target' option matches the output path '$0', which implies the '$1' format") +DIAGNOSTIC( 62, Error, failedToFindFunctionInSharedLibrary, "failed to find function '$0' in shared/dynamic library '$1'") + DIAGNOSTIC( 70, Error, cannotMatchOutputFileToEntryPoint, "the output path '$0' is not associated with any entry point; a '-o' option for a compiled kernel must follow the '-entry' option for its corresponding entry point") DIAGNOSTIC( 80, Error, duplicateOutputPathsForEntryPointAndTarget, "multiple output paths have been specified entry point '$0' on target '$1'") diff --git a/source/slang/dxc-support.cpp b/source/slang/dxc-support.cpp index 0478eef25..152710534 100644 --- a/source/slang/dxc-support.cpp +++ b/source/slang/dxc-support.cpp @@ -33,47 +33,23 @@ namespace Slang EntryPointRequest* entryPoint, TargetRequest* targetReq); - SharedLibrary loadDXCSharedLibrary(CompileRequest* request) - { - // TODO(tfoley): Let user specify name/path of library to use. - char const* libraryName = "dxcompiler"; - - SharedLibrary library = SharedLibrary::load(libraryName); - if (!library) - { - request->mSink.diagnose(SourceLoc(), Diagnostics::failedToLoadDynamicLibrary, libraryName); - } - return library; - } - - SharedLibrary getDXCSharedLibrary(CompileRequest* request) - { - static SharedLibrary library = loadDXCSharedLibrary(request); - return library; - } - int emitDXILForEntryPointUsingDXC( EntryPointRequest* entryPoint, TargetRequest* targetReq, List<uint8_t>& outCode) { auto compileRequest = entryPoint->compileRequest; + auto session = compileRequest->mSession; // First deal with all the rigamarole of loading // the `dxcompiler` library, and creating the // top-level COM objects that will be used to // compile things. - static DxcCreateInstanceProc dxcCreateInstance = nullptr; + auto dxcCreateInstance = (DxcCreateInstanceProc)session->getSharedLibraryFunc(Session::SharedLibraryFuncType::Dxc_DxcCreateInstance, &compileRequest->mSink); if (!dxcCreateInstance) { - auto dxcSharedLibrary = getDXCSharedLibrary(compileRequest); - if (!dxcSharedLibrary) - return 1; - - dxcCreateInstance = (DxcCreateInstanceProc) dxcSharedLibrary.findFuncByName("DxcCreateInstance"); - if (!dxcCreateInstance) - return 1; + return 1; } IDxcCompiler* dxcCompiler = nullptr; @@ -262,75 +238,45 @@ namespace Slang return 0; } - String dissassembleDXILUsingDXC( + SlangResult dissassembleDXILUsingDXC( CompileRequest* compileRequest, void const* data, - size_t size) + size_t size, + String& stringOut) { + stringOut = String(); + auto session = compileRequest->mSession; + // First deal with all the rigamarole of loading // the `dxcompiler` library, and creating the // top-level COM objects that will be used to // compile things. - static DxcCreateInstanceProc dxcCreateInstance = nullptr; + auto dxcCreateInstance = (DxcCreateInstanceProc)session->getSharedLibraryFunc(Session::SharedLibraryFuncType::Dxc_DxcCreateInstance, &compileRequest->mSink); if (!dxcCreateInstance) { - auto dxcSharedLibrary = getDXCSharedLibrary(compileRequest); - if (!dxcSharedLibrary) - return 1; - - dxcCreateInstance = (DxcCreateInstanceProc) dxcSharedLibrary.findFuncByName("DxcCreateInstance"); - if (!dxcCreateInstance) - return 1; - } - - IDxcCompiler* dxcCompiler = nullptr; - if (FAILED(dxcCreateInstance( - CLSID_DxcCompiler, - __uuidof(dxcCompiler), - (LPVOID*) &dxcCompiler))) - { - return 1; - } - - IDxcLibrary* dxcLibrary = nullptr; - if (FAILED(dxcCreateInstance( - CLSID_DxcLibrary, - __uuidof(dxcLibrary), - (LPVOID*) &dxcLibrary))) - { - return 1; + return SLANG_FAIL; } + ComPtr<IDxcCompiler> dxcCompiler; + SLANG_RETURN_ON_FAIL(dxcCreateInstance(CLSID_DxcCompiler, __uuidof(dxcCompiler), (LPVOID*) dxcCompiler.writeRef())); + ComPtr<IDxcLibrary> dxcLibrary; + SLANG_RETURN_ON_FAIL(dxcCreateInstance(CLSID_DxcLibrary, __uuidof(dxcLibrary), (LPVOID*) dxcLibrary.writeRef())); + // Create blob from the input data - IDxcBlobEncoding* dxcSourceBlob = nullptr; - if (FAILED(dxcLibrary->CreateBlobWithEncodingFromPinned( - (LPBYTE) data, - (UINT32) size, - 0, - &dxcSourceBlob))) - { - return 1; - } + ComPtr<IDxcBlobEncoding> dxcSourceBlob; + SLANG_RETURN_ON_FAIL(dxcLibrary->CreateBlobWithEncodingFromPinned((LPBYTE) data, (UINT32) size, 0, dxcSourceBlob.writeRef())); - IDxcBlobEncoding* dxcResultBlob = nullptr; - if(FAILED(dxcCompiler->Disassemble( - dxcSourceBlob, - &dxcResultBlob))) - { - return 1; - } + ComPtr<IDxcBlobEncoding> dxcResultBlob; + SLANG_RETURN_ON_FAIL(dxcCompiler->Disassemble(dxcSourceBlob, dxcResultBlob.writeRef())); String result; char const* codeBegin = (char const*)dxcResultBlob->GetBufferPointer(); char const* codeEnd = codeBegin + dxcResultBlob->GetBufferSize() - 1; result.append(codeBegin, codeEnd); + stringOut = result; - if(dxcResultBlob) dxcResultBlob ->Release(); - if(dxcLibrary) dxcLibrary ->Release(); - if(dxcCompiler) dxcCompiler ->Release(); - - return result; + return SLANG_OK; } diff --git a/source/slang/options.cpp b/source/slang/options.cpp index cfa631340..9f65d0e5c 100644 --- a/source/slang/options.cpp +++ b/source/slang/options.cpp @@ -43,6 +43,8 @@ struct OptionsParser Slang::CompileRequest* requestImpl = nullptr; + Slang::RefPtr<Slang::ConfigurableSharedLibraryLoader> sharedLibraryLoader; + // A "translation unit" represents one or more source files // that are processed as a single entity when it comes to // semantic checking. @@ -158,6 +160,15 @@ struct OptionsParser RawTarget defaultTarget; + void addSharedLibraryPath(SharedLibraryType libType, const String& path) + { + if (!sharedLibraryLoader) + { + sharedLibraryLoader = new ConfigurableSharedLibraryLoader; + } + sharedLibraryLoader->addEntry(libType, ConfigurableSharedLibraryLoader::changePath, path); + } + int addTranslationUnit( SlangSourceLanguage language, Stage impliedStage) @@ -566,6 +577,25 @@ struct OptionsParser compileRequest, passThrough); } + else if (argStr == "-dxc-path") + { + String name; + SLANG_RETURN_ON_FAIL(tryReadCommandLineArgument(sink, arg, &argCursor, argEnd, name)); + addSharedLibraryPath(SharedLibraryType::Dxc, name); + addSharedLibraryPath(SharedLibraryType::Dxil, name); + } + else if (argStr == "-glslang-path") + { + String name; + SLANG_RETURN_ON_FAIL(tryReadCommandLineArgument(sink, arg, &argCursor, argEnd, name)); + addSharedLibraryPath(SharedLibraryType::Glslang, name); + } + else if (argStr == "-fxc-path") + { + String name; + SLANG_RETURN_ON_FAIL(tryReadCommandLineArgument(sink, arg, &argCursor, argEnd, name)); + addSharedLibraryPath(SharedLibraryType::Fxc, name); + } else if (argStr[1] == 'D') { // The value to be defined might be part of the same option, as in: @@ -1221,6 +1251,11 @@ struct OptionsParser } } + if (sharedLibraryLoader) + { + spSessionSetSharedLibraryLoader(session, sharedLibraryLoader); + } + return (sink->GetErrorCount() == 0) ? SLANG_OK : SLANG_FAIL; } }; @@ -1236,6 +1271,7 @@ SlangResult parseOptions( OptionsParser parser; parser.compileRequest = compileRequestIn; parser.requestImpl = compileRequest; + parser.session = (SlangSession*)compileRequest->mSession; Result res = parser.parse(argc, argv); diff --git a/source/slang/slang-file-system.h b/source/slang/slang-file-system.h index aa216e6b0..b22dc4cb9 100644 --- a/source/slang/slang-file-system.h +++ b/source/slang/slang-file-system.h @@ -64,7 +64,7 @@ doing it this way means it works as before and requires no new functions. You can use a more sophisticated canonical style if you pass true to useSimplifyForCanonicalPath. This will simplify relative path to create a canonical path. */ -class CacheFileSystem: public ISlangFileSystemExt +class CacheFileSystem: public ISlangFileSystemExt, public RefObject { public: @@ -80,7 +80,7 @@ class CacheFileSystem: public ISlangFileSystemExt }; // ISlangUnknown - SLANG_IUNKNOWN_ALL + SLANG_REF_OBJECT_IUNKNOWN_ALL // ISlangFileSystem virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadFile( @@ -153,7 +153,6 @@ protected: ComPtr<ISlangFileSystem> m_fileSystem; ///< Must always be set ComPtr<ISlangFileSystemExt> m_fileSystemExt; ///< Optionally set -> if not will fall back on the m_fileSystem - uint32_t m_refCount = 0; }; } diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 1e3d1e716..28b504831 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -2,6 +2,7 @@ #include "../core/slang-io.h" #include "../core/slang-string-util.h" +#include "../core/slang-shared-library.h" #include "parameter-binding.h" #include "lower-to-ir.h" @@ -28,11 +29,16 @@ namespace Slang { + Session::Session() { // Initialize name pool getNamePool()->setRootNamePool(getRootNamePool()); + sharedLibraryLoader = DefaultSharedLibraryLoader::getSingleton(); + // Set all the shared library function pointers to nullptr + ::memset(sharedLibraryFunctions, 0, sizeof(sharedLibraryFunctions)); + // Initialize the lookup table of syntax classes: #define SYNTAX_CLASS(NAME, BASE) \ @@ -310,17 +316,11 @@ static const Guid IID_ISlangBlob = SLANG_UUID_ISlangBlob; /** Base class for simple blobs. */ -class BlobBase : public ISlangBlob +class BlobBase : public ISlangBlob, public RefObject { public: - uint32_t m_refCount = 0; - // ISlangUnknown - SLANG_IUNKNOWN_ALL - - /// Need virtual dtor, because BlobBase is derived from and release impl used is the one in the base class (that doesn't know the derived type) - /// Alternatively could be implemented by always using SLANG_IUNKNOWN_RELEASE in derived types - this would make derived types slightly smaller/faster - virtual ~BlobBase() {} + SLANG_REF_OBJECT_IUNKNOWN_ALL protected: SLANG_FORCE_INLINE ISlangUnknown* getInterface(const Guid& guid) @@ -1112,6 +1112,40 @@ SLANG_API void spAddBuiltins( sourceString); } +SLANG_API void spSessionSetSharedLibraryLoader( + SlangSession* session, + ISlangSharedLibraryLoader* loader) +{ + auto s = SESSION(session); + + if (!loader) + { + // If null set the default + loader = Slang::DefaultSharedLibraryLoader::getSingleton(); + } + + if (s->sharedLibraryLoader != loader) + { + // Need to clear all of the libraries + for (int i = 0; i < SLANG_COUNT_OF(s->sharedLibraries); ++i) + { + s->sharedLibraries[i].setNull(); + } + + // Clear all of the functions + ::memset(s->sharedLibraryFunctions, 0, sizeof(s->sharedLibraryFunctions)); + + // Set the loader + s->sharedLibraryLoader = loader; + } +} + +SLANG_API ISlangSharedLibraryLoader* spSessionGetSharedLibraryLoader( + SlangSession* session) +{ + auto s = SESSION(session); + return (s->sharedLibraryLoader == Slang::DefaultSharedLibraryLoader::getSingleton()) ? nullptr : s->sharedLibraryLoader.get(); +} SLANG_API SlangCompileRequest* spCreateCompileRequest( SlangSession* session) |
