Address Feedback.
This commit is contained in:
parent
ec2f3e48e1
commit
f616dc0b59
@ -154,12 +154,9 @@ public:
|
||||
std::lock_guard lock{mutex};
|
||||
|
||||
std::vector<MapInterval> objects = GetMapsInRange(addr, size);
|
||||
for (auto& object : objects) {
|
||||
if (object->IsModified() && object->IsRegistered()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return std::any_of(objects.begin(), objects.end(), [](const MapInterval& map) {
|
||||
return map->IsModified() && map->IsRegistered();
|
||||
});
|
||||
}
|
||||
|
||||
/// Mark the specified region as being invalidated
|
||||
@ -199,9 +196,9 @@ public:
|
||||
}
|
||||
|
||||
void CommitAsyncFlushes() {
|
||||
if (uncommited_flushes) {
|
||||
if (uncommitted_flushes) {
|
||||
auto commit_list = std::make_shared<std::list<MapInterval>>();
|
||||
for (auto& map : *uncommited_flushes) {
|
||||
for (auto& map : *uncommitted_flushes) {
|
||||
if (map->IsRegistered() && map->IsModified()) {
|
||||
// TODO(Blinkhawk): Implement backend asynchronous flushing
|
||||
// AsyncFlushMap(map)
|
||||
@ -209,41 +206,34 @@ public:
|
||||
}
|
||||
}
|
||||
if (!commit_list->empty()) {
|
||||
commited_flushes.push_back(commit_list);
|
||||
committed_flushes.push_back(commit_list);
|
||||
} else {
|
||||
commited_flushes.emplace_back();
|
||||
committed_flushes.emplace_back();
|
||||
}
|
||||
} else {
|
||||
commited_flushes.emplace_back();
|
||||
committed_flushes.emplace_back();
|
||||
}
|
||||
uncommited_flushes.reset();
|
||||
uncommitted_flushes.reset();
|
||||
}
|
||||
|
||||
bool ShouldWaitAsyncFlushes() {
|
||||
if (commited_flushes.empty()) {
|
||||
bool ShouldWaitAsyncFlushes() const {
|
||||
if (committed_flushes.empty()) {
|
||||
return false;
|
||||
}
|
||||
auto& flush_list = commited_flushes.front();
|
||||
if (!flush_list) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return committed_flushes.front() != nullptr;
|
||||
}
|
||||
|
||||
bool HasUncommitedFlushes() {
|
||||
if (uncommited_flushes) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool HasUncommittedFlushes() const {
|
||||
return uncommitted_flushes != nullptr;
|
||||
}
|
||||
|
||||
void PopAsyncFlushes() {
|
||||
if (commited_flushes.empty()) {
|
||||
if (committed_flushes.empty()) {
|
||||
return;
|
||||
}
|
||||
auto& flush_list = commited_flushes.front();
|
||||
auto& flush_list = committed_flushes.front();
|
||||
if (!flush_list) {
|
||||
commited_flushes.pop_front();
|
||||
committed_flushes.pop_front();
|
||||
return;
|
||||
}
|
||||
for (MapInterval& map : *flush_list) {
|
||||
@ -252,7 +242,7 @@ public:
|
||||
FlushMap(map);
|
||||
}
|
||||
}
|
||||
commited_flushes.pop_front();
|
||||
committed_flushes.pop_front();
|
||||
}
|
||||
|
||||
virtual BufferType GetEmptyBuffer(std::size_t size) = 0;
|
||||
@ -568,10 +558,10 @@ private:
|
||||
}
|
||||
|
||||
void MarkForAsyncFlush(MapInterval& map) {
|
||||
if (!uncommited_flushes) {
|
||||
uncommited_flushes = std::make_shared<std::unordered_set<MapInterval>>();
|
||||
if (!uncommitted_flushes) {
|
||||
uncommitted_flushes = std::make_shared<std::unordered_set<MapInterval>>();
|
||||
}
|
||||
uncommited_flushes->insert(map);
|
||||
uncommitted_flushes->insert(map);
|
||||
}
|
||||
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
@ -605,8 +595,8 @@ private:
|
||||
std::vector<u8> staging_buffer;
|
||||
std::list<MapInterval> marked_for_unregister;
|
||||
|
||||
std::shared_ptr<std::unordered_set<MapInterval>> uncommited_flushes{};
|
||||
std::list<std::shared_ptr<std::list<MapInterval>>> commited_flushes;
|
||||
std::shared_ptr<std::unordered_set<MapInterval>> uncommitted_flushes{};
|
||||
std::list<std::shared_ptr<std::list<MapInterval>>> committed_flushes;
|
||||
|
||||
std::recursive_mutex mutex;
|
||||
};
|
||||
|
@ -28,15 +28,15 @@ public:
|
||||
FenceBase(GPUVAddr address, u32 payload, bool is_stubbed)
|
||||
: address{address}, payload{payload}, is_semaphore{true}, is_stubbed{is_stubbed} {}
|
||||
|
||||
constexpr GPUVAddr GetAddress() const {
|
||||
GPUVAddr GetAddress() const {
|
||||
return address;
|
||||
}
|
||||
|
||||
constexpr u32 GetPayload() const {
|
||||
u32 GetPayload() const {
|
||||
return payload;
|
||||
}
|
||||
|
||||
constexpr bool IsSemaphore() const {
|
||||
bool IsSemaphore() const {
|
||||
return is_semaphore;
|
||||
}
|
||||
|
||||
@ -54,12 +54,8 @@ class FenceManager {
|
||||
public:
|
||||
void SignalSemaphore(GPUVAddr addr, u32 value) {
|
||||
TryReleasePendingFences();
|
||||
bool should_flush = texture_cache.HasUncommitedFlushes();
|
||||
should_flush |= buffer_cache.HasUncommitedFlushes();
|
||||
should_flush |= query_cache.HasUncommitedFlushes();
|
||||
texture_cache.CommitAsyncFlushes();
|
||||
buffer_cache.CommitAsyncFlushes();
|
||||
query_cache.CommitAsyncFlushes();
|
||||
bool should_flush = ShouldFlush();
|
||||
CommitAsyncFlushes();
|
||||
TFence new_fence = CreateFence(addr, value, !should_flush);
|
||||
fences.push(new_fence);
|
||||
QueueFence(new_fence);
|
||||
@ -71,12 +67,8 @@ public:
|
||||
|
||||
void SignalSyncPoint(u32 value) {
|
||||
TryReleasePendingFences();
|
||||
bool should_flush = texture_cache.HasUncommitedFlushes();
|
||||
should_flush |= buffer_cache.HasUncommitedFlushes();
|
||||
should_flush |= query_cache.HasUncommitedFlushes();
|
||||
texture_cache.CommitAsyncFlushes();
|
||||
buffer_cache.CommitAsyncFlushes();
|
||||
query_cache.CommitAsyncFlushes();
|
||||
bool should_flush = ShouldFlush();
|
||||
CommitAsyncFlushes();
|
||||
TFence new_fence = CreateFence(value, !should_flush);
|
||||
fences.push(new_fence);
|
||||
QueueFence(new_fence);
|
||||
@ -89,15 +81,10 @@ public:
|
||||
void WaitPendingFences() {
|
||||
while (!fences.empty()) {
|
||||
TFence& current_fence = fences.front();
|
||||
bool should_wait = texture_cache.ShouldWaitAsyncFlushes();
|
||||
should_wait |= buffer_cache.ShouldWaitAsyncFlushes();
|
||||
should_wait |= query_cache.ShouldWaitAsyncFlushes();
|
||||
if (should_wait) {
|
||||
if (ShouldWait()) {
|
||||
WaitFence(current_fence);
|
||||
}
|
||||
texture_cache.PopAsyncFlushes();
|
||||
buffer_cache.PopAsyncFlushes();
|
||||
query_cache.PopAsyncFlushes();
|
||||
PopAsyncFlushes();
|
||||
auto& gpu{system.GPU()};
|
||||
if (current_fence->IsSemaphore()) {
|
||||
auto& memory_manager{gpu.MemoryManager()};
|
||||
@ -116,10 +103,18 @@ protected:
|
||||
: system{system}, rasterizer{rasterizer}, texture_cache{texture_cache},
|
||||
buffer_cache{buffer_cache}, query_cache{query_cache} {}
|
||||
|
||||
virtual ~FenceManager() {}
|
||||
|
||||
/// Creates a Sync Point Fence Interface, does not create a backend fence if 'is_stubbed' is
|
||||
/// true
|
||||
virtual TFence CreateFence(u32 value, bool is_stubbed) = 0;
|
||||
/// Creates a Semaphore Fence Interface, does not create a backend fence if 'is_stubbed' is true
|
||||
virtual TFence CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) = 0;
|
||||
/// Queues a fence into the backend if the fence isn't stubbed.
|
||||
virtual void QueueFence(TFence& fence) = 0;
|
||||
virtual bool IsFenceSignaled(TFence& fence) = 0;
|
||||
/// Notifies that the backend fence has been signaled/reached in host GPU.
|
||||
virtual bool IsFenceSignaled(TFence& fence) const = 0;
|
||||
/// Waits until a fence has been signalled by the host GPU.
|
||||
virtual void WaitFence(TFence& fence) = 0;
|
||||
|
||||
Core::System& system;
|
||||
@ -132,15 +127,10 @@ private:
|
||||
void TryReleasePendingFences() {
|
||||
while (!fences.empty()) {
|
||||
TFence& current_fence = fences.front();
|
||||
bool should_wait = texture_cache.ShouldWaitAsyncFlushes();
|
||||
should_wait |= buffer_cache.ShouldWaitAsyncFlushes();
|
||||
should_wait |= query_cache.ShouldWaitAsyncFlushes();
|
||||
if (should_wait && !IsFenceSignaled(current_fence)) {
|
||||
if (ShouldWait() && !IsFenceSignaled(current_fence)) {
|
||||
return;
|
||||
}
|
||||
texture_cache.PopAsyncFlushes();
|
||||
buffer_cache.PopAsyncFlushes();
|
||||
query_cache.PopAsyncFlushes();
|
||||
PopAsyncFlushes();
|
||||
auto& gpu{system.GPU()};
|
||||
if (current_fence->IsSemaphore()) {
|
||||
auto& memory_manager{gpu.MemoryManager()};
|
||||
@ -152,6 +142,28 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
bool ShouldWait() const {
|
||||
return texture_cache.ShouldWaitAsyncFlushes() || buffer_cache.ShouldWaitAsyncFlushes() ||
|
||||
query_cache.ShouldWaitAsyncFlushes();
|
||||
}
|
||||
|
||||
bool ShouldFlush() const {
|
||||
return texture_cache.HasUncommittedFlushes() || buffer_cache.HasUncommittedFlushes() ||
|
||||
query_cache.HasUncommittedFlushes();
|
||||
}
|
||||
|
||||
void PopAsyncFlushes() {
|
||||
texture_cache.PopAsyncFlushes();
|
||||
buffer_cache.PopAsyncFlushes();
|
||||
query_cache.PopAsyncFlushes();
|
||||
}
|
||||
|
||||
void CommitAsyncFlushes() {
|
||||
texture_cache.CommitAsyncFlushes();
|
||||
buffer_cache.CommitAsyncFlushes();
|
||||
query_cache.CommitAsyncFlushes();
|
||||
}
|
||||
|
||||
std::queue<TFence> fences;
|
||||
};
|
||||
|
||||
|
@ -125,7 +125,7 @@ bool GPU::CancelSyncptInterrupt(const u32 syncpoint_id, const u32 value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
u64 GPU::RequestFlush(CacheAddr addr, std::size_t size) {
|
||||
u64 GPU::RequestFlush(VAddr addr, std::size_t size) {
|
||||
std::unique_lock lck{flush_request_mutex};
|
||||
const u64 fence = ++last_flush_fence;
|
||||
flush_requests.emplace_back(fence, addr, size);
|
||||
@ -137,7 +137,7 @@ void GPU::TickWork() {
|
||||
while (!flush_requests.empty()) {
|
||||
auto& request = flush_requests.front();
|
||||
const u64 fence = request.fence;
|
||||
const CacheAddr addr = request.addr;
|
||||
const VAddr addr = request.addr;
|
||||
const std::size_t size = request.size;
|
||||
flush_requests.pop_front();
|
||||
flush_request_mutex.unlock();
|
||||
|
@ -155,16 +155,22 @@ public:
|
||||
/// Calls a GPU method.
|
||||
void CallMethod(const MethodCall& method_call);
|
||||
|
||||
/// Flush all current written commands into the host GPU for execution.
|
||||
void FlushCommands();
|
||||
/// Synchronizes CPU writes with Host GPU memory.
|
||||
void SyncGuestHost();
|
||||
/// Signal the ending of command list.
|
||||
virtual void OnCommandListEnd();
|
||||
|
||||
u64 RequestFlush(CacheAddr addr, std::size_t size);
|
||||
/// Request a host GPU memory flush from the CPU.
|
||||
u64 RequestFlush(VAddr addr, std::size_t size);
|
||||
|
||||
/// Obtains current flush request fence id.
|
||||
u64 CurrentFlushRequestFence() const {
|
||||
return current_flush_fence.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
/// Tick pending requests within the GPU.
|
||||
void TickWork();
|
||||
|
||||
/// Returns a reference to the Maxwell3D GPU engine.
|
||||
@ -336,10 +342,10 @@ private:
|
||||
std::condition_variable sync_cv;
|
||||
|
||||
struct FlushRequest {
|
||||
FlushRequest(u64 fence, CacheAddr addr, std::size_t size)
|
||||
FlushRequest(u64 fence, VAddr addr, std::size_t size)
|
||||
: fence{fence}, addr{addr}, size{size} {}
|
||||
u64 fence;
|
||||
CacheAddr addr;
|
||||
VAddr addr;
|
||||
std::size_t size;
|
||||
};
|
||||
|
||||
|
@ -176,41 +176,34 @@ public:
|
||||
}
|
||||
|
||||
void CommitAsyncFlushes() {
|
||||
commited_flushes.push_back(uncommited_flushes);
|
||||
uncommited_flushes.reset();
|
||||
committed_flushes.push_back(uncommitted_flushes);
|
||||
uncommitted_flushes.reset();
|
||||
}
|
||||
|
||||
bool HasUncommitedFlushes() {
|
||||
if (uncommited_flushes) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool HasUncommittedFlushes() const {
|
||||
return uncommitted_flushes != nullptr;
|
||||
}
|
||||
|
||||
bool ShouldWaitAsyncFlushes() {
|
||||
if (commited_flushes.empty()) {
|
||||
bool ShouldWaitAsyncFlushes() const {
|
||||
if (committed_flushes.empty()) {
|
||||
return false;
|
||||
}
|
||||
auto& flush_list = commited_flushes.front();
|
||||
if (!flush_list) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return committed_flushes.front() != nullptr;
|
||||
}
|
||||
|
||||
void PopAsyncFlushes() {
|
||||
if (commited_flushes.empty()) {
|
||||
if (committed_flushes.empty()) {
|
||||
return;
|
||||
}
|
||||
auto& flush_list = commited_flushes.front();
|
||||
auto& flush_list = committed_flushes.front();
|
||||
if (!flush_list) {
|
||||
commited_flushes.pop_front();
|
||||
committed_flushes.pop_front();
|
||||
return;
|
||||
}
|
||||
for (VAddr query_address : *flush_list) {
|
||||
FlushAndRemoveRegion(query_address, 4);
|
||||
}
|
||||
commited_flushes.pop_front();
|
||||
committed_flushes.pop_front();
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -268,10 +261,10 @@ private:
|
||||
}
|
||||
|
||||
void AsyncFlushQuery(VAddr addr) {
|
||||
if (!uncommited_flushes) {
|
||||
uncommited_flushes = std::make_shared<std::unordered_set<VAddr>>();
|
||||
if (!uncommitted_flushes) {
|
||||
uncommitted_flushes = std::make_shared<std::unordered_set<VAddr>>();
|
||||
}
|
||||
uncommited_flushes->insert(addr);
|
||||
uncommitted_flushes->insert(addr);
|
||||
}
|
||||
|
||||
static constexpr std::uintptr_t PAGE_SIZE = 4096;
|
||||
@ -286,8 +279,8 @@ private:
|
||||
|
||||
std::array<CounterStream, VideoCore::NumQueryTypes> streams;
|
||||
|
||||
std::shared_ptr<std::unordered_set<VAddr>> uncommited_flushes{};
|
||||
std::list<std::shared_ptr<std::unordered_set<VAddr>>> commited_flushes;
|
||||
std::shared_ptr<std::unordered_set<VAddr>> uncommitted_flushes{};
|
||||
std::list<std::shared_ptr<std::unordered_set<VAddr>>> committed_flushes;
|
||||
};
|
||||
|
||||
template <class QueryCache, class HostCounter>
|
||||
|
@ -64,6 +64,7 @@ public:
|
||||
/// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
|
||||
virtual void FlushRegion(VAddr addr, u64 size) = 0;
|
||||
|
||||
/// Check if the the specified memory area requires flushing to CPU Memory.
|
||||
virtual bool MustFlushRegion(VAddr addr, u64 size) = 0;
|
||||
|
||||
/// Notify rasterizer that any caches of the specified region should be invalidated
|
||||
|
@ -62,7 +62,7 @@ void FenceManagerOpenGL::QueueFence(Fence& fence) {
|
||||
fence->Queue();
|
||||
}
|
||||
|
||||
bool FenceManagerOpenGL::IsFenceSignaled(Fence& fence) {
|
||||
bool FenceManagerOpenGL::IsFenceSignaled(Fence& fence) const {
|
||||
return fence->IsSignaled();
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ protected:
|
||||
Fence CreateFence(u32 value, bool is_stubbed) override;
|
||||
Fence CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) override;
|
||||
void QueueFence(Fence& fence) override;
|
||||
bool IsFenceSignaled(Fence& fence) override;
|
||||
bool IsFenceSignaled(Fence& fence) const override;
|
||||
void WaitFence(Fence& fence) override;
|
||||
};
|
||||
|
||||
|
@ -653,9 +653,6 @@ void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) {
|
||||
}
|
||||
|
||||
bool RasterizerOpenGL::MustFlushRegion(VAddr addr, u64 size) {
|
||||
if (!Settings::IsGPULevelExtreme()) {
|
||||
return buffer_cache.MustFlushRegion(addr, size);
|
||||
}
|
||||
return texture_cache.MustFlushRegion(addr, size) || buffer_cache.MustFlushRegion(addr, size);
|
||||
}
|
||||
|
||||
@ -672,7 +669,7 @@ void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size) {
|
||||
|
||||
void RasterizerOpenGL::OnCPUWrite(VAddr addr, u64 size) {
|
||||
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
|
||||
if (!addr || !size) {
|
||||
if (addr == 0 || size == 0) {
|
||||
return;
|
||||
}
|
||||
texture_cache.OnCPUWrite(addr, size);
|
||||
|
@ -90,7 +90,7 @@ void VKFenceManager::QueueFence(Fence& fence) {
|
||||
fence->Queue();
|
||||
}
|
||||
|
||||
bool VKFenceManager::IsFenceSignaled(Fence& fence) {
|
||||
bool VKFenceManager::IsFenceSignaled(Fence& fence) const {
|
||||
return fence->IsSignaled();
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ protected:
|
||||
Fence CreateFence(u32 value, bool is_stubbed) override;
|
||||
Fence CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) override;
|
||||
void QueueFence(Fence& fence) override;
|
||||
bool IsFenceSignaled(Fence& fence) override;
|
||||
bool IsFenceSignaled(Fence& fence) const override;
|
||||
void WaitFence(Fence& fence) override;
|
||||
|
||||
private:
|
||||
|
@ -533,7 +533,7 @@ void RasterizerVulkan::InvalidateRegion(VAddr addr, u64 size) {
|
||||
}
|
||||
|
||||
void RasterizerVulkan::OnCPUWrite(VAddr addr, u64 size) {
|
||||
if (!addr || !size) {
|
||||
if (addr == 0 || size == 0) {
|
||||
return;
|
||||
}
|
||||
texture_cache.OnCPUWrite(addr, size);
|
||||
|
@ -120,15 +120,8 @@ public:
|
||||
std::lock_guard lock{mutex};
|
||||
|
||||
auto surfaces = GetSurfacesInRegion(addr, size);
|
||||
if (surfaces.empty()) {
|
||||
return false;
|
||||
}
|
||||
for (const auto& surface : surfaces) {
|
||||
if (surface->IsModified()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return std::any_of(surfaces.begin(), surfaces.end(),
|
||||
[](const TSurface& surface) { return surface->IsModified(); });
|
||||
}
|
||||
|
||||
TView GetTextureSurface(const Tegra::Texture::TICEntry& tic,
|
||||
@ -333,41 +326,34 @@ public:
|
||||
}
|
||||
|
||||
void CommitAsyncFlushes() {
|
||||
commited_flushes.push_back(uncommited_flushes);
|
||||
uncommited_flushes.reset();
|
||||
committed_flushes.push_back(uncommitted_flushes);
|
||||
uncommitted_flushes.reset();
|
||||
}
|
||||
|
||||
bool HasUncommitedFlushes() {
|
||||
if (uncommited_flushes) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool HasUncommittedFlushes() const {
|
||||
return uncommitted_flushes != nullptr;
|
||||
}
|
||||
|
||||
bool ShouldWaitAsyncFlushes() {
|
||||
if (commited_flushes.empty()) {
|
||||
bool ShouldWaitAsyncFlushes() const {
|
||||
if (committed_flushes.empty()) {
|
||||
return false;
|
||||
}
|
||||
auto& flush_list = commited_flushes.front();
|
||||
if (!flush_list) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return committed_flushes.front() != nullptr;
|
||||
}
|
||||
|
||||
void PopAsyncFlushes() {
|
||||
if (commited_flushes.empty()) {
|
||||
if (committed_flushes.empty()) {
|
||||
return;
|
||||
}
|
||||
auto& flush_list = commited_flushes.front();
|
||||
auto& flush_list = committed_flushes.front();
|
||||
if (!flush_list) {
|
||||
commited_flushes.pop_front();
|
||||
committed_flushes.pop_front();
|
||||
return;
|
||||
}
|
||||
for (TSurface& surface : *flush_list) {
|
||||
FlushSurface(surface);
|
||||
}
|
||||
commited_flushes.pop_front();
|
||||
committed_flushes.pop_front();
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -1206,10 +1192,10 @@ private:
|
||||
};
|
||||
|
||||
void AsyncFlushSurface(TSurface& surface) {
|
||||
if (!uncommited_flushes) {
|
||||
uncommited_flushes = std::make_shared<std::list<TSurface>>();
|
||||
if (!uncommitted_flushes) {
|
||||
uncommitted_flushes = std::make_shared<std::list<TSurface>>();
|
||||
}
|
||||
uncommited_flushes->push_back(surface);
|
||||
uncommitted_flushes->push_back(surface);
|
||||
}
|
||||
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
@ -1258,8 +1244,8 @@ private:
|
||||
|
||||
std::list<TSurface> marked_for_unregister;
|
||||
|
||||
std::shared_ptr<std::list<TSurface>> uncommited_flushes{};
|
||||
std::list<std::shared_ptr<std::list<TSurface>>> commited_flushes;
|
||||
std::shared_ptr<std::list<TSurface>> uncommitted_flushes{};
|
||||
std::list<std::shared_ptr<std::list<TSurface>>> committed_flushes;
|
||||
|
||||
StagingCache staging_cache;
|
||||
std::recursive_mutex mutex;
|
||||
|
Loading…
Reference in New Issue
Block a user