Návod: Chybějící objekty z důvodu použití funkce vertex shading
Tento názorný postup ukazuje, jak použít Visual Studio nástroje Diagnostika grafiky k prozkoumání objekt, který chybí, protože došlo k chybě během fáze vertex shader.
Tento návod ilustruje tyto úkoly:
Použijte k vyhledání potenciálních zdrojů problému Seznam událostí grafiky.
Použijte okno Fáze kanálu grafiky ke kontrole účinku DrawIndexed volání rozhraní Direct3D API.
Použijte Ladící program HLSL k prověření shaderů pixel a vertex.
Použití Zásobník volání události grafiky vám pomůže při hledání zdroje nesprávné konstanty HLSL.
Situace
Jednou z běžných příčin chybějící objektu v 3D aplikaci je situace, kdy funkce vertex shader transformuje vrcholy objektu nesprávně nebo neočekávaně – například objekt může být upraven do velmi malé velikosti nebo přeměněn tak, že se zdá být za objektivem, nikoli před ním.
Je-li v tomto scénáři aplikace spuštěna pro účely testování, pozadí je vykresleno podle očekávání, ale jeden z objektů se nezobrazí.Pomocí Diagnostiky grafiky můžete zaznamenat problém do protokolu grafiky pro účely ladění aplikace.Problém v aplikace vypadá následovně:
Zkoumání
Pomocí nástrojů Diagnostiky grafiky můžete načíst soubor protokolu grafiky pro účely kontroly rámců, které byly zaznamenány během testu.
Přezkoumání snímku v protokolu grafiky
V Visual Studio načtěte protokol grafiky, který obsahuje snímek zobrazující chybějící objekt.Nová karta s protokolem grafiky se zobrazí v Visual Studio.V horní části této karty je výstup cíle vykreslení vybraného snímku.V dolní části je Seznam snímků, který zobrazuje každý zachycený snímek jako miniaturu.
V seznamu snímků vyberte snímek, který ukazuje, že není zobrazen objekt.Cíl vykreslení je aktualizován, aby odrážel vybraný snímek.V tomto scénáři vypadá karta protokolu grafiky takto:
Po vybrání rámce, který znázorňuje problém, jej můžete začít diagnostikovat pomocí Seznamu událostí grafiky.Seznam událostí grafiky obsahuje každé volání rozhraní API Direct3D vytvořené pro vykreslení aktivní rámce, například volání API nastavující stav zařízení, tvorbu a aktualizaci vyrovnávací paměti a kreslení objektů, které se zobrazí ve snímku.Mnoho druhů volání je zajímavých, protože často (ale ne vždy) existuje odpovídající změna cíle vykreslení, když aplikace pracuje podle očekávání, například volání kreslení, odeslání, kopírování nebo mazání.Pokyny k vykreslení jsou zajímavé, protože každý z nich představuje geometrii, kterou aplikace vykreslila (pokyny k odeslání rovněž vykreslují geometrii).
Protože víte, že chybějící objekt není do cíle vykreslení vykreslován (v tomto případě) – ale že zbytek scény je vykreslen podle očekávání – můžete použít okno Seznam událostí grafiky společně s nástrojem Fáze kanálu grafiky k určení toho, který pokyn k vykreslení odpovídá chybějící geometrii objektu.Okno Fáze kanálu grafiky zobrazí geometrii, která byla odeslána jednotlivým voláním draw, bez ohledu na její vliv na cíl vykreslení.Při procházení pokynů k vykreslení jsou fáze kanálu aktualizovány a zobrazují geometrii, která je přidružena k danému pokynu, a cílový výstup vykreslení je aktualizován tak, aby po dokončení pokynu zobrazoval stav cíle vykreslení.
Vyhledání volání draw chybějící geometrie
Otevřete okno Seznam událostí grafiky.Na panelu nástrojů Diagnostika grafiky vyberte možnost Seznam událostí.
Otevřete okno Fáze kanálu grafiky.Na panelu nástrojů Diagnostika grafiky vyberte možnost Fáze kanálu.
Při procházení jednotlivých pokynů k vykreslení v okně Seznam událostí grafiky sledujte v okně Fáze kanálu grafiky chybějící objekty.Pro zjednodušení, zadejte v pravém horním rohu okna Seznam událostí grafiky v poli Hledání termín „Draw".Seznam tak bude vyfiltrován, aby obsahoval pouze události, které obsahují v názvech řetězec „Draw“.
V okně Fáze kanálu grafiky ukazuje fáze Vstupní assembler geometrii objektu před transformací a fáze Vertex Shader ukazuje stejný objekt po transformaci.V tomto scénáři víte, že jste nalezli chybějící objekt, je-li zobrazen ve fázi vstupní assembler a ve fázi vertex shader se nic nezobrazí.
[!POZNÁMKA]
Pokud objekt zpracovávají jiné geometrické fáze, například shader trupu, doménový shader nebo geometrický shader, mohou být ony příčinou problému.Problém obvykle souvisí s nejstarší fází, ve které se nezobrazí výsledek nebo je zobrazen neočekávaným způsobem.
Zastavte při dosažení volání draw, které odpovídá chybějícímu objektu.V tomto scénáři okno Fáze kanálu grafiky ukazuje, že byla vydána geometrie do GPU (indikováno miniaturou vstupního assembleru), ale nezobrazuje se v cíli vykreslení, protože došlo k nějaké chybě během fáze vertex shaderu (indikováno miniaturou vertex shaderu):
Po potvrzení, že aplikace vydala pokyny k vykreslení pro chybějící geometrii objektu, a zjištění, že problém nastává během fáze vertex shaderu, můžete použít funkci HLSL Debugger ke kontrole vertex shaderu a zjistit, co se stalo s geometrií objektu.Můžete použít ladící program HLSL ke kontrole stavu proměnné HLSL během spuštění, krokovat kód HLSL a nastavit zarážky, které vám pomohou diagnostikovat problém.
Zkoumání shaderu vertex
Spuštění ladění shaderu ve fázi vertex.V okně Fáze kanálu grafiky ve fázi Vertex Shader zvolte tlačítko Spustit ladění.
Protože fáze Kompilátor vstupu poskytuje správná data pro vertex shader a Vertex Shader neposkytuje žádný výstup, chcete prověřit strukturu výstupu funkce vertex shader output.Při procházení kódu HLSL se můžete podívat podrobněji, když je output upraven.
Při první změně output, člen worldPos je zapsán.
Protože hodnota vypadá přiměřená, můžete pokračovat procházením kódu až do dalšího řádku, který upravuje output.
Příště při změně output, člen pos je zapsán.
Tento čas, hodnota člena pos – vše nuly – se zdají být podezřelé.Dále chcete určit, jak output.pos získal hodnotu se všemi nulami.
Všimněte si, že hodnota trvání příkazu output.pos závisí na proměnné s názvem temp.Na předchozím řádku je patrné, že hodnota temp je výsledkem násobku předchozí hodnoty konstantou s názvem projection.Máte podezření, že výsledkem tohoto násobení proměnné temp jsou podezřelé hodnoty.Při umístění ukazatele na projection zjistíte, že jeho hodnota je také nulová.
V tomto scénáři zkouška ukáže, že podezřelá hodnota temp je pravděpodobně způsobena vynásobením pomocí projection a protože projection je konstanta, která má obsahovat projekční matici, neměla by obsahovat všechny nulové hodnoty.
Po zjištění, zda je konstanta HLSL projection – předaná shaderu vaší aplikací – pravděpodobným zdrojem problému, je dalším krokem nalezení umístění ve zdrojovém kódu aplikace, kde je vyplněna konstantní vyrovnávací paměť.Můžete k vyhledání tohoto umístění použít Zásobník volání události grafiky.
Vyhledání, kde je konstanta nastavena ve zdrojovém kódu vaší aplikace
Otevřete okno Zásobník volání události grafiky.Na panelu nástrojů Diagnostika grafiky vyberte možnost Zásobník volání události grafiky.
Projděte zásobník volání do zdrojového kódu vaší aplikace.V okně Zásobník volání událostí grafiky zvolte volání zcela nahoře, abyste zjistili, zda je zaplněna vyrovnávací paměť konstant.Pokud tomu tak není, pokračujte nahoru zásobníkem volání, dokud nenajdete místo, kde je vyplňován.V tomto scénáři zjistíte zaplnění konstantní vyrovnávací paměti – pomocí Direct3D API UpdateSubresource - dále nahoru v zásobníku volání ve funkci s názvem MarbleMaze::Render a že jeho hodnota pochází z objektu konstantní vyrovnávací paměti s názvem m_marbleConstantBufferData:
Tip
Pokud současně ladíte vaši aplikaci, na tomto místě můžete nastavit zarážku, která se zapojí při vykreslení dalšího snímku.Poté můžete zkontrolovat členy m_marbleConstantBufferData a ujistit se, zda hodnota členů projection je při zaplnění konstantní vyrovnávací paměti nastavena na nulu.
Po nalezení umístění, ve kterém dochází k naplnění konstantní vyrovnávací paměti, a zjištění, že hodnoty pocházejí z proměnné m_marbleConstantBufferData, je dalším krokem zjistit, kde je člen m_marbleConstantBufferData.projection nastaven na samé nuly.K rychlému načtení kódu, který mění hodnotu m_marbleConstantBufferData.projection, můžete použít možnost Najít všechny odkazy.
Vyhledání, kde je člen projekce nastaven ve zdrojovém kódu vaší aplikace
Reference naleznete na m_marbleConstantBufferData.projection.Otevřete místní nabídku proměnné m_marbleConstantBufferData a zvolte možnost Najít všechny odkazy.
Pokud chcete přejít k umístění řádku ve zdrojovém kódu vaší aplikace, kde je upraven člen projection, zvolte tento řádek v okně Výsledky hledání symbolu.Protože první výsledek, který upravuje člena projekce, nemusí být příčinou problému, budete muset zkontrolovat několik oblastí zdrojového kódu aplikace.
Po nalezení umístění, ve kterém je nastaven objekt m_marbleConstantBufferData.projection, můžete zkontrolovat okolní zdrojový kód a určit původ nesprávné hodnoty.V tomto scénáři můžete zjistit, že je hodnota m_marbleConstantBufferData.projection nastavena na místní proměnnou s názvem projection dříve, než byla inicializována na hodnotu, která je dána kódem m_camera->GetProjection(&projection); na dalším řádku.
Abyste problém vyřešili, přesuňte řádek kódu, který nastavuje hodnotu m_marbleConstantBufferData.projection za řádek, který inicializuje hodnoty místní proměnné projection.
Po opravě kódu jej můžete znovu vytvořit a spustit aplikaci znovu, abyste zjistili, zda je problém vykreslování vyřešen: