[GPU/WGF] Use ByteAddressBuffer in precompiled shaders

Drivers and hardware may provide more optimal paths for untyped buffers
compared to typed.

Also, ByteAddressBuffer may be bound via a root descriptor in Direct3D 12,
greatly simplifying the binding logic.

ByteAddressBuffer also doesn't have the 128 * 2^20 element count limit that
typed and structured buffers have, and doesn't require the structure stride
to be specified at resource creation time in Direct3D 11.
This commit is contained in:
Triang3l
2026-02-09 21:29:18 +03:00
parent c7f61342d7
commit 80dad41454
211 changed files with 121690 additions and 123176 deletions

View File

@@ -519,48 +519,6 @@ D3D12CommandProcessor::GetSystemBindlessViewHandlePair(
view_bindless_heap_gpu_start_, uint32_t(view)));
}
ui::d3d12::util::DescriptorCpuGpuHandlePair
D3D12CommandProcessor::GetSharedMemoryUintPow2BindlessSRVHandlePair(
uint32_t element_size_bytes_pow2) const {
SystemBindlessView view;
switch (element_size_bytes_pow2) {
case 2:
view = SystemBindlessView::kSharedMemoryR32UintSRV;
break;
case 3:
view = SystemBindlessView::kSharedMemoryR32G32UintSRV;
break;
case 4:
view = SystemBindlessView::kSharedMemoryR32G32B32A32UintSRV;
break;
default:
assert_unhandled_case(element_size_bytes_pow2);
view = SystemBindlessView::kSharedMemoryR32UintSRV;
}
return GetSystemBindlessViewHandlePair(view);
}
ui::d3d12::util::DescriptorCpuGpuHandlePair
D3D12CommandProcessor::GetSharedMemoryUintPow2BindlessUAVHandlePair(
uint32_t element_size_bytes_pow2) const {
SystemBindlessView view;
switch (element_size_bytes_pow2) {
case 2:
view = SystemBindlessView::kSharedMemoryR32UintUAV;
break;
case 3:
view = SystemBindlessView::kSharedMemoryR32G32UintUAV;
break;
case 4:
view = SystemBindlessView::kSharedMemoryR32G32B32A32UintUAV;
break;
default:
assert_unhandled_case(element_size_bytes_pow2);
view = SystemBindlessView::kSharedMemoryR32UintUAV;
}
return GetSystemBindlessViewHandlePair(view);
}
ui::d3d12::util::DescriptorCpuGpuHandlePair
D3D12CommandProcessor::GetEdramUintPow2BindlessSRVHandlePair(
uint32_t element_size_bytes_pow2) const {
@@ -1470,46 +1428,10 @@ bool D3D12CommandProcessor::SetupContext() {
shared_memory_->WriteRawSRVDescriptor(provider.OffsetViewDescriptor(
view_bindless_heap_cpu_start_,
uint32_t(SystemBindlessView::kSharedMemoryRawSRV)));
// kSharedMemoryR32UintSRV.
shared_memory_->WriteUintPow2SRVDescriptor(
provider.OffsetViewDescriptor(
view_bindless_heap_cpu_start_,
uint32_t(SystemBindlessView::kSharedMemoryR32UintSRV)),
2);
// kSharedMemoryR32G32UintSRV.
shared_memory_->WriteUintPow2SRVDescriptor(
provider.OffsetViewDescriptor(
view_bindless_heap_cpu_start_,
uint32_t(SystemBindlessView::kSharedMemoryR32G32UintSRV)),
3);
// kSharedMemoryR32G32B32A32UintSRV.
shared_memory_->WriteUintPow2SRVDescriptor(
provider.OffsetViewDescriptor(
view_bindless_heap_cpu_start_,
uint32_t(SystemBindlessView::kSharedMemoryR32G32B32A32UintSRV)),
4);
// kSharedMemoryRawUAV.
shared_memory_->WriteRawUAVDescriptor(provider.OffsetViewDescriptor(
view_bindless_heap_cpu_start_,
uint32_t(SystemBindlessView::kSharedMemoryRawUAV)));
// kSharedMemoryR32UintUAV.
shared_memory_->WriteUintPow2UAVDescriptor(
provider.OffsetViewDescriptor(
view_bindless_heap_cpu_start_,
uint32_t(SystemBindlessView::kSharedMemoryR32UintUAV)),
2);
// kSharedMemoryR32G32UintUAV.
shared_memory_->WriteUintPow2UAVDescriptor(
provider.OffsetViewDescriptor(
view_bindless_heap_cpu_start_,
uint32_t(SystemBindlessView::kSharedMemoryR32G32UintUAV)),
3);
// kSharedMemoryR32G32B32A32UintUAV.
shared_memory_->WriteUintPow2UAVDescriptor(
provider.OffsetViewDescriptor(
view_bindless_heap_cpu_start_,
uint32_t(SystemBindlessView::kSharedMemoryR32G32B32A32UintUAV)),
4);
// kEdramRawSRV.
render_target_cache_->WriteEdramRawSRVDescriptor(
provider.OffsetViewDescriptor(

View File

@@ -145,13 +145,6 @@ class D3D12CommandProcessor : public CommandProcessor {
kNullRawSRV = kNullRawSRVAndSharedMemoryRawUAVStart,
kSharedMemoryRawUAV,
kSharedMemoryR32UintSRV,
kSharedMemoryR32G32UintSRV,
kSharedMemoryR32G32B32A32UintSRV,
kSharedMemoryR32UintUAV,
kSharedMemoryR32G32UintUAV,
kSharedMemoryR32G32B32A32UintUAV,
kEdramRawSRV,
kEdramR32UintSRV,
kEdramR32G32UintSRV,
@@ -177,12 +170,6 @@ class D3D12CommandProcessor : public CommandProcessor {
ui::d3d12::util::DescriptorCpuGpuHandlePair GetSystemBindlessViewHandlePair(
SystemBindlessView view) const;
ui::d3d12::util::DescriptorCpuGpuHandlePair
GetSharedMemoryUintPow2BindlessSRVHandlePair(
uint32_t element_size_bytes_pow2) const;
ui::d3d12::util::DescriptorCpuGpuHandlePair
GetSharedMemoryUintPow2BindlessUAVHandlePair(
uint32_t element_size_bytes_pow2) const;
ui::d3d12::util::DescriptorCpuGpuHandlePair
GetEdramUintPow2BindlessSRVHandlePair(uint32_t element_size_bytes_pow2) const;
ui::d3d12::util::DescriptorCpuGpuHandlePair
GetEdramUintPow2BindlessUAVHandlePair(uint32_t element_size_bytes_pow2) const;

View File

@@ -274,6 +274,7 @@ bool D3D12RenderTargetCache::Initialize() {
return false;
}
edram_buffer_->SetName(L"EDRAM Buffer");
edram_buffer_gpu_address_ = edram_buffer_->GetGPUVirtualAddress();
edram_buffer_modification_status_ =
EdramBufferModificationStatus::kUnmodified;
@@ -364,31 +365,15 @@ bool D3D12RenderTargetCache::Initialize() {
resolve_copy_root_parameters[0].ShaderVisibility =
D3D12_SHADER_VISIBILITY_ALL;
// Parameter 1 is the destination (shared memory).
D3D12_DESCRIPTOR_RANGE resolve_copy_dest_range;
resolve_copy_dest_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
resolve_copy_dest_range.NumDescriptors = 1;
resolve_copy_dest_range.BaseShaderRegister = 0;
resolve_copy_dest_range.RegisterSpace = 0;
resolve_copy_dest_range.OffsetInDescriptorsFromTableStart = 0;
resolve_copy_root_parameters[1].ParameterType =
D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
resolve_copy_root_parameters[1].DescriptorTable.NumDescriptorRanges = 1;
resolve_copy_root_parameters[1].DescriptorTable.pDescriptorRanges =
&resolve_copy_dest_range;
resolve_copy_root_parameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;
resolve_copy_root_parameters[1].Descriptor.ShaderRegister = 0;
resolve_copy_root_parameters[1].Descriptor.RegisterSpace = 0;
resolve_copy_root_parameters[1].ShaderVisibility =
D3D12_SHADER_VISIBILITY_ALL;
// Parameter 2 is the source (EDRAM).
D3D12_DESCRIPTOR_RANGE resolve_copy_source_range;
resolve_copy_source_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
resolve_copy_source_range.NumDescriptors = 1;
resolve_copy_source_range.BaseShaderRegister = 0;
resolve_copy_source_range.RegisterSpace = 0;
resolve_copy_source_range.OffsetInDescriptorsFromTableStart = 0;
resolve_copy_root_parameters[2].ParameterType =
D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
resolve_copy_root_parameters[2].DescriptorTable.NumDescriptorRanges = 1;
resolve_copy_root_parameters[2].DescriptorTable.pDescriptorRanges =
&resolve_copy_source_range;
resolve_copy_root_parameters[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
resolve_copy_root_parameters[2].Descriptor.ShaderRegister = 0;
resolve_copy_root_parameters[2].Descriptor.RegisterSpace = 0;
resolve_copy_root_parameters[2].ShaderVisibility =
D3D12_SHADER_VISIBILITY_ALL;
D3D12_ROOT_SIGNATURE_DESC resolve_copy_root_signature_desc;
@@ -583,20 +568,11 @@ bool D3D12RenderTargetCache::Initialize() {
&host_depth_store_root_source_range;
host_depth_store_root_source.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
// Destination.
D3D12_DESCRIPTOR_RANGE host_depth_store_root_dest_range;
host_depth_store_root_dest_range.RangeType =
D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
host_depth_store_root_dest_range.NumDescriptors = 1;
host_depth_store_root_dest_range.BaseShaderRegister = 0;
host_depth_store_root_dest_range.RegisterSpace = 0;
host_depth_store_root_dest_range.OffsetInDescriptorsFromTableStart = 0;
D3D12_ROOT_PARAMETER& host_depth_store_root_dest =
host_depth_store_root_parameters[kHostDepthStoreRootParameterDest];
host_depth_store_root_dest.ParameterType =
D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
host_depth_store_root_dest.DescriptorTable.NumDescriptorRanges = 1;
host_depth_store_root_dest.DescriptorTable.pDescriptorRanges =
&host_depth_store_root_dest_range;
host_depth_store_root_dest.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;
host_depth_store_root_dest.Descriptor.ShaderRegister = 0;
host_depth_store_root_dest.Descriptor.RegisterSpace = 0;
host_depth_store_root_dest.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
// Root signature.
D3D12_ROOT_SIGNATURE_DESC host_depth_store_root_desc;
@@ -1048,18 +1024,10 @@ bool D3D12RenderTargetCache::Initialize() {
resolve_rov_clear_root_parameters[0].ShaderVisibility =
D3D12_SHADER_VISIBILITY_ALL;
// Parameter 1 is the destination (EDRAM).
D3D12_DESCRIPTOR_RANGE resolve_rov_clear_dest_range;
resolve_rov_clear_dest_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
resolve_rov_clear_dest_range.NumDescriptors = 1;
resolve_rov_clear_dest_range.BaseShaderRegister = 0;
resolve_rov_clear_dest_range.RegisterSpace = 0;
resolve_rov_clear_dest_range.OffsetInDescriptorsFromTableStart = 0;
resolve_rov_clear_root_parameters[1].ParameterType =
D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
resolve_rov_clear_root_parameters[1].DescriptorTable.NumDescriptorRanges =
1;
resolve_rov_clear_root_parameters[1].DescriptorTable.pDescriptorRanges =
&resolve_rov_clear_dest_range;
D3D12_ROOT_PARAMETER_TYPE_UAV;
resolve_rov_clear_root_parameters[1].Descriptor.ShaderRegister = 0;
resolve_rov_clear_root_parameters[1].Descriptor.RegisterSpace = 0;
resolve_rov_clear_root_parameters[1].ShaderVisibility =
D3D12_SHADER_VISIBILITY_ALL;
D3D12_ROOT_SIGNATURE_DESC resolve_rov_clear_root_signature_desc;
@@ -1407,95 +1375,52 @@ bool D3D12RenderTargetCache::Resolve(const Memory& memory,
resolve_info.copy_dest_extent_length);
}
if (copy_dest_committed) {
// Write the descriptors and transition the resources.
// Full shared memory without resolution scaling, range of the scaled
// resolve buffer with scaling because only at least 128 * 2^20 R32
// elements must be addressable
// (D3D12_REQ_BUFFER_RESOURCE_TEXEL_COUNT_2_TO_EXP).
ui::d3d12::util::DescriptorCpuGpuHandlePair descriptor_dest;
ui::d3d12::util::DescriptorCpuGpuHandlePair descriptor_source;
ui::d3d12::util::DescriptorCpuGpuHandlePair descriptors[2];
if (command_processor_.RequestOneUseSingleViewDescriptors(
bindless_resources_used_ ? uint32_t(draw_resolution_scaled) : 2,
descriptors)) {
if (bindless_resources_used_) {
if (draw_resolution_scaled) {
descriptor_dest = descriptors[0];
} else {
descriptor_dest =
command_processor_
.GetSharedMemoryUintPow2BindlessUAVHandlePair(
copy_shader_info.dest_bpe_log2);
}
if (copy_shader_info.source_is_raw) {
descriptor_source =
command_processor_.GetSystemBindlessViewHandlePair(
D3D12CommandProcessor::SystemBindlessView::kEdramRawSRV);
} else {
descriptor_source =
command_processor_.GetEdramUintPow2BindlessSRVHandlePair(
copy_shader_info.source_bpe_log2);
}
} else {
descriptor_dest = descriptors[0];
if (!draw_resolution_scaled) {
shared_memory.WriteUintPow2UAVDescriptor(
descriptor_dest.first, copy_shader_info.dest_bpe_log2);
}
descriptor_source = descriptors[1];
if (copy_shader_info.source_is_raw) {
WriteEdramRawSRVDescriptor(descriptor_source.first);
} else {
WriteEdramUintPow2SRVDescriptor(descriptor_source.first,
copy_shader_info.source_bpe_log2);
}
}
if (draw_resolution_scaled) {
texture_cache.CreateCurrentScaledResolveRangeUintPow2UAV(
descriptor_dest.first, copy_shader_info.dest_bpe_log2);
texture_cache.TransitionCurrentScaledResolveRange(
D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
} else {
shared_memory.UseForWriting();
}
TransitionEdramBuffer(D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
command_list.D3DSetComputeRootSignature(resolve_copy_root_signature_);
// Submit the resolve.
command_list.D3DSetComputeRootSignature(resolve_copy_root_signature_);
command_list.D3DSetComputeRootDescriptorTable(
2, descriptor_source.second);
command_list.D3DSetComputeRootDescriptorTable(1,
descriptor_dest.second);
if (draw_resolution_scaled) {
command_list.D3DSetComputeRoot32BitConstants(
0,
sizeof(copy_shader_constants.dest_relative) / sizeof(uint32_t),
&copy_shader_constants.dest_relative, 0);
} else {
command_list.D3DSetComputeRoot32BitConstants(
0, sizeof(copy_shader_constants) / sizeof(uint32_t),
&copy_shader_constants, 0);
}
command_processor_.SetExternalPipeline(
resolve_copy_pipelines_[size_t(copy_shader)]);
command_processor_.SubmitBarriers();
command_list.D3DDispatch(copy_group_count_x, copy_group_count_y, 1);
// Source.
TransitionEdramBuffer(D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
command_list.D3DSetComputeRootShaderResourceView(
2, edram_buffer_gpu_address_);
// Order the resolve with other work using the destination as a UAV.
if (draw_resolution_scaled) {
texture_cache.MarkCurrentScaledResolveRangeUAVWritesCommitNeeded();
} else {
shared_memory.MarkUAVWritesCommitNeeded();
}
// Destination and constants.
if (draw_resolution_scaled) {
texture_cache.TransitionCurrentScaledResolveRange(
D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
command_list.D3DSetComputeRootUnorderedAccessView(
1, texture_cache.GetCurrentScaledResolveRangeGPUAddress());
// Invalidate textures and mark the range as scaled if needed.
texture_cache.MarkRangeAsResolved(
resolve_info.copy_dest_extent_start,
resolve_info.copy_dest_extent_length);
written_address_out = resolve_info.copy_dest_extent_start;
written_length_out = resolve_info.copy_dest_extent_length;
copied = true;
command_list.D3DSetComputeRoot32BitConstants(
0, sizeof(copy_shader_constants.dest_relative) / sizeof(uint32_t),
&copy_shader_constants.dest_relative, 0);
} else {
shared_memory.UseForWriting();
command_list.D3DSetComputeRootUnorderedAccessView(
1, shared_memory.GetGPUAddress());
command_list.D3DSetComputeRoot32BitConstants(
0, sizeof(copy_shader_constants) / sizeof(uint32_t),
&copy_shader_constants, 0);
}
// Dispatch the resolve.
command_processor_.SetExternalPipeline(
resolve_copy_pipelines_[size_t(copy_shader)]);
command_processor_.SubmitBarriers();
command_list.D3DDispatch(copy_group_count_x, copy_group_count_y, 1);
// Order the resolve with other work using the destination as a UAV.
if (draw_resolution_scaled) {
texture_cache.MarkCurrentScaledResolveRangeUAVWritesCommitNeeded();
} else {
shared_memory.MarkUAVWritesCommitNeeded();
}
// Invalidate textures and mark the range as scaled if needed.
texture_cache.MarkRangeAsResolved(resolve_info.copy_dest_extent_start,
resolve_info.copy_dest_extent_length);
written_address_out = resolve_info.copy_dest_extent_start;
written_length_out = resolve_info.copy_dest_extent_length;
copied = true;
} else {
XELOGE(
"D3D12RenderTargetCache: Failed to obtain the resolve destination "
@@ -1532,76 +1457,57 @@ bool D3D12RenderTargetCache::Resolve(const Memory& memory,
cleared = true;
} break;
case Path::kPixelShaderInterlock: {
ui::d3d12::util::DescriptorCpuGpuHandlePair descriptor_edram;
bool descriptor_edram_obtained;
if (bindless_resources_used_) {
descriptor_edram = command_processor_.GetSystemBindlessViewHandlePair(
D3D12CommandProcessor::SystemBindlessView ::
kEdramR32G32B32A32UintUAV);
descriptor_edram_obtained = true;
} else {
descriptor_edram_obtained =
command_processor_.RequestOneUseSingleViewDescriptors(
1, &descriptor_edram);
if (descriptor_edram_obtained) {
WriteEdramUintPow2UAVDescriptor(descriptor_edram.first, 4);
}
TransitionEdramBuffer(D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
// Should be safe to only commit once (if was UAV / ROV previously - if
// there was nothing to copy, only to clear, for some reason, for
// instance), overlap of the depth and the color ranges is highly
// unlikely.
CommitEdramBufferUAVWrites();
command_list.D3DSetComputeRootSignature(
resolve_rov_clear_root_signature_);
command_list.D3DSetComputeRootUnorderedAccessView(
1, edram_buffer_gpu_address_);
std::pair<uint32_t, uint32_t> clear_group_count =
resolve_info.GetClearShaderGroupCount(draw_resolution_scale_x(),
draw_resolution_scale_y());
assert_true(clear_group_count.first && clear_group_count.second);
if (clear_depth) {
draw_util::ResolveClearShaderConstants depth_clear_constants;
resolve_info.GetDepthClearShaderConstants(depth_clear_constants);
command_list.D3DSetComputeRoot32BitConstants(
0, sizeof(depth_clear_constants) / sizeof(uint32_t),
&depth_clear_constants, 0);
command_processor_.SetExternalPipeline(
resolve_rov_clear_32bpp_pipeline_);
command_processor_.SubmitBarriers();
command_list.D3DDispatch(clear_group_count.first,
clear_group_count.second, 1);
}
if (descriptor_edram_obtained) {
TransitionEdramBuffer(D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
// Should be safe to only commit once (if was UAV / ROV previously -
// if there was nothing to copy, only to clear, for some reason, for
// instance), overlap of the depth and the color ranges is highly
// unlikely.
CommitEdramBufferUAVWrites();
command_list.D3DSetComputeRootSignature(
resolve_rov_clear_root_signature_);
command_list.D3DSetComputeRootDescriptorTable(
1, descriptor_edram.second);
std::pair<uint32_t, uint32_t> clear_group_count =
resolve_info.GetClearShaderGroupCount(draw_resolution_scale_x(),
draw_resolution_scale_y());
assert_true(clear_group_count.first && clear_group_count.second);
if (clear_color) {
draw_util::ResolveClearShaderConstants color_clear_constants;
resolve_info.GetColorClearShaderConstants(color_clear_constants);
if (clear_depth) {
draw_util::ResolveClearShaderConstants depth_clear_constants;
resolve_info.GetDepthClearShaderConstants(depth_clear_constants);
// Non-RT-specific constants have already been set.
command_list.D3DSetComputeRoot32BitConstants(
0, sizeof(depth_clear_constants) / sizeof(uint32_t),
&depth_clear_constants, 0);
command_processor_.SetExternalPipeline(
resolve_rov_clear_32bpp_pipeline_);
command_processor_.SubmitBarriers();
command_list.D3DDispatch(clear_group_count.first,
clear_group_count.second, 1);
0, sizeof(color_clear_constants.rt_specific) / sizeof(uint32_t),
&color_clear_constants.rt_specific,
offsetof(draw_util::ResolveClearShaderConstants, rt_specific) /
sizeof(uint32_t));
} else {
command_list.D3DSetComputeRoot32BitConstants(
0, sizeof(color_clear_constants) / sizeof(uint32_t),
&color_clear_constants, 0);
}
if (clear_color) {
draw_util::ResolveClearShaderConstants color_clear_constants;
resolve_info.GetColorClearShaderConstants(color_clear_constants);
if (clear_depth) {
// Non-RT-specific constants have already been set.
command_list.D3DSetComputeRoot32BitConstants(
0,
sizeof(color_clear_constants.rt_specific) / sizeof(uint32_t),
&color_clear_constants.rt_specific,
offsetof(draw_util::ResolveClearShaderConstants,
rt_specific) /
sizeof(uint32_t));
} else {
command_list.D3DSetComputeRoot32BitConstants(
0, sizeof(color_clear_constants) / sizeof(uint32_t),
&color_clear_constants, 0);
}
command_processor_.SetExternalPipeline(
resolve_info.color_edram_info.format_is_64bpp
? resolve_rov_clear_64bpp_pipeline_
: resolve_rov_clear_32bpp_pipeline_);
command_processor_.SubmitBarriers();
command_list.D3DDispatch(clear_group_count.first,
clear_group_count.second, 1);
}
MarkEdramBufferModified();
cleared = true;
command_processor_.SetExternalPipeline(
resolve_info.color_edram_info.format_is_64bpp
? resolve_rov_clear_64bpp_pipeline_
: resolve_rov_clear_32bpp_pipeline_);
command_processor_.SubmitBarriers();
command_list.D3DDispatch(clear_group_count.first,
clear_group_count.second, 1);
}
MarkEdramBufferModified();
cleared = true;
} break;
default:
assert_unhandled_case(GetPath());
@@ -4548,38 +4454,19 @@ void D3D12RenderTargetCache::PerformTransfersAndResolveClears(
continue;
}
if (!host_depth_store_set_up) {
// Bindings.
// 0 - source.
// 1 - EDRAM if bindful.
// Source descriptor.
ui::d3d12::util::DescriptorCpuGpuHandlePair
host_depth_store_descriptors[2];
host_depth_store_descriptor_source;
if (!command_processor_.RequestOneUseSingleViewDescriptors(
1 + uint32_t(!bindless_resources_used_),
host_depth_store_descriptors)) {
1, &host_depth_store_descriptor_source)) {
continue;
}
command_list.D3DSetComputeRootSignature(
host_depth_store_root_signature_);
// Destination (EDRAM uint4 buffer).
if (bindless_resources_used_) {
command_list.D3DSetComputeRootDescriptorTable(
kHostDepthStoreRootParameterDest,
command_processor_.GetEdramUintPow2BindlessUAVHandlePair(4)
.second);
} else {
const ui::d3d12::util::DescriptorCpuGpuHandlePair&
host_depth_store_descriptor_dest =
host_depth_store_descriptors[1];
WriteEdramUintPow2UAVDescriptor(
host_depth_store_descriptor_dest.first, 4);
command_list.D3DSetComputeRootDescriptorTable(
kHostDepthStoreRootParameterDest,
host_depth_store_descriptor_dest.second);
}
// Destination (EDRAM buffer).
command_list.D3DSetComputeRootUnorderedAccessView(
kHostDepthStoreRootParameterDest, edram_buffer_gpu_address_);
// Depth source texture.
const ui::d3d12::util::DescriptorCpuGpuHandlePair&
host_depth_store_descriptor_source =
host_depth_store_descriptors[0];
device->CopyDescriptorsSimple(
1, host_depth_store_descriptor_source.first,
dest_d3d12_rt.descriptor_srv().GetHandle(),

View File

@@ -180,6 +180,7 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
// copied to a different buffer - the same range may have ROV-owned color and
// host float32 depth at the same time).
ID3D12Resource* edram_buffer_ = nullptr;
D3D12_GPU_VIRTUAL_ADDRESS edram_buffer_gpu_address_ = 0;
D3D12_RESOURCE_STATES edram_buffer_state_;
EdramBufferModificationStatus edram_buffer_modification_status_ =
EdramBufferModificationStatus::kUnmodified;

View File

@@ -237,60 +237,6 @@ void D3D12SharedMemory::WriteRawUAVDescriptor(
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
}
void D3D12SharedMemory::WriteUintPow2SRVDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE handle, uint32_t element_size_bytes_pow2) {
BufferDescriptorIndex descriptor_index;
switch (element_size_bytes_pow2) {
case 2:
descriptor_index = BufferDescriptorIndex::kR32UintSRV;
break;
case 3:
descriptor_index = BufferDescriptorIndex::kR32G32UintSRV;
break;
case 4:
descriptor_index = BufferDescriptorIndex::kR32G32B32A32UintSRV;
break;
default:
assert_unhandled_case(element_size_bytes_pow2);
return;
}
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
provider.OffsetViewDescriptor(buffer_descriptor_heap_start_,
uint32_t(descriptor_index)),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
}
void D3D12SharedMemory::WriteUintPow2UAVDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE handle, uint32_t element_size_bytes_pow2) {
BufferDescriptorIndex descriptor_index;
switch (element_size_bytes_pow2) {
case 2:
descriptor_index = BufferDescriptorIndex::kR32UintUAV;
break;
case 3:
descriptor_index = BufferDescriptorIndex::kR32G32UintUAV;
break;
case 4:
descriptor_index = BufferDescriptorIndex::kR32G32B32A32UintUAV;
break;
default:
assert_unhandled_case(element_size_bytes_pow2);
return;
}
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
provider.OffsetViewDescriptor(buffer_descriptor_heap_start_,
uint32_t(descriptor_index)),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
}
bool D3D12SharedMemory::InitializeTraceSubmitDownloads() {
ResetTraceDownload();
PrepareForTraceDownload();

View File

@@ -76,12 +76,6 @@ class D3D12SharedMemory : public SharedMemory {
void WriteRawSRVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle);
void WriteRawUAVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle);
// Due to the D3D12_REQ_BUFFER_RESOURCE_TEXEL_COUNT_2_TO_EXP limitation, the
// smallest supported formats are 32-bit.
void WriteUintPow2SRVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle,
uint32_t element_size_bytes_pow2);
void WriteUintPow2UAVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle,
uint32_t element_size_bytes_pow2);
// Returns true if any downloads were submitted to the command processor.
bool InitializeTraceSubmitDownloads();

View File

@@ -444,26 +444,14 @@ bool D3D12TextureCache::Initialize() {
root_parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
// Parameter 1 is the source (may be changed multiple times for the same
// destination).
D3D12_DESCRIPTOR_RANGE root_dest_range;
root_dest_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
root_dest_range.NumDescriptors = 1;
root_dest_range.BaseShaderRegister = 0;
root_dest_range.RegisterSpace = 0;
root_dest_range.OffsetInDescriptorsFromTableStart = 0;
root_parameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
root_parameters[1].DescriptorTable.NumDescriptorRanges = 1;
root_parameters[1].DescriptorTable.pDescriptorRanges = &root_dest_range;
root_parameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
root_parameters[1].Descriptor.ShaderRegister = 0;
root_parameters[1].Descriptor.RegisterSpace = 0;
root_parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
// Parameter 2 is the destination.
D3D12_DESCRIPTOR_RANGE root_source_range;
root_source_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
root_source_range.NumDescriptors = 1;
root_source_range.BaseShaderRegister = 0;
root_source_range.RegisterSpace = 0;
root_source_range.OffsetInDescriptorsFromTableStart = 0;
root_parameters[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
root_parameters[2].DescriptorTable.NumDescriptorRanges = 1;
root_parameters[2].DescriptorTable.pDescriptorRanges = &root_source_range;
root_parameters[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;
root_parameters[2].Descriptor.ShaderRegister = 0;
root_parameters[2].Descriptor.RegisterSpace = 0;
root_parameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
D3D12_ROOT_SIGNATURE_DESC root_signature_desc;
root_signature_desc.NumParameters = UINT(xe::countof(root_parameters));
@@ -1405,40 +1393,16 @@ void D3D12TextureCache::TransitionCurrentScaledResolveRange(
buffer.resource(), buffer.SetResourceState(new_state), new_state);
}
void D3D12TextureCache::CreateCurrentScaledResolveRangeUintPow2SRV(
D3D12_CPU_DESCRIPTOR_HANDLE handle, uint32_t element_size_bytes_pow2) {
D3D12_GPU_VIRTUAL_ADDRESS
D3D12TextureCache::GetCurrentScaledResolveRangeGPUAddress() const {
assert_true(IsDrawResolutionScaled());
size_t buffer_index = GetCurrentScaledResolveBufferIndex();
const size_t buffer_index = GetCurrentScaledResolveBufferIndex();
const ScaledResolveVirtualBuffer* buffer =
scaled_resolve_2gb_buffers_[buffer_index].get();
assert_not_null(buffer);
ui::d3d12::util::CreateBufferTypedSRV(
command_processor_.GetD3D12Provider().GetDevice(), handle,
buffer->resource(),
ui::d3d12::util::GetUintPow2DXGIFormat(element_size_bytes_pow2),
uint32_t(scaled_resolve_current_range_length_scaled_ >>
element_size_bytes_pow2),
(scaled_resolve_current_range_start_scaled_ -
(uint64_t(buffer_index) << 30)) >>
element_size_bytes_pow2);
}
void D3D12TextureCache::CreateCurrentScaledResolveRangeUintPow2UAV(
D3D12_CPU_DESCRIPTOR_HANDLE handle, uint32_t element_size_bytes_pow2) {
assert_true(IsDrawResolutionScaled());
size_t buffer_index = GetCurrentScaledResolveBufferIndex();
const ScaledResolveVirtualBuffer* buffer =
scaled_resolve_2gb_buffers_[buffer_index].get();
assert_not_null(buffer);
ui::d3d12::util::CreateBufferTypedUAV(
command_processor_.GetD3D12Provider().GetDevice(), handle,
buffer->resource(),
ui::d3d12::util::GetUintPow2DXGIFormat(element_size_bytes_pow2),
uint32_t(scaled_resolve_current_range_length_scaled_ >>
element_size_bytes_pow2),
(scaled_resolve_current_range_start_scaled_ -
(uint64_t(buffer_index) << 30)) >>
element_size_bytes_pow2);
return buffer->resource()->GetGPUVirtualAddress() +
(scaled_resolve_current_range_start_scaled_ -
(uint64_t(buffer_index) << 30));
}
ID3D12Resource* D3D12TextureCache::RequestSwapTexture(
@@ -1782,61 +1746,18 @@ bool D3D12TextureCache::LoadTextureDataFromResidentMemoryImpl(Texture& texture,
return false;
}
// Begin loading.
// May use different buffers for scaled base and mips, and also addressability
// of more than 128 * 2^20 (2^D3D12_REQ_BUFFER_RESOURCE_TEXEL_COUNT_2_TO_EXP)
// texels is not mandatory - need two separate UAV descriptors for base and
// mips.
// Destination.
uint32_t descriptor_count = 1;
if (texture_resolution_scaled) {
// Source - base and mips, one or both.
descriptor_count += (level_first == 0 && level_last != 0) ? 2 : 1;
} else {
// Source - shared memory.
if (!bindless_resources_used_) {
++descriptor_count;
}
}
ui::d3d12::util::DescriptorCpuGpuHandlePair descriptors_allocated[3];
if (!command_processor_.RequestOneUseSingleViewDescriptors(
descriptor_count, descriptors_allocated)) {
command_processor_.ReleaseScratchGPUBuffer(copy_buffer, copy_buffer_state);
return false;
}
uint32_t descriptor_write_index = 0;
command_processor_.SetExternalPipeline(pipeline);
command_list.D3DSetComputeRootSignature(load_root_signature_.Get());
// Set up the destination descriptor.
assert_true(descriptor_write_index < descriptor_count);
ui::d3d12::util::DescriptorCpuGpuHandlePair descriptor_dest =
descriptors_allocated[descriptor_write_index++];
ui::d3d12::util::CreateBufferTypedUAV(
device, descriptor_dest.first, copy_buffer,
ui::d3d12::util::GetUintPow2DXGIFormat(load_shader_info.dest_bpe_log2),
uint32_t(copy_buffer_size) >> load_shader_info.dest_bpe_log2);
command_list.D3DSetComputeRootDescriptorTable(2, descriptor_dest.second);
// Set up the unscaled source descriptor (scaled needs two descriptors that
// depend on the buffer being current, so they will be set later - for mips,
// after loading the base is done).
command_list.D3DSetComputeRootUnorderedAccessView(
2, copy_buffer->GetGPUVirtualAddress());
// Set up the unscaled source binding (scaled may have the base and the mips
// in different buffer resources).
if (!texture_resolution_scaled) {
D3D12SharedMemory& d3d12_shared_memory =
static_cast<D3D12SharedMemory&>(shared_memory());
d3d12_shared_memory.UseForReading();
ui::d3d12::util::DescriptorCpuGpuHandlePair descriptor_unscaled_source;
if (bindless_resources_used_) {
descriptor_unscaled_source =
command_processor_.GetSharedMemoryUintPow2BindlessSRVHandlePair(
load_shader_info.source_bpe_log2);
} else {
assert_true(descriptor_write_index < descriptor_count);
descriptor_unscaled_source =
descriptors_allocated[descriptor_write_index++];
d3d12_shared_memory.WriteUintPow2SRVDescriptor(
descriptor_unscaled_source.first, load_shader_info.source_bpe_log2);
}
command_list.D3DSetComputeRootDescriptorTable(
1, descriptor_unscaled_source.second);
command_list.D3DSetComputeRootShaderResourceView(
1, d3d12_shared_memory.GetGPUAddress());
}
// Submit the copy buffer population commands.
@@ -1872,20 +1793,15 @@ bool D3D12TextureCache::LoadTextureDataFromResidentMemoryImpl(Texture& texture,
uint32_t guest_size_unscaled = is_base ? d3d12_texture.GetGuestBaseSize()
: d3d12_texture.GetGuestMipsSize();
if (!MakeScaledResolveRangeCurrent(guest_address, guest_size_unscaled,
load_shader_info.source_bpe_log2)) {
4)) {
command_processor_.ReleaseScratchGPUBuffer(copy_buffer,
copy_buffer_state);
return false;
}
TransitionCurrentScaledResolveRange(
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
assert_true(descriptor_write_index < descriptor_count);
ui::d3d12::util::DescriptorCpuGpuHandlePair descriptor_scaled_source =
descriptors_allocated[descriptor_write_index++];
CreateCurrentScaledResolveRangeUintPow2SRV(
descriptor_scaled_source.first, load_shader_info.source_bpe_log2);
command_list.D3DSetComputeRootDescriptorTable(
1, descriptor_scaled_source.second);
command_list.D3DSetComputeRootShaderResourceView(
1, GetCurrentScaledResolveRangeGPUAddress());
if (!is_base) {
scaled_mips_source_set_up = true;
}

View File

@@ -140,13 +140,9 @@ class D3D12TextureCache final : public TextureCache {
bool MakeScaledResolveRangeCurrent(uint32_t start_unscaled,
uint32_t length_unscaled,
uint32_t length_scaled_alignment_log2 = 0);
// These functions create a view of the range specified in the last successful
// MakeScaledResolveRangeCurrent call because that function must be called
// before this.
void CreateCurrentScaledResolveRangeUintPow2SRV(
D3D12_CPU_DESCRIPTOR_HANDLE handle, uint32_t element_size_bytes_pow2);
void CreateCurrentScaledResolveRangeUintPow2UAV(
D3D12_CPU_DESCRIPTOR_HANDLE handle, uint32_t element_size_bytes_pow2);
// Returns the GPU address of the range specified in the last successful
// MakeScaledResolveRangeCurrent call.
D3D12_GPU_VIRTUAL_ADDRESS GetCurrentScaledResolveRangeGPUAddress() const;
void TransitionCurrentScaledResolveRange(D3D12_RESOURCE_STATES new_state);
void MarkCurrentScaledResolveRangeUAVWritesCommitNeeded() {
assert_true(IsDrawResolutionScaled());

View File

@@ -183,15 +183,13 @@ void DeferredCommandList::Execute(ID3D12GraphicsCommandList* command_list,
} break;
case Command::kD3DSetComputeRootConstantBufferView: {
auto& args =
*reinterpret_cast<const SetRootConstantBufferViewArguments*>(
stream);
*reinterpret_cast<const SetRootDescriptorArguments*>(stream);
command_list->SetComputeRootConstantBufferView(
args.root_parameter_index, args.buffer_location);
} break;
case Command::kD3DSetGraphicsRootConstantBufferView: {
auto& args =
*reinterpret_cast<const SetRootConstantBufferViewArguments*>(
stream);
*reinterpret_cast<const SetRootDescriptorArguments*>(stream);
command_list->SetGraphicsRootConstantBufferView(
args.root_parameter_index, args.buffer_location);
} break;
@@ -207,6 +205,18 @@ void DeferredCommandList::Execute(ID3D12GraphicsCommandList* command_list,
command_list->SetGraphicsRootDescriptorTable(args.root_parameter_index,
args.base_descriptor);
} break;
case Command::kD3DSetComputeRootShaderResourceView: {
auto& args =
*reinterpret_cast<const SetRootDescriptorArguments*>(stream);
command_list->SetComputeRootShaderResourceView(
args.root_parameter_index, args.buffer_location);
} break;
case Command::kD3DSetGraphicsRootShaderResourceView: {
auto& args =
*reinterpret_cast<const SetRootDescriptorArguments*>(stream);
command_list->SetGraphicsRootShaderResourceView(
args.root_parameter_index, args.buffer_location);
} break;
case Command::kD3DSetComputeRootSignature: {
command_list->SetComputeRootSignature(
*reinterpret_cast<ID3D12RootSignature* const*>(stream));
@@ -215,6 +225,18 @@ void DeferredCommandList::Execute(ID3D12GraphicsCommandList* command_list,
command_list->SetGraphicsRootSignature(
*reinterpret_cast<ID3D12RootSignature* const*>(stream));
} break;
case Command::kD3DSetComputeRootUnorderedAccessView: {
auto& args =
*reinterpret_cast<const SetRootDescriptorArguments*>(stream);
command_list->SetComputeRootUnorderedAccessView(
args.root_parameter_index, args.buffer_location);
} break;
case Command::kD3DSetGraphicsRootUnorderedAccessView: {
auto& args =
*reinterpret_cast<const SetRootDescriptorArguments*>(stream);
command_list->SetGraphicsRootUnorderedAccessView(
args.root_parameter_index, args.buffer_location);
} break;
case Command::kSetDescriptorHeaps: {
auto& args =
*reinterpret_cast<const SetDescriptorHeapsArguments*>(stream);

View File

@@ -322,18 +322,18 @@ class DeferredCommandList {
void D3DSetComputeRootConstantBufferView(
UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS buffer_location) {
auto& args = *reinterpret_cast<SetRootConstantBufferViewArguments*>(
auto& args = *reinterpret_cast<SetRootDescriptorArguments*>(
WriteCommand(Command::kD3DSetComputeRootConstantBufferView,
sizeof(SetRootConstantBufferViewArguments)));
sizeof(SetRootDescriptorArguments)));
args.root_parameter_index = root_parameter_index;
args.buffer_location = buffer_location;
}
void D3DSetGraphicsRootConstantBufferView(
UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS buffer_location) {
auto& args = *reinterpret_cast<SetRootConstantBufferViewArguments*>(
auto& args = *reinterpret_cast<SetRootDescriptorArguments*>(
WriteCommand(Command::kD3DSetGraphicsRootConstantBufferView,
sizeof(SetRootConstantBufferViewArguments)));
sizeof(SetRootDescriptorArguments)));
args.root_parameter_index = root_parameter_index;
args.buffer_location = buffer_location;
}
@@ -356,6 +356,24 @@ class DeferredCommandList {
args.base_descriptor.ptr = base_descriptor.ptr;
}
void D3DSetComputeRootShaderResourceView(
UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS buffer_location) {
auto& args = *reinterpret_cast<SetRootDescriptorArguments*>(
WriteCommand(Command::kD3DSetComputeRootShaderResourceView,
sizeof(SetRootDescriptorArguments)));
args.root_parameter_index = root_parameter_index;
args.buffer_location = buffer_location;
}
void D3DSetGraphicsRootShaderResourceView(
UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS buffer_location) {
auto& args = *reinterpret_cast<SetRootDescriptorArguments*>(
WriteCommand(Command::kD3DSetGraphicsRootShaderResourceView,
sizeof(SetRootDescriptorArguments)));
args.root_parameter_index = root_parameter_index;
args.buffer_location = buffer_location;
}
void D3DSetComputeRootSignature(ID3D12RootSignature* root_signature) {
auto& arg = *reinterpret_cast<ID3D12RootSignature**>(WriteCommand(
Command::kD3DSetComputeRootSignature, sizeof(ID3D12RootSignature*)));
@@ -368,6 +386,24 @@ class DeferredCommandList {
arg = root_signature;
}
void D3DSetComputeRootUnorderedAccessView(
UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS buffer_location) {
auto& args = *reinterpret_cast<SetRootDescriptorArguments*>(
WriteCommand(Command::kD3DSetComputeRootUnorderedAccessView,
sizeof(SetRootDescriptorArguments)));
args.root_parameter_index = root_parameter_index;
args.buffer_location = buffer_location;
}
void D3DSetGraphicsRootUnorderedAccessView(
UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS buffer_location) {
auto& args = *reinterpret_cast<SetRootDescriptorArguments*>(
WriteCommand(Command::kD3DSetGraphicsRootUnorderedAccessView,
sizeof(SetRootDescriptorArguments)));
args.root_parameter_index = root_parameter_index;
args.buffer_location = buffer_location;
}
void SetDescriptorHeaps(ID3D12DescriptorHeap* cbv_srv_uav_descriptor_heap,
ID3D12DescriptorHeap* sampler_descriptor_heap) {
auto& args = *reinterpret_cast<SetDescriptorHeapsArguments*>(WriteCommand(
@@ -427,8 +463,12 @@ class DeferredCommandList {
kD3DSetGraphicsRootConstantBufferView,
kD3DSetComputeRootDescriptorTable,
kD3DSetGraphicsRootDescriptorTable,
kD3DSetComputeRootShaderResourceView,
kD3DSetGraphicsRootShaderResourceView,
kD3DSetComputeRootSignature,
kD3DSetGraphicsRootSignature,
kD3DSetComputeRootUnorderedAccessView,
kD3DSetGraphicsRootUnorderedAccessView,
kSetDescriptorHeaps,
kD3DSetPipelineState,
kSetPipelineStateHandle,
@@ -536,7 +576,7 @@ class DeferredCommandList {
UINT dest_offset_in_32bit_values;
};
struct SetRootConstantBufferViewArguments {
struct SetRootDescriptorArguments {
UINT root_parameter_index;
D3D12_GPU_VIRTUAL_ADDRESS buffer_location;
};