[D3D12] Pre-create EDRAM and shared memory buffer descriptors

This commit is contained in:
Triang3l 2019-01-17 16:39:51 +03:00
parent cf7c981991
commit b7bcdf3e8b
7 changed files with 177 additions and 50 deletions

View File

@ -2803,14 +2803,14 @@ bool D3D12CommandProcessor::UpdateBindings(
// If updating fully, write the shared memory SRV and UAV descriptors and,
// if needed, the EDRAM descriptor.
gpu_handle_shared_memory_and_edram_ = view_gpu_handle;
shared_memory_->CreateSRV(view_cpu_handle);
shared_memory_->WriteRawSRVDescriptor(view_cpu_handle);
view_cpu_handle.ptr += descriptor_size_view;
view_gpu_handle.ptr += descriptor_size_view;
shared_memory_->CreateRawUAV(view_cpu_handle);
shared_memory_->WriteRawUAVDescriptor(view_cpu_handle);
view_cpu_handle.ptr += descriptor_size_view;
view_gpu_handle.ptr += descriptor_size_view;
if (IsROVUsedForEDRAM()) {
render_target_cache_->CreateEDRAMUint32UAV(view_cpu_handle);
render_target_cache_->WriteEDRAMUint32UAVDescriptor(view_cpu_handle);
view_cpu_handle.ptr += descriptor_size_view;
view_gpu_handle.ptr += descriptor_size_view;
}

View File

@ -121,10 +121,55 @@ bool RenderTargetCache::Initialize(const TextureCache* texture_cache) {
&edram_buffer_desc, edram_buffer_state_, nullptr,
IID_PPV_ARGS(&edram_buffer_)))) {
XELOGE("Failed to create the EDRAM buffer");
Shutdown();
return false;
}
edram_buffer_cleared_ = false;
// Create non-shader-visible descriptors of the EDRAM buffer for copying.
D3D12_DESCRIPTOR_HEAP_DESC edram_buffer_descriptor_heap_desc;
edram_buffer_descriptor_heap_desc.Type =
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
edram_buffer_descriptor_heap_desc.NumDescriptors =
uint32_t(EDRAMBufferDescriptorIndex::kCount);
edram_buffer_descriptor_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
edram_buffer_descriptor_heap_desc.NodeMask = 0;
if (FAILED(device->CreateDescriptorHeap(
&edram_buffer_descriptor_heap_desc,
IID_PPV_ARGS(&edram_buffer_descriptor_heap_)))) {
XELOGE("Failed to create the descriptor heap for EDRAM buffer views");
Shutdown();
return false;
}
edram_buffer_descriptor_heap_start_ =
edram_buffer_descriptor_heap_->GetCPUDescriptorHandleForHeapStart();
ui::d3d12::util::CreateRawBufferSRV(
device,
provider->OffsetViewDescriptor(
edram_buffer_descriptor_heap_start_,
uint32_t(EDRAMBufferDescriptorIndex::kRawSRV)),
edram_buffer_, GetEDRAMBufferSize());
ui::d3d12::util::CreateRawBufferUAV(
device,
provider->OffsetViewDescriptor(
edram_buffer_descriptor_heap_start_,
uint32_t(EDRAMBufferDescriptorIndex::kRawUAV)),
edram_buffer_, GetEDRAMBufferSize());
D3D12_UNORDERED_ACCESS_VIEW_DESC edram_buffer_uint32_uav_desc;
edram_buffer_uint32_uav_desc.Format = DXGI_FORMAT_R32_UINT;
edram_buffer_uint32_uav_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
edram_buffer_uint32_uav_desc.Buffer.FirstElement = 0;
edram_buffer_uint32_uav_desc.Buffer.NumElements =
GetEDRAMBufferSize() / sizeof(uint32_t);
edram_buffer_uint32_uav_desc.Buffer.StructureByteStride = 0;
edram_buffer_uint32_uav_desc.Buffer.CounterOffsetInBytes = 0;
edram_buffer_uint32_uav_desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
device->CreateUnorderedAccessView(
edram_buffer_, nullptr, &edram_buffer_uint32_uav_desc,
provider->OffsetViewDescriptor(
edram_buffer_descriptor_heap_start_,
uint32_t(EDRAMBufferDescriptorIndex::kUint32UAV)));
// Create the root signature for EDRAM buffer load/store.
D3D12_ROOT_PARAMETER load_store_root_parameters[2];
// Parameter 0 is constants (changed for each render target binding).
@ -343,6 +388,7 @@ void RenderTargetCache::Shutdown() {
}
ui::d3d12::util::ReleaseAndNull(edram_clear_root_signature_);
ui::d3d12::util::ReleaseAndNull(edram_load_store_root_signature_);
ui::d3d12::util::ReleaseAndNull(edram_buffer_descriptor_heap_);
ui::d3d12::util::ReleaseAndNull(edram_buffer_);
}
@ -1228,8 +1274,7 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
return false;
}
TransitionEDRAMBuffer(D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
ui::d3d12::util::CreateRawBufferSRV(device, descriptor_cpu_start,
edram_buffer_, GetEDRAMBufferSize());
WriteEDRAMRawSRVDescriptor(descriptor_cpu_start);
if (resolution_scale_2x_) {
texture_cache->UseScaledResolveBufferForWriting();
// Can't address more than 512 MB directly on Nvidia - binding only a part
@ -1240,7 +1285,7 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
((dest_address + dest_size - 1) >> 12) - (dest_address >> 12) + 1);
} else {
shared_memory->UseForWriting();
shared_memory->CreateRawUAV(
shared_memory->WriteRawUAVDescriptor(
provider->OffsetViewDescriptor(descriptor_cpu_start, 1));
}
command_processor_->SubmitBarriers();
@ -1421,8 +1466,7 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
0, sizeof(load_root_constants) / sizeof(uint32_t), &load_root_constants,
0);
ui::d3d12::util::CreateRawBufferSRV(device, descriptor_cpu_start,
edram_buffer_, GetEDRAMBufferSize());
WriteEDRAMRawSRVDescriptor(descriptor_cpu_start);
ui::d3d12::util::CreateRawBufferUAV(
device, provider->OffsetViewDescriptor(descriptor_cpu_start, 1),
copy_buffer, render_target->copy_buffer_size);
@ -1732,8 +1776,7 @@ bool RenderTargetCache::ResolveClear(uint32_t edram_base,
command_list->D3DSetComputeRootSignature(edram_clear_root_signature_);
command_list->D3DSetComputeRoot32BitConstants(
0, sizeof(root_constants) / sizeof(uint32_t), &root_constants, 0);
ui::d3d12::util::CreateRawBufferUAV(device, descriptor_cpu_start,
edram_buffer_, GetEDRAMBufferSize());
WriteEDRAMRawUAVDescriptor(descriptor_cpu_start);
command_list->D3DSetComputeRootDescriptorTable(1, descriptor_gpu_start);
// 1 group per 80x16 samples. Resolution scale handled in the shader itself.
command_list->D3DDispatch(row_width_ss_div_80, rows, 1);
@ -1946,19 +1989,16 @@ void RenderTargetCache::UseEDRAMAsUAV() {
TransitionEDRAMBuffer(D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
}
void RenderTargetCache::CreateEDRAMUint32UAV(
void RenderTargetCache::WriteEDRAMUint32UAVDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE handle) {
auto device =
command_processor_->GetD3D12Context()->GetD3D12Provider()->GetDevice();
D3D12_UNORDERED_ACCESS_VIEW_DESC desc;
desc.Format = DXGI_FORMAT_R32_UINT;
desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
desc.Buffer.FirstElement = 0;
desc.Buffer.NumElements = GetEDRAMBufferSize() / sizeof(uint32_t);
desc.Buffer.StructureByteStride = 0;
desc.Buffer.CounterOffsetInBytes = 0;
desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
device->CreateUnorderedAccessView(edram_buffer_, nullptr, &desc, handle);
auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider();
auto device = provider->GetDevice();
device->CopyDescriptorsSimple(
1, handle,
provider->OffsetViewDescriptor(
edram_buffer_descriptor_heap_start_,
uint32_t(EDRAMBufferDescriptorIndex::kUint32UAV)),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
}
void RenderTargetCache::EndFrame() { UnbindRenderTargets(); }
@ -2026,6 +2066,30 @@ void RenderTargetCache::TransitionEDRAMBuffer(D3D12_RESOURCE_STATES new_state) {
edram_buffer_state_ = new_state;
}
void RenderTargetCache::WriteEDRAMRawSRVDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE handle) {
auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider();
auto device = provider->GetDevice();
device->CopyDescriptorsSimple(
1, handle,
provider->OffsetViewDescriptor(
edram_buffer_descriptor_heap_start_,
uint32_t(EDRAMBufferDescriptorIndex::kRawSRV)),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
}
void RenderTargetCache::WriteEDRAMRawUAVDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE handle) {
auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider();
auto device = provider->GetDevice();
device->CopyDescriptorsSimple(
1, handle,
provider->OffsetViewDescriptor(
edram_buffer_descriptor_heap_start_,
uint32_t(EDRAMBufferDescriptorIndex::kRawUAV)),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
}
void RenderTargetCache::ClearBindings() {
current_surface_pitch_ = 0;
current_msaa_samples_ = MsaaSamples::k1X;
@ -2397,9 +2461,8 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() {
command_list->D3DSetComputeRootSignature(edram_load_store_root_signature_);
ui::d3d12::util::CreateRawBufferSRV(device, descriptor_cpu_start, copy_buffer,
copy_buffer_size);
ui::d3d12::util::CreateRawBufferUAV(
device, provider->OffsetViewDescriptor(descriptor_cpu_start, 1),
edram_buffer_, GetEDRAMBufferSize());
WriteEDRAMRawUAVDescriptor(
provider->OffsetViewDescriptor(descriptor_cpu_start, 1));
command_list->D3DSetComputeRootDescriptorTable(1, descriptor_gpu_start);
// Sort the bindings in ascending order of EDRAM base so data in the render
@ -2546,8 +2609,7 @@ void RenderTargetCache::LoadRenderTargetsFromEDRAM(
auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider();
auto device = provider->GetDevice();
command_list->D3DSetComputeRootSignature(edram_load_store_root_signature_);
ui::d3d12::util::CreateRawBufferSRV(device, descriptor_cpu_start,
edram_buffer_, GetEDRAMBufferSize());
WriteEDRAMRawSRVDescriptor(descriptor_cpu_start);
ui::d3d12::util::CreateRawBufferUAV(
device, provider->OffsetViewDescriptor(descriptor_cpu_start, 1),
copy_buffer, copy_buffer_size);

View File

@ -272,7 +272,7 @@ class RenderTargetCache {
void UnbindRenderTargets();
// Transitions the EDRAM buffer to a UAV - for use with ROV rendering.
void UseEDRAMAsUAV();
void CreateEDRAMUint32UAV(D3D12_CPU_DESCRIPTOR_HANDLE handle);
void WriteEDRAMUint32UAVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle);
void EndFrame();
// Totally necessary to rely on the base format - Too Human switches between
@ -419,6 +419,9 @@ class RenderTargetCache {
void TransitionEDRAMBuffer(D3D12_RESOURCE_STATES new_state);
void WriteEDRAMRawSRVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle);
void WriteEDRAMRawUAVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle);
void ClearBindings();
#if 0
@ -506,6 +509,20 @@ class RenderTargetCache {
D3D12_RESOURCE_STATES edram_buffer_state_;
bool edram_buffer_cleared_;
// Non-shader-visible descriptor heap containing pre-created SRV and UAV
// descriptors of the EDRAM buffer, for faster binding (via copying rather
// than creation).
enum class EDRAMBufferDescriptorIndex : uint32_t {
kRawSRV,
kRawUAV,
// For ROV access primarily.
kUint32UAV,
kCount,
};
ID3D12DescriptorHeap* edram_buffer_descriptor_heap_ = nullptr;
D3D12_CPU_DESCRIPTOR_HANDLE edram_buffer_descriptor_heap_start_;
// EDRAM root signatures.
ID3D12RootSignature* edram_load_store_root_signature_ = nullptr;
ID3D12RootSignature* edram_clear_root_signature_ = nullptr;

View File

@ -97,6 +97,33 @@ bool SharedMemory::Initialize() {
heap_count_ = 0;
heap_creation_failed_ = false;
D3D12_DESCRIPTOR_HEAP_DESC buffer_descriptor_heap_desc;
buffer_descriptor_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
buffer_descriptor_heap_desc.NumDescriptors =
uint32_t(BufferDescriptorIndex::kCount);
buffer_descriptor_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
buffer_descriptor_heap_desc.NodeMask = 0;
if (FAILED(device->CreateDescriptorHeap(
&buffer_descriptor_heap_desc,
IID_PPV_ARGS(&buffer_descriptor_heap_)))) {
XELOGE(
"Failed to create the descriptor heap for shared memory buffer views");
Shutdown();
return false;
}
buffer_descriptor_heap_start_ =
buffer_descriptor_heap_->GetCPUDescriptorHandleForHeapStart();
ui::d3d12::util::CreateRawBufferSRV(
device,
provider->OffsetViewDescriptor(buffer_descriptor_heap_start_,
uint32_t(BufferDescriptorIndex::kRawSRV)),
buffer_, kBufferSize);
ui::d3d12::util::CreateRawBufferUAV(
device,
provider->OffsetViewDescriptor(buffer_descriptor_heap_start_,
uint32_t(BufferDescriptorIndex::kRawUAV)),
buffer_, kBufferSize);
std::memset(valid_pages_.data(), 0, valid_pages_.size() * sizeof(uint64_t));
upload_buffer_pool_ =
@ -118,6 +145,8 @@ void SharedMemory::Shutdown() {
upload_buffer_pool_.reset();
ui::d3d12::util::ReleaseAndNull(buffer_descriptor_heap_);
// First free the buffer to detach it from the heaps.
ui::d3d12::util::ReleaseAndNull(buffer_);
@ -573,16 +602,24 @@ void SharedMemory::TransitionBuffer(D3D12_RESOURCE_STATES new_state) {
buffer_state_ = new_state;
}
void SharedMemory::CreateSRV(D3D12_CPU_DESCRIPTOR_HANDLE handle) {
ui::d3d12::util::CreateRawBufferSRV(
command_processor_->GetD3D12Context()->GetD3D12Provider()->GetDevice(),
handle, buffer_, kBufferSize);
void SharedMemory::WriteRawSRVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle) {
auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider();
auto device = provider->GetDevice();
device->CopyDescriptorsSimple(
1, handle,
provider->OffsetViewDescriptor(buffer_descriptor_heap_start_,
uint32_t(BufferDescriptorIndex::kRawSRV)),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
}
void SharedMemory::CreateRawUAV(D3D12_CPU_DESCRIPTOR_HANDLE handle) {
ui::d3d12::util::CreateRawBufferUAV(
command_processor_->GetD3D12Context()->GetD3D12Provider()->GetDevice(),
handle, buffer_, kBufferSize);
void SharedMemory::WriteRawUAVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle) {
auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider();
auto device = provider->GetDevice();
device->CopyDescriptorsSimple(
1, handle,
provider->OffsetViewDescriptor(buffer_descriptor_heap_start_,
uint32_t(BufferDescriptorIndex::kRawUAV)),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
}
} // namespace d3d12

View File

@ -119,8 +119,8 @@ class SharedMemory {
TransitionBuffer(D3D12_RESOURCE_STATE_COPY_SOURCE);
}
void CreateSRV(D3D12_CPU_DESCRIPTOR_HANDLE handle);
void CreateRawUAV(D3D12_CPU_DESCRIPTOR_HANDLE handle);
void WriteRawSRVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle);
void WriteRawUAVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle);
private:
bool AreTiledResourcesUsed() const;
@ -159,6 +159,17 @@ class SharedMemory {
// Total physical page count.
uint32_t page_count_;
// Non-shader-visible buffer descriptor heap for faster binding (via copying
// rather than creation).
enum class BufferDescriptorIndex : uint32_t {
kRawSRV,
kRawUAV,
kCount,
};
ID3D12DescriptorHeap* buffer_descriptor_heap_ = nullptr;
D3D12_CPU_DESCRIPTOR_HANDLE buffer_descriptor_heap_start_;
// Handle of the physical memory write callback.
void* physical_write_watch_handle_ = nullptr;

View File

@ -573,7 +573,7 @@ bool TextureCache::Initialize() {
Shutdown();
return false;
}
null_srv_descriptor_heap_cpu_start_ =
null_srv_descriptor_heap_start_ =
null_srv_descriptor_heap_->GetCPUDescriptorHandleForHeapStart();
D3D12_SHADER_RESOURCE_VIEW_DESC null_srv_desc;
null_srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
@ -593,7 +593,7 @@ bool TextureCache::Initialize() {
device->CreateShaderResourceView(
nullptr, &null_srv_desc,
provider->OffsetViewDescriptor(
null_srv_descriptor_heap_cpu_start_,
null_srv_descriptor_heap_start_,
uint32_t(NullSRVDescriptorIndex::k2DArray)));
null_srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;
null_srv_desc.Texture3D.MostDetailedMip = 0;
@ -601,7 +601,7 @@ bool TextureCache::Initialize() {
null_srv_desc.Texture3D.ResourceMinLODClamp = 0.0f;
device->CreateShaderResourceView(
nullptr, &null_srv_desc,
provider->OffsetViewDescriptor(null_srv_descriptor_heap_cpu_start_,
provider->OffsetViewDescriptor(null_srv_descriptor_heap_start_,
uint32_t(NullSRVDescriptorIndex::k3D)));
null_srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
null_srv_desc.TextureCube.MostDetailedMip = 0;
@ -609,7 +609,7 @@ bool TextureCache::Initialize() {
null_srv_desc.TextureCube.ResourceMinLODClamp = 0.0f;
device->CreateShaderResourceView(
nullptr, &null_srv_desc,
provider->OffsetViewDescriptor(null_srv_descriptor_heap_cpu_start_,
provider->OffsetViewDescriptor(null_srv_descriptor_heap_start_,
uint32_t(NullSRVDescriptorIndex::kCube)));
if (IsResolutionScale2X()) {
@ -961,7 +961,7 @@ void TextureCache::WriteTextureSRV(const D3D12Shader::TextureSRV& texture_srv,
// Copy a pre-made null descriptor since it's faster than to create an SRV.
device->CopyDescriptorsSimple(
1, handle,
provider->OffsetViewDescriptor(null_srv_descriptor_heap_cpu_start_,
provider->OffsetViewDescriptor(null_srv_descriptor_heap_start_,
uint32_t(null_descriptor_index)),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
return;
@ -993,15 +993,15 @@ void TextureCache::WriteTextureSRV(const D3D12Shader::TextureSRV& texture_srv,
IID_PPV_ARGS(&new_heap)))) {
SRVDescriptorCachePage new_page;
new_page.heap = new_heap;
new_page.cpu_start = new_heap->GetCPUDescriptorHandleForHeapStart();
new_page.heap_start = new_heap->GetCPUDescriptorHandleForHeapStart();
new_page.current_usage = 1;
cached_handle = new_page.cpu_start;
cached_handle = new_page.heap_start;
srv_descriptor_cache_.push_back(new_page);
}
} else {
SRVDescriptorCachePage& page = srv_descriptor_cache_.back();
cached_handle =
provider->OffsetViewDescriptor(page.cpu_start, page.current_usage);
provider->OffsetViewDescriptor(page.heap_start, page.current_usage);
++page.current_usage;
}
if (cached_handle.ptr) {
@ -1287,7 +1287,7 @@ bool TextureCache::TileResolvedTexture(
((texture_base + texture_size - 1) >> 12) - (texture_base >> 12) + 1);
} else {
resolve_tile_constants.guest_base = texture_base;
shared_memory_->CreateRawUAV(descriptor_cpu_uav);
shared_memory_->WriteRawUAVDescriptor(descriptor_cpu_uav);
}
}
command_list->D3DSetComputeRootDescriptorTable(1, descriptor_gpu_start);
@ -1928,7 +1928,7 @@ bool TextureCache::LoadTextureData(Texture* texture) {
}
} else {
shared_memory_->UseForReading();
shared_memory_->CreateSRV(descriptor_cpu_start);
shared_memory_->WriteRawSRVDescriptor(descriptor_cpu_start);
}
// Create two destination descriptors since the table has both.
for (uint32_t i = 1; i < descriptor_count; i += 2) {

View File

@ -368,7 +368,7 @@ class TextureCache {
struct SRVDescriptorCachePage {
static constexpr uint32_t kHeapSize = 65536;
ID3D12DescriptorHeap* heap;
D3D12_CPU_DESCRIPTOR_HANDLE cpu_start;
D3D12_CPU_DESCRIPTOR_HANDLE heap_start;
uint32_t current_usage;
};
@ -547,7 +547,7 @@ class TextureCache {
// Contains null SRV descriptors of dimensions from NullSRVDescriptorIndex.
// For copying, not shader-visible.
ID3D12DescriptorHeap* null_srv_descriptor_heap_ = nullptr;
D3D12_CPU_DESCRIPTOR_HANDLE null_srv_descriptor_heap_cpu_start_;
D3D12_CPU_DESCRIPTOR_HANDLE null_srv_descriptor_heap_start_;
TextureBinding texture_bindings_[32] = {};
// Bit vector with bits reset on fetch constant writes to avoid getting