-
Notifications
You must be signed in to change notification settings - Fork 718
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
Add a test dxil lib for testing loadability #5952
Conversation
555772b
to
737636f
Compare
This creates a dxil library that doesn't sign anything, but does perform the validation very much as the internal validator does. This is used to test that the compiler and validator objects can properly locate, load, and make use of the external dxil library. The DxilLib test verifies both that loading the compiler with the external dxil library available will load that library by default, resulting in compiles without the usual warning when it is not found and also that explicitly loading the library can be done and the correct API calls can be used. Fixes microsoft#5394
Co-authored-by: Xiang Li <python3kgae@outlook.com>
Co-authored-by: Xiang Li <python3kgae@outlook.com>
You can test this locally with the following command:git-clang-format --diff ceff9b8043df3ac8d7d3ce71b409d83afcd7925b 63d46cd46bfa8ae170e9bc53d93dfe4fb6f55141 -- include/dxc/HLSL/DxilValidator.h lib/HLSL/DxilValidator.cpp tools/no-sig-dxillib/DxilContainerBuilder.cpp tools/no-sig-dxillib/DxilLib.cpp tools/no-sig-dxillib/DxilLibValidator.cpp unittests/DXILLib/DxilLibTest.cpp tools/clang/tools/dxclib/dxc.cpp tools/clang/tools/dxcompiler/dxcapi.cpp tools/clang/tools/dxcompiler/dxcvalidator.cpp View the diff from clang-format here.diff --git a/lib/HLSL/DxilValidator.cpp b/lib/HLSL/DxilValidator.cpp
index 5230ec11a..58c5d1442 100644
--- a/lib/HLSL/DxilValidator.cpp
+++ b/lib/HLSL/DxilValidator.cpp
@@ -21,8 +21,8 @@
#include "dxc/DxilRootSignature/DxilRootSignature.h"
#include "dxc/Support/FileIOHelper.h"
#include "dxc/Support/Global.h"
-#include "dxc/dxcapi.h"
#include "dxc/Support/dxcapi.impl.h"
+#include "dxc/dxcapi.h"
#include "llvm/Support/MemoryBuffer.h"
#ifdef _WIN32
@@ -219,7 +219,7 @@ HRESULT DxilValidator::RunValidation(
HRESULT
DxilValidator::RunRootSignatureValidation(IDxcBlob *pShader,
- AbstractMemoryStream *pDiagStream) {
+ AbstractMemoryStream *pDiagStream) {
const DxilContainerHeader *pDxilContainer = IsDxilContainerLike(
pShader->GetBufferPointer(), pShader->GetBufferSize());
@@ -275,4 +275,3 @@ HRESULT RunInternalValidator(IDxcValidator *pValidator, llvm::Module *pModule,
return pInternalValidator->ValidateWithOptModules(pShader, Flags, pModule,
pDebugModule, ppResult);
}
-
diff --git a/tools/clang/tools/dxcompiler/dxcvalidator.cpp b/tools/clang/tools/dxcompiler/dxcvalidator.cpp
index ba68aa70c..5a11a96b4 100644
--- a/tools/clang/tools/dxcompiler/dxcvalidator.cpp
+++ b/tools/clang/tools/dxcompiler/dxcvalidator.cpp
@@ -50,15 +50,15 @@ private:
public:
DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL()
DXC_MICROCOM_TM_ALLOC(DxcValidator)
- DxcValidator(IMalloc *pMalloc) : DxilValidator(pMalloc), m_dwRef(0), m_pMalloc(pMalloc) {}
+ DxcValidator(IMalloc *pMalloc)
+ : DxilValidator(pMalloc), m_dwRef(0), m_pMalloc(pMalloc) {}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid,
void **ppvObject) override {
- return DoBasicQueryInterface<IDxcValidator, IDxcValidator2, IDxcVersionInfo>(this, iid,
- ppvObject);
+ return DoBasicQueryInterface<IDxcValidator, IDxcValidator2,
+ IDxcVersionInfo>(this, iid, ppvObject);
}
-
// IDxcVersionInfo
HRESULT STDMETHODCALLTYPE GetVersion(UINT32 *pMajor, UINT32 *pMinor) override;
HRESULT STDMETHODCALLTYPE GetFlags(UINT32 *pFlags) override;
diff --git a/tools/no-sig-dxillib/DxilLibValidator.cpp b/tools/no-sig-dxillib/DxilLibValidator.cpp
index b2636ff36..1028f0ea6 100644
--- a/tools/no-sig-dxillib/DxilLibValidator.cpp
+++ b/tools/no-sig-dxillib/DxilLibValidator.cpp
@@ -10,34 +10,34 @@
// //
///////////////////////////////////////////////////////////////////////////////
-#include "dxc/HLSL/DxilValidator.h"
#include "dxc/HLSL/DxilValidation.h"
+#include "dxc/HLSL/DxilValidator.h"
#include "dxc/Support/FileIOHelper.h"
#include "dxc/Support/dxcapi.impl.h"
-class DxilLibValidator : public DxilValidator, public IDxcVersionInfo
-{
+class DxilLibValidator : public DxilValidator, public IDxcVersionInfo {
private:
DXC_MICROCOM_TM_REF_FIELDS()
public:
DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL()
- DxilLibValidator(IMalloc *pMalloc) : DxilValidator(pMalloc), m_dwRef(0), m_pMalloc(pMalloc) {}
+ DxilLibValidator(IMalloc *pMalloc)
+ : DxilValidator(pMalloc), m_dwRef(0), m_pMalloc(pMalloc) {}
DXC_MICROCOM_TM_ALLOC(DxilLibValidator)
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid,
void **ppvObject) override {
- return DoBasicQueryInterface<IDxcValidator, IDxcValidator2, IDxcVersionInfo>(this, iid, ppvObject);
+ return DoBasicQueryInterface<IDxcValidator, IDxcValidator2,
+ IDxcVersionInfo>(this, iid, ppvObject);
}
// IDxcVersionInfo
HRESULT STDMETHODCALLTYPE GetVersion(UINT32 *pMajor, UINT32 *pMinor) override;
HRESULT STDMETHODCALLTYPE GetFlags(UINT32 *pFlags) override;
-
};
HRESULT STDMETHODCALLTYPE DxilLibValidator::GetVersion(UINT32 *pMajor,
- UINT32 *pMinor) {
+ UINT32 *pMinor) {
if (pMajor == nullptr || pMinor == nullptr)
return E_INVALIDARG;
hlsl::GetValidationVersion(pMajor, pMinor);
diff --git a/unittests/DXILLib/DxilLibTest.cpp b/unittests/DXILLib/DxilLibTest.cpp
index c369c085c..1011899a7 100644
--- a/unittests/DXILLib/DxilLibTest.cpp
+++ b/unittests/DXILLib/DxilLibTest.cpp
@@ -101,8 +101,8 @@ TEST(DxilLibTest, LoadFromCompiler) {
if (errBuf)
EXPECT_EQ(errBuf->GetBufferSize(), 0U)
- << "Unexpected diagnostics found in compiler error buffer: "
- << (const char *)errBuf->GetBufferPointer();
+ << "Unexpected diagnostics found in compiler error buffer: "
+ << (const char *)errBuf->GetBufferPointer();
}
// Check that dxil lib can be loaded and trivially used by a validator object
@@ -140,7 +140,9 @@ TEST(DxilLibTest, LoadFromValidator) {
EXPECT_TRUE(SUCCEEDED(status1));
ASSERT_TRUE(SUCCEEDED(validationResult1->GetErrorBuffer(&errBuf1)));
if (errBuf1)
- EXPECT_EQ(errBuf1->GetBufferSize(), 0U) << "Unexpected diagnostics found in validator1 error buffer: " << (const char *)errBuf1->GetBufferPointer();
+ EXPECT_EQ(errBuf1->GetBufferSize(), 0U)
+ << "Unexpected diagnostics found in validator1 error buffer: "
+ << (const char *)errBuf1->GetBufferPointer();
CComPtr<IDxcOperationResult> validationResult2;
HRESULT status2 = S_OK;
@@ -151,5 +153,7 @@ TEST(DxilLibTest, LoadFromValidator) {
EXPECT_TRUE(SUCCEEDED(status2));
ASSERT_TRUE(SUCCEEDED(validationResult2->GetErrorBuffer(&errBuf2)));
if (errBuf2)
- EXPECT_EQ(errBuf2->GetBufferSize(), 0U) << "Unexpected diagnostics found in validator2 error buffer: " << (const char *)errBuf2->GetBufferPointer();
+ EXPECT_EQ(errBuf2->GetBufferSize(), 0U)
+ << "Unexpected diagnostics found in validator2 error buffer: "
+ << (const char *)errBuf2->GetBufferPointer();
}
|
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.
Do we need a test case for validation fail?
The intent of this is not to test validation really, but just that the library is loadable and usable. We have a lot of tests for validation failures. Originally, my intent was to use the complete suite of validation tests on the loadable dxil lib, but was convinced that was overkill |
Using this library to validate more content is actually useful because it takes a different validation path than the internal validator. This validation path can and has been broken multiple times before while internal validation path did not catch the problem. This is because the internal validation path uses the main and debug llvm modules from in-memory form without going through serialization and deserialization. Something that doesn't get preserved exactly the same way through serialization/deserialization can cause a failure with the external validation path that isn't caught by the internal path. In short, I think we should run all content against this external validation path when possible. We don't even need to run content twice to do this, we can simply use this as the available external validator when running tests in GitHub pipelines. |
// License. See LICENSE.TXT for details. // | ||
// // | ||
// Implements the Dxil Container Builder // | ||
// // |
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.
The comment is incorrect, it does not really implement a container builder. Any reason why this is not part of the DxilLib.cpp?
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 catch. The reason it's not part of DxilLib.cpp is because of some inclusions this requires that confuse the code in DxilLib.cpp. I spent a little while trying to resolve them, but decided it wasn't worth it as this is the structure of similar code elsewhere likely for the same reason.
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.
Mainly: I think we might be able to move dxcvalidator.cpp
into shared lib instead of reimplementing most of it here.
using namespace hlsl; | ||
|
||
HRESULT CreateDxcContainerBuilder(_In_ REFIID riid, _Out_ LPVOID *ppv) { | ||
// Call dxil.dll's containerbuilder |
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.
Is this comment accurate? Isn't this creating the local container builder instead?
tools/testdxildll/DxilValidator.cpp
Outdated
using namespace llvm; | ||
using namespace hlsl; | ||
|
||
class DxcValidator : public IDxcValidator2, public IDxcVersionInfo { |
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.
Wait, why can't we move DxcValidator.cpp out of dxcompiler project into shared lib, then you can simply use the same one instead reimplementing so much 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.
Done
|
||
using namespace hlsl; | ||
|
||
HRESULT CreateDxcContainerBuilder(_In_ REFIID riid, _Out_ LPVOID *ppv) { |
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.
Couldn't this be implemented in DxilLib.cpp, since we really aren't supplying another implementation here? One might almost mix it up with DxcContainerBuilder.cpp
where we implement the internal builder that this code uses.
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.
There were some compilation errors when I tried to do this before that had to do with conflicting defines. I'll take another run at it.
tools/testdxildll/DxilLib.cpp
Outdated
@@ -0,0 +1,150 @@ | |||
/////////////////////////////////////////////////////////////////////////////// |
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.
Would you mind renaming DxilLib.* files to TestDxilLib.*? I am often searching through the whole code base and since this code is similar to the actual DxilLib.cpp it would be nice to have it under a different name so it can be clearly seen in the search results that this is the test dll.
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.
Will do
dashes match how directories in the same place are named. no-sig is a clearer prefix because it describes function instead of intent and makes it less likely to mistake it for a test utility. dxillib is platform neutral unline dxildll
No changes, just to make reviewing the actual changes easier since the DxilValidator parent class is mostly derived from dxcvalidator with some removals
This consolidates the validation part of the validator while separating the version queries since dxcompiler gets a different version of versioninfo than dxil lib does. DxilValidator.cpp was previously a direct copy of dxcvalidator.cpp. This strips the versioninfo from DxilValidator and strips the Validation from dxcvalidator as it now gets that functionality from the parent class
Update comment in dxc.cpp that misrepresented what legacy FXC flags are supported and which ones are planned for the future. The warning passed into DxcContainerBuilder is unassigned in the default case. It is assumed to be null if unneeded, but that's not guaranteed unless it is initialized properly.
This enables us to use it as the default unsigning validator
Remove line numbers from a number of tests that, lacking the internal validator, will not have access to line numbers anymore Take more care with default values and possibly null pointers in DxilLibTest Correctly set the out directory for the test lib copying
include/dxc/HLSL/DxilValidator.h
Outdated
class AbstractMemoryStream; | ||
} | ||
|
||
class DxilValidator : public IDxcValidator2 { |
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.
Could we rename DxilValidator
to DxcValidatorBase
?
It's already a little confusing to have DxilValidation
and DxcValidator
, but it's a pattern that is used elsewhere, with core implementation in Dxil*
and Dxc*
being the implementation of the IDxc*
interface.
Adding DxilValidator
confuses things more, while I think DxcValidatorBase
makes the purpose of being a base class for the IDxcValidator
implementation clearer.
Added a NoSig prefix to all files and classes to clarify that these are not the main dxil lib
HRESULT STDMETHODCALLTYPE DxilLibValidator::GetFlags(UINT32 *pFlags) { | ||
if (pFlags == nullptr) | ||
return E_INVALIDARG; | ||
*pFlags = DxcVersionInfoFlags_None; |
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.
One issue I recently thought of is that the lack of DxcVersionInfoFlags_Internal
would normally be used to detect that you have a signing validator. This makes the result from GetFlags on this dll potentially confusing, right? Maybe we could have a DxcVersionInfoFlags_Test
flag for the test dll, so at least we can tell this is the non-production external test validator. What do you think?
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.
DxcVersionInfoFlags_Internal
can also be used to determine whether we should expect the line-only debug info supplied to the validator when the validator is called automatically from Compile().
@@ -2,7 +2,7 @@ | |||
// RUN: %dxilver 1.6 | %dxc -E main -T as_6_5 %s | FileCheck %s -check-prefix=CHK_NODB | |||
|
|||
// CHK_DB: 23:5: error: For amplification shader with entry 'main', payload size 16400 is greater than maximum size of 16384 bytes. | |||
// CHK_NODB: 23:5: error: For amplification shader with entry 'main', payload size 16400 is greater than maximum size of 16384 bytes. | |||
// CHK_NODB: error: For amplification shader with entry 'main', payload size 16400 is greater than maximum size of 16384 bytes. |
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.
This change shouldn't have been necessary. IDxcValidator2::ValidateWithDebug allows you to provide the serialized debug module, which is normally provided to the external validator when present. This must work with the normal DXIL.dll because these don't normally fail when testing against that. So perhaps there's something wrong with the new test validator?
Renamed DxilValidator to DxcValidatorBase to prevent confusion between DxilValdation and DxilValidator. Renamed dxil lib back to testdxil because testing dxil.dll broadly is going to require more care to be done right.
correctly identify dependency of LLVMHLSL on DxilRootSignature. The dependency was pre-existing, but never caused any problems because the order of linking just happened to come out right for the Linux linker Secondly, a mistaken direct usage of declspec was left in from testing instead of using the define
Ready for review again! I recommend looking at the changes to the DxcValidatorBase using this sequence of changes that starts just after dxcvalidator.cpp was copied into that place so you can see the changes that were meaningful without the confusing copy. https://github.com/microsoft/DirectXShaderCompiler/pull/5952/files/d00cb4dfff7497a0aa096121bbdceafa0a8ea3ce..d67697a3bc2d458e948a79e6b89fd9b32794f7c3 |
Since we're not using the fake dxil.dll everywhere, these will still be available
Now that we've open sourced the validator/hashing we'll likely address this a different way. |
This creates a dxil library that doesn't sign anything, but does perform the validation very much as the internal validator does. This is used to test that the compiler and validator objects can properly locate, load, and make use of the external dxil library.
The DxilLib test verifies both that loading the compiler with the external dxil library available will load that library by default, resulting in compiles without the usual warning when it is not found and also that explicitly loading the library can be done and the correct API calls can be used.
Fixes #5394