그래픽 상태 및 구성 요소를 관리합니까?


11

나는 종종 그래픽을 다룰 때 많은 조기 최적화를하는 경향이 있습니다. 항상 따라야 할 몇 가지 원칙이 있습니다.

  • D3D 구성 요소의 수를 최소로 유지하십시오. (렌더링 상태, 버퍼, 쉐이더 등)
  • 꼭 필요한 경우에만 구성 요소를 바인딩하십시오. (미제 한 등)
  • 구성 요소를 가능한 많이 전문화하십시오. (필요한 BindFlags 등 만 설정하십시오.)

이로 인해 생성 된 구성 요소 및 현재 파이프 상태를 관리하기위한 매우 정교한 래퍼를 만들 수있었습니다. 이것은 귀중한 개발 시간을 많이 소비 할뿐만 아니라 복잡성을 더합니다.

그리고 최악의 경우 : 나는 그것이 문제의 가치가 있는지조차 모릅니다.

내 최적화 고려 사항 중 일부는 이미 낮은 수준에서 구현되었을 수 있으며 CPU에 시간을 낭비하면서 복제하고 있습니다. 성능에 미치는 영향은 무시할 수 있으므로 다른 고려 사항은 완전히 불필요 할 수 있습니다.

그래서 내 질문은 :

  1. 위의 지침 중 어느 것이 유효하며 어느 정도까지 따라야합니까?
  2. GPU는 상태 변경을 어떻게 처리합니까?
  3. 사용하지 않은 상태를 변경하면 어떻게됩니까? 활성화되어있는 동안에는 드로우 콜이 없습니다.
  4. 다양한 구성 요소를 바인딩 할 때 실제로 성능이 저하되는 것은 무엇입니까?
  5. 다른 성능 고려 사항은 무엇입니까?

실제 한계에 도달 할 때까지 성능에 신경 쓰지 말아야한다는 말만하지 마십시오. 그것은 실제적인 관점에서 분명히 사실이지만, 나는 주로 이론에 관심이 있습니다. 나는 어떻게 든 최적의 그래픽 프레임 워크 를 구축해야한다는 충동에 맞서 싸울 필요 가 있으며 평범한 "조기 최적화 강의"로는 그렇게 할 수 없다고 생각합니다.

구성 요소 관리

현재 SlimDX를 관리되는 래퍼로 사용하여 C #에서 DirectX 11 응용 프로그램을 작성하고 있습니다. 매우 낮은 수준의 래퍼이며 현재 추상화가 위에 있습니다.

Direct3D 추상화를 사용할 때 몇 가지 명백한 장점이 있습니다. 환경 설정, 셰이더 로딩, 상수 설정 및 메시 그리기는 훨씬 간단하고 훨씬 적은 코드를 사용 합니다 . 또한 대부분의 구성 요소의 생성 및 폐기를 관리하므로 모든 곳에서 자동으로 재사용 할 수 있으며 메모리 누수를 거의 완전히 피합니다.

  1. 일반적으로 모든 그래픽 구성 요소와 리소스를 어떻게 관리합니까?
  2. 아래 예제와 비슷한 방법으로 관리 래퍼를 추천 할 수 있습니까?

다음은 현재 구현 예입니다. 나는 인터페이스에 매우 만족합니다. 그것은 내 요구에 충분한 유연성을 가지고 있으며 사용하고 이해하는 것이 매우 간단합니다.

// Init D3D environment
var window = new RenderForm();
var d3d = new Direct3D(window, GraphicsSettings.Default);
var graphics = new GraphicsManager(d3d.Device);

// Load assets
var mesh = GeometryPackage.FromFile(d3d, "teapot.gp");
var texture = Texture.FromFile(d3d, "bricks.dds");

// Render states
graphics.SetViewports(new Viewport(0, 0, 800, 600);
graphics.SetRasterizer(wireFrame: false, culling: CullMode.Back);
graphics.SetDepthState(depthEnabled: true, depthWriteEnabled: true);
graphics.SetBlendState(BlendMethod.Transparency);

// Input layout
graphics.SetLayout("effect.fx", "VS", "vs_4_0",
    new InputElement("POSITION", 0, Format.R32G32B32_Float, 0),
    new InputElement("TEXCOORD", 0, Format.R32G32_Float, 0)
);

// Vertex shader
graphics.SetShader(Shader.Vertex, "effect.fx", "VS", "vs_4_0");
graphics.SetConstants(Shader.Vertex, 0, 4, stream => stream.Write(wvpMatrix));

// Pixel shader
graphics.SetShader(Shader.Pixel, "effect.fx", "PS", "ps_4_0");
graphics.SetTexture(Shader.Pixel, 0, texture);
graphics.SetSampler(Shader.Pixel, 0, Sampler.AnisotropicWrap);
graphics.SetConstants(Shader.Pixel, 0, 1, stream => stream.Write(new Color4(1, 0, 1, 0);

d3d.Run(() =>
{
    // Draw and present
    d3d.BackBuffer.Clear(new Color4(1, 0, 0.5f, 1));
    graphics.SetOutput(d3d.BackBuffer);
    graphics.Draw(mesh);
    d3d.Present();
}

8
이런 종류의 질문에 대해서는 "조기 최적화"강의를 제공하지 않겠습니다. "귀하가 직접 볼 수 있도록 프로필 변경"강의를 제공합니다.
Tetrad

@Tetrad 나는 이것이 꽤 괜찮은 조언임을 인정하는 것이 거의 부끄럽습니다. 더 많은 프로파일 링을해야합니다.
Lucius

1
프로파일 링 번호는 "pics 또는 그것이 일어나지 않았다"의 gamedev 버전입니다 =)
Patrick Hughes

답변:


3

나는 gamedev.net의 다음 스레드에서 Hodgman이 설명한 추상화 접근법을 좋아합니다.

그는 3 계층 렌더링 시스템에 대해 설명합니다.

  1. Direct3D 9, Direct3D 11 및 OpenGL과 같은 다른 그래픽 API의 차이점을 추상화하여 "명령"을 허용하는 저수준 렌더링 API. 각 "명령"은 정점 스트림 또는 텍스처 바인딩 또는 기본 요소 그리기와 같은 다른 상태 또는 드로우 콜에 매핑됩니다.
  2. "렌더링 항목"을 허용하는 API로, 특정 상태를 렌더링하는 데 필요한 모든 상태와 단일 드로우 콜을 그룹화하고이를 정렬하여 첫 번째 수준으로 전송되는 명령으로 변환합니다. 렌더 상태에는 드로우 콜과 논리적으로 상태 변경을 그룹화하는 "상태 그룹"스택이 포함됩니다. 예를 들어 렌더 패스의 상태 그룹, 재질의 상태 그룹, 지오메트리의 상태 그룹, 인스턴스의 상태 그룹 등이 있습니다. 이 레벨은 이러한 렌더링 항목을 정렬하여 중복 상태 변경을 줄이고 실제로 중복 상태를 변경합니다.
  3. 장면 그래프 또는 GUI 렌더러와 같은 고급 시스템은 렌더링 항목을 두 번째 수준으로 보냅니다. 주목해야 할 중요한 점은 이러한 시스템은 상태 정렬 알고리즘이나 특정 렌더링 API에 대해 알지 못하므로 플랫폼을 완전히 무시할 수 있다는 것입니다. 하위 수준 API가 구현되면 사용하기도 쉽습니다.

결론적으로이 모델은 두 문제를 한 번에 해결합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.