From 005e590c92c08d17baf2fd6b1fe15e36cef23284 Mon Sep 17 00:00:00 2001 From: Triang3l Date: Sun, 23 Sep 2018 18:37:41 +0300 Subject: [PATCH] [D3D12] SHM upload range cleanup and mask index buffer address --- .../gpu/d3d12/d3d12_command_processor.cc | 3 +- src/xenia/gpu/d3d12/shared_memory.cc | 43 ++++++++----------- src/xenia/gpu/d3d12/shared_memory.h | 2 +- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index 1ca8f996a..9f6a1aee5 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -1037,7 +1037,8 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type, ? sizeof(uint32_t) : sizeof(uint16_t); assert_false(index_buffer_info->guest_base & (index_size - 1)); - uint32_t index_base = index_buffer_info->guest_base & ~(index_size - 1); + uint32_t index_base = + index_buffer_info->guest_base & 0x1FFFFFFF & ~(index_size - 1); D3D12_INDEX_BUFFER_VIEW index_buffer_view; index_buffer_view.Format = index_buffer_info->format == IndexFormat::kInt32 ? DXGI_FORMAT_R32_UINT diff --git a/src/xenia/gpu/d3d12/shared_memory.cc b/src/xenia/gpu/d3d12/shared_memory.cc index 472241b89..10e719e80 100644 --- a/src/xenia/gpu/d3d12/shared_memory.cc +++ b/src/xenia/gpu/d3d12/shared_memory.cc @@ -274,10 +274,7 @@ bool SharedMemory::RequestRange(uint32_t start, uint32_t length) { } // Upload and protect used ranges. - GetRangesToUpload(start >> page_size_log2_, - ((start & ((1 << page_size_log2_) - 1)) + length + - ((1 << page_size_log2_) - 1)) >> - page_size_log2_); + GetRangesToUpload(start >> page_size_log2_, last >> page_size_log2_); if (upload_ranges_.size() == 0) { return true; } @@ -402,14 +399,12 @@ void SharedMemory::UnlinkWatchRange(WatchRange* range) { } void SharedMemory::GetRangesToUpload(uint32_t request_page_first, - uint32_t request_page_count) { + uint32_t request_page_last) { upload_ranges_.clear(); - if (request_page_first >= page_count_ || request_page_count == 0) { + request_page_last = std::min(request_page_last, page_count_ - 1u); + if (request_page_first > request_page_last) { return; } - request_page_count = - std::min(request_page_count, page_count_ - request_page_first); - uint32_t request_page_last = request_page_first + request_page_count - 1; uint32_t request_block_first = request_page_first >> 6; uint32_t request_block_last = request_page_last >> 6; @@ -418,43 +413,39 @@ void SharedMemory::GetRangesToUpload(uint32_t request_page_first, uint32_t range_start = UINT32_MAX; for (uint32_t i = request_block_first; i <= request_block_last; ++i) { uint64_t block_valid = valid_pages_[i]; - uint64_t block_invalid = ~block_valid; - - // Ignore pages outside the requested range in bits scans completely. - uint64_t bits_to_keep; + // Consider pages in the block outside the requested range valid. if (i == request_block_first) { - bits_to_keep = ~((1ull << (request_page_first & 63)) - 1); - block_valid &= bits_to_keep; - block_invalid &= bits_to_keep; + block_valid |= (1ull << (request_page_first & 63)) - 1; } if (i == request_block_last && (request_page_last & 63) != 63) { - bits_to_keep = (1ull << ((request_page_last & 63) + 1)) - 1; - block_valid &= bits_to_keep; - block_invalid &= bits_to_keep; + block_valid |= ~((1ull << ((request_page_last & 63) + 1)) - 1); } while (true) { uint32_t block_page; if (range_start == UINT32_MAX) { // Check if need to open a new range. - if (!xe::bit_scan_forward(block_invalid, &block_page)) { + if (!xe::bit_scan_forward(~block_valid, &block_page)) { break; } range_start = (i << 6) + block_page; } else { // Check if need to close the range. - if (!xe::bit_scan_forward(block_valid, &block_page)) { + // Ignore the valid pages before the beginning of the range. + uint64_t block_valid_from_start = block_valid; + if (i == (range_start >> 6)) { + block_valid_from_start &= ~((1ull << (range_start & 63)) - 1); + } + if (!xe::bit_scan_forward(block_valid_from_start, &block_page)) { break; } upload_ranges_.push_back( std::make_pair(range_start, (i << 6) + block_page - range_start)); + // In the next interation within this block, consider this range valid + // since it has been queued for upload. + block_valid |= (1ull << block_page) - 1; range_start = UINT32_MAX; } - // There may be multiple ranges within a single block, so ignore the bits - // that have already been processed. - bits_to_keep = ~((1ull << block_page) - 1); - block_valid &= bits_to_keep; - block_invalid &= bits_to_keep; } } if (range_start != UINT32_MAX) { diff --git a/src/xenia/gpu/d3d12/shared_memory.h b/src/xenia/gpu/d3d12/shared_memory.h index 828c74b30..0d126be9e 100644 --- a/src/xenia/gpu/d3d12/shared_memory.h +++ b/src/xenia/gpu/d3d12/shared_memory.h @@ -200,7 +200,7 @@ class SharedMemory { // persistently allocated vector). std::vector upload_ranges_; void GetRangesToUpload(uint32_t request_page_first, - uint32_t request_page_count); + uint32_t request_page_last); std::unique_ptr upload_buffer_pool_ = nullptr; void TransitionBuffer(D3D12_RESOURCE_STATES new_state);