-
Notifications
You must be signed in to change notification settings - Fork 692
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
Open source dxil.dll #6770
Open source dxil.dll #6770
Conversation
✅ With the latest revision this PR passed the C/C++ code formatter. |
@python3kgae, I realize that you didn't write all this code and you're really just copying it from an internal fork into the public repo. That said, there are a lot of small things about this code that don't meet the LLVM coding standards. It might be worth spending a little bit of time cleaning up some of the low hanging fruit so that the code goes into the public repo in a cleaner state. I pointed out a few places where the terminology "signing" is used to describe the hashing process. I think we need to correct all of those (there are still more). I know that historically this was called "signing", but it is not a signature and calling it a signature places an unmet expectation on what the code does. |
All the 'signning's are replaced with 'hashing' already. |
We spent months last year reviewing and cleaning up the SM 6.8 code to get closer to meeting LLVM's coding standards. I think spending a little time on this PR makes sense. Some things to look for:
I'm not asking that you rewrite this code, just spend a few minutes making sure that the code we introduce to DXC is a little nicer than what we had internally. |
Updated Signed to Hashed. For other issues, https://github.com/microsoft/DirectXShaderCompiler/blob/main/tools/clang/tools/dxcompiler/dxcvalidator.cpp need to be updated as well. Will do the job when work on Build the DXIL validator library both as a dynamic and static library where these 2 validators could be merged into one. |
Can you help me understand the benefits of doing this later rather than now in this initial PR? I assume that this change comes in with enough testing that we can make NFC refactors to the code without worrying about breaking it, and given that a bar for code style/quality has been set with SM6.8 work it isn't obvious to me why we'd change that for this change. |
The code in |
Oh, I didn't realize that this change was essentially adding a whole load of duplicate code. I think we should figure out how to deduplicate this before completing the PR, otherwise we're just adding more technical debt to the project. |
Enable dxildll.rc.
20378d5
to
31c754c
Compare
|
||
static void HashAndUpdateOrCopy(uint32_t Flags, IDxcBlob *Shader, | ||
IDxcBlob **Hashed) { | ||
if (Flags & DxcValidatorFlags_InPlaceEdit) { |
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.
If we were to add a flag to skip hashing and container modification called DxcValidatorFlags_SkipHash
, we could implement it like so:
if (Flags & DxcValidatorFlags_InPlaceEdit) { | |
if (Flags & DxcValidatorFlags_SkipHash) { | |
*Hashed = Shader; | |
Shader->AddRef(); | |
} else if (Flags & DxcValidatorFlags_InPlaceEdit) { |
// Possible gotcha: the blob allocated here is tied to this .dll, so the | ||
// DLL shouldn't be unloaded before the blob is released. |
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.
That's generally how returned blobs work in the DXC APIs. Do we need to point this out as a comment here? It probably belongs in the API documentation, and potentially as a comment on the API definition.
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.
Removed.
@@ -64,7 +64,7 @@ HRESULT STDMETHODCALLTYPE DxcValidator::Validate( | |||
IDxcOperationResult * | |||
*ppResult // Validation output status, buffer, and errors | |||
) { | |||
return hlsl::validate(pShader, Flags, ppResult); | |||
return hlsl::validate(pShader, Flags, true, ppResult); |
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 should not be true, and I don't think we should have this implementation of IDxcValidator in dxrfallbackcompiler in the first place.
@@ -155,24 +222,16 @@ runRootSignatureValidation(IDxcBlob *Shader, | |||
uint32_t hlsl::validate( | |||
IDxcBlob *Shader, // Shader to validate. | |||
uint32_t Flags, // Validation flags. | |||
bool IsInternalValidator, // Run internal validator. |
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.
I don't think we should need this flag, ultimately. But that will require a cleanup of how we do internal validation.
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.
In fact, it appears that the only way this flag is used is to ignore DxcValidatorFlags_ModuleOnly
if it's not set. I don't think this is right. See my comment on the use of this flag in hlsl::validateWithDebug
.
static uint32_t runValidation( | ||
IDxcBlob *Shader, | ||
uint32_t Flags, // Validation flags. | ||
llvm::Module *Module, // Module to validate, if available. | ||
llvm::Module *DebugModule, // Debug module to validate, if available | ||
AbstractMemoryStream *DiagMemStream) { | ||
AbstractMemoryStream *DiagMemStream, IDxcBlob **Hashed) { |
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 Hashed
output pointer is not written to in this function, nor does it compute the hash.
This function is for the internal case, which I think needs an overhaul, especially now that we are integrating the hash here.
It's likely best if we did the overhaul as a separate change before integrating the hash changes. It should greatly simplify the scenarios.
We should get rid of the special internal validator case where it accepts the main module as a llvm::Module
and always validate the serialized bitcode in the container. We will want to keep the debug module argument, so it may be passed along internally, avoiding extra deserialization, since it's only used for diagnostic locations, and not the thing being validated.
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.
Ok, so this is really meant to be the inner function used by both code paths that have debug bitcode and the internal path that has a debug module. We should probably use this in the other runValidation
overload, and in the case of DxcValidatorFlags_ModuleOnly
use a different function entirely to call this one which deserialized the debug module and does not have a Hashed
output at all.
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.
Removed.
if (Flags & DxcValidatorFlags_RootSignatureOnly) | ||
ValidationStatus = | ||
runRootSignatureValidation(Shader, DiagMemStream, Flags, &HashedBlob); | ||
else if ((Flags & DxcValidatorFlags_ModuleOnly) && IsInternalValidator) |
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.
DxcValidatorFlags_ModuleOnly
should allow validation of raw bitcode, and disable hashing. IsInternalValidator
should not be required, and I don't think this code handles this case properly.
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.
Current dxil.dll doesn't support DxcValidatorFlags_ModuleOnly, just return DXC_E_CONTAINER_INVALID.
Shall we change that in this PR?
&DiagContext, true); | ||
std::unique_ptr<llvm::Module> DebugModule; | ||
if (OptDebugBitcode) { | ||
hr = ValidateLoadModule((const char *)OptDebugBitcode->Ptr, |
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.
Why has this been removed? We should be passing the loaded debug module through to runValidation, right?
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.
Nevermind, it's just missing from the DxcValidatorFlags_ModuleOnly
case, I'll make a separate comment.
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.
Ok, I think this original structure should be restored so that a debug module may be passed down to a validateWithOptModules
function that will apply the hash when applicable.
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.
Recovered debug module.
ValidationStatus = | ||
runRootSignatureValidation(Shader, DiagMemStream, Flags, &HashedBlob); | ||
else if ((Flags & DxcValidatorFlags_ModuleOnly) && IsInternalValidator) | ||
ValidationStatus = runValidation(Shader, Flags, nullptr, nullptr, |
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 should be passing the OptDebugBitcode
along, though that will require deserialization in this overloaded runValidation
path.
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.
Fixed.
static uint32_t | ||
runRootSignatureValidation(IDxcBlob *Shader, | ||
AbstractMemoryStream *DiagMemStream) { | ||
static uint32_t runValidation(IDxcBlob *Shader, |
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.
I think it would be better if this was combined with the other overload, and the combined function handled whether DxcValidatorFlags_ModuleOnly
was being performed, or if we have a full container to sign. Right now it's confusing, and an internal path with a debug module can't go through the signing path.
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 can be accomplished by moving debug module serialization out, but it will also require a change to ValidateDxilContainer
to take the llvm::Module*
instead of the serialized bitcode.
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.
Hmm... perhaps this isn't sufficient, since it might need to load the debug module from the container instead. So maybe we just need to add a debug llvm::Module
argument to pass along if we already have one.
This pull request introduces the open-source implementation of dxil.dll, including hashing and validation functionalities for DXIL containers.
DxilHash.cpp: Implements DXBC/DXIL container hashing functions.
dxcvalidatorp.cpp: Implements the DirectX Validator object, including signing support.
dxildll.cpp: Implements the DxcCreateInstance and DllMain functions for the dxil.dll module.
DxcSigningContainerBuilder.cpp: Implements the Dxil Container Builder.
This is first part for #6769