summaryrefslogtreecommitdiffstats
path: root/source/core
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2018-11-06 14:28:25 -0500
committerGitHub <noreply@github.com>2018-11-06 14:28:25 -0500
commit1185bd464092f372430cbfaa15a7be4dcaa90752 (patch)
treeb3b68f2d9de00c0845f4912a797f10b27741031f /source/core
parent453331951b0df2a612f9bc0d68eab2ad786ec5bf (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.
Diffstat (limited to 'source/core')
-rw-r--r--source/core/core.vcxproj2
-rw-r--r--source/core/core.vcxproj.filters6
-rw-r--r--source/core/platform.cpp144
-rw-r--r--source/core/platform.h56
-rw-r--r--source/core/slang-shared-library.cpp115
-rw-r--r--source/core/slang-shared-library.h122
-rw-r--r--source/core/slang-string-util.h11
-rw-r--r--source/core/smart-pointer.h12
8 files changed, 380 insertions, 88 deletions
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()