diff --git a/lib/DxilDia/DxilDiaSymbolManager.cpp b/lib/DxilDia/DxilDiaSymbolManager.cpp index abe757d0cb..3efced6ffd 100644 --- a/lib/DxilDia/DxilDiaSymbolManager.cpp +++ b/lib/DxilDia/DxilDiaSymbolManager.cpp @@ -607,6 +607,7 @@ class SymbolManagerInit { void Embed(const TypeInfo &TI); void AddBasicType(llvm::DIBasicType *BT); + void AppendSize(uint64_t baseSize); private: DWORD m_dwTypeID; @@ -1151,6 +1152,12 @@ void dxil_dia::hlsl_symbols::SymbolManagerInit::TypeInfo::Embed(const TypeInfo & m_dwCurrentSizeInBytes += TI.m_dwCurrentSizeInBytes; } +void dxil_dia::hlsl_symbols::SymbolManagerInit::TypeInfo::AppendSize( + uint64_t baseSize) { + static constexpr DWORD kNumBitsPerByte = 8; + m_dwCurrentSizeInBytes += baseSize / kNumBitsPerByte; +} + void dxil_dia::hlsl_symbols::SymbolManagerInit::TypeInfo::AddBasicType(llvm::DIBasicType *BT) { m_Layout.emplace_back(BT); @@ -1439,6 +1446,33 @@ HRESULT dxil_dia::hlsl_symbols::SymbolManagerInit::CreateBasicType(DWORD dwParen return S_OK; } +static uint64_t getBaseClassSize(llvm::DIType * Ty) +{ + uint64_t sizeInBits = Ty->getSizeInBits(); + auto *DerivedTy = llvm::dyn_cast(Ty); + if (DerivedTy != nullptr) { + // Working around a bug where byte size is stored instead of bit size + if (sizeInBits == 4 && Ty->getSizeInBits() == 32) { + sizeInBits = 32; + } + if (sizeInBits == 0) { + const llvm::DITypeIdentifierMap EmptyMap; + switch (DerivedTy->getTag()) { + case llvm::dwarf::DW_TAG_restrict_type: + case llvm::dwarf::DW_TAG_reference_type: + case llvm::dwarf::DW_TAG_const_type: + case llvm::dwarf::DW_TAG_typedef: { + llvm::DIType *baseType = DerivedTy->getBaseType().resolve(EmptyMap); + if (baseType != nullptr) { + return getBaseClassSize(baseType); + } + } + } + } + } + return sizeInBits; +} + HRESULT dxil_dia::hlsl_symbols::SymbolManagerInit::CreateCompositeType(DWORD dwParentID, llvm::DICompositeType *CT, DWORD *pNewTypeID) { switch (CT->getTag()) { case llvm::dwarf::DW_TAG_array_type: { @@ -1529,13 +1563,27 @@ HRESULT dxil_dia::hlsl_symbols::SymbolManagerInit::CreateCompositeType(DWORD dwP TypeInfo *udtTI; IFR(GetTypeInfo(CT, &udtTI)); auto udtScope = BeginUDTScope(udtTI); - for (llvm::DINode *N : CT->getElements()) { - if (auto *Field = llvm::dyn_cast(N)) { - DWORD dwUnusedFieldID; - IFR(CreateType(Field, &dwUnusedFieldID)); + if (CT->getElements().size() == 0) { + // "Resources" (textures, samplers, etc.) are composite types without any elements, + // but they do have a size. + udtTI->AppendSize(CT->getSizeInBits()); + } else { + for (llvm::DINode *N : CT->getElements()) { + if (auto *Field = llvm::dyn_cast(N)) { + DWORD dwUnusedFieldID; + IFR(CreateType(Field, &dwUnusedFieldID)); + if (Field->getTag() == llvm::dwarf::DW_TAG_inheritance) { + // The base class is a type of its own, so will have contributed to + // its own TypeInfo. But we still need to remember the size that it + // contributed to this type: + auto *DerivedType = llvm::cast(Field); + const llvm::DITypeIdentifierMap EmptyMap; + llvm::DIType *BaseType = DerivedType->getBaseType().resolve(EmptyMap); + udtTI->AppendSize(getBaseClassSize(BaseType)); + } + } } } - return S_OK; } diff --git a/lib/DxilPIXPasses/DxilDbgValueToDbgDeclare.cpp b/lib/DxilPIXPasses/DxilDbgValueToDbgDeclare.cpp index 34a56b72c5..0db0ee9307 100644 --- a/lib/DxilPIXPasses/DxilDbgValueToDbgDeclare.cpp +++ b/lib/DxilPIXPasses/DxilDbgValueToDbgDeclare.cpp @@ -365,7 +365,8 @@ static OffsetInBits SplitValue( else { assert(VTy->isFloatTy() || VTy->isDoubleTy() || VTy->isHalfTy() || - VTy->isIntegerTy(32) || VTy->isIntegerTy(64) || VTy->isIntegerTy(16)); + VTy->isIntegerTy(32) || VTy->isIntegerTy(64) || VTy->isIntegerTy(16) || + VTy->isPointerTy()); Values->emplace_back(ValueAndOffset{V, CurrentOffset}); CurrentOffset += VTy->getScalarSizeInBits(); } diff --git a/tools/clang/unittests/HLSL/PixTest.cpp b/tools/clang/unittests/HLSL/PixTest.cpp index b633c400dc..a4db865d40 100644 --- a/tools/clang/unittests/HLSL/PixTest.cpp +++ b/tools/clang/unittests/HLSL/PixTest.cpp @@ -222,7 +222,12 @@ class PixTest { TEST_METHOD(PixStructAnnotation_ResourceAsMember) TEST_METHOD(PixStructAnnotation_WheresMyDbgValue) - TEST_METHOD(VirtualRegisters_InstructionCounts) + TEST_METHOD(PixTypeManager_InheritancePointerStruct) + TEST_METHOD(PixTypeManager_InheritancePointerTypedef) + TEST_METHOD(PixTypeManager_MatricesInBase) + TEST_METHOD(PixTypeManager_SamplersAndResources) + + TEST_METHOD(VirtualRegisters_InstructionCounts) TEST_METHOD(VirtualRegisters_AlignedOffsets) TEST_METHOD(RootSignatureUpgrade_SubObjects) @@ -1131,6 +1136,12 @@ static std::string ToString(std::wstring from) std::string RunDxilPIXAddTidToAmplificationShaderPayloadPass(IDxcBlob * blob); CComPtr RunDxilPIXMeshShaderOutputPass(IDxcBlob* blob); + void CompileAndRunAnnotationAndGetDebugPart( + dxc::DxcDllSupport &dllSupport, const char *source, wchar_t *profile, + IDxcBlob **ppDebugPart); + void CompileAndRunAnnotationAndLoadDiaSource(dxc::DxcDllSupport &dllSupport, + const char *source, wchar_t *profile, + IDiaDataSource **ppDataSource); }; @@ -1790,6 +1801,292 @@ TEST_F(PixTest, PixDebugCompileInfo) { VERIFY_ARE_EQUAL(std::wstring(profile), std::wstring(hlslTarget)); } +static void CompileAndLogErrors(dxc::DxcDllSupport &dllSupport, LPCSTR pText, + LPWSTR pTargetProfile, std::vector &args, + _Outptr_ IDxcBlob **ppResult) { + CComPtr pCompiler; + CComPtr pSource; + CComPtr pResult; + HRESULT hrCompile; + *ppResult = nullptr; + VERIFY_SUCCEEDED(dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler)); + Utf8ToBlob(dllSupport, pText, &pSource); + VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main", + pTargetProfile, args.data(), args.size(), + nullptr, 0, nullptr, &pResult)); + + VERIFY_SUCCEEDED(pResult->GetStatus(&hrCompile)); + if (FAILED(hrCompile)) { + CComPtr textBlob; + VERIFY_SUCCEEDED(pResult->GetErrorBuffer(&textBlob)); + std::wstring text = BlobToWide(textBlob); + WEX::Logging::Log::Comment(text.c_str()); + } + VERIFY_SUCCEEDED(hrCompile); + VERIFY_SUCCEEDED(pResult->GetResult(ppResult)); +} +void PixTest::CompileAndRunAnnotationAndGetDebugPart( + dxc::DxcDllSupport &dllSupport, const char *source, wchar_t *profile, + IDxcBlob **ppDebugPart) { + CComPtr pContainer; + CComPtr pLib; + CComPtr pReflection; + UINT32 index; + std::vector args; + args.push_back(L"/Zi"); + args.push_back(L"/Qembed_debug"); + + CompileAndLogErrors(dllSupport, source, profile, args, &pContainer); + + auto annotated = RunAnnotationPasses(pContainer); + + CComPtr pNewContainer; + { + CComPtr pAssembler; + IFT(m_dllSupport.CreateInstance(CLSID_DxcAssembler, &pAssembler)); + + CComPtr pAssembleResult; + VERIFY_SUCCEEDED( + pAssembler->AssembleToContainer(annotated.blob, &pAssembleResult)); + + CComPtr pAssembleErrors; + VERIFY_SUCCEEDED(pAssembleResult->GetErrorBuffer(&pAssembleErrors)); + + if (pAssembleErrors && pAssembleErrors->GetBufferSize() != 0) { + OutputDebugStringA( + static_cast(pAssembleErrors->GetBufferPointer())); + VERIFY_SUCCEEDED(E_FAIL); + } + + VERIFY_SUCCEEDED(pAssembleResult->GetResult(&pNewContainer)); + } + + VERIFY_SUCCEEDED(dllSupport.CreateInstance(CLSID_DxcLibrary, &pLib)); + VERIFY_SUCCEEDED( + dllSupport.CreateInstance(CLSID_DxcContainerReflection, &pReflection)); + VERIFY_SUCCEEDED(pReflection->Load(pNewContainer)); + VERIFY_SUCCEEDED( + pReflection->FindFirstPartKind(hlsl::DFCC_ShaderDebugInfoDXIL, &index)); + VERIFY_SUCCEEDED(pReflection->GetPartContent(index, ppDebugPart)); +} + +void PixTest::CompileAndRunAnnotationAndLoadDiaSource( + dxc::DxcDllSupport &dllSupport, const char *source, wchar_t *profile, + IDiaDataSource **ppDataSource) { + CComPtr pDebugContent; + CComPtr pStream; + CComPtr pDiaSource; + CComPtr pLib; + VERIFY_SUCCEEDED(dllSupport.CreateInstance(CLSID_DxcLibrary, &pLib)); + + CompileAndRunAnnotationAndGetDebugPart(dllSupport, source, profile, + &pDebugContent); + VERIFY_SUCCEEDED(pLib->CreateStreamFromBlobReadOnly(pDebugContent, &pStream)); + VERIFY_SUCCEEDED( + dllSupport.CreateInstance(CLSID_DxcDiaDataSource, &pDiaSource)); + VERIFY_SUCCEEDED(pDiaSource->loadDataFromIStream(pStream)); + if (ppDataSource) { + *ppDataSource = pDiaSource.Detach(); + } +} + +TEST_F(PixTest, PixTypeManager_InheritancePointerStruct) { + if (m_ver.SkipDxilVersion(1, 5)) + return; + + const char *hlsl = R"( +struct Base +{ + float floatValue; +}; + +struct Derived : Base +{ + int intValue; +}; + +RaytracingAccelerationStructure Scene : register(t0, space0); + +[shader("raygeneration")] +void main() +{ + RayDesc ray; + ray.Origin = float3(0,0,0); + ray.Direction = float3(0,0,1); + // Set TMin to a non-zero small value to avoid aliasing issues due to floating - point errors. + // TMin should be kept small to prevent missing geometry at close contact areas. + ray.TMin = 0.001; + ray.TMax = 10000.0; + Derived payload; + payload.floatValue = 1; + payload.intValue = 2; + TraceRay(Scene, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, ~0, 0, 1, 0, ray, payload);} + +)"; + + CComPtr pDiaDataSource; + CComPtr pDiaSession; + CompileAndRunAnnotationAndLoadDiaSource(m_dllSupport, hlsl, L"lib_6_6", + &pDiaDataSource); + + VERIFY_SUCCEEDED(pDiaDataSource->openSession(&pDiaSession)); +} + +TEST_F(PixTest, PixTypeManager_InheritancePointerTypedef) { + if (m_ver.SkipDxilVersion(1, 5)) + return; + + const char *hlsl = R"( +struct Base +{ + float floatValue; +}; +typedef Base BaseTypedef; + +struct Derived : BaseTypedef +{ + int intValue; +}; + +RaytracingAccelerationStructure Scene : register(t0, space0); + +[shader("raygeneration")] +void main() +{ + RayDesc ray; + ray.Origin = float3(0,0,0); + ray.Direction = float3(0,0,1); + // Set TMin to a non-zero small value to avoid aliasing issues due to floating - point errors. + // TMin should be kept small to prevent missing geometry at close contact areas. + ray.TMin = 0.001; + ray.TMax = 10000.0; + Derived payload; + payload.floatValue = 1; + payload.intValue = 2; + TraceRay(Scene, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, ~0, 0, 1, 0, ray, payload);} + +)"; + + CComPtr pDiaDataSource; + CComPtr pDiaSession; + CompileAndRunAnnotationAndLoadDiaSource(m_dllSupport, hlsl, L"lib_6_6", + &pDiaDataSource); + + VERIFY_SUCCEEDED(pDiaDataSource->openSession(&pDiaSession)); +} + +TEST_F(PixTest, PixTypeManager_MatricesInBase) { + if (m_ver.SkipDxilVersion(1, 5)) + return; + + const char *hlsl = R"( +struct Base +{ + float4x4 mat; +}; +typedef Base BaseTypedef; + +struct Derived : BaseTypedef +{ + int intValue; +}; + +RaytracingAccelerationStructure Scene : register(t0, space0); + +[shader("raygeneration")] +void main() +{ + RayDesc ray; + ray.Origin = float3(0,0,0); + ray.Direction = float3(0,0,1); + // Set TMin to a non-zero small value to avoid aliasing issues due to floating - point errors. + // TMin should be kept small to prevent missing geometry at close contact areas. + ray.TMin = 0.001; + ray.TMax = 10000.0; + Derived payload; + payload.mat[0][0] = 1; + payload.intValue = 2; + TraceRay(Scene, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, ~0, 0, 1, 0, ray, payload);} + +)"; + + CComPtr pDiaDataSource; + CComPtr pDiaSession; + CompileAndRunAnnotationAndLoadDiaSource(m_dllSupport, hlsl, L"lib_6_6", + &pDiaDataSource); + + VERIFY_SUCCEEDED(pDiaDataSource->openSession(&pDiaSession)); +} + +TEST_F(PixTest, PixTypeManager_SamplersAndResources) { + if (m_ver.SkipDxilVersion(1, 5)) + return; + + const char *hlsl = R"( + +static const SamplerState SamplerRef = SamplerDescriptorHeap[1]; + +Texture3D Tex3DTemplated ; +Texture3D Tex3d ; +Texture2D Tex2D ; +Texture2D Tex2DTemplated ; +StructuredBuffer StructBuf ; +Texture2DArray Tex2DArray ; +Buffer Buff ; + +static const struct +{ + float AFloat; + SamplerState Samp1; + Texture3D Tex1; + Texture3D Tex2; + Texture2D Tex3; + Texture2D Tex4; + StructuredBuffer Buff1; + Texture2DArray Tex5; + Buffer Buff2; + float AnotherFloat; +} View = { +1, +SamplerRef, +Tex3DTemplated, +Tex3d, +Tex2D, +Tex2DTemplated, +StructBuf, +Tex2DArray, +Buff, +2 +}; + +struct Payload +{ + int intValue; +}; + +RaytracingAccelerationStructure Scene : register(t0, space0); + +[shader("raygeneration")] +void main() +{ + RayDesc ray; + ray.Origin = float3(0,0,0); + ray.Direction = float3(0,0,1); + ray.TMin = 0.001; + ray.TMax = 10000.0; + Payload payload; + payload.intValue = View.AFloat; + TraceRay(Scene, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, ~0, 0, 1, 0, ray, payload);} +)"; + + CComPtr pDiaDataSource; + CComPtr pDiaSession; + CompileAndRunAnnotationAndLoadDiaSource(m_dllSupport, hlsl, L"lib_6_6", + &pDiaDataSource); + + VERIFY_SUCCEEDED(pDiaDataSource->openSession(&pDiaSession)); +} + CComPtr PixTest::RunShaderAccessTrackingPass(IDxcBlob *blob) { CComPtr pOptimizer; VERIFY_SUCCEEDED( @@ -3217,13 +3514,6 @@ TEST_F(PixTest, PixStructAnnotation_Inheritance) { for (auto choice : OptimizationChoices) { auto optimization = choice.Flag; - auto IsOptimized = choice.IsOptimized; - - // don't run -Od test until -Od inheritance is fixed (#3274: - // https://github.com/microsoft/DirectXShaderCompiler/issues/3274) - if (!IsOptimized) - continue; - const char* hlsl = R"( struct Base