• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 Valve Corpoation
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "nir.h"
7 #include "nir_builder.h"
8 #include "nir_builder_opcodes.h"
9 
10 /**
11  * If load_frag_coord.xy is only used by conversions to integer,
12  * replace it with load_pixel_coord.
13  */
14 
15 static bool
opt_frag_pos(nir_builder * b,nir_intrinsic_instr * intr,UNUSED void * data)16 opt_frag_pos(nir_builder *b, nir_intrinsic_instr *intr, UNUSED void *data)
17 {
18    if (intr->intrinsic != nir_intrinsic_load_frag_coord)
19       return false;
20 
21    /* Don't increase precision. */
22    if (intr->def.bit_size != 32)
23       return false;
24 
25    /* Check if xy are only used by casts to integers. */
26    nir_foreach_use(use, &intr->def) {
27       if (nir_src_is_if(use))
28          return false;
29 
30       unsigned mask = nir_src_components_read(use);
31 
32       if (!(mask & 0x3))
33          continue;
34 
35       /* Don't handle instructions that read x/y and z/w for simplicity. */
36       if (mask & ~0x3)
37          return false;
38 
39       nir_instr *use_instr = nir_src_parent_instr(use);
40 
41       if (use_instr->type != nir_instr_type_alu)
42          return false;
43 
44       switch (nir_instr_as_alu(use_instr)->op) {
45       case nir_op_f2i8:
46       case nir_op_f2i16:
47       case nir_op_f2i32:
48       case nir_op_f2i64:
49       case nir_op_f2u8:
50       case nir_op_f2u16:
51       case nir_op_f2u32:
52       case nir_op_f2u64:
53       case nir_op_ftrunc:
54       case nir_op_ffloor:
55          continue;
56       default:
57          return false;
58       }
59    }
60 
61    b->cursor = nir_before_instr(&intr->instr);
62    nir_def *pixel_coord = nir_load_pixel_coord(b);
63 
64    nir_foreach_use_safe(use, &intr->def) {
65       unsigned mask = nir_src_components_read(use);
66 
67       if (!(mask & 0x3))
68          continue;
69 
70       nir_src_rewrite(use, pixel_coord);
71 
72       nir_alu_instr *use_instr = nir_instr_as_alu(nir_src_parent_instr(use));
73 
74       /* load_frag_coord is always positive, so we should never sign extend here. */
75       bool needs_float = use_instr->op == nir_op_ffloor || use_instr->op == nir_op_ftrunc;
76       nir_alu_type dst_type = (needs_float ? nir_type_float : nir_type_uint) | use_instr->def.bit_size;
77       use_instr->op = nir_type_conversion_op(nir_type_uint16, dst_type, nir_rounding_mode_undef);
78    }
79 
80    return true;
81 }
82 
83 bool
nir_opt_frag_coord_to_pixel_coord(nir_shader * shader)84 nir_opt_frag_coord_to_pixel_coord(nir_shader *shader)
85 {
86    return nir_shader_intrinsics_pass(shader, opt_frag_pos,
87                                      nir_metadata_control_flow,
88                                      NULL);
89 }
90