• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 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 "experimental/graphite/src/Gpu.h"
9 
10 #include "experimental/graphite/src/Caps.h"
11 #include "experimental/graphite/src/CommandBuffer.h"
12 #include "experimental/graphite/src/GpuWorkSubmission.h"
13 #include "experimental/graphite/src/ResourceProvider.h"
14 
15 namespace skgpu {
16 
17 // This constant determines how many OutstandingSubmissions are allocated together as a block in
18 // the deque. As such it needs to balance allocating too much memory vs. incurring
19 // allocation/deallocation thrashing. It should roughly correspond to the max number of outstanding
20 // submissions we expect to see.
21 static constexpr int kDefaultOutstandingAllocCnt = 8;
22 
Gpu(sk_sp<const Caps> caps)23 Gpu::Gpu(sk_sp<const Caps> caps)
24     : fOutstandingSubmissions(sizeof(OutstandingSubmission), kDefaultOutstandingAllocCnt)
25     , fCaps(std::move(caps)) {
26     // subclasses create their own subclassed resource provider
27 }
28 
~Gpu()29 Gpu::~Gpu() {
30     // TODO: add disconnect?
31 
32 
33     // TODO: destroyResources instead?
34     // TODO: how do we handle command buffers that haven't been submitted yet?
35     this->checkForFinishedWork(SyncToCpu::kYes);
36     fResourceProvider.reset();
37 }
38 
refCaps() const39 sk_sp<const Caps> Gpu::refCaps() const {
40     return fCaps;
41 }
42 
submit(sk_sp<CommandBuffer> commandBuffer)43 bool Gpu::submit(sk_sp<CommandBuffer> commandBuffer) {
44     if (!commandBuffer) {
45         return false;
46     }
47 
48     if (!commandBuffer->hasWork()) {
49         return true;
50     }
51 
52     return this->onSubmit(std::move(commandBuffer));
53 }
54 
checkForFinishedWork(SyncToCpu sync)55 void Gpu::checkForFinishedWork(SyncToCpu sync) {
56     if (sync == SyncToCpu::kYes) {
57         // wait for the last submission to finish
58         OutstandingSubmission* back = (OutstandingSubmission*)fOutstandingSubmissions.back();
59         if (back) {
60             (*back)->waitUntilFinished(this);
61         }
62     }
63 
64     // Iterate over all the outstanding submissions to see if any have finished. The work
65     // submissions are in order from oldest to newest, so we start at the front to check if they
66     // have finished. If so we pop it off and move onto the next.
67     // Repeat till we find a submission that has not finished yet (and all others afterwards are
68     // also guaranteed to not have finished).
69     OutstandingSubmission* front = (OutstandingSubmission*)fOutstandingSubmissions.front();
70     while (front && (*front)->isFinished()) {
71         // Make sure we remove before deleting as deletion might try to kick off another submit
72         // (though hopefully *not* in Graphite).
73         fOutstandingSubmissions.pop_front();
74         // Since we used placement new we are responsible for calling the destructor manually.
75         front->~OutstandingSubmission();
76         front = (OutstandingSubmission*)fOutstandingSubmissions.front();
77     }
78     SkASSERT(sync == SyncToCpu::kNo || fOutstandingSubmissions.empty());
79 }
80 
81 } // namespace skgpu
82