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)23Gpu::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()29Gpu::~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() const39sk_sp<const Caps> Gpu::refCaps() const { 40 return fCaps; 41 } 42 submit(sk_sp<CommandBuffer> commandBuffer)43bool 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)55void 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