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