CommitChanges() 최적화 질문

2D, 3D, 다각형, 픽셀 등 게임의 그래픽 프로그래밍에 관한 포럼입니다.

Moderator: 류광

Locked
비회원

CommitChanges() 최적화 질문

Post by 비회원 »

아래는 이펙트를 사용하는 간단한 샘플 코드입니다.

Code: Select all

for each EFFECT
{
	e->Begin();

	for each PASS
	{
		e->BeginPass();

		for each OBJECT
		{
			// 현재 오브젝트에 대해 필요한 셰이더 상수 커밋한다.
			e->CommitChanges();

			// 그린다.
		}

		e->EndPass();
	}

	e->End();
}
제 캐릭터 엔진에서는 그리는 것 만큼이나,
그리기 위해 필요한 셰이더 상수를 셋업하는 CommitChanges()에서 제법 심한 병목을 일으킵니다.

여러분들은 CommitChanges() 최적화를 위해 어떤 작업들을 하고 계신가요?

제가 하는 방법은,

1. 기본적으로 이펙트(ID3DXEffect) 및 이펙트 패스를 우선하여 그릴 목록을 정렬한다.
2. ID3DXEffect::Setx 함수를 호출할 때 동일한(유사한) 값이라면 스킵한다.
3. ID3DXEffect::Setx 함수가 실제로 한 번도 호출되지 않았다면 CommitChanges() 자체를 스킵한다.

(3)번은 CommitChanges() 내에서 변화 목록을 관리하고 있기 때문에 안 해줘도 무방할 것 같구요.
(2)번의 경우 캐릭터 셰이더가 사용하는 대부분의 상수 레지스터가 매트릭스 팔레트이기 때문에 스킵될 확률이 낮은 편입니다.
(1)번이야 기본으로 하는 거고..

마땅히 좋은 아이디어가 떠오르지 않는데, 다른 분들은 이 문제를 어떻게 해결하고 계신지 궁금합니다. ^^:
zupet
Posts: 2764
Joined: 2003-05-13 03:34
Location: NCSOFT LE팀

Re: CommitChanges() 최적화 질문

Post by zupet »

안녕하세요. 매크로 없는 메비~랍니다.


최근 제가 접근중인 방법을 몇가지 적어보겠습니다.

ID3DXEffect::BeginParameterBlock() ~ ID3DXEffect::EndParameterBlock() 은 앞에 언급하신 내용과 직접적인 관계는 좀 떨어지지만 나름대로 유용하게 쓰고 있습니다. 일반적으로 하나의 이펙트에서 텍스쳐나 파라메터를 바꿔서 여러가지 매터리얼이 만들어지고 메터리얼 하나로 여러개의 인스턴스를 찍어주는데 각각 매터리얼별로 Parameter Block 을 만들어서 쓰고 있습니다.

얼마전 여기 언급했던 ID3DXEffectStateManager 코드도 작성해 봤습니다만 ID3DXEffect 내부에서 State Block 을 같이 사용하기 때문에 문제가 복잡해지더군요. 어쨌거나 전역으로 State Manager 를 만들어서 모든 Effect 들이 중복되는 RenderState, Sampler State, VS Constant, PS Constant 를 거르게 만들어 봤지만 성능 향상이 전혀 없었기 때문에 특별한 이유가 생기기 전에는 사용하지 않을 예정입니다. (테스트 방법이 좀 틀린 것 같지만 일단 제 렌더링은 StateManager 없이도 Batch Count 가 Draw Count 랑 거의 비슷하기 때문에 특별히 좋아질 것 같진 않습니다.)

그리고 좀 엉뚱한 짓이지만 Skinning 을 CPU 에서 처리하도록 하고 있습니다. 2006년도 테스트 했던 경험으로는 100개의 캐릭터를 동시에 찍었을때 skinning 을 적용했을때와 애니메이션 자체를 끄고 그냥 world matrix 하나만으로 심플하게 출력했을때 속도가 3배정도 났었습니다. 게시물을 작성하신분도 시간이 나실때 쉐이더를 살짝 고쳐서 skinng 없이 일반 mesh 같이 world matrix 하나만으로 화면에 렌더링을 해보시기 바랍니다.

예전에 5번에 나눠그리는 캐릭터 100마리를 화면에 띄웠을때 그냥 world matrix 로 렌더링 한 것과 속도가 3배쯤 차이가 나서 nVIDIA 에 문의를 했었지만 제대로된 답변은 돌아오지 않았습니다. (본 줄이고 DP를 줄여라 정도?) 게다가 CPU Skinning 을 하면 bone 개수 제한이 없어지기 때문에 같은 material 은 모두 한방에 렌더링이 가능해져서 DP 횟수도 줄어드는 장점이 있죠.

전체 렌더링 속도가 1/3로 떨어지는 것과 CPU로 스키닝을 하는 것.. 일단 후자가 프로그래머에게 더 많은 제어권을 주기 때문에 선택한 방법입니다. 질문자분 익히 아시겠지만 일단 D3D 단에 부하가 걸려버리면 어떠한 해결방법이 없습니다. 게다가 아직 SSE 와 듀얼코어가 남아 있으니... 부하가 커지면 미친척 2 * 2 쯤으로 속도를 늘릴 수 있다고 멋대로 기대하고 있습니다. ^_^
Last edited by zupet on 2008-03-23 01:44, edited 1 time in total.
express8
Posts: 253
Joined: 2005-05-19 13:31
Location: eppengine
Contact:

Post by express8 »

shared 는 최대한 모아서 한번에 하기.. 정도가 더 있겠네요.
차세대 멀티플랫폼 게임엔진 eppengine
(피바다 엔진3.0 )

http://www.eppengine.com
Locked