modern gpu optimize blog

60
Modern GPU Optimize In DirectX 9 http://ozlael.egloos.com 사실은 GPU 프로그래밍 가이드 문서 정리 ATI Radeon HD 2000 programming guide GPU Programming Guide GeForce 8 and 9 Series

Upload: ozlael-ozlael

Post on 07-Jul-2015

2.459 views

Category:

Documents


3 download

DESCRIPTION

Modern gpu optimize directx9

TRANSCRIPT

Page 1: Modern gpu optimize blog

Modern GPU

OptimizeIn

DirectX 9

http://ozlael.egloos.com

사실은 GPU 프로그래밍 가이드 문서 정리ATI Radeon HD 2000 programming guide

GPU Programming Guide GeForce 8 and 9 Series

Page 2: Modern gpu optimize blog

Modern GPU

OptimizeIn

DirectX 9

현대의 H/W의 기준 이야기이므로 석기시대의 H/W에서는 역효과인 것도 존재

이미지 출처 : ndc11

Page 3: Modern gpu optimize blog

Modern GPU

OptimizeIn

DirectX 9

열린글도 아니고 DX10도 아니고 DX11도 아니고...

Page 4: Modern gpu optimize blog

병목 측정API OverheadVertex ProcessingShadersTextureETC

Page 5: Modern gpu optimize blog

병목 측정

병목을 찾기 위해서는 정확한 측정 환경 필요

이미지 출처 : http://www.hellodd.com

Page 6: Modern gpu optimize blog

병목 측정

DirectX retail runtime DirectX 최종 version

어플리케이션 release versions

디스플레이 컨트롤 패널 기본 값 Anisotropic filtering, Anti aliasing, Vertical sync

평균 값으로 벤치마킹

타겟 하드웨어에서 실행 하드웨어마다 병목이 다름

Page 7: Modern gpu optimize blog

병목 측정

DirectX retail runtime DirectX 최종 version

어플리케이션 release versions

디스플레이 컨트롤 패널 기본 값 Anisotropic filtering, Anti aliasing, Vertical sync

평균 값으로 벤치마킹

타겟 하드웨어에서 실행 하드웨어마다 병목이 다름

심지어 프레임 마다도 바뀜

병목을 찾는다 =현 시나리오에서의 병목을 찾는다

Page 8: Modern gpu optimize blog

병목 측정

간단한 테스트

Page 9: Modern gpu optimize blog

병목 측정

CPU 스피드를 낮춰서 돌려본다.

속도가 저하되면 CPU limited

Page 10: Modern gpu optimize blog

병목 측정

GPU 코어 클럭을 낮춰서 돌려본다.

속도가 저하되면 Shader Limited

Vertex ShaderPixel ShaderRasterization

Page 11: Modern gpu optimize blog

병목 측정

GPU 메모리 클럭을 낮춰서 돌려본다.

속도가 저하되면 Bandwidth Limited

TextureFrame buffer

Page 12: Modern gpu optimize blog

병목 측정

PerfHUD

이미지 출처 : PurfHUD6 UserGuide

Page 13: Modern gpu optimize blog

병목 측정

Ctrl + T: 텍스쳐 유닛을 고립. 2x2 사이즈로 바꾸어 텍스쳐 대역폭 제한인지 확인

Ctrl + V: 버텍스 유닛을 고립. 버텍스 트랜스폼, CPU 워크로드, 버스 트랜잭션 제한인지 확인

Ctrl + N: GPU 제거 모든 DP calls을 무시하여 로직 오버헤드인지 확인

Page 14: Modern gpu optimize blog

병목 측정

타이밍 그래프

Driver Time (ms) CPU가 처리한 드라이버 코드 시간. Driver Sleeping 포함.GPU Idle (ms) GPU가 idle였던 시간.Driver Sleeping (ms) 드라이버가 GPU를 위해 기다린 시간

이미지 출처 : PurfHUD6 UserGuide

Page 15: Modern gpu optimize blog

병목 측정

CPU

GPU

Push Buffer Queue

command command command

Q :드라이버가 GPU를 기다리는 이유 ?

command command

command

command

Page 16: Modern gpu optimize blog

병목 측정

CPU

GPU

Push Buffer Queue

command command

A :요게 꽉 차서

command

command

command command command

* Lock(): 은 Push Buffer가 비워지길 기다림

Page 17: Modern gpu optimize blog

병목 측정

이미지 출처 : http://www.patsnap.com/patents/view/US7773090.html

Page 18: Modern gpu optimize blog

병목 측정

Driver Sleeping이 높다면 CPU의 할 일을 추가해도 FPS가 줄지 않을 것. Driver Sleeping이 적당하지 않다면 GPU 로드를 가볍게 하기 위해 장변의 복잡도를 줄여야 함.

GPU Idle이 존재한다면 GPU로 데이터를 보내지 않고 있는 경우 발생.

컬링, 물리, 로직, AI

Page 19: Modern gpu optimize blog

병목 측정

Driver Time과 Frame Time이 같이 튄다면, 드라이버가 텍스쳐 등을 CPU에서 GPU로 업로딩 중..

Driver Time은 정상이고 Frame Time만 튄다면, CPU가 빡신 일 하던가, 하드를 긁거나, OS가 딴짓 하거나..

Driver Time과 Frame Time의 차이가 크다면, CPU 의존적

Page 20: Modern gpu optimize blog

병목 측정

프레임 프로파일러

Page 21: Modern gpu optimize blog

병목 측정

PerfStudio

이미지 출처 : http://developer.amd.com/

Page 22: Modern gpu optimize blog

병목 측정

PIX

이미지 출처 : http://mynameismjp.wordpress.com/

Page 23: Modern gpu optimize blog

API Overhead 는 CPU 병목

이미지 출처 : http://blog.naver.com/seiclub

Page 24: Modern gpu optimize blog

API Overhead

배치를 줄이자

Page 25: Modern gpu optimize blog

상태 및 상수 변화를 줄일 것.

필요치 않을 시 상태를 재 설정 하지 말 것.

셰이더 상수를 개개로 많이 설정 하는 것 보다는 그룹으로 한번에.

API Overhead

Page 26: Modern gpu optimize blog

텍스쳐 아틀라스 여러 텍스쳐를 하나로 묶어서 상태 변화 및 call 절약

이미지 출처 : http://www.gamasutra.com/view/feature/2530/practical_texture_atlases.php

API Overhead

Page 27: Modern gpu optimize blog

인스턴싱 여러 DP call을 하나의 DP call로 합침

이미지 출처 : http://http.developer.nvidia.com/GPUGems2, http://blog.csdn.net/

API Overhead

Page 28: Modern gpu optimize blog

Vertex Processing

이미지 출처 : http://blog.naver.com/seiclub

Indexed Primitive 사용.

버텍스 캐시 성능을 위해 ID3DXMesh Optimize() 사용.

Attribute 병목 제거 (input assembly)

Page 29: Modern gpu optimize blog

Vertex Processing

Attribute 병목이 뭐야 ?

Page 30: Modern gpu optimize blog

Vertex Processing

Setup 시 각 버텍스의 float 데이터를 버텍스 스트림과 오프셋 정보에 기반하여 비디오 메모리의 적절한 위치에서 가져옴.

Setup : single data chunk에 assembled vertex를 설정

Page 31: Modern gpu optimize blog

Vertex Processing

Setup 시 각 버텍스의 float 데이터를 버텍스 스트림과 오프셋 정보에 기반하여 비디오 메모리의 적절한 위치에서 가져옴.

Setup : single data chunk에 assembled vertex를 설정

Attribute한 싸이클 내 처리양이 정해져 있음.

Page 32: Modern gpu optimize blog

Vertex Processing

Attribute 병목 탐지

버텍스 선언의 사이즈 늘림 : 셰이더 코드를 변경하지 말고 더미 데이터만 추가

버텍스 선언의 사이즈 줄임 : 셰이더 로직이 변경되지 않게 주의. 셰이더 바운드와 겹치면 시ㅋ망ㅋ

Page 33: Modern gpu optimize blog

Vertex Processing

Attribute 병목 해결

미 사용 Attribute 제거 : ex> 포지션으로 float4를 사용하지만 w 속성을 사용 안하는 경우

하나의 벡터에 그룹화: ex> 텍스쳐 좌표 float2 두개를 하나의 float4에 담기

Attribute 재 연산: ex> 노말과 탄젠트만 데이터에 담고 바이노말은 셰이더에서 재 연산

Page 34: Modern gpu optimize blog

Shaders

최신 셰이더 모델 사용:석기 시대에는 낮은 버젼을 사용 하는 것이 미덕이였으나,통합(Unified) 모델 이후부터는 최신 버젼을 권장

SM 2 SM 3

최신 버젼의 fxc 사용: 최적화

Page 35: Modern gpu optimize blog

Shaders

낮은 정밀도 사용: 위치 등 고 정밀 연산은 float. 색상 등의 연산은 half로도 충분

필요시에만 Uniform 파라미터: 런타임 동안 변하지 않는 값은 const 키워드로 사용

Uniform 파라미터 접기: Ex > return tex2d( sampler, uv) * g_color * 3.0f;

애초에 3.0을 곱해서 셋팅

Page 36: Modern gpu optimize blog

Shaders

대수학 사용

연산 최적화

Page 37: Modern gpu optimize blog

Shaders

대수학 사용

연산 최적화

노말라이즈가 딱 !

Page 38: Modern gpu optimize blog

Shaders

범용 함수 남발 금지

float3 reflect(float3 I, float3 N) { Return ( 2 * dot(I,N) / dot(N,N) ) * N – I;}

Page 39: Modern gpu optimize blog

Shaders

단위 벡터의 길이를 구하지 않도록

범용 함수 남발 금지

float3 reflect(float3 I, float3 N) { Return ( 2 * dot(I,N) / dot(N,N) ) * N – I;}

2 * dot(I,N) * N - I

노말라이즈가 딱 !

Page 40: Modern gpu optimize blog

Shaders

병렬 코드 사용

float x = a + b + c + d;

float x = ( a + b ) + ( c + d );

== ?

Page 41: Modern gpu optimize blog

Shaders

병렬 코드 사용

float x = a + b + c + d;

float x = ( a + b ) + ( c + d );

! =

3 operation

2 operation

Page 42: Modern gpu optimize blog

Shaders

타입 혼용 금지

int4 main(int4 a: TEXCOORD){ return a + 1.0f;}

== ?

int4 main(int4 a: TEXCOORD){ return a + 1;}

Page 43: Modern gpu optimize blog

Shaders

타입 혼용 금지

int4 main(int4 a: TEXCOORD){ return a + 1.0f;}

int4 main(int4 a: TEXCOORD){ return a + 1;}

! =

타입 캐스팅을 위한 추가 연산

Page 44: Modern gpu optimize blog

Shaders

스탠다드 라이브러리 함수: Ex > 벡터와 매트릭스의 곱은 mul().

어드레싱 직접 구현 금지: saturate()대신 D3DTADDRESS_CLAMP

적절한 타입 사용: tex2d()가 float4 리턴한다고 해서 꼭 float4로 사용 할 필요 없음

Page 45: Modern gpu optimize blog

Shaders

픽셀 셰이더 병목

Early Z: 한 패스를 추가하여 깊이만을 먼저 그려서 은면의 비싼 연산 방지

Front to Back 정렬: 앞의 오브젝트에 의해 가려지는 픽셀의 오버드로우 방지

지연 랜더: 보이는 픽셀만 라이팅 연산

스카이 박스를 마지막에: 대부분의 스카이는 가려지므로 최후에 랜더하여 픽셀 연산 및 대역폭 절약

Page 46: Modern gpu optimize blog

Shaders

PS 연산의 VS로 이동

픽셀 셰이더의 연산은 비싸다. 그러므로, 선형 보간으로 가능 한 연산은 무조건 버텍스 셰이더에서 연산하고 픽셀 셰이더로 넘겨줘라!

Page 47: Modern gpu optimize blog

Shaders

PS 연산의 VS로 이동

그건 옛날 이야기!요즘은 셰이더 연산이 짱 쎄서 오히려버텍스 캐시 퍼포먼스나 어트리뷰트 병목이방해가 될 수 있다구요!밸런스를 잘 판단하고 사용해야되욧!

픽셀 셰이더의 연산은 비싸다. 그러므로, 선형 보간으로 가능 한 연산은 무조건 버텍스 셰이더에서 연산하고 픽셀 셰이더로 넘겨줘라!

Page 48: Modern gpu optimize blog

Shaders

PS 연산의 VS로 이동

VS:Out.position = mul(mvp, In.vertex);Out.lightVec = lightPos - In.vertex.xyz;Out.viewVec = camPos – In.vertex.xyz;

VS:Out.position = mul(mvp, In.vertex);Out.vertex = In.vertex.xyz;

PS:float3 lightVec = lightPos – In.vertex;float3 viewVec = camPos – In.vertex;

Page 49: Modern gpu optimize blog

Shaders

Vertex Texture Fatch: VTF를 죄악으로 여기던 시절은 지남.통합 셰이더 모델에서는 VTF가 느리지 않음.

GPU gems 3

NDC11, VPPF

Page 50: Modern gpu optimize blog

Shaders

통합 셰이더( Unified Shader) 모델

이미지 출처 : PurfHUD6 UserGuide

Page 51: Modern gpu optimize blog

Shaders

이미지 출처 : PurfHUD6 UserGuide

DX10을 지원하기 위한 아키텍쳐모든 셰이더 타입이 같은 하드웨어 유닛을 사용GPU가 셰이더 로드 밸런싱을 조절

Page 52: Modern gpu optimize blog

Shaders

현대의 GPU는 다이나믹 브랜치의 퍼포먼스가 우왕ㅋ굿이를 이용하여 성능 향상을 볼 수 있음

ex> -라이팅 연산이 필요 없는 그림자 영역은 연산을 건너 뜀-N dot L 이 0 이하면 스페큘라 연산 건너 뜀

동적 분기

Page 53: Modern gpu optimize blog

Shaders

주의점:

최소 64개의 버텍스 또는 픽셀(8x8)이 연속적이어야 함.아니면 오히려 성능 저하를 초래 할 수도 있음

ex> -라이팅 연산이 필요 없는 그림자 영역은 연산을 건너 뜀-N dot L 이 0 이하면 스페큘라 연산 건너 뜀

고 주파 노말맵에는 부적합

넓은 범위가 아닐 경우는 부적합

Page 54: Modern gpu optimize blog

Shaders

동적 분기의 성능을 활용여러 매터리얼의 처리를 한 셰이더로 몰아넣어셰이더 설정 비용을 줄임.

셰이더가 길어지면 셰이더 캐시 문제가 발생 할 수도 있음

Uber-shaders

Page 55: Modern gpu optimize blog

Shaders

라이팅 등 복잡한 연산을 텍스쳐에 미리 그려넣어 사용

텍스쳐 룩업

Tera StarWars : The Old Republic

log(), exp()로등은 마이크로 인스트럭션이므로 그냥 사용 해도 됨

Page 56: Modern gpu optimize blog

Texture

밉맵 사용

비싼 필터링은 필요 시만 사용

• Trilinear • Anisotropic • Wide texture formats • Volume • Cubemap • Texture projection

Bilinear의 두배

Max anisotropic 만큼 느림

Page 57: Modern gpu optimize blog

Texture

RGBA8예전 세대의 하드웨어는 한 싸이클에 32bit 처리

RGBA16F요즘 세대의 하드웨어는 한 싸이클에 64bit 처리

Fixed poinf RGBA16은 여전히 두 싸이클

Page 58: Modern gpu optimize blog

ETC

clear()석기 시대에는 clear()를 건너 뛰는 것이 트릭 중 하나였음.하지만, 현대의 하드웨어에서는 항상 클리어 되어야 함.

풀 스크린 쿼드 시에는 불필요.

nVIDIA : Hyper ZATI : Fine-grained Z

Page 59: Modern gpu optimize blog

ETC

메모리 할당

다음과 같은 순위로 메모리 할당

1. 랜더타겟 pitch ( 폭 X 픽셀비트 ) 에 의한 정렬로 할당2. 셰이더 생성3. 남은 텍스쳐 로드

Page 60: Modern gpu optimize blog

To be continue :벤더 의존적인 최적화 기법