Files
Xenia-Canary/src/xenia/gpu/d3d12/d3d12_shared_memory.h
chss95cs@gmail.com 8f7f7dc6ad fixed wine crash from use of NtSetEventPriorityBoost
add xe::clear_lowest_bit, use it in place of shift-andnot in some bit iteration code
make is_allocated_ and is_enabled_ volatile in xma_context
preallocate avpacket buffer in XMAContext::Setup, the reallocations of the buffer in ffmpeg were showing up on profiles
check is_enabled and is_allocated BEFORE locking an xmacontext. XMA worker was spending most of its time locking and unlocking contexts
Removed XeDMAC, dma:: namespace. It was a bad idea and I couldn't make it work in the end. Kept vastcpy and moved it to the memory namespace instead
Made the rest of global_critical_region's members static. They never needed an instance.
Removed ifdef'ed out code from ring_buffer.h
Added EventInfo struct to threading, added Event::Query to aid with implementing NtQueryEvent.
Removed vector from WaitMultiple, instead use a fixed array of 64 handles that we populate. WaitForMultipleObjects cannot handle more than 64 objects.
Remove XE_MSVC_OPTIMIZE_SMALL() use in x64_sequences, x64 backend is now always size optimized because of premake
Make global_critical_region_ static constexpr in shared_memory.h to get rid of wasteage of 8 bytes (empty class=1byte, +alignment for next member=8)
Move trace-related data to the tail of SharedMemory to keep more important data together
In IssueDraw build an array of fetch constant addresses/sizes, then pre-lock the global lock before doing requestrange for each instead of individually locking within requestrange for each of them
Consistent access specifier protected for pm4_command_processor_declare
Devirtualize WriteOneRegisterFromRing.
Move ExecutePacket and ExecutePrimaryBuffer to pm4_command_buffer_x
Remove many redundant header inclusions access xenia-gpu
Minor microoptimization of ExecutePacketType0

Add TextureCache::RequestTextures for batch invocation of LoadTexturesData

Add TextureCache::LoadTexturesData for reducing the number of times we release and reacquire the global lock.
Ideally you should hold the global lock for as little time as possible, but if you are constantly acquiring and releasing it you are actually more likely to have contention
Add already_locked param to ObjectTable::LookupObject to help with reducing lock acquire/release pairs
Add missing checks to XAudioRegisterRenderDriverClient_entry. this is unlikely to fix anything, it was just an easy thing to do
Add NtQueryEvent system call implementation. I don't actually know of any games that need it.
Instead of using std::vector + push_back in KeWaitForMultipleObjects and xeNtWaitForMultipleObjectsEx use a fixed size array of 64 and track the count. More than 64 objects is not permitted by the kernel. The repeated reallocations from push_back were appearing unusually high on the profiler, but were masked until now by waitformultipleobjects natural overhead
Pre-lock the global lock before looking up each handle for xeNtWaitForMultipleObjectsEx and KeWaitForMultipleObjects.
Pre-lock before looking up the signal and waiter in NtSignalAndWaitForSingleObjectEx
add missing checks to NtWaitForMultipleObjectsEx
Support pre-locking in XObject::GetNativeObject
2022-10-08 09:55:17 -07:00

138 lines
4.8 KiB
C++

/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_GPU_D3D12_D3D12_SHARED_MEMORY_H_
#define XENIA_GPU_D3D12_D3D12_SHARED_MEMORY_H_
#include <algorithm>
#include <memory>
#include <utility>
#include <vector>
#include "xenia/gpu/shared_memory.h"
#include "xenia/gpu/trace_writer.h"
#include "xenia/memory.h"
#include "xenia/ui/d3d12/d3d12_api.h"
#include "xenia/ui/d3d12/d3d12_upload_buffer_pool.h"
namespace xe {
namespace gpu {
namespace d3d12 {
class D3D12CommandProcessor;
class D3D12SharedMemory : public SharedMemory {
public:
D3D12SharedMemory(D3D12CommandProcessor& command_processor, Memory& memory,
TraceWriter& trace_writer);
~D3D12SharedMemory() override;
bool Initialize();
void Shutdown(bool from_destructor = false);
void ClearCache() override;
ID3D12Resource* GetBuffer() const { return buffer_; }
D3D12_GPU_VIRTUAL_ADDRESS GetGPUAddress() const {
return buffer_gpu_address_;
}
void CompletedSubmissionUpdated();
void BeginSubmission();
// RequestRange may transition the buffer to copy destination - call it before
// UseForReading or UseForWriting.
// Makes the buffer usable for vertices, indices and texture untiling.
void UseForReading() {
// Vertex fetch is also allowed in pixel shaders.
CommitUAVWritesAndTransitionBuffer(
D3D12_RESOURCE_STATE_INDEX_BUFFER |
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE |
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
}
// Makes the buffer usable for texture tiling after a resolve.
void UseForWriting() {
CommitUAVWritesAndTransitionBuffer(D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
}
// Makes the buffer usable as a source for copy commands.
void UseAsCopySource() {
CommitUAVWritesAndTransitionBuffer(D3D12_RESOURCE_STATE_COPY_SOURCE);
}
// Must be called when doing draws/dispatches modifying data within the shared
// memory buffer as a UAV, to make sure that when UseForWriting is called the
// next time, a UAV barrier will be done, and subsequent overlapping UAV
// writes and reads are ordered.
void MarkUAVWritesCommitNeeded() {
if (buffer_state_ == D3D12_RESOURCE_STATE_UNORDERED_ACCESS) {
buffer_uav_writes_commit_needed_ = true;
}
}
void WriteRawSRVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle);
void WriteRawUAVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle);
// Due to the D3D12_REQ_BUFFER_RESOURCE_TEXEL_COUNT_2_TO_EXP limitation, the
// smallest supported formats are 32-bit.
void WriteUintPow2SRVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle,
uint32_t element_size_bytes_pow2);
void WriteUintPow2UAVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle,
uint32_t element_size_bytes_pow2);
// Returns true if any downloads were submitted to the command processor.
bool InitializeTraceSubmitDownloads();
void InitializeTraceCompleteDownloads();
protected:
bool AllocateSparseHostGpuMemoryRange(uint32_t offset_allocations,
uint32_t length_allocations) override;
bool UploadRanges(const std::pair<uint32_t, uint32_t>* upload_page_ranges,
uint32_t num_ranges) override;
private:
D3D12CommandProcessor& command_processor_;
TraceWriter& trace_writer_;
// The 512 MB tiled buffer.
ID3D12Resource* buffer_ = nullptr;
D3D12_GPU_VIRTUAL_ADDRESS buffer_gpu_address_ = 0;
std::vector<ID3D12Heap*> buffer_tiled_heaps_;
D3D12_RESOURCE_STATES buffer_state_ = D3D12_RESOURCE_STATE_COPY_DEST;
bool buffer_uav_writes_commit_needed_ = false;
void CommitUAVWritesAndTransitionBuffer(D3D12_RESOURCE_STATES new_state);
// Non-shader-visible buffer descriptor heap for faster binding (via copying
// rather than creation).
enum class BufferDescriptorIndex : uint32_t {
kRawSRV,
kR32UintSRV,
kR32G32UintSRV,
kR32G32B32A32UintSRV,
kRawUAV,
kR32UintUAV,
kR32G32UintUAV,
kR32G32B32A32UintUAV,
kCount,
};
ID3D12DescriptorHeap* buffer_descriptor_heap_ = nullptr;
D3D12_CPU_DESCRIPTOR_HANDLE buffer_descriptor_heap_start_;
std::unique_ptr<ui::d3d12::D3D12UploadBufferPool> upload_buffer_pool_;
// Created temporarily, only for downloading.
ID3D12Resource* trace_download_buffer_ = nullptr;
void ResetTraceDownload();
};
} // namespace d3d12
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_D3D12_D3D12_SHARED_MEMORY_H_