[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

@@ -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;
}