blob: a911c201007de217fec623247a145ce6557be86b [file] [log] [blame]
Jim Van Verth3eadce22020-06-01 11:34:49 -04001/*
2 * Copyright 2020 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/GrRingBuffer.h"
9
Jim Van Verth711b0392020-07-23 16:45:00 -040010#include "src/gpu/GrContextPriv.h"
11#include "src/gpu/GrGpu.h"
12#include "src/gpu/GrResourceProvider.h"
13
Jim Van Verth3eadce22020-06-01 11:34:49 -040014// Get offset into buffer that has enough space for size
15// Returns fTotalSize if no space
16size_t GrRingBuffer::getAllocationOffset(size_t size) {
17 // capture current state locally (because fTail could be overwritten by the completion handler)
18 size_t head, tail;
Jim Van Verth3eadce22020-06-01 11:34:49 -040019 head = fHead;
20 tail = fTail;
21
22 // The head and tail indices increment without bound, wrapping with overflow,
23 // so we need to mod them down to the actual bounds of the allocation to determine
24 // which blocks are available.
25 size_t modHead = head & (fTotalSize - 1);
26 size_t modTail = tail & (fTotalSize - 1);
27
28 bool full = (head != tail && modHead == modTail);
29
30 if (full) {
31 return fTotalSize;
32 }
33
34 // case 1: free space lies at the beginning and/or the end of the buffer
35 if (modHead >= modTail) {
36 // check for room at the end
37 if (fTotalSize - modHead < size) {
38 // no room at the end, check the beginning
39 if (modTail < size) {
40 // no room at the beginning
41 return fTotalSize;
42 }
43 // we are going to allocate from the beginning, adjust head to '0' position
44 head += fTotalSize - modHead;
45 modHead = 0;
46 }
47 // case 2: free space lies in the middle of the buffer, check for room there
48 } else if (modTail - modHead < size) {
49 // no room in the middle
50 return fTotalSize;
51 }
52
53 fHead = GrAlignTo(head + size, fAlignment);
54 return modHead;
55}
56
57GrRingBuffer::Slice GrRingBuffer::suballocate(size_t size) {
Jim Van Verth711b0392020-07-23 16:45:00 -040058 if (fCurrentBuffer) {
59 size_t offset = this->getAllocationOffset(size);
60 if (offset < fTotalSize) {
61 return { fCurrentBuffer.get(), offset };
62 }
63
64 // Try to grow allocation (old allocation will age out).
65 fTotalSize *= 2;
Jim Van Verth3eadce22020-06-01 11:34:49 -040066 }
67
Jim Van Verth711b0392020-07-23 16:45:00 -040068 GrResourceProvider* resourceProvider = fGpu->getContext()->priv().resourceProvider();
69 fCurrentBuffer = resourceProvider->createBuffer(fTotalSize, fType, kDynamic_GrAccessPattern);
70
71 SkASSERT(fCurrentBuffer);
72 fTrackedBuffers.push_back(fCurrentBuffer);
73 fHead = 0;
74 fTail = 0;
75 fGenID++;
76 size_t offset = this->getAllocationOffset(size);
Jim Van Verth3eadce22020-06-01 11:34:49 -040077 SkASSERT(offset < fTotalSize);
Jim Van Verth711b0392020-07-23 16:45:00 -040078 return { fCurrentBuffer.get(), offset };
Jim Van Verth3eadce22020-06-01 11:34:49 -040079}
80
81// used when current command buffer/command list is submitted
Jim Van Verth711b0392020-07-23 16:45:00 -040082void GrRingBuffer::startSubmit(GrRingBuffer::SubmitData* submitData) {
83 submitData->fTrackedBuffers = std::move(fTrackedBuffers);
84 submitData->fLastHead = fHead;
85 submitData->fGenID = fGenID;
86 // add current buffer to be tracked for next submit
87 fTrackedBuffers.push_back(fCurrentBuffer);
Jim Van Verth3eadce22020-06-01 11:34:49 -040088}
89
90// used when current command buffer/command list is completed
91void GrRingBuffer::finishSubmit(const GrRingBuffer::SubmitData& submitData) {
Jim Van Verth3eadce22020-06-01 11:34:49 -040092 if (submitData.fGenID == fGenID) {
93 fTail = submitData.fLastHead;
94 }
95}