Flutter Engine
The Flutter Engine
DrawOrder.h
Go to the documentation of this file.
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
12
13namespace 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.
19template<typename Sequence>
21public:
22 static constexpr MonotonicValue First() { return 0; }
23 static constexpr MonotonicValue Last() { return 0xffff; }
24
25 MonotonicValue() = default;
26 MonotonicValue(const MonotonicValue& o) = default;
27
29
30 bool operator< (MonotonicValue o) const { return fIndex < o.fIndex; }
31 bool operator<=(MonotonicValue o) const { return fIndex <= o.fIndex; }
32
33 bool operator> (MonotonicValue o) const { return fIndex > o.fIndex; }
34 bool operator>=(MonotonicValue o) const { return fIndex >= o.fIndex; }
35
36 bool operator==(MonotonicValue o) const { return fIndex == o.fIndex; }
37 bool operator!=(MonotonicValue o) const { return fIndex != o.fIndex; }
38
39 uint16_t bits() const { return fIndex; }
40
41 // Get the next value in the sequence after this one
42 MonotonicValue next() const { return fIndex + 1; }
43
44private:
45 constexpr MonotonicValue(uint16_t index) : fIndex(index) {}
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 */
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 */
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 */
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 */
106public:
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
114 // The first DisjointStencilIndex is reserved to indicate an unassigned stencil set.
116
117 explicit DrawOrder(PaintersDepth originalOrder)
118 : fPaintOrder(kNoIntersection)
119 , fStencilIndex(kUnassigned)
120 , fDepth(originalOrder) {}
121
122 DrawOrder(PaintersDepth originalOrder, CompressedPaintersOrder compressedOrder)
123 : fPaintOrder(compressedOrder)
124 , fStencilIndex(kUnassigned)
125 , fDepth(originalOrder) {}
126
127 CompressedPaintersOrder paintOrder() const { return fPaintOrder; }
128 DisjointStencilIndex stencilIndex() const { return fStencilIndex; }
129 PaintersDepth depth() const { return fDepth; }
130
131 float depthAsFloat() const { return fDepth.bits() / (float) PaintersDepth::Last().bits(); }
132
134 // A draw must be ordered after all previous draws that it depends on
135 CompressedPaintersOrder next = prevDraw.next();
136 if (fPaintOrder < next) {
137 fPaintOrder = next;
138 }
139 return *this;
140 }
141
143 // Stencil usage should only be set once
144 SkASSERT(fStencilIndex == kUnassigned);
145 fStencilIndex = disjointSet;
146 return *this;
147 }
148
149private:
150 CompressedPaintersOrder fPaintOrder;
151 DisjointStencilIndex fStencilIndex;
152 PaintersDepth fDepth;
153};
154
155} // namespace skgpu::graphite
156
157#endif // skgpu_graphite_DrawOrder_DEFINED
static float next(float f)
#define SkASSERT(cond)
Definition: SkAssert.h:116
DrawOrder(PaintersDepth originalOrder)
Definition: DrawOrder.h:117
static constexpr PaintersDepth kClearDepth
Definition: DrawOrder.h:109
DrawOrder(PaintersDepth originalOrder, CompressedPaintersOrder compressedOrder)
Definition: DrawOrder.h:122
static constexpr DisjointStencilIndex kUnassigned
Definition: DrawOrder.h:115
DrawOrder & dependsOnStencil(DisjointStencilIndex disjointSet)
Definition: DrawOrder.h:142
static constexpr CompressedPaintersOrder kNoIntersection
Definition: DrawOrder.h:113
float depthAsFloat() const
Definition: DrawOrder.h:131
DrawOrder & dependsOnPaintersOrder(CompressedPaintersOrder prevDraw)
Definition: DrawOrder.h:133
CompressedPaintersOrder paintOrder() const
Definition: DrawOrder.h:127
PaintersDepth depth() const
Definition: DrawOrder.h:129
DisjointStencilIndex stencilIndex() const
Definition: DrawOrder.h:128
bool operator==(MonotonicValue o) const
Definition: DrawOrder.h:36
MonotonicValue(const MonotonicValue &o)=default
bool operator<=(MonotonicValue o) const
Definition: DrawOrder.h:31
static constexpr MonotonicValue Last()
Definition: DrawOrder.h:23
bool operator<(MonotonicValue o) const
Definition: DrawOrder.h:30
static constexpr MonotonicValue First()
Definition: DrawOrder.h:22
MonotonicValue & operator=(const MonotonicValue &o)=default
bool operator>(MonotonicValue o) const
Definition: DrawOrder.h:33
bool operator!=(MonotonicValue o) const
Definition: DrawOrder.h:37
MonotonicValue next() const
Definition: DrawOrder.h:42
bool operator>=(MonotonicValue o) const
Definition: DrawOrder.h:34