1. 왜 씀
처음 봤을 때 뭔가 했던 기능.
주 용도는 D3D11_BUFFER_UAV_FLAG_APPEND 또는 D3D11_BUFFER_UAV_FLAG_COUNTER 로 생성된 UAV 의 값으로 렌더링 하기위함. 이를 위해선 버퍼크기를 알아야하고 ComputerShader 에서 계산한 값들을 넣으면 버퍼 크기가 바뀜. 이때 CPU 에 버퍼크기를 넣는게 아니라 GPU 에 넣어서 속도를 빠르게 하는데 이를 위해서 그 크기를 넣는 버퍼를 따로 만들어야함.
그 버퍼가 D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS 플래그로 만든 버퍼.
2. 사용법
2개의 buffer 를 만들어야함. 하나는 UAV 로 만들어서 ComputeShader 에서 Append 시켜서 업데이트 시킬 용도, 다른 하나는 그 버퍼의 크기를 를 복사할 용도.
D3D11_BUFFER_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Usage = m_cpu_writable ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT; desc.CPUAccessFlags = m_cpu_writable ? D3D11_CPU_ACCESS_WRITE : 0;; desc.ByteWidth = sizeof(T) * num_item; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS; desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; desc.StructureByteStride = sizeof(T); D3D11_UNORDERED_ACCESS_VIEW_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Format = DXGI_FORMAT_UNKNOWN; desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_APPEND; desc.Buffer.NumElements = GetCount(); desc.Buffer.FirstElement = 0;
전자는 Append Flag 에 주의해서 만들면 됨.
Counter 같은 다른 Flag 도 유효함.
D3D11_BUFFER_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Usage = D3D11_USAGE_DEFAULT; desc.CPUAccessFlags = 0; desc.ByteWidth = sizeof(int) * 4; desc.BindFlags = 0; desc.MiscFlags = D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS; desc.StructureByteStride = sizeof(T);
후자는 데이터 구성 요소가 정해져 있음.
d3d_context->DrawInstanced, DrawIndexedInstanced 의 인자가 4개인데 정확히 대응함.
https://docs.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-drawinstanced
d3d_context->CopyStructureCount()
를 통해서 4개의 인자를 UAV 를 통해서 읽어온 후에
d3d_context->DrawInstancedIndirectted, DrawIndexedInstancedIndirected 를 실행하면 됨.
https://docs.microsoft.com/ko-kr/windows/win32/direct3d12/indirect-drawing
Direct12 에선 더 복잡해짐.