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