Quick Comparison
DYNAMIC + CPU write every frame -> Map(WRITE_DISCARD), memcpy, Unmap
DEFAULT + occasional whole/box update -> UpdateSubresource
GPU-to-GPU transfer -> CopyResource / CopySubresourceRegion
GPU readback -> copy to STAGING, then Map(READ)갱신 API는 resource Usage와 함께 고릅니다. GPU가 아직 읽는 영역을 CPU가 덮어쓰지 않도록 discard·no-overwrite 계약을 지킵니다.
Dynamic 쓰기
D3D11_MAPPED_SUBRESOURCE mapped{};
ThrowIfFailed(context->Map(buffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped));
std::memcpy(mapped.pData, &constants, sizeof(constants));
context->Unmap(buffer.Get(), 0);WRITE_DISCARD는 이전 내용이 필요 없음을 알려 새 memory region을 받을 수 있게 합니다. 반환된 pointer에서 이전 data를 보존하려 하지 않습니다. WRITE_NO_OVERWRITE는 GPU가 사용할 기존 영역을 건드리지 않는다는 application 약속이며 지원 범위와 offset 관리가 필요합니다.
Deferred context의 Map은 WRITE_DISCARD와 WRITE_NO_OVERWRITE만 허용됩니다. Direct3D 11.1 runtime에서 dynamic constant buffer 또는 SRV로 bind된 dynamic buffer에 WRITE_NO_OVERWRITE를 쓰려면 D3D11_FEATURE_D3D11_OPTIONS의 MapNoOverwriteOnDynamicConstantBuffer 또는 MapNoOverwriteOnDynamicBufferSRV 지원을 확인합니다.
RowPitch와 DepthPitch
Texture를 map하면 row가 단순히 width * pixelSize로 붙어 있다고 가정하지 않고 RowPitch를 사용해 행별로 복사합니다. 3D texture는 DepthPitch도 확인합니다.
자주 틀리는 점
- Map 성공 뒤 모든 경로에서 Unmap이 실행되게 합니다.
UpdateSubresourcesource pointer는 함수 호출 동안 유효해야 하며 pitch를 정확히 전달합니다.- 매 draw마다 작은 update를 무작정 호출하지 않고 constant grouping을 설계합니다.
- Immediate readback으로 CPU와 GPU를 매 frame 동기화하지 않습니다.
참고 링크
2 sources