• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include "isl/isl.h"
25 
26 #ifdef IN_UNIT_TEST
27 /* STATIC_ASSERT is a do { ... } while(0) statement */
static_assert_func(void)28 UNUSED static void static_assert_func(void) {
29    STATIC_ASSERT(ISL_AUX_OP_ASSERT == ((enum isl_aux_op) 0));
30    STATIC_ASSERT(ISL_AUX_STATE_ASSERT == ((enum isl_aux_state) 0));
31 }
32 
33 #undef unreachable
34 #define unreachable(str) return 0
35 
36 #undef assert
37 #define assert(cond) do { \
38    if (!(cond)) { \
39       return 0; \
40    } \
41 } while (0)
42 #endif
43 
44 /* How writes with an isl_aux_usage behave. */
45 enum write_behavior {
46    /* Writes only touch the main surface. */
47    WRITES_ONLY_TOUCH_MAIN = 0,
48 
49    /* Writes using the 3D engine are compressed. */
50    WRITES_COMPRESS,
51 
52    /* Writes using the 3D engine are either compressed or substituted with
53     * fast-cleared blocks.
54     */
55    WRITES_COMPRESS_CLEAR,
56 
57    /* Writes implicitly fully resolve the compression block and write the data
58     * uncompressed into the main surface. The resolved aux blocks are
59     * ambiguated and left in the pass-through state.
60     */
61    WRITES_RESOLVE_AMBIGUATE,
62 };
63 
64 /* A set of features supported by an isl_aux_usage. */
65 struct aux_usage_info {
66 
67    /* How writes affect the surface(s) in use. */
68    enum write_behavior write_behavior;
69 
70    /* Aux supports "real" compression beyond just fast-clears. */
71    bool compressed;
72 
73    /* SW can perform ISL_AUX_OP_FAST_CLEAR. */
74    bool fast_clear;
75 
76    /* SW can perform ISL_AUX_OP_PARTIAL_RESOLVE. */
77    bool partial_resolve;
78 
79    /* Performing ISL_AUX_OP_FULL_RESOLVE includes ISL_AUX_OP_AMBIGUATE. */
80    bool full_resolves_ambiguate;
81 };
82 
83 #define AUX(wb, c, fc, pr, fra, type)                   \
84    [ISL_AUX_USAGE_ ## type] = { WRITES_ ## wb, c, fc, pr, fra},
85 #define Y true
86 #define x false
87 static const struct aux_usage_info info[] = {
88 /*         write_behavior c fc pr fra */
89    AUX(         COMPRESS, Y, Y, x, x, HIZ)
90    AUX(         COMPRESS, Y, Y, x, x, HIZ_CCS)
91    AUX(         COMPRESS, Y, Y, x, x, HIZ_CCS_WT)
92    AUX(         COMPRESS, Y, Y, Y, x, MCS)
93    AUX(         COMPRESS, Y, Y, Y, x, MCS_CCS)
94    AUX(         COMPRESS, Y, Y, Y, Y, CCS_E)
95    AUX(   COMPRESS_CLEAR, Y, Y, Y, Y, GFX12_CCS_E)
96    AUX(RESOLVE_AMBIGUATE, x, Y, x, Y, CCS_D)
97    AUX(RESOLVE_AMBIGUATE, Y, x, x, Y, MC)
98    AUX(         COMPRESS, Y, x, x, Y, STC_CCS)
99 };
100 #undef x
101 #undef Y
102 #undef AUX
103 
104 ASSERTED static bool
aux_state_possible(enum isl_aux_state state,enum isl_aux_usage usage)105 aux_state_possible(enum isl_aux_state state,
106                    enum isl_aux_usage usage)
107 {
108    switch (state) {
109    case ISL_AUX_STATE_CLEAR:
110    case ISL_AUX_STATE_PARTIAL_CLEAR:
111       return info[usage].fast_clear;
112    case ISL_AUX_STATE_COMPRESSED_CLEAR:
113       return info[usage].fast_clear && info[usage].compressed;
114    case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
115       return info[usage].compressed;
116    case ISL_AUX_STATE_RESOLVED:
117    case ISL_AUX_STATE_PASS_THROUGH:
118    case ISL_AUX_STATE_AUX_INVALID:
119       return true;
120 #ifdef IN_UNIT_TEST
121    case ISL_AUX_STATE_ASSERT:
122       break;
123 #endif
124    }
125 
126    unreachable("Invalid aux state.");
127 }
128 
129 enum isl_aux_op
isl_aux_prepare_access(enum isl_aux_state initial_state,enum isl_aux_usage usage,bool fast_clear_supported)130 isl_aux_prepare_access(enum isl_aux_state initial_state,
131                        enum isl_aux_usage usage,
132                        bool fast_clear_supported)
133 {
134    if (usage != ISL_AUX_USAGE_NONE) {
135       UNUSED const enum isl_aux_usage state_superset_usage =
136          usage == ISL_AUX_USAGE_CCS_D ? ISL_AUX_USAGE_CCS_E : usage;
137       assert(aux_state_possible(initial_state, state_superset_usage));
138    }
139    assert(!fast_clear_supported || info[usage].fast_clear);
140 
141    switch (initial_state) {
142    case ISL_AUX_STATE_COMPRESSED_CLEAR:
143       if (!info[usage].compressed)
144          return ISL_AUX_OP_FULL_RESOLVE;
145       FALLTHROUGH;
146    case ISL_AUX_STATE_CLEAR:
147    case ISL_AUX_STATE_PARTIAL_CLEAR:
148       return fast_clear_supported ?
149                 ISL_AUX_OP_NONE :
150              info[usage].partial_resolve ?
151                 ISL_AUX_OP_PARTIAL_RESOLVE : ISL_AUX_OP_FULL_RESOLVE;
152    case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
153       return info[usage].compressed ?
154              ISL_AUX_OP_NONE : ISL_AUX_OP_FULL_RESOLVE;
155    case ISL_AUX_STATE_RESOLVED:
156    case ISL_AUX_STATE_PASS_THROUGH:
157       return ISL_AUX_OP_NONE;
158    case ISL_AUX_STATE_AUX_INVALID:
159       return info[usage].write_behavior == WRITES_ONLY_TOUCH_MAIN ?
160              ISL_AUX_OP_NONE : ISL_AUX_OP_AMBIGUATE;
161 #ifdef IN_UNIT_TEST
162    case ISL_AUX_STATE_ASSERT:
163       break;
164 #endif
165    }
166 
167    unreachable("Invalid aux state.");
168 }
169 
170 enum isl_aux_state
isl_aux_state_transition_aux_op(enum isl_aux_state initial_state,enum isl_aux_usage usage,enum isl_aux_op op)171 isl_aux_state_transition_aux_op(enum isl_aux_state initial_state,
172                                 enum isl_aux_usage usage,
173                                 enum isl_aux_op op)
174 {
175    assert(aux_state_possible(initial_state, usage));
176    assert(usage != ISL_AUX_USAGE_NONE || op == ISL_AUX_OP_NONE);
177 
178    switch (op) {
179    case ISL_AUX_OP_NONE:
180       return initial_state;
181    case ISL_AUX_OP_FAST_CLEAR:
182       assert(info[usage].fast_clear);
183       return ISL_AUX_STATE_CLEAR;
184    case ISL_AUX_OP_PARTIAL_RESOLVE:
185       assert(isl_aux_state_has_valid_aux(initial_state));
186       assert(info[usage].partial_resolve);
187       return initial_state == ISL_AUX_STATE_CLEAR ||
188              initial_state == ISL_AUX_STATE_PARTIAL_CLEAR ||
189              initial_state == ISL_AUX_STATE_COMPRESSED_CLEAR ?
190              ISL_AUX_STATE_COMPRESSED_NO_CLEAR : initial_state;
191    case ISL_AUX_OP_FULL_RESOLVE:
192       assert(isl_aux_state_has_valid_aux(initial_state));
193       return info[usage].full_resolves_ambiguate ||
194              initial_state == ISL_AUX_STATE_PASS_THROUGH ?
195              ISL_AUX_STATE_PASS_THROUGH : ISL_AUX_STATE_RESOLVED;
196    case ISL_AUX_OP_AMBIGUATE:
197       return ISL_AUX_STATE_PASS_THROUGH;
198 #if IN_UNIT_TEST
199    case ISL_AUX_OP_ASSERT:
200       break;
201 #endif
202    }
203 
204    unreachable("Invalid aux op.");
205 }
206 
207 enum isl_aux_state
isl_aux_state_transition_write(enum isl_aux_state initial_state,enum isl_aux_usage usage,bool full_surface)208 isl_aux_state_transition_write(enum isl_aux_state initial_state,
209                                enum isl_aux_usage usage,
210                                bool full_surface)
211 {
212    if (info[usage].write_behavior == WRITES_ONLY_TOUCH_MAIN) {
213       assert(full_surface || isl_aux_state_has_valid_primary(initial_state));
214 
215       return initial_state == ISL_AUX_STATE_PASS_THROUGH ?
216              ISL_AUX_STATE_PASS_THROUGH : ISL_AUX_STATE_AUX_INVALID;
217    }
218 
219    assert(isl_aux_state_has_valid_aux(initial_state));
220    assert(aux_state_possible(initial_state, usage));
221    assert(info[usage].write_behavior == WRITES_COMPRESS ||
222           info[usage].write_behavior == WRITES_COMPRESS_CLEAR ||
223           info[usage].write_behavior == WRITES_RESOLVE_AMBIGUATE);
224 
225    if (full_surface) {
226       return info[usage].write_behavior == WRITES_COMPRESS ?
227                 ISL_AUX_STATE_COMPRESSED_NO_CLEAR :
228              info[usage].write_behavior == WRITES_COMPRESS_CLEAR ?
229                 ISL_AUX_STATE_COMPRESSED_CLEAR : ISL_AUX_STATE_PASS_THROUGH;
230    }
231 
232    switch (initial_state) {
233    case ISL_AUX_STATE_CLEAR:
234    case ISL_AUX_STATE_PARTIAL_CLEAR:
235       return info[usage].write_behavior == WRITES_RESOLVE_AMBIGUATE ?
236              ISL_AUX_STATE_PARTIAL_CLEAR : ISL_AUX_STATE_COMPRESSED_CLEAR;
237    case ISL_AUX_STATE_RESOLVED:
238    case ISL_AUX_STATE_PASS_THROUGH:
239    case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
240       return info[usage].write_behavior == WRITES_COMPRESS ?
241                 ISL_AUX_STATE_COMPRESSED_NO_CLEAR :
242              info[usage].write_behavior == WRITES_COMPRESS_CLEAR ?
243                 ISL_AUX_STATE_COMPRESSED_CLEAR : initial_state;
244    case ISL_AUX_STATE_COMPRESSED_CLEAR:
245    case ISL_AUX_STATE_AUX_INVALID:
246       return initial_state;
247 #ifdef IN_UNIT_TEST
248    case ISL_AUX_STATE_ASSERT:
249       break;
250 #endif
251    }
252 
253    unreachable("Invalid aux state.");
254 }
255 
256 bool
isl_aux_usage_has_fast_clears(enum isl_aux_usage usage)257 isl_aux_usage_has_fast_clears(enum isl_aux_usage usage)
258 {
259    return info[usage].fast_clear;
260 }
261 
262 bool
isl_aux_usage_has_compression(enum isl_aux_usage usage)263 isl_aux_usage_has_compression(enum isl_aux_usage usage)
264 {
265    return info[usage].compressed;
266 }
267