Implement CallbackTaskManager for Create*PipelineAsync
This patch implements CallbackTask and CallbackTaskManager to store the callbacks of Create*PipelineAsync(). In the futureCallbackTaskManager will manage all the callbacks that should be called in Device.Tick(). BUG=dawn:529 Change-Id: I6ad4352371eb44515bc2d85cdc68220c9b758b8e Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/49060 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
parent
321c900c6b
commit
c74af70378
|
@ -184,6 +184,8 @@ source_set("dawn_native_sources") {
|
||||||
"Buffer.h",
|
"Buffer.h",
|
||||||
"CachedObject.cpp",
|
"CachedObject.cpp",
|
||||||
"CachedObject.h",
|
"CachedObject.h",
|
||||||
|
"CallbackTaskManager.cpp",
|
||||||
|
"CallbackTaskManager.h",
|
||||||
"CommandAllocator.cpp",
|
"CommandAllocator.cpp",
|
||||||
"CommandAllocator.h",
|
"CommandAllocator.h",
|
||||||
"CommandBuffer.cpp",
|
"CommandBuffer.cpp",
|
||||||
|
@ -204,8 +206,8 @@ source_set("dawn_native_sources") {
|
||||||
"ComputePipeline.h",
|
"ComputePipeline.h",
|
||||||
"CopyTextureForBrowserHelper.cpp",
|
"CopyTextureForBrowserHelper.cpp",
|
||||||
"CopyTextureForBrowserHelper.h",
|
"CopyTextureForBrowserHelper.h",
|
||||||
"CreatePipelineAsyncTracker.cpp",
|
"CreatePipelineAsyncTask.cpp",
|
||||||
"CreatePipelineAsyncTracker.h",
|
"CreatePipelineAsyncTask.h",
|
||||||
"Device.cpp",
|
"Device.cpp",
|
||||||
"Device.h",
|
"Device.h",
|
||||||
"DynamicUploader.cpp",
|
"DynamicUploader.cpp",
|
||||||
|
|
|
@ -50,6 +50,8 @@ target_sources(dawn_native PRIVATE
|
||||||
"Buffer.h"
|
"Buffer.h"
|
||||||
"CachedObject.cpp"
|
"CachedObject.cpp"
|
||||||
"CachedObject.h"
|
"CachedObject.h"
|
||||||
|
"CallbackTaskManager.cpp"
|
||||||
|
"CallbackTaskManager.h"
|
||||||
"CommandAllocator.cpp"
|
"CommandAllocator.cpp"
|
||||||
"CommandAllocator.h"
|
"CommandAllocator.h"
|
||||||
"CommandBuffer.cpp"
|
"CommandBuffer.cpp"
|
||||||
|
@ -70,8 +72,8 @@ target_sources(dawn_native PRIVATE
|
||||||
"ComputePipeline.h"
|
"ComputePipeline.h"
|
||||||
"CopyTextureForBrowserHelper.cpp"
|
"CopyTextureForBrowserHelper.cpp"
|
||||||
"CopyTextureForBrowserHelper.h"
|
"CopyTextureForBrowserHelper.h"
|
||||||
"CreatePipelineAsyncTracker.cpp"
|
"CreatePipelineAsyncTask.cpp"
|
||||||
"CreatePipelineAsyncTracker.h"
|
"CreatePipelineAsyncTask.h"
|
||||||
"Device.cpp"
|
"Device.cpp"
|
||||||
"Device.h"
|
"Device.h"
|
||||||
"DynamicUploader.cpp"
|
"DynamicUploader.cpp"
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright 2021 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "dawn_native/CallbackTaskManager.h"
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
bool CallbackTaskManager::IsEmpty() {
|
||||||
|
std::lock_guard<std::mutex> lock(mCallbackTaskQueueMutex);
|
||||||
|
return mCallbackTaskQueue.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<CallbackTask>> CallbackTaskManager::AcquireCallbackTasks() {
|
||||||
|
std::lock_guard<std::mutex> lock(mCallbackTaskQueueMutex);
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<CallbackTask>> allTasks;
|
||||||
|
allTasks.swap(mCallbackTaskQueue);
|
||||||
|
return allTasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallbackTaskManager::AddCallbackTask(std::unique_ptr<CallbackTask> callbackTask) {
|
||||||
|
std::lock_guard<std::mutex> lock(mCallbackTaskQueueMutex);
|
||||||
|
mCallbackTaskQueue.push_back(std::move(callbackTask));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
|
@ -0,0 +1,47 @@
|
||||||
|
// Copyright 2021 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef DAWNNATIVE_CALLBACK_TASK_MANAGER_H_
|
||||||
|
#define DAWNNATIVE_CALLBACK_TASK_MANAGER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
class CallbackTaskManager;
|
||||||
|
|
||||||
|
struct CallbackTask {
|
||||||
|
public:
|
||||||
|
virtual ~CallbackTask() = default;
|
||||||
|
virtual void Finish() = 0;
|
||||||
|
virtual void HandleShutDown() = 0;
|
||||||
|
virtual void HandleDeviceLoss() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CallbackTaskManager {
|
||||||
|
public:
|
||||||
|
void AddCallbackTask(std::unique_ptr<CallbackTask> callbackTask);
|
||||||
|
bool IsEmpty();
|
||||||
|
std::vector<std::unique_ptr<CallbackTask>> AcquireCallbackTasks();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::mutex mCallbackTaskQueueMutex;
|
||||||
|
std::vector<std::unique_ptr<CallbackTask>> mCallbackTaskQueue;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
||||||
|
|
||||||
|
#endif
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "dawn_native/CreatePipelineAsyncTracker.h"
|
#include "dawn_native/CreatePipelineAsyncTask.h"
|
||||||
|
|
||||||
#include "dawn_native/ComputePipeline.h"
|
#include "dawn_native/ComputePipeline.h"
|
||||||
#include "dawn_native/Device.h"
|
#include "dawn_native/Device.h"
|
||||||
|
@ -20,25 +20,23 @@
|
||||||
|
|
||||||
namespace dawn_native {
|
namespace dawn_native {
|
||||||
|
|
||||||
CreatePipelineAsyncTaskBase::CreatePipelineAsyncTaskBase(std::string errorMessage,
|
CreatePipelineAsyncCallbackTaskBase::CreatePipelineAsyncCallbackTaskBase(
|
||||||
void* userdata)
|
std::string errorMessage,
|
||||||
|
void* userdata)
|
||||||
: mErrorMessage(errorMessage), mUserData(userdata) {
|
: mErrorMessage(errorMessage), mUserData(userdata) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CreatePipelineAsyncTaskBase::~CreatePipelineAsyncTaskBase() {
|
CreateComputePipelineAsyncCallbackTask::CreateComputePipelineAsyncCallbackTask(
|
||||||
}
|
|
||||||
|
|
||||||
CreateComputePipelineAsyncTask::CreateComputePipelineAsyncTask(
|
|
||||||
Ref<ComputePipelineBase> pipeline,
|
Ref<ComputePipelineBase> pipeline,
|
||||||
std::string errorMessage,
|
std::string errorMessage,
|
||||||
WGPUCreateComputePipelineAsyncCallback callback,
|
WGPUCreateComputePipelineAsyncCallback callback,
|
||||||
void* userdata)
|
void* userdata)
|
||||||
: CreatePipelineAsyncTaskBase(errorMessage, userdata),
|
: CreatePipelineAsyncCallbackTaskBase(errorMessage, userdata),
|
||||||
mPipeline(std::move(pipeline)),
|
mPipeline(std::move(pipeline)),
|
||||||
mCreateComputePipelineAsyncCallback(callback) {
|
mCreateComputePipelineAsyncCallback(callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateComputePipelineAsyncTask::Finish() {
|
void CreateComputePipelineAsyncCallbackTask::Finish() {
|
||||||
ASSERT(mCreateComputePipelineAsyncCallback != nullptr);
|
ASSERT(mCreateComputePipelineAsyncCallback != nullptr);
|
||||||
|
|
||||||
if (mPipeline.Get() != nullptr) {
|
if (mPipeline.Get() != nullptr) {
|
||||||
|
@ -51,31 +49,31 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateComputePipelineAsyncTask::HandleShutDown() {
|
void CreateComputePipelineAsyncCallbackTask::HandleShutDown() {
|
||||||
ASSERT(mCreateComputePipelineAsyncCallback != nullptr);
|
ASSERT(mCreateComputePipelineAsyncCallback != nullptr);
|
||||||
|
|
||||||
mCreateComputePipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_DeviceDestroyed, nullptr,
|
mCreateComputePipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_DeviceDestroyed, nullptr,
|
||||||
"Device destroyed before callback", mUserData);
|
"Device destroyed before callback", mUserData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateComputePipelineAsyncTask::HandleDeviceLoss() {
|
void CreateComputePipelineAsyncCallbackTask::HandleDeviceLoss() {
|
||||||
ASSERT(mCreateComputePipelineAsyncCallback != nullptr);
|
ASSERT(mCreateComputePipelineAsyncCallback != nullptr);
|
||||||
|
|
||||||
mCreateComputePipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_DeviceLost, nullptr,
|
mCreateComputePipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_DeviceLost, nullptr,
|
||||||
"Device lost before callback", mUserData);
|
"Device lost before callback", mUserData);
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateRenderPipelineAsyncTask::CreateRenderPipelineAsyncTask(
|
CreateRenderPipelineAsyncCallbackTask::CreateRenderPipelineAsyncCallbackTask(
|
||||||
Ref<RenderPipelineBase> pipeline,
|
Ref<RenderPipelineBase> pipeline,
|
||||||
std::string errorMessage,
|
std::string errorMessage,
|
||||||
WGPUCreateRenderPipelineAsyncCallback callback,
|
WGPUCreateRenderPipelineAsyncCallback callback,
|
||||||
void* userdata)
|
void* userdata)
|
||||||
: CreatePipelineAsyncTaskBase(errorMessage, userdata),
|
: CreatePipelineAsyncCallbackTaskBase(errorMessage, userdata),
|
||||||
mPipeline(std::move(pipeline)),
|
mPipeline(std::move(pipeline)),
|
||||||
mCreateRenderPipelineAsyncCallback(callback) {
|
mCreateRenderPipelineAsyncCallback(callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateRenderPipelineAsyncTask::Finish() {
|
void CreateRenderPipelineAsyncCallbackTask::Finish() {
|
||||||
ASSERT(mCreateRenderPipelineAsyncCallback != nullptr);
|
ASSERT(mCreateRenderPipelineAsyncCallback != nullptr);
|
||||||
|
|
||||||
if (mPipeline.Get() != nullptr) {
|
if (mPipeline.Get() != nullptr) {
|
||||||
|
@ -88,62 +86,18 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateRenderPipelineAsyncTask::HandleShutDown() {
|
void CreateRenderPipelineAsyncCallbackTask::HandleShutDown() {
|
||||||
ASSERT(mCreateRenderPipelineAsyncCallback != nullptr);
|
ASSERT(mCreateRenderPipelineAsyncCallback != nullptr);
|
||||||
|
|
||||||
mCreateRenderPipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_DeviceDestroyed, nullptr,
|
mCreateRenderPipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_DeviceDestroyed, nullptr,
|
||||||
"Device destroyed before callback", mUserData);
|
"Device destroyed before callback", mUserData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateRenderPipelineAsyncTask::HandleDeviceLoss() {
|
void CreateRenderPipelineAsyncCallbackTask::HandleDeviceLoss() {
|
||||||
ASSERT(mCreateRenderPipelineAsyncCallback != nullptr);
|
ASSERT(mCreateRenderPipelineAsyncCallback != nullptr);
|
||||||
|
|
||||||
mCreateRenderPipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_DeviceLost, nullptr,
|
mCreateRenderPipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_DeviceLost, nullptr,
|
||||||
"Device lost before callback", mUserData);
|
"Device lost before callback", mUserData);
|
||||||
}
|
}
|
||||||
|
|
||||||
CreatePipelineAsyncTracker::CreatePipelineAsyncTracker(DeviceBase* device) : mDevice(device) {
|
|
||||||
}
|
|
||||||
|
|
||||||
CreatePipelineAsyncTracker::~CreatePipelineAsyncTracker() {
|
|
||||||
ASSERT(mCreatePipelineAsyncTasksInFlight.Empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
void CreatePipelineAsyncTracker::TrackTask(std::unique_ptr<CreatePipelineAsyncTaskBase> task,
|
|
||||||
ExecutionSerial serial) {
|
|
||||||
mCreatePipelineAsyncTasksInFlight.Enqueue(std::move(task), serial);
|
|
||||||
mDevice->AddFutureSerial(serial);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CreatePipelineAsyncTracker::Tick(ExecutionSerial finishedSerial) {
|
|
||||||
// If a user calls Queue::Submit inside Create*PipelineAsync, then the device will be
|
|
||||||
// ticked, which in turns ticks the tracker, causing reentrance here. To prevent the
|
|
||||||
// reentrant call from invalidating mCreatePipelineAsyncTasksInFlight while in use by the
|
|
||||||
// first call, we remove the tasks to finish from the queue, update
|
|
||||||
// mCreatePipelineAsyncTasksInFlight, then run the callbacks.
|
|
||||||
std::vector<std::unique_ptr<CreatePipelineAsyncTaskBase>> tasks;
|
|
||||||
for (auto& task : mCreatePipelineAsyncTasksInFlight.IterateUpTo(finishedSerial)) {
|
|
||||||
tasks.push_back(std::move(task));
|
|
||||||
}
|
|
||||||
mCreatePipelineAsyncTasksInFlight.ClearUpTo(finishedSerial);
|
|
||||||
|
|
||||||
for (auto& task : tasks) {
|
|
||||||
task->Finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CreatePipelineAsyncTracker::ClearForShutDown() {
|
|
||||||
for (auto& task : mCreatePipelineAsyncTasksInFlight.IterateAll()) {
|
|
||||||
task->HandleShutDown();
|
|
||||||
}
|
|
||||||
mCreatePipelineAsyncTasksInFlight.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CreatePipelineAsyncTracker::ClearForDeviceLoss() {
|
|
||||||
for (auto& task : mCreatePipelineAsyncTasksInFlight.IterateAll()) {
|
|
||||||
task->HandleDeviceLoss();
|
|
||||||
}
|
|
||||||
mCreatePipelineAsyncTasksInFlight.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
|
@ -0,0 +1,68 @@
|
||||||
|
// Copyright 2020 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef DAWNNATIVE_CREATEPIPELINEASYNCTASK_H_
|
||||||
|
#define DAWNNATIVE_CREATEPIPELINEASYNCTASK_H_
|
||||||
|
|
||||||
|
#include "common/RefCounted.h"
|
||||||
|
#include "dawn/webgpu.h"
|
||||||
|
#include "dawn_native/CallbackTaskManager.h"
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
class ComputePipelineBase;
|
||||||
|
class DeviceBase;
|
||||||
|
class RenderPipelineBase;
|
||||||
|
|
||||||
|
struct CreatePipelineAsyncCallbackTaskBase : CallbackTask {
|
||||||
|
CreatePipelineAsyncCallbackTaskBase(std::string errorMessage, void* userData);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string mErrorMessage;
|
||||||
|
void* mUserData;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CreateComputePipelineAsyncCallbackTask final : CreatePipelineAsyncCallbackTaskBase {
|
||||||
|
CreateComputePipelineAsyncCallbackTask(Ref<ComputePipelineBase> pipeline,
|
||||||
|
std::string errorMessage,
|
||||||
|
WGPUCreateComputePipelineAsyncCallback callback,
|
||||||
|
void* userdata);
|
||||||
|
|
||||||
|
void Finish() final;
|
||||||
|
void HandleShutDown() final;
|
||||||
|
void HandleDeviceLoss() final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ref<ComputePipelineBase> mPipeline;
|
||||||
|
WGPUCreateComputePipelineAsyncCallback mCreateComputePipelineAsyncCallback;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CreateRenderPipelineAsyncCallbackTask final : CreatePipelineAsyncCallbackTaskBase {
|
||||||
|
CreateRenderPipelineAsyncCallbackTask(Ref<RenderPipelineBase> pipeline,
|
||||||
|
std::string errorMessage,
|
||||||
|
WGPUCreateRenderPipelineAsyncCallback callback,
|
||||||
|
void* userdata);
|
||||||
|
|
||||||
|
void Finish() final;
|
||||||
|
void HandleShutDown() final;
|
||||||
|
void HandleDeviceLoss() final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ref<RenderPipelineBase> mPipeline;
|
||||||
|
WGPUCreateRenderPipelineAsyncCallback mCreateRenderPipelineAsyncCallback;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
||||||
|
|
||||||
|
#endif // DAWNNATIVE_CREATEPIPELINEASYNCTASK_H_
|
|
@ -1,93 +0,0 @@
|
||||||
// Copyright 2020 The Dawn Authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#ifndef DAWNNATIVE_CREATEPIPELINEASYNCTRACKER_H_
|
|
||||||
#define DAWNNATIVE_CREATEPIPELINEASYNCTRACKER_H_
|
|
||||||
|
|
||||||
#include "common/RefCounted.h"
|
|
||||||
#include "common/SerialQueue.h"
|
|
||||||
#include "dawn/webgpu.h"
|
|
||||||
#include "dawn_native/IntegerTypes.h"
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace dawn_native {
|
|
||||||
|
|
||||||
class ComputePipelineBase;
|
|
||||||
class DeviceBase;
|
|
||||||
class RenderPipelineBase;
|
|
||||||
|
|
||||||
struct CreatePipelineAsyncTaskBase {
|
|
||||||
CreatePipelineAsyncTaskBase(std::string errorMessage, void* userData);
|
|
||||||
virtual ~CreatePipelineAsyncTaskBase();
|
|
||||||
|
|
||||||
virtual void Finish() = 0;
|
|
||||||
virtual void HandleShutDown() = 0;
|
|
||||||
virtual void HandleDeviceLoss() = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::string mErrorMessage;
|
|
||||||
void* mUserData;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CreateComputePipelineAsyncTask final : public CreatePipelineAsyncTaskBase {
|
|
||||||
CreateComputePipelineAsyncTask(Ref<ComputePipelineBase> pipeline,
|
|
||||||
std::string errorMessage,
|
|
||||||
WGPUCreateComputePipelineAsyncCallback callback,
|
|
||||||
void* userdata);
|
|
||||||
|
|
||||||
void Finish() final;
|
|
||||||
void HandleShutDown() final;
|
|
||||||
void HandleDeviceLoss() final;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ref<ComputePipelineBase> mPipeline;
|
|
||||||
WGPUCreateComputePipelineAsyncCallback mCreateComputePipelineAsyncCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CreateRenderPipelineAsyncTask final : public CreatePipelineAsyncTaskBase {
|
|
||||||
CreateRenderPipelineAsyncTask(Ref<RenderPipelineBase> pipeline,
|
|
||||||
std::string errorMessage,
|
|
||||||
WGPUCreateRenderPipelineAsyncCallback callback,
|
|
||||||
void* userdata);
|
|
||||||
|
|
||||||
void Finish() final;
|
|
||||||
void HandleShutDown() final;
|
|
||||||
void HandleDeviceLoss() final;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ref<RenderPipelineBase> mPipeline;
|
|
||||||
WGPUCreateRenderPipelineAsyncCallback mCreateRenderPipelineAsyncCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CreatePipelineAsyncTracker {
|
|
||||||
public:
|
|
||||||
explicit CreatePipelineAsyncTracker(DeviceBase* device);
|
|
||||||
~CreatePipelineAsyncTracker();
|
|
||||||
|
|
||||||
void TrackTask(std::unique_ptr<CreatePipelineAsyncTaskBase> task, ExecutionSerial serial);
|
|
||||||
void Tick(ExecutionSerial finishedSerial);
|
|
||||||
void ClearForShutDown();
|
|
||||||
void ClearForDeviceLoss();
|
|
||||||
|
|
||||||
private:
|
|
||||||
DeviceBase* mDevice;
|
|
||||||
SerialQueue<ExecutionSerial, std::unique_ptr<CreatePipelineAsyncTaskBase>>
|
|
||||||
mCreatePipelineAsyncTasksInFlight;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dawn_native
|
|
||||||
|
|
||||||
#endif // DAWNNATIVE_CREATEPIPELINEASYNCTRACKER_H_
|
|
|
@ -20,11 +20,12 @@
|
||||||
#include "dawn_native/BindGroup.h"
|
#include "dawn_native/BindGroup.h"
|
||||||
#include "dawn_native/BindGroupLayout.h"
|
#include "dawn_native/BindGroupLayout.h"
|
||||||
#include "dawn_native/Buffer.h"
|
#include "dawn_native/Buffer.h"
|
||||||
|
#include "dawn_native/CallbackTaskManager.h"
|
||||||
#include "dawn_native/CommandBuffer.h"
|
#include "dawn_native/CommandBuffer.h"
|
||||||
#include "dawn_native/CommandEncoder.h"
|
#include "dawn_native/CommandEncoder.h"
|
||||||
#include "dawn_native/CompilationMessages.h"
|
#include "dawn_native/CompilationMessages.h"
|
||||||
#include "dawn_native/ComputePipeline.h"
|
#include "dawn_native/ComputePipeline.h"
|
||||||
#include "dawn_native/CreatePipelineAsyncTracker.h"
|
#include "dawn_native/CreatePipelineAsyncTask.h"
|
||||||
#include "dawn_native/DynamicUploader.h"
|
#include "dawn_native/DynamicUploader.h"
|
||||||
#include "dawn_native/ErrorData.h"
|
#include "dawn_native/ErrorData.h"
|
||||||
#include "dawn_native/ErrorScope.h"
|
#include "dawn_native/ErrorScope.h"
|
||||||
|
@ -125,7 +126,7 @@ namespace dawn_native {
|
||||||
mCaches = std::make_unique<DeviceBase::Caches>();
|
mCaches = std::make_unique<DeviceBase::Caches>();
|
||||||
mErrorScopeStack = std::make_unique<ErrorScopeStack>();
|
mErrorScopeStack = std::make_unique<ErrorScopeStack>();
|
||||||
mDynamicUploader = std::make_unique<DynamicUploader>(this);
|
mDynamicUploader = std::make_unique<DynamicUploader>(this);
|
||||||
mCreatePipelineAsyncTracker = std::make_unique<CreatePipelineAsyncTracker>(this);
|
mCallbackTaskManager = std::make_unique<CallbackTaskManager>();
|
||||||
mDeprecationWarnings = std::make_unique<DeprecationWarnings>();
|
mDeprecationWarnings = std::make_unique<DeprecationWarnings>();
|
||||||
mInternalPipelineStore = std::make_unique<InternalPipelineStore>();
|
mInternalPipelineStore = std::make_unique<InternalPipelineStore>();
|
||||||
mPersistentCache = std::make_unique<PersistentCache>(this);
|
mPersistentCache = std::make_unique<PersistentCache>(this);
|
||||||
|
@ -142,8 +143,11 @@ namespace dawn_native {
|
||||||
void DeviceBase::ShutDownBase() {
|
void DeviceBase::ShutDownBase() {
|
||||||
// Skip handling device facilities if they haven't even been created (or failed doing so)
|
// Skip handling device facilities if they haven't even been created (or failed doing so)
|
||||||
if (mState != State::BeingCreated) {
|
if (mState != State::BeingCreated) {
|
||||||
// Reject all async pipeline creations.
|
// Call all the callbacks immediately as the device is about to shut down.
|
||||||
mCreatePipelineAsyncTracker->ClearForShutDown();
|
auto callbackTasks = mCallbackTaskManager->AcquireCallbackTasks();
|
||||||
|
for (std::unique_ptr<CallbackTask>& callbackTask : callbackTasks) {
|
||||||
|
callbackTask->HandleShutDown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disconnect the device, depending on which state we are currently in.
|
// Disconnect the device, depending on which state we are currently in.
|
||||||
|
@ -188,7 +192,7 @@ namespace dawn_native {
|
||||||
mState = State::Disconnected;
|
mState = State::Disconnected;
|
||||||
|
|
||||||
mDynamicUploader = nullptr;
|
mDynamicUploader = nullptr;
|
||||||
mCreatePipelineAsyncTracker = nullptr;
|
mCallbackTaskManager = nullptr;
|
||||||
mPersistentCache = nullptr;
|
mPersistentCache = nullptr;
|
||||||
|
|
||||||
mEmptyBindGroupLayout = nullptr;
|
mEmptyBindGroupLayout = nullptr;
|
||||||
|
@ -238,7 +242,10 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
|
|
||||||
mQueue->HandleDeviceLoss();
|
mQueue->HandleDeviceLoss();
|
||||||
mCreatePipelineAsyncTracker->ClearForDeviceLoss();
|
auto callbackTasks = mCallbackTaskManager->AcquireCallbackTasks();
|
||||||
|
for (std::unique_ptr<CallbackTask>& callbackTask : callbackTasks) {
|
||||||
|
callbackTask->HandleDeviceLoss();
|
||||||
|
}
|
||||||
|
|
||||||
// Still forward device loss errors to the error scopes so they all reject.
|
// Still forward device loss errors to the error scopes so they all reject.
|
||||||
mErrorScopeStack->HandleError(ToWGPUErrorType(type), message);
|
mErrorScopeStack->HandleError(ToWGPUErrorType(type), message);
|
||||||
|
@ -766,10 +773,10 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<RenderPipelineBase> result = maybeResult.AcquireSuccess();
|
Ref<RenderPipelineBase> result = maybeResult.AcquireSuccess();
|
||||||
std::unique_ptr<CreateRenderPipelineAsyncTask> request =
|
std::unique_ptr<CreateRenderPipelineAsyncCallbackTask> callbackTask =
|
||||||
std::make_unique<CreateRenderPipelineAsyncTask>(std::move(result), "", callback,
|
std::make_unique<CreateRenderPipelineAsyncCallbackTask>(std::move(result), "", callback,
|
||||||
userdata);
|
userdata);
|
||||||
mCreatePipelineAsyncTracker->TrackTask(std::move(request), GetPendingCommandSerial());
|
mCallbackTaskManager->AddCallbackTask(std::move(callbackTask));
|
||||||
}
|
}
|
||||||
RenderBundleEncoder* DeviceBase::APICreateRenderBundleEncoder(
|
RenderBundleEncoder* DeviceBase::APICreateRenderBundleEncoder(
|
||||||
const RenderBundleEncoderDescriptor* descriptor) {
|
const RenderBundleEncoderDescriptor* descriptor) {
|
||||||
|
@ -951,8 +958,19 @@ namespace dawn_native {
|
||||||
// reclaiming resources one tick earlier.
|
// reclaiming resources one tick earlier.
|
||||||
mDynamicUploader->Deallocate(mCompletedSerial);
|
mDynamicUploader->Deallocate(mCompletedSerial);
|
||||||
mQueue->Tick(mCompletedSerial);
|
mQueue->Tick(mCompletedSerial);
|
||||||
|
}
|
||||||
|
|
||||||
mCreatePipelineAsyncTracker->Tick(mCompletedSerial);
|
// We have to check mCallbackTaskManager in every Tick because it is not related to any
|
||||||
|
// global serials.
|
||||||
|
if (!mCallbackTaskManager->IsEmpty()) {
|
||||||
|
// If a user calls Queue::Submit inside the callback, then the device will be ticked,
|
||||||
|
// which in turns ticks the tracker, causing reentrance and dead lock here. To prevent
|
||||||
|
// such reentrant call, we remove all the callback tasks from mCallbackTaskManager,
|
||||||
|
// update mCallbackTaskManager, then call all the callbacks.
|
||||||
|
auto callbackTasks = mCallbackTaskManager->AcquireCallbackTasks();
|
||||||
|
for (std::unique_ptr<CallbackTask>& callbackTask : callbackTasks) {
|
||||||
|
callbackTask->Finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -1158,10 +1176,10 @@ namespace dawn_native {
|
||||||
result = AddOrGetCachedPipeline(resultOrError.AcquireSuccess(), blueprintHash);
|
result = AddOrGetCachedPipeline(resultOrError.AcquireSuccess(), blueprintHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CreateComputePipelineAsyncTask> request =
|
std::unique_ptr<CreateComputePipelineAsyncCallbackTask> callbackTask =
|
||||||
std::make_unique<CreateComputePipelineAsyncTask>(result, errorMessage, callback,
|
std::make_unique<CreateComputePipelineAsyncCallbackTask>(
|
||||||
userdata);
|
std::move(result), errorMessage, callback, userdata);
|
||||||
mCreatePipelineAsyncTracker->TrackTask(std::move(request), GetPendingCommandSerial());
|
mCallbackTaskManager->AddCallbackTask(std::move(callbackTask));
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<Ref<PipelineLayoutBase>> DeviceBase::CreatePipelineLayout(
|
ResultOrError<Ref<PipelineLayoutBase>> DeviceBase::CreatePipelineLayout(
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace dawn_native {
|
||||||
class AttachmentState;
|
class AttachmentState;
|
||||||
class AttachmentStateBlueprint;
|
class AttachmentStateBlueprint;
|
||||||
class BindGroupLayoutBase;
|
class BindGroupLayoutBase;
|
||||||
class CreatePipelineAsyncTracker;
|
class CallbackTaskManager;
|
||||||
class DynamicUploader;
|
class DynamicUploader;
|
||||||
class ErrorScopeStack;
|
class ErrorScopeStack;
|
||||||
class ExternalTextureBase;
|
class ExternalTextureBase;
|
||||||
|
@ -402,7 +402,7 @@ namespace dawn_native {
|
||||||
Ref<BindGroupLayoutBase> mEmptyBindGroupLayout;
|
Ref<BindGroupLayoutBase> mEmptyBindGroupLayout;
|
||||||
|
|
||||||
std::unique_ptr<DynamicUploader> mDynamicUploader;
|
std::unique_ptr<DynamicUploader> mDynamicUploader;
|
||||||
std::unique_ptr<CreatePipelineAsyncTracker> mCreatePipelineAsyncTracker;
|
std::unique_ptr<CallbackTaskManager> mCallbackTaskManager;
|
||||||
Ref<QueueBase> mQueue;
|
Ref<QueueBase> mQueue;
|
||||||
|
|
||||||
struct DeprecationWarnings;
|
struct DeprecationWarnings;
|
||||||
|
|
Loading…
Reference in New Issue