blob: 145c88a72df8eb7e609263c976846dd193f7f2f2 [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
10// Get offset into buffer that has enough space for size
11// Returns fTotalSize if no space
12size_t GrRingBuffer::getAllocationOffset(size_t size) {
13 // capture current state locally (because fTail could be overwritten by the completion handler)
14 size_t head, tail;
Jim Van Verthc8bc99f2020-07-24 14:48:48 +000015 SkAutoSpinlock lock(fMutex);
Jim Van Verth3eadce22020-06-01 11:34:49 -040016 head = fHead;
17 tail = fTail;
18
19 // The head and tail indices increment without bound, wrapping with overflow,
20 // so we need to mod them down to the actual bounds of the allocation to determine
21 // which blocks are available.
22 size_t modHead = head & (fTotalSize - 1);
23 size_t modTail = tail & (fTotalSize - 1);
24
25 bool full = (head != tail && modHead == modTail);
26
27 if (full) {
28 return fTotalSize;
29 }
30
31 // case 1: free space lies at the beginning and/or the end of the buffer
32 if (modHead >= modTail) {
33 // check for room at the end
34 if (fTotalSize - modHead < size) {
35 // no room at the end, check the beginning
36 if (modTail < size) {
37 // no room at the beginning
38 return fTotalSize;
39 }
40 // we are going to allocate from the beginning, adjust head to '0' position
41 head += fTotalSize - modHead;
42 modHead = 0;
43 }
44 // case 2: free space lies in the middle of the buffer, check for room there
45 } else if (modTail - modHead < size) {
46 // no room in the middle
47 return fTotalSize;
48 }
49
50 fHead = GrAlignTo(head + size, fAlignment);
51 return modHead;
52}
53
54GrRingBuffer::Slice GrRingBuffer::suballocate(size_t size) {
Jim Van Verthc8bc99f2020-07-24 14:48:48 +000055 size_t offset = this->getAllocationOffset(size);
56 if (offset < fTotalSize) {
57 return { fBuffer, offset };
Jim Van Verth3eadce22020-06-01 11:34:49 -040058 }
59
Jim Van Verthc8bc99f2020-07-24 14:48:48 +000060 // Try to grow allocation (old allocation will age out).
61 fTotalSize *= 2;
62 fBuffer = this->createBuffer(fTotalSize);
63 SkASSERT(fBuffer);
64 {
65 SkAutoSpinlock lock(fMutex);
66 fHead = 0;
67 fTail = 0;
68 fGenID++;
69 }
70 offset = this->getAllocationOffset(size);
Jim Van Verth3eadce22020-06-01 11:34:49 -040071 SkASSERT(offset < fTotalSize);
Jim Van Verthc8bc99f2020-07-24 14:48:48 +000072 return { fBuffer, offset };
Jim Van Verth3eadce22020-06-01 11:34:49 -040073}
74
75// used when current command buffer/command list is submitted
Jim Van Verthc8bc99f2020-07-24 14:48:48 +000076GrRingBuffer::SubmitData GrRingBuffer::startSubmit() {
77 SubmitData submitData;
78 SkAutoSpinlock lock(fMutex);
79 submitData.fBuffer = fBuffer;
80 submitData.fLastHead = fHead;
81 submitData.fGenID = fGenID;
82 return submitData;
Jim Van Verth3eadce22020-06-01 11:34:49 -040083}
84
85// used when current command buffer/command list is completed
86void GrRingBuffer::finishSubmit(const GrRingBuffer::SubmitData& submitData) {
Jim Van Verthc8bc99f2020-07-24 14:48:48 +000087 SkAutoSpinlock lock(fMutex);
Jim Van Verth3eadce22020-06-01 11:34:49 -040088 if (submitData.fGenID == fGenID) {
89 fTail = submitData.fLastHead;
90 }
91}