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