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..7d14a7edb1 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) { - auto staging_buffer = GetStagingBuffer(kCopyTypeWrite, required_data_size); - staging_resource = staging_buffer; + batching = true; + staging_resource = staging_buffer_for_batching; + } + else + { + 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,19 +644,19 @@ 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 }; - - uint64_t subresource_count = subresource_layouts.size(); + const dx12::ResourceStateInfo copy_state = { D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_BARRIER_FLAG_NONE }; + uint64_t subresource_count = subresource_layouts.size(); // The number of incoming subresource states should match the number of subresource layouts. if ((subresource_count != before_states.size()) || (subresource_count != after_states.size())) @@ -642,6 +665,93 @@ 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; + } + + HRESULT result = S_OK; + 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]); + } + + if (FAILED(result)) + { + GFXRECON_LOG_ERROR("Error recording commands to copy resource data. (error = %lx)", result); + } + + return result; +} + +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 +759,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,64 +779,14 @@ 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) 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;