From cec58f6b6bb41f037706abdd262d5073cd70b534 Mon Sep 17 00:00:00 2001 From: davidd-lunarg <73848817+davidd-lunarg@users.noreply.github.com> Date: Tue, 6 Feb 2024 11:48:41 -0800 Subject: [PATCH] Refactor methods in Dx12ResourceDataUtil Refactor common code for reading or writing resource data into static functions. The existing functions work the same. The new functions can be used to allow more control for reading and writing resources. --- .../decode/dx12_replay_consumer_base.cpp | 3 +- .../decode/dx12_resource_value_mapper.cpp | 8 +- .../graphics/dx12_resource_data_util.cpp | 495 ++++++++++-------- framework/graphics/dx12_resource_data_util.h | 79 +-- 4 files changed, 323 insertions(+), 262 deletions(-) diff --git a/framework/decode/dx12_replay_consumer_base.cpp b/framework/decode/dx12_replay_consumer_base.cpp index f489d44897..e559efce09 100644 --- a/framework/decode/dx12_replay_consumer_base.cpp +++ b/framework/decode/dx12_replay_consumer_base.cpp @@ -354,8 +354,7 @@ void Dx12ReplayConsumerBase::ApplyBatchedResourceInitInfo( resource_info.second.data, resource_info.second.subresource_offsets, resource_info.second.subresource_sizes, - resource_info.second.staging_resource, - true); + resource_info.second.staging_resource); } } resource_data_util_->CloseCommandList(); diff --git a/framework/decode/dx12_resource_value_mapper.cpp b/framework/decode/dx12_resource_value_mapper.cpp index 99e9b8f811..6fc240ba49 100644 --- a/framework/decode/dx12_resource_value_mapper.cpp +++ b/framework/decode/dx12_resource_value_mapper.cpp @@ -1333,8 +1333,8 @@ void Dx12ResourceValueMapper::MapResources(const ResourceValueInfoMap& temp_resource_states, temp_resource_states, temp_resource_data, - temp_resource_sizes, - temp_resource_offsets); + temp_resource_offsets, + temp_resource_sizes); if (SUCCEEDED(hr)) { @@ -1367,8 +1367,8 @@ void Dx12ResourceValueMapper::MapResources(const ResourceValueInfoMap& temp_resource_states, temp_resource_states, temp_resource_data, - temp_resource_sizes, - temp_resource_offsets); + temp_resource_offsets, + temp_resource_sizes); } if (FAILED(hr)) diff --git a/framework/graphics/dx12_resource_data_util.cpp b/framework/graphics/dx12_resource_data_util.cpp index 68cfd8e809..a039473613 100644 --- a/framework/graphics/dx12_resource_data_util.cpp +++ b/framework/graphics/dx12_resource_data_util.cpp @@ -127,16 +127,64 @@ bool AddTransitionBarrier(ID3D12GraphicsCommandList* cmd_list, return true; } +size_t Dx12ResourceDataUtil::GetSubresourceCount(ID3D12Resource* resource) +{ + GFXRECON_ASSERT(resource != nullptr); + + size_t sub_count = 0; + auto device = dx12::GetDeviceComPtrFromChild(resource); + auto res_desc = resource->GetDesc(); + + if (res_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + sub_count = 1; + } + else + { + GFXRECON_ASSERT((res_desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D) || + (res_desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D) || + (res_desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D)); + + uint32_t plane_count = 1; + + // Get the plane count for the texture format. With D3D12, each plane has its own subresource. + D3D12_FEATURE_DATA_FORMAT_INFO format_info = { res_desc.Format, 0 }; + if (SUCCEEDED(device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &format_info, sizeof(format_info)))) + { + plane_count = format_info.PlaneCount; + } + + sub_count = res_desc.MipLevels * plane_count; + + if ((res_desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D) || + (res_desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D)) + { + sub_count *= res_desc.DepthOrArraySize; + } + } + return sub_count; +} + void Dx12ResourceDataUtil::GetResourceCopyInfo(ID3D12Resource* resource, size_t& subresource_count, std::vector& subresource_offsets, std::vector& subresource_sizes, std::vector& layouts, - uint64_t& total_size) + uint64_t& total_size, + ID3D12Device* device) { GFXRECON_ASSERT(resource != nullptr); - subresource_count = 0; + dx12::ID3D12DeviceComPtr device_com_ptr; + if (device == nullptr) + { + device_com_ptr = dx12::GetDeviceComPtrFromChild(resource); + device = device_com_ptr.GetInterfacePtr(); + } + GFXRECON_ASSERT(device != nullptr); + + subresource_count = GetSubresourceCount(resource); + subresource_offsets.clear(); subresource_sizes.clear(); layouts.clear(); total_size = 0; @@ -145,60 +193,35 @@ void Dx12ResourceDataUtil::GetResourceCopyInfo(ID3D12Resource* if (resource_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) { - subresource_count = 1; layouts.resize(subresource_count); subresource_sizes.push_back(resource_desc.Width); subresource_offsets.push_back(0); - device_->GetCopyableFootprints(&resource_desc, 0, 1, 0, layouts.data(), nullptr, nullptr, &total_size); + device->GetCopyableFootprints(&resource_desc, 0, 1, 0, layouts.data(), nullptr, nullptr, &total_size); // Total resource size should be equal to buffer width and should have 0 offset. GFXRECON_ASSERT((total_size == resource_desc.Width) && (layouts[0].Offset == 0)); } else { - GFXRECON_ASSERT((resource_desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D) || - (resource_desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D) || - (resource_desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D)); - - uint32_t plane_count = 1; - - // Get the plane count for the texture format. With D3D12, each plane has its own subresource. - D3D12_FEATURE_DATA_FORMAT_INFO format_info = { resource_desc.Format, 0 }; - if (SUCCEEDED(device_->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &format_info, sizeof(format_info)))) - { - plane_count = format_info.PlaneCount; - } - - auto num_subresources = resource_desc.MipLevels * plane_count; - - if ((resource_desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D) || - (resource_desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D)) - { - num_subresources *= resource_desc.DepthOrArraySize; - } - - layouts.resize(num_subresources); - temp_subresource_row_counts_.clear(); - temp_subresource_row_counts_.resize(num_subresources); - temp_subresource_row_size_bytes_.clear(); - temp_subresource_row_size_bytes_.resize(num_subresources); + layouts.resize(subresource_count); + std::vector subresource_row_counts(subresource_count); + std::vector subresource_row_size_bytes(subresource_count); - graphics::dx12::RobustGetCopyableFootprint(device_, + graphics::dx12::RobustGetCopyableFootprint(device, resource, &resource_desc, 0, - num_subresources, + subresource_count, 0, layouts.data(), - temp_subresource_row_counts_.data(), - temp_subresource_row_size_bytes_.data(), + subresource_row_counts.data(), + subresource_row_size_bytes.data(), &total_size); - subresource_count = num_subresources; - subresource_sizes.resize(num_subresources); - subresource_offsets.resize(num_subresources); - for (size_t i = 0; i < num_subresources; ++i) + subresource_sizes.resize(subresource_count); + subresource_offsets.resize(subresource_count); + for (size_t i = 0; i < subresource_count; ++i) { size_t slice_count = 1; if (resource_desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D) @@ -212,9 +235,8 @@ void Dx12ResourceDataUtil::GetResourceCopyInfo(ID3D12Resource* // Compute the size required to copy the subresource. The final row of the subresource does not require // padding, so the total size is (row_count - 1) * row_pitch + row_size_bytes. - size_t row_count = temp_subresource_row_counts_[i] * slice_count; - subresource_sizes[i] = - (row_count - 1) * layouts[i].Footprint.RowPitch + temp_subresource_row_size_bytes_[i]; + size_t row_count = subresource_row_counts[i] * slice_count; + subresource_sizes[i] = (row_count - 1) * layouts[i].Footprint.RowPitch + subresource_row_size_bytes[i]; subresource_offsets[i] = layouts[i].Offset; } @@ -334,7 +356,8 @@ dx12::ID3D12ResourceComPtr Dx12ResourceDataUtil::GetStagingBuffer(CopyType type, return staging_buffers_[type]; } -dx12::ID3D12ResourceComPtr Dx12ResourceDataUtil::CreateStagingBuffer(CopyType type, uint64_t required_buffer_size) +dx12::ID3D12ResourceComPtr +Dx12ResourceDataUtil::CreateStagingBuffer(ID3D12Device* device, CopyType type, uint64_t required_buffer_size) { if (required_buffer_size == 0) { @@ -350,7 +373,12 @@ dx12::ID3D12ResourceComPtr Dx12ResourceDataUtil::CreateStagingBuffer(CopyType ty staging_resource_state = D3D12_RESOURCE_STATE_GENERIC_READ; } return graphics::dx12::CreateBufferResource( - device_, required_buffer_size, staging_resource_type, staging_resource_state, D3D12_RESOURCE_FLAG_NONE); + device, required_buffer_size, staging_resource_type, staging_resource_state, D3D12_RESOURCE_FLAG_NONE); +} + +dx12::ID3D12ResourceComPtr Dx12ResourceDataUtil::CreateStagingBuffer(CopyType type, uint64_t required_buffer_size) +{ + return CreateStagingBuffer(device_, type, required_buffer_size); } HRESULT Dx12ResourceDataUtil::ReadFromResource(ID3D12Resource* target_resource, @@ -360,7 +388,7 @@ HRESULT Dx12ResourceDataUtil::ReadFromResource(ID3D12Resource* std::vector& data, std::vector& subresource_offsets, std::vector& subresource_sizes, - ID3D12Resource* staging_resource) + ID3D12Resource* staging_buffer_for_batching) { HRESULT result = E_FAIL; @@ -373,48 +401,52 @@ HRESULT Dx12ResourceDataUtil::ReadFromResource(ID3D12Resource* subresource_offsets, subresource_sizes, temp_subresource_layouts_, - required_data_size); + required_data_size, + device_); GFXRECON_CHECK_CONVERSION_DATA_LOSS(size_t, required_data_size); data.clear(); - data.resize(static_cast(required_data_size)); // If the resource can be mapped, map it, copy the data, and return success. - if (try_map_and_copy && CopyMappableResource(target_resource, - before_states, - after_states, - kCopyTypeRead, - &data, - nullptr, - subresource_offsets, - subresource_sizes)) + if (try_map_and_copy && IsResourceCpuAccessible(target_resource, kCopyTypeRead)) { - return S_OK; + data.resize(static_cast(required_data_size)); + if (CopyMappableResource( + target_resource, kCopyTypeRead, &data, nullptr, subresource_offsets, subresource_sizes)) + { + return S_OK; + } } // Get or create the staging buffer for copying the resource on device. - if (staging_resource != nullptr) + bool batching; + ID3D12Resource* staging_resource; + if (staging_buffer_for_batching != nullptr) { - result = ExecuteCopyCommandList(target_resource, - kCopyTypeRead, - required_data_size, - temp_subresource_layouts_, - before_states, - after_states, - staging_resource); + batching = true; + staging_resource = staging_buffer_for_batching; } else { - auto staging_resource_temp = GetStagingBuffer(kCopyTypeRead, required_data_size); - staging_resource = staging_resource_temp.GetInterfacePtr(); - // Build and execute commands to copy data to the resource. - result = ExecuteCopyCommandList( - target_resource, kCopyTypeRead, required_data_size, temp_subresource_layouts_, before_states, after_states); + batching = false; + staging_resource = GetStagingBuffer(kCopyTypeRead, required_data_size); } + + // Build and execute commands to copy data to the resource. + result = ExecuteCopyCommandList(target_resource, + kCopyTypeRead, + required_data_size, + temp_subresource_layouts_, + before_states, + after_states, + staging_resource, + batching); + // After the command list has completed, map the copy resource and read its data. - if (SUCCEEDED(result)) + if (!batching && SUCCEEDED(result)) { + data.resize(static_cast(required_data_size)); result = MapSubresourceAndReadData(staging_resource, 0, static_cast(required_data_size), data.data()); } @@ -428,8 +460,7 @@ HRESULT Dx12ResourceDataUtil::WriteToResource(ID3D12Resource* const std::vector& data, const std::vector& subresource_offsets, const std::vector& subresource_sizes, - ID3D12Resource* staging_resource, - bool batching) + ID3D12Resource* staging_buffer_for_batching) { HRESULT result = E_FAIL; @@ -445,26 +476,31 @@ HRESULT Dx12ResourceDataUtil::WriteToResource(ID3D12Resource* layout_offsets, layout_sizes, temp_subresource_layouts_, - required_data_size); + required_data_size, + device_); // If the resource can be mapped, map it, copy the data, and return success. - if (try_map_and_copy && CopyMappableResource(target_resource, - before_states, - after_states, - kCopyTypeWrite, - nullptr, - &data, - subresource_offsets, - subresource_sizes)) + if (try_map_and_copy && IsResourceCpuAccessible(target_resource, kCopyTypeWrite)) { - return S_OK; + if (CopyMappableResource( + target_resource, kCopyTypeWrite, nullptr, &data, subresource_offsets, subresource_sizes)) + { + return S_OK; + } } // Get or create the staging buffer for copying the resource on device. - if (staging_resource == nullptr) + bool batching; + ID3D12Resource* staging_resource; + if (staging_buffer_for_batching != nullptr) + { + batching = true; + staging_resource = staging_buffer_for_batching; + } + else { - auto staging_buffer = GetStagingBuffer(kCopyTypeWrite, required_data_size); - staging_resource = staging_buffer; + batching = false; + staging_resource = GetStagingBuffer(kCopyTypeWrite, required_data_size); } // When writing and before running the command list, map the copy resource and write its data. @@ -500,83 +536,70 @@ HRESULT Dx12ResourceDataUtil::WriteToResource(ID3D12Resource* } // Build and execute commands to copy data to the resource. - if (batching == false) - { - result = ExecuteCopyCommandList(target_resource, - kCopyTypeWrite, - required_data_size, - temp_subresource_layouts_, - before_states, - after_states); + result = ExecuteCopyCommandList(target_resource, + kCopyTypeWrite, + required_data_size, + temp_subresource_layouts_, + before_states, + after_states, + staging_resource, + batching); + + return result; +} + +bool Dx12ResourceDataUtil::IsResourceCpuAccessible(ID3D12Resource* resource, CopyType copy_type) +{ + bool cpu_accessible = false; + D3D12_HEAP_PROPERTIES heap_properties; + D3D12_HEAP_FLAGS heap_flags; + HRESULT hr = resource->GetHeapProperties(&heap_properties, &heap_flags); + if (SUCCEEDED(hr)) + { + cpu_accessible = ((heap_properties.Type == D3D12_HEAP_TYPE_UPLOAD) && (copy_type == kCopyTypeWrite)) || + ((heap_properties.Type == D3D12_HEAP_TYPE_READBACK) && (copy_type == kCopyTypeRead)) || + ((heap_properties.Type == D3D12_HEAP_TYPE_CUSTOM) && + (heap_properties.CPUPageProperty != D3D12_CPU_PAGE_PROPERTY_UNKNOWN) && + (heap_properties.CPUPageProperty != D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE)); } else { - result = ExecuteCopyCommandList(target_resource, - kCopyTypeWrite, - required_data_size, - temp_subresource_layouts_, - before_states, - after_states, - staging_resource, - batching); + GFXRECON_LOG_DEBUG("Call to GetHeapProperties failed. Unable to determine if resource is CPU accessible."); } - - return result; + return cpu_accessible; } -bool Dx12ResourceDataUtil::CopyMappableResource(ID3D12Resource* target_resource, - const std::vector& before_states, - const std::vector& after_states, - CopyType copy_type, - std::vector* read_data, - const std::vector* write_data, - const std::vector& subresource_offsets, - const std::vector& subresource_sizes) +bool Dx12ResourceDataUtil::CopyMappableResource(ID3D12Resource* target_resource, + CopyType copy_type, + std::vector* read_data, + const std::vector* write_data, + const std::vector& subresource_offsets, + const std::vector& subresource_sizes) { uint64_t subresource_count = subresource_offsets.size(); - // Map the resource and copy the data if the resource has the correct heap type. - D3D12_HEAP_PROPERTIES target_heap_properties; - D3D12_HEAP_FLAGS target_heap_flags; - HRESULT result = target_resource->GetHeapProperties(&target_heap_properties, &target_heap_flags); - if (SUCCEEDED(result)) + GFXRECON_ASSERT((copy_type != kCopyTypeRead) || (read_data != nullptr)); + GFXRECON_ASSERT((copy_type != kCopyTypeWrite) || (write_data != nullptr)); + + HRESULT result = S_OK; + for (UINT i = 0; i < subresource_count && SUCCEEDED(result); ++i) { - bool is_cpu_accessible = - ((target_heap_properties.Type == D3D12_HEAP_TYPE_UPLOAD) && (copy_type == kCopyTypeWrite)) || - ((target_heap_properties.Type == D3D12_HEAP_TYPE_READBACK) && (copy_type == kCopyTypeRead)) || - ((target_heap_properties.Type == D3D12_HEAP_TYPE_CUSTOM) && - (target_heap_properties.CPUPageProperty != D3D12_CPU_PAGE_PROPERTY_UNKNOWN) && - (target_heap_properties.CPUPageProperty != D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE)); + GFXRECON_CHECK_CONVERSION_DATA_LOSS(size_t, subresource_sizes[i]); + size_t subresource_size = static_cast(subresource_sizes[i]); - if (is_cpu_accessible) + if (copy_type == kCopyTypeRead) { - for (UINT i = 0; i < subresource_count; ++i) - { - GFXRECON_CHECK_CONVERSION_DATA_LOSS(size_t, subresource_sizes[i]); - size_t subresource_size = static_cast(subresource_sizes[i]); - - if (copy_type == kCopyTypeRead) - { - GFXRECON_ASSERT(read_data != nullptr); - result = MapSubresourceAndReadData( - target_resource, i, subresource_size, read_data->data() + subresource_offsets[i]); - } - else - { - GFXRECON_ASSERT(write_data != nullptr); - result = MapSubresourceAndWriteData( - target_resource, i, subresource_size, write_data->data() + subresource_offsets[i]); - } - if (before_states[i].states != after_states[i].states) - { - GFXRECON_LOG_ERROR_ONCE("CPU buffer state not match"); - } - return SUCCEEDED(result); - } + result = MapSubresourceAndReadData( + target_resource, i, subresource_size, read_data->data() + subresource_offsets[i]); + } + else + { + result = MapSubresourceAndWriteData( + target_resource, i, subresource_size, write_data->data() + subresource_offsets[i]); } } - return false; + return SUCCEEDED(result); } HRESULT Dx12ResourceDataUtil::ExecuteAndWaitForCommandList() @@ -621,14 +644,15 @@ Dx12ResourceDataUtil::ResetCommandList() } HRESULT -Dx12ResourceDataUtil::ExecuteCopyCommandList(ID3D12Resource* target_resource, - CopyType copy_type, - uint64_t copy_size, - const std::vector& subresource_layouts, - const std::vector& before_states, - const std::vector& after_states, - ID3D12Resource* staging_buffer, - bool batching) +Dx12ResourceDataUtil::RecordCommandsToCopyResource( + ID3D12GraphicsCommandList* target_command_list, + ID3D12Resource* target_resource, + CopyType copy_type, + uint64_t copy_size, + const std::vector& subresource_layouts, + const std::vector& before_states, + const std::vector& after_states, + ID3D12Resource* staging_buffer) { // The resource state required to copy data to the target resource. const dx12::ResourceStateInfo copy_state = { D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_BARRIER_FLAG_NONE }; @@ -642,6 +666,87 @@ Dx12ResourceDataUtil::ExecuteCopyCommandList(ID3D12Resource* return E_INVALIDARG; } + // Transition the resource, copy the data, and transition it back. + auto resource_desc = target_resource->GetDesc(); + + if (resource_desc.SampleDesc.Count > 1) + { + GFXRECON_LOG_ERROR("Dx12ResourceDataUtil: Multi-sampled resources are not supported."); + return E_INVALIDARG; + } + + for (UINT i = 0; i < subresource_count; ++i) + { + if ((before_states[i].states & D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE) == + D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE) + { + GFXRECON_LOG_ERROR("Copying ray tracing acceleration structure resources is not supported. Ray tracing " + "acceleration structure resources cannot be transitioned out of resource state " + "D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE."); + return E_INVALIDARG; + } + + // Prepare resource state. + AddTransitionBarrier(target_command_list, target_resource, i, before_states[i], copy_state); + + // Copy data. + if (resource_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + // There is only 1 subresource for buffers. + GFXRECON_ASSERT(i == 0); + + if (copy_type == kCopyTypeRead) + { + // Copy from buffer. + target_command_list->CopyBufferRegion(staging_buffer, 0, target_resource, 0, copy_size); + } + else + { + // Copy to buffer. + target_command_list->CopyBufferRegion(target_resource, 0, staging_buffer, 0, copy_size); + } + } + else + { + D3D12_TEXTURE_COPY_LOCATION texture_location = {}; + texture_location.pResource = target_resource; + texture_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + texture_location.SubresourceIndex = i; + + D3D12_TEXTURE_COPY_LOCATION copy_location = {}; + copy_location.pResource = staging_buffer; + copy_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + copy_location.PlacedFootprint = subresource_layouts[i]; + + if (copy_type == kCopyTypeRead) + { + // Copy from texture. + target_command_list->CopyTextureRegion(©_location, 0, 0, 0, &texture_location, nullptr); + } + else + { + // Copy to texture. + target_command_list->CopyTextureRegion(&texture_location, 0, 0, 0, ©_location, nullptr); + } + } + + // Restore resource state. + AddTransitionBarrier(target_command_list, target_resource, i, copy_state, after_states[i]); + } + + return S_OK; +} + +HRESULT +Dx12ResourceDataUtil::ExecuteCopyCommandList(ID3D12Resource* target_resource, + CopyType copy_type, + uint64_t copy_size, + const std::vector& subresource_layouts, + const std::vector& before_states, + const std::vector& after_states, + ID3D12Resource* staging_buffer, + bool batching) +{ // Make sure the target resource is resident. ID3D12Pageable* const pageable = target_resource; if (!SUCCEEDED(device_->MakeResident(1, &pageable))) @@ -649,21 +754,13 @@ Dx12ResourceDataUtil::ExecuteCopyCommandList(ID3D12Resource* GFXRECON_LOG_ERROR("Failed to make resource resident for copying resource data."); return E_FAIL; } - if (staging_buffer == nullptr) - { - auto staging_resource = GetStagingBuffer(copy_type, copy_size); - staging_buffer = staging_resource; - } + + GFXRECON_ASSERT(staging_buffer != nullptr); + resident_resources.push_back(pageable); // Transition the resource, copy the data, and transition it back. auto resource_desc = target_resource->GetDesc(); - if (resource_desc.SampleDesc.Count > 1) - { - GFXRECON_LOG_ERROR("Dx12ResourceDataUtil: Multi-sampled resources are not supported."); - return E_INVALIDARG; - } - HRESULT result = S_OK; if (batching == false) { @@ -677,67 +774,17 @@ Dx12ResourceDataUtil::ExecuteCopyCommandList(ID3D12Resource* } if (SUCCEEDED(result)) { - for (UINT i = 0; i < subresource_count; ++i) - { - if ((before_states[i].states & D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE) == - D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE) - { - command_list_->Close(); - GFXRECON_LOG_ERROR( - "Dx12ResourceDataUtil: Ray tracing acceleration structure resources are not supported."); - return E_INVALIDARG; - } - - // Prepare resource state. - AddTransitionBarrier(command_list_, target_resource, i, before_states[i], copy_state); - - // Copy data. - if (resource_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) - { - // There is only 1 subresource for buffers. - GFXRECON_ASSERT(i == 0); - - if (copy_type == kCopyTypeRead) - { - // Copy from buffer. - command_list_->CopyBufferRegion(staging_buffer, 0, target_resource, 0, copy_size); - } - else - { - // Copy to buffer. - command_list_->CopyBufferRegion(target_resource, 0, staging_buffer, 0, copy_size); - } - } - else - { - D3D12_TEXTURE_COPY_LOCATION texture_location = {}; - texture_location.pResource = target_resource; - texture_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - texture_location.SubresourceIndex = i; - - D3D12_TEXTURE_COPY_LOCATION copy_location = {}; - copy_location.pResource = staging_buffer; - copy_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - copy_location.PlacedFootprint = subresource_layouts[i]; - - if (copy_type == kCopyTypeRead) - { - // Copy from texture. - command_list_->CopyTextureRegion(©_location, 0, 0, 0, &texture_location, nullptr); - } - else - { - // Copy to texture. - command_list_->CopyTextureRegion(&texture_location, 0, 0, 0, ©_location, nullptr); - } - } - - // Restore resource state. - AddTransitionBarrier(command_list_, target_resource, i, copy_state, after_states[i]); - } + result = RecordCommandsToCopyResource(command_list_, + target_resource, + copy_type, + copy_size, + subresource_layouts, + before_states, + after_states, + staging_buffer); // Close and execute the command list. - if (batching == false) + if (SUCCEEDED(result) && (batching == false)) { result = command_list_->Close(); if (SUCCEEDED(result)) diff --git a/framework/graphics/dx12_resource_data_util.h b/framework/graphics/dx12_resource_data_util.h index e2aa4b8034..feb06d741e 100644 --- a/framework/graphics/dx12_resource_data_util.h +++ b/framework/graphics/dx12_resource_data_util.h @@ -35,6 +35,43 @@ GFXRECON_BEGIN_NAMESPACE(graphics) class Dx12ResourceDataUtil { + public: + enum CopyType : int + { + kCopyTypeRead = 0, + kCopyTypeWrite = 1 + }; + + static void GetResourceCopyInfo(ID3D12Resource* resource, + size_t& subresource_count, + std::vector& subresource_offsets, + std::vector& subresource_sizes, + std::vector& layouts, + uint64_t& total_size, + ID3D12Device* device = nullptr); + + static HRESULT + RecordCommandsToCopyResource(ID3D12GraphicsCommandList* target_command_list, + ID3D12Resource* target_resource, + CopyType copy_type, + uint64_t copy_size, + const std::vector& subresource_layouts, + const std::vector& before_states, + const std::vector& after_states, + ID3D12Resource* staging_buffer); + + static bool IsResourceCpuAccessible(ID3D12Resource* resource, CopyType copy_type); + + static HRESULT MapSubresourceAndReadData(ID3D12Resource* resource, UINT subresource, size_t size, uint8_t* data); + + static HRESULT + MapSubresourceAndWriteData(ID3D12Resource* resource, UINT subresource, size_t size, const uint8_t* data); + + static dx12::ID3D12ResourceComPtr + CreateStagingBuffer(ID3D12Device* device, CopyType type, uint64_t required_buffer_size); + + static size_t GetSubresourceCount(ID3D12Resource* resource); + public: Dx12ResourceDataUtil(ID3D12Device* device, uint64_t min_buffer_size); @@ -47,7 +84,7 @@ class Dx12ResourceDataUtil std::vector& data, std::vector& subresource_offsets, std::vector& subresource_sizes, - ID3D12Resource* staging_resource = nullptr); + ID3D12Resource* staging_buffer_for_batching = nullptr); HRESULT WriteToResource(ID3D12Resource* target_resource, bool try_map_and_copy, @@ -56,36 +93,12 @@ class Dx12ResourceDataUtil const std::vector& data, const std::vector& subresource_offsets, const std::vector& subresource_sizes, - ID3D12Resource* staging_resource = nullptr, - bool batching = false); - - enum CopyType : int - { - kCopyTypeRead = 0, - kCopyTypeWrite = 1 - }; + ID3D12Resource* staging_buffer_for_batching = nullptr); // Create a mappable buffer used to copy data to or from another resource via a command list. dx12::ID3D12ResourceComPtr GetStagingBuffer(CopyType type, uint64_t required_buffer_size); dx12::ID3D12ResourceComPtr CreateStagingBuffer(CopyType type, uint64_t required_buffer_size); - void GetResourceCopyInfo(ID3D12Resource* resource, - size_t& subresource_count, - std::vector& subresource_offsets, - std::vector& subresource_sizes, - std::vector& layouts, - uint64_t& total_size); - - // Copy data to or from a mappable resource. Also transitions the resource to after_states. - bool CopyMappableResource(ID3D12Resource* target_resource, - const std::vector& before_states, - const std::vector& after_states, - CopyType copy_type, - std::vector* read_data, - const std::vector* write_data, - const std::vector& subresource_offsets, - const std::vector& subresource_sizes); - HRESULT ExecuteAndWaitForCommandList(); // Build and execute a command list that copies data to or from the target_resource. @@ -110,11 +123,15 @@ class Dx12ResourceDataUtil const std::vector& before_states, const std::vector& after_states); - HRESULT MapSubresourceAndReadData(ID3D12Resource* resource, UINT subresource, size_t size, uint8_t* data); - - HRESULT MapSubresourceAndWriteData(ID3D12Resource* resource, UINT subresource, size_t size, const uint8_t* data); - private: + // Copy data to or from a mappable resource. + static bool CopyMappableResource(ID3D12Resource* target_resource, + CopyType copy_type, + std::vector* read_data, + const std::vector* write_data, + const std::vector& subresource_offsets, + const std::vector& subresource_sizes); + ID3D12Device* device_; dx12::ID3D12CommandQueueComPtr command_queue_; dx12::ID3D12CommandAllocatorComPtr command_allocator_; @@ -127,8 +144,6 @@ class Dx12ResourceDataUtil // Temporary buffers. std::vector temp_subresource_layouts_; - std::vector temp_subresource_row_counts_; - std::vector temp_subresource_row_size_bytes_; // Vector to Resident resources std::vector resident_resources;