Coverage Report

Created: 2024-09-14 07:19

/src/skia/src/gpu/graphite/DrawOrder.h
Line
Count
Source (jump to first uncovered line)
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
#ifndef skgpu_graphite_DrawOrder_DEFINED
9
#define skgpu_graphite_DrawOrder_DEFINED
10
11
#include "include/core/SkTypes.h"
12
13
namespace skgpu::graphite {
14
15
// Helper to encapsulate an unsigned number and enforce that it can only be used to create a
16
// monotonic sequence. The template argument 'Sequence' is used to define different sequences
17
// enforced by the compiler. For simplicity, and current needs within Graphite, it's assumed the
18
// entire sequence can be indexed by uint16_t.
19
template<typename Sequence>
20
class MonotonicValue {
21
public:
22
0
    static constexpr MonotonicValue First() { return 0;      }
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::PaintersDepthSequence>::First()
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::CompressedPaintersOrderSequence>::First()
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::DisjointStencilIndexSequence>::First()
23
0
    static constexpr MonotonicValue Last()  { return 0xffff; }
24
25
    MonotonicValue() = default;
26
    MonotonicValue(const MonotonicValue& o) = default;
27
28
    MonotonicValue& operator=(const MonotonicValue& o) = default;
29
30
0
    bool operator< (MonotonicValue o) const { return fIndex <  o.fIndex; }
31
    bool operator<=(MonotonicValue o) const { return fIndex <= o.fIndex; }
32
33
0
    bool operator> (MonotonicValue o) const { return fIndex >  o.fIndex; }
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::CompressedPaintersOrderSequence>::operator>(skgpu::graphite::MonotonicValue<skgpu::graphite::CompressedPaintersOrderSequence>) const
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::PaintersDepthSequence>::operator>(skgpu::graphite::MonotonicValue<skgpu::graphite::PaintersDepthSequence>) const
34
    bool operator>=(MonotonicValue o) const { return fIndex >= o.fIndex; }
35
36
0
    bool operator==(MonotonicValue o) const { return fIndex == o.fIndex; }
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::CompressedPaintersOrderSequence>::operator==(skgpu::graphite::MonotonicValue<skgpu::graphite::CompressedPaintersOrderSequence>) const
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::DisjointStencilIndexSequence>::operator==(skgpu::graphite::MonotonicValue<skgpu::graphite::DisjointStencilIndexSequence>) const
37
0
    bool operator!=(MonotonicValue o) const { return fIndex != o.fIndex; }
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::CompressedPaintersOrderSequence>::operator!=(skgpu::graphite::MonotonicValue<skgpu::graphite::CompressedPaintersOrderSequence>) const
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::DisjointStencilIndexSequence>::operator!=(skgpu::graphite::MonotonicValue<skgpu::graphite::DisjointStencilIndexSequence>) const
38
39
0
    uint16_t bits() const { return fIndex; }
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::PaintersDepthSequence>::bits() const
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::CompressedPaintersOrderSequence>::bits() const
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::DisjointStencilIndexSequence>::bits() const
40
41
    // Get the next value in the sequence after this one
42
0
    MonotonicValue next() const { return fIndex + 1; }
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::CompressedPaintersOrderSequence>::next() const
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::DisjointStencilIndexSequence>::next() const
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::PaintersDepthSequence>::next() const
43
44
private:
45
0
    constexpr MonotonicValue(uint16_t index) : fIndex(index) {}
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::PaintersDepthSequence>::MonotonicValue(unsigned short)
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::CompressedPaintersOrderSequence>::MonotonicValue(unsigned short)
Unexecuted instantiation: skgpu::graphite::MonotonicValue<skgpu::graphite::DisjointStencilIndexSequence>::MonotonicValue(unsigned short)
46
47
    uint16_t fIndex;
48
};
49
50
/**
51
 * CompressedPaintersOrder is an ordinal number that allows draw commands to be re-ordered so long
52
 * as when they are executed, the read/writes to the color|depth attachments respect the original
53
 * painter's order. Logical draws with the same CompressedPaintersOrder can be assumed to be
54
 * executed in any order, however that may have been determined (e.g. BoundsManager or relying on
55
 * a depth test during rasterization).
56
 */
57
struct CompressedPaintersOrderSequence {};
58
using CompressedPaintersOrder = MonotonicValue<CompressedPaintersOrderSequence>;
59
60
/**
61
 * Each DisjointStencilIndex specifies an implicit set of non-overlapping draws. Assuming that two
62
 * draws have the same CompressedPaintersOrder and the same DisjointStencilIndex, their substeps
63
 * for multi-pass rendering (stencil-then-cover, etc.) can be intermingled with each other and
64
 * produce the same results as if each draw's substeps were executed in order before moving on to
65
 * the next draw's.
66
 *
67
 * Ordering within a set can be entirely arbitrary (i.e. all stencil steps can go before all cover
68
 * steps). Ordering between sets is also arbitrary since all draws share the same
69
 * CompressedPaintersOrder, so long as one set is entirely drawn before the next.
70
 *
71
 * Two draws that have different CompressedPaintersOrders but the same DisjointStencilIndex are
72
 * unrelated, they may or may not overlap. The painters order scopes the disjoint sets.
73
 */
74
struct DisjointStencilIndexSequence {};
75
using DisjointStencilIndex = MonotonicValue<DisjointStencilIndexSequence>;
76
77
/**
78
 * Every draw has an associated depth value. The value is constant across the entire draw and is
79
 * not related to any varying Z coordinate induced by a 4x4 transform. The painter's depth is stored
80
 * in the depth attachment and the GREATER depth test is used to reject or accept pixels/samples
81
 * relative to what has already been rendered into the depth attachment. This allows draws that do
82
 * not depend on the previous color to be radically re-ordered relative to their original painter's
83
 * order while producing correct results.
84
 */
85
struct PaintersDepthSequence {};
86
using PaintersDepth = MonotonicValue<PaintersDepthSequence>;
87
88
/**
89
 * DrawOrder aggregates the three separate sequences that Graphite uses to re-order draws and their
90
 * substeps as much as possible while preserving the painter's order semantics of the Skia API.
91
 *
92
 * To build the full DrawOrder for a draw, start with its assigned PaintersDepth (i.e. the original
93
 * painter's order of the draw call). From there, the DrawOrder can be updated to reflect
94
 * dependencies on previous draws, either from depth-only clip draws or because the draw is
95
 * transparent and must blend with the previous color values. Lastly, once the
96
 * CompressedPaintersOrder is finalized, the DrawOrder can be updated to reflect whether or not
97
 * the draw will involve the stencil buffer--and if so, specify the disjoint stencil set it
98
 * belongs to.
99
 *
100
 * The original and effective order that draws are executed in is defined by the PaintersDepth.
101
 * However, the actual execution order is defined by first the CompressedPaintersOrder and then
102
 * the DisjointStencilIndex. This means that draws with much higher depths can be executed earlier
103
 * if painter's order compression allows for it.
104
 */
105
class DrawOrder {
106
public:
107
    // The first PaintersDepth is reserved for clearing the depth attachment; any draw using this
108
    // depth will always fail the depth test.
109
    inline static constexpr PaintersDepth kClearDepth = PaintersDepth::First();
110
    // The first CompressedPaintersOrder is reserved to indicate there is no previous draw that
111
    // must come before a draw.
112
    inline static constexpr
113
            CompressedPaintersOrder kNoIntersection = CompressedPaintersOrder::First();
114
    // The first DisjointStencilIndex is reserved to indicate an unassigned stencil set.
115
    inline static constexpr DisjointStencilIndex kUnassigned = DisjointStencilIndex::First();
116
117
    explicit DrawOrder(PaintersDepth originalOrder)
118
            : fPaintOrder(kNoIntersection)
119
            , fStencilIndex(kUnassigned)
120
0
            , fDepth(originalOrder) {}
121
122
    DrawOrder(PaintersDepth originalOrder, CompressedPaintersOrder compressedOrder)
123
            : fPaintOrder(compressedOrder)
124
            , fStencilIndex(kUnassigned)
125
0
            , fDepth(originalOrder) {}
126
127
0
    CompressedPaintersOrder paintOrder()   const { return fPaintOrder;   }
128
0
    DisjointStencilIndex    stencilIndex() const { return fStencilIndex; }
129
0
    PaintersDepth           depth()        const { return fDepth;        }
130
131
0
    float depthAsFloat() const { return fDepth.bits() / (float) PaintersDepth::Last().bits(); }
132
133
0
    DrawOrder& dependsOnPaintersOrder(CompressedPaintersOrder prevDraw) {
134
        // A draw must be ordered after all previous draws that it depends on
135
0
        CompressedPaintersOrder next = prevDraw.next();
136
0
        if (fPaintOrder < next) {
137
0
            fPaintOrder = next;
138
0
        }
139
0
        return *this;
140
0
    }
141
142
0
    DrawOrder& dependsOnStencil(DisjointStencilIndex disjointSet) {
143
        // Stencil usage should only be set once
144
0
        SkASSERT(fStencilIndex == kUnassigned);
145
0
        fStencilIndex = disjointSet;
146
0
        return *this;
147
0
    }
Unexecuted instantiation: skgpu::graphite::DrawOrder::dependsOnStencil(skgpu::graphite::MonotonicValue<skgpu::graphite::DisjointStencilIndexSequence>)
Unexecuted instantiation: skgpu::graphite::DrawOrder::dependsOnStencil(skgpu::graphite::MonotonicValue<skgpu::graphite::DisjointStencilIndexSequence>)
148
149
private:
150
    CompressedPaintersOrder fPaintOrder;
151
    DisjointStencilIndex    fStencilIndex;
152
    PaintersDepth           fDepth;
153
};
154
155
} // namespace skgpu::graphite
156
157
#endif // skgpu_graphite_DrawOrder_DEFINED