Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/intel/isl/isl_aux_info.c
4547 views
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 */
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
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
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
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
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
257
isl_aux_usage_has_fast_clears(enum isl_aux_usage usage)
258
{
259
return info[usage].fast_clear;
260
}
261
262
bool
263
isl_aux_usage_has_compression(enum isl_aux_usage usage)
264
{
265
return info[usage].compressed;
266
}
267
268