~mmach/netext73/mesa-ryzen

« back to all changes in this revision

Viewing changes to src/asahi/lib/agx_nir_lower_sample_intrinsics.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
/*
 
2
 * Copyright 2023 Valve Corporation
 
3
 * Copyright 2023 Alyssa Rosenzweig
 
4
 * SPDX-License-Identifier: MIT
 
5
 */
 
6
 
 
7
#include "agx_tilebuffer.h"
 
8
#include "nir_builder.h"
 
9
 
 
10
static nir_ssa_def *
 
11
mask_by_sample_id(nir_builder *b, nir_ssa_def *mask)
 
12
{
 
13
   nir_ssa_def *id_mask =
 
14
      nir_ishl(b, nir_imm_intN_t(b, 1, mask->bit_size), nir_load_sample_id(b));
 
15
   return nir_iand(b, mask, id_mask);
 
16
}
 
17
 
 
18
static bool
 
19
lower_to_sample(nir_builder *b, nir_instr *instr, void *_)
 
20
{
 
21
   if (instr->type != nir_instr_type_intrinsic)
 
22
      return false;
 
23
 
 
24
   nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
 
25
   b->cursor = nir_before_instr(instr);
 
26
 
 
27
   switch (intr->intrinsic) {
 
28
   case nir_intrinsic_load_sample_pos: {
 
29
      /* Lower sample positions to decode the packed fixed-point register:
 
30
       *
 
31
       *    uint32_t packed = load_sample_positions();
 
32
       *    uint32_t shifted = packed >> (sample_id * 8);
 
33
       *
 
34
       *    for (i = 0; i < 2; ++i) {
 
35
       *       uint8_t nibble = (shifted >> (i * 4)) & 0xF;
 
36
       *       xy[component] = ((float)nibble) / 16.0;
 
37
       *    }
 
38
       */
 
39
      nir_ssa_def *packed = nir_load_sample_positions_agx(b);
 
40
 
 
41
      /* The n'th sample is the in the n'th byte of the register */
 
42
      nir_ssa_def *shifted = nir_ushr(
 
43
         b, packed, nir_u2u32(b, nir_imul_imm(b, nir_load_sample_id(b), 8)));
 
44
 
 
45
      nir_ssa_def *xy[2];
 
46
      for (unsigned i = 0; i < 2; ++i) {
 
47
         /* Get the appropriate nibble */
 
48
         nir_ssa_def *nibble =
 
49
            nir_iand_imm(b, nir_ushr_imm(b, shifted, i * 4), 0xF);
 
50
 
 
51
         /* Convert it from fixed point to float */
 
52
         xy[i] = nir_fmul_imm(b, nir_u2f16(b, nibble), 1.0 / 16.0);
 
53
 
 
54
         /* Upconvert if necessary */
 
55
         xy[i] = nir_f2fN(b, xy[i], nir_dest_bit_size(intr->dest));
 
56
      }
 
57
 
 
58
      /* Collect and rewrite */
 
59
      nir_ssa_def_rewrite_uses(&intr->dest.ssa, nir_vec2(b, xy[0], xy[1]));
 
60
      nir_instr_remove(instr);
 
61
      return true;
 
62
   }
 
63
 
 
64
   case nir_intrinsic_load_sample_mask_in: {
 
65
      /* In OpenGL, gl_SampleMaskIn is only supposed to have the single bit set
 
66
       * of the sample currently being shaded when sample shading is used. Mask
 
67
       * by the sample ID to make that happen.
 
68
       */
 
69
      b->cursor = nir_after_instr(instr);
 
70
      nir_ssa_def *old = &intr->dest.ssa;
 
71
      nir_ssa_def *lowered = mask_by_sample_id(b, old);
 
72
      nir_ssa_def_rewrite_uses_after(old, lowered, lowered->parent_instr);
 
73
      return true;
 
74
   }
 
75
 
 
76
   case nir_intrinsic_load_barycentric_sample: {
 
77
      /* Lower fragment varyings with "sample" interpolation to
 
78
       * interpolateAtSample() with the sample ID
 
79
       */
 
80
      b->cursor = nir_after_instr(instr);
 
81
      nir_ssa_def *old = &intr->dest.ssa;
 
82
 
 
83
      nir_ssa_def *lowered = nir_load_barycentric_at_sample(
 
84
         b, nir_dest_bit_size(intr->dest), nir_load_sample_id(b),
 
85
         .interp_mode = nir_intrinsic_interp_mode(intr));
 
86
 
 
87
      nir_ssa_def_rewrite_uses_after(old, lowered, lowered->parent_instr);
 
88
      return true;
 
89
   }
 
90
 
 
91
   default:
 
92
      return false;
 
93
   }
 
94
}
 
95
 
 
96
/*
 
97
 * In a fragment shader using sample shading, lower intrinsics like
 
98
 * load_sample_position to variants in terms of load_sample_id. Except for a
 
99
 * possible API bit to force sample shading in shaders that don't otherwise need
 
100
 * it, this pass does not depend on the shader key. In particular, it does not
 
101
 * depend on the sample count. So it runs on fragment shaders at compile-time.
 
102
 * The load_sample_id intrinsics themselves are lowered later, with different
 
103
 * lowerings for monolithic vs epilogs.
 
104
 *
 
105
 * Note that fragment I/O (like store_local_pixel_agx and discard_agx) does not
 
106
 * get lowered here, because that lowering is different for monolithic vs FS
 
107
 * epilogs even though there's no dependency on sample count.
 
108
 */
 
109
bool
 
110
agx_nir_lower_sample_intrinsics(nir_shader *shader)
 
111
{
 
112
   /* If sample shading is disabled, the unlowered shader will broadcast pixel
 
113
    * values across the sample (the default). By definition, there are no sample
 
114
    * position or sample barycentrics, as these trigger sample shading.
 
115
    */
 
116
   if (!shader->info.fs.uses_sample_shading)
 
117
      return false;
 
118
 
 
119
   return nir_shader_instructions_pass(
 
120
      shader, lower_to_sample,
 
121
      nir_metadata_block_index | nir_metadata_dominance, NULL);
 
122
}