1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2018 Advanced Micro Devices, Inc.
3bf215546Sopenharmony_ci * All Rights Reserved.
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub
9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom
10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
14bf215546Sopenharmony_ci * Software.
15bf215546Sopenharmony_ci *
16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
23bf215546Sopenharmony_ci */
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci#define AC_SURFACE_INCLUDE_NIR
26bf215546Sopenharmony_ci#include "ac_surface.h"
27bf215546Sopenharmony_ci#include "si_pipe.h"
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_cistatic void *create_shader_state(struct si_context *sctx, nir_shader *nir)
30bf215546Sopenharmony_ci{
31bf215546Sopenharmony_ci   sctx->b.screen->finalize_nir(sctx->b.screen, (void*)nir);
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci   struct pipe_shader_state state = {0};
34bf215546Sopenharmony_ci   state.type = PIPE_SHADER_IR_NIR;
35bf215546Sopenharmony_ci   state.ir.nir = nir;
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci   switch (nir->info.stage) {
38bf215546Sopenharmony_ci   case MESA_SHADER_VERTEX:
39bf215546Sopenharmony_ci      return sctx->b.create_vs_state(&sctx->b, &state);
40bf215546Sopenharmony_ci   case MESA_SHADER_TESS_CTRL:
41bf215546Sopenharmony_ci      return sctx->b.create_tcs_state(&sctx->b, &state);
42bf215546Sopenharmony_ci   case MESA_SHADER_TESS_EVAL:
43bf215546Sopenharmony_ci      return sctx->b.create_tes_state(&sctx->b, &state);
44bf215546Sopenharmony_ci   case MESA_SHADER_FRAGMENT:
45bf215546Sopenharmony_ci      return sctx->b.create_fs_state(&sctx->b, &state);
46bf215546Sopenharmony_ci   case MESA_SHADER_COMPUTE: {
47bf215546Sopenharmony_ci      struct pipe_compute_state cs_state = {0};
48bf215546Sopenharmony_ci      cs_state.ir_type = PIPE_SHADER_IR_NIR;
49bf215546Sopenharmony_ci      cs_state.prog = nir;
50bf215546Sopenharmony_ci      return sctx->b.create_compute_state(&sctx->b, &cs_state);
51bf215546Sopenharmony_ci   }
52bf215546Sopenharmony_ci   default:
53bf215546Sopenharmony_ci      unreachable("invalid shader stage");
54bf215546Sopenharmony_ci      return NULL;
55bf215546Sopenharmony_ci   }
56bf215546Sopenharmony_ci}
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_cistatic nir_ssa_def *get_global_ids(nir_builder *b, unsigned num_components)
59bf215546Sopenharmony_ci{
60bf215546Sopenharmony_ci   unsigned mask = BITFIELD_MASK(num_components);
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci   nir_ssa_def *local_ids = nir_channels(b, nir_load_local_invocation_id(b), mask);
63bf215546Sopenharmony_ci   nir_ssa_def *block_ids = nir_channels(b, nir_load_workgroup_id(b, 32), mask);
64bf215546Sopenharmony_ci   nir_ssa_def *block_size = nir_channels(b, nir_load_workgroup_size(b), mask);
65bf215546Sopenharmony_ci   return nir_iadd(b, nir_imul(b, block_ids, block_size), local_ids);
66bf215546Sopenharmony_ci}
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_cistatic void unpack_2x16(nir_builder *b, nir_ssa_def *src, nir_ssa_def **x, nir_ssa_def **y)
69bf215546Sopenharmony_ci{
70bf215546Sopenharmony_ci   *x = nir_iand(b, src, nir_imm_int(b, 0xffff));
71bf215546Sopenharmony_ci   *y = nir_ushr(b, src, nir_imm_int(b, 16));
72bf215546Sopenharmony_ci}
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_cistatic nir_ssa_def *
75bf215546Sopenharmony_cideref_ssa(nir_builder *b, nir_variable *var)
76bf215546Sopenharmony_ci{
77bf215546Sopenharmony_ci   return &nir_build_deref_var(b, var)->dest.ssa;
78bf215546Sopenharmony_ci}
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci/* Create a NIR compute shader implementing copy_image.
81bf215546Sopenharmony_ci *
82bf215546Sopenharmony_ci * This shader can handle 1D and 2D, linear and non-linear images.
83bf215546Sopenharmony_ci * It expects the source and destination (x,y,z) coords as user_data_amd,
84bf215546Sopenharmony_ci * packed into 3 SGPRs as 2x16bits per component.
85bf215546Sopenharmony_ci */
86bf215546Sopenharmony_civoid *si_create_copy_image_cs(struct si_context *sctx, bool src_is_1d_array, bool dst_is_1d_array)
87bf215546Sopenharmony_ci{
88bf215546Sopenharmony_ci   const nir_shader_compiler_options *options =
89bf215546Sopenharmony_ci      sctx->b.screen->get_compiler_options(sctx->b.screen, PIPE_SHADER_IR_NIR, PIPE_SHADER_COMPUTE);
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, options, "copy_image_cs");
92bf215546Sopenharmony_ci   b.shader->info.num_images = 2;
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci   /* The workgroup size is either 8x8 for normal (non-linear) 2D images,
95bf215546Sopenharmony_ci    * or 64x1 for 1D and linear-2D images.
96bf215546Sopenharmony_ci    */
97bf215546Sopenharmony_ci   b.shader->info.workgroup_size_variable = true;
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci   b.shader->info.cs.user_data_components_amd = 3;
100bf215546Sopenharmony_ci   nir_ssa_def *ids = get_global_ids(&b, 3);
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci   nir_ssa_def *coord_src = NULL, *coord_dst = NULL;
103bf215546Sopenharmony_ci   unpack_2x16(&b, nir_load_user_data_amd(&b), &coord_src, &coord_dst);
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci   coord_src = nir_iadd(&b, coord_src, ids);
106bf215546Sopenharmony_ci   coord_dst = nir_iadd(&b, coord_dst, ids);
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci   static unsigned swizzle_xz[] = {0, 2, 0, 0};
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci   if (src_is_1d_array)
111bf215546Sopenharmony_ci      coord_src = nir_swizzle(&b, coord_src, swizzle_xz, 4);
112bf215546Sopenharmony_ci   if (dst_is_1d_array)
113bf215546Sopenharmony_ci      coord_dst = nir_swizzle(&b, coord_dst, swizzle_xz, 4);
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci   const struct glsl_type *src_img_type = glsl_image_type(src_is_1d_array ? GLSL_SAMPLER_DIM_1D
116bf215546Sopenharmony_ci                                                                          : GLSL_SAMPLER_DIM_2D,
117bf215546Sopenharmony_ci                                                          /*is_array*/ true, GLSL_TYPE_FLOAT);
118bf215546Sopenharmony_ci   const struct glsl_type *dst_img_type = glsl_image_type(dst_is_1d_array ? GLSL_SAMPLER_DIM_1D
119bf215546Sopenharmony_ci                                                                          : GLSL_SAMPLER_DIM_2D,
120bf215546Sopenharmony_ci                                                          /*is_array*/ true, GLSL_TYPE_FLOAT);
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   nir_variable *img_src = nir_variable_create(b.shader, nir_var_image, src_img_type, "img_src");
123bf215546Sopenharmony_ci   img_src->data.binding = 0;
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci   nir_variable *img_dst = nir_variable_create(b.shader, nir_var_image, dst_img_type, "img_dst");
126bf215546Sopenharmony_ci   img_dst->data.binding = 1;
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   nir_ssa_def *undef32 = nir_ssa_undef(&b, 1, 32);
129bf215546Sopenharmony_ci   nir_ssa_def *zero = nir_imm_int(&b, 0);
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci   nir_ssa_def *data = nir_image_deref_load(&b, /*num_components*/ 4, /*bit_size*/ 32,
132bf215546Sopenharmony_ci      deref_ssa(&b, img_src), coord_src, undef32, zero);
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci   nir_image_deref_store(&b, deref_ssa(&b, img_dst), coord_dst, undef32, data, zero);
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci   return create_shader_state(sctx, b.shader);
137bf215546Sopenharmony_ci}
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_civoid *si_create_dcc_retile_cs(struct si_context *sctx, struct radeon_surf *surf)
140bf215546Sopenharmony_ci{
141bf215546Sopenharmony_ci   const nir_shader_compiler_options *options =
142bf215546Sopenharmony_ci      sctx->b.screen->get_compiler_options(sctx->b.screen, PIPE_SHADER_IR_NIR, PIPE_SHADER_COMPUTE);
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, options, "dcc_retile");
145bf215546Sopenharmony_ci   b.shader->info.workgroup_size[0] = 8;
146bf215546Sopenharmony_ci   b.shader->info.workgroup_size[1] = 8;
147bf215546Sopenharmony_ci   b.shader->info.workgroup_size[2] = 1;
148bf215546Sopenharmony_ci   b.shader->info.cs.user_data_components_amd = 3;
149bf215546Sopenharmony_ci   b.shader->info.num_ssbos = 1;
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci   /* Get user data SGPRs. */
152bf215546Sopenharmony_ci   nir_ssa_def *user_sgprs = nir_load_user_data_amd(&b);
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci   /* Relative offset from the displayable DCC to the non-displayable DCC in the same buffer. */
155bf215546Sopenharmony_ci   nir_ssa_def *src_dcc_offset = nir_channel(&b, user_sgprs, 0);
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   nir_ssa_def *src_dcc_pitch, *dst_dcc_pitch, *src_dcc_height, *dst_dcc_height;
158bf215546Sopenharmony_ci   unpack_2x16(&b, nir_channel(&b, user_sgprs, 1), &src_dcc_pitch, &src_dcc_height);
159bf215546Sopenharmony_ci   unpack_2x16(&b, nir_channel(&b, user_sgprs, 2), &dst_dcc_pitch, &dst_dcc_height);
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci   /* Get the 2D coordinates. */
162bf215546Sopenharmony_ci   nir_ssa_def *coord = get_global_ids(&b, 2);
163bf215546Sopenharmony_ci   nir_ssa_def *zero = nir_imm_int(&b, 0);
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci   /* Multiply the coordinates by the DCC block size (they are DCC block coordinates). */
166bf215546Sopenharmony_ci   coord = nir_imul(&b, coord, nir_imm_ivec2(&b, surf->u.gfx9.color.dcc_block_width,
167bf215546Sopenharmony_ci                                             surf->u.gfx9.color.dcc_block_height));
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci   nir_ssa_def *src_offset =
170bf215546Sopenharmony_ci      ac_nir_dcc_addr_from_coord(&b, &sctx->screen->info, surf->bpe, &surf->u.gfx9.color.dcc_equation,
171bf215546Sopenharmony_ci                                 src_dcc_pitch, src_dcc_height, zero, /* DCC slice size */
172bf215546Sopenharmony_ci                                 nir_channel(&b, coord, 0), nir_channel(&b, coord, 1), /* x, y */
173bf215546Sopenharmony_ci                                 zero, zero, zero); /* z, sample, pipe_xor */
174bf215546Sopenharmony_ci   src_offset = nir_iadd(&b, src_offset, src_dcc_offset);
175bf215546Sopenharmony_ci   nir_ssa_def *value = nir_load_ssbo(&b, 1, 8, zero, src_offset, .align_mul=1);
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_ci   nir_ssa_def *dst_offset =
178bf215546Sopenharmony_ci      ac_nir_dcc_addr_from_coord(&b, &sctx->screen->info, surf->bpe, &surf->u.gfx9.color.display_dcc_equation,
179bf215546Sopenharmony_ci                                 dst_dcc_pitch, dst_dcc_height, zero, /* DCC slice size */
180bf215546Sopenharmony_ci                                 nir_channel(&b, coord, 0), nir_channel(&b, coord, 1), /* x, y */
181bf215546Sopenharmony_ci                                 zero, zero, zero); /* z, sample, pipe_xor */
182bf215546Sopenharmony_ci   nir_store_ssbo(&b, value, zero, dst_offset, .write_mask=0x1, .align_mul=1);
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci   return create_shader_state(sctx, b.shader);
185bf215546Sopenharmony_ci}
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_civoid *gfx9_create_clear_dcc_msaa_cs(struct si_context *sctx, struct si_texture *tex)
188bf215546Sopenharmony_ci{
189bf215546Sopenharmony_ci   const nir_shader_compiler_options *options =
190bf215546Sopenharmony_ci      sctx->b.screen->get_compiler_options(sctx->b.screen, PIPE_SHADER_IR_NIR, PIPE_SHADER_COMPUTE);
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_ci   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, options, "clear_dcc_msaa");
193bf215546Sopenharmony_ci   b.shader->info.workgroup_size[0] = 8;
194bf215546Sopenharmony_ci   b.shader->info.workgroup_size[1] = 8;
195bf215546Sopenharmony_ci   b.shader->info.workgroup_size[2] = 1;
196bf215546Sopenharmony_ci   b.shader->info.cs.user_data_components_amd = 2;
197bf215546Sopenharmony_ci   b.shader->info.num_ssbos = 1;
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci   /* Get user data SGPRs. */
200bf215546Sopenharmony_ci   nir_ssa_def *user_sgprs = nir_load_user_data_amd(&b);
201bf215546Sopenharmony_ci   nir_ssa_def *dcc_pitch, *dcc_height, *clear_value, *pipe_xor;
202bf215546Sopenharmony_ci   unpack_2x16(&b, nir_channel(&b, user_sgprs, 0), &dcc_pitch, &dcc_height);
203bf215546Sopenharmony_ci   unpack_2x16(&b, nir_channel(&b, user_sgprs, 1), &clear_value, &pipe_xor);
204bf215546Sopenharmony_ci   clear_value = nir_u2u16(&b, clear_value);
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci   /* Get the 2D coordinates. */
207bf215546Sopenharmony_ci   nir_ssa_def *coord = get_global_ids(&b, 3);
208bf215546Sopenharmony_ci   nir_ssa_def *zero = nir_imm_int(&b, 0);
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci   /* Multiply the coordinates by the DCC block size (they are DCC block coordinates). */
211bf215546Sopenharmony_ci   coord = nir_imul(&b, coord,
212bf215546Sopenharmony_ci                    nir_channels(&b, nir_imm_ivec4(&b, tex->surface.u.gfx9.color.dcc_block_width,
213bf215546Sopenharmony_ci                                                   tex->surface.u.gfx9.color.dcc_block_height,
214bf215546Sopenharmony_ci                                                   tex->surface.u.gfx9.color.dcc_block_depth, 0), 0x7));
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci   nir_ssa_def *offset =
217bf215546Sopenharmony_ci      ac_nir_dcc_addr_from_coord(&b, &sctx->screen->info, tex->surface.bpe,
218bf215546Sopenharmony_ci                                 &tex->surface.u.gfx9.color.dcc_equation,
219bf215546Sopenharmony_ci                                 dcc_pitch, dcc_height, zero, /* DCC slice size */
220bf215546Sopenharmony_ci                                 nir_channel(&b, coord, 0), nir_channel(&b, coord, 1), /* x, y */
221bf215546Sopenharmony_ci                                 tex->buffer.b.b.array_size > 1 ? nir_channel(&b, coord, 2) : zero, /* z */
222bf215546Sopenharmony_ci                                 zero, pipe_xor); /* sample, pipe_xor */
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ci   /* The trick here is that DCC elements for an even and the next odd sample are next to each other
225bf215546Sopenharmony_ci    * in memory, so we only need to compute the address for sample 0 and the next DCC byte is always
226bf215546Sopenharmony_ci    * sample 1. That's why the clear value has 2 bytes - we're clearing 2 samples at the same time.
227bf215546Sopenharmony_ci    */
228bf215546Sopenharmony_ci   nir_store_ssbo(&b, clear_value, zero, offset, .write_mask=0x1, .align_mul=2);
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci   return create_shader_state(sctx, b.shader);
231bf215546Sopenharmony_ci}
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_ci/* Create a compute shader implementing clear_buffer or copy_buffer. */
234bf215546Sopenharmony_civoid *si_create_clear_buffer_rmw_cs(struct si_context *sctx)
235bf215546Sopenharmony_ci{
236bf215546Sopenharmony_ci   const nir_shader_compiler_options *options =
237bf215546Sopenharmony_ci      sctx->b.screen->get_compiler_options(sctx->b.screen, PIPE_SHADER_IR_NIR, PIPE_SHADER_COMPUTE);
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci   nir_builder b =
240bf215546Sopenharmony_ci      nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, options, "clear_buffer_rmw_cs");
241bf215546Sopenharmony_ci   b.shader->info.workgroup_size[0] = 64;
242bf215546Sopenharmony_ci   b.shader->info.workgroup_size[1] = 1;
243bf215546Sopenharmony_ci   b.shader->info.workgroup_size[2] = 1;
244bf215546Sopenharmony_ci   b.shader->info.cs.user_data_components_amd = 2;
245bf215546Sopenharmony_ci   b.shader->info.num_ssbos = 1;
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_ci   /* address = blockID * 64 + threadID; */
248bf215546Sopenharmony_ci   nir_ssa_def *address = get_global_ids(&b, 1);
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci   /* address = address * 16; (byte offset, loading one vec4 per thread) */
251bf215546Sopenharmony_ci   address = nir_ishl(&b, address, nir_imm_int(&b, 4));
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ci   nir_ssa_def *zero = nir_imm_int(&b, 0);
254bf215546Sopenharmony_ci   nir_ssa_def *data = nir_load_ssbo(&b, 4, 32, zero, address, .align_mul = 4);
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ci   /* Get user data SGPRs. */
257bf215546Sopenharmony_ci   nir_ssa_def *user_sgprs = nir_load_user_data_amd(&b);
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci   /* data &= inverted_writemask; */
260bf215546Sopenharmony_ci   data = nir_iand(&b, data, nir_channel(&b, user_sgprs, 1));
261bf215546Sopenharmony_ci   /* data |= clear_value_masked; */
262bf215546Sopenharmony_ci   data = nir_ior(&b, data, nir_channel(&b, user_sgprs, 0));
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_ci   nir_store_ssbo(&b, data, zero, address,
265bf215546Sopenharmony_ci      .access = SI_COMPUTE_DST_CACHE_POLICY != L2_LRU ? ACCESS_STREAM_CACHE_POLICY : 0,
266bf215546Sopenharmony_ci      .align_mul = 4);
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci   return create_shader_state(sctx, b.shader);
269bf215546Sopenharmony_ci}
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci/* This is used when TCS is NULL in the VS->TCS->TES chain. In this case,
272bf215546Sopenharmony_ci * VS passes its outputs to TES directly, so the fixed-function shader only
273bf215546Sopenharmony_ci * has to write TESSOUTER and TESSINNER.
274bf215546Sopenharmony_ci */
275bf215546Sopenharmony_civoid *si_create_passthrough_tcs(struct si_context *sctx)
276bf215546Sopenharmony_ci{
277bf215546Sopenharmony_ci   const nir_shader_compiler_options *options =
278bf215546Sopenharmony_ci      sctx->b.screen->get_compiler_options(sctx->b.screen, PIPE_SHADER_IR_NIR,
279bf215546Sopenharmony_ci                                           PIPE_SHADER_TESS_CTRL);
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_TESS_CTRL, options,
282bf215546Sopenharmony_ci                                                  "tcs passthrough");
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci   unsigned num_inputs = 0;
285bf215546Sopenharmony_ci   unsigned num_outputs = 0;
286bf215546Sopenharmony_ci
287bf215546Sopenharmony_ci   nir_variable *in_inner =
288bf215546Sopenharmony_ci      nir_variable_create(b.shader, nir_var_system_value, glsl_vec_type(2),
289bf215546Sopenharmony_ci                          "tess inner default");
290bf215546Sopenharmony_ci   in_inner->data.location = SYSTEM_VALUE_TESS_LEVEL_INNER_DEFAULT;
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci   nir_variable *out_inner =
293bf215546Sopenharmony_ci      nir_variable_create(b.shader, nir_var_shader_out, glsl_vec_type(2),
294bf215546Sopenharmony_ci                          "tess inner");
295bf215546Sopenharmony_ci   out_inner->data.location = VARYING_SLOT_TESS_LEVEL_INNER;
296bf215546Sopenharmony_ci   out_inner->data.driver_location = num_outputs++;
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci   nir_ssa_def *inner = nir_load_var(&b, in_inner);
299bf215546Sopenharmony_ci   nir_store_var(&b, out_inner, inner, 0x3);
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci   nir_variable *in_outer =
302bf215546Sopenharmony_ci      nir_variable_create(b.shader, nir_var_system_value, glsl_vec4_type(),
303bf215546Sopenharmony_ci                          "tess outer default");
304bf215546Sopenharmony_ci   in_outer->data.location = SYSTEM_VALUE_TESS_LEVEL_OUTER_DEFAULT;
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_ci   nir_variable *out_outer =
307bf215546Sopenharmony_ci      nir_variable_create(b.shader, nir_var_shader_out, glsl_vec4_type(),
308bf215546Sopenharmony_ci                          "tess outer");
309bf215546Sopenharmony_ci   out_outer->data.location = VARYING_SLOT_TESS_LEVEL_OUTER;
310bf215546Sopenharmony_ci   out_outer->data.driver_location = num_outputs++;
311bf215546Sopenharmony_ci
312bf215546Sopenharmony_ci   nir_ssa_def *outer = nir_load_var(&b, in_outer);
313bf215546Sopenharmony_ci   nir_store_var(&b, out_outer, outer, 0xf);
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci   nir_ssa_def *id = nir_load_invocation_id(&b);
316bf215546Sopenharmony_ci   struct si_shader_info *info = &sctx->shader.vs.cso->info;
317bf215546Sopenharmony_ci   for (unsigned i = 0; i < info->num_outputs; i++) {
318bf215546Sopenharmony_ci      const struct glsl_type *type;
319bf215546Sopenharmony_ci      unsigned semantic = info->output_semantic[i];
320bf215546Sopenharmony_ci      if (semantic < VARYING_SLOT_VAR31 && semantic != VARYING_SLOT_EDGE)
321bf215546Sopenharmony_ci         type = glsl_array_type(glsl_vec4_type(), 0, 0);
322bf215546Sopenharmony_ci      else if (semantic >= VARYING_SLOT_VAR0_16BIT)
323bf215546Sopenharmony_ci         type = glsl_array_type(glsl_vector_type(GLSL_TYPE_FLOAT16, 4), 0, 0);
324bf215546Sopenharmony_ci      else
325bf215546Sopenharmony_ci         continue;
326bf215546Sopenharmony_ci
327bf215546Sopenharmony_ci      char name[10];
328bf215546Sopenharmony_ci      snprintf(name, sizeof(name), "in_%u", i);
329bf215546Sopenharmony_ci      nir_variable *in = nir_variable_create(b.shader, nir_var_shader_in, type, name);
330bf215546Sopenharmony_ci      in->data.location = semantic;
331bf215546Sopenharmony_ci      in->data.driver_location = num_inputs++;
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_ci      snprintf(name, sizeof(name), "out_%u", i);
334bf215546Sopenharmony_ci      nir_variable *out = nir_variable_create(b.shader, nir_var_shader_out, type, name);
335bf215546Sopenharmony_ci      out->data.location = semantic;
336bf215546Sopenharmony_ci      out->data.driver_location = num_outputs++;
337bf215546Sopenharmony_ci
338bf215546Sopenharmony_ci      /* no need to use copy_var to save a lower pass */
339bf215546Sopenharmony_ci      nir_ssa_def *value = nir_load_array_var(&b, in, id);
340bf215546Sopenharmony_ci      nir_store_array_var(&b, out, id, value, 0xf);
341bf215546Sopenharmony_ci   }
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci   b.shader->num_inputs = num_inputs;
344bf215546Sopenharmony_ci   b.shader->num_outputs = num_outputs;
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci   b.shader->info.tess.tcs_vertices_out = sctx->patch_vertices;
347bf215546Sopenharmony_ci
348bf215546Sopenharmony_ci   return create_shader_state(sctx, b.shader);
349bf215546Sopenharmony_ci}
350