Search

'DirectX11 최적화'에 해당되는 글 2건

  1. 2009.11.18 [JumpToDX11-7] 간편해진 리소스 처리.
  2. 2009.11.09 [JumpToDX11-6] 커맨드(Command)...

[JumpToDX11-7] 간편해진 리소스 처리.

DirectX 11 2009. 11. 18. 15:00 Posted by 알 수 없는 사용자


이번 회의 설명을 위해서 API 를 다음과 같이 크게 나누어 보았습니다.

·        Thread unsafe API

·        Thread safe API

·        Free threaded API


Thread unsafe 한 경우에는 멀티스레드들이 동시에 호출할 수 있지만,
이들에 대한 안정성에 대해서는 전혀 보장하지 않습니다.
결과가 갑자기 이상할 수도 있고, 예측 불가능한 상황을 연출할 수도 있습니다.
주로 즉시즉시 상황을 만들어야 할때 사용될 수 있을 것입니다.

Thread safe 한 API 는 어떤 동기화 모델에 의해서 API 가 보호되어집니다.
여러 스레드에서 API 를 호출하더라도, 그들의 안정적인 동작을 보장한다는 의미입니다.
동기화 작업이 별도로 있기 때문에 느려질 수 있다는 단점이 있습니다.

Free threaded 한 API 는 여러 스레드에서 호출을 하더라도,
어떠한 동기화 모델 없이도 API 가 안정적으로 동작한다는 것을 의미합니다.
그렇기 때문에 아주 높은 성능 향상을 얻을 수 있습니다.

< 기존의 리소스 처리 >

멀티스레드 기반의 렌더링으로 가는 첫번째 길은 리소스 부분입니다.
PC 가 발전하면서 성능적으로나 용량적으로 많은 발전을 거듭했습니다.
더블어 게임에서 사용되는 리소스의 용량도 크게 증가했습니다.

멀티스레드 처리가 어느 정도 자리를 잡으면서,
현재 많은 게임들은 이들 리소스에 대한 처리를 별도의 스레드에서 처리하기도 합니다.




일반적인 텍스쳐 로딩 상황을 한번 가정해 보았습니다.
가장 먼저 로더 스레드가 특정한 파일을 읽습니다.
읽어둔 파일을 바탕으로 실제 메모리를 할당하기 위해서는 결국 Device 인터페이스를 통해야 합니다.
DirectX 에서 리소스 관련 메모리를 할당하는 것은
Device 인터페이스를 통해서만 가능하기 때문입니다.
커맨드(Command) 를 생성하는 권한은 오직 Device 인터페이스만이 가지고 있습니다.
( 지난 회를 참고하시기 바랍니다. )

멀티스레드 기반으로 리소스를 로딩하고 있지만,
실제로는 많은 부분이 메인스레드( 여기서는 Render Thread )에 의존하여 작업이 수행되고 있습니다.
리소스를 생성하기 위해서는 반드시 Create, Lock & Unlock 작업이 필요합니다.

< 여기서 잠깐...>
사실 위의 그림의 경우에는 일반적으로 사용되는 구조로 보기 어렵습니다.
그림은 거의 순차적인 처리 구조이기 때문에,
이런 경우라면 굳이 저렇게 사용할 필요가 없습니다.
실제로 많은 게임들은 텍스쳐가 아직 로딩 중이라면,
Default-Material 을 적용해서 폴리곤을 렌더링하도록 구현하기도 합니다.
즉, Render Thread 가 쉴새 없이 계속 커맨드를 생성하는 구조입니다.^^
그리고 위의 예는 간단한 설명을 위한 것입니다.
개발자분들마다 개성 강한 여러 방법들이 존재하시겠죠? ^^

 

 < 간편해진 리소스 관련 커맨드 생성 >

우리가 DirectX 에서 사용하는 대부분의 리소스 작업은 사실 Free Threaded 합니다.
리소스 처리를 위해서 특별한 동기화 처리가 API 레벨에서는 필요하지 않습니다.
( 개발자의 몫입니다. )
그런데 위의 그림처럼 그 동안은 커맨드를 생성해주는 인터페이스가 오직 하나였기 때문에
메인 스레드에 의존해서 처리할 수 밖에 없었습니다.

두번째 시간에 저는 Device와 DeviceContext 에 대해서 설명을 드렸습니다.
기억이 나지 않으시는 분들은 다시 살펴보시기 바랍니다.^^
요약해드리자면, DirectX11 에서는 Free threaded 한 API 와 그렇지 않은 API 들을 분리했습니다.
Free threaded 한 부분에 바로 리소스 처리가 있습니다.
앞서 우리는 Free threaded 의 이점에 대해서 짧게 언급했었습니다.

위의 그림에서,
이제는 Loader therad 는 굳이 메인 스레드( Render thread ) 에 의존하지 않아도,
순차적으로 리소스 관련 커맨드들을 생성시킬 수 있습니다.
커맨드들이 생성되는 순서는 Free threaded 한 경우에는 중요하지 않기 때문에,
빠른 속도로 처리
할 수 있습니다.
특히나, 메인스레드가 별도로 다른 작업을 수행해서 커맨드를 생성시키는 작업이 있다고 해도,
그것과는 별도로 커맨드 생성 작업을 수행할 수 있습니다.
( 커맨드 생성을 위한 대기 시간이 짧아졌다고 할 수 있습니다. )
이로써, 이제는 조금 더 멀티스레딩 형식에 가까워졌다고 할 수 있습니다.

리소스 처리를 이렇게 분리하는 것은
멀티스레드 기반으로 렌더링으로 가는 중요한 기반을 제공
해 주었습니다.

< 다음 회에서는.... >
다음 회부터는 이제 멀티스레드 기반으로 렌더링 관련 커맨드를 생성하는 것을 살펴볼 것입니다.


[JumpToDX11-6] 커맨드(Command)...

DirectX 11 2009. 11. 9. 15:00 Posted by 알 수 없는 사용자


앞서 제 개인적인 판단에 DirectX11 의 큰 특징을 3가지 언급했었습니다.
( 테셀레이션, Compute Shader, Multi-threaded-rendering )
저는 이 세가지 중에서 멀티스레드 기반의 렌더링에 대해서
앞으로의 시간동안 글을 전개해 나갈 생각입니다.


< 커맨드를 생성하는 일 >


혹시 '커맨드(Command)' 라는 개념에 대해서 기억이 나시나요?
기억이 나지 않으신다면,
 [JumpToDX11-2]DeviceContext...넌 누구냣!! 편을 다시 읽어보시기 바랍니다.
요약을 해보자면,
API 를 통한 호출은 결국 하드웨어가 인식할 수 있는 커맨드 형태로 전달되어지게 됩니다.



지난 세대의 DirectX 는 이 모든 처리를 하나의 인터페이스를 통해서 처리했었습니다.
즉, 커맨드를 생성할 수 있는 인터페이스가 오직 하나였습니다.
그리고 그렇게 저장된 커맨드들을 그래픽카드는 순차적으로 실행만 합니다.

이를 멀티스레드 기반으로 처리하기 위해서는 사실 굉장한 노력을 해야합니다.
더 어려운 것은 멀티스레드 기반으로 처리 노력을 기울인다고 해도,
성능 향상에 대한 보장은 장담할 수 없습니다.
일반적으로 로직처리는 멀티스레드 기반으로 분산해서 처리하고는 있지만,
렌더링과 관련된 부분은 이러한 처리가 굉장히 어렵습니다.
( 렌더 스레드의 실행 중간에 렌더링 스테이트가 변하면 문제가 크겠죠? )

그래서 지난 세대의 DirectX 는 이러한 커맨드를 생성하는 부분은
단, 하나의 경로를 통해서만 가능했습니다.
그 동안 우리가 사용했던 IDirect3DDevice9 같은 인터페이스가 바로 이러한 역활을 했었습니다.
이 인터페이스는 실제로 API 를 통해서 하드웨어에게 명령 수행을 지시한다는 의미보다는,
API 를 하드웨어가 이해할 수 있는 커맨드로 변환해 주는 것에 더 가깝습니다.
그리고 그 커맨드를 통해서, 실제로 하드웨어가 실행
을 할 것입니다.

그런데 바로 이 커맨드를 생성하는 일, 누가 해주는 것일까요?
하드웨어가 이해할 수 있는 커맨드들은 드라이버( Driver )가 알고 있습니다.
드라이버는 Core API 나 런타임과 통신을 합니다.

"텍스쳐를 로딩해주세요~"
"메모리를 생성해주세요~"
"렌더링 스테이트를 설정해 주세요~"
"비디오 메모리에 리소스를 바인딩 시켜주세요~"

뭐 이런 식으로 API 를 사용하면,
이들과 관련된 커맨드를 생성하기 위해서 누군가 바쁘게 움직여줘야 할 것입니다.
그것은 바로 'CPU'
겠죠?

실제로 우리가 생성하는 커맨드들 이외에도 처리에 필요하면 커맨드가 더 많이 생성될 수도 있습니다.
예를 들면, 비디오 메모리가 가득찬 상태에서 어떤 리소스를 로드한다면
상황에 맞게 특정 리소스를 비디오 메모리에서 제거해야 합니다.
결국 커맨드들의 실행 중간에,
DirectX 의 리소스 매니져에 이를 요구할 수 있는 커맨드들이 생겨져서 더 붙여질 수도 있습니다.
만약 이런 경우라면, 처리 시간이 더 길어지게 되며,
뒤에 있는 커맨드들의 대기시간도 더 길어지게 됩니다.
전체적으로 작업 시간이 지연되는 것이죠.



< 멀티코어의 시대 >

바야흐로 멀티코어시대의 시대입니다.
이제는 CPU 의 성능적인 발전은 정체되었고,
PC 에 탑재되는 CPU 의 갯수가 성능을 좌우하는 시대입니다.

지금까지의 DirectX 는 싱글코어 기반으로 설계되었다고 지난 회에 언급했었습니다.
CPU 의 성능 발전이 지속적으로 상승 곡선을 그렸다면,
아마 렌더링을 멀티스레드로 할 위험(?)은 피할 수 있었을지도 모릅니다.^^

그 동안 DirectX 팀이 최적화 작업을 한다는 것은
API 호출에 대한 오버헤드를 줄이는 것이 가장 큰 일 중에 하나였습니다.
되도록이면 적은 CPU 사이클을 통해서 커맨드를 실행하게 하려고,
정말이지 많은 노력들을 해왔습니다.

그런데 CPU 가 여러개 탑재되고, GPU 가 발전하면서
놀고 있는 CPU 가 생겨나기 시작했고,
GPU 도 많은 시간을 놀면서 지내기 시작했습니다.
그래서 이들에 대한 활용에 대안으로 등장한 것이 바로
멀티 스레드 기반의 렌더링 작업과 Compute Shader 입니다.
멀티스레드 기반의 렌더링은 CPU 에게 렌더링 작업을 분산시키는 것이고,
Compute Shader 는 GPU 를 CPU 처럼 활용하는 것입니다.

제가 앞으로 언급할 것이 바로 멀티스레드 기반으로 렌더링하는 것입니다.
즉, CPU를 활용하는 것으로 볼 수 있습니다.
앞서 렌더링을 멀티스레드로 하는 것은 굉장히 위험한 일이라고 제가 언급했었는데,
이것이 어떻게 가능하냐구요?
네, 맞습니다.
사실 이것은 틀린 말입니다.
정확히는 커맨드를 멀티스레드 기반으로 생성하는 것이 
바로 멀티스레드 기반의 렌더링의 핵심
입니다.


< 다음 회에는... >
이번 시간에 커맨드에 대한 개념을 확실히 잡으셨는지 모르겠습니다.
다음 회 부터는 멀티스레드여서 행복(?)한 부분들을 하나씩 살펴보겠습니다.^^