D3D12엔진 개발 – Dynamic VertexBuffer 사용

Voxel Horizon데모를 D3D12엔진으로 돌아가게 만들었다.

데모에서 바닥과 블럭 렌더링은 Dynamic VertexBuffer를 사용한다. D3D11에선 Map(), Unmap()을 사용해서 하나의 VertexBuffer에 Update하고 Draw..(), 또 Update하고 Draw..()하면 되었다. D3D11이라고 해서 Draw..()한다고 즉시 렌더링이 이루어지진 않는데 Resource Renaming이란 방법으로 해결하고 있다.
D3D12에선 이런거 없다. 게다가 CommandList를 이욯하기 때문에 Execute()하는 시점까진 Draw…()에 사용될 VertexBuffer의 내용이 그대로 유지되어야한다.

우선 Vertex Buffer는 다음과 같이 만든다. Dynamic이기 때문에, 즉 CPU에서 write해야하기 때문에 D3D12_HEAP_PROPERTIES로 CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD)를 사용한다.

   HRESULT hr = S_OK;
	
	D3D12_VERTEX_BUFFER_VIEW	VertexBufferView = {};
	ID3D12Resource*	pVertexBuffer = NULL;
	UINT		VertexBufferSize = SizePerVertex*dwVertexNum;

	// create vertexbuffer for Dynamic Accessing
	hr = m_pD3DDevice->CreateCommittedResource(
		&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
		D3D12_HEAP_FLAG_NONE,
		&CD3DX12_RESOURCE_DESC::Buffer(VertexBufferSize),
		D3D12_RESOURCE_STATE_GENERIC_READ,
		nullptr,
		IID_PPV_ARGS(&pVertexBuffer));


	// Initialize the vertex buffer view.
	VertexBufferView.BufferLocation = pVertexBuffer->GetGPUVirtualAddress();
	VertexBufferView.StrideInBytes = SizePerVertex;
	VertexBufferView.SizeInBytes = VertexBufferSize;

그리고 다음과 같이 Write흘 시스템 메모리 어드레스를 확보한다. Unmap()은 호출할 필요없다. 이 어드레스에 써넣을 것이고 Draw..()시점..아니 정확히는 Execute()를 통해서 실제로 Draw..()가 실행될 시점에서 D3D런타임이 시스템메모리로부터 GPU메모리로 버텍스 데이타를 카피한다.

   // CPU address
	CD3DX12_RANGE readRange(0, 0);	
	UINT8*	pVetexDataBegin = NULL;
	pVertexBuffer->Map(0,&readRange,(void**)&pVetexDataBegin);	// Write Vertex Data to pVertexDataBegin dynamically

렌더링할때는 일반적인 VertexBuffer를 사용하듯 똑같이 사용한다.

// Draw
D3D12_VERTEX_BUFFER_VIEW VBView[] = {VertexBufferView};
pCommandList->IASetVertexBuffers(0, _countof(VBView), VBView);

pCommandList->DrawInstanced(VertexCount,1,VertexStartIndex,0);

다시 한번 강조하지만 프레임 갱신 전에, 즉 Execute()가 호출되기 전에는 VertexBuffer를 재활용할 수 없다. 간단한 메모리 풀 구조를 만들어서 Execute()시점까지 write한 VertexBuffer를 모두 유지해야한다.

 


voxel_horizon_d3d12_00


voxel_horizon_d3d12_01

voxel_horizon_d3d12_02


답글 남기기

댓글을 게시하려면 다음의 방법 중 하나를 사용하여 로그인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중