-
Notifications
You must be signed in to change notification settings - Fork 463
Expand file tree
/
Copy pathGraphicsMemory.h
More file actions
258 lines (212 loc) · 10.2 KB
/
Copy pathGraphicsMemory.h
File metadata and controls
258 lines (212 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
//--------------------------------------------------------------------------------------
// File: GraphicsMemory.h
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
// https://go.microsoft.com/fwlink/?LinkID=615561
//--------------------------------------------------------------------------------------
#pragma once
#ifdef _GAMING_XBOX_SCARLETT
#include <d3d12_xs.h>
#elif (defined(_XBOX_ONE) && defined(_TITLE)) || defined(_GAMING_XBOX)
#include <d3d12_x.h>
#elif defined(USING_DIRECTX_HEADERS)
#include <directx/d3d12.h>
#include <dxguids/dxguids.h>
#else
#include <d3d12.h>
#endif
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <memory>
#ifdef _GAMING_XBOX
#include <gxdk.h>
#endif
#if defined(_GAMING_XBOX) && (defined(_DEBUG) || defined(PROFILE)) && (_GXDK_VER >= 0x585D073C) /* GDK Edition 221000 */
#define USING_PIX_CUSTOM_MEMORY_EVENTS
#include <tuple>
#endif
#ifndef DIRECTX_TOOLKIT_API
#ifdef DIRECTX_TOOLKIT_EXPORT
#ifdef __GNUC__
#define DIRECTX_TOOLKIT_API __attribute__ ((dllexport))
#else
#define DIRECTX_TOOLKIT_API __declspec(dllexport)
#endif
#elif defined(DIRECTX_TOOLKIT_IMPORT)
#ifdef __GNUC__
#define DIRECTX_TOOLKIT_API __attribute__ ((dllimport))
#else
#define DIRECTX_TOOLKIT_API __declspec(dllimport)
#endif
#else
#define DIRECTX_TOOLKIT_API
#endif
#endif
#if defined(DIRECTX_TOOLKIT_IMPORT) && defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4251)
#endif
namespace DirectX
{
class LinearAllocatorPage;
inline namespace DX12
{
// Works a little like a smart pointer. The memory will only be fenced by the GPU once the pointer
// has been invalidated or the user explicitly marks it for fencing.
class DIRECTX_TOOLKIT_API GraphicsResource
{
public:
GraphicsResource() noexcept;
GraphicsResource(
_In_ LinearAllocatorPage* page,
_In_ D3D12_GPU_VIRTUAL_ADDRESS gpuAddress,
_In_ ID3D12Resource* resource,
_In_ void* memory,
_In_ size_t offset,
_In_ size_t size) noexcept;
GraphicsResource(GraphicsResource&& other) noexcept;
GraphicsResource&& operator= (GraphicsResource&&) noexcept;
GraphicsResource(const GraphicsResource&) = delete;
GraphicsResource& operator= (const GraphicsResource&) = delete;
~GraphicsResource();
D3D12_GPU_VIRTUAL_ADDRESS GpuAddress() const noexcept { return mGpuAddress; }
ID3D12Resource* Resource() const noexcept { return mResource; }
void* Memory() const noexcept { return mMemory; }
size_t ResourceOffset() const noexcept { return mBufferOffset; }
size_t Size() const noexcept { return mSize; }
explicit operator bool() const noexcept { return mResource != nullptr; }
// Clear the pointer. Using operator -> will produce bad results.
void __cdecl Reset() noexcept;
void __cdecl Reset(GraphicsResource&&) noexcept;
private:
LinearAllocatorPage* mPage;
D3D12_GPU_VIRTUAL_ADDRESS mGpuAddress;
ID3D12Resource* mResource;
void* mMemory;
size_t mBufferOffset;
size_t mSize;
};
class DIRECTX_TOOLKIT_API SharedGraphicsResource
{
public:
SharedGraphicsResource() noexcept;
SharedGraphicsResource(SharedGraphicsResource&&) noexcept;
SharedGraphicsResource&& operator= (SharedGraphicsResource&&) noexcept;
SharedGraphicsResource(GraphicsResource&&);
SharedGraphicsResource&& operator= (GraphicsResource&&);
SharedGraphicsResource(const SharedGraphicsResource&) noexcept;
SharedGraphicsResource& operator= (const SharedGraphicsResource&) noexcept;
SharedGraphicsResource(const GraphicsResource&) = delete;
SharedGraphicsResource& operator= (const GraphicsResource&) = delete;
~SharedGraphicsResource();
D3D12_GPU_VIRTUAL_ADDRESS GpuAddress() const noexcept { return mSharedResource->GpuAddress(); }
ID3D12Resource* Resource() const noexcept { return mSharedResource->Resource(); }
void* Memory() const noexcept { return mSharedResource->Memory(); }
size_t ResourceOffset() const noexcept { return mSharedResource->ResourceOffset(); }
size_t Size() const noexcept { return mSharedResource->Size(); }
explicit operator bool() const noexcept { return mSharedResource != nullptr; }
bool operator == (const SharedGraphicsResource& other) const noexcept { return mSharedResource.get() == other.mSharedResource.get(); }
bool operator != (const SharedGraphicsResource& other) const noexcept { return mSharedResource.get() != other.mSharedResource.get(); }
// Clear the pointer. Using operator -> will produce bad results.
void __cdecl Reset() noexcept;
void __cdecl Reset(GraphicsResource&&);
void __cdecl Reset(SharedGraphicsResource&&) noexcept;
void __cdecl Reset(const SharedGraphicsResource& resource) noexcept;
private:
std::shared_ptr<GraphicsResource> mSharedResource;
};
//------------------------------------------------------------------------------
struct GraphicsMemoryStatistics
{
size_t committedMemory; // Bytes of memory currently committed/in-flight
size_t totalMemory; // Total bytes of memory used by the allocators
size_t totalPages; // Total page count
size_t peakCommitedMemory; // Peak commited memory value since last reset
size_t peakTotalMemory; // Peak total bytes
size_t peakTotalPages; // Peak total page count
};
//------------------------------------------------------------------------------
class GraphicsMemory
{
public:
enum Tag : uint32_t
{
TAG_GENERIC = 0,
TAG_CONSTANT,
TAG_VERTEX,
TAG_INDEX,
TAG_SPRITES,
TAG_TEXTURE,
TAG_COMPUTE,
};
DIRECTX_TOOLKIT_API explicit GraphicsMemory(_In_ ID3D12Device* device);
DIRECTX_TOOLKIT_API GraphicsMemory(GraphicsMemory&&) noexcept;
DIRECTX_TOOLKIT_API GraphicsMemory& operator= (GraphicsMemory&&) noexcept;
GraphicsMemory(GraphicsMemory const&) = delete;
GraphicsMemory& operator=(GraphicsMemory const&) = delete;
DIRECTX_TOOLKIT_API virtual ~GraphicsMemory();
// Make sure to keep the GraphicsResource handle alive as long as you need to access
// the memory on the CPU. For example, do not simply cache GpuAddress() and discard
// the GraphicsResource object, or your memory may be overwritten later.
DIRECTX_TOOLKIT_API inline GraphicsResource __cdecl Allocate(size_t size, size_t alignment = 16, uint32_t tag = TAG_GENERIC)
{
auto alloc = AllocateImpl(size, alignment);
#ifdef USING_PIX_CUSTOM_MEMORY_EVENTS
std::ignore = ReportCustomMemoryAlloc(alloc.Memory(), alloc.Size(), tag);
#else
UNREFERENCED_PARAMETER(tag);
#endif
return alloc;
}
// Version of Allocate that aligns to D3D12 constant buffer requirements
template<typename T> GraphicsResource AllocateConstant()
{
constexpr size_t alignment = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT;
constexpr size_t alignedSize = (sizeof(T) + alignment - 1) & ~(alignment - 1);
auto alloc = AllocateImpl(alignedSize, alignment);
#ifdef USING_PIX_CUSTOM_MEMORY_EVENTS
// This cast is needed to capture the type information in the PDB
std::ignore = reinterpret_cast<T*>(ReportCustomMemoryAlloc(alloc.Memory(), alloc.Size(), TAG_CONSTANT));
#endif
return alloc;
}
template<typename T> GraphicsResource AllocateConstant(const T& setData)
{
GraphicsResource alloc = AllocateConstant<T>();
memcpy(alloc.Memory(), &setData, sizeof(T));
return alloc;
}
// Submits all the pending one-shot memory to the GPU.
// The memory will be recycled once the GPU is done with it.
DIRECTX_TOOLKIT_API void __cdecl Commit(_In_ ID3D12CommandQueue* commandQueue);
// This frees up any unused memory.
// If you want to make sure all memory is reclaimed, idle the GPU before calling this.
// It is not recommended that you call this unless absolutely necessary (e.g. your
// memory budget changes at run-time, or perhaps you're changing levels in your game.)
DIRECTX_TOOLKIT_API void __cdecl GarbageCollect();
// Memory statistics
DIRECTX_TOOLKIT_API GraphicsMemoryStatistics __cdecl GetStatistics();
DIRECTX_TOOLKIT_API void __cdecl ResetStatistics();
// Properties
DIRECTX_TOOLKIT_API ID3D12Device* __cdecl GetDevice() const noexcept;
// Singleton
// Should only use nullptr for single GPU scenarios; mGPU requires a specific device
DIRECTX_TOOLKIT_API static GraphicsMemory& __cdecl Get(_In_opt_ ID3D12Device* device = nullptr);
private:
// Private implementation.
class Impl;
DIRECTX_TOOLKIT_API GraphicsResource __cdecl AllocateImpl(size_t size, size_t alignment);
#ifdef USING_PIX_CUSTOM_MEMORY_EVENTS
// The declspec is required to ensure the proper information is captured in the PDB
DIRECTX_TOOLKIT_API __declspec(allocator) static void* __cdecl ReportCustomMemoryAlloc(void* pMem, size_t size, UINT64 metadata);
#endif
std::unique_ptr<Impl> pImpl;
};
}
}
#if defined(DIRECTX_TOOLKIT_IMPORT) && defined(_MSC_VER)
#pragma warning(pop)
#endif