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