Coverage Report

Created: 2021-08-22 09:07

/src/skia/src/gpu/GrRingBuffer.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
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
#include "src/gpu/GrDirectContextPriv.h"
11
#include "src/gpu/GrGpu.h"
12
#include "src/gpu/GrResourceProvider.h"
13
14
// Get offset into buffer that has enough space for size
15
// Returns fTotalSize if no space
16
0
size_t GrRingBuffer::getAllocationOffset(size_t size) {
17
    // capture current state locally (because fTail could be overwritten by the completion handler)
18
0
    size_t head, tail;
19
0
    head = fHead;
20
0
    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
0
    size_t modHead = head & (fTotalSize - 1);
26
0
    size_t modTail = tail & (fTotalSize - 1);
27
28
0
    bool full = (head != tail && modHead == modTail);
29
30
0
    if (full) {
31
0
        return fTotalSize;
32
0
    }
33
34
    // case 1: free space lies at the beginning and/or the end of the buffer
35
0
    if (modHead >= modTail) {
36
        // check for room at the end
37
0
        if (fTotalSize - modHead < size) {
38
            // no room at the end, check the beginning
39
0
            if (modTail < size) {
40
                // no room at the beginning
41
0
                return fTotalSize;
42
0
            }
43
            // we are going to allocate from the beginning, adjust head to '0' position
44
0
            head += fTotalSize - modHead;
45
0
            modHead = 0;
46
0
        }
47
        // case 2: free space lies in the middle of the buffer, check for room there
48
0
    } else if (modTail - modHead < size) {
49
        // no room in the middle
50
0
        return fTotalSize;
51
0
    }
52
53
0
    fHead = GrAlignTo(head + size, fAlignment);
54
0
    return modHead;
55
0
}
56
57
0
GrRingBuffer::Slice GrRingBuffer::suballocate(size_t size) {
58
0
    fNewAllocation = true;
59
0
    if (fCurrentBuffer) {
60
0
        size_t offset = this->getAllocationOffset(size);
61
0
        if (offset < fTotalSize) {
62
0
            return { fCurrentBuffer.get(), offset };
63
0
        }
64
65
        // Try to grow allocation (old allocation will age out).
66
0
        fTotalSize *= 2;
67
        // Add current buffer to be tracked for next submit.
68
0
        fPreviousBuffers.push_back(std::move(fCurrentBuffer));
69
0
    }
70
71
0
    GrResourceProvider* resourceProvider = fGpu->getContext()->priv().resourceProvider();
72
0
    fCurrentBuffer = resourceProvider->createBuffer(fTotalSize, fType, kDynamic_GrAccessPattern);
73
74
0
    SkASSERT(fCurrentBuffer);
75
0
    fHead = 0;
76
0
    fTail = 0;
77
0
    fGenID++;
78
0
    size_t offset = this->getAllocationOffset(size);
79
0
    SkASSERT(offset < fTotalSize);
80
0
    return { fCurrentBuffer.get(), offset };
81
0
}
Unexecuted instantiation: GrRingBuffer::suballocate(unsigned long)
Unexecuted instantiation: GrRingBuffer::suballocate(unsigned long)
82
83
// used when current command buffer/command list is submitted
84
0
void GrRingBuffer::startSubmit(GrGpu* gpu) {
85
0
    for (unsigned int i = 0; i < fPreviousBuffers.size(); ++i) {
86
0
        fPreviousBuffers[i]->unmap();
87
0
        gpu->takeOwnershipOfBuffer(std::move(fPreviousBuffers[i]));
88
0
    }
89
0
    fPreviousBuffers.clear();
90
91
0
    if (fNewAllocation) {
92
#ifdef SK_BUILD_FOR_MAC
93
        // Since we're using a Managed buffer on MacOS we need to unmap to write back to GPU
94
        // TODO: once we set up persistently mapped UPLOAD buffers on D3D, we can remove the
95
        // platform restriction.
96
        fCurrentBuffer->unmap();
97
#endif
98
0
        SubmitData* submitData = new SubmitData();
99
0
        submitData->fOwner = this;
100
0
        submitData->fLastHead = fHead;
101
0
        submitData->fGenID = fGenID;
102
0
        gpu->addFinishedProc(FinishSubmit, submitData);
103
0
        fNewAllocation = false;
104
0
    }
105
0
}
106
107
// used when current command buffer/command list is completed
108
0
void GrRingBuffer::FinishSubmit(void* finishedContext) {
109
0
    GrRingBuffer::SubmitData* submitData = (GrRingBuffer::SubmitData*)finishedContext;
110
0
    if (submitData && submitData->fOwner && submitData->fGenID == submitData->fOwner->fGenID) {
111
0
        submitData->fOwner->fTail = submitData->fLastHead;
112
0
        submitData->fOwner = nullptr;
113
0
    }
114
0
    delete submitData;
115
0
}