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