summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/core/slang-shared-library.cpp58
-rw-r--r--source/core/slang-shared-library.h7
-rw-r--r--source/slang/slang-api.cpp72
3 files changed, 136 insertions, 1 deletions
diff --git a/source/core/slang-shared-library.cpp b/source/core/slang-shared-library.cpp
index 746e14e4c..8d362fd89 100644
--- a/source/core/slang-shared-library.cpp
+++ b/source/core/slang-shared-library.cpp
@@ -5,6 +5,18 @@
#include "slang-io.h"
#include "slang-string-util.h"
+#if defined(_WIN32)
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+#elif defined(__linux__)
+#include <dlfcn.h>
+#endif
+#include <sys/stat.h>
+#include <sys/types.h>
+#ifndef WIN32
+# include <unistd.h>
+#endif
+
namespace Slang
{
@@ -87,4 +99,50 @@ void* DefaultSharedLibrary::findSymbolAddressByName(char const* name)
return SharedLibrary::findSymbolAddressByName(m_sharedLibraryHandle, name);
}
+
+String SharedLibraryUtils::getSharedLibraryFileName(void* symbolInLib)
+{
+#if defined(_WIN32)
+ HMODULE moduleHandle;
+ GetModuleHandleExA(
+ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ (LPCSTR)symbolInLib,
+ &moduleHandle);
+ const int maxLength = 1024;
+ wchar_t filenameBuffer[maxLength];
+ auto length = GetModuleFileNameW(moduleHandle, filenameBuffer, maxLength);
+ if (length == maxLength)
+ {
+ // Insufficient buffer, return empty.
+ return String();
+ }
+ return String::fromWString(filenameBuffer);
+
+#elif defined(__linux__)
+ Dl_info dllInfo;
+ if (!dladdr(symbolInLib, &dllInfo))
+ {
+ return String();
+ }
+ return dllInfo.dli_fname;
+
+#else
+ return String();
+#endif
+}
+
+uint64_t SharedLibraryUtils::getSharedLibraryTimestamp(void* symbolInLib)
+{
+ auto fileName = getSharedLibraryFileName(symbolInLib);
+ if (fileName.getLength() == 0)
+ return 0;
+ struct stat result;
+ if (stat(fileName.getBuffer(), &result) == 0)
+ {
+ auto mod_time = result.st_mtime;
+ return (uint64_t)mod_time;
+ }
+ return 0;
+}
+
}
diff --git a/source/core/slang-shared-library.h b/source/core/slang-shared-library.h
index c29f16289..c33f1f41b 100644
--- a/source/core/slang-shared-library.h
+++ b/source/core/slang-shared-library.h
@@ -94,6 +94,13 @@ protected:
String m_path;
};
+class SharedLibraryUtils
+{
+public:
+ static String getSharedLibraryFileName(void* symbolInLib);
+ static uint64_t getSharedLibraryTimestamp(void* symbolInLib);
+};
+
}
#endif // SLANG_SHARED_LIBRARY_H_INCLUDED
diff --git a/source/slang/slang-api.cpp b/source/slang/slang-api.cpp
index 56dc44c04..251a3980b 100644
--- a/source/slang/slang-api.cpp
+++ b/source/slang/slang-api.cpp
@@ -4,6 +4,8 @@
#include "slang-repro.h"
+#include "../core/slang-shared-library.h"
+
// implementation of C interface
SLANG_API SlangSession* spCreateSession(const char*)
@@ -17,6 +19,65 @@ SLANG_API SlangSession* spCreateSession(const char*)
return globalSession.detach();
}
+// Attempt to load a previously compiled stdlib from the same file system location as the slang dll.
+// Returns SLANG_OK when the cache is sucessfully loaded.
+// Also returns the filename to the stdlib cache and the timestamp of current slang dll.
+SlangResult tryLoadStdLibFromCache(
+ slang::IGlobalSession* globalSession,
+ Slang::String& outCachePath,
+ uint64_t& outTimestamp)
+{
+ auto fileName =
+ Slang::SharedLibraryUtils::getSharedLibraryFileName((void*)slang_createGlobalSession);
+ uint64_t currentLibTimestamp =
+ Slang::SharedLibraryUtils::getSharedLibraryTimestamp((void*)slang_createGlobalSession);
+ auto dirName = Slang::Path::getParentDirectory(fileName);
+ auto cacheFileName = Slang::Path::combine(dirName, "slang-stdlib.bin");
+ outTimestamp = currentLibTimestamp;
+ outCachePath = cacheFileName;
+ if (currentLibTimestamp == 0)
+ {
+ return SLANG_FAIL;
+ }
+ Slang::ScopedAllocation cacheData;
+ SLANG_RETURN_ON_FAIL(Slang::File::readAllBytes(cacheFileName, cacheData));
+
+ // The first 8 bytes stores the timestamp of the slang dll that created this stdlib cache.
+ if (cacheData.getSizeInBytes() < sizeof(uint64_t))
+ return SLANG_FAIL;
+ auto cacheTimestamp = *(uint64_t*)(cacheData.getData());
+ if (cacheTimestamp != currentLibTimestamp)
+ return SLANG_FAIL;
+ SLANG_RETURN_ON_FAIL(globalSession->loadStdLib(
+ (uint8_t*)cacheData.getData() + sizeof(uint64_t),
+ cacheData.getSizeInBytes() - sizeof(uint64_t)));
+ return SLANG_OK;
+}
+
+SlangResult trySaveStdLibToCache(
+ slang::IGlobalSession* globalSession,
+ const Slang::String& cacheFilename,
+ uint64_t dllTimestamp)
+{
+ if (dllTimestamp != 0 && cacheFilename.getLength() != 0)
+ {
+ Slang::ComPtr<ISlangBlob> stdLibBlobPtr;
+ SLANG_RETURN_ON_FAIL(
+ globalSession->saveStdLib(SLANG_ARCHIVE_TYPE_RIFF_LZ4, stdLibBlobPtr.writeRef()));
+ try
+ {
+ Slang::FileStream fileStream(cacheFilename, Slang::FileMode::Create);
+ fileStream.write(&dllTimestamp, sizeof(dllTimestamp));
+ fileStream.write(stdLibBlobPtr->getBufferPointer(), stdLibBlobPtr->getBufferSize());
+ return SLANG_OK;
+ }
+ catch (...)
+ {
+ }
+ }
+ return SLANG_FAIL;
+}
+
SLANG_API SlangResult slang_createGlobalSession(
SlangInt apiVersion,
slang::IGlobalSession** outGlobalSession)
@@ -32,7 +93,16 @@ SLANG_API SlangResult slang_createGlobalSession(
}
else
{
- SLANG_RETURN_ON_FAIL(globalSession->compileStdLib());
+ Slang::String cacheFilename;
+ uint64_t dllTimestamp = 0;
+ if (tryLoadStdLibFromCache(globalSession, cacheFilename, dllTimestamp) != SLANG_OK)
+ {
+ // Compile std lib from embeded source.
+ SLANG_RETURN_ON_FAIL(globalSession->compileStdLib());
+
+ // Store the compiled stdlib to cache file.
+ trySaveStdLibToCache(globalSession, cacheFilename, dllTimestamp);
+ }
}
*outGlobalSession = globalSession.detach();