J'essaie d'améliorer un simple code de rendu DirectX que j'ai implémenté. Mon idée est de ne mettre à jour le pipeline de rendu que lorsque cela est absolument nécessaire car, d'après ce que je comprends, il est avantageux de minimiser autant que possible le nombre de modifications du pipeline. Ce que je veux dire par là est démontré dans le pseudo-code suivant:Comprendre les optimisations de pipeline DirectX
ID3D11VertexShader *t_shader = getVertexShader();
ID3D11DeviceContext->VSSetShader(t_shader, nullptr, 0);
// Do some other processing/pipeline setup without modifying t_shader
ID3D11DeviceContext->VSSetShader(t_shader, nullptr, 0);
ID3D11DeviceContext->Draw(10, 0);
Ceci est inefficace parce que nous appelons VSSetShader deux fois lorsque le shader n'a pas changé. C'est une simplification excessive, mais j'espère que vous obtenez d'où je viens, ma compréhension de base est ce type de liens inutiles/appels sont inefficaces?
Si tel est le cas, alors est-il possible d'effectuer l'optimisation ci-dessous entre deux appels ID3D11DeviceContext :: Draw distincts? (Encore une fois pseudocode donc s'il vous plaît pardonnez les étapes manquantes et d'assumer tout ce que nous devons faire est de définir avec une topologie d'un pixel shader sommet & le long avant de tirer):
void Object1::Draw() {
ID3D11VertexShader *t_vs = ShaderMgr::vertexShader1();
ID3D11DeviceContext->VSSetShader(t_vs, nullptr, 0);
ID3D11PixelShader *t_ps = ShaderMgr::pixelShader1();
ID3D11DeviceContext->PSSetShader(t_ps, nullptr, 0);
ID3D11DeviceContext->IASetPrimitiveTopology(ID3D11_PRIMITIVE_TOPOLOGY_LINELIST);
ID3D11DeviceContext->Draw(m_vertexCount, 0);
}
void Object2::Draw() {
ID3D11VertexShader *t_vs = ShaderMgr::vertexShader1();
ID3D11DeviceContext->VSSetShader(t_vs, nullptr, 0);
// Use a different pixel shader to Object1
ID3D11PixelShader *t_ps = ShaderMgr::pixelShader2();
ID3D11DeviceContext->PSSetShader(t_ps, nullptr, 0);
ID3D11DeviceContext->IASetPrimitiveTopology(ID3D11_PRIMITIVE_TOPOLOGY_LINELIST);
ID3D11DeviceContext->Draw(m_vertexCount, 0);
}
La seule différence entre les deux tirage au sort appelle est l'utilisation d'un pixel shader différent. Est-ce que la suivante est une optimisation possible ou est-ce que chaque appel de tirage réinitialise efficacement le pipeline?
void Object1::Draw() {
// Removed common set code
ID3D11PixelShader *t_ps = ShaderMgr::pixelShader1();
ID3D11DeviceContext->PSSetShader(t_ps, nullptr, 0);
ID3D11DeviceContext->Draw(m_vertexCount, 0);
}
void Object2::Draw() {
// Removed common set code
ID3D11PixelShader *t_ps = ShaderMgr::pixelShader2();
ID3D11DeviceContext->PSSetShader(t_ps, nullptr, 0);
ID3D11DeviceContext->Draw(m_vertexCount, 0);
}
void drawObjects() {
// Common states amongst object1 and object2
ID3D11VertexShader *t_vs = ShaderMgr::vertexShader1();
ID3D11DeviceContext->VSSetShader(t_vs, nullptr, 0);
ID3D11DeviceContext->IASetPrimitiveTopology(ID3D11_PRIMITIVE_TOPOLOGY_LINELIST);
m_object1->draw();
// Don't bother setting the vs or topology here
m_object2->draw();
}
Une rétroaction/information serait grandement appréciée.
Vous pouvez simplement encapsuler le périphérique dans une classe qui effectue la mise en cache d'état pour intercepter la redondance. Habituellement, le gain de perf, à moins que quelque chose de vraiment mauvais ne soit fait, est minime lorsque vous vous débarrassez de ces appels de toute façon car le pilote cache et teste d'habitude les changements d'état inutiles déjà. – galop1n
C'est ce que j'essaie d'implémenter en ce moment, en concevant une classe Pipeline qui ne change d'état qu'en cas de besoin, le problème que je vois à la minute est après un appel draw initial, l'état du pipeline semble avoir été réinitialisé et je dois tout remettre en place, par exemple InputTopology, tampons de vertex etc. – TheRarebit
Vous pouvez voir comment DirectX12 encapsule l'état du pipeline (Pipeline State Objects). Je ne suggère pas que vous utilisez réellement DirectX 12 à moins que vous soyez déjà un utilisateur expert de DirectX 11, mais la conception reflète les préférences du matériel GPU moderne. –