|
@@ -10,6 +10,7 @@
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#include "dxc/Support/WinIncludes.h"
|
|
#include "dxc/Support/WinIncludes.h"
|
|
|
|
+#include "dxc/Support/Global.h"
|
|
#include "dxc/dxcapi.h"
|
|
#include "dxc/dxcapi.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/Hashing.h"
|
|
#include "llvm/ADT/Hashing.h"
|
|
@@ -18,10 +19,59 @@
|
|
#include <unordered_map>
|
|
#include <unordered_map>
|
|
#include "lib_share_helper.h"
|
|
#include "lib_share_helper.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
+#include "dxc/Support/FileIOHelper.h"
|
|
|
|
|
|
using namespace llvm;
|
|
using namespace llvm;
|
|
using namespace libshare;
|
|
using namespace libshare;
|
|
|
|
|
|
|
|
+#include "dxc/Support/dxcapi.use.h"
|
|
|
|
+#include "dxc/dxctools.h"
|
|
|
|
+namespace {
|
|
|
|
+class NoFuncBodyRewriter {
|
|
|
|
+public:
|
|
|
|
+ NoFuncBodyRewriter() {
|
|
|
|
+ if (!m_dllSupport.IsEnabled())
|
|
|
|
+ m_dllSupport.Initialize();
|
|
|
|
+ m_dllSupport.CreateInstance(CLSID_DxcRewriter, &m_pRewriter);
|
|
|
|
+ }
|
|
|
|
+ HRESULT RewriteToNoFuncBody(LPCWSTR pFilename,
|
|
|
|
+ IDxcBlobEncoding *pSource,
|
|
|
|
+ std::vector<DxcDefine> &m_defines,
|
|
|
|
+ IDxcBlob **ppNoFuncBodySource);
|
|
|
|
+
|
|
|
|
+private:
|
|
|
|
+ CComPtr<IDxcRewriter> m_pRewriter;
|
|
|
|
+ dxc::DxcDllSupport m_dllSupport;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+HRESULT NoFuncBodyRewriter::RewriteToNoFuncBody(
|
|
|
|
+ LPCWSTR pFilename, IDxcBlobEncoding *pSource,
|
|
|
|
+ std::vector<DxcDefine> &m_defines, IDxcBlob **ppNoFuncBodySource) {
|
|
|
|
+ // Create header with no function body.
|
|
|
|
+ CComPtr<IDxcOperationResult> pRewriteResult;
|
|
|
|
+ IFT(m_pRewriter->RewriteUnchangedWithInclude(
|
|
|
|
+ pSource, pFilename, m_defines.data(), m_defines.size(),
|
|
|
|
+ // Don't need include handler here, include already read in
|
|
|
|
+ // RewriteIncludesToSnippet
|
|
|
|
+ nullptr,
|
|
|
|
+ RewriterOptionMask::SkipFunctionBody | RewriterOptionMask::KeepUserMacro,
|
|
|
|
+ &pRewriteResult));
|
|
|
|
+ HRESULT status;
|
|
|
|
+ if (!SUCCEEDED(pRewriteResult->GetStatus(&status)) || !SUCCEEDED(status)) {
|
|
|
|
+ CComPtr<IDxcBlobEncoding> pErr;
|
|
|
|
+ IFT(pRewriteResult->GetErrorBuffer(&pErr));
|
|
|
|
+ std::string errString =
|
|
|
|
+ std::string((char *)pErr->GetBufferPointer(), pErr->GetBufferSize());
|
|
|
|
+ IFTMSG(E_FAIL, errString);
|
|
|
|
+ return E_FAIL;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // Get result.
|
|
|
|
+ IFT(pRewriteResult->GetResult(ppNoFuncBodySource));
|
|
|
|
+ return S_OK;
|
|
|
|
+}
|
|
|
|
+} // namespace
|
|
|
|
+
|
|
namespace {
|
|
namespace {
|
|
|
|
|
|
struct KeyHash {
|
|
struct KeyHash {
|
|
@@ -36,19 +86,26 @@ struct KeyEqual {
|
|
class LibCacheManagerImpl : public libshare::LibCacheManager {
|
|
class LibCacheManagerImpl : public libshare::LibCacheManager {
|
|
public:
|
|
public:
|
|
~LibCacheManagerImpl() {}
|
|
~LibCacheManagerImpl() {}
|
|
- HRESULT AddLibBlob(IDxcBlob *pSource, CompileInput &compiler, size_t &hash,
|
|
|
|
|
|
+ HRESULT AddLibBlob(std::string &processedHeader, const std::string &snippet,
|
|
|
|
+ CompileInput &compiler, size_t &hash,
|
|
IDxcBlob **pResultLib,
|
|
IDxcBlob **pResultLib,
|
|
- std::function<void(void)> compileFn) override;
|
|
|
|
- bool GetLibBlob(IDxcBlob *pSource, CompileInput &compiler, size_t &hash,
|
|
|
|
|
|
+ std::function<void(IDxcBlob *pSource)> compileFn) override;
|
|
|
|
+ bool GetLibBlob(std::string &processedHeader, const std::string &snippet,
|
|
|
|
+ CompileInput &compiler, size_t &hash,
|
|
IDxcBlob **pResultLib) override;
|
|
IDxcBlob **pResultLib) override;
|
|
void Release() { m_libCache.clear(); }
|
|
void Release() { m_libCache.clear(); }
|
|
|
|
|
|
private:
|
|
private:
|
|
- hash_code GetHash(IDxcBlob *pSource, CompileInput &compiler);
|
|
|
|
|
|
+ hash_code GetHash(const std::string &header, const std::string &snippet,
|
|
|
|
+ CompileInput &compiler);
|
|
using libCacheType =
|
|
using libCacheType =
|
|
std::unordered_map<hash_code, CComPtr<IDxcBlob>, KeyHash, KeyEqual>;
|
|
std::unordered_map<hash_code, CComPtr<IDxcBlob>, KeyHash, KeyEqual>;
|
|
libCacheType m_libCache;
|
|
libCacheType m_libCache;
|
|
|
|
+ using headerCacheType =
|
|
|
|
+ std::unordered_map<hash_code, std::string, KeyHash, KeyEqual>;
|
|
|
|
+ headerCacheType m_headerCache;
|
|
std::shared_mutex m_mutex;
|
|
std::shared_mutex m_mutex;
|
|
|
|
+ NoFuncBodyRewriter m_rewriter;
|
|
};
|
|
};
|
|
|
|
|
|
static hash_code CombineWStr(hash_code hash, LPCWSTR Arg) {
|
|
static hash_code CombineWStr(hash_code hash, LPCWSTR Arg) {
|
|
@@ -57,9 +114,10 @@ static hash_code CombineWStr(hash_code hash, LPCWSTR Arg) {
|
|
return hash_combine(hash, StringRef(pUtf8Arg.m_psz, length));
|
|
return hash_combine(hash, StringRef(pUtf8Arg.m_psz, length));
|
|
}
|
|
}
|
|
|
|
|
|
-hash_code LibCacheManagerImpl::GetHash(IDxcBlob *pSource, CompileInput &compiler) {
|
|
|
|
- hash_code libHash = hash_value(
|
|
|
|
- StringRef((char *)pSource->GetBufferPointer(), pSource->GetBufferSize()));
|
|
|
|
|
|
+hash_code LibCacheManagerImpl::GetHash(const std::string &header, const std::string &snippet,
|
|
|
|
+ CompileInput &compiler) {
|
|
|
|
+ hash_code libHash = hash_value(header);
|
|
|
|
+ libHash = hash_combine(libHash, snippet);
|
|
// Combine compile input.
|
|
// Combine compile input.
|
|
for (auto &Arg : compiler.arguments) {
|
|
for (auto &Arg : compiler.arguments) {
|
|
libHash = CombineWStr(libHash, Arg);
|
|
libHash = CombineWStr(libHash, Arg);
|
|
@@ -73,31 +131,14 @@ hash_code LibCacheManagerImpl::GetHash(IDxcBlob *pSource, CompileInput &compiler
|
|
return libHash;
|
|
return libHash;
|
|
}
|
|
}
|
|
|
|
|
|
-bool LibCacheManagerImpl::GetLibBlob(IDxcBlob *pSource, CompileInput &compiler,
|
|
|
|
- size_t &hash, IDxcBlob **pResultLib) {
|
|
|
|
- if (!pSource || !pResultLib) {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
- // Create hash from source.
|
|
|
|
- hash_code libHash = GetHash(pSource, compiler);
|
|
|
|
- hash = libHash;
|
|
|
|
- // lock
|
|
|
|
- std::shared_lock<std::shared_mutex> lk(m_mutex);
|
|
|
|
-
|
|
|
|
- auto it = m_libCache.find(libHash);
|
|
|
|
- if (it != m_libCache.end()) {
|
|
|
|
- *pResultLib = it->second;
|
|
|
|
- return true;
|
|
|
|
- } else {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
|
|
+using namespace hlsl;
|
|
|
|
|
|
-HRESULT
|
|
|
|
-LibCacheManagerImpl::AddLibBlob(IDxcBlob *pSource, CompileInput &compiler,
|
|
|
|
- size_t &hash, IDxcBlob **pResultLib,
|
|
|
|
- std::function<void(void)> compileFn) {
|
|
|
|
- if (!pSource || !pResultLib) {
|
|
|
|
|
|
+HRESULT LibCacheManagerImpl::AddLibBlob(std::string &processedHeader,
|
|
|
|
+ const std::string &snippet,
|
|
|
|
+ CompileInput &compiler, size_t &hash,
|
|
|
|
+ IDxcBlob **pResultLib,
|
|
|
|
+ std::function<void(IDxcBlob *pSource)> compileFn) {
|
|
|
|
+ if (!pResultLib) {
|
|
return E_FAIL;
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -106,16 +147,51 @@ LibCacheManagerImpl::AddLibBlob(IDxcBlob *pSource, CompileInput &compiler,
|
|
auto it = m_libCache.find(hash);
|
|
auto it = m_libCache.find(hash);
|
|
if (it != m_libCache.end()) {
|
|
if (it != m_libCache.end()) {
|
|
*pResultLib = it->second;
|
|
*pResultLib = it->second;
|
|
|
|
+ DXASSERT(m_headerCache.count(hash), "else mismatch header and lib");
|
|
|
|
+ processedHeader = m_headerCache[hash];
|
|
return S_OK;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
+ std::string shader = processedHeader + snippet;
|
|
|
|
+ CComPtr<IDxcBlobEncoding> pSource;
|
|
|
|
+ IFT(DxcCreateBlobWithEncodingOnMallocCopy(GetGlobalHeapMalloc(), shader.data(), shader.size(), CP_UTF8, &pSource));
|
|
|
|
|
|
- compileFn();
|
|
|
|
|
|
+ compileFn(pSource);
|
|
|
|
|
|
m_libCache[hash] = *pResultLib;
|
|
m_libCache[hash] = *pResultLib;
|
|
|
|
|
|
|
|
+ // Rewrite curHeader to remove function body.
|
|
|
|
+ CComPtr<IDxcBlob> result;
|
|
|
|
+ IFT(m_rewriter.RewriteToNoFuncBody(L"input.hlsl", pSource, compiler.defines, &result));
|
|
|
|
+ processedHeader = std::string((char *)(result)->GetBufferPointer(),
|
|
|
|
+ (result)->GetBufferSize());
|
|
|
|
+ m_headerCache[hash] = processedHeader;
|
|
return S_OK;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+bool LibCacheManagerImpl::GetLibBlob(std::string &processedHeader,
|
|
|
|
+ const std::string &snippet,
|
|
|
|
+ CompileInput &compiler, size_t &hash,
|
|
|
|
+ IDxcBlob **pResultLib) {
|
|
|
|
+ if (!pResultLib) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ // Create hash from source.
|
|
|
|
+ hash_code libHash = GetHash(processedHeader, snippet, compiler);
|
|
|
|
+ hash = libHash;
|
|
|
|
+ // lock
|
|
|
|
+ std::shared_lock<std::shared_mutex> lk(m_mutex);
|
|
|
|
+
|
|
|
|
+ auto it = m_libCache.find(libHash);
|
|
|
|
+ if (it != m_libCache.end()) {
|
|
|
|
+ *pResultLib = it->second;
|
|
|
|
+ DXASSERT(m_headerCache.count(libHash), "else mismatch header and lib");
|
|
|
|
+ processedHeader = m_headerCache[libHash];
|
|
|
|
+ return true;
|
|
|
|
+ } else {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
LibCacheManager *GetLibCacheManagerPtr(bool bFree) {
|
|
LibCacheManager *GetLibCacheManagerPtr(bool bFree) {
|
|
static std::unique_ptr<LibCacheManagerImpl> g_LibCache =
|
|
static std::unique_ptr<LibCacheManagerImpl> g_LibCache =
|
|
llvm::make_unique<LibCacheManagerImpl>();
|
|
llvm::make_unique<LibCacheManagerImpl>();
|