11 assert(device !=
nullptr);
13 m_commandQueue = queue;
16 ConfigureFromBufferType(type);
20 D3D12_HEAP_TYPE heapType, D3D12_RESOURCE_STATES resourceState)
23 m_resourceState(resourceState)
25 assert(device !=
nullptr);
32 m_device(std::move(other.m_device)),
33 m_commandQueue(other.m_commandQueue),
34 m_buffer(std::move(other.m_buffer)),
35 m_uploadBuffer(std::move(other.m_uploadBuffer)),
36 m_commandAllocator(std::move(other.m_commandAllocator)),
37 m_commandList(std::move(other.m_commandList)),
38 m_heapType(other.m_heapType),
39 m_resourceState(other.m_resourceState),
40 m_currentState(other.m_currentState),
41 m_mappedData(other.m_mappedData)
43 other.m_commandQueue =
nullptr;
44 other.m_mappedData =
nullptr;
52 BufferBase::operator=(std::move(other));
53 m_device = std::move(other.m_device);
54 m_commandQueue = other.m_commandQueue;
55 m_buffer = std::move(other.m_buffer);
56 m_uploadBuffer = std::move(other.m_uploadBuffer);
57 m_commandAllocator = std::move(other.m_commandAllocator);
58 m_commandList = std::move(other.m_commandList);
59 m_heapType = other.m_heapType;
60 m_resourceState = other.m_resourceState;
61 m_currentState = other.m_currentState;
62 m_mappedData = other.m_mappedData;
64 other.m_commandQueue =
nullptr;
65 other.m_mappedData =
nullptr;
75void DirectX12Buffer::ConfigureFromBufferType(
BufferType type)
79 m_heapType = D3D12_HEAP_TYPE_DEFAULT;
80 m_resourceState = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
84 m_heapType = D3D12_HEAP_TYPE_DEFAULT;
85 m_resourceState = D3D12_RESOURCE_STATE_INDEX_BUFFER;
89 m_heapType = D3D12_HEAP_TYPE_UPLOAD;
90 m_resourceState = D3D12_RESOURCE_STATE_GENERIC_READ;
94 m_heapType = D3D12_HEAP_TYPE_DEFAULT;
95 m_resourceState = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
99 m_heapType = D3D12_HEAP_TYPE_DEFAULT;
100 m_resourceState = D3D12_RESOURCE_STATE_COMMON;
105D3D12_RESOURCE_DESC DirectX12Buffer::CreateBufferDesc()
const
107 D3D12_RESOURCE_DESC desc = {};
108 desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
112 desc.DepthOrArraySize = 1;
114 desc.Format = DXGI_FORMAT_UNKNOWN;
115 desc.SampleDesc.Count = 1;
116 desc.SampleDesc.Quality = 0;
117 desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
118 desc.Flags = D3D12_RESOURCE_FLAG_NONE;
128 if (!m_device ||
Size == 0)
134 D3D12_HEAP_PROPERTIES heapProps = {};
135 heapProps.Type = m_heapType;
136 heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
137 heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
138 heapProps.CreationNodeMask = 1;
139 heapProps.VisibleNodeMask = 1;
141 auto desc = CreateBufferDesc();
145 D3D12_RESOURCE_STATES initialState =
146 (data && m_heapType == D3D12_HEAP_TYPE_DEFAULT)
147 ? D3D12_RESOURCE_STATE_COPY_DEST
149 m_currentState = initialState;
150 HRESULT hr = m_device->CreateCommittedResource(
152 D3D12_HEAP_FLAG_NONE,
156 IID_PPV_ARGS(&m_buffer));
165 if (m_heapType == D3D12_HEAP_TYPE_DEFAULT) {
167 CreateUploadBuffer(data, size);
170 Update(
const_cast<void*
>(data), size);
178bool DirectX12Buffer::CreateUploadBuffer(
const void* data,
size_t dataSize)
181 D3D12_HEAP_PROPERTIES uploadHeapProps = {};
182 uploadHeapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
183 uploadHeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
184 uploadHeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
185 uploadHeapProps.CreationNodeMask = 1;
186 uploadHeapProps.VisibleNodeMask = 1;
188 D3D12_RESOURCE_DESC uploadDesc = CreateBufferDesc();
190 HRESULT hr = m_device->CreateCommittedResource(
192 D3D12_HEAP_FLAG_NONE,
194 D3D12_RESOURCE_STATE_GENERIC_READ,
196 IID_PPV_ARGS(&m_uploadBuffer));
204 void* mappedData =
nullptr;
205 hr = m_uploadBuffer->Map(0,
nullptr, &mappedData);
213 memcpy(mappedData, data, dataSize);
214 m_uploadBuffer->Unmap(0,
nullptr);
217 if (!m_commandAllocator) {
218 hr = m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,
219 IID_PPV_ARGS(&m_commandAllocator));
225 WaitForUploadComplete();
226 hr = m_commandAllocator->Reset();
231 if (!m_commandList) {
232 hr = m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
233 m_commandAllocator.Get(),
nullptr,
234 IID_PPV_ARGS(&m_commandList));
239 hr = m_commandList->Reset(m_commandAllocator.Get(),
nullptr);
247 if (m_currentState != D3D12_RESOURCE_STATE_COPY_DEST) {
248 D3D12_RESOURCE_BARRIER barrier = {};
249 barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
250 barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
251 barrier.Transition.pResource = m_buffer.Get();
252 barrier.Transition.StateBefore = m_currentState;
253 barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
254 barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
256 m_commandList->ResourceBarrier(1, &barrier);
260 m_commandList->CopyBufferRegion(m_buffer.Get(), 0, m_uploadBuffer.Get(), 0, dataSize);
263 if (m_resourceState != D3D12_RESOURCE_STATE_COPY_DEST) {
264 D3D12_RESOURCE_BARRIER barrier = {};
265 barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
266 barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
267 barrier.Transition.pResource = m_buffer.Get();
268 barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
269 barrier.Transition.StateAfter = m_resourceState;
270 barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
272 m_commandList->ResourceBarrier(1, &barrier);
275 m_currentState = m_resourceState;
277 hr = m_commandList->Close();
285 if (!m_commandList) {
291 SLEAK_ERROR(
"Command list is null for buffer Update!");
297 SetAsVertexBuffer(m_commandList.Get(),0,
sizeof(
Sleak::Vertex));
300 SetAsIndexBuffer(m_commandList.Get(),DXGI_FORMAT_R32_UINT);
303 SetAsConstantBuffer(m_commandList.Get(),0);
331 m_uploadBuffer.Reset();
332 m_commandList.Reset();
333 m_commandAllocator.Reset();
342 if (m_heapType != D3D12_HEAP_TYPE_UPLOAD && m_heapType != D3D12_HEAP_TYPE_READBACK)
345 HRESULT hr = m_buffer->Map(0,
nullptr, &m_mappedData);
360 m_buffer->Unmap(0,
nullptr);
362 m_mappedData =
nullptr;
369 if (!m_buffer || size >
Size || !data)
377 if (m_heapType == D3D12_HEAP_TYPE_UPLOAD) {
382 memcpy(m_mappedData, data, size);
389 if (CreateUploadBuffer(data, size) && m_commandQueue) {
390 ID3D12CommandList* ppCmdLists[] = {m_commandList.Get()};
391 m_commandQueue->ExecuteCommandLists(1, ppCmdLists);
392 WaitForUploadComplete();
397void DirectX12Buffer::SetAsVertexBuffer(ID3D12GraphicsCommandList* commandList, UINT slot, UINT stride, UINT offset) {
398 D3D12_VERTEX_BUFFER_VIEW vbView;
399 vbView.BufferLocation = m_buffer->GetGPUVirtualAddress() + offset;
400 vbView.StrideInBytes = stride;
401 vbView.SizeInBytes =
static_cast<UINT
>(
Size - offset);
403 commandList->IASetVertexBuffers(slot, 1, &vbView);
407void DirectX12Buffer::SetAsIndexBuffer(ID3D12GraphicsCommandList* commandList, DXGI_FORMAT format, UINT offset) {
408 D3D12_INDEX_BUFFER_VIEW ibView;
409 ibView.BufferLocation = m_buffer->GetGPUVirtualAddress() + offset;
410 ibView.Format = format;
411 ibView.SizeInBytes =
static_cast<UINT
>(
Size - offset);
413 commandList->IASetIndexBuffer(&ibView);
417void DirectX12Buffer::SetAsConstantBuffer(ID3D12GraphicsCommandList* commandList, UINT rootParameterIndex) {
418 commandList->SetGraphicsRootConstantBufferView(
420 m_buffer->GetGPUVirtualAddress()
428void DirectX12Buffer::WaitForUploadComplete()
430 if (!m_device || !m_commandQueue)
433 Microsoft::WRL::ComPtr<ID3D12Fence> tempFence;
434 HRESULT hr = m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&tempFence));
435 if (FAILED(hr))
return;
437 m_commandQueue->Signal(tempFence.Get(), 1);
439 HANDLE ev = CreateEvent(
nullptr, FALSE, FALSE,
nullptr);
442 if (tempFence->GetCompletedValue() < 1) {
443 tempFence->SetEventOnCompletion(1, ev);
444 WaitForSingleObject(ev, INFINITE);
Backend-agnostic GPU buffer: vertex, index, constant, or resource view target.
void StoreCPUShadowCopy(const void *data, size_t size)
Copies up to 128 bytes into the inline shadow-copy storage, clamping oversized input.
void * GetData() override
void ReleaseUploadResources()
~DirectX12Buffer() override
bool Initialize(void *Data) override
Creates the default-heap resource and uploads initial data via a staging buffer, if any.
DirectX12Buffer(ID3D12Device *device, ID3D12CommandQueue *queue, size_t size, BufferType type)
static void ProcessDeferredCleanup()
static void DeferCleanup(Microsoft::WRL::ComPtr< ID3D12Resource > resource)
bool Map() override
Maps the buffer for CPU writes (upload-heap buffers only).
DirectX12Buffer & operator=(const DirectX12Buffer &)=delete
Backend-facing rendering layer shared by the four graphics backends.
static std::vector< Microsoft::WRL::ComPtr< ID3D12Resource > > s_deferredResources
BufferType
GPU buffer usage kind, drives backend binding flags and layout.
static std::vector< Microsoft::WRL::ComPtr< ID3D12Resource > > s_pendingResources
Root namespace for everything the engine exposes.