1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2021 Google
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 DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include <assert.h>
25bf215546Sopenharmony_ci#include <stdbool.h>
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "nir/nir_builder.h"
28bf215546Sopenharmony_ci#include "radv_meta.h"
29bf215546Sopenharmony_ci#include "radv_private.h"
30bf215546Sopenharmony_ci#include "sid.h"
31bf215546Sopenharmony_ci#include "vk_format.h"
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci/* Based on
34bf215546Sopenharmony_ci * https://github.com/Themaister/Granite/blob/master/assets/shaders/decode/etc2.comp
35bf215546Sopenharmony_ci * https://github.com/Themaister/Granite/blob/master/assets/shaders/decode/eac.comp
36bf215546Sopenharmony_ci *
37bf215546Sopenharmony_ci * With some differences:
38bf215546Sopenharmony_ci *  - Use the vk format to do all the settings.
39bf215546Sopenharmony_ci *  - Combine the ETC2 and EAC shaders.
40bf215546Sopenharmony_ci *  - Since we combined the above, reuse the function for the ETC2 A8 component.
41bf215546Sopenharmony_ci *  - the EAC shader doesn't do SNORM correctly, so this has that fixed.
42bf215546Sopenharmony_ci */
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_cistatic nir_ssa_def *
45bf215546Sopenharmony_ciflip_endian(nir_builder *b, nir_ssa_def *src, unsigned cnt)
46bf215546Sopenharmony_ci{
47bf215546Sopenharmony_ci   nir_ssa_def *v[2];
48bf215546Sopenharmony_ci   for (unsigned i = 0; i < cnt; ++i) {
49bf215546Sopenharmony_ci      nir_ssa_def *intermediate[4];
50bf215546Sopenharmony_ci      nir_ssa_def *chan = cnt == 1 ? src : nir_channel(b, src, i);
51bf215546Sopenharmony_ci      for (unsigned j = 0; j < 4; ++j)
52bf215546Sopenharmony_ci         intermediate[j] = nir_ubfe_imm(b, chan, 8 * j, 8);
53bf215546Sopenharmony_ci      v[i] = nir_ior(
54bf215546Sopenharmony_ci         b, nir_ior(b, nir_ishl_imm(b, intermediate[0], 24), nir_ishl_imm(b, intermediate[1], 16)),
55bf215546Sopenharmony_ci         nir_ior(b, nir_ishl_imm(b, intermediate[2], 8), nir_ishl_imm(b, intermediate[3], 0)));
56bf215546Sopenharmony_ci   }
57bf215546Sopenharmony_ci   return cnt == 1 ? v[0] : nir_vec(b, v, cnt);
58bf215546Sopenharmony_ci}
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_cistatic nir_ssa_def *
61bf215546Sopenharmony_cietc1_color_modifier_lookup(nir_builder *b, nir_ssa_def *x, nir_ssa_def *y)
62bf215546Sopenharmony_ci{
63bf215546Sopenharmony_ci   const unsigned table[8][2] = {{2, 8},   {5, 17},  {9, 29},   {13, 42},
64bf215546Sopenharmony_ci                                 {18, 60}, {24, 80}, {33, 106}, {47, 183}};
65bf215546Sopenharmony_ci   nir_ssa_def *upper = nir_ieq_imm(b, y, 1);
66bf215546Sopenharmony_ci   nir_ssa_def *result = NULL;
67bf215546Sopenharmony_ci   for (unsigned i = 0; i < 8; ++i) {
68bf215546Sopenharmony_ci      nir_ssa_def *tmp =
69bf215546Sopenharmony_ci         nir_bcsel(b, upper, nir_imm_int(b, table[i][1]), nir_imm_int(b, table[i][0]));
70bf215546Sopenharmony_ci      if (result)
71bf215546Sopenharmony_ci         result = nir_bcsel(b, nir_ieq_imm(b, x, i), tmp, result);
72bf215546Sopenharmony_ci      else
73bf215546Sopenharmony_ci         result = tmp;
74bf215546Sopenharmony_ci   }
75bf215546Sopenharmony_ci   return result;
76bf215546Sopenharmony_ci}
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_cistatic nir_ssa_def *
79bf215546Sopenharmony_cietc2_distance_lookup(nir_builder *b, nir_ssa_def *x)
80bf215546Sopenharmony_ci{
81bf215546Sopenharmony_ci   const unsigned table[8] = {3, 6, 11, 16, 23, 32, 41, 64};
82bf215546Sopenharmony_ci   nir_ssa_def *result = NULL;
83bf215546Sopenharmony_ci   for (unsigned i = 0; i < 8; ++i) {
84bf215546Sopenharmony_ci      if (result)
85bf215546Sopenharmony_ci         result = nir_bcsel(b, nir_ieq_imm(b, x, i), nir_imm_int(b, table[i]), result);
86bf215546Sopenharmony_ci      else
87bf215546Sopenharmony_ci         result = nir_imm_int(b, table[i]);
88bf215546Sopenharmony_ci   }
89bf215546Sopenharmony_ci   return result;
90bf215546Sopenharmony_ci}
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_cistatic nir_ssa_def *
93bf215546Sopenharmony_cietc1_alpha_modifier_lookup(nir_builder *b, nir_ssa_def *x, nir_ssa_def *y)
94bf215546Sopenharmony_ci{
95bf215546Sopenharmony_ci   const unsigned table[16] = {0xe852, 0xc962, 0xc741, 0xc531, 0xb752, 0xa862, 0xa763, 0xa742,
96bf215546Sopenharmony_ci                               0x9751, 0x9741, 0x9731, 0x9641, 0x9632, 0x9210, 0x8753, 0x8642};
97bf215546Sopenharmony_ci   nir_ssa_def *result = NULL;
98bf215546Sopenharmony_ci   for (unsigned i = 0; i < 16; ++i) {
99bf215546Sopenharmony_ci      nir_ssa_def *tmp = nir_imm_int(b, table[i]);
100bf215546Sopenharmony_ci      if (result)
101bf215546Sopenharmony_ci         result = nir_bcsel(b, nir_ieq_imm(b, x, i), tmp, result);
102bf215546Sopenharmony_ci      else
103bf215546Sopenharmony_ci         result = tmp;
104bf215546Sopenharmony_ci   }
105bf215546Sopenharmony_ci   return nir_ubfe(b, result, nir_imul_imm(b, y, 4), nir_imm_int(b, 4));
106bf215546Sopenharmony_ci}
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_cistatic nir_ssa_def *
109bf215546Sopenharmony_cietc_extend(nir_builder *b, nir_ssa_def *v, int bits)
110bf215546Sopenharmony_ci{
111bf215546Sopenharmony_ci   if (bits == 4)
112bf215546Sopenharmony_ci      return nir_imul_imm(b, v, 0x11);
113bf215546Sopenharmony_ci   return nir_ior(b, nir_ishl_imm(b, v, 8 - bits), nir_ushr_imm(b, v, bits - (8 - bits)));
114bf215546Sopenharmony_ci}
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_cistatic nir_ssa_def *
117bf215546Sopenharmony_cidecode_etc2_alpha(struct nir_builder *b, nir_ssa_def *alpha_payload, nir_ssa_def *linear_pixel,
118bf215546Sopenharmony_ci                  bool eac, nir_ssa_def *is_signed)
119bf215546Sopenharmony_ci{
120bf215546Sopenharmony_ci   alpha_payload = flip_endian(b, alpha_payload, 2);
121bf215546Sopenharmony_ci   nir_ssa_def *alpha_x = nir_channel(b, alpha_payload, 1);
122bf215546Sopenharmony_ci   nir_ssa_def *alpha_y = nir_channel(b, alpha_payload, 0);
123bf215546Sopenharmony_ci   nir_ssa_def *bit_offset = nir_isub_imm(b, 45, nir_imul_imm(b, linear_pixel, 3));
124bf215546Sopenharmony_ci   nir_ssa_def *base = nir_ubfe_imm(b, alpha_y, 24, 8);
125bf215546Sopenharmony_ci   nir_ssa_def *multiplier = nir_ubfe_imm(b, alpha_y, 20, 4);
126bf215546Sopenharmony_ci   nir_ssa_def *table = nir_ubfe_imm(b, alpha_y, 16, 4);
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   if (eac) {
129bf215546Sopenharmony_ci      nir_ssa_def *signed_base = nir_ibfe_imm(b, alpha_y, 24, 8);
130bf215546Sopenharmony_ci      signed_base = nir_imul_imm(b, signed_base, 8);
131bf215546Sopenharmony_ci      base = nir_iadd_imm(b, nir_imul_imm(b, base, 8), 4);
132bf215546Sopenharmony_ci      base = nir_bcsel(b, is_signed, signed_base, base);
133bf215546Sopenharmony_ci      multiplier = nir_imax(b, nir_imul_imm(b, multiplier, 8), nir_imm_int(b, 1));
134bf215546Sopenharmony_ci   }
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci   nir_ssa_def *lsb_index =
137bf215546Sopenharmony_ci      nir_ubfe(b, nir_bcsel(b, nir_uge(b, bit_offset, nir_imm_int(b, 32)), alpha_y, alpha_x),
138bf215546Sopenharmony_ci               nir_iand_imm(b, bit_offset, 31), nir_imm_int(b, 2));
139bf215546Sopenharmony_ci   bit_offset = nir_iadd_imm(b, bit_offset, 2);
140bf215546Sopenharmony_ci   nir_ssa_def *msb =
141bf215546Sopenharmony_ci      nir_ubfe(b, nir_bcsel(b, nir_uge(b, bit_offset, nir_imm_int(b, 32)), alpha_y, alpha_x),
142bf215546Sopenharmony_ci               nir_iand_imm(b, bit_offset, 31), nir_imm_int(b, 1));
143bf215546Sopenharmony_ci   nir_ssa_def *mod =
144bf215546Sopenharmony_ci      nir_ixor(b, etc1_alpha_modifier_lookup(b, table, lsb_index), nir_iadd_imm(b, msb, -1));
145bf215546Sopenharmony_ci   nir_ssa_def *a = nir_iadd(b, base, nir_imul(b, mod, multiplier));
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_ci   nir_ssa_def *low_bound = nir_imm_int(b, 0);
148bf215546Sopenharmony_ci   nir_ssa_def *high_bound = nir_imm_int(b, 255);
149bf215546Sopenharmony_ci   nir_ssa_def *final_mult = nir_imm_float(b, 1 / 255.0);
150bf215546Sopenharmony_ci   if (eac) {
151bf215546Sopenharmony_ci      low_bound = nir_bcsel(b, is_signed, nir_imm_int(b, -1023), low_bound);
152bf215546Sopenharmony_ci      high_bound = nir_bcsel(b, is_signed, nir_imm_int(b, 1023), nir_imm_int(b, 2047));
153bf215546Sopenharmony_ci      final_mult =
154bf215546Sopenharmony_ci         nir_bcsel(b, is_signed, nir_imm_float(b, 1 / 1023.0), nir_imm_float(b, 1 / 2047.0));
155bf215546Sopenharmony_ci   }
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   return nir_fmul(b, nir_i2f32(b, nir_iclamp(b, a, low_bound, high_bound)), final_mult);
158bf215546Sopenharmony_ci}
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_cistatic nir_shader *
161bf215546Sopenharmony_cibuild_shader(struct radv_device *dev)
162bf215546Sopenharmony_ci{
163bf215546Sopenharmony_ci   const struct glsl_type *sampler_type_2d =
164bf215546Sopenharmony_ci      glsl_sampler_type(GLSL_SAMPLER_DIM_2D, false, true, GLSL_TYPE_FLOAT);
165bf215546Sopenharmony_ci   const struct glsl_type *sampler_type_3d =
166bf215546Sopenharmony_ci      glsl_sampler_type(GLSL_SAMPLER_DIM_3D, false, false, GLSL_TYPE_FLOAT);
167bf215546Sopenharmony_ci   const struct glsl_type *img_type_2d =
168bf215546Sopenharmony_ci      glsl_image_type(GLSL_SAMPLER_DIM_2D, true, GLSL_TYPE_FLOAT);
169bf215546Sopenharmony_ci   const struct glsl_type *img_type_3d =
170bf215546Sopenharmony_ci      glsl_image_type(GLSL_SAMPLER_DIM_3D, false, GLSL_TYPE_FLOAT);
171bf215546Sopenharmony_ci   nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_COMPUTE, "meta_decode_etc");
172bf215546Sopenharmony_ci   b.shader->info.workgroup_size[0] = 8;
173bf215546Sopenharmony_ci   b.shader->info.workgroup_size[1] = 8;
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_ci   nir_variable *input_img_2d =
176bf215546Sopenharmony_ci      nir_variable_create(b.shader, nir_var_uniform, sampler_type_2d, "s_tex_2d");
177bf215546Sopenharmony_ci   input_img_2d->data.descriptor_set = 0;
178bf215546Sopenharmony_ci   input_img_2d->data.binding = 0;
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci   nir_variable *input_img_3d =
181bf215546Sopenharmony_ci      nir_variable_create(b.shader, nir_var_uniform, sampler_type_3d, "s_tex_3d");
182bf215546Sopenharmony_ci   input_img_2d->data.descriptor_set = 0;
183bf215546Sopenharmony_ci   input_img_2d->data.binding = 0;
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci   nir_variable *output_img_2d =
186bf215546Sopenharmony_ci      nir_variable_create(b.shader, nir_var_image, img_type_2d, "out_img_2d");
187bf215546Sopenharmony_ci   output_img_2d->data.descriptor_set = 0;
188bf215546Sopenharmony_ci   output_img_2d->data.binding = 1;
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci   nir_variable *output_img_3d =
191bf215546Sopenharmony_ci      nir_variable_create(b.shader, nir_var_image, img_type_3d, "out_img_3d");
192bf215546Sopenharmony_ci   output_img_3d->data.descriptor_set = 0;
193bf215546Sopenharmony_ci   output_img_3d->data.binding = 1;
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci   nir_ssa_def *global_id = get_global_ids(&b, 3);
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci   nir_ssa_def *consts = nir_load_push_constant(&b, 4, 32, nir_imm_int(&b, 0), .range = 16);
198bf215546Sopenharmony_ci   nir_ssa_def *consts2 =
199bf215546Sopenharmony_ci      nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 0), .base = 0, .range = 4);
200bf215546Sopenharmony_ci   nir_ssa_def *offset = nir_channels(&b, consts, 7);
201bf215546Sopenharmony_ci   nir_ssa_def *format = nir_channel(&b, consts, 3);
202bf215546Sopenharmony_ci   nir_ssa_def *image_type = nir_channel(&b, consts2, 0);
203bf215546Sopenharmony_ci   nir_ssa_def *is_3d = nir_ieq_imm(&b, image_type, VK_IMAGE_TYPE_3D);
204bf215546Sopenharmony_ci   nir_ssa_def *coord = nir_iadd(&b, global_id, offset);
205bf215546Sopenharmony_ci   nir_ssa_def *src_coord =
206bf215546Sopenharmony_ci      nir_vec3(&b, nir_ushr_imm(&b, nir_channel(&b, coord, 0), 2),
207bf215546Sopenharmony_ci               nir_ushr_imm(&b, nir_channel(&b, coord, 1), 2), nir_channel(&b, coord, 2));
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci   nir_variable *payload_var =
210bf215546Sopenharmony_ci      nir_variable_create(b.shader, nir_var_shader_temp, glsl_vec4_type(), "payload");
211bf215546Sopenharmony_ci   nir_push_if(&b, is_3d);
212bf215546Sopenharmony_ci   {
213bf215546Sopenharmony_ci      nir_ssa_def *tex_deref = &nir_build_deref_var(&b, input_img_3d)->dest.ssa;
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci      nir_tex_instr *tex = nir_tex_instr_create(b.shader, 3);
216bf215546Sopenharmony_ci      tex->sampler_dim = GLSL_SAMPLER_DIM_3D;
217bf215546Sopenharmony_ci      tex->op = nir_texop_txf;
218bf215546Sopenharmony_ci      tex->src[0].src_type = nir_tex_src_coord;
219bf215546Sopenharmony_ci      tex->src[0].src = nir_src_for_ssa(src_coord);
220bf215546Sopenharmony_ci      tex->src[1].src_type = nir_tex_src_lod;
221bf215546Sopenharmony_ci      tex->src[1].src = nir_src_for_ssa(nir_imm_int(&b, 0));
222bf215546Sopenharmony_ci      tex->src[2].src_type = nir_tex_src_texture_deref;
223bf215546Sopenharmony_ci      tex->src[2].src = nir_src_for_ssa(tex_deref);
224bf215546Sopenharmony_ci      tex->dest_type = nir_type_uint32;
225bf215546Sopenharmony_ci      tex->is_array = false;
226bf215546Sopenharmony_ci      tex->coord_components = 3;
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci      nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, "tex");
229bf215546Sopenharmony_ci      nir_builder_instr_insert(&b, &tex->instr);
230bf215546Sopenharmony_ci      nir_store_var(&b, payload_var, &tex->dest.ssa, 0xf);
231bf215546Sopenharmony_ci   }
232bf215546Sopenharmony_ci   nir_push_else(&b, NULL);
233bf215546Sopenharmony_ci   {
234bf215546Sopenharmony_ci      nir_ssa_def *tex_deref = &nir_build_deref_var(&b, input_img_2d)->dest.ssa;
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_ci      nir_tex_instr *tex = nir_tex_instr_create(b.shader, 3);
237bf215546Sopenharmony_ci      tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
238bf215546Sopenharmony_ci      tex->op = nir_texop_txf;
239bf215546Sopenharmony_ci      tex->src[0].src_type = nir_tex_src_coord;
240bf215546Sopenharmony_ci      tex->src[0].src = nir_src_for_ssa(src_coord);
241bf215546Sopenharmony_ci      tex->src[1].src_type = nir_tex_src_lod;
242bf215546Sopenharmony_ci      tex->src[1].src = nir_src_for_ssa(nir_imm_int(&b, 0));
243bf215546Sopenharmony_ci      tex->src[2].src_type = nir_tex_src_texture_deref;
244bf215546Sopenharmony_ci      tex->src[2].src = nir_src_for_ssa(tex_deref);
245bf215546Sopenharmony_ci      tex->dest_type = nir_type_uint32;
246bf215546Sopenharmony_ci      tex->is_array = true;
247bf215546Sopenharmony_ci      tex->coord_components = 3;
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_ci      nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, "tex");
250bf215546Sopenharmony_ci      nir_builder_instr_insert(&b, &tex->instr);
251bf215546Sopenharmony_ci      nir_store_var(&b, payload_var, &tex->dest.ssa, 0xf);
252bf215546Sopenharmony_ci   }
253bf215546Sopenharmony_ci   nir_pop_if(&b, NULL);
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci   nir_ssa_def *pixel_coord = nir_iand_imm(&b, nir_channels(&b, coord, 3), 3);
256bf215546Sopenharmony_ci   nir_ssa_def *linear_pixel = nir_iadd(&b, nir_imul_imm(&b, nir_channel(&b, pixel_coord, 0), 4),
257bf215546Sopenharmony_ci                                        nir_channel(&b, pixel_coord, 1));
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci   nir_ssa_def *payload = nir_load_var(&b, payload_var);
260bf215546Sopenharmony_ci   nir_variable *color =
261bf215546Sopenharmony_ci      nir_variable_create(b.shader, nir_var_shader_temp, glsl_vec4_type(), "color");
262bf215546Sopenharmony_ci   nir_store_var(&b, color, nir_imm_vec4(&b, 1.0, 0.0, 0.0, 1.0), 0xf);
263bf215546Sopenharmony_ci   nir_push_if(&b, nir_ilt(&b, format, nir_imm_int(&b, VK_FORMAT_EAC_R11_UNORM_BLOCK)));
264bf215546Sopenharmony_ci   {
265bf215546Sopenharmony_ci      nir_ssa_def *alpha_bits_8 =
266bf215546Sopenharmony_ci         nir_ige(&b, format, nir_imm_int(&b, VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK));
267bf215546Sopenharmony_ci      nir_ssa_def *alpha_bits_1 =
268bf215546Sopenharmony_ci         nir_iand(&b, nir_ige(&b, format, nir_imm_int(&b, VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK)),
269bf215546Sopenharmony_ci                  nir_ilt(&b, format, nir_imm_int(&b, VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK)));
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci      nir_ssa_def *color_payload =
272bf215546Sopenharmony_ci         nir_bcsel(&b, alpha_bits_8, nir_channels(&b, payload, 0xC), nir_channels(&b, payload, 3));
273bf215546Sopenharmony_ci      color_payload = flip_endian(&b, color_payload, 2);
274bf215546Sopenharmony_ci      nir_ssa_def *color_y = nir_channel(&b, color_payload, 0);
275bf215546Sopenharmony_ci      nir_ssa_def *color_x = nir_channel(&b, color_payload, 1);
276bf215546Sopenharmony_ci      nir_ssa_def *flip = nir_test_mask(&b, color_y, 1);
277bf215546Sopenharmony_ci      nir_ssa_def *subblock = nir_ushr_imm(
278bf215546Sopenharmony_ci         &b, nir_bcsel(&b, flip, nir_channel(&b, pixel_coord, 1), nir_channel(&b, pixel_coord, 0)),
279bf215546Sopenharmony_ci         1);
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci      nir_variable *punchthrough =
282bf215546Sopenharmony_ci         nir_variable_create(b.shader, nir_var_shader_temp, glsl_bool_type(), "punchthrough");
283bf215546Sopenharmony_ci      nir_ssa_def *punchthrough_init =
284bf215546Sopenharmony_ci         nir_iand(&b, alpha_bits_1, nir_inot(&b, nir_test_mask(&b, color_y, 2)));
285bf215546Sopenharmony_ci      nir_store_var(&b, punchthrough, punchthrough_init, 0x1);
286bf215546Sopenharmony_ci
287bf215546Sopenharmony_ci      nir_variable *etc1_compat =
288bf215546Sopenharmony_ci         nir_variable_create(b.shader, nir_var_shader_temp, glsl_bool_type(), "etc1_compat");
289bf215546Sopenharmony_ci      nir_store_var(&b, etc1_compat, nir_imm_bool(&b, false), 0x1);
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci      nir_variable *alpha_result =
292bf215546Sopenharmony_ci         nir_variable_create(b.shader, nir_var_shader_temp, glsl_float_type(), "alpha_result");
293bf215546Sopenharmony_ci      nir_push_if(&b, alpha_bits_8);
294bf215546Sopenharmony_ci      {
295bf215546Sopenharmony_ci         nir_store_var(
296bf215546Sopenharmony_ci            &b, alpha_result,
297bf215546Sopenharmony_ci            decode_etc2_alpha(&b, nir_channels(&b, payload, 3), linear_pixel, false, NULL), 1);
298bf215546Sopenharmony_ci      }
299bf215546Sopenharmony_ci      nir_push_else(&b, NULL);
300bf215546Sopenharmony_ci      {
301bf215546Sopenharmony_ci         nir_store_var(&b, alpha_result, nir_imm_float(&b, 1.0), 1);
302bf215546Sopenharmony_ci      }
303bf215546Sopenharmony_ci      nir_pop_if(&b, NULL);
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci      const struct glsl_type *uvec3_type = glsl_vector_type(GLSL_TYPE_UINT, 3);
306bf215546Sopenharmony_ci      nir_variable *rgb_result =
307bf215546Sopenharmony_ci         nir_variable_create(b.shader, nir_var_shader_temp, uvec3_type, "rgb_result");
308bf215546Sopenharmony_ci      nir_variable *base_rgb =
309bf215546Sopenharmony_ci         nir_variable_create(b.shader, nir_var_shader_temp, uvec3_type, "base_rgb");
310bf215546Sopenharmony_ci      nir_store_var(&b, rgb_result, nir_imm_ivec3(&b, 255, 0, 0), 0x7);
311bf215546Sopenharmony_ci
312bf215546Sopenharmony_ci      nir_ssa_def *msb =
313bf215546Sopenharmony_ci         nir_iand_imm(&b, nir_ushr(&b, color_x, nir_iadd_imm(&b, linear_pixel, 15)), 2);
314bf215546Sopenharmony_ci      nir_ssa_def *lsb = nir_iand_imm(&b, nir_ushr(&b, color_x, linear_pixel), 1);
315bf215546Sopenharmony_ci
316bf215546Sopenharmony_ci      nir_push_if(
317bf215546Sopenharmony_ci         &b, nir_iand(&b, nir_inot(&b, alpha_bits_1), nir_inot(&b, nir_test_mask(&b, color_y, 2))));
318bf215546Sopenharmony_ci      {
319bf215546Sopenharmony_ci         nir_store_var(&b, etc1_compat, nir_imm_bool(&b, true), 1);
320bf215546Sopenharmony_ci         nir_ssa_def *tmp[3];
321bf215546Sopenharmony_ci         for (unsigned i = 0; i < 3; ++i)
322bf215546Sopenharmony_ci            tmp[i] = etc_extend(
323bf215546Sopenharmony_ci               &b,
324bf215546Sopenharmony_ci               nir_iand_imm(&b,
325bf215546Sopenharmony_ci                            nir_ushr(&b, color_y,
326bf215546Sopenharmony_ci                                     nir_isub_imm(&b, 28 - 8 * i, nir_imul_imm(&b, subblock, 4))),
327bf215546Sopenharmony_ci                            0xf),
328bf215546Sopenharmony_ci               4);
329bf215546Sopenharmony_ci         nir_store_var(&b, base_rgb, nir_vec(&b, tmp, 3), 0x7);
330bf215546Sopenharmony_ci      }
331bf215546Sopenharmony_ci      nir_push_else(&b, NULL);
332bf215546Sopenharmony_ci      {
333bf215546Sopenharmony_ci         nir_ssa_def *rb = nir_ubfe_imm(&b, color_y, 27, 5);
334bf215546Sopenharmony_ci         nir_ssa_def *rd = nir_ibfe_imm(&b, color_y, 24, 3);
335bf215546Sopenharmony_ci         nir_ssa_def *gb = nir_ubfe_imm(&b, color_y, 19, 5);
336bf215546Sopenharmony_ci         nir_ssa_def *gd = nir_ibfe_imm(&b, color_y, 16, 3);
337bf215546Sopenharmony_ci         nir_ssa_def *bb = nir_ubfe_imm(&b, color_y, 11, 5);
338bf215546Sopenharmony_ci         nir_ssa_def *bd = nir_ibfe_imm(&b, color_y, 8, 3);
339bf215546Sopenharmony_ci         nir_ssa_def *r1 = nir_iadd(&b, rb, rd);
340bf215546Sopenharmony_ci         nir_ssa_def *g1 = nir_iadd(&b, gb, gd);
341bf215546Sopenharmony_ci         nir_ssa_def *b1 = nir_iadd(&b, bb, bd);
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci         nir_push_if(&b, nir_ult(&b, nir_imm_int(&b, 31), r1));
344bf215546Sopenharmony_ci         {
345bf215546Sopenharmony_ci            nir_ssa_def *r0 = nir_ior(&b, nir_ubfe_imm(&b, color_y, 24, 2),
346bf215546Sopenharmony_ci                                      nir_ishl_imm(&b, nir_ubfe_imm(&b, color_y, 27, 2), 2));
347bf215546Sopenharmony_ci            nir_ssa_def *g0 = nir_ubfe_imm(&b, color_y, 20, 4);
348bf215546Sopenharmony_ci            nir_ssa_def *b0 = nir_ubfe_imm(&b, color_y, 16, 4);
349bf215546Sopenharmony_ci            nir_ssa_def *r2 = nir_ubfe_imm(&b, color_y, 12, 4);
350bf215546Sopenharmony_ci            nir_ssa_def *g2 = nir_ubfe_imm(&b, color_y, 8, 4);
351bf215546Sopenharmony_ci            nir_ssa_def *b2 = nir_ubfe_imm(&b, color_y, 4, 4);
352bf215546Sopenharmony_ci            nir_ssa_def *da = nir_ior(&b, nir_ishl_imm(&b, nir_ubfe_imm(&b, color_y, 2, 2), 1),
353bf215546Sopenharmony_ci                                      nir_iand_imm(&b, color_y, 1));
354bf215546Sopenharmony_ci            nir_ssa_def *dist = etc2_distance_lookup(&b, da);
355bf215546Sopenharmony_ci            nir_ssa_def *index = nir_ior(&b, lsb, msb);
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_ci            nir_store_var(&b, punchthrough,
358bf215546Sopenharmony_ci                          nir_iand(&b, nir_load_var(&b, punchthrough),
359bf215546Sopenharmony_ci                                   nir_ieq_imm(&b, nir_iadd(&b, lsb, msb), 2)),
360bf215546Sopenharmony_ci                          0x1);
361bf215546Sopenharmony_ci            nir_push_if(&b, nir_ieq_imm(&b, index, 0));
362bf215546Sopenharmony_ci            {
363bf215546Sopenharmony_ci               nir_store_var(&b, rgb_result, etc_extend(&b, nir_vec3(&b, r0, g0, b0), 4), 0x7);
364bf215546Sopenharmony_ci            }
365bf215546Sopenharmony_ci            nir_push_else(&b, NULL);
366bf215546Sopenharmony_ci            {
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_ci               nir_ssa_def *tmp = nir_iadd(&b, etc_extend(&b, nir_vec3(&b, r2, g2, b2), 4),
369bf215546Sopenharmony_ci                                           nir_imul(&b, dist, nir_isub_imm(&b, 2, index)));
370bf215546Sopenharmony_ci               nir_store_var(&b, rgb_result, tmp, 0x7);
371bf215546Sopenharmony_ci            }
372bf215546Sopenharmony_ci            nir_pop_if(&b, NULL);
373bf215546Sopenharmony_ci         }
374bf215546Sopenharmony_ci         nir_push_else(&b, NULL);
375bf215546Sopenharmony_ci         nir_push_if(&b, nir_ult(&b, nir_imm_int(&b, 31), g1));
376bf215546Sopenharmony_ci         {
377bf215546Sopenharmony_ci            nir_ssa_def *r0 = nir_ubfe_imm(&b, color_y, 27, 4);
378bf215546Sopenharmony_ci            nir_ssa_def *g0 = nir_ior(&b, nir_ishl_imm(&b, nir_ubfe_imm(&b, color_y, 24, 3), 1),
379bf215546Sopenharmony_ci                                      nir_iand_imm(&b, nir_ushr_imm(&b, color_y, 20), 1));
380bf215546Sopenharmony_ci            nir_ssa_def *b0 = nir_ior(&b, nir_ubfe_imm(&b, color_y, 15, 3),
381bf215546Sopenharmony_ci                                      nir_iand_imm(&b, nir_ushr_imm(&b, color_y, 16), 8));
382bf215546Sopenharmony_ci            nir_ssa_def *r2 = nir_ubfe_imm(&b, color_y, 11, 4);
383bf215546Sopenharmony_ci            nir_ssa_def *g2 = nir_ubfe_imm(&b, color_y, 7, 4);
384bf215546Sopenharmony_ci            nir_ssa_def *b2 = nir_ubfe_imm(&b, color_y, 3, 4);
385bf215546Sopenharmony_ci            nir_ssa_def *da = nir_iand_imm(&b, color_y, 4);
386bf215546Sopenharmony_ci            nir_ssa_def *db = nir_iand_imm(&b, color_y, 1);
387bf215546Sopenharmony_ci            nir_ssa_def *d = nir_iadd(&b, da, nir_imul_imm(&b, db, 2));
388bf215546Sopenharmony_ci            nir_ssa_def *d0 =
389bf215546Sopenharmony_ci               nir_iadd(&b, nir_ishl_imm(&b, r0, 16), nir_iadd(&b, nir_ishl_imm(&b, g0, 8), b0));
390bf215546Sopenharmony_ci            nir_ssa_def *d2 =
391bf215546Sopenharmony_ci               nir_iadd(&b, nir_ishl_imm(&b, r2, 16), nir_iadd(&b, nir_ishl_imm(&b, g2, 8), b2));
392bf215546Sopenharmony_ci            d = nir_bcsel(&b, nir_uge(&b, d0, d2), nir_iadd_imm(&b, d, 1), d);
393bf215546Sopenharmony_ci            nir_ssa_def *dist = etc2_distance_lookup(&b, d);
394bf215546Sopenharmony_ci            nir_ssa_def *base = nir_bcsel(&b, nir_ine_imm(&b, msb, 0), nir_vec3(&b, r2, g2, b2),
395bf215546Sopenharmony_ci                                          nir_vec3(&b, r0, g0, b0));
396bf215546Sopenharmony_ci            base = etc_extend(&b, base, 4);
397bf215546Sopenharmony_ci            base = nir_iadd(&b, base,
398bf215546Sopenharmony_ci                            nir_imul(&b, dist, nir_isub_imm(&b, 1, nir_imul_imm(&b, lsb, 2))));
399bf215546Sopenharmony_ci            nir_store_var(&b, rgb_result, base, 0x7);
400bf215546Sopenharmony_ci            nir_store_var(&b, punchthrough,
401bf215546Sopenharmony_ci                          nir_iand(&b, nir_load_var(&b, punchthrough),
402bf215546Sopenharmony_ci                                   nir_ieq_imm(&b, nir_iadd(&b, lsb, msb), 2)),
403bf215546Sopenharmony_ci                          0x1);
404bf215546Sopenharmony_ci         }
405bf215546Sopenharmony_ci         nir_push_else(&b, NULL);
406bf215546Sopenharmony_ci         nir_push_if(&b, nir_ult(&b, nir_imm_int(&b, 31), b1));
407bf215546Sopenharmony_ci         {
408bf215546Sopenharmony_ci            nir_ssa_def *r0 = nir_ubfe_imm(&b, color_y, 25, 6);
409bf215546Sopenharmony_ci            nir_ssa_def *g0 = nir_ior(&b, nir_ubfe_imm(&b, color_y, 17, 6),
410bf215546Sopenharmony_ci                                      nir_iand_imm(&b, nir_ushr_imm(&b, color_y, 18), 0x40));
411bf215546Sopenharmony_ci            nir_ssa_def *b0 =
412bf215546Sopenharmony_ci               nir_ior(&b, nir_ishl_imm(&b, nir_ubfe_imm(&b, color_y, 11, 2), 3),
413bf215546Sopenharmony_ci                       nir_ior(&b, nir_iand_imm(&b, nir_ushr_imm(&b, color_y, 11), 0x20),
414bf215546Sopenharmony_ci                               nir_ubfe_imm(&b, color_y, 7, 3)));
415bf215546Sopenharmony_ci            nir_ssa_def *rh = nir_ior(&b, nir_iand_imm(&b, color_y, 1),
416bf215546Sopenharmony_ci                                      nir_ishl_imm(&b, nir_ubfe_imm(&b, color_y, 2, 5), 1));
417bf215546Sopenharmony_ci            nir_ssa_def *rv = nir_ubfe_imm(&b, color_x, 13, 6);
418bf215546Sopenharmony_ci            nir_ssa_def *gh = nir_ubfe_imm(&b, color_x, 25, 7);
419bf215546Sopenharmony_ci            nir_ssa_def *gv = nir_ubfe_imm(&b, color_x, 6, 7);
420bf215546Sopenharmony_ci            nir_ssa_def *bh = nir_ubfe_imm(&b, color_x, 19, 6);
421bf215546Sopenharmony_ci            nir_ssa_def *bv = nir_ubfe_imm(&b, color_x, 0, 6);
422bf215546Sopenharmony_ci
423bf215546Sopenharmony_ci            r0 = etc_extend(&b, r0, 6);
424bf215546Sopenharmony_ci            g0 = etc_extend(&b, g0, 7);
425bf215546Sopenharmony_ci            b0 = etc_extend(&b, b0, 6);
426bf215546Sopenharmony_ci            rh = etc_extend(&b, rh, 6);
427bf215546Sopenharmony_ci            rv = etc_extend(&b, rv, 6);
428bf215546Sopenharmony_ci            gh = etc_extend(&b, gh, 7);
429bf215546Sopenharmony_ci            gv = etc_extend(&b, gv, 7);
430bf215546Sopenharmony_ci            bh = etc_extend(&b, bh, 6);
431bf215546Sopenharmony_ci            bv = etc_extend(&b, bv, 6);
432bf215546Sopenharmony_ci
433bf215546Sopenharmony_ci            nir_ssa_def *rgb = nir_vec3(&b, r0, g0, b0);
434bf215546Sopenharmony_ci            nir_ssa_def *dx = nir_imul(&b, nir_isub(&b, nir_vec3(&b, rh, gh, bh), rgb),
435bf215546Sopenharmony_ci                                       nir_channel(&b, pixel_coord, 0));
436bf215546Sopenharmony_ci            nir_ssa_def *dy = nir_imul(&b, nir_isub(&b, nir_vec3(&b, rv, gv, bv), rgb),
437bf215546Sopenharmony_ci                                       nir_channel(&b, pixel_coord, 1));
438bf215546Sopenharmony_ci            rgb = nir_iadd(&b, rgb, nir_ishr_imm(&b, nir_iadd_imm(&b, nir_iadd(&b, dx, dy), 2), 2));
439bf215546Sopenharmony_ci            nir_store_var(&b, rgb_result, rgb, 0x7);
440bf215546Sopenharmony_ci            nir_store_var(&b, punchthrough, nir_imm_bool(&b, false), 0x1);
441bf215546Sopenharmony_ci         }
442bf215546Sopenharmony_ci         nir_push_else(&b, NULL);
443bf215546Sopenharmony_ci         {
444bf215546Sopenharmony_ci            nir_store_var(&b, etc1_compat, nir_imm_bool(&b, true), 1);
445bf215546Sopenharmony_ci            nir_ssa_def *subblock_b = nir_ine_imm(&b, subblock, 0);
446bf215546Sopenharmony_ci            nir_ssa_def *tmp[] = {
447bf215546Sopenharmony_ci               nir_bcsel(&b, subblock_b, r1, rb),
448bf215546Sopenharmony_ci               nir_bcsel(&b, subblock_b, g1, gb),
449bf215546Sopenharmony_ci               nir_bcsel(&b, subblock_b, b1, bb),
450bf215546Sopenharmony_ci            };
451bf215546Sopenharmony_ci            nir_store_var(&b, base_rgb, etc_extend(&b, nir_vec(&b, tmp, 3), 5), 0x7);
452bf215546Sopenharmony_ci         }
453bf215546Sopenharmony_ci         nir_pop_if(&b, NULL);
454bf215546Sopenharmony_ci         nir_pop_if(&b, NULL);
455bf215546Sopenharmony_ci         nir_pop_if(&b, NULL);
456bf215546Sopenharmony_ci      }
457bf215546Sopenharmony_ci      nir_pop_if(&b, NULL);
458bf215546Sopenharmony_ci      nir_push_if(&b, nir_load_var(&b, etc1_compat));
459bf215546Sopenharmony_ci      {
460bf215546Sopenharmony_ci         nir_ssa_def *etc1_table_index = nir_ubfe(
461bf215546Sopenharmony_ci            &b, color_y, nir_isub_imm(&b, 5, nir_imul_imm(&b, subblock, 3)), nir_imm_int(&b, 3));
462bf215546Sopenharmony_ci         nir_ssa_def *sgn = nir_isub_imm(&b, 1, msb);
463bf215546Sopenharmony_ci         sgn = nir_bcsel(&b, nir_load_var(&b, punchthrough), nir_imul(&b, sgn, lsb), sgn);
464bf215546Sopenharmony_ci         nir_store_var(&b, punchthrough,
465bf215546Sopenharmony_ci                       nir_iand(&b, nir_load_var(&b, punchthrough),
466bf215546Sopenharmony_ci                                nir_ieq_imm(&b, nir_iadd(&b, lsb, msb), 2)),
467bf215546Sopenharmony_ci                       0x1);
468bf215546Sopenharmony_ci         nir_ssa_def *off =
469bf215546Sopenharmony_ci            nir_imul(&b, etc1_color_modifier_lookup(&b, etc1_table_index, lsb), sgn);
470bf215546Sopenharmony_ci         nir_ssa_def *result = nir_iadd(&b, nir_load_var(&b, base_rgb), off);
471bf215546Sopenharmony_ci         nir_store_var(&b, rgb_result, result, 0x7);
472bf215546Sopenharmony_ci      }
473bf215546Sopenharmony_ci      nir_pop_if(&b, NULL);
474bf215546Sopenharmony_ci      nir_push_if(&b, nir_load_var(&b, punchthrough));
475bf215546Sopenharmony_ci      {
476bf215546Sopenharmony_ci         nir_store_var(&b, alpha_result, nir_imm_float(&b, 0), 0x1);
477bf215546Sopenharmony_ci         nir_store_var(&b, rgb_result, nir_imm_ivec3(&b, 0, 0, 0), 0x7);
478bf215546Sopenharmony_ci      }
479bf215546Sopenharmony_ci      nir_pop_if(&b, NULL);
480bf215546Sopenharmony_ci      nir_ssa_def *col[4];
481bf215546Sopenharmony_ci      for (unsigned i = 0; i < 3; ++i)
482bf215546Sopenharmony_ci         col[i] = nir_fdiv(&b, nir_i2f32(&b, nir_channel(&b, nir_load_var(&b, rgb_result), i)),
483bf215546Sopenharmony_ci                           nir_imm_float(&b, 255.0));
484bf215546Sopenharmony_ci      col[3] = nir_load_var(&b, alpha_result);
485bf215546Sopenharmony_ci      nir_store_var(&b, color, nir_vec(&b, col, 4), 0xf);
486bf215546Sopenharmony_ci   }
487bf215546Sopenharmony_ci   nir_push_else(&b, NULL);
488bf215546Sopenharmony_ci   { /* EAC */
489bf215546Sopenharmony_ci      nir_ssa_def *is_signed = nir_ior(&b, nir_ieq_imm(&b, format, VK_FORMAT_EAC_R11_SNORM_BLOCK),
490bf215546Sopenharmony_ci                                       nir_ieq_imm(&b, format, VK_FORMAT_EAC_R11G11_SNORM_BLOCK));
491bf215546Sopenharmony_ci      nir_ssa_def *val[4];
492bf215546Sopenharmony_ci      for (int i = 0; i < 2; ++i) {
493bf215546Sopenharmony_ci         val[i] = decode_etc2_alpha(&b, nir_channels(&b, payload, 3 << (2 * i)), linear_pixel, true,
494bf215546Sopenharmony_ci                                    is_signed);
495bf215546Sopenharmony_ci      }
496bf215546Sopenharmony_ci      val[2] = nir_imm_float(&b, 0.0);
497bf215546Sopenharmony_ci      val[3] = nir_imm_float(&b, 1.0);
498bf215546Sopenharmony_ci      nir_store_var(&b, color, nir_vec(&b, val, 4), 0xf);
499bf215546Sopenharmony_ci   }
500bf215546Sopenharmony_ci   nir_pop_if(&b, NULL);
501bf215546Sopenharmony_ci
502bf215546Sopenharmony_ci   nir_ssa_def *outval = nir_load_var(&b, color);
503bf215546Sopenharmony_ci   nir_ssa_def *img_coord = nir_vec4(&b, nir_channel(&b, coord, 0), nir_channel(&b, coord, 1),
504bf215546Sopenharmony_ci                                     nir_channel(&b, coord, 2), nir_ssa_undef(&b, 1, 32));
505bf215546Sopenharmony_ci
506bf215546Sopenharmony_ci   nir_push_if(&b, is_3d);
507bf215546Sopenharmony_ci   {
508bf215546Sopenharmony_ci      nir_image_deref_store(&b, &nir_build_deref_var(&b, output_img_3d)->dest.ssa, img_coord,
509bf215546Sopenharmony_ci                            nir_ssa_undef(&b, 1, 32), outval, nir_imm_int(&b, 0),
510bf215546Sopenharmony_ci                            .image_dim = GLSL_SAMPLER_DIM_3D);
511bf215546Sopenharmony_ci   }
512bf215546Sopenharmony_ci   nir_push_else(&b, NULL);
513bf215546Sopenharmony_ci   {
514bf215546Sopenharmony_ci      nir_image_deref_store(&b, &nir_build_deref_var(&b, output_img_2d)->dest.ssa, img_coord,
515bf215546Sopenharmony_ci                            nir_ssa_undef(&b, 1, 32), outval, nir_imm_int(&b, 0),
516bf215546Sopenharmony_ci                            .image_dim = GLSL_SAMPLER_DIM_2D, .image_array = true);
517bf215546Sopenharmony_ci   }
518bf215546Sopenharmony_ci   nir_pop_if(&b, NULL);
519bf215546Sopenharmony_ci   return b.shader;
520bf215546Sopenharmony_ci}
521bf215546Sopenharmony_ci
522bf215546Sopenharmony_cistatic VkResult
523bf215546Sopenharmony_cicreate_layout(struct radv_device *device)
524bf215546Sopenharmony_ci{
525bf215546Sopenharmony_ci   VkResult result;
526bf215546Sopenharmony_ci   VkDescriptorSetLayoutCreateInfo ds_create_info = {
527bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
528bf215546Sopenharmony_ci      .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,
529bf215546Sopenharmony_ci      .bindingCount = 2,
530bf215546Sopenharmony_ci      .pBindings = (VkDescriptorSetLayoutBinding[]){
531bf215546Sopenharmony_ci         {.binding = 0,
532bf215546Sopenharmony_ci          .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
533bf215546Sopenharmony_ci          .descriptorCount = 1,
534bf215546Sopenharmony_ci          .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
535bf215546Sopenharmony_ci          .pImmutableSamplers = NULL},
536bf215546Sopenharmony_ci         {.binding = 1,
537bf215546Sopenharmony_ci          .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
538bf215546Sopenharmony_ci          .descriptorCount = 1,
539bf215546Sopenharmony_ci          .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
540bf215546Sopenharmony_ci          .pImmutableSamplers = NULL},
541bf215546Sopenharmony_ci      }};
542bf215546Sopenharmony_ci
543bf215546Sopenharmony_ci   result = radv_CreateDescriptorSetLayout(radv_device_to_handle(device), &ds_create_info,
544bf215546Sopenharmony_ci                                           &device->meta_state.alloc,
545bf215546Sopenharmony_ci                                           &device->meta_state.etc_decode.ds_layout);
546bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
547bf215546Sopenharmony_ci      goto fail;
548bf215546Sopenharmony_ci
549bf215546Sopenharmony_ci   VkPipelineLayoutCreateInfo pl_create_info = {
550bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
551bf215546Sopenharmony_ci      .setLayoutCount = 1,
552bf215546Sopenharmony_ci      .pSetLayouts = &device->meta_state.etc_decode.ds_layout,
553bf215546Sopenharmony_ci      .pushConstantRangeCount = 1,
554bf215546Sopenharmony_ci      .pPushConstantRanges = &(VkPushConstantRange){VK_SHADER_STAGE_COMPUTE_BIT, 0, 20},
555bf215546Sopenharmony_ci   };
556bf215546Sopenharmony_ci
557bf215546Sopenharmony_ci   result =
558bf215546Sopenharmony_ci      radv_CreatePipelineLayout(radv_device_to_handle(device), &pl_create_info,
559bf215546Sopenharmony_ci                                &device->meta_state.alloc, &device->meta_state.etc_decode.p_layout);
560bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
561bf215546Sopenharmony_ci      goto fail;
562bf215546Sopenharmony_ci   return VK_SUCCESS;
563bf215546Sopenharmony_cifail:
564bf215546Sopenharmony_ci   return result;
565bf215546Sopenharmony_ci}
566bf215546Sopenharmony_ci
567bf215546Sopenharmony_cistatic VkResult
568bf215546Sopenharmony_cicreate_decode_pipeline(struct radv_device *device, VkPipeline *pipeline)
569bf215546Sopenharmony_ci{
570bf215546Sopenharmony_ci   VkResult result;
571bf215546Sopenharmony_ci
572bf215546Sopenharmony_ci   mtx_lock(&device->meta_state.mtx);
573bf215546Sopenharmony_ci   if (*pipeline) {
574bf215546Sopenharmony_ci      mtx_unlock(&device->meta_state.mtx);
575bf215546Sopenharmony_ci      return VK_SUCCESS;
576bf215546Sopenharmony_ci   }
577bf215546Sopenharmony_ci
578bf215546Sopenharmony_ci   nir_shader *cs = build_shader(device);
579bf215546Sopenharmony_ci
580bf215546Sopenharmony_ci   /* compute shader */
581bf215546Sopenharmony_ci
582bf215546Sopenharmony_ci   VkPipelineShaderStageCreateInfo pipeline_shader_stage = {
583bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
584bf215546Sopenharmony_ci      .stage = VK_SHADER_STAGE_COMPUTE_BIT,
585bf215546Sopenharmony_ci      .module = vk_shader_module_handle_from_nir(cs),
586bf215546Sopenharmony_ci      .pName = "main",
587bf215546Sopenharmony_ci      .pSpecializationInfo = NULL,
588bf215546Sopenharmony_ci   };
589bf215546Sopenharmony_ci
590bf215546Sopenharmony_ci   VkComputePipelineCreateInfo vk_pipeline_info = {
591bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
592bf215546Sopenharmony_ci      .stage = pipeline_shader_stage,
593bf215546Sopenharmony_ci      .flags = 0,
594bf215546Sopenharmony_ci      .layout = device->meta_state.resolve_compute.p_layout,
595bf215546Sopenharmony_ci   };
596bf215546Sopenharmony_ci
597bf215546Sopenharmony_ci   result = radv_CreateComputePipelines(radv_device_to_handle(device),
598bf215546Sopenharmony_ci                                        radv_pipeline_cache_to_handle(&device->meta_state.cache), 1,
599bf215546Sopenharmony_ci                                        &vk_pipeline_info, NULL, pipeline);
600bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
601bf215546Sopenharmony_ci      goto fail;
602bf215546Sopenharmony_ci
603bf215546Sopenharmony_ci   ralloc_free(cs);
604bf215546Sopenharmony_ci   mtx_unlock(&device->meta_state.mtx);
605bf215546Sopenharmony_ci   return VK_SUCCESS;
606bf215546Sopenharmony_cifail:
607bf215546Sopenharmony_ci   ralloc_free(cs);
608bf215546Sopenharmony_ci   mtx_unlock(&device->meta_state.mtx);
609bf215546Sopenharmony_ci   return result;
610bf215546Sopenharmony_ci}
611bf215546Sopenharmony_ci
612bf215546Sopenharmony_ciVkResult
613bf215546Sopenharmony_ciradv_device_init_meta_etc_decode_state(struct radv_device *device, bool on_demand)
614bf215546Sopenharmony_ci{
615bf215546Sopenharmony_ci   struct radv_meta_state *state = &device->meta_state;
616bf215546Sopenharmony_ci   VkResult res;
617bf215546Sopenharmony_ci
618bf215546Sopenharmony_ci   if (!device->physical_device->emulate_etc2)
619bf215546Sopenharmony_ci      return VK_SUCCESS;
620bf215546Sopenharmony_ci
621bf215546Sopenharmony_ci   res = create_layout(device);
622bf215546Sopenharmony_ci   if (res != VK_SUCCESS)
623bf215546Sopenharmony_ci      return res;
624bf215546Sopenharmony_ci
625bf215546Sopenharmony_ci   if (on_demand)
626bf215546Sopenharmony_ci      return VK_SUCCESS;
627bf215546Sopenharmony_ci
628bf215546Sopenharmony_ci   return create_decode_pipeline(device, &state->etc_decode.pipeline);
629bf215546Sopenharmony_ci}
630bf215546Sopenharmony_ci
631bf215546Sopenharmony_civoid
632bf215546Sopenharmony_ciradv_device_finish_meta_etc_decode_state(struct radv_device *device)
633bf215546Sopenharmony_ci{
634bf215546Sopenharmony_ci   struct radv_meta_state *state = &device->meta_state;
635bf215546Sopenharmony_ci   radv_DestroyPipeline(radv_device_to_handle(device), state->etc_decode.pipeline, &state->alloc);
636bf215546Sopenharmony_ci   radv_DestroyPipelineLayout(radv_device_to_handle(device), state->etc_decode.p_layout,
637bf215546Sopenharmony_ci                              &state->alloc);
638bf215546Sopenharmony_ci   device->vk.dispatch_table.DestroyDescriptorSetLayout(radv_device_to_handle(device),
639bf215546Sopenharmony_ci                                                        state->etc_decode.ds_layout, &state->alloc);
640bf215546Sopenharmony_ci}
641bf215546Sopenharmony_ci
642bf215546Sopenharmony_cistatic VkPipeline
643bf215546Sopenharmony_ciradv_get_etc_decode_pipeline(struct radv_cmd_buffer *cmd_buffer)
644bf215546Sopenharmony_ci{
645bf215546Sopenharmony_ci   struct radv_device *device = cmd_buffer->device;
646bf215546Sopenharmony_ci   VkPipeline *pipeline = &device->meta_state.etc_decode.pipeline;
647bf215546Sopenharmony_ci
648bf215546Sopenharmony_ci   if (!*pipeline) {
649bf215546Sopenharmony_ci      VkResult ret;
650bf215546Sopenharmony_ci
651bf215546Sopenharmony_ci      ret = create_decode_pipeline(device, pipeline);
652bf215546Sopenharmony_ci      if (ret != VK_SUCCESS) {
653bf215546Sopenharmony_ci         cmd_buffer->record_result = ret;
654bf215546Sopenharmony_ci         return VK_NULL_HANDLE;
655bf215546Sopenharmony_ci      }
656bf215546Sopenharmony_ci   }
657bf215546Sopenharmony_ci
658bf215546Sopenharmony_ci   return *pipeline;
659bf215546Sopenharmony_ci}
660bf215546Sopenharmony_ci
661bf215546Sopenharmony_cistatic void
662bf215546Sopenharmony_cidecode_etc(struct radv_cmd_buffer *cmd_buffer, struct radv_image_view *src_iview,
663bf215546Sopenharmony_ci           struct radv_image_view *dest_iview, const VkOffset3D *offset, const VkExtent3D *extent)
664bf215546Sopenharmony_ci{
665bf215546Sopenharmony_ci   struct radv_device *device = cmd_buffer->device;
666bf215546Sopenharmony_ci
667bf215546Sopenharmony_ci   radv_meta_push_descriptor_set(
668bf215546Sopenharmony_ci      cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, device->meta_state.resolve_compute.p_layout,
669bf215546Sopenharmony_ci      0, /* set */
670bf215546Sopenharmony_ci      2, /* descriptorWriteCount */
671bf215546Sopenharmony_ci      (VkWriteDescriptorSet[]){{.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
672bf215546Sopenharmony_ci                                .dstBinding = 0,
673bf215546Sopenharmony_ci                                .dstArrayElement = 0,
674bf215546Sopenharmony_ci                                .descriptorCount = 1,
675bf215546Sopenharmony_ci                                .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
676bf215546Sopenharmony_ci                                .pImageInfo =
677bf215546Sopenharmony_ci                                   (VkDescriptorImageInfo[]){
678bf215546Sopenharmony_ci                                      {.sampler = VK_NULL_HANDLE,
679bf215546Sopenharmony_ci                                       .imageView = radv_image_view_to_handle(src_iview),
680bf215546Sopenharmony_ci                                       .imageLayout = VK_IMAGE_LAYOUT_GENERAL},
681bf215546Sopenharmony_ci                                   }},
682bf215546Sopenharmony_ci                               {.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
683bf215546Sopenharmony_ci                                .dstBinding = 1,
684bf215546Sopenharmony_ci                                .dstArrayElement = 0,
685bf215546Sopenharmony_ci                                .descriptorCount = 1,
686bf215546Sopenharmony_ci                                .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
687bf215546Sopenharmony_ci                                .pImageInfo = (VkDescriptorImageInfo[]){
688bf215546Sopenharmony_ci                                   {
689bf215546Sopenharmony_ci                                      .sampler = VK_NULL_HANDLE,
690bf215546Sopenharmony_ci                                      .imageView = radv_image_view_to_handle(dest_iview),
691bf215546Sopenharmony_ci                                      .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
692bf215546Sopenharmony_ci                                   },
693bf215546Sopenharmony_ci                                }}});
694bf215546Sopenharmony_ci
695bf215546Sopenharmony_ci   VkPipeline pipeline = radv_get_etc_decode_pipeline(cmd_buffer);
696bf215546Sopenharmony_ci
697bf215546Sopenharmony_ci   radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_COMPUTE,
698bf215546Sopenharmony_ci                        pipeline);
699bf215546Sopenharmony_ci
700bf215546Sopenharmony_ci   unsigned push_constants[5] = {
701bf215546Sopenharmony_ci      offset->x, offset->y, offset->z, src_iview->image->vk.format, src_iview->image->vk.image_type,
702bf215546Sopenharmony_ci   };
703bf215546Sopenharmony_ci
704bf215546Sopenharmony_ci   radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
705bf215546Sopenharmony_ci                         device->meta_state.resolve_compute.p_layout, VK_SHADER_STAGE_COMPUTE_BIT,
706bf215546Sopenharmony_ci                         0, 20, push_constants);
707bf215546Sopenharmony_ci   radv_unaligned_dispatch(cmd_buffer, extent->width, extent->height, extent->depth);
708bf215546Sopenharmony_ci}
709bf215546Sopenharmony_ci
710bf215546Sopenharmony_civoid
711bf215546Sopenharmony_ciradv_meta_decode_etc(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
712bf215546Sopenharmony_ci                     VkImageLayout layout, const VkImageSubresourceLayers *subresource,
713bf215546Sopenharmony_ci                     VkOffset3D offset, VkExtent3D extent)
714bf215546Sopenharmony_ci{
715bf215546Sopenharmony_ci   struct radv_meta_saved_state saved_state;
716bf215546Sopenharmony_ci   radv_meta_save(&saved_state, cmd_buffer,
717bf215546Sopenharmony_ci                  RADV_META_SAVE_COMPUTE_PIPELINE | RADV_META_SAVE_CONSTANTS |
718bf215546Sopenharmony_ci                     RADV_META_SAVE_DESCRIPTORS | RADV_META_SUSPEND_PREDICATING);
719bf215546Sopenharmony_ci
720bf215546Sopenharmony_ci   uint32_t base_slice = radv_meta_get_iview_layer(image, subresource, &offset);
721bf215546Sopenharmony_ci   uint32_t slice_count = image->vk.image_type == VK_IMAGE_TYPE_3D ? extent.depth : subresource->layerCount;
722bf215546Sopenharmony_ci
723bf215546Sopenharmony_ci   extent = vk_image_sanitize_extent(&image->vk, extent);
724bf215546Sopenharmony_ci   offset = vk_image_sanitize_offset(&image->vk, offset);
725bf215546Sopenharmony_ci
726bf215546Sopenharmony_ci   VkFormat load_format = vk_format_get_blocksize(image->vk.format) == 16
727bf215546Sopenharmony_ci                             ? VK_FORMAT_R32G32B32A32_UINT
728bf215546Sopenharmony_ci                             : VK_FORMAT_R32G32_UINT;
729bf215546Sopenharmony_ci   struct radv_image_view src_iview;
730bf215546Sopenharmony_ci   radv_image_view_init(
731bf215546Sopenharmony_ci      &src_iview, cmd_buffer->device,
732bf215546Sopenharmony_ci      &(VkImageViewCreateInfo){
733bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
734bf215546Sopenharmony_ci         .image = radv_image_to_handle(image),
735bf215546Sopenharmony_ci         .viewType = radv_meta_get_view_type(image),
736bf215546Sopenharmony_ci         .format = load_format,
737bf215546Sopenharmony_ci         .subresourceRange =
738bf215546Sopenharmony_ci            {
739bf215546Sopenharmony_ci               .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
740bf215546Sopenharmony_ci               .baseMipLevel = subresource->mipLevel,
741bf215546Sopenharmony_ci               .levelCount = 1,
742bf215546Sopenharmony_ci               .baseArrayLayer = 0,
743bf215546Sopenharmony_ci               .layerCount = subresource->baseArrayLayer + subresource->layerCount,
744bf215546Sopenharmony_ci            },
745bf215546Sopenharmony_ci      },
746bf215546Sopenharmony_ci      0, NULL);
747bf215546Sopenharmony_ci
748bf215546Sopenharmony_ci   VkFormat store_format;
749bf215546Sopenharmony_ci   switch (image->vk.format) {
750bf215546Sopenharmony_ci   case VK_FORMAT_EAC_R11_UNORM_BLOCK:
751bf215546Sopenharmony_ci      store_format = VK_FORMAT_R16_UNORM;
752bf215546Sopenharmony_ci      break;
753bf215546Sopenharmony_ci   case VK_FORMAT_EAC_R11_SNORM_BLOCK:
754bf215546Sopenharmony_ci      store_format = VK_FORMAT_R16_SNORM;
755bf215546Sopenharmony_ci      break;
756bf215546Sopenharmony_ci   case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
757bf215546Sopenharmony_ci      store_format = VK_FORMAT_R16G16_UNORM;
758bf215546Sopenharmony_ci      break;
759bf215546Sopenharmony_ci   case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
760bf215546Sopenharmony_ci      store_format = VK_FORMAT_R16G16_SNORM;
761bf215546Sopenharmony_ci      break;
762bf215546Sopenharmony_ci   default:
763bf215546Sopenharmony_ci      store_format = VK_FORMAT_R8G8B8A8_UNORM;
764bf215546Sopenharmony_ci   }
765bf215546Sopenharmony_ci   struct radv_image_view dest_iview;
766bf215546Sopenharmony_ci   radv_image_view_init(
767bf215546Sopenharmony_ci      &dest_iview, cmd_buffer->device,
768bf215546Sopenharmony_ci      &(VkImageViewCreateInfo){
769bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
770bf215546Sopenharmony_ci         .image = radv_image_to_handle(image),
771bf215546Sopenharmony_ci         .viewType = radv_meta_get_view_type(image),
772bf215546Sopenharmony_ci         .format = store_format,
773bf215546Sopenharmony_ci         .subresourceRange =
774bf215546Sopenharmony_ci            {
775bf215546Sopenharmony_ci               .aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT,
776bf215546Sopenharmony_ci               .baseMipLevel = subresource->mipLevel,
777bf215546Sopenharmony_ci               .levelCount = 1,
778bf215546Sopenharmony_ci               .baseArrayLayer = 0,
779bf215546Sopenharmony_ci               .layerCount = subresource->baseArrayLayer + subresource->layerCount,
780bf215546Sopenharmony_ci            },
781bf215546Sopenharmony_ci      },
782bf215546Sopenharmony_ci      0, NULL);
783bf215546Sopenharmony_ci
784bf215546Sopenharmony_ci   decode_etc(cmd_buffer, &src_iview, &dest_iview, &(VkOffset3D){offset.x, offset.y, base_slice},
785bf215546Sopenharmony_ci              &(VkExtent3D){extent.width, extent.height, slice_count});
786bf215546Sopenharmony_ci
787bf215546Sopenharmony_ci   radv_image_view_finish(&src_iview);
788bf215546Sopenharmony_ci   radv_image_view_finish(&dest_iview);
789bf215546Sopenharmony_ci
790bf215546Sopenharmony_ci   radv_meta_restore(&saved_state, cmd_buffer);
791bf215546Sopenharmony_ci}
792