mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-16 03:59:18 +01:00
Set state to CpuDirty
directly in SynchronizeGuest
`SynchronizeGuest` could only set the dirty state to `Clean` which was redundant since calls to it from inside the write trap handler would set it to `CpuDirty` directly after, this fixes that by doing it inside the function when necessary.
This commit is contained in:
parent
4f6a67af36
commit
c1f2445772
@ -31,8 +31,7 @@ namespace skyline::gpu {
|
|||||||
std::unique_lock lock{*this, std::try_to_lock};
|
std::unique_lock lock{*this, std::try_to_lock};
|
||||||
if (!lock)
|
if (!lock)
|
||||||
return false;
|
return false;
|
||||||
SynchronizeGuest(true);
|
SynchronizeGuest(true, false, true); // We need to assume the buffer is dirty since we don't know what the guest is writing
|
||||||
dirtyState = DirtyState::CpuDirty; // We need to assume the buffer is dirty since we don't know what the guest is writing
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -161,15 +160,15 @@ namespace skyline::gpu {
|
|||||||
gpu.state.nce->RetrapRegions(*trapHandle, !rwTrap); // Trap any future CPU reads (optionally) + writes to this buffer
|
gpu.state.nce->RetrapRegions(*trapHandle, !rwTrap); // Trap any future CPU reads (optionally) + writes to this buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::SynchronizeGuest(bool skipTrap, bool nonBlocking) {
|
void Buffer::SynchronizeGuest(bool skipTrap, bool nonBlocking, bool setDirty) {
|
||||||
if (!guest)
|
if (!guest)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto currentState{dirtyState.load(std::memory_order_relaxed)};
|
auto currentState{dirtyState.load(std::memory_order_relaxed)};
|
||||||
do {
|
do {
|
||||||
if (currentState != DirtyState::GpuDirty)
|
if (currentState == DirtyState::CpuDirty || (currentState == DirtyState::Clean && setDirty))
|
||||||
return; // If the buffer has not been used on the GPU, there is no need to synchronize it
|
return; // If the buffer is synchronized (Clean/CpuDirty), there is no need to synchronize it
|
||||||
} while (!dirtyState.compare_exchange_strong(currentState, DirtyState::Clean, std::memory_order_relaxed));
|
} while (!dirtyState.compare_exchange_strong(currentState, setDirty ? DirtyState::CpuDirty : DirtyState::Clean, std::memory_order_relaxed));
|
||||||
|
|
||||||
if (nonBlocking && !PollFence())
|
if (nonBlocking && !PollFence())
|
||||||
return;
|
return;
|
||||||
@ -179,6 +178,9 @@ namespace skyline::gpu {
|
|||||||
if (!skipTrap)
|
if (!skipTrap)
|
||||||
gpu.state.nce->RetrapRegions(*trapHandle, true);
|
gpu.state.nce->RetrapRegions(*trapHandle, true);
|
||||||
|
|
||||||
|
if (setDirty && currentState == DirtyState::Clean)
|
||||||
|
return; // If the texture was simply transitioned from Clean to CpuDirty, there is no need to synchronize it
|
||||||
|
|
||||||
if (!nonBlocking)
|
if (!nonBlocking)
|
||||||
WaitOnFence();
|
WaitOnFence();
|
||||||
|
|
||||||
|
@ -233,9 +233,10 @@ namespace skyline::gpu {
|
|||||||
* @brief Synchronizes the guest buffer with the host buffer
|
* @brief Synchronizes the guest buffer with the host buffer
|
||||||
* @param skipTrap If true, setting up a CPU trap will be skipped and the dirty state will be Clean/CpuDirty
|
* @param skipTrap If true, setting up a CPU trap will be skipped and the dirty state will be Clean/CpuDirty
|
||||||
* @param nonBlocking If true, the call will return immediately if the fence is not signalled, skipping the sync
|
* @param nonBlocking If true, the call will return immediately if the fence is not signalled, skipping the sync
|
||||||
|
* @param setDirty If true, the buffer will be marked as CpuDirty rather than Clean
|
||||||
* @note The buffer **must** be locked prior to calling this
|
* @note The buffer **must** be locked prior to calling this
|
||||||
*/
|
*/
|
||||||
void SynchronizeGuest(bool skipTrap = false, bool nonBlocking = false);
|
void SynchronizeGuest(bool skipTrap = false, bool nonBlocking = false, bool setDirty = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Synchronizes the guest buffer with the host buffer immediately, flushing GPU work if necessary
|
* @brief Synchronizes the guest buffer with the host buffer immediately, flushing GPU work if necessary
|
||||||
|
@ -160,8 +160,7 @@ namespace skyline::gpu {
|
|||||||
std::unique_lock lock{*this, std::try_to_lock};
|
std::unique_lock lock{*this, std::try_to_lock};
|
||||||
if (!lock)
|
if (!lock)
|
||||||
return false;
|
return false;
|
||||||
SynchronizeGuest(true);
|
SynchronizeGuest(true, true); // We need to assume the texture is dirty since we don't know what the guest is writing
|
||||||
dirtyState = DirtyState::CpuDirty; // We need to assume the texture is dirty since we don't know what the guest is writing
|
|
||||||
WaitOnFence();
|
WaitOnFence();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@ -555,9 +554,9 @@ namespace skyline::gpu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Texture::~Texture() {
|
Texture::~Texture() {
|
||||||
|
SynchronizeGuest(true);
|
||||||
if (trapHandle)
|
if (trapHandle)
|
||||||
gpu.state.nce->DeleteTrap(*trapHandle);
|
gpu.state.nce->DeleteTrap(*trapHandle);
|
||||||
SynchronizeGuest(true);
|
|
||||||
if (alignedMirror.valid())
|
if (alignedMirror.valid())
|
||||||
munmap(alignedMirror.data(), alignedMirror.size());
|
munmap(alignedMirror.data(), alignedMirror.size());
|
||||||
WaitOnFence();
|
WaitOnFence();
|
||||||
@ -705,20 +704,23 @@ namespace skyline::gpu {
|
|||||||
gpu.state.nce->RetrapRegions(*trapHandle, !rwTrap); // Trap any future CPU reads (optionally) + writes to this texture
|
gpu.state.nce->RetrapRegions(*trapHandle, !rwTrap); // Trap any future CPU reads (optionally) + writes to this texture
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::SynchronizeGuest(bool skipTrap) {
|
void Texture::SynchronizeGuest(bool skipTrap, bool setDirty) {
|
||||||
if (!guest)
|
if (!guest)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto currentState{dirtyState.load(std::memory_order_relaxed)};
|
auto currentState{dirtyState.load(std::memory_order_relaxed)};
|
||||||
do {
|
do {
|
||||||
if (currentState != DirtyState::GpuDirty)
|
if (currentState == DirtyState::CpuDirty || (currentState == DirtyState::Clean && setDirty))
|
||||||
return; // If the buffer has not been used on the GPU, there is no need to synchronize it
|
return; // If the texture is synchronized (Clean/CpuDirty), there is no need to synchronize it
|
||||||
} while (!dirtyState.compare_exchange_strong(currentState, DirtyState::Clean, std::memory_order_relaxed));
|
} while (!dirtyState.compare_exchange_strong(currentState, setDirty ? DirtyState::CpuDirty : DirtyState::Clean, std::memory_order_relaxed));
|
||||||
|
|
||||||
TRACE_EVENT("gpu", "Texture::SynchronizeGuest");
|
TRACE_EVENT("gpu", "Texture::SynchronizeGuest");
|
||||||
|
|
||||||
if (!skipTrap)
|
if (!skipTrap)
|
||||||
gpu.state.nce->RetrapRegions(*trapHandle, true);
|
gpu.state.nce->RetrapRegions(*trapHandle, !setDirty);
|
||||||
|
|
||||||
|
if (setDirty && currentState == DirtyState::Clean)
|
||||||
|
return; // If the texture was simply transitioned from Clean to CpuDirty, there is no need to synchronize it
|
||||||
|
|
||||||
if (layout == vk::ImageLayout::eUndefined || format != guest->format)
|
if (layout == vk::ImageLayout::eUndefined || format != guest->format)
|
||||||
// If the state of the host texture is undefined then so can the guest
|
// If the state of the host texture is undefined then so can the guest
|
||||||
@ -752,7 +754,7 @@ namespace skyline::gpu {
|
|||||||
auto currentState{dirtyState.load(std::memory_order_relaxed)};
|
auto currentState{dirtyState.load(std::memory_order_relaxed)};
|
||||||
do {
|
do {
|
||||||
if (currentState != DirtyState::GpuDirty)
|
if (currentState != DirtyState::GpuDirty)
|
||||||
return; // If the buffer has not been used on the GPU, there is no need to synchronize it
|
return; // If the texture has not been used on the GPU, there is no need to synchronize it
|
||||||
} while (!dirtyState.compare_exchange_strong(currentState, DirtyState::Clean, std::memory_order_relaxed));
|
} while (!dirtyState.compare_exchange_strong(currentState, DirtyState::Clean, std::memory_order_relaxed));
|
||||||
|
|
||||||
TRACE_EVENT("gpu", "Texture::SynchronizeGuestWithBuffer");
|
TRACE_EVENT("gpu", "Texture::SynchronizeGuestWithBuffer");
|
||||||
|
@ -559,10 +559,11 @@ namespace skyline::gpu {
|
|||||||
/**
|
/**
|
||||||
* @brief Synchronizes the guest texture with the host texture after it has been modified
|
* @brief Synchronizes the guest texture with the host texture after it has been modified
|
||||||
* @param skipTrap If true, setting up a CPU trap will be skipped and the dirty state will be Clean/CpuDirty
|
* @param skipTrap If true, setting up a CPU trap will be skipped and the dirty state will be Clean/CpuDirty
|
||||||
|
* @param setDirty If true, the texture will be marked as CpuDirty rather than Clean
|
||||||
* @note The texture **must** be locked prior to calling this
|
* @note The texture **must** be locked prior to calling this
|
||||||
* @note The guest texture should not be null prior to calling this
|
* @note The guest texture should not be null prior to calling this
|
||||||
*/
|
*/
|
||||||
void SynchronizeGuest(bool skipTrap = false);
|
void SynchronizeGuest(bool skipTrap = false, bool setDirty = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Synchronizes the guest texture with the host texture after it has been modified
|
* @brief Synchronizes the guest texture with the host texture after it has been modified
|
||||||
|
Loading…
Reference in New Issue
Block a user