}
}
+static void
+write_image_ibo(struct tu_cmd_buffer *cmd,
+ uint32_t *dst,
+ struct tu_descriptor_state *descriptors_state,
+ const struct tu_descriptor_map *map,
+ unsigned i, unsigned array_index)
+{
+ assert(descriptors_state->valid & (1 << map->set[i]));
+
+ struct tu_descriptor_set *set = descriptors_state->sets[map->set[i]];
+ assert(map->binding[i] < set->layout->binding_count);
+
+ const struct tu_descriptor_set_binding_layout *layout =
+ &set->layout->binding[map->binding[i]];
+
+ assert(layout->type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
+
+ memcpy(dst, &set->mapped_ptr[layout->offset / 4 +
+ (array_index * 2 + 1) * A6XX_TEX_CONST_DWORDS],
+ A6XX_TEX_CONST_DWORDS * 4);
+}
+
static uint64_t
buffer_ptr(struct tu_descriptor_state *descriptors_state,
const struct tu_descriptor_map *map,
&pipeline->program.link[type];
VkResult result;
- unsigned num_desc = link->ssbo_map.num_desc;
+ unsigned num_desc = link->ssbo_map.num_desc + link->image_map.num_desc;
if (num_desc == 0) {
*entry = (struct tu_cs_entry) {};
ssbo_index++;
}
}
+
+ for (unsigned i = 0; i < link->image_map.num; i++) {
+ for (int j = 0; j < link->image_map.array_size[i]; j++) {
+ uint32_t *dst = &ibo_const.map[A6XX_TEX_CONST_DWORDS * ssbo_index];
+
+ write_image_ibo(cmd, dst,
+ descriptors_state, &link->image_map, i, j);
+
+ ssbo_index++;
+ }
+ }
+
assert(ssbo_index == num_desc);
struct tu_cs cs;
/* 64bit pointer */
return 8;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
- case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
return A6XX_TEX_CONST_DWORDS * 4;
+ case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ /* We may need the IBO or the TEX representation, or both. */
+ return A6XX_TEX_CONST_DWORDS * 4 * 2;
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
/* texture const + tu_sampler struct (includes border color) */
return A6XX_TEX_CONST_DWORDS * 4 + sizeof(struct tu_sampler);
const VkDescriptorImageInfo *image_info)
{
TU_FROM_HANDLE(tu_image_view, iview, image_info->imageView);
- uint32_t *descriptor;
+ memcpy(dst, iview->descriptor, sizeof(iview->descriptor));
if (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
- descriptor = iview->storage_descriptor;
- } else {
- descriptor = iview->descriptor;
+ memcpy(&dst[A6XX_TEX_CONST_DWORDS], iview->storage_descriptor,
+ sizeof(iview->storage_descriptor));
}
- memcpy(dst, descriptor, sizeof(iview->descriptor));
-
if (cmd_buffer)
tu_bo_list_add(&cmd_buffer->bo_list, iview->image->bo, MSM_SUBMIT_BO_READ);
else
enum a6xx_tile_mode tile_mode = tu6_get_image_tile_mode(image, iview->base_mip);
uint32_t width = u_minify(image->extent.width, iview->base_mip);
uint32_t height = u_minify(image->extent.height, iview->base_mip);
+ uint32_t depth = pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_3D ?
+ u_minify(image->extent.depth, iview->base_mip) : iview->layer_count;
unsigned fmt_tex = fmt->tex;
if (iview->aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT &&
A6XX_TEX_CONST_2_TYPE(tu6_tex_type(pCreateInfo->viewType));
iview->descriptor[3] = A6XX_TEX_CONST_3_ARRAY_PITCH(tu_layer_size(image, iview->base_mip));
iview->descriptor[4] = base_addr;
- iview->descriptor[5] = base_addr >> 32;
+ iview->descriptor[5] = (base_addr >> 32) | A6XX_TEX_CONST_5_DEPTH(depth);
if (image->layout.ubwc_size) {
uint32_t block_width, block_height;
A6XX_TEX_CONST_10_FLAG_BUFFER_LOGH(util_logbase2_ceil(DIV_ROUND_UP(height, block_height)));
}
- if (pCreateInfo->viewType != VK_IMAGE_VIEW_TYPE_3D) {
- iview->descriptor[5] |= A6XX_TEX_CONST_5_DEPTH(iview->layer_count);
- } else {
+ if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_3D) {
iview->descriptor[3] |=
A6XX_TEX_CONST_3_MIN_LAYERSZ(image->layout.slices[image->level_count - 1].size0);
- iview->descriptor[5] |=
- A6XX_TEX_CONST_5_DEPTH(u_minify(image->extent.depth, iview->base_mip));
+ }
+
+ if (image->usage & VK_IMAGE_USAGE_STORAGE_BIT) {
+ memset(iview->storage_descriptor, 0, sizeof(iview->storage_descriptor));
+
+ iview->storage_descriptor[0] =
+ A6XX_IBO_0_FMT(fmt->tex) |
+ A6XX_IBO_0_TILE_MODE(tile_mode);
+ iview->storage_descriptor[1] =
+ A6XX_IBO_1_WIDTH(width) |
+ A6XX_IBO_1_HEIGHT(height);
+ iview->storage_descriptor[2] =
+ A6XX_IBO_2_PITCH(pitch) |
+ A6XX_IBO_2_TYPE(tu6_tex_type(pCreateInfo->viewType));
+ iview->storage_descriptor[3] = A6XX_IBO_3_ARRAY_PITCH(tu_layer_size(image, iview->base_mip));
+
+ iview->storage_descriptor[4] = base_addr;
+ iview->storage_descriptor[5] = (base_addr >> 32) | A6XX_IBO_5_DEPTH(depth);
+
+ if (image->layout.ubwc_size) {
+ iview->storage_descriptor[3] |= A6XX_IBO_3_FLAG | A6XX_IBO_3_UNK27;
+ iview->storage_descriptor[7] |= ubwc_addr;
+ iview->storage_descriptor[8] |= ubwc_addr >> 32;
+ iview->storage_descriptor[9] = A6XX_IBO_9_FLAG_BUFFER_ARRAY_PITCH(tu_image_ubwc_size(image, iview->base_mip) >> 2);
+ iview->storage_descriptor[10] =
+ A6XX_IBO_10_FLAG_BUFFER_PITCH(tu_image_ubwc_pitch(image, iview->base_mip));
+ }
}
}
static unsigned
tu_shader_nibo(const struct tu_shader *shader)
{
- /* In tu_cmd_buffer.c we emit the SSBO's IBOS, but not yet storage image
- * IBOs.
+ /* Don't use ir3_shader_nibo(), because that would include declared but
+ * unused storage images and SSBOs.
*/
- return shader->ssbo_map.num_desc;
+ return shader->ssbo_map.num_desc + shader->image_map.num_desc;
}
static void
link->sampler_map = shader->sampler_map;
link->ubo_map = shader->ubo_map;
link->ssbo_map = shader->ssbo_map;
- link->image_mapping = v->image_mapping;
+ link->image_map = shader->image_map;
}
static void
struct tu_descriptor_map sampler_map;
struct tu_descriptor_map ubo_map;
struct tu_descriptor_map ssbo_map;
+ struct tu_descriptor_map image_map;
/* This may be true for vertex shaders. When true, variants[1] is the
* binning variant and binning_binary is non-NULL.
struct tu_descriptor_map sampler_map;
struct tu_descriptor_map ubo_map;
struct tu_descriptor_map ssbo_map;
- struct ir3_ibo_mapping image_mapping;
+ struct tu_descriptor_map image_map;
};
struct tu_pipeline
nir_instr_remove(&instr->instr);
}
+static void
+add_image_deref_mapping(nir_intrinsic_instr *instr, struct tu_shader *shader,
+ const struct tu_pipeline_layout *layout)
+{
+ nir_deref_instr *deref = nir_src_as_deref(instr->src[0]);
+ nir_variable *var = nir_deref_instr_get_variable(deref);
+
+ uint32_t set = var->data.descriptor_set;
+ uint32_t binding = var->data.binding;
+ struct tu_descriptor_set_layout *set_layout = layout->set[set].layout;
+ struct tu_descriptor_set_binding_layout *binding_layout =
+ &set_layout->binding[binding];
+
+ var->data.driver_location =
+ map_add(&shader->image_map, set, binding, var->data.index,
+ binding_layout->array_size);
+}
+
static bool
lower_intrinsic(nir_builder *b, nir_intrinsic_instr *instr,
struct tu_shader *shader,
lower_vulkan_resource_index(b, instr, shader, layout);
return true;
+ case nir_intrinsic_image_deref_load:
+ case nir_intrinsic_image_deref_store:
+ case nir_intrinsic_image_deref_atomic_add:
+ case nir_intrinsic_image_deref_atomic_imin:
+ case nir_intrinsic_image_deref_atomic_umin:
+ case nir_intrinsic_image_deref_atomic_imax:
+ case nir_intrinsic_image_deref_atomic_umax:
+ case nir_intrinsic_image_deref_atomic_and:
+ case nir_intrinsic_image_deref_atomic_or:
+ case nir_intrinsic_image_deref_atomic_xor:
+ case nir_intrinsic_image_deref_atomic_exchange:
+ case nir_intrinsic_image_deref_atomic_comp_swap:
+ case nir_intrinsic_image_deref_size:
+ case nir_intrinsic_image_deref_samples:
+ case nir_intrinsic_image_deref_load_param_intel:
+ case nir_intrinsic_image_deref_load_raw_intel:
+ case nir_intrinsic_image_deref_store_raw_intel:
+ add_image_deref_mapping(instr, shader, layout);
+ return true;
+
default:
return false;
}