diff --git a/engine/include/XCEngine/RHI/D3D12/D3D12Buffer.h b/engine/include/XCEngine/RHI/D3D12/D3D12Buffer.h index 58e44faf..8f14d4a3 100644 --- a/engine/include/XCEngine/RHI/D3D12/D3D12Buffer.h +++ b/engine/include/XCEngine/RHI/D3D12/D3D12Buffer.h @@ -17,6 +17,8 @@ public: bool Initialize(ID3D12Device* device, uint64_t size, D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COMMON, D3D12_HEAP_TYPE heapType = D3D12_HEAP_TYPE_DEFAULT); bool InitializeFromExisting(ID3D12Resource* resource); + bool InitializeWithData(ID3D12Device* device, ID3D12GraphicsCommandList* commandList, + const void* data, uint64_t size, D3D12_RESOURCE_STATES finalState); void Shutdown(); ID3D12Resource* GetResource() const { return m_resource.Get(); } diff --git a/engine/src/RHI/D3D12Buffer.cpp b/engine/src/RHI/D3D12Buffer.cpp index a818b38b..322451bc 100644 --- a/engine/src/RHI/D3D12Buffer.cpp +++ b/engine/src/RHI/D3D12Buffer.cpp @@ -52,6 +52,97 @@ bool D3D12Buffer::InitializeFromExisting(ID3D12Resource* resource) { return true; } +bool D3D12Buffer::InitializeWithData(ID3D12Device* device, ID3D12GraphicsCommandList* commandList, + const void* data, uint64_t size, D3D12_RESOURCE_STATES finalState) { + + D3D12_HEAP_PROPERTIES heapProperties = {}; + heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT; + + D3D12_RESOURCE_DESC bufferDesc = {}; + bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + bufferDesc.Alignment = 0; + bufferDesc.Width = size; + bufferDesc.Height = 1; + bufferDesc.DepthOrArraySize = 1; + bufferDesc.MipLevels = 1; + bufferDesc.Format = DXGI_FORMAT_UNKNOWN; + bufferDesc.SampleDesc.Count = 1; + bufferDesc.SampleDesc.Quality = 0; + bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + bufferDesc.Flags = D3D12_RESOURCE_FLAG_NONE; + + HRESULT hResult = device->CreateCommittedResource( + &heapProperties, + D3D12_HEAP_FLAG_NONE, + &bufferDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(&m_resource) + ); + + if (FAILED(hResult)) { + return false; + } + + bufferDesc = m_resource->GetDesc(); + UINT64 memorySizeUsed = 0; + UINT64 rowSizeInBytes = 0; + UINT rowUsed = 0; + D3D12_PLACED_SUBRESOURCE_FOOTPRINT subresourceFootprint; + device->GetCopyableFootprints(&bufferDesc, 0, 1, 0, + &subresourceFootprint, &rowUsed, &rowSizeInBytes, &memorySizeUsed); + + ComPtr tempBufferObject; + D3D12_HEAP_PROPERTIES d3dTempHeapProperties = {}; + d3dTempHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD; + + D3D12_RESOURCE_DESC d3d12TempResourceDesc = {}; + d3d12TempResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + d3d12TempResourceDesc.Alignment = 0; + d3d12TempResourceDesc.Width = memorySizeUsed; + d3d12TempResourceDesc.Height = 1; + d3d12TempResourceDesc.DepthOrArraySize = 1; + d3d12TempResourceDesc.MipLevels = 1; + d3d12TempResourceDesc.Format = DXGI_FORMAT_UNKNOWN; + d3d12TempResourceDesc.SampleDesc.Count = 1; + d3d12TempResourceDesc.SampleDesc.Quality = 0; + d3d12TempResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + d3d12TempResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE; + + hResult = device->CreateCommittedResource( + &d3dTempHeapProperties, + D3D12_HEAP_FLAG_NONE, + &d3d12TempResourceDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(&tempBufferObject) + ); + + if (FAILED(hResult)) { + return false; + } + + BYTE* pData; + tempBufferObject->Map(0, nullptr, reinterpret_cast(&pData)); + BYTE* pDstTempBuffer = reinterpret_cast(pData + subresourceFootprint.Offset); + const BYTE* pSrcData = reinterpret_cast(data); + memcpy(pDstTempBuffer, pSrcData, size); + tempBufferObject->Unmap(0, nullptr); + + commandList->CopyBufferRegion(m_resource.Get(), 0, tempBufferObject.Get(), 0, subresourceFootprint.Footprint.Width); + + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier.Transition.pResource = m_resource.Get(); + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + barrier.Transition.StateAfter = finalState; + barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + commandList->ResourceBarrier(1, &barrier); + + return true; +} + void D3D12Buffer::Shutdown() { m_resource.Reset(); }