본문 바로가기
게임 공부/DirectX

[DX11] UpdateSubresource 와 map은 각각 언제?

by woohyeon 2021. 4. 18.
반응형

GPU에 어떤 자원을 업데이트 할 때 필요한 함수로 UpdateSubresourcemap이 있다.

차이점은 우선 UpdateSubresourcesrcdest가 같은 포맷(단위)이 동일할 때 그 단위로 복사해주는 함수이다. 반면 map은 read/write 하려는 GPU 메모리 영역에 Lock을 걸고 그 주소를 얻어와서 이 주소를 통해 하고 싶은 동작을 수행하는 것이다.

그러나 실제로 map은 GPU 메모리 영역의 주소를 주는 것이 아니라 그 영역을 시스템(CPU) 메모리에 mapping한 주소를 준다. 만약 read가 필요한 경우, 해당되는 GPU 메모리 영역을 시스템 메모리에 copy 후 시스템 메모리의 주소를 반환하기 때문에 복사 및 mapping만큼의 오버헤드가 있다. 만약 write 용도일 경우 GPU 메모리 내용을 알 필요가 없기에 시스템 메모리에 copy할 이유가 없다. 따라서 그냥 업데이트할 내용을 시스템 메모리에 write하고 그 내용을 GPU 메모리에 copy하면 된다. 때문에 write 용도로 버퍼를 생성했을 경우 map으로 얻은 주소의 내용을 read하면 안된다.

어떻게 두 함수를 구분하여 사용할지는 버퍼의 옵션에 달려 있다. 초기에 버퍼를 생성할 때 옵션으로 설정하는 값에 따라 사용할 수 있는 함수가 나뉘게 된다.

버퍼를 생성할 때 D3D11_BUFFER_DESC라는 구조체 데이터를 채워야 하는데, Usage라는 옵션이 있다. 이 옵션으로 다음과 같은 옵션들을 설정할 수 있는데

D3D11_USAGE

기본적으로 보통 DEFAULT 혹은 DYNAMIC을 사용하게 된다. 만약 DEFAULT로 설정하게 되면 UpdateSubresource 함수를 사용하게 되고, DYNAMIC으로 설정하게 되면 map을 사용해야 한다. 또한 CPUAccessFlags라는 옵션이 있는데 usageDEFAULT일 경우 0을 주고, DYNAMIC일 경우 D3D11_CPU_ACCESS_WRITE를 준다. 즉 다음과 같다.

if(dynamic) // map()
{
	desc.Usage = D3D11_USAGE_DYNAMIC;
	desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
}
else // UpdateSubresource()
{
	desc.Usage = D3D11_USAGE_DEFAULT;
	desc.CPUAccessFlags = 0;
}

 

UpdateSubresource는 애초에 CPU -> GPU 메모리로의 단방향 연산이고, map은 양방향 모두 가능하다. 따라서 GPU
메모리를 read해야 한다면 무조건 버퍼를 DYNAMIC으로 만들어 map을 사용하는 수 밖에 없다. 

만약 업데이트 하려는 데이터 단위가 대응될 경우 UpdateSubresource를 사용하는 것이 좋다. 예를 들어 Constant buffer는 보통 updateSubresource를 사용하는 것 같다.




댓글