Skip to content

Commit bae2325

Browse files
authored
Pix: Fix crash getting type name of unnamed structs (microsoft#5658)
...and other types while I'm at it. There are tests for all of the possible unnamed types (structs, members, arrays). Don't think I can express an unnamed scalar or typededf so there's no test for those. (This was hit in the wild while debugging a pixel shader in a WinPIX capture of a Large Well-Known Engine.)
1 parent 72c3384 commit bae2325

File tree

2 files changed

+175
-6
lines changed

2 files changed

+175
-6
lines changed

lib/DxilDia/DxcPixTypes.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@
1414
#include "DxcPixTypes.h"
1515
#include "DxilDiaSession.h"
1616

17+
static CA2W GetTypeNameOrDefault(llvm::DIType *diType) {
18+
auto stringRef = diType->getName();
19+
if (stringRef.empty())
20+
return CA2W("<unnamed>");
21+
return CA2W(stringRef.data());
22+
}
23+
1724
HRESULT dxil_debug_info::CreateDxcPixType(
1825
DxcPixDxilDebugInfo *pDxilDebugInfo,
1926
llvm::DIType *diType,
@@ -89,7 +96,9 @@ STDMETHODIMP dxil_debug_info::DxcPixConstType::GetName(
8996
CComBSTR BaseName;
9097
IFR(BaseType->GetName(&BaseName));
9198

92-
*Name = CComBSTR((L"const " + std::wstring(BaseName)).c_str()).Detach();
99+
*Name =
100+
CComBSTR((L"const " + std::wstring(BaseName)).c_str())
101+
.Detach();
93102
return S_OK;
94103
}
95104

@@ -111,7 +120,8 @@ STDMETHODIMP dxil_debug_info::DxcPixConstType::UnAlias(
111120
STDMETHODIMP dxil_debug_info::DxcPixTypedefType::GetName(
112121
_Outptr_result_z_ BSTR *Name)
113122
{
114-
*Name = CComBSTR(CA2W(m_pType->getName().data())).Detach();
123+
*Name =
124+
CComBSTR(GetTypeNameOrDefault(m_pType)).Detach();
115125
return S_OK;
116126
}
117127

@@ -133,7 +143,8 @@ STDMETHODIMP dxil_debug_info::DxcPixTypedefType::UnAlias(
133143
STDMETHODIMP dxil_debug_info::DxcPixScalarType::GetName(
134144
_Outptr_result_z_ BSTR *Name)
135145
{
136-
*Name = CComBSTR(CA2W(m_pType->getName().data())).Detach();
146+
*Name =
147+
CComBSTR(GetTypeNameOrDefault(m_pType)).Detach();
137148
return S_OK;
138149
}
139150

@@ -155,7 +166,7 @@ STDMETHODIMP dxil_debug_info::DxcPixScalarType::UnAlias(
155166
STDMETHODIMP dxil_debug_info::DxcPixArrayType::GetName(
156167
_Outptr_result_z_ BSTR *Name)
157168
{
158-
CComBSTR name(CA2W(m_pBaseType->getName().data()));
169+
CComBSTR name(GetTypeNameOrDefault(m_pBaseType));
159170
name.Append(L"[]");
160171
*Name = name.Detach();
161172
return S_OK;
@@ -225,7 +236,8 @@ STDMETHODIMP dxil_debug_info::DxcPixArrayType::GetElementType(
225236
STDMETHODIMP dxil_debug_info::DxcPixStructType::GetName(
226237
_Outptr_result_z_ BSTR *Name)
227238
{
228-
*Name = CComBSTR(CA2W(m_pStruct->getName().data())).Detach();
239+
*Name =
240+
CComBSTR(GetTypeNameOrDefault(m_pStruct)).Detach();
229241
return S_OK;
230242
}
231243

@@ -357,7 +369,8 @@ STDMETHODIMP dxil_debug_info::DxcPixStructType::GetBaseType(
357369
STDMETHODIMP dxil_debug_info::DxcPixStructField::GetName(
358370
_Outptr_result_z_ BSTR *Name)
359371
{
360-
*Name = CComBSTR(CA2W(m_pField->getName().data())).Detach();
372+
*Name =
373+
CComBSTR(GetTypeNameOrDefault(m_pField)).Detach();
361374
return S_OK;
362375
}
363376

tools/clang/unittests/HLSL/PixTest.cpp

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,10 @@ class PixTest {
237237
TEST_METHOD(DxcPixDxilDebugInfo_StructContainedResource)
238238
TEST_METHOD(DxcPixDxilDebugInfo_StructStaticInit)
239239
TEST_METHOD(DxcPixDxilDebugInfo_StructMemberFnFirst)
240+
TEST_METHOD(DxcPixDxilDebugInfo_UnnamedConstStruct)
241+
TEST_METHOD(DxcPixDxilDebugInfo_UnnamedStruct)
242+
TEST_METHOD(DxcPixDxilDebugInfo_UnnamedArray)
243+
TEST_METHOD(DxcPixDxilDebugInfo_UnnamedField)
240244

241245
TEST_METHOD(VirtualRegisters_InstructionCounts)
242246
TEST_METHOD(VirtualRegisters_AlignedOffsets)
@@ -250,6 +254,9 @@ class PixTest {
250254
dxc::DxcDllSupport m_dllSupport;
251255
VersionSupportInfo m_ver;
252256

257+
void PixTest::TestUnnamedTypeCase(const char *hlsl,
258+
const wchar_t *expectedTypeName);
259+
253260
void CreateBlobPinned(_In_bytecount_(size) LPCVOID data, SIZE_T size,
254261
UINT32 codePage, _Outptr_ IDxcBlobEncoding **ppBlob) {
255262
CComPtr<IDxcLibrary> library;
@@ -3048,6 +3055,155 @@ void main()
30483055
VERIFY_IS_TRUE(FoundTheStruct);
30493056
}
30503057

3058+
void PixTest::TestUnnamedTypeCase(const char* hlsl, const wchar_t* expectedTypeName) {
3059+
if (m_ver.SkipDxilVersion(1, 2))
3060+
return;
3061+
auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, L"cs_6_0");
3062+
auto liveVariables =
3063+
GetLiveVariablesAt(hlsl, "InterestingLine", dxilDebugger);
3064+
DWORD count;
3065+
VERIFY_SUCCEEDED(liveVariables->GetCount(&count));
3066+
bool FoundTheVariable = false;
3067+
for (DWORD i = 0; i < count; ++i) {
3068+
CComPtr<IDxcPixVariable> variable;
3069+
VERIFY_SUCCEEDED(liveVariables->GetVariableByIndex(i, &variable));
3070+
CComBSTR name;
3071+
variable->GetName(&name);
3072+
if (0 == wcscmp(name, L"glbl")) {
3073+
FoundTheVariable = true;
3074+
CComPtr<IDxcPixType> type;
3075+
VERIFY_SUCCEEDED(variable->GetType(&type));
3076+
CComBSTR typeName;
3077+
VERIFY_SUCCEEDED(type->GetName(&typeName));
3078+
VERIFY_ARE_EQUAL(typeName, expectedTypeName);
3079+
break;
3080+
}
3081+
}
3082+
VERIFY_IS_TRUE(FoundTheVariable);
3083+
}
3084+
3085+
TEST_F(PixTest, DxcPixDxilDebugInfo_UnnamedConstStruct) {
3086+
const char *hlsl = R"(
3087+
RWStructuredBuffer<float> floatRWUAV: register(u0);
3088+
3089+
[numthreads(1, 1, 1)]
3090+
void main()
3091+
{
3092+
const struct
3093+
{
3094+
float fg;
3095+
RWStructuredBuffer<float> buf;
3096+
} glbl = {42.f, floatRWUAV};
3097+
3098+
float f = glbl.fg + glbl.buf[1]; // InterestingLine
3099+
floatRWUAV[0] = f;
3100+
}
3101+
3102+
)";
3103+
3104+
TestUnnamedTypeCase(hlsl, L"const <unnamed>");
3105+
}
3106+
3107+
TEST_F(PixTest, DxcPixDxilDebugInfo_UnnamedStruct) {
3108+
const char *hlsl = R"(
3109+
RWStructuredBuffer<float> floatRWUAV: register(u0);
3110+
3111+
[numthreads(1, 1, 1)]
3112+
void main()
3113+
{
3114+
struct
3115+
{
3116+
float fg;
3117+
RWStructuredBuffer<float> buf;
3118+
} glbl = {42.f, floatRWUAV};
3119+
glbl.fg = 41.f;
3120+
float f = glbl.fg + glbl.buf[1]; // InterestingLine
3121+
floatRWUAV[0] = f;
3122+
}
3123+
3124+
)";
3125+
3126+
TestUnnamedTypeCase(hlsl, L"<unnamed>");
3127+
}
3128+
3129+
TEST_F(PixTest, DxcPixDxilDebugInfo_UnnamedArray) {
3130+
const char *hlsl = R"(
3131+
RWStructuredBuffer<float> floatRWUAV: register(u0);
3132+
3133+
[numthreads(1, 1, 1)]
3134+
void main()
3135+
{
3136+
struct
3137+
{
3138+
float fg;
3139+
RWStructuredBuffer<float> buf;
3140+
} glbl[2] = {{42.f, floatRWUAV},{43.f, floatRWUAV}};
3141+
float f = glbl[0].fg + glbl[1].buf[1]; // InterestingLine
3142+
floatRWUAV[0] = f;
3143+
}
3144+
3145+
)";
3146+
3147+
TestUnnamedTypeCase(hlsl, L"<unnamed>[]");
3148+
}
3149+
3150+
TEST_F(PixTest, DxcPixDxilDebugInfo_UnnamedField) {
3151+
const char *hlsl = R"(
3152+
RWStructuredBuffer<float> floatRWUAV: register(u0);
3153+
3154+
[numthreads(1, 1, 1)]
3155+
void main()
3156+
{
3157+
struct
3158+
{
3159+
struct {
3160+
float fg;
3161+
RWStructuredBuffer<float> buf;
3162+
} contained;
3163+
} glbl = { {42.f, floatRWUAV} };
3164+
float f = glbl.contained.fg + glbl.contained.buf[1]; // InterestingLine
3165+
floatRWUAV[0] = f;
3166+
}
3167+
3168+
)";
3169+
3170+
if (m_ver.SkipDxilVersion(1, 2))
3171+
return;
3172+
auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, L"cs_6_0");
3173+
auto liveVariables =
3174+
GetLiveVariablesAt(hlsl, "InterestingLine", dxilDebugger);
3175+
DWORD count;
3176+
VERIFY_SUCCEEDED(liveVariables->GetCount(&count));
3177+
bool FoundTheVariable = false;
3178+
for (DWORD i = 0; i < count; ++i) {
3179+
CComPtr<IDxcPixVariable> variable;
3180+
VERIFY_SUCCEEDED(liveVariables->GetVariableByIndex(i, &variable));
3181+
CComBSTR name;
3182+
variable->GetName(&name);
3183+
if (0 == wcscmp(name, L"glbl")) {
3184+
CComPtr<IDxcPixType> type;
3185+
VERIFY_SUCCEEDED(variable->GetType(&type));
3186+
CComPtr<IDxcPixStructType> structType;
3187+
VERIFY_SUCCEEDED(type->QueryInterface(IID_PPV_ARGS(&structType)));
3188+
DWORD fieldCount = 0;
3189+
VERIFY_SUCCEEDED(structType->GetNumFields(&fieldCount));
3190+
VERIFY_ARE_EQUAL(fieldCount, 1);
3191+
//Just a crash test:
3192+
CComPtr<IDxcPixStructField> structField;
3193+
structType->GetFieldByName(L"", & structField);
3194+
VERIFY_SUCCEEDED(structType->GetFieldByIndex(0, &structField));
3195+
FoundTheVariable = true;
3196+
CComPtr<IDxcPixType> fieldType;
3197+
VERIFY_SUCCEEDED(structField->GetType(&fieldType));
3198+
CComBSTR typeName;
3199+
VERIFY_SUCCEEDED(fieldType->GetName(&typeName));
3200+
VERIFY_ARE_EQUAL(typeName, L"<unnamed>");
3201+
break;
3202+
}
3203+
}
3204+
VERIFY_IS_TRUE(FoundTheVariable);
3205+
}
3206+
30513207
CComPtr<IDxcBlob> PixTest::RunShaderAccessTrackingPass(IDxcBlob *blob) {
30523208
CComPtr<IDxcOptimizer> pOptimizer;
30533209
VERIFY_SUCCEEDED(

0 commit comments

Comments
 (0)