-
Notifications
You must be signed in to change notification settings - Fork 792
Create new class to handle external validation, and rename existing dll loading class. #7514
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 36 commits
d7d1936
c527502
7f7dc30
e7ec854
39f913c
3700bfd
33c88f9
544a9c7
eeb1516
9800c91
a4c9629
a9282fd
e781627
2915a8d
57dd853
98b25af
c274e5b
b46def4
b76fab2
89dcc4a
acbf68a
f2890f5
eb1e96f
36c33a2
6577046
80b50a6
bfc508f
a144ca1
bd01fa5
647c946
a29f6ee
fffb407
5411894
45f74fa
64f61a8
ed23ada
2383541
209582f
daf6f0a
c8d867e
0aa3c8d
15fceac
09be489
be99192
cba829b
17f26c6
c0ee094
cdf321e
c8b704a
965f78c
48fb6fa
b100acd
f66408c
c8bebee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#include "dxc/Support/dxcapi.use.h" | ||
#include <string> | ||
|
||
namespace dxc { | ||
class DxcDllExtValidationLoader : public DllLoader { | ||
// DxCompilerSupport manages the | ||
// lifetime of dxcompiler.dll, while DxilExtValSupport | ||
// manages the lifetime of dxil.dll | ||
dxc::SpecificDllLoader DxCompilerSupport; | ||
dxc::SpecificDllLoader DxilExtValSupport; | ||
|
||
DxcCreateInstanceProc m_createFn; | ||
DxcCreateInstance2Proc m_createFn2; | ||
|
||
std::string DxilDllPath; | ||
tex3d marked this conversation as resolved.
Show resolved
Hide resolved
|
||
HRESULT InitializeInternal(LPCSTR fnName); | ||
|
||
public: | ||
std::string GetDxilDllPath() { return DxilDllPath; } | ||
bool DxilDllFailedToLoad() { | ||
tex3d marked this conversation as resolved.
Show resolved
Hide resolved
damyanp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return !DxilDllPath.empty() && !DxilExtValSupport.IsEnabled(); | ||
} | ||
|
||
HRESULT CreateInstance(REFCLSID clsid, REFIID riid, IUnknown **pResult); | ||
HRESULT CreateInstance2(IMalloc *pMalloc, REFCLSID clsid, REFIID riid, | ||
IUnknown **pResult); | ||
|
||
HRESULT Initialize() { return InitializeInternal("DxcCreateInstance"); } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point, looks like we dont need it at all. I'll remove InitializeInternal and move its implementation to Initialize(). |
||
HRESULT InitializeForDll(LPCSTR dll, LPCSTR entryPoint) { | ||
return InitializeInternal(dll); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't look right. I mention elsewhere in the review that I think a better name for this interface would be "overrideDll" or something to that effect. The users of this API are saying "use this other Dll I specified on the command line" or something to that effect. I guess we should pass on both parameters here when we call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the right fix here is simply to change what's passed from dll to entryPoint, like you said. But, I don't think we should pass both args to InitializeInternal. TLDR: I'll replace dll with entry point, that is correct. But InitialzieInternal shouldn't care about user dlls, the dlls that are loaded should be hard-coded into the internal function itself. |
||
|
||
bool HasCreateWithMalloc() const { return m_createFn2 != nullptr; } | ||
damyanp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
bool IsEnabled() const { return DxCompilerSupport.IsEnabled(); } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to check both dlls here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think so. It is legal for this object to be initialized with no env var, and thus no dxil.dll loaded. So the 2nd dll won't be enabled. |
||
|
||
bool GetCreateInstanceProcs(DxcCreateInstanceProc *pCreateFn, | ||
DxcCreateInstance2Proc *pCreateFn2) const; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this for? Is it used for anything? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was originally intended just to be defined for the |
||
|
||
void Cleanup() { | ||
DxilExtValSupport.Cleanup(); | ||
DxCompilerSupport.Cleanup(); | ||
} | ||
|
||
HMODULE Detach() { | ||
// Can't Detach and return a handle for DxilSupport. Cleanup() instead. | ||
DxilExtValSupport.Cleanup(); | ||
return DxCompilerSupport.Detach(); | ||
} | ||
}; | ||
tex3d marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} // namespace dxc |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,9 +19,52 @@ namespace dxc { | |
extern const char *kDxCompilerLib; | ||
extern const char *kDxilLib; | ||
|
||
// Interface for common dll operations | ||
class DllLoader { | ||
damyanp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public: | ||
damyanp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
DllLoader() = default; | ||
|
||
DllLoader(DllLoader &&other) = default; | ||
damyanp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
virtual ~DllLoader() = default; | ||
|
||
virtual HRESULT Initialize() = 0; | ||
|
||
virtual HRESULT InitializeForDll(LPCSTR dll, LPCSTR entryPoint) = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be nice if we could remove
|
||
|
||
template <typename TInterface> | ||
HRESULT CreateInstance(REFCLSID clsid, TInterface **pResult) { | ||
return CreateInstance(clsid, __uuidof(TInterface), (IUnknown **)pResult); | ||
} | ||
|
||
virtual HRESULT CreateInstance(REFCLSID clsid, REFIID riid, | ||
IUnknown **pResult) = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would simplify things to implement this whole overload set and then add a protected:
virtual HRESULT CreateInstanceImpl(REFCLSID clsid, REFIID riid,
IUnknown **pResult) = 0; public:
template <typename TInterface>
HRESULT CreateInstance(REFCLSID clsid, TInterface **pResult) {
return CreateInstanceImpl(clsid, __uuidof(TInterface),
(IUnknown **)pResult);
}
HRESULT CreateInstance(REFCLSID clsid, REFIID riid,
IUnknown **pResult) {
return CreateInstanceImpl(clsid, riid, (IUnknown **)pResult);
} This also applies to |
||
|
||
template <typename TInterface> | ||
HRESULT CreateInstance2(IMalloc *pMalloc, REFCLSID clsid, | ||
TInterface **pResult) { | ||
return CreateInstance2(pMalloc, clsid, __uuidof(TInterface), | ||
(IUnknown **)pResult); | ||
} | ||
|
||
virtual HRESULT CreateInstance2(IMalloc *pMalloc, REFCLSID clsid, REFIID riid, | ||
IUnknown **pResult) = 0; | ||
|
||
virtual bool HasCreateWithMalloc() const = 0; | ||
damyanp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
virtual bool IsEnabled() const = 0; | ||
|
||
virtual bool | ||
GetCreateInstanceProcs(DxcCreateInstanceProc *pCreateFn, | ||
DxcCreateInstance2Proc *pCreateFn2) const = 0; | ||
|
||
virtual void Cleanup() = 0; | ||
virtual HMODULE Detach() = 0; | ||
damyanp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}; | ||
|
||
// Helper class to dynamically load the dxcompiler or a compatible libraries. | ||
class DxcDllSupport { | ||
protected: | ||
class SpecificDllLoader : public DllLoader { | ||
|
||
HMODULE m_dll; | ||
DxcCreateInstanceProc m_createFn; | ||
DxcCreateInstance2Proc m_createFn2; | ||
|
@@ -74,9 +117,10 @@ class DxcDllSupport { | |
} | ||
|
||
public: | ||
DxcDllSupport() : m_dll(nullptr), m_createFn(nullptr), m_createFn2(nullptr) {} | ||
SpecificDllLoader() | ||
: m_dll(nullptr), m_createFn(nullptr), m_createFn2(nullptr) {} | ||
|
||
DxcDllSupport(DxcDllSupport &&other) { | ||
SpecificDllLoader(SpecificDllLoader &&other) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this move constructor actually used? I would expect that we pass these around exclusively as pointers (and usually pointers to the interface class) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is an instance here: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In HlslIntellisenseSupport? That instance isn't used either - so both the HlslIntellisenseSupport and SpecificDllLoader move constructors should be removed. (I'm a bit surprised that this compiles as is, since we've deleted the base class's copy and move constructors) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This move constructor should be removed. |
||
m_dll = other.m_dll; | ||
other.m_dll = nullptr; | ||
m_createFn = other.m_createFn; | ||
|
@@ -85,7 +129,7 @@ class DxcDllSupport { | |
other.m_createFn2 = nullptr; | ||
} | ||
|
||
~DxcDllSupport() { Cleanup(); } | ||
~SpecificDllLoader() { Cleanup(); } | ||
damyanp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
HRESULT Initialize() { | ||
return InitializeInternal(kDxCompilerLib, "DxcCreateInstance"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having this particular implementation of I don't think this is really possible without either removing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps it would raise an eyebrow on first glance, but the initialize function needs a dll to work with, because it has no args. We need some dll to default to, and dxcompilerlib is a fine one to default to. If users wanted something else, they could initialize with OverrideDll and specify the dll. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What I'm saying is is "do we even want an For convenience, we could subclass this with |
||
|
@@ -95,11 +139,9 @@ class DxcDllSupport { | |
return InitializeInternal(dll, entryPoint); | ||
} | ||
|
||
template <typename TInterface> | ||
HRESULT CreateInstance(REFCLSID clsid, TInterface **pResult) { | ||
return CreateInstance(clsid, __uuidof(TInterface), (IUnknown **)pResult); | ||
} | ||
|
||
// Also bring visibility into the interface definition of this function | ||
// which takes 2 args | ||
using DllLoader::CreateInstance; | ||
HRESULT CreateInstance(REFCLSID clsid, REFIID riid, IUnknown **pResult) { | ||
if (pResult == nullptr) | ||
return E_POINTER; | ||
|
@@ -109,13 +151,9 @@ class DxcDllSupport { | |
return hr; | ||
} | ||
|
||
template <typename TInterface> | ||
HRESULT CreateInstance2(IMalloc *pMalloc, REFCLSID clsid, | ||
TInterface **pResult) { | ||
return CreateInstance2(pMalloc, clsid, __uuidof(TInterface), | ||
(IUnknown **)pResult); | ||
} | ||
|
||
// Also bring visibility into the interface definition of this function | ||
// which takes 3 args | ||
using DllLoader::CreateInstance2; | ||
HRESULT CreateInstance2(IMalloc *pMalloc, REFCLSID clsid, REFIID riid, | ||
IUnknown **pResult) { | ||
if (pResult == nullptr) | ||
|
@@ -132,6 +170,15 @@ class DxcDllSupport { | |
|
||
bool IsEnabled() const { return m_dll != nullptr; } | ||
|
||
bool GetCreateInstanceProcs(DxcCreateInstanceProc *pCreateFn, | ||
DxcCreateInstance2Proc *pCreateFn2) const { | ||
if (pCreateFn == nullptr || pCreateFn2 == nullptr || m_createFn == nullptr) | ||
return false; | ||
*pCreateFn = m_createFn; | ||
*pCreateFn2 = m_createFn2; | ||
return true; | ||
} | ||
|
||
void Cleanup() { | ||
if (m_dll != nullptr) { | ||
m_createFn = nullptr; | ||
|
@@ -162,8 +209,8 @@ inline DxcDefine GetDefine(LPCWSTR name, LPCWSTR value) { | |
// Checks an HRESULT and formats an error message with the appended data. | ||
void IFT_Data(HRESULT hr, LPCWSTR data); | ||
|
||
void EnsureEnabled(DxcDllSupport &dxcSupport); | ||
void ReadFileIntoBlob(DxcDllSupport &dxcSupport, LPCWSTR pFileName, | ||
void EnsureEnabled(SpecificDllLoader &dxcSupport); | ||
void ReadFileIntoBlob(SpecificDllLoader &dxcSupport, LPCWSTR pFileName, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These should be |
||
IDxcBlobEncoding **ppBlobEncoding); | ||
void WriteBlobToConsole(IDxcBlob *pBlob, DWORD streamType = STD_OUTPUT_HANDLE); | ||
void WriteBlobToFile(IDxcBlob *pBlob, LPCWSTR pFileName, UINT32 textCodePage); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1383,9 +1383,10 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, | |
return 0; | ||
} | ||
|
||
/// Sets up the specified DxcDllSupport instance as per the given options. | ||
int SetupDxcDllSupport(const DxcOpts &opts, dxc::DxcDllSupport &dxcSupport, | ||
llvm::raw_ostream &errors) { | ||
/// Sets up the specified SpecificDllLoader instance as per the given options. | ||
int SetupSpecificDllLoader(const DxcOpts &opts, | ||
dxc::SpecificDllLoader &dxcSupport, | ||
llvm::raw_ostream &errors) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this rename is kind of confusing - the type of the object isn't what's interesting here, we're actually modifying how our There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, in some cases this should be more abstracted. However, in cases like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand this comment - this function is never called in ShaderOpTest.cpp - it's only used in |
||
if (!opts.ExternalLib.empty()) { | ||
DXASSERT(!opts.ExternalFn.empty(), "else ReadDxcOpts should have failed"); | ||
HRESULT hrLoad = dxcSupport.InitializeForDll(opts.ExternalLib.data(), | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are never initialized to anything. Should they really be here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I don't think so. I imagine the relevant creation functions will only be stored in the specificdllloader member objects.