9constexpr uint64_t kAlignment = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT;
11uint64_t AlignUp(uint64_t value) {
12 return (value + kAlignment - 1) & ~(kAlignment - 1);
20 m_pageSize = AlignUp(pageSize);
21 m_frames.resize(frameCount);
26 if (frameIndex >= m_frames.size())
return;
27 m_current = frameIndex;
28 m_frames[frameIndex].page = 0;
29 m_frames[frameIndex].offset = 0;
33 if (!m_device || m_current >= m_frames.size() || size == 0)
return false;
35 const uint64_t aligned = AlignUp(size);
36 Frame& frame = m_frames[m_current];
38 while (frame.page < frame.pages.size()) {
39 Page& page = frame.pages[frame.page];
40 if (frame.offset + aligned <= page.size) {
41 out.
cpu = page.cpu + frame.offset;
42 out.
gpu = page.gpu + frame.offset;
43 frame.offset += aligned;
51 if (!CreatePage(aligned > m_pageSize ? aligned : m_pageSize, page))
53 frame.pages.push_back(std::move(page));
54 frame.page = frame.pages.size() - 1;
56 Page& fresh = frame.pages.back();
59 frame.offset = aligned;
64 for (Frame& frame : m_frames) {
65 for (Page& page : frame.pages) {
66 if (page.resource && page.cpu) page.resource->Unmap(0,
nullptr);
77bool DirectX12UploadRing::CreatePage(uint64_t size, Page& out) {
78 D3D12_HEAP_PROPERTIES heapProps = {};
79 heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
81 D3D12_RESOURCE_DESC desc = {};
82 desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
85 desc.DepthOrArraySize = 1;
87 desc.Format = DXGI_FORMAT_UNKNOWN;
88 desc.SampleDesc.Count = 1;
89 desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
91 HRESULT hr = m_device->CreateCommittedResource(
92 &heapProps, D3D12_HEAP_FLAG_NONE, &desc,
93 D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
94 IID_PPV_ARGS(&out.resource));
96 SLEAK_ERROR(
"Failed to create upload ring page! HRESULT: 0x{:08X}",
97 static_cast<unsigned int>(hr));
100 out.resource->SetName(L
"UploadRingPage");
102 D3D12_RANGE noRead = {0, 0};
103 void* mapped =
nullptr;
104 hr = out.resource->Map(0, &noRead, &mapped);
106 SLEAK_ERROR(
"Failed to map upload ring page! HRESULT: 0x{:08X}",
107 static_cast<unsigned int>(hr));
108 out.resource.Reset();
111 out.cpu =
static_cast<uint8_t*
>(mapped);
112 out.gpu = out.resource->GetGPUVirtualAddress();
void Release()
Unmaps and frees every page. The GPU must be idle.
void BeginFrame(uint32_t frameIndex)
Rewinds the frame's pages. The GPU must be done with that frame.
bool Allocate(uint64_t size, Allocation &out)
Returns 256-byte aligned memory valid until the frame is reused.
void Initialize(ID3D12Device *device, uint32_t frameCount, uint64_t pageSize)
Stores the device and sizes the ring. Pages are created on demand.
Backend-facing rendering layer shared by the four graphics backends.
Root namespace for everything the engine exposes.
CPU write pointer and matching GPU address of one allocation.
D3D12_GPU_VIRTUAL_ADDRESS gpu