Visual Studio图形调试器详细使用教程(基于DirectX11)
前言
對于DirectX程序開發(fā)者來說,學(xué)會使用Visual Studio Graphics Debugger(圖形調(diào)試器)可以幫助你全面了解渲染管線綁定的資源和運行狀態(tài),從而確認(rèn)問題所在。現(xiàn)在就以我所掌握的圖形調(diào)試經(jīng)驗來進行展開描述。
下面的教程基于Visual Studio 2017/2019 Community進行.因為最近換了VS2019,并且添加了調(diào)試對象具名化的功能,里面的圖片來不及做完整更換,但還是能看的。
這一篇需要消耗比較多的流量,沒連接WIFI或者網(wǎng)線的慎入。
同時推薦大家了解一下我的DirectX 11教程,講述了如何脫離DirectX SDK及Effects11,使用HLSL編譯器/D3DCompiler和Windows SDK來開發(fā)DirectX 11應(yīng)用程序:
DirectX11 With Windows SDK完整目錄
歡迎加入QQ群: 727623616 可以一起探討DX11,以及有什么問題也可以在這里匯報。
準(zhǔn)備工作
首先確定是否安裝了DirectX圖形調(diào)試器,需要在Visual Studio Installer中確定是否已經(jīng)勾選了該項內(nèi)容。
安裝好并進入項目,在調(diào)試之前需要將項目配置成Debug模式
然后觀察著色器的編譯選項,如果使用的是HLSL編譯器,則要重點關(guān)注Debug模式下所有著色器是否都禁用了優(yōu)化,并啟用了調(diào)試信息。
首先對其中的一個著色器右鍵-屬性
然后在Debug配置下,選擇HLSL編譯器-所有選項,禁用優(yōu)化并啟用調(diào)試信息
如果使用的是D3DCompiler,在代碼層(運行時)編譯著色器,則需要在Debug模式下給D3DComplieFromFile函數(shù)添加D3DCOMPILE_DEBUG和D3DCOMPILE_SKIP_OPTIMIZATION的Flag以開啟著色器調(diào)試并關(guān)閉優(yōu)化,否則在調(diào)試著色器的時候只能看到匯編代碼:
HRESULT CreateShaderFromFile(const WCHAR * csoFileNameInOut, const WCHAR * hlslFileName,LPCSTR entryPoint, LPCSTR shaderModel, ID3DBlob ** ppBlobOut) {HRESULT hr = S_OK;// 尋找是否有已經(jīng)編譯好的頂點著色器if (csoFileNameInOut && filesystem::exists(csoFileNameInOut)){return D3DReadFileToBlob(csoFileNameInOut, ppBlobOut);}else{DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS; #ifdef _DEBUG// 設(shè)置 D3DCOMPILE_DEBUG 標(biāo)志用于獲取著色器調(diào)試信息。該標(biāo)志可以提升調(diào)試體驗,// 但仍然允許著色器進行優(yōu)化操作dwShaderFlags |= D3DCOMPILE_DEBUG;// 在Debug環(huán)境下禁用優(yōu)化以避免出現(xiàn)一些不合理的情況dwShaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION; #endifID3DBlob* errorBlob = nullptr;hr = D3DCompileFromFile(hlslFileName, nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE, entryPoint, shaderModel,dwShaderFlags, 0, ppBlobOut, &errorBlob);if (FAILED(hr)){if (errorBlob != nullptr){OutputDebugStringA(reinterpret_cast<const char*>(errorBlob->GetBufferPointer()));}SAFE_RELEASE(errorBlob);return hr;}// 若指定了輸出文件名,則將著色器二進制信息輸出if (csoFileNameInOut){return D3DWriteBlobToFile(*ppBlobOut, csoFileNameInOut, FALSE);}}return hr; }截取一幀畫面
圖形調(diào)試器的調(diào)試通常是針對某一幀的畫面進行的。完成了上面的配置后,第一步我們需要打開圖形調(diào)試器去截取一幀認(rèn)為有問題的畫面來進行調(diào)試。
運行圖形調(diào)試之前請先確保沒有能夠?qū)е掠|發(fā)斷點異常的問題,如果有的話請先通過普通的調(diào)試器解決問題。畢竟圖形調(diào)試器是要解決圖形顯示異常,普通調(diào)試無法查出來的問題,而要對GPU進行調(diào)試。除此之外,還需要撤掉之前在圖形繪制階段的所有斷點。
有兩種方式打開圖形調(diào)試器,第一種是快捷鍵Alt+F5啟動,如果沒有反應(yīng),則可以通過第二種方式啟動并確認(rèn)快捷鍵。
第二種是VS界面選擇調(diào)試-圖形-啟動圖形調(diào)試。
在進入程序后,按下Print Screen(PrtSc)鍵截取一幀有問題的畫面,然后就可以看到紅色方框區(qū)域就是你剛截下的一幀畫面
實際上生成的是一個圖形日志文檔(.vsglog),我們需要通過他來進行圖形調(diào)試。
你可以在一次調(diào)試截取多幀畫面,但基本上目前我們只需要截取一幀畫面就可以退出程序了。關(guān)閉程序后,我們可以點擊藍(lán)色部分的字:幀XXXX 或者雙擊畫面來打開Visual Studio圖形分析器。
圖形調(diào)試器預(yù)覽
下面是圖形調(diào)試器的主界面
事件列表
事件列表展示了DirectX的一些接口類對象的重要調(diào)用。當(dāng)前查看的是GPU工作,可以觀察到D3D設(shè)備上下文關(guān)于繪制和內(nèi)部綁定的GPU數(shù)據(jù)更新的所有操作。若更改為時間線,則可以觀察更多有關(guān)D3D設(shè)備上下文的詳細(xì)調(diào)用操作,可以看到各個階段都有哪些資源被綁定,哪些狀態(tài)被改變,以及調(diào)用了繪制。
其中帶筆刷的調(diào)用說明這是一個繪制調(diào)用,可以點擊它觀察直到這個方法被調(diào)用后的繪制狀態(tài)。
為圖形調(diào)試器的對象添加自定義名稱
看到上面的幾張圖片,雖然我們可以推測出來對象: 2就是m_pd3dImmediateContext,但是也僅限少數(shù)的幾個固定對象名我們能直接推測出是什么對象。等對象一多,我們就難以判別管線所綁定的對象是否正確。因此我們可以在C++代碼來為對象指定名稱。
在d3dUtil.h中提供了兩個函數(shù),一個用于D3D設(shè)備創(chuàng)建出來的對象,一個用于DXGI對象。通過SetPrivateData方法,并使用WKPDID_D3DDebugObjectName的GUID使得我們可以為其設(shè)置圖形調(diào)試器下的名稱:
// ------------------------------ // D3D11SetDebugObjectName函數(shù) // ------------------------------ // 為D3D設(shè)備創(chuàng)建出來的對象在圖形調(diào)試器中設(shè)置對象名 // [In]ID3D11DeviceChild D3D11設(shè)備創(chuàng)建出的對象 // [In]name 對象名 template<UINT TNameLength> inline void D3D11SetDebugObjectName(_In_ ID3D11DeviceChild* resource, _In_ const char(&name)[TNameLength]) { #if (defined(DEBUG) || defined(_DEBUG)) && (GRAPHICS_DEBUGGER_OBJECT_NAME)resource->SetPrivateData(WKPDID_D3DDebugObjectName, TNameLength - 1, name); #elseUNREFERENCED_PARAMETER(resource);UNREFERENCED_PARAMETER(name); #endif }// ------------------------------ // DXGISetDebugObjectName函數(shù) // ------------------------------ // 為DXGI對象在圖形調(diào)試器中設(shè)置對象名 // [In]IDXGIObject DXGI對象 // [In]name 對象名 template<UINT TNameLength> inline void DXGISetDebugObjectName(_In_ IDXGIObject* resource, _In_ const char(&name)[TNameLength]) { #if (defined(DEBUG) || defined(_DEBUG)) && (GRAPHICS_DEBUGGER_OBJECT_NAME)resource->SetPrivateData(WKPDID_D3DDebugObjectName, TNameLength - 1, name); #elseUNREFERENCED_PARAMETER(resource);UNREFERENCED_PARAMETER(name); #endif }此外,GameObject類、Model類、TextureRender類、SkyRender類和DynamicSkyRender類都添加了SetDebugObjectName方法來為對象設(shè)置調(diào)試自定義名稱。
現(xiàn)在打開圖形調(diào)試器查看,類似效果如下:
對象具名化后可以十分方便地確認(rèn)自己有沒有正確綁定所需資源。
如果你不希望使用調(diào)試器對象具名化,可以在d3dUtil.h的開頭找到這樣的宏:
// 默認(rèn)開啟圖形調(diào)試器具名化 // 如果不需要該項功能,可通過全局文本替換將其值設(shè)置為0 #ifndef GRAPHICS_DEBUGGER_OBJECT_NAME #define GRAPHICS_DEBUGGER_OBJECT_NAME (1) #endif將其修改后只會剩下默認(rèn)的DDSTextureLoader和WICTextureLoader的對象具名化。
注意:在你的Release版本應(yīng)用程序應(yīng)該避免出現(xiàn)對調(diào)試對象名稱的設(shè)置。你可以將相關(guān)代碼移出項目。
查看傳入的緩沖區(qū)數(shù)據(jù)
我們可以在圖形調(diào)試器查看頂點緩沖區(qū),索引緩沖區(qū)和常量緩沖區(qū)。
在上面的事件列表中,我們可以看到很多藍(lán)色字體的對象,這些都可以點進去觀察。這里我們以某個繪制事件綁定的頂點緩沖區(qū)為例
我們可以觀察到緩沖區(qū)的字節(jié)數(shù)、使用情況、綁定標(biāo)簽、CPU訪問權(quán)限等。其中觀察到的數(shù)據(jù)取決于我們設(shè)置的格式。
圖形調(diào)試器支持觀察的基本類型如下:
| 有符號字節(jié)類型 | byte(sbyte) 2byte 4byte 8byte |
| 無符號字節(jié)類型 | ubyte u2byte u4byte u8byte |
| 十六進制字節(jié)類型 | xbyte x2byte x4byte x8byte |
| 有符號整型 | short int int64(long) |
| 無符號整型 | ushort uint uint64(ulong) |
| 十六進制整型 | xshort xint xint64(xlong) |
| 半精度浮點型 | half half2 half3 half4 |
| 單精度浮點型 | float float2 float3 float4 |
| 雙精度浮點型 | double |
除此之外,格式欄允許我們輸入以支持不同基本類型的組合。比如說現(xiàn)在傳入的頂點包含位置、法向量和紋理坐標(biāo),那我們可以在格式欄輸入float3 float3 float2來將輸入的數(shù)據(jù)重新解釋成我們傳入的頂點信息:
同樣,對于索引緩沖區(qū),我們可以在格式欄輸入short short short或int int int來觀察三個索引組裝一個圖元的索引數(shù)組:
而對于常量緩沖區(qū)來說,一個著色器階段可能會綁定多個常量緩沖區(qū),傳入的數(shù)據(jù)取決于你調(diào)用的ID3D11DeviceContext::*SSetConstantBuffers方法綁定的常量緩沖區(qū)以及最近一次ID3D11DeviceContext::UpdateSubresource方法更新的數(shù)據(jù),而使用的緩沖區(qū)取決于你在著色器寫的代碼。比如有下面這個常量緩沖區(qū)塊:
// 物體表面材質(zhì) struct Material {float4 Ambient;float4 Diffuse;float4 Specular; // w = SpecPowerfloat4 Reflect; };cbuffer CBChangesOnResize : register(b3) {matrix g_Proj; }我們使用float4格式就可以觀察信息。其中每個矩陣占了4行:
查看著色器資源視圖中的紋理資源
因為著色器資源視圖中可以綁定一張紋理,也可以綁定一個紋理數(shù)組。這里我以另一個程序的圖形調(diào)試作為實例,演示如何觀察綁定到渲染管線上的紋理資源。
點擊PS著色器資源的藍(lán)字部分(Grass.dds),可以查看著色器資源的狀態(tài)
現(xiàn)在我們要查看著色器資源綁定的內(nèi)容,點擊資源對應(yīng)的藍(lán)字(DDSTextureLoader)就可以查看綁定的紋理資源。
這里我們可以觀察到加載的紋理格式。在經(jīng)過DDSTextureLoader或WICTextureLoader加載的紋理會自動生成MipMap鏈,現(xiàn)在加載的是一張512x512的紋理,它有10張子資源,選擇Mip切片可以查看其余子資源紋理。隨著Mip切片等級增大,寬度和高度逐漸是原來上一級的1/2.
而在通道直方圖中,默認(rèn)觀察的是紋理RGB通道顏色的組合,你可以取消勾選來關(guān)閉某一通道的顏色,或者修改范圍來選擇顏色的可視范圍。若選擇Alpha通道,則只會單獨觀察該通道的顏色。下面是原來用的籬笆盒Alpha通道的情況(白色為Alpha值1, 黑色為Alpha值0):
接下來是紋理數(shù)組的觀察,其實和之前的操作差不多,但有時候我們在繪制過程可能找不到之前綁定上的紋理,我們可以通過下面的對象表來尋找。對象表已經(jīng)包含了由D3D設(shè)備創(chuàng)建出來的絕大多數(shù)資源或?qū)ο蟆?/p>
這里用的是公告板的例子,比如我現(xiàn)在要尋找紋理資源,在搜索欄輸入Texture來根據(jù)類型進行查找:
紋理數(shù)組加載了4張紋理,它的字節(jié)大小也應(yīng)該是最大的,雙擊它就可以看到樹的紋理了:
我們通過更改數(shù)組切片來觀察別的樹的紋理:
當(dāng)然,如果給對象具名化,在這里面找對象會更加容易一些:
查看資源歷史記錄
細(xì)心的話可以發(fā)現(xiàn)有些資源是有個時間標(biāo)志的,點擊它可以查看該資源的歷史變更情況,即有哪些方法對該資源進行了變更。
比如說我點擊了PS著色器資源:Grass.dds右邊的時間標(biāo)志(VS2015不支持)
就可以在右邊看到資源的讀取和寫入情況:
然后點擊查看就可以看到該資源當(dāng)時的具體情況了。
跟蹤渲染管線各個階段的狀態(tài)
選擇一個繪制事件,然后在下面的狀態(tài)欄就可以看到跟上一繪制事件相比,有哪些階段發(fā)生了變化。變化的部分會有紅色高亮顯示。在該狀態(tài)可以查看當(dāng)前繪制已經(jīng)綁定的所有資源、著色器和狀態(tài),相比對象表查找起來會更清晰一些。
管道階段
同樣是要先選擇一個繪制事件,然后在下面的狀態(tài)欄選擇管道階段,就可以看到當(dāng)前運行的各個著色階段,以及是否存在從某個階段開始就沒有輸入/輸出或者沒有執(zhí)行的問題。
對象查看
對于3D模型,你可以點擊輸入裝配器進入預(yù)覽網(wǎng)格界面來觀察加載出來的網(wǎng)格。
要對場景進行操作,必須要選擇上行的其中一個工具才能對場景操作。
若要對物體進行操作,則必須要選擇左邊列的其中一個工具來對其操作。
此外,你可以觀察物體的法向量或面向量
你也可以通過上圖右邊的屬性欄修改物體的基本屬性。至于其余功能你可以自行探索。
頂點位置
對于可編程的頂點著色器階段來說,我們可以看到視圖:輸入/輸出欄有 輸入/輸出的每個頂點的值和對應(yīng)語義。其中SV_POSITION的值是未經(jīng)過透視除法的,我們可以將(x, y, z, w)的每個分量除以w,變成(x/w, y/w, z/w, 1)來觀察它是否位于NDC坐標(biāo)系(齊次裁剪坐標(biāo)系)內(nèi),若不在則該頂點不會傳遞給下一階段。每個頂點都可以單獨進行著色器調(diào)試。
注意:在像素著色器中,SV_POSITION的x分量和y分量都已經(jīng)經(jīng)過視口變換成為最終的屏幕坐標(biāo),且?guī)в行?shù)點0.5,這是因為要取到像素的中心位置,即對于800x600的視口區(qū)域,實際上的屏幕坐標(biāo)取值范圍為[0.5, 800.5]x[0.5, 600.5],z分量取值范圍為[0, 1]。這一點讀者可以修改像素著色器使得SV_POSITION與像素顏色結(jié)果有關(guān)聯(lián),然后進入調(diào)試以驗證。
綁定的資源
將視圖:輸入/輸出切換成綁定的資源,同樣也能看到在該著色器階段綁定了哪些資源可供使用。
切換到像素著色器有可能是看不到任何的輸入和輸出的,但可以通過另一種方式,指定像素來觀察該像素經(jīng)歷的像素著色器階段。這里在下面會講到。
最后是輸出合并器,切換到綁定的資源,可以看到輸出合并階段綁定的深度/模板緩沖區(qū)和后備緩沖區(qū)的狀態(tài)。
查看深度/模板緩沖區(qū)資源
緊接著剛才所講的內(nèi)容,點擊左邊的深度/模板緩沖區(qū),我們就可以看到一張以紅色為背景,黑色代表深度值的紋理。黑色越深,深度值越小。
因為這張圖沒有模板值的變更,我再選擇一張帶有模板和深度值的輸出來演示。
實際上在這里,包含有模板值的區(qū)域應(yīng)當(dāng)是綠色,但是連同深度緩沖區(qū)的紅色混在一起就變成了黃色,我們可以關(guān)閉深度部分來觀察只包含模板值的綠色部分。
另一種方式就是更改查看方式。如DXGI_FORMAT_D24_UNORM_S8_UINT同時包含了模板值和深度值,那DXGI_FORMAT_R24_UNORM_X8_TYPELESS就只包含了深度值,DXGI_FORMAT_X24_TYPELESS_G8_UINT則只包含了模板值。
查看該幀圖片下某一像素的繪制歷史
點擊加載的報告XX-XX.vsglog,然后選擇要觀察的某一個像素,就可以看到該像素從開始到結(jié)束都經(jīng)歷了哪些繪制步驟,在某一個繪制事件還可以看到它屬于頂點/幾何著色器的哪一個圖元內(nèi),以及像素著色器、輸出合并器的經(jīng)歷。
著色器調(diào)試
接下來就開始進入到重點部分了,使用圖形調(diào)試器的核心目的還是要觀察著色器運行的時候遇到了哪些問題。當(dāng)然有時候甚至?xí)龅皆撚械闹鲄s被跳過不執(zhí)行的情況,這時候就先要去前面排查該綁定的資源、狀態(tài)、著色器、輸入是否都OK了,然后才是對上一個正常運行的著色器進行調(diào)試。
回到管線階段或者在像素的繪制歷史,指定某一個著色器階段,選擇一個元素,點擊一個類似播放的按鈕就可以開始進入著色器調(diào)試。
然后就會在著色器代碼實際可執(zhí)行的第一行暫停停住。你可以設(shè)置斷點,也可以單步調(diào)試,像之前在VS調(diào)試那樣來調(diào)試。此時首先你需要優(yōu)先關(guān)注局部變量中各個會被用到的常量、輸入值是否都是正常的,如果出現(xiàn)常量緩沖區(qū)中的值全0或者亂值的情況,說明常量緩沖區(qū)可能沒有被更新。若常量緩沖區(qū)的值在從C++端傳入到這里出現(xiàn)問題,你還需要去觀察常量緩沖區(qū)的打包是否出現(xiàn)了問題。
關(guān)于HLSL的打包規(guī)則,可以查看這里:
深入理解HLSL常量緩沖區(qū)打包規(guī)則
若出現(xiàn)局部變量有未使用的說明,有可能在這個調(diào)試器的確根本不會用到這個值,又或者你忘記將該常量緩沖區(qū)綁定到該著色器階段了。
而局部變量出現(xiàn)在作用域內(nèi)的說明,則可能是該變量還沒被聲明出來或者沒被賦值,需要繼續(xù)執(zhí)行才能看到。
著色器反匯編
一般來說我們看著色器的反匯編不主要是為了看匯編指令,而是它還附帶了一些額外的信息,如該著色器使用了哪些常量緩沖區(qū)、結(jié)構(gòu)體,輸入/輸出簽名如何,這些常量緩沖區(qū)經(jīng)過打包后各個元素所處的字節(jié)偏移量如何。
有的同學(xué)在還沒開始進行GPU調(diào)試的時候點擊了管道階段的藍(lán)字,然后看到編譯器輸出那欄字,以為反匯編沒有開啟。實際上是你的打開方式不對。
進入著色器調(diào)試后,對著色器代碼右鍵,選擇 轉(zhuǎn)到反匯編,就可以看到反匯編指令,又或者是點擊上方的反匯編窗口切換:
然后一路往上滾,滾到開頭就可以看到上述所說的內(nèi)容:
以編程方式捕獲圖形信息
在某些特殊情況下,你可以需要用到編程捕獲的方法:
Windows 8.1及以上的編程捕獲
DirectX 11.2 API需要Windows 8.1及更高版本系統(tǒng)的支持。接下來你需要完成下面的任務(wù):
注意:以前的編程捕獲的實現(xiàn)依賴于Visual Studio遠(yuǎn)程工具提供的捕獲功能,但從Windows 8.1起可以直接通過Direct3D 11.2來支持捕獲功能。因此,你不需要在Windows 8.1上安裝用于編程捕獲的遠(yuǎn)程工具。
首先你需要包含下面的這些頭文件:
#include <DXGItype.h> #include <dxgi1_2.h> #include <dxgi1_3.h> #include <DXProgrammableCapture.h>需要注意的是,這些頭文件無法與頭文件vsgcapture.h兼容,因為它不能與DirectX 11.2兼容。如果在d3d11_2.h后面包含該頭文件,編譯器將會發(fā)出警告;而如果在d3d11_2.h前面包含該頭文件,應(yīng)用程序?qū)⒉粫印?/p>
此外,如果你的電腦安裝了DirectX SDK(June 2010),并且你的項目包含路徑包括了%(DXSDK_DIR)Include\,請將它移到包含路徑的最末端或者去掉。
然后你需要添加下面代碼以獲取DXGI調(diào)試接口IDXGraphicsAnalysis:
IDXGraphicsAnalysis* pGraphicsAnalysis; HRESULT getAnalysis = DXGIGetDebugInterface1(0, __uuidof(pGraphicsAnalysis), reinterpret_cast<void**>(&pGraphicsAnalysis)); if (FAILED(getAnalysis)) {// 終止你的應(yīng)用程序 }如果你沒有以圖形調(diào)試形式啟動程序,DXGIGetDebugInterface1將返回E_NOINTERFACE
現(xiàn)在假定你已經(jīng)獲取了一個能用的IDXGraphicsAnalysis接口,你可以使用BeginCapture和EndCapture方法捕獲圖形信息:
pGraphicsAnalysis->BeginCapture(); // ...這部分管線命令都將被捕獲到 pGraphicsAnalysis->EndCapture();現(xiàn)在,你應(yīng)該可以看到計算著色器的調(diào)試了:
早期版本的編程捕獲
如果你的系統(tǒng)不支持DirectX 11.2及以上版本的API,則可以使用該舊版圖形捕獲方法。這種方法適用于任意DirectX 11.X版本API中使用。
首先你需要包含頭文件vsgcapture.h,然后創(chuàng)建VsgDbg對象。關(guān)于VsgDbg類,目前你只需要了解這些方法:
| 構(gòu)造函數(shù) | 形參指定為true時,將默認(rèn)產(chǎn)生臨時的vsglog文件 |
| BeginCapture | 從該語句執(zhí)行起捕獲所有的GPU事件 |
| EndCapture | 結(jié)束以BeginCature開始的捕獲事件 |
| CaptureCurrentFrame | 捕獲從當(dāng)前語句到這一幀結(jié)束的所有GPU事件 |
通常情況下我們可以構(gòu)造函數(shù)的形參指定為true,然后可以開始捕獲圖形信息:
pVSGraphicsDebugger->BeginCapture(); // ...這部分管線命令都將被捕獲到 pVSGraphicsDebugger->EndCapture();要想了解更多的信息,可以查閱MSDN文檔(編程捕獲)
總結(jié)
調(diào)試技巧需要經(jīng)常使用才能夠熟練掌握,相比普通調(diào)試來說,圖形調(diào)試會更加復(fù)雜。在初學(xué)DX的階段容易在資源管理上出問題,因此重點是要先確認(rèn)在繪制之前,綁定到渲染管線的各種資源是否正常,然后才是對著色器代碼進行調(diào)試。所以前期準(zhǔn)備工作的出錯一般占很大的一部分,而著色器代碼引發(fā)的錯誤可能只是占較小的一部分。等到了渲染管線的資源綁定管理體系逐漸穩(wěn)定以后,使用圖形調(diào)試的重心才會逐漸轉(zhuǎn)移到以著色器代碼的調(diào)試為主。有時候圖形調(diào)試器解決不了的問題,還需要仔細(xì)觀察普通調(diào)試下的輸出窗口是否有渲染管線繪制事件執(zhí)行時輸出的報錯信息。
當(dāng)然里面還有很多強大的功能沒有挖掘出來,或者現(xiàn)在還不是比較常用而沒列出來。有興趣的讀者可以查看微軟的官方中文文檔了解一下:
Visual Studio 圖形診斷概述
這篇博客在后續(xù)還會有所變動,因為后續(xù)個人的學(xué)習(xí)會引發(fā)新的調(diào)試需求而變動。
DirectX11 With Windows SDK完整目錄
歡迎加入QQ群: 727623616 可以一起探討DX11,以及有什么問題也可以在這里匯報。
轉(zhuǎn)載于:https://www.cnblogs.com/X-Jun/p/9638817.html
總結(jié)
以上是生活随笔為你收集整理的Visual Studio图形调试器详细使用教程(基于DirectX11)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 0xC00000FD: Stack ov
- 下一篇: 区分range() , np.arang