• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2021 Valve Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  */
6 
7 #include "ac_nir.h"
8 #include "ac_nir_helpers.h"
9 
10 #include "nir_builder.h"
11 #include "nir_xfb_info.h"
12 
13 nir_shader *
ac_nir_create_gs_copy_shader(const nir_shader * gs_nir,enum amd_gfx_level gfx_level,uint32_t clip_cull_mask,const uint8_t * param_offsets,bool has_param_exports,bool disable_streamout,bool kill_pointsize,bool kill_layer,bool force_vrs,ac_nir_gs_output_info * output_info)14 ac_nir_create_gs_copy_shader(const nir_shader *gs_nir,
15                              enum amd_gfx_level gfx_level,
16                              uint32_t clip_cull_mask,
17                              const uint8_t *param_offsets,
18                              bool has_param_exports,
19                              bool disable_streamout,
20                              bool kill_pointsize,
21                              bool kill_layer,
22                              bool force_vrs,
23                              ac_nir_gs_output_info *output_info)
24 {
25    nir_builder b = nir_builder_init_simple_shader(
26       MESA_SHADER_VERTEX, gs_nir->options, "gs_copy");
27 
28    nir_foreach_shader_out_variable(var, gs_nir)
29       nir_shader_add_variable(b.shader, nir_variable_clone(var, b.shader));
30 
31    b.shader->info.outputs_written = gs_nir->info.outputs_written;
32    b.shader->info.outputs_written_16bit = gs_nir->info.outputs_written_16bit;
33 
34    nir_def *gsvs_ring = nir_load_ring_gsvs_amd(&b);
35 
36    nir_xfb_info *info = ac_nir_get_sorted_xfb_info(gs_nir);
37    nir_def *stream_id = NULL;
38    if (!disable_streamout && info)
39       stream_id = nir_ubfe_imm(&b, nir_load_streamout_config_amd(&b), 24, 2);
40 
41    nir_def *vtx_offset = nir_imul_imm(&b, nir_load_vertex_id_zero_base(&b), 4);
42    nir_def *zero = nir_imm_zero(&b, 1, 32);
43 
44    for (unsigned stream = 0; stream < 4; stream++) {
45       if (stream > 0 && (!stream_id || !(info->streams_written & BITFIELD_BIT(stream))))
46          continue;
47 
48       if (stream_id)
49          nir_push_if(&b, nir_ieq_imm(&b, stream_id, stream));
50 
51       uint32_t offset = 0;
52       ac_nir_prerast_out out = {0};
53       if (output_info->types_16bit_lo)
54          memcpy(&out.types_16bit_lo, output_info->types_16bit_lo, sizeof(out.types_16bit_lo));
55       if (output_info->types_16bit_hi)
56          memcpy(&out.types_16bit_hi, output_info->types_16bit_hi, sizeof(out.types_16bit_hi));
57 
58       u_foreach_bit64 (i, gs_nir->info.outputs_written) {
59          const uint8_t usage_mask = output_info->varying_mask[i] | output_info->sysval_mask[i];
60          out.infos[i].components_mask = usage_mask;
61          out.infos[i].as_varying_mask = output_info->varying_mask[i];
62          out.infos[i].as_sysval_mask = output_info->sysval_mask[i];
63 
64          u_foreach_bit (j, usage_mask) {
65             if (((output_info->streams[i] >> (j * 2)) & 0x3) != stream)
66                continue;
67 
68             out.outputs[i][j] =
69                nir_load_buffer_amd(&b, 1, 32, gsvs_ring, vtx_offset, zero, zero,
70                                    .base = offset,
71                                    .access = ACCESS_COHERENT | ACCESS_NON_TEMPORAL);
72             offset += gs_nir->info.gs.vertices_out * 16 * 4;
73          }
74       }
75 
76       u_foreach_bit (i, gs_nir->info.outputs_written_16bit) {
77          out.infos_16bit_lo[i].components_mask = output_info->varying_mask_16bit_lo[i];
78          out.infos_16bit_lo[i].as_varying_mask = output_info->varying_mask_16bit_lo[i];
79          out.infos_16bit_hi[i].components_mask = output_info->varying_mask_16bit_hi[i];
80          out.infos_16bit_hi[i].as_varying_mask = output_info->varying_mask_16bit_hi[i];
81 
82          for (unsigned j = 0; j < 4; j++) {
83             out.infos[i].as_varying_mask = output_info->varying_mask[i];
84             out.infos[i].as_sysval_mask = output_info->sysval_mask[i];
85 
86             bool has_lo_16bit = (output_info->varying_mask_16bit_lo[i] & (1 << j)) &&
87                ((output_info->streams_16bit_lo[i] >> (j * 2)) & 0x3) == stream;
88             bool has_hi_16bit = (output_info->varying_mask_16bit_hi[i] & (1 << j)) &&
89                ((output_info->streams_16bit_hi[i] >> (j * 2)) & 0x3) == stream;
90             if (!has_lo_16bit && !has_hi_16bit)
91                continue;
92 
93             nir_def *data =
94                nir_load_buffer_amd(&b, 1, 32, gsvs_ring, vtx_offset, zero, zero,
95                                    .base = offset,
96                                    .access = ACCESS_COHERENT | ACCESS_NON_TEMPORAL);
97 
98             if (has_lo_16bit)
99                out.outputs_16bit_lo[i][j] = nir_unpack_32_2x16_split_x(&b, data);
100 
101             if (has_hi_16bit)
102                out.outputs_16bit_hi[i][j] = nir_unpack_32_2x16_split_y(&b, data);
103 
104             offset += gs_nir->info.gs.vertices_out * 16 * 4;
105          }
106       }
107 
108       if (stream_id)
109          ac_nir_emit_legacy_streamout(&b, stream, info, &out);
110 
111       /* This should be after streamout and before exports. */
112       ac_nir_clamp_vertex_color_outputs(&b, &out);
113 
114       if (stream == 0) {
115          uint64_t export_outputs = b.shader->info.outputs_written | VARYING_BIT_POS;
116          if (kill_pointsize)
117             export_outputs &= ~VARYING_BIT_PSIZ;
118          if (kill_layer)
119             export_outputs &= ~VARYING_BIT_LAYER;
120 
121          ac_nir_export_position(&b, gfx_level, clip_cull_mask, !has_param_exports,
122                                 force_vrs, true, export_outputs, &out, NULL);
123 
124          if (has_param_exports) {
125             ac_nir_export_parameters(&b, param_offsets,
126                                      b.shader->info.outputs_written,
127                                      b.shader->info.outputs_written_16bit,
128                                      &out);
129          }
130       }
131 
132       if (stream_id)
133          nir_push_else(&b, NULL);
134    }
135 
136    b.shader->info.clip_distance_array_size = gs_nir->info.clip_distance_array_size;
137    b.shader->info.cull_distance_array_size = gs_nir->info.cull_distance_array_size;
138 
139    return b.shader;
140 }
141