forked from mirrors/gecko-dev
Bug 1878316 - Defer SwapChain drop until readback complete r=lsalzman
Differential Revision: https://phabricator.services.mozilla.com/D201192
This commit is contained in:
parent
0aaf858381
commit
2b666cc1a6
1 changed files with 53 additions and 7 deletions
|
|
@ -4,6 +4,9 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "WebGPUParent.h"
|
#include "WebGPUParent.h"
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include "mozilla/PodOperations.h"
|
#include "mozilla/PodOperations.h"
|
||||||
#include "mozilla/ScopeExit.h"
|
#include "mozilla/ScopeExit.h"
|
||||||
#include "mozilla/dom/WebGPUBinding.h"
|
#include "mozilla/dom/WebGPUBinding.h"
|
||||||
|
|
@ -153,10 +156,16 @@ class ErrorBuffer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PendingSwapChainDrop {
|
||||||
|
layers::RemoteTextureTxnType mTxnType;
|
||||||
|
layers::RemoteTextureTxnId mTxnId;
|
||||||
|
};
|
||||||
|
|
||||||
class PresentationData {
|
class PresentationData {
|
||||||
NS_INLINE_DECL_REFCOUNTING(PresentationData);
|
NS_INLINE_DECL_REFCOUNTING(PresentationData);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
WeakPtr<WebGPUParent> mParent;
|
||||||
const bool mUseExternalTextureInSwapChain;
|
const bool mUseExternalTextureInSwapChain;
|
||||||
const RawId mDeviceId;
|
const RawId mDeviceId;
|
||||||
const RawId mQueueId;
|
const RawId mQueueId;
|
||||||
|
|
@ -166,16 +175,22 @@ class PresentationData {
|
||||||
|
|
||||||
std::deque<std::shared_ptr<ExternalTexture>> mRecycledExternalTextures;
|
std::deque<std::shared_ptr<ExternalTexture>> mRecycledExternalTextures;
|
||||||
|
|
||||||
|
std::unordered_set<layers::RemoteTextureId, layers::RemoteTextureId::HashFn>
|
||||||
|
mWaitingReadbackTexturesForPresent;
|
||||||
|
Maybe<PendingSwapChainDrop> mPendingSwapChainDrop;
|
||||||
|
|
||||||
const uint32_t mSourcePitch;
|
const uint32_t mSourcePitch;
|
||||||
std::vector<RawId> mUnassignedBufferIds MOZ_GUARDED_BY(mBuffersLock);
|
std::vector<RawId> mUnassignedBufferIds MOZ_GUARDED_BY(mBuffersLock);
|
||||||
std::vector<RawId> mAvailableBufferIds MOZ_GUARDED_BY(mBuffersLock);
|
std::vector<RawId> mAvailableBufferIds MOZ_GUARDED_BY(mBuffersLock);
|
||||||
std::vector<RawId> mQueuedBufferIds MOZ_GUARDED_BY(mBuffersLock);
|
std::vector<RawId> mQueuedBufferIds MOZ_GUARDED_BY(mBuffersLock);
|
||||||
Mutex mBuffersLock;
|
Mutex mBuffersLock;
|
||||||
|
|
||||||
PresentationData(bool aUseExternalTextureInSwapChain, RawId aDeviceId,
|
PresentationData(WebGPUParent* aParent, bool aUseExternalTextureInSwapChain,
|
||||||
RawId aQueueId, const layers::RGBDescriptor& aDesc,
|
RawId aDeviceId, RawId aQueueId,
|
||||||
uint32_t aSourcePitch, const nsTArray<RawId>& aBufferIds)
|
const layers::RGBDescriptor& aDesc, uint32_t aSourcePitch,
|
||||||
: mUseExternalTextureInSwapChain(aUseExternalTextureInSwapChain),
|
const nsTArray<RawId>& aBufferIds)
|
||||||
|
: mParent(aParent),
|
||||||
|
mUseExternalTextureInSwapChain(aUseExternalTextureInSwapChain),
|
||||||
mDeviceId(aDeviceId),
|
mDeviceId(aDeviceId),
|
||||||
mQueueId(aQueueId),
|
mQueueId(aQueueId),
|
||||||
mDesc(aDesc),
|
mDesc(aDesc),
|
||||||
|
|
@ -861,9 +876,9 @@ ipc::IPCResult WebGPUParent::RecvDeviceCreateSwapChain(
|
||||||
}
|
}
|
||||||
mRemoteTextureOwner->RegisterTextureOwner(aOwnerId);
|
mRemoteTextureOwner->RegisterTextureOwner(aOwnerId);
|
||||||
|
|
||||||
auto data =
|
auto data = MakeRefPtr<PresentationData>(this, aUseExternalTextureInSwapChain,
|
||||||
MakeRefPtr<PresentationData>(aUseExternalTextureInSwapChain, aDeviceId,
|
aDeviceId, aQueueId, aDesc,
|
||||||
aQueueId, aDesc, bufferStride, aBufferIds);
|
bufferStride, aBufferIds);
|
||||||
if (!mPresentationDataMap.emplace(aOwnerId, data).second) {
|
if (!mPresentationDataMap.emplace(aOwnerId, data).second) {
|
||||||
NS_ERROR("External image is already registered as WebGPU canvas!");
|
NS_ERROR("External image is already registered as WebGPU canvas!");
|
||||||
}
|
}
|
||||||
|
|
@ -933,6 +948,23 @@ static void ReadbackPresentCallback(ffi::WGPUBufferMapAsyncStatus status,
|
||||||
UniquePtr<ReadbackPresentRequest> req(
|
UniquePtr<ReadbackPresentRequest> req(
|
||||||
reinterpret_cast<ReadbackPresentRequest*>(userdata));
|
reinterpret_cast<ReadbackPresentRequest*>(userdata));
|
||||||
|
|
||||||
|
const auto onExit = mozilla::MakeScopeExit([&]() {
|
||||||
|
auto& waitingTextures = req->mData->mWaitingReadbackTexturesForPresent;
|
||||||
|
auto it = waitingTextures.find(req->mTextureId);
|
||||||
|
MOZ_ASSERT(it != waitingTextures.end());
|
||||||
|
if (it != waitingTextures.end()) {
|
||||||
|
waitingTextures.erase(it);
|
||||||
|
}
|
||||||
|
if (req->mData->mPendingSwapChainDrop.isSome() && waitingTextures.empty()) {
|
||||||
|
if (req->mData->mParent) {
|
||||||
|
auto& pendingDrop = req->mData->mPendingSwapChainDrop.ref();
|
||||||
|
req->mData->mParent->RecvSwapChainDrop(
|
||||||
|
req->mOwnerId, pendingDrop.mTxnType, pendingDrop.mTxnId);
|
||||||
|
req->mData->mPendingSwapChainDrop = Nothing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (!req->mRemoteTextureOwner->IsRegistered(req->mOwnerId)) {
|
if (!req->mRemoteTextureOwner->IsRegistered(req->mOwnerId)) {
|
||||||
// SwapChain is already Destroyed
|
// SwapChain is already Destroyed
|
||||||
return;
|
return;
|
||||||
|
|
@ -1186,6 +1218,13 @@ ipc::IPCResult WebGPUParent::RecvSwapChainPresent(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto& waitingTextures = data->mWaitingReadbackTexturesForPresent;
|
||||||
|
auto it = waitingTextures.find(aRemoteTextureId);
|
||||||
|
MOZ_ASSERT(it == waitingTextures.end());
|
||||||
|
if (it == waitingTextures.end()) {
|
||||||
|
waitingTextures.emplace(aRemoteTextureId);
|
||||||
|
}
|
||||||
|
|
||||||
// step 4: request the pixels to be copied into the external texture
|
// step 4: request the pixels to be copied into the external texture
|
||||||
// TODO: this isn't strictly necessary. When WR wants to Lock() the external
|
// TODO: this isn't strictly necessary. When WR wants to Lock() the external
|
||||||
// texture,
|
// texture,
|
||||||
|
|
@ -1220,6 +1259,13 @@ ipc::IPCResult WebGPUParent::RecvSwapChainDrop(
|
||||||
|
|
||||||
RefPtr<PresentationData> data = lookup->second.get();
|
RefPtr<PresentationData> data = lookup->second.get();
|
||||||
|
|
||||||
|
auto waitingCount = data->mWaitingReadbackTexturesForPresent.size();
|
||||||
|
if (waitingCount > 0) {
|
||||||
|
// Defer SwapChainDrop until readback complete
|
||||||
|
data->mPendingSwapChainDrop = Some(PendingSwapChainDrop{aTxnType, aTxnId});
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
if (mRemoteTextureOwner) {
|
if (mRemoteTextureOwner) {
|
||||||
if (aTxnType && aTxnId) {
|
if (aTxnType && aTxnId) {
|
||||||
mRemoteTextureOwner->WaitForTxn(aOwnerId, aTxnType, aTxnId);
|
mRemoteTextureOwner->WaitForTxn(aOwnerId, aTxnType, aTxnId);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue