Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Existuje několik typů dotazů, které jsou navržené k dotazování stavu prostředků. Stav daného prostředku zahrnuje stav grafického procesoru (GPU), stav ovladače nebo stav modulu runtime. Abyste pochopili rozdíl mezi různými typy dotazů, musíte porozumět stavům dotazu. Následující diagram přechodu stavu vysvětluje jednotlivé stavy dotazu.
diagram 
Diagram znázorňuje tři stavy definované kruhy. Každá plná čára jsou události řízené aplikací, které způsobují přechod stavu. Přerušovaná čára je událost řízená prostředkem, která přepne dotaz z vystaveného stavu do signalizačního stavu. Každý z těchto stavů má jiný účel:
- Signalovaný stav je jako nečinný stav. Objekt dotazu se vygeneroval a čeká na vydání dotazu aplikací. Jakmile se dotaz dokončí a přepnou zpět do signalovaného stavu, můžete načíst odpověď na dotaz.
- Stav budovy je jako pracovní oblast dotazu. Ze stavu budovy byl vydán dotaz (voláním D3DISSUE_BEGIN), ale ještě nepřešel na vystavený stav. Když aplikace vydá konec dotazu (zavoláním D3DISSUE_END), dotaz se přepne do vystaveného stavu.
- Vystavený stav znamená, že dotazovaný prostředek má kontrolu nad dotazem. Jakmile zdroj dokončí svoji práci, prostředek přejde stavový počítač do signalovaného stavu. Během vydaného stavu se aplikace musí dotazovat, aby zjistila přechod do signalovaného stavu. Jakmile dojde k přechodu do signalovaného stavu, GetData vrátí výsledek dotazu (prostřednictvím argumentu) do aplikace.
Následující tabulka uvádí dostupné typy dotazů.
| Typ dotazu | Událost problému | Vyrovnávací paměť GetData | Runtime | Implicitní začátek dotazu |
|---|---|---|---|---|
| ODHADY ŠÍŘKY PÁSMA | D3DISSUE_BEGIN, D3DISSUE_END | D3DDEVINFO_D3D9BANDWIDTHTIMINGS | Maloobchodní/ladicí | Není k dispozici |
| VYUŽITÍ MEZIPAMĚTI | D3DISSUE_BEGIN, D3DISSUE_END | D3DDEVINFO_D3D9CACHEUTILIZATION | Maloobchodní/ladicí | Není k dispozici |
| UDÁLOST | D3DISSUE_END | BOOL | Maloobchodní/ladicí | CreateDevice |
| INTERFACETIMINGS | D3DISSUE_BEGIN, D3DISSUE_END | D3DDEVINFO_D3D9INTERFACETIMINGS | Maloobchodní/ladicí | Není k dispozici |
| OKLUZE | D3DISSUE_BEGIN, D3DISSUE_END | DWORD | Maloobchodní/ladicí | Není k dispozici |
| PIPELINETIMINGS | D3DISSUE_BEGIN, D3DISSUE_END | D3DDEVINFO_D3D9PIPELINETIMINGS | Maloobchodní/ladicí | Není k dispozici |
| RESOURCEMANAGER | D3DISSUE_END | D3DDEVINFO_ResourceManager | Pouze ladění | prezentovat |
| ČASOVÁ ZNAČKA | D3DISSUE_END | UINT64 | Maloobchodní/ladicí | Není k dispozici |
| TIMESTAMPDISJOINT | D3DISSUE_BEGIN, D3DISSUE_END | BOOL | Maloobchodní/ladicí | Není k dispozici |
| TIMESTAMPFREQ | D3DISSUE_END | UINT64 | Maloobchodní/ladicí | Není k dispozici |
| VCACHE | D3DISSUE_END | D3DDEVINFO_VCACHE | Maloobchodní/ladicí | CreateDevice |
| VERTEXSTATS | D3DISSUE_END | D3DDEVINFO_D3DVERTEXSTATS | Pouze ladění | prezentovat |
| VERTEXTIMINGS | D3DISSUE_BEGIN, D3DISSUE_END | D3DDEVINFO_D3D9STAGETIMINGS | Maloobchodní/ladicí | Není k dispozici |
Některé dotazy vyžadují počáteční a koncovou událost, zatímco jiné vyžadují jenom koncovou událost. Dotazy, které vyžadují pouze koncovou událost, začínají, když dojde k jiné implicitní události (která je uvedená v tabulce). Všechny dotazy vrací odpověď s výjimkou dotazu události, jehož odpověď je vždy TRUE. Aplikace používá stav dotazu nebo návratový kód GetData.
Vytvoření dotazu
Než vytvoříte dotaz, můžete zkontrolovat, jestli modul runtime podporuje dotazy voláním CreateQuery s ukazatelem NULL takto:
IDirect3DQuery9* pEventQuery;
// Create a device pointer m_pd3dDevice
// Create a query object
HRESULT hr = m_pd3dDevice->CreateQuery(D3DQUERYTYPE_EVENT, NULL);
Tato metoda vrátí kód úspěchu, pokud lze vytvořit dotaz; v opačném případě vrátí kód chyby. Jakmile CreateQuery úspěšně, můžete vytvořit objekt dotazu takto:
IDirect3DQuery9* pEventQuery;
m_pd3dDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pEventQuery);
Pokud je toto volání úspěšné, vytvoří se objekt dotazu. Dotaz je v podstatě nečinný v signalizovaném stavu (s neinicializovanou odpovědí) čekající na vydání. Až dotaz dokončíte, uvolněte ho stejně jako jakékoli jiné rozhraní.
Vydání dotazu
Aplikace změní stav dotazu vydáním dotazu. Tady je příklad vystavení dotazu:
IDirect3DQuery9* pEventQuery;
m_pD3DDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pEventQuery);
// Issue a Begin event
pEventQuery->Issue(D3DISSUE_BEGIN);
or
// Issue an End event
pEventQuery->Issue(D3DISSUE_END);
Dotaz v signalizačním stavu se při vystavení změní takto:
| Typ problému | Přechody dotazu na . . . |
|---|---|
| D3DISSUE_BEGIN | Stav budovy. |
| D3DISSUE_END | Vystavený stav. |
Dotaz ve stavu budovy se při vydání změní takto:
| Typ problému | Přechody dotazu na . . . |
|---|---|
| D3DISSUE_BEGIN | (Žádný přechod, zůstane ve stavu budovy. Restartuje závorku dotazu.) |
| D3DISSUE_END | Vystavený stav. |
Dotaz ve vydaném stavu se při vydání změní takto:
| Typ problému | Přechody dotazu na . . . |
|---|---|
| D3DISSUE_BEGIN | Sestavení stavu a restartování závorky dotazu |
| D3DISSUE_END | Vystavený stav po opuštění existujícího dotazu |
Zkontrolujte stav dotazu a získejte odpověď na dotaz.
GetData dělá dvě věci:
- Vrátí stav dotazu ve návratovém kódu.
- Vrátí odpověď na dotaz v pData.
V každém ze tří stavů dotazu jsou tady návratové kódy GetData:
| Stav dotazu | Návratový kód GetData |
|---|---|
| Signalizovala | S_OK |
| Budova | Kód chyby |
| Vydaný | S_FALSE |
Pokud je například dotaz ve vydaném stavu a odpověď na dotaz není k dispozici, GetData vrátí S_FALSE. Jakmile prostředek dokončí svou práci a aplikace vydala konec dotazu, prostředek přepne dotaz do signalovaného stavu. Z signalizačního stavu GetData vrátí S_OK což znamená, že odpověď na dotaz se vrátí také v pData. Tady je například posloupnost událostí, která vrátí počet pixelů (nebo vzorky při povolení vícevzorkování) v posloupnosti vykreslování:
- Vytvořte dotaz.
- Zadejte počáteční událost.
- Něco nakreslete.
- Vyřešte koncovou událost.
Následuje odpovídající posloupnost kódu:
IDirect3DQuery9* pOcclusionQuery;
DWORD numberOfSamplesDrawn;
m_pD3DDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &pOcclusionQuery);
// Add an end marker to the command buffer queue.
pOcclusionQuery->Issue(D3DISSUE_BEGIN);
// API render loop
...
Draw(...)
...
// Add an end marker to the command buffer queue.
pOcclusionQuery->Issue(D3DISSUE_END);
// Force the driver to execute the commands from the command buffer.
// Empty the command buffer and wait until the GPU is idle.
while(S_FALSE == pOcclusionQuery->GetData( &numberOfSamplesDrawn,
sizeof(DWORD), D3DGETDATA_FLUSH ))
;
// To get the number of pixels drawn when multisampling is enabled,
// divide numberOfSamplesDrawn by the sample count of the render target.
Tyto řádky kódu dělají několik věcí:
- Voláním GetData vrátíte počet pixelů/vzorků nakreslených.
- Zadejte D3DGETDATA_FLUSH, aby prostředek mohl převést dotaz do signalovaného stavu.
- Dotazujte prostředek dotazu voláním GetData ze smyčky. Pokud GetData vrátí S_FALSE, znamená to, že prostředek ještě nevrátil odpověď.
Návratová hodnota GetData vám v podstatě řekne, v jakém stavu je dotaz. Možné hodnoty jsou S_OK, S_FALSE a chyba. Nevolejte GetData dotazu, který je ve stavu sestavení.
- S_OK znamená dokončení prostředku (GPU nebo ovladače nebo modulu runtime). Dotaz se vrací do signalovaného stavu. Odpověď (pokud existuje) vrací GetData.
- S_FALSE znamená, že prostředek (GPU nebo ovladač nebo modul runtime) zatím nemůže vrátit odpověď. Důvodem může být to, že GPU není dokončené nebo ještě neviděl práci.
- Chyba znamená, že dotaz vygeneroval chybu, ze které se nedá obnovit. To může být případ ztráty zařízení během dotazu. Jakmile dotaz vygeneruje chybu (jinou než S_FALSE), musí se dotaz znovu vytvořit, což restartuje sekvenci dotazu z signalovaného stavu.
Místo zadání D3DGETDATA_FLUSH, která poskytuje více up-to-date informace, můžete zadat nulu, což je kontrola lehké hmotnosti, pokud je dotaz ve vydaném stavu. Zadání nuly způsobí, že GetData nevyprázdní vyrovnávací paměť příkazů. Z tohoto důvodu je potřeba věnovat pozornost tomu, abyste se vyhnuli nekonečné smyčce (podrobnosti najdete v tématu GetData). Vzhledem k tomu, že modul runtime zařadí do fronty práci v vyrovnávací paměti příkazů, D3DGETDATA_FLUSH je mechanismus pro vyprázdnění vyrovnávací paměti příkazu ovladači (a proto GPU; viz Přesné profilace volání rozhraní API Direct3D (Direct3D 9)). Během vyprázdnění vyrovnávací paměti příkazu může dotaz přejít do signalizačního stavu.
Příklad: Dotaz na událost
Dotaz události nepodporuje počáteční událost.
- Vytvořte dotaz.
- Vyřešte koncovou událost.
- Dotazujte se, dokud nebude GPU nečinný.
- Vyřešte koncovou událost.
IDirect3DQuery9* pEventQuery = NULL;
m_pD3DDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pEventQuery);
// Add an end marker to the command buffer queue.
pEventQuery->Issue(D3DISSUE_END);
// Empty the command buffer and wait until the GPU is idle.
while(S_FALSE == pEventQuery->GetData( NULL, 0, D3DGETDATA_FLUSH ))
;
... // API calls
// Add an end marker to the command buffer queue.
pEventQuery->Issue(D3DISSUE_END);
// Force the driver to execute the commands from the command buffer.
// Empty the command buffer and wait until the GPU is idle.
while(S_FALSE == pEventQuery->GetData( NULL, 0, D3DGETDATA_FLUSH ))
;
Toto je posloupnost příkazů, které dotaz události používá k profilování volání aplikačního programovacího rozhraní (API) (viz Přesné profilace volání rozhraní API Direct3D (Direct3D 9)). Tato sekvence používá značky, které pomáhají řídit množství práce v vyrovnávací paměti příkazů.
Všimněte si, že aplikace by měly věnovat zvláštní pozornost velkým nákladům spojeným s vyprázdněním vyrovnávací paměti příkazů, protože to způsobí, že operační systém přepne do režimu jádra, což způsobí snížení velikosti výkonu. Aplikace by také měly vědět o plýtvání cykly procesoru čekáním na dokončení dotazů.
Dotazy jsou optimalizace, která se použije při vykreslování ke zvýšení výkonu. Proto není výhodné strávit čas čekáním na dokončení dotazu. Pokud je dotaz vystavený a výsledky ještě nejsou připravené v době, kdy je aplikace zkontroluje, pokus o optimalizaci neprošel úspěšně a vykreslování by mělo pokračovat v normálním stavu.
Klasickým příkladem je occlusion Culling. Místo , když smyčka výše, může aplikace, která používá dotazy, implementovat okluzování, aby zkontrolovala, jestli byl dotaz dokončený v době, kdy potřebuje výsledek. Pokud se dotaz nedokončil, pokračujte (jako nejhorší scénář), jako kdyby testovaný objekt nebyl odlehlé (tj. viditelné) a vykreslujte ho. Kód by vypadal podobně jako v následujícím příkladu.
IDirect3DQuery9* pOcclusionQuery = NULL;
m_pD3DDevice->CreateQuery( D3DQUERYTYPE_OCCLUSION, &pOcclusionQuery );
// Add a begin marker to the command buffer queue.
pOcclusionQuery->Issue( D3DISSUE_BEGIN );
... // API calls
// Add an end marker to the command buffer queue.
pOcclusionQuery->Issue( D3DISSUE_END );
// Avoid flushing and letting the CPU go idle by not using a while loop.
// Check if queries are finished:
DWORD dwOccluded = 0;
if( S_FALSE == pOcclusionQuery->GetData( &dwOccluded, sizeof(DWORD), 0 ) )
{
// Query is not done yet or object not occluded; avoid flushing/wait by continuing with worst-case scenario
pSomeComplexMesh->Render();
}
else if( dwOccluded != 0 )
{
// Query is done and object is not occluded.
pSomeComplexMesh->Render();
}
Související témata