인덱스 버퍼(Direct3D 9)

IDirect3DIndexBuffer9 인터페이스로 표시되는 인덱스 버퍼는 인덱스 데이터를 포함하는 메모리 버퍼입니다. 인덱스 데이터 또는 인덱스는 꼭짓점 버퍼에 대한 정수 오프셋이며 IDirect3DDevice9::D rawIndexedPrimitive 메서드를 사용하여 기본 형식을 렌더링하는 데 사용됩니다.

꼭짓점 버퍼에는 꼭짓점이 포함되므로 인덱싱된 원형을 이용하거나 이용하지 않고 꼭짓점 버퍼를 그릴 수 있습니다. 하지만 인덱스 버퍼에는 인덱스가 포함되므로 해당하는 꼭짓점 버퍼 없이 인덱스 버퍼를 사용할 수 없습니다. (참고로 IDirect3DDevice9::D rawIndexedPrimitiveUPIDirect3DDevice9::D rawPrimitiveUP 은 인덱스 또는 꼭짓점 버퍼 없이 그리는 유일한 그리기 메서드입니다.)

인덱스 버퍼 설명

인덱스 버퍼는 메모리 내에서의 위치, 읽기 및 쓰기 지원 여부, 버퍼가 포함할 수 있는 인덱스의 유형과 개수 등 기능의 관점에서 설명됩니다. 이러한 특성은 D3DINDEXBUFFER_DESC 구조로 유지됩니다.

인덱스 버퍼 설명은 기존 버퍼의 생성 과정에 대한 정보를 애플리케이션에 제공합니다. 이전에 생성한 인덱스 버퍼의 기능으로 채우려면 시스템에 빈 설명 구조를 제공합니다.

  • Format 멤버는 인덱스 버퍼 데이터의 표면 형식을 설명합니다.
  • Type은 인덱스 버퍼의 리소스 유형을 식별합니다.
  • 사용 구조 멤버에는 일반 기능 플래그가 포함됩니다. D3DUSAGE_SOFTWAREPROCESSING 플래그는 인덱스 버퍼를 소프트웨어 꼭짓점 처리와 함께 사용할 것임을 나타냅니다. 사용량에 D3DUSAGE_WRITEONLY 플래그가 있으면 인덱스 버퍼 메모리가 쓰기 작업에만 사용됨을 나타냅니다. 이렇게 하면 드라이버가 인덱스 데이터를 최상의 메모리 위치에 배치하여 빠른 처리 및 렌더링을 가능하게 합니다. D3DUSAGE_WRITEONLY 플래그를 사용하지 않으면 드라이버는 읽기 작업에 비효율적인 위치에 데이터를 배치할 가능성이 적습니다. 이렇게 하면 약간의 처리 및 렌더링 속도가 희생됩니다. 이 플래그를 지정하지 않으면 애플리케이션이 인덱스 버퍼의 데이터에 대한 읽기 및 쓰기 작업을 수행한다고 가정합니다.
  • 풀은 인덱스 버퍼에 할당된 메모리 클래스를 지정합니다. D3DPOOL_SYSTEMMEM 플래그는 시스템이 시스템 메모리에 인덱스 버퍼를 생성했음을 나타냅니다.
  • Size 멤버는 꼭짓점 버퍼 데이터의 크기(바이트)를 저장합니다.
  • 마지막 매개 변수 pSharedHandle은 사용되지 않습니다. NULL로 설정합니다.

인덱스 처리 요구 사항

인덱스 처리 작업의 성능은 인덱스 버퍼가 메모리의 어느 위치에 있는지, 그리고 어떤 종류의 렌더링 디바이스가 사용되는지에 크게 좌우됩니다. 애플리케이션은 인덱스 버퍼가 만들어질 때 이에 대한 메모리 할당을 제어합니다. D3DPOOL_SYSTEMMEM 메모리 플래그가 설정되면 인덱스 버퍼가 시스템 메모리에 만들어집니다. D3DPOOL_DEFAULT 메모리 플래그를 사용하는 경우 디바이스 드라이버는 인덱스 버퍼의 메모리가 가장 잘 할당되는 위치를 결정하며, 이를 드라이버 최적 메모리라고도 합니다. 드라이버 최적 메모리는 로컬 비디오 메모리, 비 로컬 비디오 메모리 또는 시스템 메모리일 수 있습니다.

IDirect3DDevice9::CreateIndexBuffer 메서드를 호출할 때 D3DUSAGE_SOFTWAREPROCESSING 동작 플래그를 설정하면 소프트웨어 꼭짓점 처리에 인덱스 버퍼를 사용하도록 지정합니다. 이 플래그는 소프트웨어 꼭짓점 처리를 사용할 때 혼합 모드 꼭짓점 처리(D3DCREATE_MIXED_VERTEXPROCESSING)에 필요합니다.

애플리케이션은 드라이버 최적 메모리에 할당된 인덱스 버퍼에 직접 인덱스를 작성할 수 있습니다. 이 기술은 나중에 중복 사본 작업이 발생하는 것을 방지합니다. 애플리케이션이 인덱스 버퍼에서 데이터를 다시 읽는 경우, 드라이버 최적 메모리의 호스트에서 수행하는 읽기 작업이 매우 느릴 수 있기 때문에 이 기술은 제대로 작동하지 않습니다. 따라서 애플리케이션이 처리 중에 데이터를 읽거나 버퍼에 데이터를 비정상적으로 써야 하는 경우, 시스템 메모리 인덱스 버퍼가 더 낫습니다.

참고

드라이버가 꼭짓점 또는 인덱스 버퍼를 AGP 메모리에 배치할 때 비디오 메모리를 사용하거나 많은 양의 페이지 잠금 RAM을 사용하지 않으려는 경우를 제외하고 항상 D3DPOOL_DEFAULT 사용합니다.

 

인덱스 버퍼 만들기

6개의 매개 변수를 허용하는 IDirect3DDevice9::CreateIndexBuffer 메서드를 호출하여 인덱스 버퍼 개체를 만듭니다.

  • 첫 번째 매개 변수는 인덱스 버퍼 길이(바이트)를 지정합니다.

  • 두 번째 매개 변수는 사용 컨트롤 집합입니다. 무엇보다도 해당 값은 인덱스에 의해 참조되는 꼭짓점이 클리핑 정보를 포함할 수 있는지 여부를 결정합니다. 성능을 향상시키려면 클리핑이 필요하지 않은 경우 D3DUSAGE_DONOTCLIP 지정합니다.

    해당 디바이스에 대해 혼합 모드 또는 소프트웨어 꼭짓점 처리(D3DCREATE_MIXED_VERTEXPROCESSING/D3DCREATE_SOFTWARE_VERTEXPROCESSING)를 사용하도록 설정하면 D3DUSAGE_SOFTWAREPROCESSING 플래그를 설정할 수 있습니다. 혼합 모드에서 소프트웨어 꼭짓점 처리에 버퍼를 사용하려면 D3DUSAGE_SOFTWAREPROCESSING 설정해야 하지만 혼합 모드(D3DCREATE_HARDWARE_VERTEXPROCESSING)에서 하드웨어 인덱스 처리를 사용할 때 최상의 성능을 위해 설정해서는 안 됩니다. 그러나 D3DUSAGE_SOFTWAREPROCESSING 설정은 하드웨어 및 소프트웨어 꼭짓점 처리와 함께 단일 버퍼를 사용하는 유일한 옵션입니다. 혼합 및 소프트웨어 디바이스에는 D3DUSAGE_SOFTWAREPROCESSING 허용됩니다.

    하드웨어에서 인덱스 처리가 수행되는 경우에도 D3DPOOL_SYSTEMMEM 지정하여 꼭짓점 및 인덱스 버퍼를 시스템 메모리에 강제 적용할 수 있습니다. 이는 드라이버가 이러한 버퍼를 AGP 메모리에 배치할 때 지나치게 많은 양의 페이지 잠금 메모리를 방지하는 방법입니다.

  • 세 번째 매개 변수는 각 인덱스의 크기를 지정하는 D3DFORMAT 열거형 형식의 D3DFMT_INDEX16 또는 D3DFMT_INDEX32 멤버입니다.

  • 네 번째 매개 변수는 메모리에서 새 인덱스 버퍼를 배치할 위치를 시스템에 알려주는 D3DPOOL 열거형 형식의 멤버입니다.

  • IDirect3DDevice9::CreateIndexBuffer가 허용하는 마지막 매개 변수는 호출이 성공하면 꼭짓점 버퍼 개체의 새 IDirect3DIndexBuffer9 인터페이스에 대한 포인터로 채워진 변수의 주소입니다.

다음 C++ 코드 예제에서는 코드에서 인덱스 버퍼를 만드는 것이 어떤 모습일지 보여 있습니다.

/*
 * For the purposes of this example, the d3dDevice variable is the 
 * address of an IDirect3DDevice9 interface exposed by a 
 * Direct3DDevice object, g_IB is a variable of type 
 * LPDIRECT3DINDEXBUFFER9.
 */

if( FAILED( d3dDevice->CreateIndexBuffer( 16384 *sizeof(WORD),
           D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, 
           &g_IB, NULL ) ) )
    return E_FAIL;

인덱스 버퍼 액세스

인덱스 버퍼 개체를 사용하면 애플리케이션이 인덱스 데이터에 할당된 메모리에 직접 액세스할 수 있습니다. IDirect3DIndexBuffer9::Lock 메서드를 호출한 다음 필요에 따라 메모리에 액세스하여 버퍼를 새 인덱스 데이터로 채우거나 포함된 데이터를 읽어 인덱스 버퍼 메모리에 대한 포인터를 검색할 수 있습니다. Lock 메서드는 네 개의 매개 변수를 허용합니다. 첫 번째 OffsetToLock은 인덱스 데이터의 오프셋입니다. 두 번째 매개 변수는 인덱스 데이터의 크기(바이트 단위)입니다. IDirect3DIndexBuffer9::Lock 메서드 ppbData에서 허용하는 세 번째 매개 변수는 호출이 성공하면 인덱스 데이터에 대한 포인터로 채워진 BYTE 포인터의 주소입니다.

마지막 매개 변수인 Flags는 메모리를 잠글 방법을 시스템에 알려줍니다. 이를 사용하여 애플리케이션이 버퍼의 데이터에 액세스하는 방법을 나타낼 수 있습니다. 애플리케이션에서 인덱스 데이터에 액세스하는 방식에 따라 Flags 매개 변수에 상수를 지정합니다. 이렇게 하면 드라이버가 메모리를 잠그고 요청된 액세스 유형에 따라 최상의 성능을 제공할 수 있습니다. 애플리케이션이 인덱스 버퍼 메모리에서만 읽는 경우 D3DLOCK_READONLY 플래그를 사용합니다. 이 플래그를 포함하면 Direct3D는 메모리에 대한 액세스가 읽기 전용이라는 점을 감안할 때 내부 절차를 최적화하여 효율성을 향상시킬 수 있습니다.

인덱스 데이터를 채우거나 읽은 후 다음 코드 예제와 같이 IDirect3DIndexBuffer9::Unlock 메서드를 호출합니다.

// This code example assumes the m_pIndexBuffer is a variable of type 
// LPDIRECT3DINDEXBUFFER9 and that g_Indices has been properly 
// initialized with indices.

// To fill the index buffer, you must lock the buffer to gain 
// access to the indices. This mechanism is required because index
// buffers may be in device memory.

VOID* pIndices;

if( FAILED( m_pIndexBuffer->Lock( 
      0,                 // Fill from start of the buffer
      sizeof(g_Indices), // Size of the data to load
      BYTE**)&pIndices,  // Returned index data
      0 ) ) )            // Send default flags to the lock
{
    SAFE_RELEASE(m_pIndexBuffer);
    return E_FAIL;
}

memcpy( pIndices, g_Indices, sizeof(g_Indices) );
m_pIndexBuffer->Unlock();

참고

D3DUSAGE_WRITEONLY 플래그를 사용하여 인덱스 버퍼를 만드는 경우 D3DLOCK_READONLY 잠금 플래그를 사용하지 마세요. 애플리케이션이 인덱스 버퍼 메모리에서만 읽는 경우 D3DLOCK_READONLY 플래그를 사용합니다. 이 플래그를 포함하면 Direct3D는 메모리에 대한 액세스가 읽기 전용이라는 점을 감안할 때 내부 절차를 최적화하여 효율성을 향상시킬 수 있습니다.

IDirect3DIndexBuffer9::Lock 메서드의 Flags 매개 변수에 D3DLOCK_DISCARD 또는 D3DLOCK_NOOVERWRITE 사용하는 방법에 대한 자세한 내용은 성능 최적화(Direct3D 9)를 참조하세요.

 

C++에서는 인덱스 버퍼에 할당된 메모리에 직접 액세스하므로 애플리케이션이 할당된 메모리에 제대로 액세스하는지 확인합니다. 그렇지 않으면 해당 메모리를 잘못 렌더링할 위험이 있습니다. 애플리케이션이 할당된 버퍼의 한 인덱스에서 다른 인덱스로 이동하는 데 사용하는 인덱스 형식의 보폭을 사용합니다.

IDirect3DIndexBuffer9::GetDesc 메서드를 호출하여 인덱스 버퍼에 대한 정보를 검색합니다. 이 메서드는 인덱스 버퍼에 대한 정보로 D3DINDEXBUFFER_DESC 구조체의 멤버를 채웁니다.

Direct3D 리소스

꼭짓점 및 인덱스 버퍼에서 렌더링(Direct3D 9)

꼭짓점 버퍼(Direct3D 9)