Skip to content

Commit 99726f9

Browse files
[Error Handling] Fix DxcContainerBuilder error handling (microsoft#7056)
Some error handling changes were incorrectly made to the container assembler, as described in the issue below. This is bad because the API protocol for error handling must remain consistent across all functions. This PR aims to restore the correct semantic meaning of returning bad HR values. Fixes microsoft#7051 --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent ef1472a commit 99726f9

File tree

3 files changed

+65
-16
lines changed

3 files changed

+65
-16
lines changed

lib/DxilContainer/DxcContainerBuilder.cpp

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,11 @@ HRESULT STDMETHODCALLTYPE DxcContainerBuilder::RemovePart(UINT32 fourCC) {
104104

105105
HRESULT STDMETHODCALLTYPE
106106
DxcContainerBuilder::SerializeContainer(IDxcOperationResult **ppResult) {
107+
if (ppResult == nullptr)
108+
return E_INVALIDARG;
109+
107110
DxcThreadMalloc TM(m_pMalloc);
111+
108112
try {
109113
// Allocate memory for new dxil container.
110114
uint32_t ContainerSize = ComputeContainerSize();
@@ -161,6 +165,11 @@ DxcContainerBuilder::SerializeContainer(IDxcOperationResult **ppResult) {
161165
errorHeap.Detach();
162166
}
163167

168+
// Add Hash.
169+
if (SUCCEEDED(valHR))
170+
HashAndUpdate(IsDxilContainerLike(pResult->GetBufferPointer(),
171+
pResult->GetBufferSize()));
172+
164173
IFT(DxcResult::Create(
165174
valHR, DXC_OUT_OBJECT,
166175
{DxcOutputObject::DataOutput(DXC_OUT_OBJECT, pResult, DxcOutNoName),
@@ -169,21 +178,6 @@ DxcContainerBuilder::SerializeContainer(IDxcOperationResult **ppResult) {
169178
}
170179
CATCH_CPP_RETURN_HRESULT();
171180

172-
if (ppResult == nullptr || *ppResult == nullptr)
173-
return S_OK;
174-
175-
HRESULT HR;
176-
(*ppResult)->GetStatus(&HR);
177-
if (FAILED(HR))
178-
return HR;
179-
180-
CComPtr<IDxcBlob> pObject;
181-
IFR((*ppResult)->GetResult(&pObject));
182-
183-
// Add Hash.
184-
LPVOID PTR = pObject->GetBufferPointer();
185-
if (IsDxilContainerLike(PTR, pObject->GetBufferSize()))
186-
HashAndUpdate((DxilContainerHeader *)PTR);
187181
return S_OK;
188182
}
189183

tools/clang/tools/dxclib/dxc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,7 @@ int DxcContext::VerifyRootSignature() {
644644
IFT(pContainerBuilder->AddPart(hlsl::DxilFourCC::DFCC_RootSignature,
645645
pRootSignature));
646646
CComPtr<IDxcOperationResult> pOperationResult;
647-
pContainerBuilder->SerializeContainer(&pOperationResult);
647+
IFT(pContainerBuilder->SerializeContainer(&pOperationResult));
648648
HRESULT status = E_FAIL;
649649
CComPtr<IDxcBlob> pResult;
650650
IFT(pOperationResult->GetStatus(&status));

tools/clang/unittests/HLSL/ValidationTest.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ class ValidationTest : public ::testing::Test {
206206
TEST_METHOD(SimpleGs1Fail)
207207
TEST_METHOD(UavBarrierFail)
208208
TEST_METHOD(UndefValueFail)
209+
TEST_METHOD(ValidationFailNoHash)
209210
TEST_METHOD(UpdateCounterFail)
210211
TEST_METHOD(LocalResCopy)
211212
TEST_METHOD(ResCounter)
@@ -1189,6 +1190,60 @@ TEST_F(ValidationTest, UavBarrierFail) {
11891190
TEST_F(ValidationTest, UndefValueFail) {
11901191
TestCheck(L"..\\CodeGenHLSL\\UndefValue.hlsl");
11911192
}
1193+
// verify that containers that are not valid DXIL do not
1194+
// get assigned a hash.
1195+
TEST_F(ValidationTest, ValidationFailNoHash) {
1196+
if (m_ver.SkipDxilVersion(1, 8))
1197+
return;
1198+
CComPtr<IDxcBlob> pProgram;
1199+
1200+
// We need any shader that will pass compilation but fail validation.
1201+
// This shader reads from uninitialized 'float a', which works for now.
1202+
LPCSTR pSource = R"(
1203+
float main(snorm float b : B) : SV_DEPTH
1204+
{
1205+
float a;
1206+
return b + a;
1207+
}
1208+
)";
1209+
1210+
CComPtr<IDxcBlobEncoding> pSourceBlob;
1211+
Utf8ToBlob(m_dllSupport, pSource, &pSourceBlob);
1212+
std::vector<LPCWSTR> pArguments = {L"-Vd"};
1213+
LPCSTR pShaderModel = "ps_6_0";
1214+
bool result = CompileSource(pSourceBlob, pShaderModel, pArguments.data(), 1,
1215+
nullptr, 0, &pProgram);
1216+
1217+
VERIFY_IS_TRUE(result);
1218+
1219+
CComPtr<IDxcValidator> pValidator;
1220+
CComPtr<IDxcOperationResult> pResult;
1221+
unsigned Flags = 0;
1222+
VERIFY_SUCCEEDED(
1223+
m_dllSupport.CreateInstance(CLSID_DxcValidator, &pValidator));
1224+
1225+
VERIFY_SUCCEEDED(pValidator->Validate(pProgram, Flags, &pResult));
1226+
HRESULT status;
1227+
VERIFY_IS_NOT_NULL(pResult);
1228+
CComPtr<IDxcBlob> pValidationOutput;
1229+
pResult->GetStatus(&status);
1230+
1231+
// expect validation to fail
1232+
VERIFY_FAILED(status);
1233+
pResult->GetResult(&pValidationOutput);
1234+
// Make sure the validation output is not null even when validation fails
1235+
VERIFY_SUCCEEDED(pValidationOutput != nullptr);
1236+
1237+
hlsl::DxilContainerHeader *pHeader = IsDxilContainerLike(
1238+
pProgram->GetBufferPointer(), pProgram->GetBufferSize());
1239+
VERIFY_IS_NOT_NULL(pHeader);
1240+
1241+
BYTE ZeroHash[DxilContainerHashSize] = {0, 0, 0, 0, 0, 0, 0, 0,
1242+
0, 0, 0, 0, 0, 0, 0, 0};
1243+
1244+
// Should be equal, this proves the hash isn't written when validation fails
1245+
VERIFY_ARE_EQUAL(memcmp(ZeroHash, pHeader->Hash.Digest, sizeof(ZeroHash)), 0);
1246+
}
11921247
TEST_F(ValidationTest, UpdateCounterFail) {
11931248
if (m_ver.SkipIRSensitiveTest())
11941249
return;

0 commit comments

Comments
 (0)