SleakEngine
0.1.0
C++23 multi-backend game engine
Toggle main menu visibility
Loading...
Searching...
No Matches
DirectX12UploadContext.cpp
Go to the documentation of this file.
1
#include <
Core/Logger.hpp
>
2
#include <
Graphics/DirectX12/DirectX12UploadContext.hpp
>
3
#include <utility>
4
5
namespace
Sleak
{
6
namespace
RenderEngine
{
7
8
bool
DirectX12UploadContext::Initialize
(ID3D12Device* device,
9
ID3D12CommandQueue* queue) {
10
Release
();
11
if
(!device || !queue)
return
false
;
12
13
HRESULT hr =
14
device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence));
15
if
(FAILED(hr)) {
16
SLEAK_ERROR
(
"Failed to create upload fence! HRESULT: 0x{:08X}"
,
17
static_cast<
unsigned
int
>
(hr));
18
return
false
;
19
}
20
21
m_event = CreateEvent(
nullptr
, FALSE, FALSE,
nullptr
);
22
if
(!m_event) {
23
SLEAK_ERROR
(
"Failed to create upload fence event!"
);
24
m_fence.Reset();
25
return
false
;
26
}
27
28
m_device = device;
29
m_queue = queue;
30
return
true
;
31
}
32
33
ID3D12GraphicsCommandList*
DirectX12UploadContext::GetCommandList
() {
34
if
(m_recording)
return
m_commandList.Get();
35
if
(!m_device)
return
nullptr
;
36
37
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> allocator;
38
HRESULT hr = S_OK;
39
if
(!m_freeAllocators.empty()) {
40
allocator = std::move(m_freeAllocators.back());
41
m_freeAllocators.pop_back();
42
hr = allocator->Reset();
43
}
else
{
44
hr = m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,
45
IID_PPV_ARGS(&allocator));
46
}
47
if
(FAILED(hr)) {
48
SLEAK_ERROR
(
"Failed to prepare upload allocator! HRESULT: 0x{:08X}"
,
49
static_cast<
unsigned
int
>
(hr));
50
return
nullptr
;
51
}
52
53
if
(m_commandList) {
54
hr = m_commandList->Reset(allocator.Get(),
nullptr
);
55
}
else
{
56
hr = m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
57
allocator.Get(),
nullptr
,
58
IID_PPV_ARGS(&m_commandList));
59
if
(SUCCEEDED(hr)) m_commandList->SetName(L
"UploadCommandList"
);
60
}
61
if
(FAILED(hr)) {
62
SLEAK_ERROR
(
"Failed to open upload command list! HRESULT: 0x{:08X}"
,
63
static_cast<
unsigned
int
>
(hr));
64
return
nullptr
;
65
}
66
67
m_open.allocator = std::move(allocator);
68
m_recording =
true
;
69
return
m_commandList.Get();
70
}
71
72
void
*
DirectX12UploadContext::AllocateStaging
(uint64_t size,
73
ID3D12Resource** resource) {
74
if
(!resource || size == 0 || !
GetCommandList
())
return
nullptr
;
75
76
D3D12_HEAP_PROPERTIES heapProps = {};
77
heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
78
79
D3D12_RESOURCE_DESC desc = {};
80
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
81
desc.Width = size;
82
desc.Height = 1;
83
desc.DepthOrArraySize = 1;
84
desc.MipLevels = 1;
85
desc.Format = DXGI_FORMAT_UNKNOWN;
86
desc.SampleDesc.Count = 1;
87
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
88
89
Microsoft::WRL::ComPtr<ID3D12Resource> staging;
90
HRESULT hr = m_device->CreateCommittedResource(
91
&heapProps, D3D12_HEAP_FLAG_NONE, &desc,
92
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr
, IID_PPV_ARGS(&staging));
93
if
(FAILED(hr)) {
94
SLEAK_ERROR
(
"Failed to create staging buffer! HRESULT: 0x{:08X}"
,
95
static_cast<
unsigned
int
>
(hr));
96
return
nullptr
;
97
}
98
99
D3D12_RANGE noRead = {0, 0};
100
void
* mapped =
nullptr
;
101
hr = staging->Map(0, &noRead, &mapped);
102
if
(FAILED(hr)) {
103
SLEAK_ERROR
(
"Failed to map staging buffer! HRESULT: 0x{:08X}"
,
104
static_cast<
unsigned
int
>
(hr));
105
return
nullptr
;
106
}
107
108
*resource = staging.Get();
109
m_open.staging.push_back(std::move(staging));
110
return
mapped;
111
}
112
113
void
DirectX12UploadContext::Submit
() {
114
if
(!m_recording)
return
;
115
m_recording =
false
;
116
117
HRESULT hr = m_commandList->Close();
118
if
(FAILED(hr)) {
119
SLEAK_ERROR
(
"Failed to close upload command list! HRESULT: 0x{:08X}"
,
120
static_cast<
unsigned
int
>
(hr));
121
m_open = Batch{};
122
return
;
123
}
124
125
ID3D12CommandList* lists[] = {m_commandList.Get()};
126
m_queue->ExecuteCommandLists(1, lists);
127
m_open.fenceValue = ++m_fenceValue;
128
m_queue->Signal(m_fence.Get(), m_fenceValue);
129
130
m_inFlight.push_back(std::move(m_open));
131
m_open = Batch{};
132
}
133
134
void
DirectX12UploadContext::Flush
() {
135
Submit
();
136
if
(!m_fence)
return
;
137
if
(m_fence->GetCompletedValue() < m_fenceValue) {
138
m_fence->SetEventOnCompletion(m_fenceValue, m_event);
139
WaitForSingleObject(m_event, INFINITE);
140
}
141
Retire
();
142
}
143
144
void
DirectX12UploadContext::Retire
() {
145
if
(!m_fence)
return
;
146
const
uint64_t completed = m_fence->GetCompletedValue();
147
148
size_t
finished = 0;
149
while
(finished < m_inFlight.size() &&
150
m_inFlight[finished].fenceValue <= completed) {
151
m_freeAllocators.push_back(std::move(m_inFlight[finished].allocator));
152
++finished;
153
}
154
m_inFlight.erase(m_inFlight.begin(), m_inFlight.begin() + finished);
155
}
156
157
void
DirectX12UploadContext::Release
() {
158
if
(m_queue && m_fence)
Flush
();
159
160
m_inFlight.clear();
161
m_freeAllocators.clear();
162
m_open = Batch{};
163
m_recording =
false
;
164
m_commandList.Reset();
165
m_fence.Reset();
166
if
(m_event) {
167
CloseHandle(m_event);
168
m_event =
nullptr
;
169
}
170
m_fenceValue = 0;
171
m_device =
nullptr
;
172
m_queue =
nullptr
;
173
}
174
175
}
// namespace RenderEngine
176
}
// namespace Sleak
DirectX12UploadContext.hpp
Logger.hpp
SLEAK_ERROR
#define SLEAK_ERROR(...)
Definition
Logger.hpp:22
Sleak::RenderEngine::DirectX12UploadContext::Release
void Release()
Flushes outstanding work and frees everything.
Definition
DirectX12UploadContext.cpp:157
Sleak::RenderEngine::DirectX12UploadContext::AllocateStaging
void * AllocateStaging(uint64_t size, ID3D12Resource **resource)
Returns a mapped upload buffer that lives until the open batch is done.
Definition
DirectX12UploadContext.cpp:72
Sleak::RenderEngine::DirectX12UploadContext::GetCommandList
ID3D12GraphicsCommandList * GetCommandList()
Returns the open copy command list, starting a new batch if needed.
Definition
DirectX12UploadContext.cpp:33
Sleak::RenderEngine::DirectX12UploadContext::Retire
void Retire()
Frees staging memory of batches the GPU has finished.
Definition
DirectX12UploadContext.cpp:144
Sleak::RenderEngine::DirectX12UploadContext::Initialize
bool Initialize(ID3D12Device *device, ID3D12CommandQueue *queue)
Creates the fence used to track submitted batches.
Definition
DirectX12UploadContext.cpp:8
Sleak::RenderEngine::DirectX12UploadContext::Submit
void Submit()
Executes the recorded copies without waiting for them.
Definition
DirectX12UploadContext.cpp:113
Sleak::RenderEngine::DirectX12UploadContext::Flush
void Flush()
Submits and blocks until every batch has finished on the GPU.
Definition
DirectX12UploadContext.cpp:134
Sleak::RenderEngine
Backend-facing rendering layer shared by the four graphics backends.
Definition
Application.hpp:60
Sleak
Root namespace for everything the engine exposes.
Definition
Camera.hpp:10
src
Graphics
DirectX12
DirectX12UploadContext.cpp
Generated on
for SleakEngine by
1.18.0