|
|
|
@ -22,7 +22,11 @@ namespace VideoCommon { |
|
|
|
|
|
|
|
class FenceBase { |
|
|
|
public: |
|
|
|
FenceBase(GPUVAddr address, u32 payload) : address{address}, payload{payload} {} |
|
|
|
FenceBase(u32 payload, bool is_stubbed) |
|
|
|
: address{}, payload{payload}, is_semaphore{false}, is_stubbed{is_stubbed} {} |
|
|
|
|
|
|
|
FenceBase(GPUVAddr address, u32 payload, bool is_stubbed) |
|
|
|
: address{address}, payload{payload}, is_semaphore{true}, is_stubbed{is_stubbed} {} |
|
|
|
|
|
|
|
constexpr GPUVAddr GetAddress() const { |
|
|
|
return address; |
|
|
|
@ -32,22 +36,49 @@ public: |
|
|
|
return payload; |
|
|
|
} |
|
|
|
|
|
|
|
constexpr bool IsSemaphore() const { |
|
|
|
return is_semaphore; |
|
|
|
} |
|
|
|
|
|
|
|
private: |
|
|
|
GPUVAddr address; |
|
|
|
u32 payload; |
|
|
|
bool is_semaphore; |
|
|
|
|
|
|
|
protected: |
|
|
|
bool is_stubbed; |
|
|
|
}; |
|
|
|
|
|
|
|
template <typename TFence, typename TTextureCache, typename TTBufferCache> |
|
|
|
class FenceManager { |
|
|
|
public: |
|
|
|
void SignalFence(GPUVAddr addr, u32 value) { |
|
|
|
void SignalSemaphore(GPUVAddr addr, u32 value) { |
|
|
|
TryReleasePendingFences(); |
|
|
|
bool should_flush = texture_cache.HasUncommitedFlushes(); |
|
|
|
should_flush |= buffer_cache.HasUncommitedFlushes(); |
|
|
|
texture_cache.CommitAsyncFlushes(); |
|
|
|
buffer_cache.CommitAsyncFlushes(); |
|
|
|
TFence new_fence = CreateFence(addr, value, !should_flush); |
|
|
|
fences.push(new_fence); |
|
|
|
QueueFence(new_fence); |
|
|
|
if (should_flush) { |
|
|
|
rasterizer.FlushCommands(); |
|
|
|
} |
|
|
|
rasterizer.SyncGuestHost(); |
|
|
|
} |
|
|
|
|
|
|
|
void SignalSyncPoint(u32 value) { |
|
|
|
TryReleasePendingFences(); |
|
|
|
bool should_flush = texture_cache.HasUncommitedFlushes(); |
|
|
|
should_flush |= buffer_cache.HasUncommitedFlushes(); |
|
|
|
texture_cache.CommitAsyncFlushes(); |
|
|
|
buffer_cache.CommitAsyncFlushes(); |
|
|
|
TFence new_fence = CreateFence(addr, value); |
|
|
|
TFence new_fence = CreateFence(value, !should_flush); |
|
|
|
fences.push(new_fence); |
|
|
|
QueueFence(new_fence); |
|
|
|
if (should_flush) { |
|
|
|
rasterizer.FlushCommands(); |
|
|
|
} |
|
|
|
rasterizer.SyncGuestHost(); |
|
|
|
} |
|
|
|
|
|
|
|
@ -62,8 +93,12 @@ public: |
|
|
|
texture_cache.PopAsyncFlushes(); |
|
|
|
buffer_cache.PopAsyncFlushes(); |
|
|
|
auto& gpu{system.GPU()}; |
|
|
|
if (current_fence->IsSemaphore()) { |
|
|
|
auto& memory_manager{gpu.MemoryManager()}; |
|
|
|
memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload()); |
|
|
|
} else { |
|
|
|
gpu.IncrementSyncPoint(current_fence->GetPayload()); |
|
|
|
} |
|
|
|
fences.pop(); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -74,7 +109,8 @@ protected: |
|
|
|
: system{system}, rasterizer{rasterizer}, texture_cache{texture_cache}, buffer_cache{ |
|
|
|
buffer_cache} {} |
|
|
|
|
|
|
|
virtual TFence CreateFence(GPUVAddr addr, u32 value) = 0; |
|
|
|
virtual TFence CreateFence(u32 value, bool is_stubbed) = 0; |
|
|
|
virtual TFence CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) = 0; |
|
|
|
virtual void QueueFence(TFence& fence) = 0; |
|
|
|
virtual bool IsFenceSignaled(TFence& fence) = 0; |
|
|
|
virtual void WaitFence(TFence& fence) = 0; |
|
|
|
@ -96,8 +132,12 @@ private: |
|
|
|
texture_cache.PopAsyncFlushes(); |
|
|
|
buffer_cache.PopAsyncFlushes(); |
|
|
|
auto& gpu{system.GPU()}; |
|
|
|
if (current_fence->IsSemaphore()) { |
|
|
|
auto& memory_manager{gpu.MemoryManager()}; |
|
|
|
memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload()); |
|
|
|
} else { |
|
|
|
gpu.IncrementSyncPoint(current_fence->GetPayload()); |
|
|
|
} |
|
|
|
fences.pop(); |
|
|
|
} |
|
|
|
} |
|
|
|
|