구현 한 간단한 DirectX 렌더링 코드를 개선하려고합니다. 가능한 한 파이프 라인 수정 횟수를 최소화하는 것이 좋다고 생각하기 때문에 내 생각은 절대적으로 필요한 경우에만 렌더링 파이프 라인을 업데이트하는 것입니다. 내가이 뜻하는 것은 다음 의사 코드에서 설명된다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);
쉐이더가 변경되지 않은 경우 우리는 두 번 VSSetShader를 호출하고 있기 때문에 이것은 비효율적이다. 이것은 지나치게 단순화되었지만 잘하면 내가 어디에서 왔는지 이해할 수 있습니다. 기본적인 이해는 이러한 유형의 불필요한 바인드/호출이 비효율적입니까?
그런 경우 두 개의 개별 ID3D11DeviceContext :: Draw 호출 사이에서 아래 최적화를 수행 할 수 있습니까? (다시 의사는 이렇게 누락 된 단계를 용서하고 우리가 그리기 전에 토폴로지로 정점 & 픽셀 쉐이더를 함께 설정해야 할 모든 가정하십시오) : 두 무승부 사이의 유일한 차이는 호출
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);
}
이 사용입니다 다른 픽셀 쉐이더의 다음은 가능한 최적화입니까 아니면 각 그리기 호출이 파이프 라인을 효과적으로 재설정합니까?
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();
}
의견/정보를 보내 주시면 감사하겠습니다.
중복성을 포착하기 위해 상태 캐싱을 수행하는 클래스 내에 장치를 캡슐화하면됩니다. 드라이버가 보통 불필요한 상태 변화를 캐시하고 테스트하기 때문에 어쨌든 이러한 호출을 제거하면 실제로 성능이 좋지 않은 것이 아니라면 퍼포먼스 이득이 최소화됩니다. – galop1n
이것은 현재 구현하려고하는 것입니다. 필요할 때만 상태를 변경하는 Pipeline 클래스를 디자인합니다. 초기 그리기 호출 후에 파이프 라인의 "상태"가있는 것처럼 보입니다. 다시 설정하고 나는 모든 것을 다시 설정해야합니다. 입력 토폴로지, 버텍스 버퍼 등 – TheRarebit
DirectX12가 파이프 라인 상태 (파이프 라인 상태 개체)를 캡슐화하는 방법을 살펴볼 수 있습니다. 이미 DirectX 11을 전문 사용자로 사용하지 않는 한 실제로 DirectX 12를 사용하라고 제안하지는 않지만, 디자인은 최신 GPU 하드웨어의 기본 설정을 반영합니다. –