I'm currently writing my own graphics framework for DirectX12 (I've already written several DirectX 11 frameworks for personal game engines), and I'm currently trying to copy the methods used in the recent Hitman game for resource binding.
I'm confused about the best way to handle per-object resource binding for the SRV/CBV/UAV heap. I've watched several GDC presentations, and they all seem to gloss over this.
Only 1 SRV/CBV/UAV heap can be bound at a time, and switching the currently-bound heap in the middle of a command list can be bad for performance on some hardware by forcing a flush. Because of this, what is the best way to handle updating the heap with new descriptors? To me, it seems like each command list would:
- Get a hold of a SRV/CBV/UAV heap for itself.
- For each object in a subset of objects, create descriptors on the heap pointing to per-object data that was placed into a separate upload heap.
- Afterwards, another command list takes this filled descriptor heap and binds it, then issues draw calls mixed with
SetGraphicsRootDescriptorTable
in order to move through the current descriptor heap.
This being said, several sources online (including another SO post) suggest using one large SRV/CBV/UAV heap and copying into it using CPU-visible heaps. I'm assuming they're not attempting to use the asynchronous CopyDescriptors
, but rather CopyBufferRegion
. I tried using CopyBufferRegion
to update data per-object, but to me this seems under-performant with so many transitions between D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
and D3D12_RESOURCE_STATE_COPY_DEST
. Am I misunderstanding something? Any clarity would be appreciated.