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 }
Namespace for the OpenGL implementation of the graphics engine.
Definition: BufferD3D11Impl.h:34
Definition: AdvancedMath.h:316