~mmach/netext73/mesa-ryzen

« back to all changes in this revision

Viewing changes to src/amd/common/ac_nir_lower_ps.c

  • Committer: mmach
  • Date: 2023-11-02 21:31:35 UTC
  • Revision ID: netbit73@gmail.com-20231102213135-18d4tzh7tj0uz752
2023-11-02 22:11:57

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * Copyright 2023 Advanced Micro Devices, Inc.
3
3
 *
4
 
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 
 * copy of this software and associated documentation files (the "Software"),
6
 
 * to deal in the Software without restriction, including without limitation
7
 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 
 * and/or sell copies of the Software, and to permit persons to whom the
9
 
 * Software is furnished to do so, subject to the following conditions:
10
 
 *
11
 
 * The above copyright notice and this permission notice (including the next
12
 
 * paragraph) shall be included in all copies or substantial portions of the
13
 
 * Software.
14
 
 *
15
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
 
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
 
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
 
 * SOFTWARE.
 
4
 * SPDX-License-Identifier: MIT
22
5
 */
23
6
 
24
7
#include "ac_nir.h"
29
12
typedef struct {
30
13
   const ac_nir_lower_ps_options *options;
31
14
 
 
15
   nir_variable *persp_center;
 
16
   nir_variable *persp_centroid;
 
17
   nir_variable *persp_sample;
 
18
   nir_variable *linear_center;
 
19
   nir_variable *linear_centroid;
 
20
   nir_variable *linear_sample;
 
21
   bool lower_load_barycentric;
 
22
 
32
23
   /* Add one for dual source blend second output. */
33
24
   nir_ssa_def *outputs[FRAG_RESULT_MAX + 1][4];
34
25
   nir_alu_type output_types[FRAG_RESULT_MAX + 1];
42
33
 
43
34
#define DUAL_SRC_BLEND_SLOT FRAG_RESULT_MAX
44
35
 
 
36
static void
 
37
create_interp_param(nir_builder *b, lower_ps_state *s)
 
38
{
 
39
   if (s->options->force_persp_sample_interp) {
 
40
      s->persp_center =
 
41
         nir_local_variable_create(b->impl, glsl_vec_type(2), "persp_center");
 
42
   }
 
43
 
 
44
   if (s->options->bc_optimize_for_persp ||
 
45
       s->options->force_persp_sample_interp ||
 
46
       s->options->force_persp_center_interp) {
 
47
      s->persp_centroid =
 
48
         nir_local_variable_create(b->impl, glsl_vec_type(2), "persp_centroid");
 
49
   }
 
50
 
 
51
   if (s->options->force_persp_center_interp) {
 
52
      s->persp_sample =
 
53
         nir_local_variable_create(b->impl, glsl_vec_type(2), "persp_sample");
 
54
   }
 
55
 
 
56
   if (s->options->force_linear_sample_interp) {
 
57
      s->linear_center =
 
58
         nir_local_variable_create(b->impl, glsl_vec_type(2), "linear_center");
 
59
   }
 
60
 
 
61
   if (s->options->bc_optimize_for_linear ||
 
62
       s->options->force_linear_sample_interp ||
 
63
       s->options->force_linear_center_interp) {
 
64
      s->linear_centroid =
 
65
         nir_local_variable_create(b->impl, glsl_vec_type(2), "linear_centroid");
 
66
   }
 
67
 
 
68
   if (s->options->force_linear_center_interp) {
 
69
      s->linear_sample =
 
70
         nir_local_variable_create(b->impl, glsl_vec_type(2), "linear_sample");
 
71
   }
 
72
 
 
73
   s->lower_load_barycentric =
 
74
      s->persp_center || s->persp_centroid || s->persp_sample ||
 
75
      s->linear_center || s->linear_centroid || s->linear_sample;
 
76
}
 
77
 
 
78
static void
 
79
init_interp_param(nir_builder *b, lower_ps_state *s)
 
80
{
 
81
   b->cursor = nir_before_cf_list(&b->impl->body);
 
82
 
 
83
   /* The shader should do: if (PRIM_MASK[31]) CENTROID = CENTER;
 
84
    * The hw doesn't compute CENTROID if the whole wave only
 
85
    * contains fully-covered quads.
 
86
    */
 
87
   if (s->options->bc_optimize_for_persp || s->options->bc_optimize_for_linear) {
 
88
      nir_ssa_def *bc_optimize = nir_load_barycentric_optimize_amd(b);
 
89
 
 
90
      if (s->options->bc_optimize_for_persp) {
 
91
         nir_ssa_def *center =
 
92
            nir_load_barycentric_pixel(b, 32, .interp_mode = INTERP_MODE_SMOOTH);
 
93
         nir_ssa_def *centroid =
 
94
            nir_load_barycentric_centroid(b, 32, .interp_mode = INTERP_MODE_SMOOTH);
 
95
 
 
96
         nir_ssa_def *value = nir_bcsel(b, bc_optimize, center, centroid);
 
97
         nir_store_var(b, s->persp_centroid, value, 0x3);
 
98
      }
 
99
 
 
100
      if (s->options->bc_optimize_for_linear) {
 
101
         nir_ssa_def *center =
 
102
            nir_load_barycentric_pixel(b, 32, .interp_mode = INTERP_MODE_NOPERSPECTIVE);
 
103
         nir_ssa_def *centroid =
 
104
            nir_load_barycentric_centroid(b, 32, .interp_mode = INTERP_MODE_NOPERSPECTIVE);
 
105
 
 
106
         nir_ssa_def *value = nir_bcsel(b, bc_optimize, center, centroid);
 
107
         nir_store_var(b, s->linear_centroid, value, 0x3);
 
108
      }
 
109
   }
 
110
 
 
111
   if (s->options->force_persp_sample_interp) {
 
112
      nir_ssa_def *sample =
 
113
         nir_load_barycentric_sample(b, 32, .interp_mode = INTERP_MODE_SMOOTH);
 
114
      nir_store_var(b, s->persp_center, sample, 0x3);
 
115
      nir_store_var(b, s->persp_centroid, sample, 0x3);
 
116
   }
 
117
 
 
118
   if (s->options->force_linear_sample_interp) {
 
119
      nir_ssa_def *sample =
 
120
         nir_load_barycentric_sample(b, 32, .interp_mode = INTERP_MODE_NOPERSPECTIVE);
 
121
      nir_store_var(b, s->linear_center, sample, 0x3);
 
122
      nir_store_var(b, s->linear_centroid, sample, 0x3);
 
123
   }
 
124
 
 
125
   if (s->options->force_persp_center_interp) {
 
126
      nir_ssa_def *center =
 
127
         nir_load_barycentric_pixel(b, 32, .interp_mode = INTERP_MODE_SMOOTH);
 
128
      nir_store_var(b, s->persp_sample, center, 0x3);
 
129
      nir_store_var(b, s->persp_centroid, center, 0x3);
 
130
   }
 
131
 
 
132
   if (s->options->force_linear_center_interp) {
 
133
      nir_ssa_def *center =
 
134
         nir_load_barycentric_pixel(b, 32, .interp_mode = INTERP_MODE_NOPERSPECTIVE);
 
135
      nir_store_var(b, s->linear_sample, center, 0x3);
 
136
      nir_store_var(b, s->linear_centroid, center, 0x3);
 
137
   }
 
138
}
 
139
 
 
140
static bool
 
141
lower_ps_load_barycentric(nir_builder *b, nir_intrinsic_instr *intrin, lower_ps_state *s)
 
142
{
 
143
   enum glsl_interp_mode mode = nir_intrinsic_interp_mode(intrin);
 
144
   nir_variable *var = NULL;
 
145
 
 
146
   switch (mode) {
 
147
   case INTERP_MODE_NONE:
 
148
   case INTERP_MODE_SMOOTH:
 
149
      switch (intrin->intrinsic) {
 
150
      case nir_intrinsic_load_barycentric_pixel:
 
151
         var = s->persp_center;
 
152
         break;
 
153
      case nir_intrinsic_load_barycentric_centroid:
 
154
         var = s->persp_centroid;
 
155
         break;
 
156
      case nir_intrinsic_load_barycentric_sample:
 
157
         var = s->persp_sample;
 
158
         break;
 
159
      default:
 
160
         break;
 
161
      }
 
162
      break;
 
163
 
 
164
   case INTERP_MODE_NOPERSPECTIVE:
 
165
      switch (intrin->intrinsic) {
 
166
      case nir_intrinsic_load_barycentric_pixel:
 
167
         var = s->linear_center;
 
168
         break;
 
169
      case nir_intrinsic_load_barycentric_centroid:
 
170
         var = s->linear_centroid;
 
171
         break;
 
172
      case nir_intrinsic_load_barycentric_sample:
 
173
         var = s->linear_sample;
 
174
         break;
 
175
      default:
 
176
         break;
 
177
      }
 
178
      break;
 
179
 
 
180
   default:
 
181
      break;
 
182
   }
 
183
 
 
184
   if (!var)
 
185
      return false;
 
186
 
 
187
   b->cursor = nir_before_instr(&intrin->instr);
 
188
 
 
189
   nir_ssa_def *replacement = nir_load_var(b, var);
 
190
   nir_ssa_def_rewrite_uses(&intrin->dest.ssa, replacement);
 
191
 
 
192
   nir_instr_remove(&intrin->instr);
 
193
   return true;
 
194
}
 
195
 
45
196
static bool
46
197
gather_ps_store_output(nir_builder *b, nir_intrinsic_instr *intrin, lower_ps_state *s)
47
198
{
66
217
 
67
218
   s->output_types[slot] = type;
68
219
 
 
220
   /* Keep color output instruction if not exported in nir. */
 
221
   if (!s->options->no_color_export ||
 
222
       (slot < FRAG_RESULT_DATA0 && slot != FRAG_RESULT_COLOR)) {
 
223
      nir_instr_remove(&intrin->instr);
 
224
   }
 
225
 
 
226
   return true;
 
227
}
 
228
 
 
229
static bool
 
230
lower_ps_load_sample_mask_in(nir_builder *b, nir_intrinsic_instr *intrin, lower_ps_state *s)
 
231
{
 
232
   /* Section 15.2.2 (Shader Inputs) of the OpenGL 4.5 (Core Profile) spec
 
233
    * says:
 
234
    *
 
235
    *    "When per-sample shading is active due to the use of a fragment
 
236
    *     input qualified by sample or due to the use of the gl_SampleID
 
237
    *     or gl_SamplePosition variables, only the bit for the current
 
238
    *     sample is set in gl_SampleMaskIn. When state specifies multiple
 
239
    *     fragment shader invocations for a given fragment, the sample
 
240
    *     mask for any single fragment shader invocation may specify a
 
241
    *     subset of the covered samples for the fragment. In this case,
 
242
    *     the bit corresponding to each covered sample will be set in
 
243
    *     exactly one fragment shader invocation."
 
244
    *
 
245
    * The samplemask loaded by hardware is always the coverage of the
 
246
    * entire pixel/fragment, so mask bits out based on the sample ID.
 
247
    */
 
248
 
 
249
   b->cursor = nir_before_instr(&intrin->instr);
 
250
 
 
251
   uint32_t ps_iter_mask = ac_get_ps_iter_mask(s->options->ps_iter_samples);
 
252
   nir_ssa_def *sampleid = nir_load_sample_id(b);
 
253
   nir_ssa_def *submask = nir_ishl(b, nir_imm_int(b, ps_iter_mask), sampleid);
 
254
 
 
255
   nir_ssa_def *sample_mask = nir_load_sample_mask_in(b);
 
256
   nir_ssa_def *replacement = nir_iand(b, sample_mask, submask);
 
257
 
 
258
   nir_ssa_def_rewrite_uses(&intrin->dest.ssa, replacement);
 
259
 
69
260
   nir_instr_remove(&intrin->instr);
70
261
   return true;
71
262
}
80
271
 
81
272
   nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
82
273
 
83
 
   if (intrin->intrinsic == nir_intrinsic_store_output)
 
274
   switch (intrin->intrinsic) {
 
275
   case nir_intrinsic_store_output:
84
276
      return gather_ps_store_output(b, intrin, s);
 
277
   case nir_intrinsic_load_barycentric_pixel:
 
278
   case nir_intrinsic_load_barycentric_centroid:
 
279
   case nir_intrinsic_load_barycentric_sample:
 
280
      if (s->lower_load_barycentric)
 
281
         return lower_ps_load_barycentric(b, intrin, s);
 
282
      break;
 
283
   case nir_intrinsic_load_sample_mask_in:
 
284
      if (s->options->ps_iter_samples > 1)
 
285
         return lower_ps_load_sample_mask_in(b, intrin, s);
 
286
      break;
 
287
   default:
 
288
      break;
 
289
   }
85
290
 
86
291
   return false;
87
292
}
117
322
      }
118
323
 
119
324
      if (slot == FRAG_RESULT_COLOR || slot == FRAG_RESULT_DATA0) {
120
 
         if (s->options->alpha_func == PIPE_FUNC_ALWAYS) {
 
325
         if (s->options->alpha_func == COMPARE_FUNC_ALWAYS) {
121
326
            /* always pass, do nothing */
122
 
         } else if (s->options->alpha_func == PIPE_FUNC_NEVER) {
 
327
         } else if (s->options->alpha_func == COMPARE_FUNC_NEVER) {
123
328
            nir_discard(b);
124
329
         } else if (s->outputs[slot][3]) {
125
330
            nir_ssa_def *ref = nir_load_alpha_reference_amd(b);
134
339
static void
135
340
emit_ps_mrtz_export(nir_builder *b, lower_ps_state *s)
136
341
{
 
342
   uint64_t outputs_written = b->shader->info.outputs_written;
 
343
 
137
344
   nir_ssa_def *mrtz_alpha = NULL;
138
345
   if (s->options->alpha_to_coverage_via_mrtz) {
139
346
      mrtz_alpha = s->outputs[FRAG_RESULT_COLOR][3] ?
145
352
   nir_ssa_def *stencil = s->outputs[FRAG_RESULT_STENCIL][0];
146
353
   nir_ssa_def *sample_mask = s->outputs[FRAG_RESULT_SAMPLE_MASK][0];
147
354
 
 
355
   if (s->options->kill_samplemask) {
 
356
      sample_mask = NULL;
 
357
      outputs_written &= ~BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK);
 
358
   }
 
359
 
148
360
   /* skip mrtz export if no one has written to any of them */
149
361
   if (!depth && !stencil && !sample_mask && !mrtz_alpha)
150
362
      return;
151
363
 
152
 
   uint64_t outputs_written = b->shader->info.outputs_written;
153
364
   /* use outputs_written to determine export format as we use it to set
154
 
    * R_028710_SPI_SHADER_Z_FORMAT instead of relying on the real store ouput,
155
 
    * because store ouput may be optimized out.
 
365
    * R_028710_SPI_SHADER_Z_FORMAT instead of relying on the real store output,
 
366
    * because store output may be optimized out.
156
367
    */
157
368
   unsigned format =
158
369
      ac_get_spi_shader_z_format(outputs_written & BITFIELD64_BIT(FRAG_RESULT_DEPTH),
377
588
         pack_op = nir_op_pack_snorm_2x16;
378
589
         break;
379
590
      default:
380
 
         unreachable("unsupport color export format");
 
591
         unreachable("unsupported color export format");
381
592
         break;
382
593
      }
383
594
 
452
663
   /* Swizzle code is right before mrt0_exp. */
453
664
   b->cursor = nir_before_instr(&mrt0_exp->instr);
454
665
 
 
666
   /* ACO need to emit the swizzle code by a pseudo instruction. */
 
667
   if (s->options->use_aco) {
 
668
      nir_export_dual_src_blend_amd(b, mrt0_arg, mrt1_arg, .write_mask = write_mask);
 
669
      nir_instr_remove(&mrt0_exp->instr);
 
670
      nir_instr_remove(&mrt1_exp->instr);
 
671
      return;
 
672
   }
 
673
 
455
674
   nir_ssa_def *undef = nir_ssa_undef(b, 1, 32);
456
675
   nir_ssa_def *arg0_vec[4] = {undef, undef, undef, undef};
457
676
   nir_ssa_def *arg1_vec[4] = {undef, undef, undef, undef};
496
715
static void
497
716
emit_ps_null_export(nir_builder *b, lower_ps_state *s)
498
717
{
 
718
   const bool pops = b->shader->info.fs.sample_interlock_ordered ||
 
719
                     b->shader->info.fs.sample_interlock_unordered ||
 
720
                     b->shader->info.fs.pixel_interlock_ordered ||
 
721
                     b->shader->info.fs.pixel_interlock_unordered;
 
722
 
499
723
   /* Gfx10+ doesn't need to export anything if we don't need to export the EXEC mask
500
724
    * for discard.
 
725
    * In Primitive Ordered Pixel Shading, however, GFX11+ explicitly uses the `done` export to exit
 
726
    * the ordered section, and before GFX11, shaders with POPS also need an export.
501
727
    */
502
 
   if (s->options->gfx_level >= GFX10 && !s->options->uses_discard)
 
728
   if (s->options->gfx_level >= GFX10 && !s->options->uses_discard && !pops)
503
729
      return;
504
730
 
 
731
   /* The `done` export exits the POPS ordered section on GFX11+, make sure UniformMemory and
 
732
    * ImageMemory (in SPIR-V terms) accesses from the ordered section may not be reordered below it.
 
733
    */
 
734
   if (s->options->gfx_level >= GFX11 && pops)
 
735
      nir_scoped_memory_barrier(b, SCOPE_QUEUE_FAMILY, NIR_MEMORY_RELEASE,
 
736
                                nir_var_image | nir_var_mem_ubo | nir_var_mem_ssbo |
 
737
                                nir_var_mem_global);
 
738
 
505
739
   /* Gfx11 doesn't support null exports, and mrt0 should be exported instead. */
506
740
   unsigned target = s->options->gfx_level >= GFX11 ?
507
741
      V_008DFC_SQ_EXP_MRT : V_008DFC_SQ_EXP_NULL;
515
749
}
516
750
 
517
751
static void
518
 
export_ps_outputs(nir_shader *nir, lower_ps_state *s)
 
752
export_ps_outputs(nir_builder *b, lower_ps_state *s)
519
753
{
520
 
   nir_function_impl *impl = nir_shader_get_entrypoint(nir);
521
 
 
522
 
   nir_builder builder;
523
 
   nir_builder *b = &builder;
524
 
   nir_builder_init(b, impl);
525
 
 
526
 
   b->cursor = nir_after_cf_list(&impl->body);
 
754
   b->cursor = nir_after_cf_list(&b->impl->body);
527
755
 
528
756
   emit_ps_color_clamp_and_alpha_test(b, s);
529
757
 
530
758
   emit_ps_mrtz_export(b, s);
531
759
 
 
760
   /* When non-monolithic shader, RADV export mrtz in main part and export color in epilog. */
 
761
   if (s->options->no_color_export)
 
762
      return;
 
763
 
532
764
   unsigned first_color_export = s->exp_num;
533
765
 
534
766
   /* When dual src blend is enabled and we need both src0 and src1
582
814
   }
583
815
 
584
816
   if (s->exp_num) {
585
 
      if (s->options->dual_src_blend_swizzle)
 
817
      if (s->options->dual_src_blend_swizzle) {
586
818
         emit_ps_dual_src_blend_swizzle(b, s, first_color_export);
 
819
         /* Skip last export flag setting because they have been replaced by
 
820
          * a pseudo instruction.
 
821
          */
 
822
         if (s->options->use_aco)
 
823
            return;
 
824
      }
587
825
 
588
826
      /* Specify that this is the last export */
589
827
      nir_intrinsic_instr *final_exp = s->exp[s->exp_num - 1];
590
828
      unsigned final_exp_flags = nir_intrinsic_flags(final_exp);
591
829
      final_exp_flags |= AC_EXP_FLAG_DONE | AC_EXP_FLAG_VALID_MASK;
592
830
      nir_intrinsic_set_flags(final_exp, final_exp_flags);
 
831
 
 
832
      /* The `done` export exits the POPS ordered section on GFX11+, make sure UniformMemory and
 
833
       * ImageMemory (in SPIR-V terms) accesses from the ordered section may not be reordered below
 
834
       * it.
 
835
       */
 
836
      if (s->options->gfx_level >= GFX11 &&
 
837
          (b->shader->info.fs.sample_interlock_ordered ||
 
838
           b->shader->info.fs.sample_interlock_unordered ||
 
839
           b->shader->info.fs.pixel_interlock_ordered ||
 
840
           b->shader->info.fs.pixel_interlock_unordered)) {
 
841
         b->cursor = nir_before_instr(&final_exp->instr);
 
842
         nir_scoped_memory_barrier(b, SCOPE_QUEUE_FAMILY, NIR_MEMORY_RELEASE,
 
843
                                   nir_var_image | nir_var_mem_ubo | nir_var_mem_ssbo |
 
844
                                   nir_var_mem_global);
 
845
      }
593
846
   } else {
594
847
      emit_ps_null_export(b, s);
595
848
   }
598
851
void
599
852
ac_nir_lower_ps(nir_shader *nir, const ac_nir_lower_ps_options *options)
600
853
{
 
854
   nir_function_impl *impl = nir_shader_get_entrypoint(nir);
 
855
 
 
856
   nir_builder builder = nir_builder_create(impl);
 
857
   nir_builder *b = &builder;
 
858
 
601
859
   lower_ps_state state = {
602
860
      .options = options,
603
861
   };
604
862
 
 
863
   create_interp_param(b, &state);
 
864
 
605
865
   nir_shader_instructions_pass(nir, lower_ps_intrinsic,
606
866
                                nir_metadata_block_index | nir_metadata_dominance,
607
867
                                &state);
608
868
 
609
 
   export_ps_outputs(nir, &state);
 
869
   /* Must be after lower_ps_intrinsic() to prevent it lower added intrinsic here. */
 
870
   init_interp_param(b, &state);
 
871
 
 
872
   export_ps_outputs(b, &state);
 
873
 
 
874
   /* Cleanup nir variable, as RADV won't do this. */
 
875
   if (state.lower_load_barycentric)
 
876
      nir_lower_vars_to_ssa(nir);
610
877
}