1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright (C) 2022 Collabora, Ltd.
3*61046927SAndroid Build Coastguard Worker *
4*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker *
11*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker * Software.
14*61046927SAndroid Build Coastguard Worker *
15*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20*61046927SAndroid Build Coastguard Worker * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21*61046927SAndroid Build Coastguard Worker * SOFTWARE.
22*61046927SAndroid Build Coastguard Worker */
23*61046927SAndroid Build Coastguard Worker
24*61046927SAndroid Build Coastguard Worker #include "pan_earlyzs.h"
25*61046927SAndroid Build Coastguard Worker #include "panfrost/util/pan_ir.h"
26*61046927SAndroid Build Coastguard Worker
27*61046927SAndroid Build Coastguard Worker /*
28*61046927SAndroid Build Coastguard Worker * Return an "early" mode. If it is known that the depth/stencil tests always
29*61046927SAndroid Build Coastguard Worker * pass (so the shader is always executed), weak early is usually faster than
30*61046927SAndroid Build Coastguard Worker * force early.
31*61046927SAndroid Build Coastguard Worker */
32*61046927SAndroid Build Coastguard Worker static enum pan_earlyzs
best_early_mode(bool zs_always_passes)33*61046927SAndroid Build Coastguard Worker best_early_mode(bool zs_always_passes)
34*61046927SAndroid Build Coastguard Worker {
35*61046927SAndroid Build Coastguard Worker if (zs_always_passes)
36*61046927SAndroid Build Coastguard Worker return PAN_EARLYZS_WEAK_EARLY;
37*61046927SAndroid Build Coastguard Worker else
38*61046927SAndroid Build Coastguard Worker return PAN_EARLYZS_FORCE_EARLY;
39*61046927SAndroid Build Coastguard Worker }
40*61046927SAndroid Build Coastguard Worker
41*61046927SAndroid Build Coastguard Worker /*
42*61046927SAndroid Build Coastguard Worker * Analyze a fragment shader and provided API state to determine the early-ZS
43*61046927SAndroid Build Coastguard Worker * configuration. The order of arguments must match the order of states in the
44*61046927SAndroid Build Coastguard Worker * lookup table, synchronized with pan_earlyzs_get.
45*61046927SAndroid Build Coastguard Worker */
46*61046927SAndroid Build Coastguard Worker static struct pan_earlyzs_state
analyze(const struct pan_shader_info * s,bool writes_zs_or_oq,bool alpha_to_coverage,bool zs_always_passes)47*61046927SAndroid Build Coastguard Worker analyze(const struct pan_shader_info *s, bool writes_zs_or_oq,
48*61046927SAndroid Build Coastguard Worker bool alpha_to_coverage, bool zs_always_passes)
49*61046927SAndroid Build Coastguard Worker {
50*61046927SAndroid Build Coastguard Worker /* If the shader writes depth or stencil, all depth/stencil tests must
51*61046927SAndroid Build Coastguard Worker * be deferred until the value is known after the ZS_EMIT instruction,
52*61046927SAndroid Build Coastguard Worker * if present. ZS_EMIT must precede ATEST, so the value is known when
53*61046927SAndroid Build Coastguard Worker * ATEST executes, justifying the late test/update.
54*61046927SAndroid Build Coastguard Worker */
55*61046927SAndroid Build Coastguard Worker bool shader_writes_zs = (s->fs.writes_depth || s->fs.writes_stencil);
56*61046927SAndroid Build Coastguard Worker bool late_update = shader_writes_zs;
57*61046927SAndroid Build Coastguard Worker bool late_kill = shader_writes_zs;
58*61046927SAndroid Build Coastguard Worker
59*61046927SAndroid Build Coastguard Worker /* Late coverage updates are required if the coverage mask depends on
60*61046927SAndroid Build Coastguard Worker * the results of the shader. Discards are implemented as coverage mask
61*61046927SAndroid Build Coastguard Worker * updates and must be considered. Strictly, depth/stencil writes may
62*61046927SAndroid Build Coastguard Worker * also update the coverage mask, but these already force late updates.
63*61046927SAndroid Build Coastguard Worker */
64*61046927SAndroid Build Coastguard Worker bool late_coverage =
65*61046927SAndroid Build Coastguard Worker s->fs.writes_coverage || s->fs.can_discard || alpha_to_coverage;
66*61046927SAndroid Build Coastguard Worker
67*61046927SAndroid Build Coastguard Worker /* Late coverage mask updates may affect the value written to the
68*61046927SAndroid Build Coastguard Worker * depth/stencil buffer (if a pixel is discarded entirely). However,
69*61046927SAndroid Build Coastguard Worker * they do not affect depth/stencil testing. So they may only matter if
70*61046927SAndroid Build Coastguard Worker * depth or stencil is written.
71*61046927SAndroid Build Coastguard Worker *
72*61046927SAndroid Build Coastguard Worker * That dependency does mean late coverage mask updates require late
73*61046927SAndroid Build Coastguard Worker * depth/stencil updates.
74*61046927SAndroid Build Coastguard Worker *
75*61046927SAndroid Build Coastguard Worker * Similarly, occlusion queries count samples that pass the
76*61046927SAndroid Build Coastguard Worker * depth/stencil tests, so occlusion queries with late coverage also
77*61046927SAndroid Build Coastguard Worker * require a late update.
78*61046927SAndroid Build Coastguard Worker */
79*61046927SAndroid Build Coastguard Worker late_update |= (late_coverage && writes_zs_or_oq);
80*61046927SAndroid Build Coastguard Worker
81*61046927SAndroid Build Coastguard Worker /* Side effects require late depth/stencil tests to ensure the shader
82*61046927SAndroid Build Coastguard Worker * isn't killed before the side effects execute.
83*61046927SAndroid Build Coastguard Worker */
84*61046927SAndroid Build Coastguard Worker late_kill |= s->writes_global;
85*61046927SAndroid Build Coastguard Worker
86*61046927SAndroid Build Coastguard Worker /* Finally, the shader may override and force early fragment tests */
87*61046927SAndroid Build Coastguard Worker late_update &= !s->fs.early_fragment_tests;
88*61046927SAndroid Build Coastguard Worker late_kill &= !s->fs.early_fragment_tests;
89*61046927SAndroid Build Coastguard Worker
90*61046927SAndroid Build Coastguard Worker /* Collect results */
91*61046927SAndroid Build Coastguard Worker enum pan_earlyzs early_mode = best_early_mode(zs_always_passes);
92*61046927SAndroid Build Coastguard Worker
93*61046927SAndroid Build Coastguard Worker return (struct pan_earlyzs_state){
94*61046927SAndroid Build Coastguard Worker .update = late_update ? PAN_EARLYZS_FORCE_LATE : early_mode,
95*61046927SAndroid Build Coastguard Worker .kill = late_kill ? PAN_EARLYZS_FORCE_LATE : early_mode,
96*61046927SAndroid Build Coastguard Worker };
97*61046927SAndroid Build Coastguard Worker }
98*61046927SAndroid Build Coastguard Worker
99*61046927SAndroid Build Coastguard Worker /*
100*61046927SAndroid Build Coastguard Worker * Analyze a fragment shader to determine all possible early-ZS configurations.
101*61046927SAndroid Build Coastguard Worker * Returns a lookup table of configurations indexed by the API state.
102*61046927SAndroid Build Coastguard Worker */
103*61046927SAndroid Build Coastguard Worker struct pan_earlyzs_lut
pan_earlyzs_analyze(const struct pan_shader_info * s)104*61046927SAndroid Build Coastguard Worker pan_earlyzs_analyze(const struct pan_shader_info *s)
105*61046927SAndroid Build Coastguard Worker {
106*61046927SAndroid Build Coastguard Worker struct pan_earlyzs_lut lut;
107*61046927SAndroid Build Coastguard Worker
108*61046927SAndroid Build Coastguard Worker for (unsigned v0 = 0; v0 < 2; ++v0) {
109*61046927SAndroid Build Coastguard Worker for (unsigned v1 = 0; v1 < 2; ++v1) {
110*61046927SAndroid Build Coastguard Worker for (unsigned v2 = 0; v2 < 2; ++v2)
111*61046927SAndroid Build Coastguard Worker lut.states[v0][v1][v2] = analyze(s, v0, v1, v2);
112*61046927SAndroid Build Coastguard Worker }
113*61046927SAndroid Build Coastguard Worker }
114*61046927SAndroid Build Coastguard Worker
115*61046927SAndroid Build Coastguard Worker return lut;
116*61046927SAndroid Build Coastguard Worker }
117