[GEG1] 10.camera-centric engine design for multithreaded rendering

26
Game Engine Gems 1 Chap 10. Camera-Centric Engine Design for Multithreaded Rendering ohyecloudy http://ohyecloudy.com shader café http://cafe.naver.com/shader 2011.04.11

Transcript of [GEG1] 10.camera-centric engine design for multithreaded rendering

Page 1: [GEG1] 10.camera-centric engine design for multithreaded rendering

Game Engine Gems 1 Chap 10. Camera-Centric Engine Design for Multithreaded Rendering

ohyecloudy http://ohyecloudy.com

shader café http://cafe.naver.com/shader

2011.04.11

Page 2: [GEG1] 10.camera-centric engine design for multithreaded rendering

Uses of Multi-Core in Video Games

Multithreaded Command Buffers

Device-Independent Command Buffers

A Camera-Centric Design

Future Work

Page 3: [GEG1] 10.camera-centric engine design for multithreaded rendering

Sim Update

Anim Physics Update

Particle Update

Shadow Maps

Reflect Maps

Main View

Post- Process

frame

Main thread

Thread Pool

Page 4: [GEG1] 10.camera-centric engine design for multithreaded rendering

Sim Update

Anim Physics Update

Particle Update

Shadow Maps

Reflect Maps

Main View

Post- Process

frame

Main thread

Thread Pool

Rendering API를 호출할 필요가 없는 작업만 multithread

Page 5: [GEG1] 10.camera-centric engine design for multithreaded rendering

Sim Update

Anim Physics Update

Particle Update

Shadow Maps

Reflect Maps

Main View

Post- Process

frame

Main thread

Thread Pool

Stage 별로 그룹화 각 스테이지에서 직접 device call 그래서 device를 소유하는 thread에서 대부분 일을 처리

Page 6: [GEG1] 10.camera-centric engine design for multithreaded rendering

Uses of Multi-Core in Video Games

Multithreaded Command Buffers

Device-Independent Command Buffers

A Camera-Centric Design

Future Work

Page 7: [GEG1] 10.camera-centric engine design for multithreaded rendering

• 그리기 명령을 수행하는데 필요한 정보

– device level

• rendering API 내부에 존재

– API를 호출하면 버퍼를 채움

– CPU 사용

Page 8: [GEG1] 10.camera-centric engine design for multithreaded rendering

• command buffer를 추상화 – multithread로 command buffer를 채울 수 있게

– device 독립

• DX9 – multithread command buffer 불가능

– device를 소유한 thread에서만 API call

– multithread를 지원 옵션이 있긴 있다 • 모든 call에 베타제어

• 성능 저하가 심함

• 제외

Page 9: [GEG1] 10.camera-centric engine design for multithreaded rendering

Uses of Multi-Core in Video Games

Multithreaded Command Buffers

Device-Independent Command Buffers

A Camera-Centric Design

Future Work

Page 10: [GEG1] 10.camera-centric engine design for multithreaded rendering

struct RenderCommand { ResourceHandle VertexBufferHandle; uint32 VertexDeclEnumIndex; uint32 NumTriangles; uint32 NumVerts; enum PrimType { kTriList, kTriStrip }; PrimType PrimitiveType; enum BlendType { kBlend_None, kBlend_Standard, kBlend_Additive, kBlend_Subtractive }; BlendType BlendType; // and so on… };

RenderCommand 드로우 콜 단위

Page 11: [GEG1] 10.camera-centric engine design for multithreaded rendering

void RenderObject::fillCommandBuffer (RenderCommand *RC) { ThreadAssert(ThreadPoolThread); if (ObjectType == kTypeOpaqueMesh) { RC->VertexBufferHandle = mVBHandle; RC->VertexDeclEnumIndex = kVD_Mesh; RC->PrimitiveType = kTriList; RC->BlendType = kBlend_None; RC->NumTriangles = numTrisFromPrimType(); RC->NumVerts = mNumVerts; } else if (ObjectType == kTypeTransparentMesh) { // and so on… } }

Page 12: [GEG1] 10.camera-centric engine design for multithreaded rendering

void RenderObject::fillCommandBuffer (RenderCommand *RC) { ThreadAssert(ThreadPoolThread); if (ObjectType == kTypeOpaqueMesh) { RC->VertexBufferHandle = mVBHandle; RC->VertexDeclEnumIndex = kVD_Mesh; RC->PrimitiveType = kTriList; RC->BlendType = kBlend_None; RC->NumTriangles = numTrisFromPrimType(); RC->NumVerts = mNumVerts; } else if (ObjectType == kTypeTransparentMesh) { // and so on… } }

렌더링 리소스 수명을 제어하는 객체 오브젝트 하나가 여러 개 RenderCommand를 만들 수 있음 character, terrain, …

Page 13: [GEG1] 10.camera-centric engine design for multithreaded rendering

void RenderObject::fillCommandBuffer (RenderCommand *RC) { ThreadAssert(ThreadPoolThread); if (ObjectType == kTypeOpaqueMesh) { RC->VertexBufferHandle = mVBHandle; RC->VertexDeclEnumIndex = kVD_Mesh; RC->PrimitiveType = kTriList; RC->BlendType = kBlend_None; RC->NumTriangles = numTrisFromPrimType(); RC->NumVerts = mNumVerts; } else if (ObjectType == kTypeTransparentMesh) { // and so on… } }

RenderObject 상태를 단지 읽기만 한다. thread safe

Page 14: [GEG1] 10.camera-centric engine design for multithreaded rendering

void renderControl::executeDrawCommandDx9 (const RenderCommand *params) { ThreadAssert(DeviceOwningThread); const VertexBufferContainer *vbc = mManagedVBs.getElement(params->vbHandle); DX9Dev->SetStreamSource( 0, (IDirect3DVertexBuffer9 *)vbc->devicehandle, 0, vbc->perVertSizeInBytes); SetShaderData(params); SetRenderStates(params); DX9Dev->SetVertexDeclaration( StaticVDeclHandles[params->vDecl]); D3DPRIMITIVETYPE type = PrimTypeMappingLUT[params->PrimitiveType]; DX9Dev->DrawPrimitive(type, 0, params->NumTriangles); }

Page 15: [GEG1] 10.camera-centric engine design for multithreaded rendering

Uses of Multi-Core in Video Games

Multithreaded Command Buffers

Device-Independent Command Buffers

A Camera-Centric Design

Future Work

Page 16: [GEG1] 10.camera-centric engine design for multithreaded rendering

• load balancing 필요

– command buffer 채우는 작업을 할당

– thread 별로 어떻게 할당?

• 최종 장면이 나오기 전까지 여러 장면을 렌더링

– shadow map, reflection, post processing, …

– 카메라

• 장면마다 공유

Page 17: [GEG1] 10.camera-centric engine design for multithreaded rendering

• camera 단위

– command buffer 생성을 쪼갠다.

• draw call 묶기

– API 호출에 따른 오버헤드 최소화

– render state 변경 최소화

– batch

Page 18: [GEG1] 10.camera-centric engine design for multithreaded rendering

Sim Update

Anim Physics Update

Particle Update

frame

Main thread

Thread Pool

Render View Filling

Submit to

Device

Page 19: [GEG1] 10.camera-centric engine design for multithreaded rendering

struct Camera { Float3 at, up, right; float aspectRatio; }; struct RenderView { Camera ViewCamera; Frustum Frust; RenderTargetHandle DestColorRTT; RenderTargetHandle DestDepthRTT; List<RenderCommand *> RenderCommands; enum ViewType { kVT_ShadowMap, kVT_ReflectionMap, kVT_MainCamera, kVT_PostProcessing, kVT_Count }; ViewType ViewType; };

Page 20: [GEG1] 10.camera-centric engine design for multithreaded rendering

void renderControl::CreateRenderViews() { List<RenderView *> currentViews; for (int i = 0; i < mCameras.size(); ++i) { currentViews.add( new RenderView(mCameras[i], kVT_MainCamera)); } for (int i = 0; i < mLights.size(); ++i) { if (mLights[i].IsShadowCasting()) { currentViews.add( new RenderView( mLights[i].getShadowCamera(), kVT_ShadowMap)); } } for (int i = 0; i < currentViews.size(); ++i) { ThreadPool.QueueWork( procThreadedFillRenderView, currentViews[i]); } ThreadPool.waitForWorkToFinish(); }

Page 21: [GEG1] 10.camera-centric engine design for multithreaded rendering

void renderControl::procThreadedFillRenderView (

void *DataPacket) {

RenderView *currView = (RenderView *)DataPacket;

List<RenderObject *> objects =

gObjectManager.giveFrustumCollision(

currView->frustum);

for (int q = 0; q < objects.size(); ++q) {

RenderCommand *RC = new RenderCommand();

Objects[q]->fillCommandBuffer(RC);

currentViews[i].RenderCommands.add(RC);

}

}

Page 22: [GEG1] 10.camera-centric engine design for multithreaded rendering

void renderControl::serializeRenderView (List<RenderView *> Views) { for (int viewType = 0; viewType < Count; ++viewType) { for (int i = 0; i < Views.size(); ++i) { if (Views[i].mViewType != viewType) continue; BindRenderTarget( Views[i]->renderTarget, Views[i]->DepthTarget); if (Views[i]->clearTargets) { ClearTarget( Views[i]->clearFlags, Views[i]->clearColor, Views[i]->clearDepths); } for (int k = 0; k < Views[i]->commands.size(); ++k) { executeDrawCommand(Views[i]->commands[k]); } } } }

Page 23: [GEG1] 10.camera-centric engine design for multithreaded rendering

Uses of Multi-Core in Video Games

Multithreaded Command Buffers

Device-Independent Command Buffers

A Camera-Centric Design

Future Work

Page 24: [GEG1] 10.camera-centric engine design for multithreaded rendering

• Sorting and Instancing

– material index, vertex data, object type…

– instancing command

• draw command 여러 개를

• Better Load Balancing

– draw call을 job 하나로

– job을 잘게 나눠 thread utilization을 높임

Page 25: [GEG1] 10.camera-centric engine design for multithreaded rendering
Page 26: [GEG1] 10.camera-centric engine design for multithreaded rendering