1 /*
2 * Copyright 2022 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "src/gpu/graphite/dawn/DawnQueueManager.h"
9
10 #include "src/gpu/graphite/dawn/DawnAsyncWait.h"
11 #include "src/gpu/graphite/dawn/DawnCommandBuffer.h"
12 #include "src/gpu/graphite/dawn/DawnResourceProvider.h"
13 #include "src/gpu/graphite/dawn/DawnSharedContext.h"
14 #include "src/gpu/graphite/dawn/DawnUtilsPriv.h"
15
16 namespace skgpu::graphite {
17 namespace {
18 // GpuWorkSubmission with AsyncWait. This is useful for wasm where wgpu::Future
19 // is not available yet.
20 class [[maybe_unused]] DawnWorkSubmissionWithAsyncWait final : public GpuWorkSubmission {
21 public:
22 DawnWorkSubmissionWithAsyncWait(std::unique_ptr<CommandBuffer> cmdBuffer,
23 DawnQueueManager* queueManager,
24 const DawnSharedContext* sharedContext);
25
26 private:
27 bool onIsFinished(const SharedContext* sharedContext) override;
28 void onWaitUntilFinished(const SharedContext* sharedContext) override;
29
30 DawnAsyncWait fAsyncWait;
31 };
32
DawnWorkSubmissionWithAsyncWait(std::unique_ptr<CommandBuffer> cmdBuffer,DawnQueueManager * queueManager,const DawnSharedContext * sharedContext)33 DawnWorkSubmissionWithAsyncWait::DawnWorkSubmissionWithAsyncWait(
34 std::unique_ptr<CommandBuffer> cmdBuffer,
35 DawnQueueManager* queueManager,
36 const DawnSharedContext* sharedContext)
37 : GpuWorkSubmission(std::move(cmdBuffer), queueManager), fAsyncWait(sharedContext) {
38 queueManager->dawnQueue().OnSubmittedWorkDone(
39 #if defined(__EMSCRIPTEN__)
40 // This is parameter is being removed:
41 // https://github.com/webgpu-native/webgpu-headers/issues/130
42 /*signalValue=*/0,
43 #endif
44 [](WGPUQueueWorkDoneStatus, void* userData) {
45 auto asyncWaitPtr = static_cast<DawnAsyncWait*>(userData);
46 asyncWaitPtr->signal();
47 },
48 &fAsyncWait);
49 }
50
onIsFinished(const SharedContext *)51 bool DawnWorkSubmissionWithAsyncWait::onIsFinished(const SharedContext*) {
52 return fAsyncWait.yieldAndCheck();
53 }
54
onWaitUntilFinished(const SharedContext *)55 void DawnWorkSubmissionWithAsyncWait::onWaitUntilFinished(const SharedContext*) {
56 fAsyncWait.busyWait();
57 }
58
59 #if !defined(__EMSCRIPTEN__)
60
61 // The version with wgpu::Future. This is not available in wasm yet so we have
62 // to guard behind #if
63 class DawnWorkSubmissionWithFuture final : public GpuWorkSubmission {
64 public:
65 DawnWorkSubmissionWithFuture(std::unique_ptr<CommandBuffer> cmdBuffer,
66 DawnQueueManager* queueManager);
67
68 private:
69 bool onIsFinished(const SharedContext* sharedContext) override;
70 void onWaitUntilFinished(const SharedContext* sharedContext) override;
71
72 wgpu::Future fSubmittedWorkDoneFuture;
73 };
74
DawnWorkSubmissionWithFuture(std::unique_ptr<CommandBuffer> cmdBuffer,DawnQueueManager * queueManager)75 DawnWorkSubmissionWithFuture::DawnWorkSubmissionWithFuture(std::unique_ptr<CommandBuffer> cmdBuffer,
76 DawnQueueManager* queueManager)
77 : GpuWorkSubmission(std::move(cmdBuffer), queueManager) {
78 fSubmittedWorkDoneFuture = queueManager->dawnQueue().OnSubmittedWorkDone(
79 wgpu::CallbackMode::WaitAnyOnly, [](wgpu::QueueWorkDoneStatus) {});
80 }
81
onIsFinished(const SharedContext * sharedContext)82 bool DawnWorkSubmissionWithFuture::onIsFinished(const SharedContext* sharedContext) {
83 wgpu::FutureWaitInfo waitInfo{};
84 waitInfo.future = fSubmittedWorkDoneFuture;
85 const auto& instance = static_cast<const DawnSharedContext*>(sharedContext)
86 ->device()
87 .GetAdapter()
88 .GetInstance();
89 if (instance.WaitAny(1, &waitInfo, /*timeoutNS=*/0) != wgpu::WaitStatus::Success) {
90 return false;
91 }
92
93 return waitInfo.completed;
94 }
95
onWaitUntilFinished(const SharedContext * sharedContext)96 void DawnWorkSubmissionWithFuture::onWaitUntilFinished(const SharedContext* sharedContext) {
97 wgpu::FutureWaitInfo waitInfo{};
98 waitInfo.future = fSubmittedWorkDoneFuture;
99 const auto& instance = static_cast<const DawnSharedContext*>(sharedContext)
100 ->device()
101 .GetAdapter()
102 .GetInstance();
103 [[maybe_unused]] auto status =
104 instance.WaitAny(1, &waitInfo, /*timeoutNS=*/std::numeric_limits<uint64_t>::max());
105 SkASSERT(status == wgpu::WaitStatus::Success);
106 SkASSERT(waitInfo.completed);
107 }
108
109 #endif // !defined(__EMSCRIPTEN__)
110
111 } // namespace
112
DawnQueueManager(wgpu::Queue queue,const SharedContext * sharedContext)113 DawnQueueManager::DawnQueueManager(wgpu::Queue queue, const SharedContext* sharedContext)
114 : QueueManager(sharedContext), fQueue(std::move(queue)) {}
115
tick() const116 void DawnQueueManager::tick() const { this->dawnSharedContext()->tick(); }
117
dawnSharedContext() const118 const DawnSharedContext* DawnQueueManager::dawnSharedContext() const {
119 return static_cast<const DawnSharedContext*>(fSharedContext);
120 }
121
getNewCommandBuffer(ResourceProvider * resourceProvider)122 std::unique_ptr<CommandBuffer> DawnQueueManager::getNewCommandBuffer(
123 ResourceProvider* resourceProvider) {
124 return DawnCommandBuffer::Make(dawnSharedContext(),
125 static_cast<DawnResourceProvider*>(resourceProvider));
126 }
127
onSubmitToGpu()128 QueueManager::OutstandingSubmission DawnQueueManager::onSubmitToGpu() {
129 SkASSERT(fCurrentCommandBuffer);
130 DawnCommandBuffer* dawnCmdBuffer = static_cast<DawnCommandBuffer*>(fCurrentCommandBuffer.get());
131 auto wgpuCmdBuffer = dawnCmdBuffer->finishEncoding();
132 if (!wgpuCmdBuffer) {
133 fCurrentCommandBuffer->callFinishedProcs(/*success=*/false);
134 return nullptr;
135 }
136
137 fQueue.Submit(/*commandCount=*/1, &wgpuCmdBuffer);
138
139 #if defined(__EMSCRIPTEN__)
140 return std::make_unique<DawnWorkSubmissionWithAsyncWait>(
141 std::move(fCurrentCommandBuffer), this, dawnSharedContext());
142 #else
143 return std::make_unique<DawnWorkSubmissionWithFuture>(std::move(fCurrentCommandBuffer), this);
144 #endif
145 }
146
147 #if defined(GRAPHITE_TEST_UTILS)
startCapture()148 void DawnQueueManager::startCapture() {
149 // TODO: Dawn doesn't have capturing feature yet.
150 }
151
stopCapture()152 void DawnQueueManager::stopCapture() {
153 // TODO: Dawn doesn't have capturing feature yet.
154 }
155 #endif
156
157 } // namespace skgpu::graphite
158