Diligent Engine API Reference: D:/GitHub/DiligentEngine/DiligentCore/Graphics/GraphicsEngineD3D12/include/DynamicUploadHeap.h Source File

Diligent Engine API Reference

DynamicUploadHeap.h
1 /* Copyright 2015-2018 Egor Yusov
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
12 *
13 * In no event and under no legal theory, whether in tort (including negligence),
14 * contract, or otherwise, unless required by applicable law (such as deliberate
15 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
16 * liable for any damages, including any direct, indirect, special, incidental,
17 * or consequential damages of any character arising as a result of this License or
18 * out of the use or inability to use the software (including but not limited to damages
19 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
20 * all other commercial damages or losses), even if such Contributor has been advised
21 * of the possibility of such damages.
22 */
23
24 #pragma once
25
26 #include "RingBuffer.h"
27
28 namespace Diligent
29 {
30
31 // Constant blocks must be multiples of 16 constants @ 16 bytes each
32 #define DEFAULT_ALIGN 256
33
34 struct DynamicAllocation
35 {
36 DynamicAllocation(ID3D12Resource *pBuff = nullptr, size_t ThisOffset = 0, size_t ThisSize = 0)
37 : pBuffer(pBuff), Offset(ThisOffset), Size(ThisSize) {}
38
39 //CComPtr<ID3D12Resource> pBuffer; // The D3D buffer associated with this memory.
40 ID3D12Resource *pBuffer = nullptr; // The D3D buffer associated with this memory.
41 size_t Offset = 0; // Offset from start of buffer resource
42 size_t Size = 0; // Reserved size of this allocation
43 void* CPUAddress = 0; // The CPU-writeable address
44 D3D12_GPU_VIRTUAL_ADDRESS GPUAddress = 0; // The GPU-visible address
45 #ifdef _DEBUG
46 Uint64 FrameNum = static_cast<Uint64>(-1);
47 #endif
48 };
49
50 class GPURingBuffer : public RingBuffer
51 {
52 public:
53 GPURingBuffer(size_t MaxSize, IMemoryAllocator &Allocator, ID3D12Device *pd3d12Device, bool AllowCPUAccess);
54
55 GPURingBuffer(GPURingBuffer&& rhs) :
56 RingBuffer(std::move(rhs)),
57 m_CpuVirtualAddress(rhs.m_CpuVirtualAddress),
58 m_GpuVirtualAddress(rhs.m_GpuVirtualAddress),
59 m_pBuffer(std::move(rhs.m_pBuffer))
60 {
61 rhs.m_CpuVirtualAddress = nullptr;
62 rhs.m_GpuVirtualAddress = 0;
63 rhs.m_pBuffer.Release();
64 }
65
66 GPURingBuffer& operator =(GPURingBuffer&& rhs)
67 {
68 Destroy();
69
70 static_cast<RingBuffer&>(*this) = std::move(rhs);
71 m_CpuVirtualAddress = rhs.m_CpuVirtualAddress;
72 m_GpuVirtualAddress = rhs.m_GpuVirtualAddress;
73 m_pBuffer = std::move(rhs.m_pBuffer);
74 rhs.m_CpuVirtualAddress = 0;
75 rhs.m_GpuVirtualAddress = 0;
76
77 return *this;
78 }
79
80 ~GPURingBuffer();
81
82 DynamicAllocation Allocate(size_t SizeInBytes)
83 {
84 auto Offset = RingBuffer::Allocate(SizeInBytes);
85 if (Offset != RingBuffer::InvalidOffset)
86 {
87 DynamicAllocation DynAlloc(m_pBuffer, Offset, SizeInBytes);
88 DynAlloc.GPUAddress = m_GpuVirtualAddress + Offset;
89 DynAlloc.CPUAddress = m_CpuVirtualAddress;
90 if(DynAlloc.CPUAddress)
91 DynAlloc.CPUAddress = reinterpret_cast<char*>(DynAlloc.CPUAddress) + Offset;
92 return DynAlloc;
93 }
94 else
95 {
96 return DynamicAllocation(nullptr, 0, 0);
97 }
98 }
99
100 GPURingBuffer(const GPURingBuffer&) = delete;
101 GPURingBuffer& operator =(GPURingBuffer&) = delete;
102
103 private:
104 void Destroy();
105
106 void* m_CpuVirtualAddress;
107 D3D12_GPU_VIRTUAL_ADDRESS m_GpuVirtualAddress;
108 CComPtr<ID3D12Resource> m_pBuffer;
109 };
110
111 class DynamicUploadHeap
112 {
113 public:
114
115 DynamicUploadHeap(IMemoryAllocator &Allocator, bool bIsCPUAccessible, class RenderDeviceD3D12Impl* pDevice, size_t InitialSize);
116
117 DynamicUploadHeap(const DynamicUploadHeap&)=delete;
118 DynamicUploadHeap(DynamicUploadHeap&&)=delete;
119 DynamicUploadHeap& operator=(const DynamicUploadHeap&)=delete;
120 DynamicUploadHeap& operator=(DynamicUploadHeap&&)=delete;
121
122 DynamicAllocation Allocate( size_t SizeInBytes, size_t Alignment = DEFAULT_ALIGN );
123
124 void FinishFrame(Uint64 FenceValue, Uint64 LastCompletedFenceValue);
125
126 private:
127 const bool m_bIsCPUAccessible;
128 // When a chunk of dynamic memory is requested, the heap first tries to allocate the memory in the largest GPU buffer.
129 // If allocation fails, a new ring buffer is created that provides enough space and requests memory from that buffer.
130 // Only the largest buffer is used for allocation and all other buffers are released when GPU is done with corresponding frames
131 std::vector<GPURingBuffer, STDAllocatorRawMem<GPURingBuffer> > m_RingBuffers;
132 IMemoryAllocator &m_Allocator;
133 RenderDeviceD3D12Impl* m_pDeviceD3D12 = nullptr;
134 //std::mutex m_Mutex;
135 };
136
137 }
Diligent
Namespace for the OpenGL implementation of the graphics engine.
Definition: BufferD3D11Impl.h:34
std
Definition: AdvancedMath.h:316