2
* Copyright 2019 Intel Corporation
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:
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
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.
27
/* STATIC_ASSERT is a do { ... } while(0) statement */
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));
34
#define unreachable(str) return 0
37
#define assert(cond) do { \
44
/* How writes with an isl_aux_usage behave. */
46
/* Writes only touch the main surface. */
47
WRITES_ONLY_TOUCH_MAIN = 0,
49
/* Writes using the 3D engine are compressed. */
52
/* Writes using the 3D engine are either compressed or substituted with
53
* fast-cleared blocks.
55
WRITES_COMPRESS_CLEAR,
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.
61
WRITES_RESOLVE_AMBIGUATE,
64
/* A set of features supported by an isl_aux_usage. */
65
struct aux_usage_info {
67
/* How writes affect the surface(s) in use. */
68
enum write_behavior write_behavior;
70
/* Aux supports "real" compression beyond just fast-clears. */
73
/* SW can perform ISL_AUX_OP_FAST_CLEAR. */
76
/* SW can perform ISL_AUX_OP_PARTIAL_RESOLVE. */
79
/* Performing ISL_AUX_OP_FULL_RESOLVE includes ISL_AUX_OP_AMBIGUATE. */
80
bool full_resolves_ambiguate;
83
#define AUX(wb, c, fc, pr, fra, type) \
84
[ISL_AUX_USAGE_ ## type] = { WRITES_ ## wb, c, fc, pr, fra},
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)
105
aux_state_possible(enum isl_aux_state state,
106
enum isl_aux_usage usage)
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:
121
case ISL_AUX_STATE_ASSERT:
126
unreachable("Invalid aux state.");
130
isl_aux_prepare_access(enum isl_aux_state initial_state,
131
enum isl_aux_usage usage,
132
bool fast_clear_supported)
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));
139
assert(!fast_clear_supported || info[usage].fast_clear);
141
switch (initial_state) {
142
case ISL_AUX_STATE_COMPRESSED_CLEAR:
143
if (!info[usage].compressed)
144
return ISL_AUX_OP_FULL_RESOLVE;
146
case ISL_AUX_STATE_CLEAR:
147
case ISL_AUX_STATE_PARTIAL_CLEAR:
148
return fast_clear_supported ?
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;
162
case ISL_AUX_STATE_ASSERT:
167
unreachable("Invalid aux state.");
171
isl_aux_state_transition_aux_op(enum isl_aux_state initial_state,
172
enum isl_aux_usage usage,
175
assert(aux_state_possible(initial_state, usage));
176
assert(usage != ISL_AUX_USAGE_NONE || op == ISL_AUX_OP_NONE);
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;
199
case ISL_AUX_OP_ASSERT:
204
unreachable("Invalid aux op.");
208
isl_aux_state_transition_write(enum isl_aux_state initial_state,
209
enum isl_aux_usage usage,
212
if (info[usage].write_behavior == WRITES_ONLY_TOUCH_MAIN) {
213
assert(full_surface || isl_aux_state_has_valid_primary(initial_state));
215
return initial_state == ISL_AUX_STATE_PASS_THROUGH ?
216
ISL_AUX_STATE_PASS_THROUGH : ISL_AUX_STATE_AUX_INVALID;
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);
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;
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;
248
case ISL_AUX_STATE_ASSERT:
253
unreachable("Invalid aux state.");
257
isl_aux_usage_has_fast_clears(enum isl_aux_usage usage)
259
return info[usage].fast_clear;
263
isl_aux_usage_has_compression(enum isl_aux_usage usage)
265
return info[usage].compressed;