1 /* 2 * Copyright 2015 Intel Corporation 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 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24 #include "anv_nir.h" 25 #include "program/prog_parameter.h" 26 #include "nir/nir_builder.h" 27 28 struct apply_pipeline_layout_state { 29 nir_shader *shader; 30 nir_builder builder; 31 32 struct anv_pipeline_layout *layout; 33 bool add_bounds_checks; 34 35 struct { 36 BITSET_WORD *used; 37 uint8_t *surface_offsets; 38 uint8_t *sampler_offsets; 39 uint8_t *image_offsets; 40 } set[MAX_SETS]; 41 }; 42 43 static void 44 add_binding(struct apply_pipeline_layout_state *state, 45 uint32_t set, uint32_t binding) 46 { 47 BITSET_SET(state->set[set].used, binding); 48 } 49 50 static void 51 add_var_binding(struct apply_pipeline_layout_state *state, nir_variable *var) 52 { 53 add_binding(state, var->data.descriptor_set, var->data.binding); 54 } 55 56 static void 57 get_used_bindings_block(nir_block *block, 58 struct apply_pipeline_layout_state *state) 59 { 60 nir_foreach_instr_safe(instr, block) { 61 switch (instr->type) { 62 case nir_instr_type_intrinsic: { 63 nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); 64 switch (intrin->intrinsic) { 65 case nir_intrinsic_vulkan_resource_index: 66 add_binding(state, nir_intrinsic_desc_set(intrin), 67 nir_intrinsic_binding(intrin)); 68 break; 69 70 case nir_intrinsic_image_load: 71 case nir_intrinsic_image_store: 72 case nir_intrinsic_image_atomic_add: 73 case nir_intrinsic_image_atomic_min: 74 case nir_intrinsic_image_atomic_max: 75 case nir_intrinsic_image_atomic_and: 76 case nir_intrinsic_image_atomic_or: 77 case nir_intrinsic_image_atomic_xor: 78 case nir_intrinsic_image_atomic_exchange: 79 case nir_intrinsic_image_atomic_comp_swap: 80 case nir_intrinsic_image_size: 81 case nir_intrinsic_image_samples: 82 add_var_binding(state, intrin->variables[0]->var); 83 break; 84 85 default: 86 break; 87 } 88 break; 89 } 90 case nir_instr_type_tex: { 91 nir_tex_instr *tex = nir_instr_as_tex(instr); 92 assert(tex->texture); 93 add_var_binding(state, tex->texture->var); 94 if (tex->sampler) 95 add_var_binding(state, tex->sampler->var); 96 break; 97 } 98 default: 99 continue; 100 } 101 } 102 } 103 104 static void 105 lower_res_index_intrinsic(nir_intrinsic_instr *intrin, 106 struct apply_pipeline_layout_state *state) 107 { 108 nir_builder *b = &state->builder; 109 110 b->cursor = nir_before_instr(&intrin->instr); 111 112 uint32_t set = nir_intrinsic_desc_set(intrin); 113 uint32_t binding = nir_intrinsic_binding(intrin); 114 115 uint32_t surface_index = state->set[set].surface_offsets[binding]; 116 uint32_t array_size = 117 state->layout->set[set].layout->binding[binding].array_size; 118 119 nir_ssa_def *block_index = nir_ssa_for_src(b, intrin->src[0], 1); 120 121 if (state->add_bounds_checks) 122 block_index = nir_umin(b, block_index, nir_imm_int(b, array_size - 1)); 123 124 block_index = nir_iadd(b, nir_imm_int(b, surface_index), block_index); 125 126 assert(intrin->dest.is_ssa); 127 nir_ssa_def_rewrite_uses(&intrin->dest.ssa, nir_src_for_ssa(block_index)); 128 nir_instr_remove(&intrin->instr); 129 } 130 131 static void 132 lower_tex_deref(nir_tex_instr *tex, nir_deref_var *deref, 133 unsigned *const_index, unsigned array_size, 134 nir_tex_src_type src_type, 135 struct apply_pipeline_layout_state *state) 136 { 137 nir_builder *b = &state->builder; 138 139 if (deref->deref.child) { 140 assert(deref->deref.child->deref_type == nir_deref_type_array); 141 nir_deref_array *deref_array = nir_deref_as_array(deref->deref.child); 142 143 if (deref_array->deref_array_type == nir_deref_array_type_indirect) { 144 nir_ssa_def *index = 145 nir_iadd(b, nir_imm_int(b, deref_array->base_offset), 146 nir_ssa_for_src(b, deref_array->indirect, 1)); 147 148 if (state->add_bounds_checks) 149 index = nir_umin(b, index, nir_imm_int(b, array_size - 1)); 150 151 nir_tex_src *new_srcs = rzalloc_array(tex, nir_tex_src, 152 tex->num_srcs + 1); 153 154 for (unsigned i = 0; i < tex->num_srcs; i++) { 155 new_srcs[i].src_type = tex->src[i].src_type; 156 nir_instr_move_src(&tex->instr, &new_srcs[i].src, &tex->src[i].src); 157 } 158 159 ralloc_free(tex->src); 160 tex->src = new_srcs; 161 162 /* Now we can go ahead and move the source over to being a 163 * first-class texture source. 164 */ 165 tex->src[tex->num_srcs].src_type = src_type; 166 nir_instr_rewrite_src(&tex->instr, &tex->src[tex->num_srcs].src, 167 nir_src_for_ssa(index)); 168 tex->num_srcs++; 169 } else { 170 *const_index += MIN2(deref_array->base_offset, array_size - 1); 171 } 172 } 173 } 174 175 static void 176 cleanup_tex_deref(nir_tex_instr *tex, nir_deref_var *deref) 177 { 178 if (deref->deref.child == NULL) 179 return; 180 181 nir_deref_array *deref_array = nir_deref_as_array(deref->deref.child); 182 183 if (deref_array->deref_array_type != nir_deref_array_type_indirect) 184 return; 185 186 nir_instr_rewrite_src(&tex->instr, &deref_array->indirect, NIR_SRC_INIT); 187 } 188 189 static void 190 lower_tex(nir_tex_instr *tex, struct apply_pipeline_layout_state *state) 191 { 192 /* No one should have come by and lowered it already */ 193 assert(tex->texture); 194 195 state->builder.cursor = nir_before_instr(&tex->instr); 196 197 unsigned set = tex->texture->var->data.descriptor_set; 198 unsigned binding = tex->texture->var->data.binding; 199 unsigned array_size = 200 state->layout->set[set].layout->binding[binding].array_size; 201 tex->texture_index = state->set[set].surface_offsets[binding]; 202 lower_tex_deref(tex, tex->texture, &tex->texture_index, array_size, 203 nir_tex_src_texture_offset, state); 204 205 if (tex->sampler) { 206 unsigned set = tex->sampler->var->data.descriptor_set; 207 unsigned binding = tex->sampler->var->data.binding; 208 unsigned array_size = 209 state->layout->set[set].layout->binding[binding].array_size; 210 tex->sampler_index = state->set[set].sampler_offsets[binding]; 211 lower_tex_deref(tex, tex->sampler, &tex->sampler_index, array_size, 212 nir_tex_src_sampler_offset, state); 213 } 214 215 /* The backend only ever uses this to mark used surfaces. We don't care 216 * about that little optimization so it just needs to be non-zero. 217 */ 218 tex->texture_array_size = 1; 219 220 cleanup_tex_deref(tex, tex->texture); 221 if (tex->sampler) 222 cleanup_tex_deref(tex, tex->sampler); 223 tex->texture = NULL; 224 tex->sampler = NULL; 225 } 226 227 static void 228 apply_pipeline_layout_block(nir_block *block, 229 struct apply_pipeline_layout_state *state) 230 { 231 nir_foreach_instr_safe(instr, block) { 232 switch (instr->type) { 233 case nir_instr_type_intrinsic: { 234 nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); 235 if (intrin->intrinsic == nir_intrinsic_vulkan_resource_index) { 236 lower_res_index_intrinsic(intrin, state); 237 } 238 break; 239 } 240 case nir_instr_type_tex: 241 lower_tex(nir_instr_as_tex(instr), state); 242 break; 243 default: 244 continue; 245 } 246 } 247 } 248 249 static void 250 setup_vec4_uniform_value(const union gl_constant_value **params, 251 const union gl_constant_value *values, 252 unsigned n) 253 { 254 static const gl_constant_value zero = { 0 }; 255 256 for (unsigned i = 0; i < n; ++i) 257 params[i] = &values[i]; 258 259 for (unsigned i = n; i < 4; ++i) 260 params[i] = &zero; 261 } 262 263 void 264 anv_nir_apply_pipeline_layout(struct anv_pipeline *pipeline, 265 nir_shader *shader, 266 struct brw_stage_prog_data *prog_data, 267 struct anv_pipeline_bind_map *map) 268 { 269 struct anv_pipeline_layout *layout = pipeline->layout; 270 271 struct apply_pipeline_layout_state state = { 272 .shader = shader, 273 .layout = layout, 274 .add_bounds_checks = pipeline->device->robust_buffer_access, 275 }; 276 277 void *mem_ctx = ralloc_context(NULL); 278 279 for (unsigned s = 0; s < layout->num_sets; s++) { 280 const unsigned count = layout->set[s].layout->binding_count; 281 const unsigned words = BITSET_WORDS(count); 282 state.set[s].used = rzalloc_array(mem_ctx, BITSET_WORD, words); 283 state.set[s].surface_offsets = rzalloc_array(mem_ctx, uint8_t, count); 284 state.set[s].sampler_offsets = rzalloc_array(mem_ctx, uint8_t, count); 285 state.set[s].image_offsets = rzalloc_array(mem_ctx, uint8_t, count); 286 } 287 288 nir_foreach_function(function, shader) { 289 if (!function->impl) 290 continue; 291 292 nir_foreach_block(block, function->impl) 293 get_used_bindings_block(block, &state); 294 } 295 296 for (uint32_t set = 0; set < layout->num_sets; set++) { 297 struct anv_descriptor_set_layout *set_layout = layout->set[set].layout; 298 299 BITSET_WORD b, _tmp; 300 BITSET_FOREACH_SET(b, _tmp, state.set[set].used, 301 set_layout->binding_count) { 302 if (set_layout->binding[b].stage[shader->stage].surface_index >= 0) 303 map->surface_count += set_layout->binding[b].array_size; 304 if (set_layout->binding[b].stage[shader->stage].sampler_index >= 0) 305 map->sampler_count += set_layout->binding[b].array_size; 306 if (set_layout->binding[b].stage[shader->stage].image_index >= 0) 307 map->image_count += set_layout->binding[b].array_size; 308 } 309 } 310 311 unsigned surface = 0; 312 unsigned sampler = 0; 313 unsigned image = 0; 314 for (uint32_t set = 0; set < layout->num_sets; set++) { 315 struct anv_descriptor_set_layout *set_layout = layout->set[set].layout; 316 317 BITSET_WORD b, _tmp; 318 BITSET_FOREACH_SET(b, _tmp, state.set[set].used, 319 set_layout->binding_count) { 320 unsigned array_size = set_layout->binding[b].array_size; 321 322 if (set_layout->binding[b].stage[shader->stage].surface_index >= 0) { 323 state.set[set].surface_offsets[b] = surface; 324 for (unsigned i = 0; i < array_size; i++) { 325 map->surface_to_descriptor[surface + i].set = set; 326 map->surface_to_descriptor[surface + i].binding = b; 327 map->surface_to_descriptor[surface + i].index = i; 328 } 329 surface += array_size; 330 } 331 332 if (set_layout->binding[b].stage[shader->stage].sampler_index >= 0) { 333 state.set[set].sampler_offsets[b] = sampler; 334 for (unsigned i = 0; i < array_size; i++) { 335 map->sampler_to_descriptor[sampler + i].set = set; 336 map->sampler_to_descriptor[sampler + i].binding = b; 337 map->sampler_to_descriptor[sampler + i].index = i; 338 } 339 sampler += array_size; 340 } 341 342 if (set_layout->binding[b].stage[shader->stage].image_index >= 0) { 343 state.set[set].image_offsets[b] = image; 344 image += array_size; 345 } 346 } 347 } 348 349 nir_foreach_variable(var, &shader->uniforms) { 350 if (!glsl_type_is_image(var->interface_type)) 351 continue; 352 353 enum glsl_sampler_dim dim = glsl_get_sampler_dim(var->interface_type); 354 if (dim != GLSL_SAMPLER_DIM_SUBPASS && 355 dim != GLSL_SAMPLER_DIM_SUBPASS_MS) 356 continue; 357 358 const uint32_t set = var->data.descriptor_set; 359 const uint32_t binding = var->data.binding; 360 const uint32_t array_size = 361 layout->set[set].layout->binding[binding].array_size; 362 363 if (!BITSET_TEST(state.set[set].used, binding)) 364 continue; 365 366 struct anv_pipeline_binding *pipe_binding = 367 &map->surface_to_descriptor[state.set[set].surface_offsets[binding]]; 368 for (unsigned i = 0; i < array_size; i++) { 369 assert(pipe_binding[i].set == set); 370 assert(pipe_binding[i].binding == binding); 371 assert(pipe_binding[i].index == i); 372 pipe_binding[i].input_attachment_index = var->data.index + i; 373 } 374 } 375 376 nir_foreach_function(function, shader) { 377 if (!function->impl) 378 continue; 379 380 nir_builder_init(&state.builder, function->impl); 381 nir_foreach_block(block, function->impl) 382 apply_pipeline_layout_block(block, &state); 383 nir_metadata_preserve(function->impl, nir_metadata_block_index | 384 nir_metadata_dominance); 385 } 386 387 if (map->image_count > 0) { 388 assert(map->image_count <= MAX_IMAGES); 389 nir_foreach_variable(var, &shader->uniforms) { 390 if (glsl_type_is_image(var->type) || 391 (glsl_type_is_array(var->type) && 392 glsl_type_is_image(glsl_get_array_element(var->type)))) { 393 /* Images are represented as uniform push constants and the actual 394 * information required for reading/writing to/from the image is 395 * storred in the uniform. 396 */ 397 unsigned set = var->data.descriptor_set; 398 unsigned binding = var->data.binding; 399 unsigned image_index = state.set[set].image_offsets[binding]; 400 401 var->data.driver_location = shader->num_uniforms + 402 image_index * BRW_IMAGE_PARAM_SIZE * 4; 403 } 404 } 405 406 struct anv_push_constants *null_data = NULL; 407 const gl_constant_value **param = 408 prog_data->param + (shader->num_uniforms / 4); 409 const struct brw_image_param *image_param = null_data->images; 410 for (uint32_t i = 0; i < map->image_count; i++) { 411 setup_vec4_uniform_value(param + BRW_IMAGE_PARAM_SURFACE_IDX_OFFSET, 412 (const union gl_constant_value *)&image_param->surface_idx, 1); 413 setup_vec4_uniform_value(param + BRW_IMAGE_PARAM_OFFSET_OFFSET, 414 (const union gl_constant_value *)image_param->offset, 2); 415 setup_vec4_uniform_value(param + BRW_IMAGE_PARAM_SIZE_OFFSET, 416 (const union gl_constant_value *)image_param->size, 3); 417 setup_vec4_uniform_value(param + BRW_IMAGE_PARAM_STRIDE_OFFSET, 418 (const union gl_constant_value *)image_param->stride, 4); 419 setup_vec4_uniform_value(param + BRW_IMAGE_PARAM_TILING_OFFSET, 420 (const union gl_constant_value *)image_param->tiling, 3); 421 setup_vec4_uniform_value(param + BRW_IMAGE_PARAM_SWIZZLING_OFFSET, 422 (const union gl_constant_value *)image_param->swizzling, 2); 423 424 param += BRW_IMAGE_PARAM_SIZE; 425 image_param ++; 426 } 427 428 shader->num_uniforms += map->image_count * BRW_IMAGE_PARAM_SIZE * 4; 429 } 430 431 ralloc_free(mem_ctx); 432 } 433