• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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