[kgc2014] dx9에서dx11로의이행경험공유

93
DirectX9에서 DirectX11 으로의 이행 경험 공유 민환 CyberConnect2 / 기술개발실

Upload: hwan-min

Post on 12-Jul-2015

541 views

Category:

Engineering


3 download

TRANSCRIPT

Page 1: [KGC2014] DX9에서DX11로의이행경험공유

DirectX9에서 DirectX11으로의 이행 경험 공유

민 환

CyberConnect2 / 기술개발실

Page 2: [KGC2014] DX9에서DX11로의이행경험공유

세션에서 다루는 내용• CyberConnect2의 DirectX11엔진 이야기

• DirectX11 API설계

• 게임 내용, 최신 테크닉은 다루지 않습니다

세션의 대상• DirectX9세대의 Graphics API를 사용해 본 적이 있는 분

• 앞으로 DirectX11를 사용하실 분

세션 개요

Page 3: [KGC2014] DX9에서DX11로의이행경험공유

Company

CyberConnect2

福岡県福岡市博多区博多駅前1丁目

東京都品川区大井1丁目

1996年 2月 16日

본사134명 동경25명

40,000,000 円

가정용 게임소프트의 제작 및 개발

회사명

본사

동경지사

설립일

사원수

자본금

사업내용

Page 4: [KGC2014] DX9에서DX11로의이행경험공유

Company

NARUTO SHIPPUDEN™: Ultimate Ninja® STORM Revolutiongame software ©2014 BANDAI NAMCO Games Inc.NARUTO artwork and elements © 2002 MASASHI KISHIMOTO / 2007 SHIPPUDEN All Rights Reserved.©Drecom Co., Ltd. powered by CyberConnect2 Co., Ltd.

.hack series NARUTO SHIPPUDENseries

JoJo's Bizarre AdventureAll Star Battle

Page 5: [KGC2014] DX9에서DX11로의이행경험공유

• CyberConnect2 기술개발실

• Engine Programmer

• 현재 내부 엔진 제작중

[email protected]

Speaker

Page 6: [KGC2014] DX9에서DX11로의이행경험공유

Engine 소개

이행시 주의점• DirectX11 변경점

• Constant Buffer

• VertexInputLayout

• State Management

• Multithread

• Shader

• Etc.

결론

Contents

Page 7: [KGC2014] DX9에서DX11로의이행경험공유

Engine 소개

이행시 주의점• DirectX11 변경점

• Constant Buffer

• VertexInputLayout

• State Management

• Multithread

• Shader

• Etc.

결론

Contents

Page 8: [KGC2014] DX9에서DX11로의이행경험공유

History

2013년 3월부터 내부엔진 제작 시작

3~4명으로 제작중

Engine 소개

Page 9: [KGC2014] DX9에서DX11로의이행경험공유

방향성

멀티 플랫폼, 멀티 코어 대응• 기본적으로 Windows, PlayStation4, XBOX ONE 대응

• 멀티코어를 고려한 설계

Engine 규모• 프로젝트 규모상 상용엔진 수준은 무리

• 필요한 기능만 최소한으로 제작중

Engine 소개

Page 10: [KGC2014] DX9에서DX11로의이행경험공유

방향성

기능• 최소한 지금까지 가능했던 일은 구현 가능하도록 설계

• 기존 엔진에서 불편했던 부분은 개선, 좋았던 부분은 채용, 가능하면코드 재사용

차세대 대비• 차세대를 준비하기 위한 최소한의 환경 구축

Engine 소개

Page 11: [KGC2014] DX9에서DX11로의이행경험공유

제작 이유

기존 엔진의 문제점• PlayStation2 시절의 낡은 설계

• 리소스 파이프라인에 불필요한 작업이 많았음

• 부족한 기능을 구현하기 위해 game에서 억지로 구현한 부분이 점차많아지기 시작함

• 외부 엔진이라 대응이 늦거나 불가능한 일이 잦았음

콘솔 개발킷의 부족• 기존 엔진 및 각종 툴이 콘솔기기에서 밖에 동작하지 않아 콘솔 개

발킷이 없으면 디버깅이 불가능

• Windows에서 개발하고 싶다는 요청이 많아짐

Engine 소개

Page 12: [KGC2014] DX9에서DX11로의이행경험공유

제작 이유

내부 기술력 강화• 외부 엔진만 사용해서는 노하우 쌓기가 쉽지 않다고 판단

차세대기로 갈아타기 위한 좋은 타이밍• 차세대기 발매

• 하드웨어의 진화

• 지금까지의 설계로는 하드웨어의 스펙을 전부 활용하기 힘들어짐

Engine 소개

Page 13: [KGC2014] DX9에서DX11로의이행경험공유

Engine 소개

Page 14: [KGC2014] DX9에서DX11로의이행경험공유

Engine 소개

Page 15: [KGC2014] DX9에서DX11로의이행경험공유

구성

Engine 소개

기본적으로 C++라이브러리

콘솔 툴은 python이 많음

기타 툴은 C++, 일부는 C#검토중

Page 16: [KGC2014] DX9에서DX11로의이행경험공유

구성

Engine 소개

CoreEffect

AnimationParticle

Rendering

60%

MathMemory

FileThread

System

90%

ExporterResource manager

Parameter -Configuration

Tool

20%

Page 17: [KGC2014] DX9에서DX11로의이행경험공유

CoreEffect

AnimationParticle

Rendering

60%

MathMemory

FileThread

System

90%

ExporterResource manager

Parameter –Configuration

Tool

20%

구성

Engine 소개

오늘의 주제

Page 18: [KGC2014] DX9에서DX11로의이행경험공유

Rendering Core

Multithread 대응 구조

각 플랫폼의 저레벨API 추상화• 차후 대응 플랫폼 추가를 고려하여 설계

DirectX11 기반

Engine 소개

Page 19: [KGC2014] DX9에서DX11로의이행경험공유

Engine 소개

이행시 주의점• DirectX11 변경점

• Constant Buffer

• VertexInputLayout

• State Management

• Multithread

• Shader

• Etc.

결론

Contents

Page 20: [KGC2014] DX9에서DX11로의이행경험공유

DirectX11변경점

고정 파이프라인 삭제

Device 분리

CAPS비트 삭제

새로운 shader stage 추가

Multithread Rendering

Dynamic Shader Linkage

Tesselation, OIT

BC6, BC7 texture format

Etc.

Page 21: [KGC2014] DX9에서DX11로의이행경험공유

DirectX11변경점

이 중 DirectX11 을 사용하여 rendering하기 위해 반드시 필요한 부분을 DirectX9과 비교

독자적으로 대응한 방법에 대한 소개도 있습니다만 정답은아니므로 어디까지나 참고

Page 22: [KGC2014] DX9에서DX11로의이행경험공유

Device 분리

DirectX11변경점

DirectX9의 IDirect3DDevice9 은 DirectX11에서부터 ID3D11Device 와ID3D11DeviceContext 로 분리되었음

ID3D11Device은 주로 resource 생성을 담당• thread-safe

ID3D11DeviceContext은 주로 rendering을 담당• thread-unsafe

자료 소스코드 중 pDevice 는 IDirect3DDevice9, pImmediateContext 은ID3D11DeviceContext 의 객체이므로 참고

Page 23: [KGC2014] DX9에서DX11로의이행경험공유

Engine 소개

이행시 주의점• DirectX11 변경점

• Constant Buffer

• VertexInputLayout

• State Management

• Multithread

• Shader

• Etc.

결론

Contents

Page 24: [KGC2014] DX9에서DX11로의이행경험공유

Constant Buffer?

Constant Buffer

DirectX10부터 추가된 shader parameter 설정을 위한 버퍼

DirectX9에서는 개별적으로 설정했지만 DirectX11에서는 버퍼 단위의 오브젝트로 변경

DirectX11에서 shader 에 값을 전달하기 위해 반드시 필요

Page 25: [KGC2014] DX9에서DX11로의이행경험공유

DirectX9

Constant Buffer

HLSL(sm3.0)까지의 shader 변수정의

• C++ global variable 처럼 정의

float3 g_vLightPos;

float3 g_vLightDir;

float4x4 g_mView;

float4x4 g_mProj;

float4x4 g_mWorld;

float4x4 g_mBone[128];

float4 g_vMaterial;

HLSL

Page 26: [KGC2014] DX9에서DX11로의이행경험공유

DirectX9

Constant Buffer

Parameter 전달 방법• Set[datatype](“variable”, &data)

float3 g_vLightPos;

float3 g_vLightDir;

float4x4 g_mView;

float4x4 g_mProj;

float4x4 g_mWorld;

float4x4 g_mBone[128];

float4 g_vMaterial;

SetMatrix("g_mWorld",&worldMatrix);

Application

SetVector("g_vLightPos",&lightPos);

HLSL

Page 27: [KGC2014] DX9에서DX11로의이행경험공유

DirectX11

Constant Buffer

cbuffer키워드 안에 변수를 묶어서 정의. C언어의 구조체와 비슷한 형태

선언 뒤에 바인드될 레지스터의 번호를 설정. 16번까지 설정 가능- 설정하지 않을 경우, 0번부터 차례대로 부여됨

cbuffer CB : register(b0)

{

float3 vLightPos;

float3 vLightDir;

float4x4 mView;

float4x4 mProj;

float4x4 mWorld;

float4x4 mBone[128];

float4 vMaterial;

};

HLSL

Page 28: [KGC2014] DX9에서DX11로의이행경험공유

DirectX11

Constant Buffer

1. CreateBuffer로 constant buffer용 버퍼 생성

2. UpdateSubresource(Map)로 버퍼의 내용을 update• 한번의 update로 constant buffer 내용 전부를 덮어씌우므로 주의

3. XXSetconstantBuffers로 레지스터에 바인드ex) VSSetConstantBuffers, PSSetConstantBuffer 등

Page 29: [KGC2014] DX9에서DX11로의이행경험공유

주의점

Constant Buffer

update 사이즈와 호출회수를 최대한으로 줄여야 함• 성능 저하에 민감함

가장 실수하기 쉬운 부분

world matrix만 덮어씌워도

8424bytes update해야함

cbuffer CB : register(b0)

{

float3 vLightPos;

float3 vLightDir;

float4x4 mView;

float4x4 mProj;

float4x4 mWorld;

float4x4 mBone[128];

float4 vMaterial;

};

HLSL

Page 30: [KGC2014] DX9에서DX11로의이행경험공유

Constant Buffer

shader로 전달할 데이터 크기 이상의 constant buffer 를update 하는 것은 잘못된 설계

필요한 부분만 update 할 수 있도록 constant buffer 를 나누어 설계. update 빈도에 따라 나누길 추천

한 번 update 한 constant buffer는 최대한 돌려쓰거나 모아서 rendering

Page 31: [KGC2014] DX9에서DX11로의이행경험공유

Global

Constant Buffer

cbuffer CB : register(b0)

{

float3 vLightPos;

float3 vLightDir;

float4x4 mView;

float4x4 mProj;

float4x4 mWorld;

float4x4 mBone[128];

float4 vMaterial;

};

HLSLApplication

Camera

Object

Material

Page 32: [KGC2014] DX9에서DX11로의이행경험공유

Camera

Global

Constant Buffer

cbuffer CB : register(b0)

{

float3 vLightPos;

float3 vLightDir;

float4x4 mView;

float4x4 mProj;

float4x4 mWorld;

float4x4 mBone[128];

float4 vMaterial;

};

HLSLApplication

25272bytes

8424bytesObject

Material

Material

Material

Page 33: [KGC2014] DX9에서DX11로의이행경험공유

Constant Buffer

cbuffer perGlobalCB : register(b0)

{

float3 vLightPos;

float3 vLightDir;

};

cbuffer perCameraCB : register(b1)

{

float4x4 mView;

float4x4 mProj;

};

cbuffer perObjectCB : register(b2)

{

float4x4 mWorld;

float4x4 mBone[128];

};

cbuffer perMaterialCB : register(b3)

{

float4 vMaterial;

};

HLSLApplication

128bytes

24bytes

8256bytes

16bytes

8456bytes

Camera

Global

Object

Material

Material

Material

Page 34: [KGC2014] DX9에서DX11로의이행경험공유

Constant Buffer

처음부터 constant buffer의update 빈도에 따라 sorting하여 rendering 할 수 있도록 설계 하는 것이 중요

내부 엔진에서는 다음의 4개의 빈도로 나누어서 설계- Global

- Camera

- Object

- Material

Camera

Global

Object

Material

Object

Material

Material

Camera

Object

Material

Page 35: [KGC2014] DX9에서DX11로의이행경험공유

Engine 소개

이행시 주의점• DirectX11 변경점

• Constant Buffer

• VertexInputLayout

• State Management

• Multithread

• Shader

• Etc.

결론

Contents

Page 36: [KGC2014] DX9에서DX11로의이행경험공유

VertexInputLayout

VertexInputLayout?

vertex buffer가 어떤 내용으로 구성되어 있는지 GPU에 알려주기 위한 DirectX11 오브젝트

DirectX9의 IDirect3DVertexDeclaration9과 비슷

Page 37: [KGC2014] DX9에서DX11로의이행경험공유

VertexInputLayout

GPU

?

1.0f 1.0f 1.0f 1.0f 1.0f 1.0f 1.0fvertex buffer

Page 38: [KGC2014] DX9에서DX11로의이행경험공유

DirectX9

VertexInputLayout

D3DVERTEXELEMENT9 decl[] =

{

{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },

{ 0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },

D3DDECL_END()

};

pd3dDevice->CreateVertexDeclaration(decl, &pVertexDeclaration);

pd3dDevice->SetVertexDeclaration(pVertexDeclaration);

1.0f 1.0f 1.0f 1.0f 1.0f 1.0f 1.0fvertex buffer

position color

Page 39: [KGC2014] DX9에서DX11로의이행경험공유

DirectX11

VertexInputLayout

D3D11_INPUT_ELEMENT_DESC decl[] =

{

{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},

{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},

};

UINT numElements = ARRAYSIZE( layout );

pd3dDevice->CreateInputLayout( decl, numElements, pVSBlob->GetBufferPointer(),

pVSBlob->GetBufferSize(), &pVertexLayout );

pImmediateContext->IASetInputLayout( pVertexLayout );

1.0f 1.0f 1.0f 1.0f 1.0f 1.0f 1.0fvertex buffer

position color

Page 40: [KGC2014] DX9에서DX11로의이행경험공유

VertexInputLayout

HRESULT CreateInputLayout([in] const D3D11_INPUT_ELEMENT_DESC *pInputElementDescs,[in] UINT NumElements,[in] const void *pShaderBytecodeWithInputSignature,[in] SIZE_T BytecodeLength,[out] ID3D11InputLayout **ppInputLayout

);

pShaderBytecodeWithInputSignature [in] voidA pointer to the compiled shader. The compiled shader code contains a input signature which is validated against the array of elements.

BytecodeLength [in] SIZE_TSize of the compiled shader.

Page 41: [KGC2014] DX9에서DX11로의이행경험공유

VertexInputLayout

CreateInputLayout 에서 D3D11_INPUT_ELEMENT_DESC과 vertex shader semantic 의 매칭이 이루어짐

구조가 일치할 경우 success, 불일치할 경우 fail

Page 42: [KGC2014] DX9에서DX11로의이행경험공유

VertexInputLayout

vertex buffer position color

CreateInputLayout 성공

D3D11_INPUT_ELEMENT_DESC decl[] =

{

{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},

{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},

};

struct VS_INPUT

{

float3 position : POSITION;

float4 color : COLOR0;

};

HLSL

Page 43: [KGC2014] DX9에서DX11로의이행경험공유

VertexInputLayout

CreateInputLayout 실패

D3D11_INPUT_ELEMENT_DESC decl[] =

{

{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},

{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},

};

struct VS_INPUT

{

float3 position : POSITION;

float3 normal : NORMAL;

};

HLSL

vertex buffer position color

Page 44: [KGC2014] DX9에서DX11로의이행경험공유

D3D11_INPUT_ELEMENT_DESC decl[] =

{

{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},

{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},

};

UINT numElements = ARRAYSIZE( layout );

pd3dDevice->CreateInputLayout( decl, numElements, pVSBlob->GetBufferPointer(),

pVSBlob->GetBufferSize(), &pVertexLayout );

pImmediateContext->IASetInputLayout( pVertexLayout );

VertexInputLayout

struct VS_INPUT

{

float3 position : POSITION;

float4 color : COLOR0;

};

HLSL

1.0f 1.0f 1.0f 1.0f 1.0f 1.0f 1.0fvertex buffer

position color

Page 45: [KGC2014] DX9에서DX11로의이행경험공유

VertexInputLayout

vertex buffer 의 구성을 알고 있어도 같은 구성의 semantic 을 가지고 있는 vertex shader를 컴파일 하지 않으면VertexInputLayout 생성이 불가능

vertex buffer 의 구성만으로 생성이 가능 했던 DirectX9에비해 엄격해졌음

Page 46: [KGC2014] DX9에서DX11로의이행경험공유

VertexInputLayout

vertex buffer 와 vertex shader semantic 의 binding이 결정된 시점에 VertexInputLayout 동적생성한번 생성된 객체는 vertex buffer 와 vertex shader semantic 을 key로 가지는 hash table 관리

⇒ 동적 생성, hash table 검색이 느리고, rendering 할때마다 체크하지 않으면 안되기 때문에 비효율적

Page 47: [KGC2014] DX9에서DX11로의이행경험공유

VertexInputLayout

DirectX11에서는 shader reflection기능이 대폭 강화됨• semantic 의 type, num, offset 이외에도 constant buffer 의 name,

variable type 등 대부분의 정보를 프로그램에서 얻어 낼 수 있음

vertex shader를 reflection하여 semantic과 일치하는VertexInputLayout를 미리 생성. 즉, vertex buffer 기준이 아닌 shader semantic기준으로VertexInputLayout를 생성

Page 48: [KGC2014] DX9에서DX11로의이행경험공유

VertexInputLayout

D3D11_INPUT_ELEMENT_DESC decl[] =

{

{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},

{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},

};

UINT numElements = ARRAYSIZE( layout );

pd3dDevice->CreateInputLayout( decl, numElements, pVSBlob->GetBufferPointer(),

pVSBlob->GetBufferSize(), &pVertexLayout );

pImmediateContext->IASetInputLayout( pVertexLayout );

struct VS_INPUT

{

float3 position : POSITION;

float4 color : COLOR0;

};

HLSL

vertex buffer position color

shader reflection

Page 49: [KGC2014] DX9에서DX11로의이행경험공유

VertexInputLayout

vertex buffer 와 상관없이 미리 VertexInputLayout 을 생성하기때문에 vertex buffer 와의 불일치가 발생하는 경우가 있음

vertex bufferVertexInputLayout

position color 문제 없음

assert

normal position normal color

position normal

position normal color assert ?

position colornormal

position color

Page 50: [KGC2014] DX9에서DX11로의이행경험공유

VertexInputLayout

vertex buffer 가 GPU에 binding될 때 VertexInputLayout 정보를 참조하여 필요한 semantic 만 binding

VertexInputLayout position color

vertex buffer position colornormal

GPU

Page 51: [KGC2014] DX9에서DX11로의이행경험공유

vertex buffer binding

VertexInputLayout

vertex buffer 를 나누어 생성

UINT posStride = sizeof(float)*3;

UINT posOffset = 0;

pImmediateContext->IASetVertexBuffers( 0, 1, &posVB, &posStride, &posOffset );

UINT colorStride = sizeof(float)*4;

UINT colorOffset = 0;

pImmediateContext->IASetVertexBuffers( 1, 1, &colorVB, &colorStride, &colorOffset );

GPU

1.0f 1.0f 1.0f

1.0f 1.0f 1.0f 1.0f

position

normal 1.0f 1.0f 1.0f

color

Page 52: [KGC2014] DX9에서DX11로의이행경험공유

vertex buffer binding

VertexInputLayout

stride와 offset을 적절히 설정하여 binding

UINT posStride = sizeof(float)*3;

UINT posOffset = 0;

pImmediateContext->IASetVertexBuffers( 0, 1, &VB, &posStride, &posOffset );

UINT colorStride = sizeof(float)*4;

UINT colorOffset = 24;

pImmediateContext->IASetVertexBuffers( 1, 1, &VB, &colorStride, &colorOffset );

1.0fvertex buffer 1.0f 1.0f 1.0f 1.0f 1.0f 1.0f

position normal

1.0f 1.0f 1.0f

color

GPU

Page 53: [KGC2014] DX9에서DX11로의이행경험공유

Engine 소개

이행시 주의점• DirectX11 변경점

• Constant Buffer

• VertexInputLayout

• State Management

• Multithread

• Shader

• Etc.

결론

Contents

Page 54: [KGC2014] DX9에서DX11로의이행경험공유

DirectX9

State Management

pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );

Render(); // z enable – On

pDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );

Render(); // z enable – On, z write - Off

개별적으로 설정

한번 설정된 값은 변경하지 않는 이상 지속됨

Page 55: [KGC2014] DX9에서DX11로의이행경험공유

DirectX11

State Management

CreateXXXState 함수로 생성하며 오브젝트로 변경됨

개별 설정 불가능. 오브젝트 단위로 설정

state를 변경하는 경우 오브젝트를 재생성할 필요가 있음

texture sampler도 render state와 동일한 설계로 변경됨

Page 56: [KGC2014] DX9에서DX11로의이행경험공유

DirectX11

State Management

data create set

Rasterizer D3D11_RASTERIZER_DESC CreateRasterizerState RSSetState

Blend D3D11_BLEND_DESC CreateBlendState OMSetBlendState

DepthStencil D3D11_DEPTH_STENCIL_DESC CreateDepthStencilState OMSetDepthStencilState

Page 57: [KGC2014] DX9에서DX11로의이행경험공유

DirectX11

State Management

D3D11_DEPTH_STENCIL_DESC desc;

ZeroMemory( &desc, sizeof( D3D11_DEPTH_STENCIL_DESC ) );

desc.DepthEnable = TRUE;

desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;

desc.DepthFunc = D3D11_COMPARISON_LESS;

desc.StencilEnable = FALSE;

/* set desc.... */

ID3D11DepthStencilState* depthStencilState = NULL;

pDevice->CreateDepthStencilState(&desc, &depthStencilState);

pImmediateContext->OMSetDepthStencilState( depthStencilState );

생성 예

Page 58: [KGC2014] DX9에서DX11로의이행경험공유

DirectX11

State Management

변경 예

1. z enable – on

2. z enable – on, z write – off

pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );

Render(); // z enable – On

pDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );

Render(); // z enable – On, z write - Off

Page 59: [KGC2014] DX9에서DX11로의이행경험공유

DirectX11

State Management

ID3D11DepthStencilState* depthStencilState = NULL;

D3D11_DEPTH_STENCIL_DESC desc;

desc.DepthEnable = TRUE;

desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;

/* set desc.... */

device->CreateDepthStencilState(&desc, &depthStencilState);

pImmediateContext->OMSetDepthStencilState( depthStencilState );

Render(); // z enable – On

SAFE_RELEASE( depthStencilState );

desc.DepthEnable = TRUE;

desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;

/* set desc.... */

pDevice->CreateDepthStencilState(&desc, &depthStencilState);

pImmediateContext->OMSetDepthStencilState( depthStencilState );

Render(); // z enable – On, z write - Off

Page 60: [KGC2014] DX9에서DX11로의이행경험공유

State Management

DirectX9 처럼 global render state 에 모든 설정을 한 후, rendering 직전에 오브젝트 생성

⇒ 동적생성으로 인한 속도저하, multithread 대응 불가능, release 타이밍을 잡기 쉽지 않음

사전에 사용될 가능성이 있는 render state를 전부 미리 생성해 둠

⇒ program에서 동적으로 생성되는 타입의 render state에 대응하기 쉽지 않음ex) wireframe, blend 등

Page 61: [KGC2014] DX9에서DX11로의이행경험공유

State Management

DirectX11은 한번 생성되었던 render state 오브젝트를 내부적으로 관리하고 있음

2번째 생성하는 경우에 이전에 생성된 render state 오브젝트의reference count를 올리고 해당 오브젝트의 pointer를 반환함

즉, 한번 생성된 오브젝트를 해제하지 않고 놔두면 2번째 부터는 고속으로 생성 가능

Page 62: [KGC2014] DX9에서DX11로의이행경험공유

State Management

한번 생성된 render state는 해제하지 않고 stl set 에 저장. 2번째 같은 오브젝트가 생성된 경우 reference count를 1로유지하기 위해 Release호출

Create - solid

Create – wireframe

solid

1

solid

1

wireframe

1

count

count

render state

render state

Page 63: [KGC2014] DX9에서DX11로의이행경험공유

State Management

Create – alpha

solid wireframe

1 1

Create – wireframe

solid wireframe

1 2

alpha

1

solid wireframe

1 1

alpha

1

alpha

1

Release

count

count

count

render state

render state

render state

Page 64: [KGC2014] DX9에서DX11로의이행경험공유

State Management

차후 CreateXXXState 하기 위한 copy연산을 줄이기 위해render state parameter를 hash key로 관리하는 시스템도입 검토중

D3D11_DEPTH_STENCIL_DESC desc;

ZeroMemory( &desc, sizeof( D3D11_DEPTH_STENCIL_DESC ) );

desc.DepthEnable = EngineToDX11(ENGINE_DEPTH_ON);

desc.DepthWriteMask = EngineToDX11(ENGINE_ZWRITE_ON);

desc.DepthFunc = EngineToDX11(ENGINE_COMPARISON_LESS);

desc.StencilEnable = EngineToDX11(ENGINE_STENCIL_ON);

/* set desc.... */

Page 65: [KGC2014] DX9에서DX11로의이행경험공유

Engine 소개

이행시 주의점• DirectX11 변경점

• Constant Buffer

• VertexInputLayout

• State Management

• Multithread

• Shader

• Etc.

결론

Contents

Page 66: [KGC2014] DX9에서DX11로의이행경험공유

Multithread

코어수의 증가와 더불어, 멀티코어 대응 프로그래밍은 선택이 아닌 필수!

Page 67: [KGC2014] DX9에서DX11로의이행경험공유

Multithread

Page 68: [KGC2014] DX9에서DX11로의이행경험공유

Multithread

Page 69: [KGC2014] DX9에서DX11로의이행경험공유

ID3D11DeviceContext

Multithread

immediate context• rendering 명령을 실행하는 오브젝트

• 1개만 생성 가능하며 thread unsafe

deferred context• immediate context의 multithread 대응 오브젝트. 여러 개 생성 가능

하며 각 thread 에서 rendering 명령을 실행

• immediate context와 사용가능한 함수는 완전 일치

• 각 thread에서 모든 rendering 명령의 실행이 끝난 후에FinishCommandList 를 호출하여 command list 를 얻어옴. 이후command list를 immediate context 에서 실행

Page 70: [KGC2014] DX9에서DX11로의이행경험공유

Deferred Context

Multithread

1. 생성

ID3D11DeviceContext* pImmediateContext;

ID3D11DeviceContext* pDeferredContext;

/* pImmediateContext생성 후 */

pDevice->CreateDeferredContext( 0, &pDeferredContext );

2. 각 thread 마지막에 실행

/* pDeferredContext를 이용한 rendering 완료후 */

pDeferredContext->FinishCommandList( FALSE, &pCommandList );

3. immediate context에서 command list 실행

pImmediateContext->ExecuteCommandList( pCommandList, FALSE );

Page 71: [KGC2014] DX9에서DX11로의이행경험공유

Deferred Context

Multithread

Page 72: [KGC2014] DX9에서DX11로의이행경험공유

Draw Command

Multithread

내부 엔진에서는 중간 단계 rendering command 를 자체적으로 구현

모든 command 에는 priority 를 붙여서 생성

각 thread에서 생성된 command 를 sorting 한 후rendering thread 에 전달

rendering thread에서 각각의 command를 merge sort 한후 이를 순차적으로 실행

Page 73: [KGC2014] DX9에서DX11로의이행경험공유

Multithread

Draw Command

Secondary thread#1

BindBuffer61

SetShader60

Clear10

Secondary thread#2 Secondary thread#3

Clear10

BindBuffer61

SetShader60

SetRenderState50

SetShader22

SetRenderState21

SetShader22

SetRenderState21

SetRenderState50

Clear40

RenderPolygon30

BindTexture23

BindTexture23

RenderPolygon30

Clear40

Page 74: [KGC2014] DX9에서DX11로의이행경험공유

Multithread

Draw Command

Render thread

SetShader22

SetRenderState21

Clear10

Clear40

RenderPolygon30

BindTexture23

BindBuffer61

SetShader60

SetRenderState50

BindBuffer61

SetShader60

Clear10

SetRenderState50

SetShader22

SetRenderState21

Clear40

RenderPolygon30

BindTexture23

Page 75: [KGC2014] DX9에서DX11로의이행경험공유

Draw Command

Multithread

장점• priority를 이용해 유연성있게 rendering 순서를 조절 가능

• Graphics API에서 multithread를 대응하지 않는 경우 대응이 쉬움

• Draw Command의 기록을 남겨 replay나 디버깅에 활용

단점• Graphics API단에서의 병렬화가 아니므로, 일부 명령어는 병렬화 되

지 않을 가능성이 있음

Page 76: [KGC2014] DX9에서DX11로의이행경험공유

Multithread

처음부터 multithread를 고려하여 설계하는 것이 중요• Single-thread기준으로 작성된 프로젝트를 multithread 구조로 변경

하기 매우 힘듦

Multithread를 고려하지 않으면 속도 올리기가 쉽지 않음

하드웨어의 스펙을 100% 활용합시다!

Page 77: [KGC2014] DX9에서DX11로의이행경험공유

Engine 소개

이행시 주의점• DirectX11 변경점

• Constant Buffer

• VertexInputLayout

• State Management

• Multithread

• Shader

• Etc.

결론

Contents

Page 78: [KGC2014] DX9에서DX11로의이행경험공유

shader model

Shader

DirectX9 – 1.0, 2.0, 3.0

DirectX10 – 4.0, 4.1

DirectX11 – 5.0

Page 79: [KGC2014] DX9에서DX11로의이행경험공유

constant buffer

Shader

program에서 값을 받을 필요가 있는 parameter는 constant buffer로 정의

cbuffer perGlobalCB : register(b0)

{

float3 vLightPos;

float3 vLightDir;

};

cbuffer perCameraCB : register(b1)

{

float4x4 mView;

float4x4 mProj;

};

cbuffer perObjectCB : register(b2)

{

float4x4 mWorld;

float4x4 mBone[128];

};

cbuffer perMaterialCB : register(b3)

{

float4 vMaterial;

};

float3 g_vLightPos;

float3 g_vLightDir;

float4x4 g_mView;

float4x4 g_mProj;

float4x4 g_mWorld;

float4x4 g_mBone[128];

float4 g_vMaterial;

Page 80: [KGC2014] DX9에서DX11로의이행경험공유

Texture, Sampler 의 Binding

Shader

DirectX9에서는 sampler선언 시에 binding

texture g_texture;

sampler2D g_sampler = sampler_state

{

Texture = <g_texture>;

MinFilter = Point;

MagFilter = Linear;

MipFilter = Linear;

};

float4 PS( PS_INPUT input ) : COLOR

{

return tex2D( g_sampler, input.texCoord );

}

Page 81: [KGC2014] DX9에서DX11로의이행경험공유

Texture, Sampler 의 Binding

Shader

DirectX11에서는 sampling 함수를 호출하는 시점에 binding

texture2D g_texture;

SamplerState g_sampler;

float4 PS( PS_INPUT input ) : SV_Target

{

return g_texture.Sample( g_sampler, input.texCoord );

}

Page 82: [KGC2014] DX9에서DX11로의이행경험공유

Sampler 정의

Shader

DirectX11의 경우, shader에 적힌 sampler 속성은 effect를 사용하지 않는 한 적용되지 않으므로 주의

effect를 사용하지 않는 경우는 프로그램에서 설정

DirectX9

sampler2D g_sampler = sampler_state

{

Texture = <g_texture>;

MinFilter = Point;

MagFilter = Linear;

MipFilter = Linear;

};

SamplerState g_sampler

{

Filter = MIN_MAG_MIP_LINEAR;

};

DirectX11

Page 83: [KGC2014] DX9에서DX11로의이행경험공유

Effect

Shader

shader 설정, render state의 정의하는 방법이 변경 되었으니 주의

BlendState NoBlend

{

BlendEnbale[0] = False;

};

DepthStencilState DepthTestOn

{

DepthEnable = True;

DepthWriteMask = All;

DepthFunc = LESS;

};

RasterizerState rsWireframe

{

FillMode = Solid;

CullMode = Back;

FrontCounterClockwise = False;

};

VertexShader vs_main = CompileShader( vs_5_0, VS() );

PixelShader ps_main = CompileShader( ps_5_0, PS() );

technique11 t0

{

pass p0

{

SetBlendState( NoBlend, float4(0.0f,0.0f,0.0f,0.0f),0xFFFFFFFF );

SetDepthStencilState( DepthTestOn, 0 );

SetRasterizerState( rsWireframe );

SetVertexShader( vs_main );

SetGeometryShader( NULL );

SetPixelShader( ps_main );

}

}

Page 84: [KGC2014] DX9에서DX11로의이행경험공유

Intrinsic Functions

Shader

Page 85: [KGC2014] DX9에서DX11로의이행경험공유

Engine 소개

이행시 주의점• DirectX11 변경점

• Constant Buffer

• VertexInputLayout

• State Management

• Multithread

• Shader

• Etc.

결론

Contents

Page 86: [KGC2014] DX9에서DX11로의이행경험공유

Texture Array

Etc.

다수의 texture를 한번에 shader로 전달하는 것이 가능해짐

Texture이외의 material parameter가 같은 경우, texture 변경 없이 한번에 rendering 할 수 있음

리소스 파이프라인 변경 없이 texture atlas의 효과를 얻을 수 있음

Page 87: [KGC2014] DX9에서DX11로의이행경험공유

Format

Etc.

D3DFMT_XXX가 DXGI_FORMAT_XXX로 변경

D3DFMT_XXX에서 추가, 변경, 삭제 된 포맷이 있으므로 주의

지원되지 않는 포맷을 리소스에서 사용하고 있는경우 차후 문제가 생길 여지가 있으므로 주의

Page 88: [KGC2014] DX9에서DX11로의이행경험공유

Primitive

Etc.

D3DPT_TRIANGLEFAN가 삭제됨

프로그램에서 geometry를 생성하는 타입은 소스코드 수정

리소스에서 사용되는 경우 지원되는 primitive 포맷으로 export를 다시하거나 로딩 시에 변환

Page 89: [KGC2014] DX9에서DX11로의이행경험공유

Engine 소개

이행시 주의점• DirectX11 변경점

• Constant Buffer

• VertexInputLayout

• State Management

• Multithread

• Shader

• Etc.

결론

Contents

Page 90: [KGC2014] DX9에서DX11로의이행경험공유

결론

DirectX11 은 DirectX9 과 비교하여 많은 점이 변경 되었음. 기존 엔진&라이브러리를 이식하는 경우 생각보다 쉽지 않음

단, 그만큼 차세대에 어울리는 설계가 되어 있으므로, application에서도 graphics API를 이해하고 그 성능을 십분 활용할 수 있는 설계가 필요함

Page 91: [KGC2014] DX9에서DX11로의이행경험공유

결론

Q&A

Page 92: [KGC2014] DX9에서DX11로의이행경험공유

WE’RE HIRING

결론

엔지니어 채용중

[email protected]

Page 93: [KGC2014] DX9에서DX11로의이행경험공유

결론

References

• Game fest2007 : Windows to Reality: Getting the Most out of Direct3D 10 Graphics in Your Games

• GDC 2013 : D3D11 Deferred Contexts

• CEDEC 2006 : 次世代機に向けたゲームエンジンの設計

• GDC 2011 : DX11 Performance Gems

• CEDEC 2014 : 「世代間マルチプラットフォーム平行開発」 ~PlayStation4版 「龍が如く 維新!」開発の一年~

• http://msdn.microsoft.com/ko-kr/library/windows/apps/bb943991.aspx#File_Layout1

• http://msdn.microsoft.com/ko-kr/library/windows/desktop/ff476892%28v=vs.85%29.aspx

• http://msdn.microsoft.com/en-us/library/windows/desktop/ff471376%28v=vs.85%29.aspx

• http://www.gamedev.net/topic/542778-samplerstate-within-shader-snt-working-in-d3d10/

• http://en.wikipedia.org/wiki/High-level_shader_language

• http://msdn.microsoft.com/en-us/library/windows/desktop/hh404586%28v=vs.85%29.aspx

Images

• http://btoのパソコン.com/mametisiki/cpu.php

• http://www.virtuaniz.com/2013/12/playstation-4-vs-playstation-3-heres-the-comparison-is-ps4-worth-buying-or-sit-back-with-ps3/

• http://prohardver.hu/tudastar/direct3d_deferred_context.html

• http://lukasz.dk/2011/04/18/texture-atlas-generator/

• http://www.codesampler.com/d3dbook/chapter_05/chapter_05.htm

• http://volkansahin.net/oyunlarda-grafik/