[D3D12] Detach UploadBufferPool and DescriptorHeapPool from D3D12Context
This commit is contained in:
parent
f23ba862f6
commit
b4af63fe31
|
@ -435,16 +435,16 @@ uint32_t D3D12CommandProcessor::GetRootExtraParameterIndices(
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t D3D12CommandProcessor::RequestViewDescriptors(
|
uint64_t D3D12CommandProcessor::RequestViewDescriptors(
|
||||||
uint64_t previous_full_update, uint32_t count_for_partial_update,
|
uint64_t previous_heap_index, uint32_t count_for_partial_update,
|
||||||
uint32_t count_for_full_update, D3D12_CPU_DESCRIPTOR_HANDLE& cpu_handle_out,
|
uint32_t count_for_full_update, D3D12_CPU_DESCRIPTOR_HANDLE& cpu_handle_out,
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE& gpu_handle_out) {
|
D3D12_GPU_DESCRIPTOR_HANDLE& gpu_handle_out) {
|
||||||
uint32_t descriptor_index;
|
uint32_t descriptor_index;
|
||||||
uint64_t current_full_update =
|
uint64_t current_heap_index = view_heap_pool_->Request(
|
||||||
view_heap_pool_->Request(previous_full_update, count_for_partial_update,
|
GetD3D12Context()->GetCurrentFrame(), previous_heap_index,
|
||||||
count_for_full_update, descriptor_index);
|
count_for_partial_update, count_for_full_update, descriptor_index);
|
||||||
if (current_full_update == 0) {
|
if (current_heap_index == ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid) {
|
||||||
// There was an error.
|
// There was an error.
|
||||||
return 0;
|
return ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid;
|
||||||
}
|
}
|
||||||
ID3D12DescriptorHeap* heap = view_heap_pool_->GetLastRequestHeap();
|
ID3D12DescriptorHeap* heap = view_heap_pool_->GetLastRequestHeap();
|
||||||
if (current_view_heap_ != heap) {
|
if (current_view_heap_ != heap) {
|
||||||
|
@ -457,20 +457,20 @@ uint64_t D3D12CommandProcessor::RequestViewDescriptors(
|
||||||
view_heap_pool_->GetLastRequestHeapCPUStart(), descriptor_index);
|
view_heap_pool_->GetLastRequestHeapCPUStart(), descriptor_index);
|
||||||
gpu_handle_out = provider->OffsetViewDescriptor(
|
gpu_handle_out = provider->OffsetViewDescriptor(
|
||||||
view_heap_pool_->GetLastRequestHeapGPUStart(), descriptor_index);
|
view_heap_pool_->GetLastRequestHeapGPUStart(), descriptor_index);
|
||||||
return current_full_update;
|
return current_heap_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t D3D12CommandProcessor::RequestSamplerDescriptors(
|
uint64_t D3D12CommandProcessor::RequestSamplerDescriptors(
|
||||||
uint64_t previous_full_update, uint32_t count_for_partial_update,
|
uint64_t previous_heap_index, uint32_t count_for_partial_update,
|
||||||
uint32_t count_for_full_update, D3D12_CPU_DESCRIPTOR_HANDLE& cpu_handle_out,
|
uint32_t count_for_full_update, D3D12_CPU_DESCRIPTOR_HANDLE& cpu_handle_out,
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE& gpu_handle_out) {
|
D3D12_GPU_DESCRIPTOR_HANDLE& gpu_handle_out) {
|
||||||
uint32_t descriptor_index;
|
uint32_t descriptor_index;
|
||||||
uint64_t current_full_update = sampler_heap_pool_->Request(
|
uint64_t current_heap_index = sampler_heap_pool_->Request(
|
||||||
previous_full_update, count_for_partial_update, count_for_full_update,
|
GetD3D12Context()->GetCurrentFrame(), previous_heap_index,
|
||||||
descriptor_index);
|
count_for_partial_update, count_for_full_update, descriptor_index);
|
||||||
if (current_full_update == 0) {
|
if (current_heap_index == ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid) {
|
||||||
// There was an error.
|
// There was an error.
|
||||||
return 0;
|
return ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid;
|
||||||
}
|
}
|
||||||
ID3D12DescriptorHeap* heap = sampler_heap_pool_->GetLastRequestHeap();
|
ID3D12DescriptorHeap* heap = sampler_heap_pool_->GetLastRequestHeap();
|
||||||
if (current_sampler_heap_ != heap) {
|
if (current_sampler_heap_ != heap) {
|
||||||
|
@ -485,7 +485,7 @@ uint64_t D3D12CommandProcessor::RequestSamplerDescriptors(
|
||||||
sampler_heap_pool_->GetLastRequestHeapCPUStart().ptr + descriptor_offset;
|
sampler_heap_pool_->GetLastRequestHeapCPUStart().ptr + descriptor_offset;
|
||||||
gpu_handle_out.ptr =
|
gpu_handle_out.ptr =
|
||||||
sampler_heap_pool_->GetLastRequestHeapGPUStart().ptr + descriptor_offset;
|
sampler_heap_pool_->GetLastRequestHeapGPUStart().ptr + descriptor_offset;
|
||||||
return current_full_update;
|
return current_heap_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3D12Resource* D3D12CommandProcessor::RequestScratchGPUBuffer(
|
ID3D12Resource* D3D12CommandProcessor::RequestScratchGPUBuffer(
|
||||||
|
@ -705,8 +705,7 @@ bool D3D12CommandProcessor::SetupContext() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto context = GetD3D12Context();
|
auto provider = GetD3D12Context()->GetD3D12Provider();
|
||||||
auto provider = context->GetD3D12Provider();
|
|
||||||
auto device = provider->GetDevice();
|
auto device = provider->GetDevice();
|
||||||
auto direct_queue = provider->GetDirectQueue();
|
auto direct_queue = provider->GetDirectQueue();
|
||||||
|
|
||||||
|
@ -721,12 +720,12 @@ bool D3D12CommandProcessor::SetupContext() {
|
||||||
deferred_command_list_ = std::make_unique<DeferredCommandList>(this);
|
deferred_command_list_ = std::make_unique<DeferredCommandList>(this);
|
||||||
|
|
||||||
constant_buffer_pool_ =
|
constant_buffer_pool_ =
|
||||||
std::make_unique<ui::d3d12::UploadBufferPool>(context, 1024 * 1024);
|
std::make_unique<ui::d3d12::UploadBufferPool>(device, 1024 * 1024);
|
||||||
view_heap_pool_ = std::make_unique<ui::d3d12::DescriptorHeapPool>(
|
view_heap_pool_ = std::make_unique<ui::d3d12::DescriptorHeapPool>(
|
||||||
context, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 32768);
|
device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 32768);
|
||||||
// Can't create a shader-visible heap with more than 2048 samplers.
|
// Can't create a shader-visible heap with more than 2048 samplers.
|
||||||
sampler_heap_pool_ = std::make_unique<ui::d3d12::DescriptorHeapPool>(
|
sampler_heap_pool_ = std::make_unique<ui::d3d12::DescriptorHeapPool>(
|
||||||
context, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, 2048);
|
device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, 2048);
|
||||||
|
|
||||||
shared_memory_ =
|
shared_memory_ =
|
||||||
std::make_unique<SharedMemory>(this, memory_, &trace_writer_);
|
std::make_unique<SharedMemory>(this, memory_, &trace_writer_);
|
||||||
|
@ -1068,8 +1067,10 @@ void D3D12CommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
|
||||||
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
||||||
if (RequestViewDescriptors(0, 2, 2, descriptor_cpu_start,
|
if (RequestViewDescriptors(ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid,
|
||||||
descriptor_gpu_start) != 0) {
|
2, 2, descriptor_cpu_start,
|
||||||
|
descriptor_gpu_start) !=
|
||||||
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid) {
|
||||||
TextureFormat frontbuffer_format;
|
TextureFormat frontbuffer_format;
|
||||||
if (texture_cache_->RequestSwapTexture(descriptor_cpu_start,
|
if (texture_cache_->RequestSwapTexture(descriptor_cpu_start,
|
||||||
frontbuffer_format)) {
|
frontbuffer_format)) {
|
||||||
|
@ -1818,8 +1819,8 @@ bool D3D12CommandProcessor::BeginFrame() {
|
||||||
cbuffer_bindings_float_pixel_.up_to_date = false;
|
cbuffer_bindings_float_pixel_.up_to_date = false;
|
||||||
cbuffer_bindings_bool_loop_.up_to_date = false;
|
cbuffer_bindings_bool_loop_.up_to_date = false;
|
||||||
cbuffer_bindings_fetch_.up_to_date = false;
|
cbuffer_bindings_fetch_.up_to_date = false;
|
||||||
draw_view_full_update_ = 0;
|
draw_view_heap_index_ = ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid;
|
||||||
draw_sampler_full_update_ = 0;
|
draw_sampler_heap_index_ = ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid;
|
||||||
texture_bindings_written_vertex_ = false;
|
texture_bindings_written_vertex_ = false;
|
||||||
texture_bindings_written_pixel_ = false;
|
texture_bindings_written_pixel_ = false;
|
||||||
samplers_written_vertex_ = false;
|
samplers_written_vertex_ = false;
|
||||||
|
@ -1836,9 +1837,9 @@ bool D3D12CommandProcessor::BeginFrame() {
|
||||||
}
|
}
|
||||||
deferred_command_list_->Reset();
|
deferred_command_list_->Reset();
|
||||||
|
|
||||||
constant_buffer_pool_->BeginFrame();
|
constant_buffer_pool_->Reclaim(last_completed_frame);
|
||||||
view_heap_pool_->BeginFrame();
|
view_heap_pool_->Reclaim(last_completed_frame);
|
||||||
sampler_heap_pool_->BeginFrame();
|
sampler_heap_pool_->Reclaim(last_completed_frame);
|
||||||
|
|
||||||
shared_memory_->BeginFrame();
|
shared_memory_->BeginFrame();
|
||||||
|
|
||||||
|
@ -1858,16 +1859,12 @@ bool D3D12CommandProcessor::EndFrame() {
|
||||||
|
|
||||||
assert_false(scratch_buffer_used_);
|
assert_false(scratch_buffer_used_);
|
||||||
|
|
||||||
primitive_converter_->EndFrame();
|
|
||||||
|
|
||||||
pipeline_cache_->EndFrame();
|
pipeline_cache_->EndFrame();
|
||||||
|
|
||||||
render_target_cache_->EndFrame();
|
render_target_cache_->EndFrame();
|
||||||
|
|
||||||
texture_cache_->EndFrame();
|
texture_cache_->EndFrame();
|
||||||
|
|
||||||
shared_memory_->EndFrame();
|
|
||||||
|
|
||||||
// Submit barriers now because resources the queued barriers are for may be
|
// Submit barriers now because resources the queued barriers are for may be
|
||||||
// destroyed between frames.
|
// destroyed between frames.
|
||||||
SubmitBarriers();
|
SubmitBarriers();
|
||||||
|
@ -1888,10 +1885,6 @@ bool D3D12CommandProcessor::EndFrame() {
|
||||||
pix_capturing_ = false;
|
pix_capturing_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sampler_heap_pool_->EndFrame();
|
|
||||||
view_heap_pool_->EndFrame();
|
|
||||||
constant_buffer_pool_->EndFrame();
|
|
||||||
|
|
||||||
auto context = GetD3D12Context();
|
auto context = GetD3D12Context();
|
||||||
context->EndSwap();
|
context->EndSwap();
|
||||||
current_queue_frame_ = UINT32_MAX;
|
current_queue_frame_ = UINT32_MAX;
|
||||||
|
@ -2633,8 +2626,10 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
|
||||||
bool D3D12CommandProcessor::UpdateBindings(
|
bool D3D12CommandProcessor::UpdateBindings(
|
||||||
const D3D12Shader* vertex_shader, const D3D12Shader* pixel_shader,
|
const D3D12Shader* vertex_shader, const D3D12Shader* pixel_shader,
|
||||||
ID3D12RootSignature* root_signature) {
|
ID3D12RootSignature* root_signature) {
|
||||||
auto provider = GetD3D12Context()->GetD3D12Provider();
|
auto context = GetD3D12Context();
|
||||||
|
auto provider = context->GetD3D12Provider();
|
||||||
auto device = provider->GetDevice();
|
auto device = provider->GetDevice();
|
||||||
|
auto current_frame = context->GetCurrentFrame();
|
||||||
auto& regs = *register_file_;
|
auto& regs = *register_file_;
|
||||||
|
|
||||||
#if FINE_GRAINED_DRAW_SCOPES
|
#if FINE_GRAINED_DRAW_SCOPES
|
||||||
|
@ -2769,9 +2764,9 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||||
|
|
||||||
// Update constant buffers.
|
// Update constant buffers.
|
||||||
if (!cbuffer_bindings_system_.up_to_date) {
|
if (!cbuffer_bindings_system_.up_to_date) {
|
||||||
uint8_t* system_constants = constant_buffer_pool_->RequestFull(
|
uint8_t* system_constants = constant_buffer_pool_->Request(
|
||||||
xe::align(uint32_t(sizeof(system_constants_)), 256u), nullptr, nullptr,
|
current_frame, xe::align(uint32_t(sizeof(system_constants_)), 256u),
|
||||||
&cbuffer_bindings_system_.buffer_address);
|
nullptr, nullptr, &cbuffer_bindings_system_.buffer_address);
|
||||||
if (system_constants == nullptr) {
|
if (system_constants == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2781,8 +2776,8 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||||
write_system_constant_view = true;
|
write_system_constant_view = true;
|
||||||
}
|
}
|
||||||
if (!cbuffer_bindings_float_vertex_.up_to_date) {
|
if (!cbuffer_bindings_float_vertex_.up_to_date) {
|
||||||
uint8_t* float_constants = constant_buffer_pool_->RequestFull(
|
uint8_t* float_constants = constant_buffer_pool_->Request(
|
||||||
float_constant_size_vertex, nullptr, nullptr,
|
current_frame, float_constant_size_vertex, nullptr, nullptr,
|
||||||
&cbuffer_bindings_float_vertex_.buffer_address);
|
&cbuffer_bindings_float_vertex_.buffer_address);
|
||||||
if (float_constants == nullptr) {
|
if (float_constants == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -2806,8 +2801,8 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||||
write_float_constant_view_vertex = true;
|
write_float_constant_view_vertex = true;
|
||||||
}
|
}
|
||||||
if (!cbuffer_bindings_float_pixel_.up_to_date) {
|
if (!cbuffer_bindings_float_pixel_.up_to_date) {
|
||||||
uint8_t* float_constants = constant_buffer_pool_->RequestFull(
|
uint8_t* float_constants = constant_buffer_pool_->Request(
|
||||||
float_constant_size_pixel, nullptr, nullptr,
|
current_frame, float_constant_size_pixel, nullptr, nullptr,
|
||||||
&cbuffer_bindings_float_pixel_.buffer_address);
|
&cbuffer_bindings_float_pixel_.buffer_address);
|
||||||
if (float_constants == nullptr) {
|
if (float_constants == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -2836,8 +2831,8 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||||
}
|
}
|
||||||
if (!cbuffer_bindings_bool_loop_.up_to_date) {
|
if (!cbuffer_bindings_bool_loop_.up_to_date) {
|
||||||
uint32_t* bool_loop_constants =
|
uint32_t* bool_loop_constants =
|
||||||
reinterpret_cast<uint32_t*>(constant_buffer_pool_->RequestFull(
|
reinterpret_cast<uint32_t*>(constant_buffer_pool_->Request(
|
||||||
768, nullptr, nullptr,
|
current_frame, 768, nullptr, nullptr,
|
||||||
&cbuffer_bindings_bool_loop_.buffer_address));
|
&cbuffer_bindings_bool_loop_.buffer_address));
|
||||||
if (bool_loop_constants == nullptr) {
|
if (bool_loop_constants == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -2856,8 +2851,9 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||||
write_bool_loop_constant_view = true;
|
write_bool_loop_constant_view = true;
|
||||||
}
|
}
|
||||||
if (!cbuffer_bindings_fetch_.up_to_date) {
|
if (!cbuffer_bindings_fetch_.up_to_date) {
|
||||||
uint8_t* fetch_constants = constant_buffer_pool_->RequestFull(
|
uint8_t* fetch_constants =
|
||||||
768, nullptr, nullptr, &cbuffer_bindings_fetch_.buffer_address);
|
constant_buffer_pool_->Request(current_frame, 768, nullptr, nullptr,
|
||||||
|
&cbuffer_bindings_fetch_.buffer_address);
|
||||||
if (fetch_constants == nullptr) {
|
if (fetch_constants == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2901,10 +2897,10 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE view_cpu_handle;
|
D3D12_CPU_DESCRIPTOR_HANDLE view_cpu_handle;
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE view_gpu_handle;
|
D3D12_GPU_DESCRIPTOR_HANDLE view_gpu_handle;
|
||||||
uint32_t descriptor_size_view = provider->GetViewDescriptorSize();
|
uint32_t descriptor_size_view = provider->GetViewDescriptorSize();
|
||||||
uint64_t view_full_update_index = RequestViewDescriptors(
|
uint64_t view_heap_index = RequestViewDescriptors(
|
||||||
draw_view_full_update_, view_count_partial_update, view_count_full_update,
|
draw_view_heap_index_, view_count_partial_update, view_count_full_update,
|
||||||
view_cpu_handle, view_gpu_handle);
|
view_cpu_handle, view_gpu_handle);
|
||||||
if (view_full_update_index == 0) {
|
if (view_heap_index == ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid) {
|
||||||
XELOGE("Failed to allocate view descriptors!");
|
XELOGE("Failed to allocate view descriptors!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2918,18 +2914,20 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE sampler_cpu_handle = {};
|
D3D12_CPU_DESCRIPTOR_HANDLE sampler_cpu_handle = {};
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE sampler_gpu_handle = {};
|
D3D12_GPU_DESCRIPTOR_HANDLE sampler_gpu_handle = {};
|
||||||
uint32_t descriptor_size_sampler = provider->GetSamplerDescriptorSize();
|
uint32_t descriptor_size_sampler = provider->GetSamplerDescriptorSize();
|
||||||
uint64_t sampler_full_update_index = 0;
|
uint64_t sampler_heap_index =
|
||||||
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid;
|
||||||
if (sampler_count_vertex != 0 || sampler_count_pixel != 0) {
|
if (sampler_count_vertex != 0 || sampler_count_pixel != 0) {
|
||||||
sampler_full_update_index = RequestSamplerDescriptors(
|
sampler_heap_index = RequestSamplerDescriptors(
|
||||||
draw_sampler_full_update_, sampler_count_partial_update,
|
draw_sampler_heap_index_, sampler_count_partial_update,
|
||||||
sampler_count_vertex + sampler_count_pixel, sampler_cpu_handle,
|
sampler_count_vertex + sampler_count_pixel, sampler_cpu_handle,
|
||||||
sampler_gpu_handle);
|
sampler_gpu_handle);
|
||||||
if (sampler_full_update_index == 0) {
|
if (sampler_heap_index ==
|
||||||
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid) {
|
||||||
XELOGE("Failed to allocate sampler descriptors!");
|
XELOGE("Failed to allocate sampler descriptors!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (draw_view_full_update_ != view_full_update_index) {
|
if (draw_view_heap_index_ != view_heap_index) {
|
||||||
// Need to update all view descriptors.
|
// Need to update all view descriptors.
|
||||||
write_system_constant_view = true;
|
write_system_constant_view = true;
|
||||||
write_fetch_constant_view = true;
|
write_fetch_constant_view = true;
|
||||||
|
@ -2957,7 +2955,8 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||||
current_graphics_root_up_to_date_ &=
|
current_graphics_root_up_to_date_ &=
|
||||||
~(1u << kRootParameter_SharedMemoryAndEDRAM);
|
~(1u << kRootParameter_SharedMemoryAndEDRAM);
|
||||||
}
|
}
|
||||||
if (draw_sampler_full_update_ != sampler_full_update_index) {
|
if (sampler_heap_index != ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid &&
|
||||||
|
draw_sampler_heap_index_ != sampler_heap_index) {
|
||||||
write_samplers_vertex = sampler_count_vertex != 0;
|
write_samplers_vertex = sampler_count_vertex != 0;
|
||||||
write_samplers_pixel = sampler_count_pixel != 0;
|
write_samplers_pixel = sampler_count_pixel != 0;
|
||||||
samplers_written_vertex_ = false;
|
samplers_written_vertex_ = false;
|
||||||
|
@ -3085,8 +3084,10 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrote new descriptors on the current page.
|
// Wrote new descriptors on the current page.
|
||||||
draw_view_full_update_ = view_full_update_index;
|
draw_view_heap_index_ = view_heap_index;
|
||||||
draw_sampler_full_update_ = sampler_full_update_index;
|
if (sampler_heap_index != ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid) {
|
||||||
|
draw_sampler_heap_index_ = sampler_heap_index;
|
||||||
|
}
|
||||||
|
|
||||||
// Update the root parameters.
|
// Update the root parameters.
|
||||||
if (!(current_graphics_root_up_to_date_ &
|
if (!(current_graphics_root_up_to_date_ &
|
||||||
|
|
|
@ -92,13 +92,13 @@ class D3D12CommandProcessor : public CommandProcessor {
|
||||||
}
|
}
|
||||||
// Request and automatically rebind descriptors on the draw command list.
|
// Request and automatically rebind descriptors on the draw command list.
|
||||||
// Refer to DescriptorHeapPool::Request for partial/full update explanation.
|
// Refer to DescriptorHeapPool::Request for partial/full update explanation.
|
||||||
uint64_t RequestViewDescriptors(uint64_t previous_full_update,
|
uint64_t RequestViewDescriptors(uint64_t previous_heap_index,
|
||||||
uint32_t count_for_partial_update,
|
uint32_t count_for_partial_update,
|
||||||
uint32_t count_for_full_update,
|
uint32_t count_for_full_update,
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE& cpu_handle_out,
|
D3D12_CPU_DESCRIPTOR_HANDLE& cpu_handle_out,
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE& gpu_handle_out);
|
D3D12_GPU_DESCRIPTOR_HANDLE& gpu_handle_out);
|
||||||
uint64_t RequestSamplerDescriptors(
|
uint64_t RequestSamplerDescriptors(
|
||||||
uint64_t previous_full_update, uint32_t count_for_partial_update,
|
uint64_t previous_heap_index, uint32_t count_for_partial_update,
|
||||||
uint32_t count_for_full_update,
|
uint32_t count_for_full_update,
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE& cpu_handle_out,
|
D3D12_CPU_DESCRIPTOR_HANDLE& cpu_handle_out,
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE& gpu_handle_out);
|
D3D12_GPU_DESCRIPTOR_HANDLE& gpu_handle_out);
|
||||||
|
@ -362,8 +362,8 @@ class D3D12CommandProcessor : public CommandProcessor {
|
||||||
ConstantBufferBinding cbuffer_bindings_fetch_;
|
ConstantBufferBinding cbuffer_bindings_fetch_;
|
||||||
|
|
||||||
// Pages with the descriptors currently used for handling Xenos draw calls.
|
// Pages with the descriptors currently used for handling Xenos draw calls.
|
||||||
uint64_t draw_view_full_update_;
|
uint64_t draw_view_heap_index_;
|
||||||
uint64_t draw_sampler_full_update_;
|
uint64_t draw_sampler_heap_index_;
|
||||||
|
|
||||||
// Whether the last used texture bindings have been written to the current
|
// Whether the last used texture bindings have been written to the current
|
||||||
// view descriptor heap.
|
// view descriptor heap.
|
||||||
|
|
|
@ -53,14 +53,14 @@ PrimitiveConverter::PrimitiveConverter(D3D12CommandProcessor* command_processor,
|
||||||
PrimitiveConverter::~PrimitiveConverter() { Shutdown(); }
|
PrimitiveConverter::~PrimitiveConverter() { Shutdown(); }
|
||||||
|
|
||||||
bool PrimitiveConverter::Initialize() {
|
bool PrimitiveConverter::Initialize() {
|
||||||
auto context = command_processor_->GetD3D12Context();
|
auto device =
|
||||||
auto device = context->GetD3D12Provider()->GetDevice();
|
command_processor_->GetD3D12Context()->GetD3D12Provider()->GetDevice();
|
||||||
|
|
||||||
// There can be at most 65535 indices in a Xenos draw call, but they can be up
|
// There can be at most 65535 indices in a Xenos draw call, but they can be up
|
||||||
// to 4 bytes large, and conversion can add more indices (almost triple the
|
// to 4 bytes large, and conversion can add more indices (almost triple the
|
||||||
// count for triangle strips, for instance).
|
// count for triangle strips, for instance).
|
||||||
buffer_pool_ =
|
buffer_pool_ =
|
||||||
std::make_unique<ui::d3d12::UploadBufferPool>(context, 4 * 1024 * 1024);
|
std::make_unique<ui::d3d12::UploadBufferPool>(device, 4 * 1024 * 1024);
|
||||||
|
|
||||||
// Create the static index buffer for non-indexed drawing.
|
// Create the static index buffer for non-indexed drawing.
|
||||||
D3D12_RESOURCE_DESC static_ib_desc;
|
D3D12_RESOURCE_DESC static_ib_desc;
|
||||||
|
@ -162,14 +162,13 @@ void PrimitiveConverter::BeginFrame() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_pool_->BeginFrame();
|
buffer_pool_->Reclaim(
|
||||||
|
command_processor_->GetD3D12Context()->GetLastCompletedFrame());
|
||||||
|
|
||||||
converted_indices_cache_.clear();
|
converted_indices_cache_.clear();
|
||||||
memory_regions_used_ = 0;
|
memory_regions_used_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrimitiveConverter::EndFrame() { buffer_pool_->EndFrame(); }
|
|
||||||
|
|
||||||
PrimitiveType PrimitiveConverter::GetReplacementPrimitiveType(
|
PrimitiveType PrimitiveConverter::GetReplacementPrimitiveType(
|
||||||
PrimitiveType type) {
|
PrimitiveType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -695,8 +694,9 @@ void* PrimitiveConverter::AllocateIndices(
|
||||||
size += 16;
|
size += 16;
|
||||||
}
|
}
|
||||||
D3D12_GPU_VIRTUAL_ADDRESS gpu_address;
|
D3D12_GPU_VIRTUAL_ADDRESS gpu_address;
|
||||||
uint8_t* mapping =
|
uint8_t* mapping = buffer_pool_->Request(
|
||||||
buffer_pool_->RequestFull(size, nullptr, nullptr, &gpu_address);
|
command_processor_->GetD3D12Context()->GetCurrentFrame(), size, nullptr,
|
||||||
|
nullptr, &gpu_address);
|
||||||
if (mapping == nullptr) {
|
if (mapping == nullptr) {
|
||||||
XELOGE("Failed to allocate space for %u converted %u-bit vertex indices",
|
XELOGE("Failed to allocate space for %u converted %u-bit vertex indices",
|
||||||
count, format == IndexFormat::kInt32 ? 32 : 16);
|
count, format == IndexFormat::kInt32 ? 32 : 16);
|
||||||
|
|
|
@ -47,7 +47,6 @@ class PrimitiveConverter {
|
||||||
void ClearCache();
|
void ClearCache();
|
||||||
|
|
||||||
void BeginFrame();
|
void BeginFrame();
|
||||||
void EndFrame();
|
|
||||||
|
|
||||||
// Returns the primitive type that the original type will be converted to.
|
// Returns the primitive type that the original type will be converted to.
|
||||||
static PrimitiveType GetReplacementPrimitiveType(PrimitiveType type);
|
static PrimitiveType GetReplacementPrimitiveType(PrimitiveType type);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "xenia/gpu/texture_info.h"
|
#include "xenia/gpu/texture_info.h"
|
||||||
#include "xenia/gpu/texture_util.h"
|
#include "xenia/gpu/texture_util.h"
|
||||||
#include "xenia/ui/d3d12/d3d12_util.h"
|
#include "xenia/ui/d3d12/d3d12_util.h"
|
||||||
|
#include "xenia/ui/d3d12/pools.h"
|
||||||
|
|
||||||
DEFINE_bool(d3d12_16bit_rtv_full_range, true,
|
DEFINE_bool(d3d12_16bit_rtv_full_range, true,
|
||||||
"Use full -32...32 range for RG16 and RGBA16 render targets "
|
"Use full -32...32 range for RG16 and RGBA16 render targets "
|
||||||
|
@ -1379,7 +1380,9 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
||||||
if (command_processor_->RequestViewDescriptors(
|
if (command_processor_->RequestViewDescriptors(
|
||||||
0, 2, 2, descriptor_cpu_start, descriptor_gpu_start) == 0) {
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid, 2, 2,
|
||||||
|
descriptor_cpu_start, descriptor_gpu_start) ==
|
||||||
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
TransitionEDRAMBuffer(D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
|
TransitionEDRAMBuffer(D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
|
||||||
|
@ -1527,7 +1530,9 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
||||||
if (command_processor_->RequestViewDescriptors(
|
if (command_processor_->RequestViewDescriptors(
|
||||||
0, 3, 3, descriptor_cpu_start, descriptor_gpu_start) == 0) {
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid, 3, 3,
|
||||||
|
descriptor_cpu_start, descriptor_gpu_start) ==
|
||||||
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Buffer for copying.
|
// Buffer for copying.
|
||||||
|
@ -1833,8 +1838,10 @@ bool RenderTargetCache::ResolveClear(uint32_t edram_base,
|
||||||
command_processor_->GetD3D12Context()->GetD3D12Provider()->GetDevice();
|
command_processor_->GetD3D12Context()->GetD3D12Provider()->GetDevice();
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
||||||
if (command_processor_->RequestViewDescriptors(0, 1, 1, descriptor_cpu_start,
|
if (command_processor_->RequestViewDescriptors(
|
||||||
descriptor_gpu_start) == 0) {
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid, 1, 1,
|
||||||
|
descriptor_cpu_start, descriptor_gpu_start) ==
|
||||||
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2549,8 +2556,10 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() {
|
||||||
// Allocate descriptors for the buffers.
|
// Allocate descriptors for the buffers.
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
||||||
if (command_processor_->RequestViewDescriptors(0, 2, 2, descriptor_cpu_start,
|
if (command_processor_->RequestViewDescriptors(
|
||||||
descriptor_gpu_start) == 0) {
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid, 2, 2,
|
||||||
|
descriptor_cpu_start, descriptor_gpu_start) ==
|
||||||
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2694,8 +2703,10 @@ void RenderTargetCache::LoadRenderTargetsFromEDRAM(
|
||||||
// Allocate descriptors for the buffers.
|
// Allocate descriptors for the buffers.
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
||||||
if (command_processor_->RequestViewDescriptors(0, 2, 2, descriptor_cpu_start,
|
if (command_processor_->RequestViewDescriptors(
|
||||||
descriptor_gpu_start) == 0) {
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid, 2, 2,
|
||||||
|
descriptor_cpu_start, descriptor_gpu_start) ==
|
||||||
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,8 +59,7 @@ SharedMemory::SharedMemory(D3D12CommandProcessor* command_processor,
|
||||||
SharedMemory::~SharedMemory() { Shutdown(); }
|
SharedMemory::~SharedMemory() { Shutdown(); }
|
||||||
|
|
||||||
bool SharedMemory::Initialize() {
|
bool SharedMemory::Initialize() {
|
||||||
auto context = command_processor_->GetD3D12Context();
|
auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider();
|
||||||
auto provider = context->GetD3D12Provider();
|
|
||||||
auto device = provider->GetDevice();
|
auto device = provider->GetDevice();
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC buffer_desc;
|
D3D12_RESOURCE_DESC buffer_desc;
|
||||||
|
@ -131,7 +130,7 @@ bool SharedMemory::Initialize() {
|
||||||
valid_and_gpu_written_pages_.size() * sizeof(uint64_t));
|
valid_and_gpu_written_pages_.size() * sizeof(uint64_t));
|
||||||
|
|
||||||
upload_buffer_pool_ =
|
upload_buffer_pool_ =
|
||||||
std::make_unique<ui::d3d12::UploadBufferPool>(context, 4 * 1024 * 1024);
|
std::make_unique<ui::d3d12::UploadBufferPool>(device, 4 * 1024 * 1024);
|
||||||
|
|
||||||
physical_write_watch_handle_ =
|
physical_write_watch_handle_ =
|
||||||
memory_->RegisterPhysicalWriteWatch(MemoryWriteCallbackThunk, this);
|
memory_->RegisterPhysicalWriteWatch(MemoryWriteCallbackThunk, this);
|
||||||
|
@ -168,12 +167,11 @@ void SharedMemory::Shutdown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedMemory::BeginFrame() {
|
void SharedMemory::BeginFrame() {
|
||||||
upload_buffer_pool_->BeginFrame();
|
upload_buffer_pool_->Reclaim(
|
||||||
|
command_processor_->GetD3D12Context()->GetLastCompletedFrame());
|
||||||
heap_creation_failed_ = false;
|
heap_creation_failed_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedMemory::EndFrame() { upload_buffer_pool_->EndFrame(); }
|
|
||||||
|
|
||||||
SharedMemory::GlobalWatchHandle SharedMemory::RegisterGlobalWatch(
|
SharedMemory::GlobalWatchHandle SharedMemory::RegisterGlobalWatch(
|
||||||
GlobalWatchCallback callback, void* callback_context) {
|
GlobalWatchCallback callback, void* callback_context) {
|
||||||
GlobalWatch* watch = new GlobalWatch;
|
GlobalWatch* watch = new GlobalWatch;
|
||||||
|
@ -378,6 +376,7 @@ bool SharedMemory::RequestRange(uint32_t start, uint32_t length) {
|
||||||
ID3D12Resource* upload_buffer;
|
ID3D12Resource* upload_buffer;
|
||||||
uint32_t upload_buffer_offset, upload_buffer_size;
|
uint32_t upload_buffer_offset, upload_buffer_size;
|
||||||
uint8_t* upload_buffer_mapping = upload_buffer_pool_->RequestPartial(
|
uint8_t* upload_buffer_mapping = upload_buffer_pool_->RequestPartial(
|
||||||
|
command_processor_->GetD3D12Context()->GetCurrentFrame(),
|
||||||
upload_range_length << page_size_log2_, &upload_buffer,
|
upload_range_length << page_size_log2_, &upload_buffer,
|
||||||
&upload_buffer_offset, &upload_buffer_size, nullptr);
|
&upload_buffer_offset, &upload_buffer_size, nullptr);
|
||||||
if (upload_buffer_mapping == nullptr) {
|
if (upload_buffer_mapping == nullptr) {
|
||||||
|
|
|
@ -45,7 +45,6 @@ class SharedMemory {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BeginFrame();
|
void BeginFrame();
|
||||||
void EndFrame();
|
|
||||||
|
|
||||||
typedef void (*GlobalWatchCallback)(void* context, uint32_t address_first,
|
typedef void (*GlobalWatchCallback)(void* context, uint32_t address_first,
|
||||||
uint32_t address_last,
|
uint32_t address_last,
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "xenia/gpu/texture_info.h"
|
#include "xenia/gpu/texture_info.h"
|
||||||
#include "xenia/gpu/texture_util.h"
|
#include "xenia/gpu/texture_util.h"
|
||||||
#include "xenia/ui/d3d12/d3d12_util.h"
|
#include "xenia/ui/d3d12/d3d12_util.h"
|
||||||
|
#include "xenia/ui/d3d12/pools.h"
|
||||||
|
|
||||||
DEFINE_int32(d3d12_resolution_scale, 1,
|
DEFINE_int32(d3d12_resolution_scale, 1,
|
||||||
"Scale of rendering width and height (currently only 1 and 2 "
|
"Scale of rendering width and height (currently only 1 and 2 "
|
||||||
|
@ -1813,8 +1814,10 @@ bool TextureCache::TileResolvedTexture(
|
||||||
// Tile the texture.
|
// Tile the texture.
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
||||||
if (command_processor_->RequestViewDescriptors(0, 2, 2, descriptor_cpu_start,
|
if (command_processor_->RequestViewDescriptors(
|
||||||
descriptor_gpu_start) == 0) {
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid, 2, 2,
|
||||||
|
descriptor_cpu_start, descriptor_gpu_start) ==
|
||||||
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (resolution_scale_log2) {
|
if (resolution_scale_log2) {
|
||||||
|
@ -2403,7 +2406,8 @@ bool TextureCache::LoadTextureData(Texture* texture) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto command_list = command_processor_->GetDeferredCommandList();
|
auto command_list = command_processor_->GetDeferredCommandList();
|
||||||
auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider();
|
auto context = command_processor_->GetD3D12Context();
|
||||||
|
auto provider = context->GetD3D12Provider();
|
||||||
auto device = provider->GetDevice();
|
auto device = provider->GetDevice();
|
||||||
|
|
||||||
// Get the pipeline.
|
// Get the pipeline.
|
||||||
|
@ -2496,8 +2500,9 @@ bool TextureCache::LoadTextureData(Texture* texture) {
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
||||||
if (command_processor_->RequestViewDescriptors(
|
if (command_processor_->RequestViewDescriptors(
|
||||||
0, descriptor_count, descriptor_count, descriptor_cpu_start,
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid, descriptor_count,
|
||||||
descriptor_gpu_start) == 0) {
|
descriptor_count, descriptor_cpu_start, descriptor_gpu_start) ==
|
||||||
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid) {
|
||||||
command_processor_->ReleaseScratchGPUBuffer(copy_buffer, copy_buffer_state);
|
command_processor_->ReleaseScratchGPUBuffer(copy_buffer, copy_buffer_state);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2602,7 +2607,8 @@ bool TextureCache::LoadTextureData(Texture* texture) {
|
||||||
load_constants.guest_mip_offset[2]);
|
load_constants.guest_mip_offset[2]);
|
||||||
}
|
}
|
||||||
D3D12_GPU_VIRTUAL_ADDRESS cbuffer_gpu_address;
|
D3D12_GPU_VIRTUAL_ADDRESS cbuffer_gpu_address;
|
||||||
uint8_t* cbuffer_mapping = cbuffer_pool->RequestFull(
|
uint8_t* cbuffer_mapping = cbuffer_pool->Request(
|
||||||
|
context->GetCurrentFrame(),
|
||||||
xe::align(uint32_t(sizeof(load_constants)), 256u), nullptr, nullptr,
|
xe::align(uint32_t(sizeof(load_constants)), 256u), nullptr, nullptr,
|
||||||
&cbuffer_gpu_address);
|
&cbuffer_gpu_address);
|
||||||
if (cbuffer_mapping == nullptr) {
|
if (cbuffer_mapping == nullptr) {
|
||||||
|
|
|
@ -287,9 +287,10 @@ bool D3D12ImmediateDrawer::Initialize() {
|
||||||
|
|
||||||
// Create pools for draws.
|
// Create pools for draws.
|
||||||
vertex_buffer_pool_ =
|
vertex_buffer_pool_ =
|
||||||
std::make_unique<UploadBufferPool>(context_, 2 * 1024 * 1024);
|
std::make_unique<UploadBufferPool>(device, 2 * 1024 * 1024);
|
||||||
texture_descriptor_pool_ = std::make_unique<DescriptorHeapPool>(
|
texture_descriptor_pool_ = std::make_unique<DescriptorHeapPool>(
|
||||||
context_, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 2048);
|
device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 2048);
|
||||||
|
texture_descriptor_pool_heap_index_ = DescriptorHeapPool::kHeapIndexInvalid;
|
||||||
|
|
||||||
// Reset the current state.
|
// Reset the current state.
|
||||||
current_command_list_ = nullptr;
|
current_command_list_ = nullptr;
|
||||||
|
@ -460,9 +461,9 @@ void D3D12ImmediateDrawer::Begin(int render_target_width,
|
||||||
texture_uploads_pending_.pop_back();
|
texture_uploads_pending_.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
vertex_buffer_pool_->BeginFrame();
|
vertex_buffer_pool_->Reclaim(last_completed_frame);
|
||||||
texture_descriptor_pool_->BeginFrame();
|
texture_descriptor_pool_->Reclaim(last_completed_frame);
|
||||||
texture_descriptor_pool_full_update_ = 0;
|
texture_descriptor_pool_heap_index_ = DescriptorHeapPool::kHeapIndexInvalid;
|
||||||
|
|
||||||
current_render_target_width_ = render_target_width;
|
current_render_target_width_ = render_target_width;
|
||||||
current_render_target_height_ = render_target_height;
|
current_render_target_height_ = render_target_height;
|
||||||
|
@ -500,9 +501,9 @@ void D3D12ImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) {
|
||||||
vertex_buffer_view.StrideInBytes = UINT(sizeof(ImmediateVertex));
|
vertex_buffer_view.StrideInBytes = UINT(sizeof(ImmediateVertex));
|
||||||
vertex_buffer_view.SizeInBytes =
|
vertex_buffer_view.SizeInBytes =
|
||||||
batch.vertex_count * uint32_t(sizeof(ImmediateVertex));
|
batch.vertex_count * uint32_t(sizeof(ImmediateVertex));
|
||||||
void* vertex_buffer_mapping = vertex_buffer_pool_->RequestFull(
|
void* vertex_buffer_mapping = vertex_buffer_pool_->Request(
|
||||||
vertex_buffer_view.SizeInBytes, nullptr, nullptr,
|
context_->GetCurrentFrame(), vertex_buffer_view.SizeInBytes, nullptr,
|
||||||
&vertex_buffer_view.BufferLocation);
|
nullptr, &vertex_buffer_view.BufferLocation);
|
||||||
if (vertex_buffer_mapping == nullptr) {
|
if (vertex_buffer_mapping == nullptr) {
|
||||||
XELOGE("Failed to get a buffer for %u vertices in the immediate drawer",
|
XELOGE("Failed to get a buffer for %u vertices in the immediate drawer",
|
||||||
batch.vertex_count);
|
batch.vertex_count);
|
||||||
|
@ -518,7 +519,8 @@ void D3D12ImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) {
|
||||||
D3D12_INDEX_BUFFER_VIEW index_buffer_view;
|
D3D12_INDEX_BUFFER_VIEW index_buffer_view;
|
||||||
index_buffer_view.SizeInBytes = batch.index_count * sizeof(uint16_t);
|
index_buffer_view.SizeInBytes = batch.index_count * sizeof(uint16_t);
|
||||||
index_buffer_view.Format = DXGI_FORMAT_R16_UINT;
|
index_buffer_view.Format = DXGI_FORMAT_R16_UINT;
|
||||||
void* index_buffer_mapping = vertex_buffer_pool_->RequestFull(
|
void* index_buffer_mapping = vertex_buffer_pool_->Request(
|
||||||
|
context_->GetCurrentFrame(),
|
||||||
xe::align(index_buffer_view.SizeInBytes, UINT(sizeof(uint32_t))),
|
xe::align(index_buffer_view.SizeInBytes, UINT(sizeof(uint32_t))),
|
||||||
nullptr, nullptr, &index_buffer_view.BufferLocation);
|
nullptr, nullptr, &index_buffer_view.BufferLocation);
|
||||||
if (index_buffer_mapping == nullptr) {
|
if (index_buffer_mapping == nullptr) {
|
||||||
|
@ -560,15 +562,15 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) {
|
||||||
}
|
}
|
||||||
bool bind_texture = current_texture_ != texture;
|
bool bind_texture = current_texture_ != texture;
|
||||||
uint32_t texture_descriptor_index;
|
uint32_t texture_descriptor_index;
|
||||||
uint64_t texture_full_update = texture_descriptor_pool_->Request(
|
uint64_t texture_heap_index = texture_descriptor_pool_->Request(
|
||||||
texture_descriptor_pool_full_update_, bind_texture ? 1 : 0, 1,
|
context_->GetCurrentFrame(), texture_descriptor_pool_heap_index_,
|
||||||
texture_descriptor_index);
|
bind_texture ? 1 : 0, 1, texture_descriptor_index);
|
||||||
if (texture_full_update == 0) {
|
if (texture_heap_index == DescriptorHeapPool::kHeapIndexInvalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (texture_descriptor_pool_full_update_ != texture_full_update) {
|
if (texture_descriptor_pool_heap_index_ != texture_heap_index) {
|
||||||
bind_texture = true;
|
bind_texture = true;
|
||||||
texture_descriptor_pool_full_update_ = texture_full_update;
|
texture_descriptor_pool_heap_index_ = texture_heap_index;
|
||||||
ID3D12DescriptorHeap* descriptor_heaps[] = {
|
ID3D12DescriptorHeap* descriptor_heaps[] = {
|
||||||
texture_descriptor_pool_->GetLastRequestHeap(), sampler_heap_};
|
texture_descriptor_pool_->GetLastRequestHeap(), sampler_heap_};
|
||||||
current_command_list_->SetDescriptorHeaps(2, descriptor_heaps);
|
current_command_list_->SetDescriptorHeaps(2, descriptor_heaps);
|
||||||
|
@ -673,9 +675,6 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) {
|
||||||
void D3D12ImmediateDrawer::EndDrawBatch() { batch_open_ = false; }
|
void D3D12ImmediateDrawer::EndDrawBatch() { batch_open_ = false; }
|
||||||
|
|
||||||
void D3D12ImmediateDrawer::End() {
|
void D3D12ImmediateDrawer::End() {
|
||||||
texture_descriptor_pool_->EndFrame();
|
|
||||||
vertex_buffer_pool_->EndFrame();
|
|
||||||
|
|
||||||
current_command_list_ = nullptr;
|
current_command_list_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,7 @@ class D3D12ImmediateDrawer : public ImmediateDrawer {
|
||||||
|
|
||||||
std::unique_ptr<UploadBufferPool> vertex_buffer_pool_ = nullptr;
|
std::unique_ptr<UploadBufferPool> vertex_buffer_pool_ = nullptr;
|
||||||
std::unique_ptr<DescriptorHeapPool> texture_descriptor_pool_ = nullptr;
|
std::unique_ptr<DescriptorHeapPool> texture_descriptor_pool_ = nullptr;
|
||||||
|
uint64_t texture_descriptor_pool_heap_index_;
|
||||||
|
|
||||||
struct PendingTextureUpload {
|
struct PendingTextureUpload {
|
||||||
ImmediateTexture* texture;
|
ImmediateTexture* texture;
|
||||||
|
@ -94,7 +95,6 @@ class D3D12ImmediateDrawer : public ImmediateDrawer {
|
||||||
int current_render_target_width_, current_render_target_height_;
|
int current_render_target_width_, current_render_target_height_;
|
||||||
bool batch_open_ = false;
|
bool batch_open_ = false;
|
||||||
bool batch_has_index_buffer_;
|
bool batch_has_index_buffer_;
|
||||||
uint64_t texture_descriptor_pool_full_update_;
|
|
||||||
D3D_PRIMITIVE_TOPOLOGY current_primitive_topology_;
|
D3D_PRIMITIVE_TOPOLOGY current_primitive_topology_;
|
||||||
ImmediateTexture* current_texture_;
|
ImmediateTexture* current_texture_;
|
||||||
SamplerIndex current_sampler_index_;
|
SamplerIndex current_sampler_index_;
|
||||||
|
|
|
@ -13,251 +13,212 @@
|
||||||
|
|
||||||
#include "xenia/base/assert.h"
|
#include "xenia/base/assert.h"
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
#include "xenia/ui/d3d12/d3d12_context.h"
|
|
||||||
#include "xenia/ui/d3d12/d3d12_util.h"
|
#include "xenia/ui/d3d12/d3d12_util.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace ui {
|
namespace ui {
|
||||||
namespace d3d12 {
|
namespace d3d12 {
|
||||||
|
|
||||||
UploadBufferPool::UploadBufferPool(D3D12Context* context, uint32_t page_size)
|
UploadBufferPool::UploadBufferPool(ID3D12Device* device, uint32_t page_size)
|
||||||
: context_(context), page_size_(page_size) {}
|
: device_(device), page_size_(page_size) {}
|
||||||
|
|
||||||
UploadBufferPool::~UploadBufferPool() {
|
UploadBufferPool::~UploadBufferPool() {
|
||||||
// Allow mid-frame destruction in cases like device loss.
|
|
||||||
if (current_mapping_ != nullptr) {
|
|
||||||
// Don't care about the written range - destroying anyway.
|
|
||||||
D3D12_RANGE written_range;
|
|
||||||
written_range.Begin = 0;
|
|
||||||
written_range.End = 0;
|
|
||||||
unsent_->buffer->Unmap(0, &written_range);
|
|
||||||
current_mapping_ = nullptr;
|
|
||||||
}
|
|
||||||
current_size_ = 0;
|
|
||||||
ClearCache();
|
ClearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UploadBufferPool::BeginFrame() {
|
void UploadBufferPool::Reclaim(uint64_t completed_fence_value) {
|
||||||
// Recycle submitted pages not used by the GPU anymore.
|
while (submitted_first_) {
|
||||||
uint64_t last_completed_frame = context_->GetLastCompletedFrame();
|
if (submitted_first_->last_usage_fence_value > completed_fence_value) {
|
||||||
while (sent_first_ != nullptr) {
|
|
||||||
auto page = sent_first_;
|
|
||||||
if (page->frame_sent > last_completed_frame) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sent_first_ = page->next;
|
if (writable_last_) {
|
||||||
page->next = unsent_;
|
writable_last_->next = submitted_first_;
|
||||||
unsent_ = page;
|
} else {
|
||||||
|
writable_first_ = submitted_first_;
|
||||||
|
}
|
||||||
|
writable_last_ = submitted_first_;
|
||||||
|
submitted_first_ = submitted_first_->next;
|
||||||
|
writable_last_->next = nullptr;
|
||||||
}
|
}
|
||||||
if (sent_first_ == nullptr) {
|
if (!submitted_first_) {
|
||||||
sent_last_ = nullptr;
|
submitted_last_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to create new pages again in this frame if failed in the previous.
|
|
||||||
page_creation_failed_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UploadBufferPool::EndFrame() {
|
|
||||||
// If something is written to the current page, mark it as submitted.
|
|
||||||
EndPage();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UploadBufferPool::ClearCache() {
|
void UploadBufferPool::ClearCache() {
|
||||||
assert(current_size_ == 0);
|
current_page_used_ = 0;
|
||||||
while (unsent_ != nullptr) {
|
// Deleting anyway, so assuming data not needed anymore.
|
||||||
auto next = unsent_->next;
|
D3D12_RANGE written_range;
|
||||||
unsent_->buffer->Release();
|
written_range.Begin = 0;
|
||||||
delete unsent_;
|
written_range.End = 0;
|
||||||
unsent_ = next;
|
while (submitted_first_) {
|
||||||
|
auto next = submitted_first_->next;
|
||||||
|
submitted_first_->buffer->Unmap(0, &written_range);
|
||||||
|
submitted_first_->buffer->Release();
|
||||||
|
delete submitted_first_;
|
||||||
|
submitted_first_ = next;
|
||||||
}
|
}
|
||||||
while (sent_first_ != nullptr) {
|
submitted_last_ = nullptr;
|
||||||
auto next = sent_first_->next;
|
while (writable_first_) {
|
||||||
sent_first_->buffer->Release();
|
auto next = writable_first_->next;
|
||||||
delete sent_first_;
|
writable_first_->buffer->Unmap(0, &written_range);
|
||||||
sent_first_ = next;
|
writable_first_->buffer->Release();
|
||||||
|
delete writable_first_;
|
||||||
|
writable_first_ = next;
|
||||||
}
|
}
|
||||||
sent_last_ = nullptr;
|
writable_last_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* UploadBufferPool::RequestFull(
|
uint8_t* UploadBufferPool::Request(uint64_t usage_fence_value, uint32_t size,
|
||||||
uint32_t size, ID3D12Resource** buffer_out, uint32_t* offset_out,
|
ID3D12Resource** buffer_out,
|
||||||
D3D12_GPU_VIRTUAL_ADDRESS* gpu_address_out) {
|
uint32_t* offset_out,
|
||||||
|
D3D12_GPU_VIRTUAL_ADDRESS* gpu_address_out) {
|
||||||
assert_true(size <= page_size_);
|
assert_true(size <= page_size_);
|
||||||
if (size > page_size_) {
|
if (size > page_size_) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (page_size_ - current_size_ < size || current_mapping_ == nullptr) {
|
assert_true(!current_page_used_ ||
|
||||||
|
usage_fence_value >= writable_first_->last_usage_fence_value);
|
||||||
|
assert_true(!submitted_last_ ||
|
||||||
|
usage_fence_value >= submitted_last_->last_usage_fence_value);
|
||||||
|
if (page_size_ - current_page_used_ < size || !writable_first_) {
|
||||||
// Start a new page if can't fit all the bytes or don't have an open page.
|
// Start a new page if can't fit all the bytes or don't have an open page.
|
||||||
if (!BeginNextPage()) {
|
if (writable_first_) {
|
||||||
return nullptr;
|
// Close the page that was current.
|
||||||
|
if (submitted_last_) {
|
||||||
|
submitted_last_->next = writable_first_;
|
||||||
|
} else {
|
||||||
|
submitted_first_ = writable_first_;
|
||||||
|
}
|
||||||
|
submitted_last_ = writable_first_;
|
||||||
|
writable_first_ = writable_first_->next;
|
||||||
|
submitted_last_->next = nullptr;
|
||||||
|
if (!writable_first_) {
|
||||||
|
writable_last_ = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (!writable_first_) {
|
||||||
if (buffer_out != nullptr) {
|
// Create a new page if none available.
|
||||||
*buffer_out = unsent_->buffer;
|
D3D12_RESOURCE_DESC new_buffer_desc;
|
||||||
}
|
util::FillBufferResourceDesc(new_buffer_desc, page_size_,
|
||||||
if (offset_out != nullptr) {
|
D3D12_RESOURCE_FLAG_NONE);
|
||||||
*offset_out = current_size_;
|
ID3D12Resource* new_buffer;
|
||||||
}
|
if (FAILED(device_->CreateCommittedResource(
|
||||||
if (gpu_address_out != nullptr) {
|
&util::kHeapPropertiesUpload, D3D12_HEAP_FLAG_NONE,
|
||||||
if (current_gpu_address_ == 0) {
|
&new_buffer_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr,
|
||||||
current_gpu_address_ = unsent_->buffer->GetGPUVirtualAddress();
|
IID_PPV_ARGS(&new_buffer)))) {
|
||||||
|
XELOGE("Failed to create a D3D upload buffer with %u bytes",
|
||||||
|
page_size_);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
D3D12_RANGE read_range;
|
||||||
|
read_range.Begin = 0;
|
||||||
|
read_range.End = 0;
|
||||||
|
void* new_buffer_mapping;
|
||||||
|
if (FAILED(new_buffer->Map(0, &read_range, &new_buffer_mapping))) {
|
||||||
|
XELOGE("Failed to map a D3D upload buffer with %u bytes", page_size_);
|
||||||
|
new_buffer->Release();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
writable_first_ = new Page;
|
||||||
|
writable_first_->buffer = new_buffer;
|
||||||
|
writable_first_->gpu_address = new_buffer->GetGPUVirtualAddress();
|
||||||
|
writable_first_->mapping = new_buffer_mapping;
|
||||||
|
writable_first_->last_usage_fence_value = usage_fence_value;
|
||||||
|
writable_first_->next = nullptr;
|
||||||
|
writable_last_ = writable_first_;
|
||||||
}
|
}
|
||||||
*gpu_address_out = current_gpu_address_ + current_size_;
|
current_page_used_ = 0;
|
||||||
}
|
}
|
||||||
uint8_t* mapping = current_mapping_ + current_size_;
|
writable_first_->last_usage_fence_value = usage_fence_value;
|
||||||
current_size_ += size;
|
if (buffer_out) {
|
||||||
|
*buffer_out = writable_first_->buffer;
|
||||||
|
}
|
||||||
|
if (offset_out) {
|
||||||
|
*offset_out = current_page_used_;
|
||||||
|
}
|
||||||
|
if (gpu_address_out) {
|
||||||
|
*gpu_address_out = writable_first_->gpu_address + current_page_used_;
|
||||||
|
}
|
||||||
|
uint8_t* mapping =
|
||||||
|
reinterpret_cast<uint8_t*>(writable_first_->mapping) + current_page_used_;
|
||||||
|
current_page_used_ += size;
|
||||||
return mapping;
|
return mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* UploadBufferPool::RequestPartial(
|
uint8_t* UploadBufferPool::RequestPartial(
|
||||||
uint32_t size, ID3D12Resource** buffer_out, uint32_t* offset_out,
|
uint64_t usage_fence_value, uint32_t size, ID3D12Resource** buffer_out,
|
||||||
uint32_t* size_out, D3D12_GPU_VIRTUAL_ADDRESS* gpu_address_out) {
|
uint32_t* offset_out, uint32_t* size_out,
|
||||||
if (current_size_ == page_size_ || current_mapping_ == nullptr) {
|
D3D12_GPU_VIRTUAL_ADDRESS* gpu_address_out) {
|
||||||
// Start a new page if can't fit any bytes or don't have an open page.
|
size = std::min(size, page_size_);
|
||||||
if (!BeginNextPage()) {
|
if (current_page_used_ < page_size_) {
|
||||||
return nullptr;
|
size = std::min(size, page_size_ - current_page_used_);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
size = std::min(size, page_size_ - current_size_);
|
uint8_t* mapping =
|
||||||
if (buffer_out != nullptr) {
|
Request(usage_fence_value, size, buffer_out, offset_out, gpu_address_out);
|
||||||
*buffer_out = unsent_->buffer;
|
if (!mapping) {
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (offset_out != nullptr) {
|
if (size_out) {
|
||||||
*offset_out = current_size_;
|
|
||||||
}
|
|
||||||
if (size_out != nullptr) {
|
|
||||||
*size_out = size;
|
*size_out = size;
|
||||||
}
|
}
|
||||||
if (gpu_address_out != nullptr) {
|
|
||||||
if (current_gpu_address_ == 0) {
|
|
||||||
current_gpu_address_ = unsent_->buffer->GetGPUVirtualAddress();
|
|
||||||
}
|
|
||||||
*gpu_address_out = current_gpu_address_ + current_size_;
|
|
||||||
}
|
|
||||||
uint8_t* mapping = current_mapping_ + current_size_;
|
|
||||||
current_size_ += size;
|
|
||||||
return mapping;
|
return mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UploadBufferPool::EndPage() {
|
constexpr uint64_t DescriptorHeapPool::kHeapIndexInvalid;
|
||||||
if (current_mapping_ != nullptr) {
|
|
||||||
D3D12_RANGE written_range;
|
|
||||||
written_range.Begin = 0;
|
|
||||||
written_range.End = current_size_;
|
|
||||||
unsent_->buffer->Unmap(0, &written_range);
|
|
||||||
current_mapping_ = nullptr;
|
|
||||||
}
|
|
||||||
if (current_size_ != 0) {
|
|
||||||
auto page = unsent_;
|
|
||||||
page->frame_sent = context_->GetCurrentFrame();
|
|
||||||
unsent_ = page->next;
|
|
||||||
page->next = nullptr;
|
|
||||||
if (sent_last_ != nullptr) {
|
|
||||||
sent_last_->next = page;
|
|
||||||
} else {
|
|
||||||
sent_first_ = page;
|
|
||||||
}
|
|
||||||
sent_last_ = page;
|
|
||||||
current_size_ = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UploadBufferPool::BeginNextPage() {
|
DescriptorHeapPool::DescriptorHeapPool(ID3D12Device* device,
|
||||||
EndPage();
|
|
||||||
|
|
||||||
if (page_creation_failed_) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unsent_ == nullptr) {
|
|
||||||
auto device = context_->GetD3D12Provider()->GetDevice();
|
|
||||||
D3D12_RESOURCE_DESC buffer_desc;
|
|
||||||
util::FillBufferResourceDesc(buffer_desc, page_size_,
|
|
||||||
D3D12_RESOURCE_FLAG_NONE);
|
|
||||||
ID3D12Resource* buffer_resource;
|
|
||||||
if (FAILED(device->CreateCommittedResource(
|
|
||||||
&util::kHeapPropertiesUpload, D3D12_HEAP_FLAG_NONE, &buffer_desc,
|
|
||||||
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr,
|
|
||||||
IID_PPV_ARGS(&buffer_resource)))) {
|
|
||||||
XELOGE("Failed to create a D3D upload buffer with %u bytes", page_size_);
|
|
||||||
page_creation_failed_ = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
unsent_ = new UploadBuffer;
|
|
||||||
unsent_->buffer = buffer_resource;
|
|
||||||
unsent_->next = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12_RANGE read_range;
|
|
||||||
read_range.Begin = 0;
|
|
||||||
read_range.End = 0;
|
|
||||||
void* mapping;
|
|
||||||
if (FAILED(unsent_->buffer->Map(0, &read_range, &mapping))) {
|
|
||||||
XELOGE("Failed to map a D3D upload buffer with %u bytes", page_size_);
|
|
||||||
page_creation_failed_ = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
current_mapping_ = reinterpret_cast<uint8_t*>(mapping);
|
|
||||||
current_gpu_address_ = 0;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DescriptorHeapPool::DescriptorHeapPool(D3D12Context* context,
|
|
||||||
D3D12_DESCRIPTOR_HEAP_TYPE type,
|
D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||||
uint32_t page_size)
|
uint32_t page_size)
|
||||||
: context_(context), type_(type), page_size_(page_size) {}
|
: device_(device), type_(type), page_size_(page_size) {}
|
||||||
|
|
||||||
DescriptorHeapPool::~DescriptorHeapPool() {
|
DescriptorHeapPool::~DescriptorHeapPool() {
|
||||||
// Allow mid-frame destruction in cases like device loss.
|
|
||||||
current_size_ = 0;
|
|
||||||
ClearCache();
|
ClearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptorHeapPool::BeginFrame() {
|
void DescriptorHeapPool::Reclaim(uint64_t completed_fence_value) {
|
||||||
// Don't hold old pages if few descriptors are written, also make 0 usable as
|
while (submitted_first_) {
|
||||||
// an invalid page index.
|
if (submitted_first_->last_usage_fence_value > completed_fence_value) {
|
||||||
++current_page_;
|
|
||||||
|
|
||||||
// Recycle submitted pages not used by the GPU anymore.
|
|
||||||
uint64_t last_completed_frame = context_->GetLastCompletedFrame();
|
|
||||||
while (sent_first_ != nullptr) {
|
|
||||||
auto page = sent_first_;
|
|
||||||
if (page->frame_sent > last_completed_frame) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sent_first_ = page->next;
|
if (writable_last_) {
|
||||||
page->next = unsent_;
|
writable_last_->next = submitted_first_;
|
||||||
unsent_ = page;
|
} else {
|
||||||
|
writable_first_ = submitted_first_;
|
||||||
|
}
|
||||||
|
writable_last_ = submitted_first_;
|
||||||
|
submitted_first_ = submitted_first_->next;
|
||||||
|
writable_last_->next = nullptr;
|
||||||
}
|
}
|
||||||
if (sent_first_ == nullptr) {
|
if (!submitted_first_) {
|
||||||
sent_last_ = nullptr;
|
submitted_last_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to create new pages again in this frame if failed in the previous.
|
|
||||||
page_creation_failed_ = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptorHeapPool::EndFrame() { EndPage(); }
|
|
||||||
|
|
||||||
void DescriptorHeapPool::ClearCache() {
|
void DescriptorHeapPool::ClearCache() {
|
||||||
assert_true(current_size_ == 0);
|
// Not checking current_page_used_ != 0 because asking for 0 descriptors
|
||||||
while (unsent_ != nullptr) {
|
// returns a valid heap also - but actually the new heap will be different now
|
||||||
auto next = unsent_->next;
|
// and the old one must be unbound since it doesn't exist anymore.
|
||||||
unsent_->heap->Release();
|
++current_heap_index_;
|
||||||
delete unsent_;
|
current_page_used_ = 0;
|
||||||
unsent_ = next;
|
while (submitted_first_) {
|
||||||
|
auto next = submitted_first_->next;
|
||||||
|
submitted_first_->heap->Release();
|
||||||
|
delete submitted_first_;
|
||||||
|
submitted_first_ = next;
|
||||||
}
|
}
|
||||||
while (sent_first_ != nullptr) {
|
submitted_last_ = nullptr;
|
||||||
auto next = sent_first_->next;
|
while (writable_first_) {
|
||||||
sent_first_->heap->Release();
|
auto next = writable_first_->next;
|
||||||
delete sent_first_;
|
writable_first_->heap->Release();
|
||||||
sent_first_ = next;
|
delete writable_first_;
|
||||||
|
writable_first_ = next;
|
||||||
}
|
}
|
||||||
sent_last_ = nullptr;
|
writable_last_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t DescriptorHeapPool::Request(uint64_t previous_full_update,
|
uint64_t DescriptorHeapPool::Request(uint64_t usage_fence_value,
|
||||||
|
uint64_t previous_heap_index,
|
||||||
uint32_t count_for_partial_update,
|
uint32_t count_for_partial_update,
|
||||||
uint32_t count_for_full_update,
|
uint32_t count_for_full_update,
|
||||||
uint32_t& index_out) {
|
uint32_t& index_out) {
|
||||||
|
@ -265,75 +226,63 @@ uint64_t DescriptorHeapPool::Request(uint64_t previous_full_update,
|
||||||
assert_true(count_for_full_update <= page_size_);
|
assert_true(count_for_full_update <= page_size_);
|
||||||
if (count_for_partial_update > count_for_full_update ||
|
if (count_for_partial_update > count_for_full_update ||
|
||||||
count_for_full_update > page_size_) {
|
count_for_full_update > page_size_) {
|
||||||
return 0;
|
return kHeapIndexInvalid;
|
||||||
}
|
}
|
||||||
|
assert_true(!current_page_used_ ||
|
||||||
if (page_creation_failed_) {
|
usage_fence_value >= writable_first_->last_usage_fence_value);
|
||||||
// Don't touch the page index every call if there was a failure as well.
|
assert_true(!submitted_last_ ||
|
||||||
return 0;
|
usage_fence_value >= submitted_last_->last_usage_fence_value);
|
||||||
}
|
|
||||||
|
|
||||||
// If the last full update happened on the current page, a partial update is
|
// If the last full update happened on the current page, a partial update is
|
||||||
// possible.
|
// possible.
|
||||||
uint32_t count = previous_full_update == current_page_
|
uint32_t count = previous_heap_index == current_heap_index_
|
||||||
? count_for_partial_update
|
? count_for_partial_update
|
||||||
: count_for_full_update;
|
: count_for_full_update;
|
||||||
|
|
||||||
// Go to the next page if there's not enough free space on the current one,
|
// Go to the next page if there's not enough free space on the current one,
|
||||||
// or because the previous page may be outdated. In this case, a full update
|
// or because the previous page may be outdated. In this case, a full update
|
||||||
// is necessary.
|
// is necessary.
|
||||||
if (page_size_ - current_size_ < count) {
|
if (page_size_ - current_page_used_ < count) {
|
||||||
EndPage();
|
// Close the page that was current.
|
||||||
++current_page_;
|
if (submitted_last_) {
|
||||||
|
submitted_last_->next = writable_first_;
|
||||||
|
} else {
|
||||||
|
submitted_first_ = writable_first_;
|
||||||
|
}
|
||||||
|
submitted_last_ = writable_first_;
|
||||||
|
writable_first_ = writable_first_->next;
|
||||||
|
submitted_last_->next = nullptr;
|
||||||
|
if (!writable_first_) {
|
||||||
|
writable_last_ = nullptr;
|
||||||
|
}
|
||||||
|
++current_heap_index_;
|
||||||
|
current_page_used_ = 0;
|
||||||
count = count_for_full_update;
|
count = count_for_full_update;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the page if needed (may be the first call for the page).
|
// Create the page if needed (may be the first call for the page).
|
||||||
if (unsent_ == nullptr) {
|
if (!writable_first_) {
|
||||||
auto device = context_->GetD3D12Provider()->GetDevice();
|
D3D12_DESCRIPTOR_HEAP_DESC new_heap_desc;
|
||||||
D3D12_DESCRIPTOR_HEAP_DESC heap_desc;
|
new_heap_desc.Type = type_;
|
||||||
heap_desc.Type = type_;
|
new_heap_desc.NumDescriptors = page_size_;
|
||||||
heap_desc.NumDescriptors = page_size_;
|
new_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||||
heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
new_heap_desc.NodeMask = 0;
|
||||||
heap_desc.NodeMask = 0;
|
ID3D12DescriptorHeap* new_heap;
|
||||||
ID3D12DescriptorHeap* heap;
|
if (FAILED(device_->CreateDescriptorHeap(&new_heap_desc,
|
||||||
if (FAILED(device->CreateDescriptorHeap(&heap_desc, IID_PPV_ARGS(&heap)))) {
|
IID_PPV_ARGS(&new_heap)))) {
|
||||||
XELOGE("Failed to create a heap for %u shader-visible descriptors",
|
XELOGE("Failed to create a heap for %u shader-visible descriptors",
|
||||||
page_size_);
|
page_size_);
|
||||||
page_creation_failed_ = true;
|
return kHeapIndexInvalid;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
unsent_ = new DescriptorHeap;
|
writable_first_ = new Page;
|
||||||
unsent_->heap = heap;
|
writable_first_->heap = new_heap;
|
||||||
unsent_->next = nullptr;
|
writable_first_->cpu_start = new_heap->GetCPUDescriptorHandleForHeapStart();
|
||||||
}
|
writable_first_->gpu_start = new_heap->GetGPUDescriptorHandleForHeapStart();
|
||||||
|
writable_first_->last_usage_fence_value = usage_fence_value;
|
||||||
// If starting a new page, get the handles to the beginning of it.
|
writable_first_->next = nullptr;
|
||||||
if (current_size_ == 0) {
|
writable_last_ = writable_first_;
|
||||||
current_heap_cpu_start_ =
|
|
||||||
unsent_->heap->GetCPUDescriptorHandleForHeapStart();
|
|
||||||
current_heap_gpu_start_ =
|
|
||||||
unsent_->heap->GetGPUDescriptorHandleForHeapStart();
|
|
||||||
}
|
|
||||||
index_out = current_size_;
|
|
||||||
current_size_ += count;
|
|
||||||
return current_page_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptorHeapPool::EndPage() {
|
|
||||||
if (current_size_ != 0) {
|
|
||||||
auto page = unsent_;
|
|
||||||
page->frame_sent = context_->GetCurrentFrame();
|
|
||||||
unsent_ = page->next;
|
|
||||||
page->next = nullptr;
|
|
||||||
if (sent_last_ != nullptr) {
|
|
||||||
sent_last_->next = page;
|
|
||||||
} else {
|
|
||||||
sent_first_ = page;
|
|
||||||
}
|
|
||||||
sent_last_ = page;
|
|
||||||
current_size_ = 0;
|
|
||||||
}
|
}
|
||||||
|
writable_first_->last_usage_fence_value = usage_fence_value;
|
||||||
|
index_out = current_page_used_;
|
||||||
|
current_page_used_ += count;
|
||||||
|
return current_heap_index_;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace d3d12
|
} // namespace d3d12
|
||||||
|
|
|
@ -18,64 +18,57 @@ namespace xe {
|
||||||
namespace ui {
|
namespace ui {
|
||||||
namespace d3d12 {
|
namespace d3d12 {
|
||||||
|
|
||||||
class D3D12Context;
|
|
||||||
|
|
||||||
class UploadBufferPool {
|
class UploadBufferPool {
|
||||||
public:
|
public:
|
||||||
UploadBufferPool(D3D12Context* context, uint32_t page_size);
|
UploadBufferPool(ID3D12Device* device, uint32_t page_size);
|
||||||
~UploadBufferPool();
|
~UploadBufferPool();
|
||||||
|
|
||||||
void BeginFrame();
|
void Reclaim(uint64_t completed_fence_value);
|
||||||
void EndFrame();
|
|
||||||
void ClearCache();
|
void ClearCache();
|
||||||
|
|
||||||
// Request to write data in a single piece, creating a new page if the current
|
// Request to write data in a single piece, creating a new page if the current
|
||||||
// one doesn't have enough free space.
|
// one doesn't have enough free space.
|
||||||
uint8_t* RequestFull(uint32_t size, ID3D12Resource** buffer_out,
|
uint8_t* Request(uint64_t usage_fence_value, uint32_t size,
|
||||||
uint32_t* offset_out,
|
ID3D12Resource** buffer_out, uint32_t* offset_out,
|
||||||
D3D12_GPU_VIRTUAL_ADDRESS* gpu_address_out);
|
D3D12_GPU_VIRTUAL_ADDRESS* gpu_address_out);
|
||||||
// Request to write data in multiple parts, filling the buffer entirely.
|
// Request to write data in multiple parts, filling the buffer entirely.
|
||||||
uint8_t* RequestPartial(uint32_t size, ID3D12Resource** buffer_out,
|
uint8_t* RequestPartial(uint64_t usage_fence_value, uint32_t size,
|
||||||
uint32_t* offset_out, uint32_t* size_out,
|
ID3D12Resource** buffer_out, uint32_t* offset_out,
|
||||||
|
uint32_t* size_out,
|
||||||
D3D12_GPU_VIRTUAL_ADDRESS* gpu_address_out);
|
D3D12_GPU_VIRTUAL_ADDRESS* gpu_address_out);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
D3D12Context* context_;
|
ID3D12Device* device_;
|
||||||
uint32_t page_size_;
|
uint32_t page_size_;
|
||||||
|
|
||||||
void EndPage();
|
struct Page {
|
||||||
bool BeginNextPage();
|
|
||||||
|
|
||||||
struct UploadBuffer {
|
|
||||||
ID3D12Resource* buffer;
|
ID3D12Resource* buffer;
|
||||||
UploadBuffer* next;
|
D3D12_GPU_VIRTUAL_ADDRESS gpu_address;
|
||||||
uint64_t frame_sent;
|
void* mapping;
|
||||||
|
uint64_t last_usage_fence_value;
|
||||||
|
Page* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A list of unsent buffers, with the first one being the current.
|
// A list of buffers with free space, with the first buffer being the one
|
||||||
UploadBuffer* unsent_ = nullptr;
|
// currently being filled.
|
||||||
// A list of sent buffers, moved to unsent in the beginning of a frame.
|
Page* writable_first_ = nullptr;
|
||||||
UploadBuffer* sent_first_ = nullptr;
|
Page* writable_last_ = nullptr;
|
||||||
UploadBuffer* sent_last_ = nullptr;
|
// A list of full buffers that can be reclaimed when the GPU doesn't use them
|
||||||
|
// anymore.
|
||||||
uint32_t current_size_ = 0;
|
Page* submitted_first_ = nullptr;
|
||||||
uint8_t* current_mapping_ = nullptr;
|
Page* submitted_last_ = nullptr;
|
||||||
// Not updated until actually requested.
|
uint32_t current_page_used_ = 0;
|
||||||
D3D12_GPU_VIRTUAL_ADDRESS current_gpu_address_ = 0;
|
|
||||||
|
|
||||||
// Reset in the beginning of a frame - don't try and fail to create a new page
|
|
||||||
// if failed to create one in the current frame.
|
|
||||||
bool page_creation_failed_ = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DescriptorHeapPool {
|
class DescriptorHeapPool {
|
||||||
public:
|
public:
|
||||||
DescriptorHeapPool(D3D12Context* context, D3D12_DESCRIPTOR_HEAP_TYPE type,
|
static constexpr uint64_t kHeapIndexInvalid = UINT64_MAX;
|
||||||
|
|
||||||
|
DescriptorHeapPool(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||||
uint32_t page_size);
|
uint32_t page_size);
|
||||||
~DescriptorHeapPool();
|
~DescriptorHeapPool();
|
||||||
|
|
||||||
void BeginFrame();
|
void Reclaim(uint64_t completed_fence_value);
|
||||||
void EndFrame();
|
|
||||||
void ClearCache();
|
void ClearCache();
|
||||||
|
|
||||||
// Because all descriptors for a single draw call must be in the same heap,
|
// Because all descriptors for a single draw call must be in the same heap,
|
||||||
|
@ -88,64 +81,64 @@ class DescriptorHeapPool {
|
||||||
//
|
//
|
||||||
// If something uses this pool to do partial updates, it must let this
|
// If something uses this pool to do partial updates, it must let this
|
||||||
// function determine whether a partial update is possible. For this purpose,
|
// function determine whether a partial update is possible. For this purpose,
|
||||||
// this function returns a full update number - and it must be called with its
|
// this function returns the heap reset index - and it must be called with its
|
||||||
// previous return value for the set of descriptors it's updating.
|
// previous return value for the set of descriptors it's updating.
|
||||||
//
|
//
|
||||||
// If this function returns a value that is the same as previous_full_update,
|
// If this function returns a value that is the same as previous_heap_index, a
|
||||||
// a partial update needs to be done - and space for count_for_partial_update
|
// partial update needs to be done - and space for count_for_partial_update is
|
||||||
// is allocated.
|
// allocated.
|
||||||
//
|
//
|
||||||
// If it's different, all descriptors must be written again - and space for
|
// If it's different, all descriptors must be written again - and space for
|
||||||
// count_for_full_update is allocated.
|
// count_for_full_update is allocated.
|
||||||
//
|
//
|
||||||
// If 0 is returned, there was an error.
|
// If kHeapIndexInvalid is returned, there was an error.
|
||||||
//
|
//
|
||||||
// This MUST be called even if there's nothing to write in a partial update
|
// This MUST be called even if there's nothing to write in a partial update
|
||||||
// (with count_for_partial_update being 0), because a full update may still be
|
// (with count_for_partial_update being 0), because a full update may still be
|
||||||
// required.
|
// required.
|
||||||
uint64_t Request(uint64_t previous_full_update,
|
uint64_t Request(uint64_t usage_fence_value, uint64_t previous_heap_index,
|
||||||
uint32_t count_for_partial_update,
|
uint32_t count_for_partial_update,
|
||||||
uint32_t count_for_full_update, uint32_t& index_out);
|
uint32_t count_for_full_update, uint32_t& index_out);
|
||||||
|
|
||||||
// The current heap, for binding and actually writing - may be called only
|
// The current heap, for binding and actually writing - may be called only
|
||||||
// after a successful request because before a request, the heap may not exist
|
// after a successful request because before a request, the heap may not exist
|
||||||
// yet.
|
// yet.
|
||||||
ID3D12DescriptorHeap* GetLastRequestHeap() const { return unsent_->heap; }
|
ID3D12DescriptorHeap* GetLastRequestHeap() const {
|
||||||
|
return writable_first_->heap;
|
||||||
|
}
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE GetLastRequestHeapCPUStart() const {
|
D3D12_CPU_DESCRIPTOR_HANDLE GetLastRequestHeapCPUStart() const {
|
||||||
return current_heap_cpu_start_;
|
return writable_first_->cpu_start;
|
||||||
}
|
}
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE GetLastRequestHeapGPUStart() const {
|
D3D12_GPU_DESCRIPTOR_HANDLE GetLastRequestHeapGPUStart() const {
|
||||||
return current_heap_gpu_start_;
|
return writable_first_->gpu_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
D3D12Context* context_;
|
ID3D12Device* device_;
|
||||||
D3D12_DESCRIPTOR_HEAP_TYPE type_;
|
D3D12_DESCRIPTOR_HEAP_TYPE type_;
|
||||||
uint32_t page_size_;
|
uint32_t page_size_;
|
||||||
|
|
||||||
void EndPage();
|
struct Page {
|
||||||
bool BeginNextPage();
|
|
||||||
|
|
||||||
struct DescriptorHeap {
|
|
||||||
ID3D12DescriptorHeap* heap;
|
ID3D12DescriptorHeap* heap;
|
||||||
DescriptorHeap* next;
|
D3D12_CPU_DESCRIPTOR_HANDLE cpu_start;
|
||||||
uint64_t frame_sent;
|
D3D12_GPU_DESCRIPTOR_HANDLE gpu_start;
|
||||||
|
uint64_t last_usage_fence_value;
|
||||||
|
Page* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A list of unsent heaps, with the first one being the current.
|
// A list of heap with free space, with the first buffer being the one
|
||||||
DescriptorHeap* unsent_ = nullptr;
|
// currently being filled.
|
||||||
// A list of sent heaps, moved to unsent in the beginning of a frame.
|
Page* writable_first_ = nullptr;
|
||||||
DescriptorHeap* sent_first_ = nullptr;
|
Page* writable_last_ = nullptr;
|
||||||
DescriptorHeap* sent_last_ = nullptr;
|
// A list of full heaps that can be reclaimed when the GPU doesn't use them
|
||||||
|
// anymore.
|
||||||
uint64_t current_page_ = 0;
|
Page* submitted_first_ = nullptr;
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE current_heap_cpu_start_ = {};
|
Page* submitted_last_ = nullptr;
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE current_heap_gpu_start_ = {};
|
// Monotonically increased when a new request is going to a different
|
||||||
uint32_t current_size_ = 0;
|
// ID3D12DescriptorHeap than the one that may be bound currently. See Request
|
||||||
|
// for more information.
|
||||||
// Reset in the beginning of a frame - don't try and fail to create a new page
|
uint64_t current_heap_index_ = 0;
|
||||||
// if failed to create one in the current frame.
|
uint32_t current_page_used_ = 0;
|
||||||
bool page_creation_failed_ = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace d3d12
|
} // namespace d3d12
|
||||||
|
|
Loading…
Reference in New Issue