• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "CL/cl.h"
2 
3 #include "nir.h"
4 #include "nir_builder.h"
5 
6 #include "rusticl_nir.h"
7 
8 static bool
rusticl_lower_intrinsics_filter(const nir_instr * instr,const void * state)9 rusticl_lower_intrinsics_filter(const nir_instr* instr, const void* state)
10 {
11     return instr->type == nir_instr_type_intrinsic;
12 }
13 
14 static nir_def*
rusticl_lower_intrinsics_instr(nir_builder * b,nir_instr * instr,void * _state)15 rusticl_lower_intrinsics_instr(
16     nir_builder *b,
17     nir_instr *instr,
18     void* _state
19 ) {
20     nir_intrinsic_instr *intrins = nir_instr_as_intrinsic(instr);
21     struct rusticl_lower_state *state = _state;
22 
23     switch (intrins->intrinsic) {
24     case nir_intrinsic_image_deref_format:
25     case nir_intrinsic_image_deref_order: {
26         int32_t offset;
27         nir_deref_instr *deref;
28         nir_def *val;
29         nir_variable *var;
30 
31         if (intrins->intrinsic == nir_intrinsic_image_deref_format) {
32             offset = CL_SNORM_INT8;
33             var = nir_find_variable_with_location(b->shader, nir_var_uniform, state->format_arr_loc);
34         } else {
35             offset = CL_R;
36             var = nir_find_variable_with_location(b->shader, nir_var_uniform, state->order_arr_loc);
37         }
38 
39         val = intrins->src[0].ssa;
40 
41         if (val->parent_instr->type == nir_instr_type_deref) {
42             nir_deref_instr *deref = nir_instr_as_deref(val->parent_instr);
43             nir_variable *var = nir_deref_instr_get_variable(deref);
44             assert(var);
45             val = nir_imm_intN_t(b, var->data.binding, val->bit_size);
46         }
47 
48         // we put write images after read images
49         if (glsl_type_is_image(var->type)) {
50             val = nir_iadd_imm(b, val, b->shader->info.num_textures);
51         }
52 
53         deref = nir_build_deref_var(b, var);
54         deref = nir_build_deref_array(b, deref, val);
55         val = nir_u2uN(b, nir_load_deref(b, deref), 32);
56 
57         // we have to fix up the value base
58         val = nir_iadd_imm(b, val, -offset);
59 
60         return val;
61     }
62     case nir_intrinsic_load_global_invocation_id_zero_base:
63         if (intrins->def.bit_size == 64)
64             return nir_u2u64(b, nir_load_global_invocation_id_zero_base(b, 32));
65         return NULL;
66     case nir_intrinsic_load_base_global_invocation_id:
67         return nir_load_var(b, nir_find_variable_with_location(b->shader, nir_var_uniform, state->base_global_invoc_id_loc));
68     case nir_intrinsic_load_constant_base_ptr:
69         return nir_load_var(b, nir_find_variable_with_location(b->shader, nir_var_uniform, state->const_buf_loc));
70     case nir_intrinsic_load_printf_buffer_address:
71         return nir_load_var(b, nir_find_variable_with_location(b->shader, nir_var_uniform, state->printf_buf_loc));
72     case nir_intrinsic_load_work_dim:
73         assert(nir_find_variable_with_location(b->shader, nir_var_uniform, state->work_dim_loc));
74         return nir_u2uN(b, nir_load_var(b, nir_find_variable_with_location(b->shader, nir_var_uniform, state->work_dim_loc)),
75                         intrins->def.bit_size);
76     default:
77         return NULL;
78     }
79 }
80 
81 bool
rusticl_lower_intrinsics(nir_shader * nir,struct rusticl_lower_state * state)82 rusticl_lower_intrinsics(nir_shader *nir, struct rusticl_lower_state* state)
83 {
84     return nir_shader_lower_instructions(
85         nir,
86         rusticl_lower_intrinsics_filter,
87         rusticl_lower_intrinsics_instr,
88         state
89     );
90 }
91 
92 static nir_def*
rusticl_lower_input_instr(struct nir_builder * b,nir_instr * instr,void * _)93 rusticl_lower_input_instr(struct nir_builder *b, nir_instr *instr, void *_)
94 {
95    nir_intrinsic_instr *intrins = nir_instr_as_intrinsic(instr);
96    if (intrins->intrinsic != nir_intrinsic_load_kernel_input)
97       return NULL;
98 
99    nir_def *ubo_idx = nir_imm_int(b, 0);
100    nir_def *uniform_offset = intrins->src[0].ssa;
101 
102    assert(intrins->def.bit_size >= 8);
103    nir_def *load_result =
104       nir_load_ubo(b, intrins->num_components, intrins->def.bit_size,
105                    ubo_idx, nir_iadd_imm(b, uniform_offset, nir_intrinsic_base(intrins)));
106 
107    nir_intrinsic_instr *load = nir_instr_as_intrinsic(load_result->parent_instr);
108 
109    nir_intrinsic_set_align_mul(load, nir_intrinsic_align_mul(intrins));
110    nir_intrinsic_set_align_offset(load, nir_intrinsic_align_offset(intrins));
111    nir_intrinsic_set_range_base(load, nir_intrinsic_base(intrins));
112    nir_intrinsic_set_range(load, nir_intrinsic_range(intrins));
113 
114    return load_result;
115 }
116 
117 bool
rusticl_lower_inputs(nir_shader * shader)118 rusticl_lower_inputs(nir_shader *shader)
119 {
120    bool progress = false;
121 
122    assert(!shader->info.first_ubo_is_default_ubo);
123 
124    progress = nir_shader_lower_instructions(
125       shader,
126       rusticl_lower_intrinsics_filter,
127       rusticl_lower_input_instr,
128       NULL
129    );
130 
131    nir_foreach_variable_with_modes(var, shader, nir_var_mem_ubo) {
132       var->data.binding++;
133       var->data.driver_location++;
134    }
135    shader->info.num_ubos++;
136 
137    if (shader->num_uniforms > 0) {
138       const struct glsl_type *type = glsl_array_type(glsl_uint8_t_type(), shader->num_uniforms, 1);
139       nir_variable *ubo = nir_variable_create(shader, nir_var_mem_ubo, type, "kernel_input");
140       ubo->data.binding = 0;
141       ubo->data.explicit_binding = 1;
142    }
143 
144    shader->info.first_ubo_is_default_ubo = true;
145    return progress;
146 }
147