[Memory, D3D12] Various refactoring from data provider development
This commit is contained in:
@@ -11,7 +11,6 @@
|
||||
#define XENIA_GPU_D3D12_SHARED_MEMORY_H_
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -44,7 +43,7 @@ class SharedMemory {
|
||||
return buffer_gpu_address_;
|
||||
}
|
||||
|
||||
void BeginSubmission();
|
||||
void CompletedSubmissionUpdated();
|
||||
|
||||
typedef void (*GlobalWatchCallback)(void* context, uint32_t address_first,
|
||||
uint32_t address_last,
|
||||
@@ -57,7 +56,7 @@ class SharedMemory {
|
||||
// example, if the game changes protection level of a memory range containing
|
||||
// the watched range.
|
||||
//
|
||||
// The callback is called with the mutex locked.
|
||||
// The callback is called within the global critical region.
|
||||
GlobalWatchHandle RegisterGlobalWatch(GlobalWatchCallback callback,
|
||||
void* callback_context);
|
||||
void UnregisterGlobalWatch(GlobalWatchHandle handle);
|
||||
@@ -84,15 +83,10 @@ class SharedMemory {
|
||||
void* callback_data, uint64_t callback_argument);
|
||||
// Unregisters previously registered watched memory range.
|
||||
void UnwatchMemoryRange(WatchHandle handle);
|
||||
// Locks the mutex that gets locked when watch callbacks are invoked - must be
|
||||
// done when checking variables that may be changed by a watch callback.
|
||||
inline std::unique_lock<std::recursive_mutex> LockWatchMutex() {
|
||||
return global_critical_region_.Acquire();
|
||||
}
|
||||
|
||||
// Ensures the buffer tiles backing the range are resident, but doesn't upload
|
||||
// anything.
|
||||
bool MakeTilesResident(uint32_t start, uint32_t length);
|
||||
bool EnsureTilesResident(uint32_t start, uint32_t length);
|
||||
|
||||
// Checks if the range has been updated, uploads new data if needed and
|
||||
// ensures the buffer tiles backing the range are resident. May transition the
|
||||
@@ -105,7 +99,7 @@ class SharedMemory {
|
||||
// (to up to the first GPU-written page, as an access violation exception
|
||||
// count optimization) as modified by the CPU, also invalidating GPU-written
|
||||
// pages directly in the range.
|
||||
std::pair<uint32_t, uint32_t> MemoryWriteCallback(
|
||||
std::pair<uint32_t, uint32_t> MemoryInvalidationCallback(
|
||||
uint32_t physical_address_start, uint32_t length, bool exact_range);
|
||||
|
||||
// Marks the range as containing GPU-generated data (such as resolves),
|
||||
@@ -141,8 +135,7 @@ class SharedMemory {
|
||||
bool AreTiledResourcesUsed() const;
|
||||
|
||||
// Mark the memory range as updated and protect it.
|
||||
void MakeRangeValid(uint32_t valid_page_first, uint32_t valid_page_count,
|
||||
bool written_by_gpu);
|
||||
void MakeRangeValid(uint32_t start, uint32_t length, bool written_by_gpu);
|
||||
|
||||
D3D12CommandProcessor* command_processor_;
|
||||
Memory* memory_;
|
||||
@@ -154,6 +147,7 @@ class SharedMemory {
|
||||
ID3D12Resource* buffer_ = nullptr;
|
||||
D3D12_GPU_VIRTUAL_ADDRESS buffer_gpu_address_ = 0;
|
||||
D3D12_RESOURCE_STATES buffer_state_ = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
void TransitionBuffer(D3D12_RESOURCE_STATES new_state);
|
||||
|
||||
// Heaps are 4 MB, so not too many of them are allocated, but also not to
|
||||
// waste too much memory for padding (with 16 MB there's too much).
|
||||
@@ -166,9 +160,11 @@ class SharedMemory {
|
||||
// Number of the heaps currently resident, for profiling.
|
||||
uint32_t heap_count_ = 0;
|
||||
|
||||
// Log2 of system page size.
|
||||
// Log2 of invalidation granularity (the system page size, but the dependency
|
||||
// on it is not hard - the access callback takes a range as an argument, and
|
||||
// touched pages of the buffer of this size will be invalidated).
|
||||
uint32_t page_size_log2_;
|
||||
// Total physical page count.
|
||||
// Total buffer page count.
|
||||
uint32_t page_count_;
|
||||
|
||||
// Non-shader-visible buffer descriptor heap for faster binding (via copying
|
||||
@@ -182,24 +178,46 @@ class SharedMemory {
|
||||
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;
|
||||
// First page and length in pages.
|
||||
typedef std::pair<uint32_t, uint32_t> UploadRange;
|
||||
// Ranges that need to be uploaded, generated by GetRangesToUpload (a
|
||||
// persistently allocated vector).
|
||||
std::vector<UploadRange> upload_ranges_;
|
||||
void GetRangesToUpload(uint32_t request_page_first,
|
||||
uint32_t request_page_last);
|
||||
std::unique_ptr<ui::d3d12::UploadBufferPool> upload_buffer_pool_ = nullptr;
|
||||
|
||||
// Mutex between the exception handler and the command processor, to be locked
|
||||
// when checking or updating validity of pages/ranges.
|
||||
// GPU-written memory downloading for traces.
|
||||
// Start page, length in pages.
|
||||
std::vector<std::pair<uint32_t, uint32_t>> trace_gpu_written_ranges_;
|
||||
// Created temporarily, only for downloading.
|
||||
ID3D12Resource* trace_gpu_written_buffer_ = nullptr;
|
||||
void ResetTraceGPUWrittenBuffer();
|
||||
|
||||
void* memory_invalidation_callback_handle_ = nullptr;
|
||||
void* memory_data_provider_handle_ = nullptr;
|
||||
|
||||
// Mutex between the guest memory subsystem and the command processor, to be
|
||||
// locked when checking or updating validity of pages/ranges and when firing
|
||||
// watches.
|
||||
xe::global_critical_region global_critical_region_;
|
||||
|
||||
// ***************************************************************************
|
||||
// Things below should be protected by global_critical_region.
|
||||
// Things below should be fully protected by global_critical_region.
|
||||
// ***************************************************************************
|
||||
|
||||
// Bit vector containing:
|
||||
// - Even block indices - whether physical memory system pages are up to date.
|
||||
// - Odd block indices - whether phyical memory system pages contain data
|
||||
// written by the GPU not synchronized with the CPU (subset of valid pages).
|
||||
std::vector<uint64_t> valid_and_gpu_written_pages_;
|
||||
struct SystemPageFlagsBlock {
|
||||
// Whether each page is up to date in the GPU buffer.
|
||||
uint64_t valid;
|
||||
// Subset of valid pages - whether each page in the GPU buffer contains data
|
||||
// that was written on the GPU, thus should not be invalidated spuriously.
|
||||
uint64_t valid_and_gpu_written;
|
||||
};
|
||||
// Flags for each 64 system pages, interleaved as blocks, so bit scan can be
|
||||
// used to quickly extract ranges.
|
||||
std::vector<SystemPageFlagsBlock> system_page_flags_;
|
||||
|
||||
static std::pair<uint32_t, uint32_t> MemoryWriteCallbackThunk(
|
||||
static std::pair<uint32_t, uint32_t> MemoryInvalidationCallbackThunk(
|
||||
void* context_ptr, uint32_t physical_address_start, uint32_t length,
|
||||
bool exact_range);
|
||||
|
||||
@@ -259,30 +277,9 @@ class SharedMemory {
|
||||
// watches.
|
||||
void FireWatches(uint32_t page_first, uint32_t page_last,
|
||||
bool invalidated_by_gpu);
|
||||
// Unlinks and frees the range and its nodes. Call this with the mutex locked.
|
||||
// Unlinks and frees the range and its nodes. Call this in the global critical
|
||||
// region.
|
||||
void UnlinkWatchRange(WatchRange* range);
|
||||
|
||||
// ***************************************************************************
|
||||
// Things above should be protected by global_critical_region.
|
||||
// ***************************************************************************
|
||||
|
||||
// First page and length in pages.
|
||||
typedef std::pair<uint32_t, uint32_t> UploadRange;
|
||||
// Ranges that need to be uploaded, generated by GetRangesToUpload (a
|
||||
// persistently allocated vector).
|
||||
std::vector<UploadRange> upload_ranges_;
|
||||
void GetRangesToUpload(uint32_t request_page_first,
|
||||
uint32_t request_page_last);
|
||||
std::unique_ptr<ui::d3d12::UploadBufferPool> upload_buffer_pool_ = nullptr;
|
||||
|
||||
void TransitionBuffer(D3D12_RESOURCE_STATES new_state);
|
||||
|
||||
// GPU-written memory downloading for traces.
|
||||
// Start page, length in pages.
|
||||
std::vector<std::pair<uint32_t, uint32_t>> trace_gpu_written_ranges_;
|
||||
// Created temporarily, only for downloading.
|
||||
ID3D12Resource* trace_gpu_written_buffer_ = nullptr;
|
||||
void ResetTraceGPUWrittenBuffer();
|
||||
};
|
||||
|
||||
} // namespace d3d12
|
||||
|
||||
Reference in New Issue
Block a user