+static void
+anv_descriptor_set_write_image_param(uint32_t *param_desc_map,
+ const struct brw_image_param *param)
+{
+#define WRITE_PARAM_FIELD(field, FIELD) \
+ for (unsigned i = 0; i < ARRAY_SIZE(param->field); i++) \
+ param_desc_map[BRW_IMAGE_PARAM_##FIELD##_OFFSET + i] = param->field[i]
+
+ WRITE_PARAM_FIELD(offset, OFFSET);
+ WRITE_PARAM_FIELD(size, SIZE);
+ WRITE_PARAM_FIELD(stride, STRIDE);
+ WRITE_PARAM_FIELD(tiling, TILING);
+ WRITE_PARAM_FIELD(swizzling, SWIZZLING);
+ WRITE_PARAM_FIELD(size, SIZE);
+
+#undef WRITE_PARAM_FIELD
+}
+
+static uint32_t
+anv_surface_state_to_handle(struct anv_state state)
+{
+ /* Bits 31:12 of the bindless surface offset in the extended message
+ * descriptor is bits 25:6 of the byte-based address.
+ */
+ assert(state.offset >= 0);
+ uint32_t offset = state.offset;
+ assert((offset & 0x3f) == 0 && offset < (1 << 26));
+ return offset << 6;
+}
+
+void
+anv_descriptor_set_write_image_view(struct anv_device *device,
+ struct anv_descriptor_set *set,
+ const VkDescriptorImageInfo * const info,
+ VkDescriptorType type,
+ uint32_t binding,
+ uint32_t element)
+{
+ const struct anv_descriptor_set_binding_layout *bind_layout =
+ &set->layout->binding[binding];
+ struct anv_descriptor *desc =
+ &set->descriptors[bind_layout->descriptor_index + element];
+ struct anv_image_view *image_view = NULL;
+ struct anv_sampler *sampler = NULL;
+
+ /* We get called with just VK_DESCRIPTOR_TYPE_SAMPLER as part of descriptor
+ * set initialization to set the bindless samplers.
+ */
+ assert(type == bind_layout->type ||
+ type == VK_DESCRIPTOR_TYPE_SAMPLER);
+
+ switch (type) {
+ case VK_DESCRIPTOR_TYPE_SAMPLER:
+ sampler = anv_sampler_from_handle(info->sampler);
+ break;
+
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ image_view = anv_image_view_from_handle(info->imageView);
+ sampler = anv_sampler_from_handle(info->sampler);
+ break;
+
+ case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+ image_view = anv_image_view_from_handle(info->imageView);
+ break;
+
+ default:
+ unreachable("invalid descriptor type");
+ }
+
+ /* If this descriptor has an immutable sampler, we don't want to stomp on
+ * it.
+ */
+ sampler = bind_layout->immutable_samplers ?
+ bind_layout->immutable_samplers[element] :
+ sampler;
+
+ *desc = (struct anv_descriptor) {
+ .type = type,
+ .layout = info->imageLayout,
+ .image_view = image_view,
+ .sampler = sampler,
+ };
+
+ void *desc_map = set->desc_mem.map + bind_layout->descriptor_offset +
+ element * anv_descriptor_size(bind_layout);
+
+ if (bind_layout->data & ANV_DESCRIPTOR_SAMPLED_IMAGE) {
+ struct anv_sampled_image_descriptor desc_data[3];
+ memset(desc_data, 0, sizeof(desc_data));
+
+ if (image_view) {
+ for (unsigned p = 0; p < image_view->n_planes; p++) {
+ struct anv_surface_state sstate =
+ (desc->layout == VK_IMAGE_LAYOUT_GENERAL) ?
+ image_view->planes[p].general_sampler_surface_state :
+ image_view->planes[p].optimal_sampler_surface_state;
+ desc_data[p].image = anv_surface_state_to_handle(sstate.state);
+ }
+ }
+
+ if (sampler) {
+ for (unsigned p = 0; p < sampler->n_planes; p++)
+ desc_data[p].sampler = sampler->bindless_state.offset + p * 32;
+ }
+
+ /* We may have max_plane_count < 0 if this isn't a sampled image but it
+ * can be no more than the size of our array of handles.
+ */
+ assert(bind_layout->max_plane_count <= ARRAY_SIZE(desc_data));
+ memcpy(desc_map, desc_data,
+ MAX2(1, bind_layout->max_plane_count) * sizeof(desc_data[0]));
+ }
+
+ if (bind_layout->data & ANV_DESCRIPTOR_STORAGE_IMAGE) {
+ assert(!(bind_layout->data & ANV_DESCRIPTOR_IMAGE_PARAM));
+ assert(image_view->n_planes == 1);
+ struct anv_storage_image_descriptor desc_data = {
+ .read_write = anv_surface_state_to_handle(
+ image_view->planes[0].storage_surface_state.state),
+ .write_only = anv_surface_state_to_handle(
+ image_view->planes[0].writeonly_storage_surface_state.state),
+ };
+ memcpy(desc_map, &desc_data, sizeof(desc_data));
+ }
+
+ if (bind_layout->data & ANV_DESCRIPTOR_IMAGE_PARAM) {
+ /* Storage images can only ever have one plane */
+ assert(image_view->n_planes == 1);
+ const struct brw_image_param *image_param =
+ &image_view->planes[0].storage_image_param;
+
+ anv_descriptor_set_write_image_param(desc_map, image_param);
+ }
+
+ if (image_view && (bind_layout->data & ANV_DESCRIPTOR_TEXTURE_SWIZZLE)) {
+ assert(!(bind_layout->data & ANV_DESCRIPTOR_SAMPLED_IMAGE));
+ assert(image_view);
+ struct anv_texture_swizzle_descriptor desc_data[3];
+ memset(desc_data, 0, sizeof(desc_data));
+
+ for (unsigned p = 0; p < image_view->n_planes; p++) {
+ desc_data[p] = (struct anv_texture_swizzle_descriptor) {
+ .swizzle = {
+ (uint8_t)image_view->planes[p].isl.swizzle.r,
+ (uint8_t)image_view->planes[p].isl.swizzle.g,
+ (uint8_t)image_view->planes[p].isl.swizzle.b,
+ (uint8_t)image_view->planes[p].isl.swizzle.a,
+ },
+ };
+ }
+ memcpy(desc_map, desc_data,
+ MAX2(1, bind_layout->max_plane_count) * sizeof(desc_data[0]));
+ }
+}
+
+void
+anv_descriptor_set_write_buffer_view(struct anv_device *device,
+ struct anv_descriptor_set *set,
+ VkDescriptorType type,
+ struct anv_buffer_view *buffer_view,
+ uint32_t binding,
+ uint32_t element)
+{
+ const struct anv_descriptor_set_binding_layout *bind_layout =
+ &set->layout->binding[binding];
+ struct anv_descriptor *desc =
+ &set->descriptors[bind_layout->descriptor_index + element];
+
+ assert(type == bind_layout->type);
+
+ *desc = (struct anv_descriptor) {
+ .type = type,
+ .buffer_view = buffer_view,
+ };
+
+ void *desc_map = set->desc_mem.map + bind_layout->descriptor_offset +
+ element * anv_descriptor_size(bind_layout);
+
+ if (bind_layout->data & ANV_DESCRIPTOR_SAMPLED_IMAGE) {
+ struct anv_sampled_image_descriptor desc_data = {
+ .image = anv_surface_state_to_handle(buffer_view->surface_state),
+ };
+ memcpy(desc_map, &desc_data, sizeof(desc_data));
+ }
+
+ if (bind_layout->data & ANV_DESCRIPTOR_STORAGE_IMAGE) {
+ assert(!(bind_layout->data & ANV_DESCRIPTOR_IMAGE_PARAM));
+ struct anv_storage_image_descriptor desc_data = {
+ .read_write = anv_surface_state_to_handle(
+ buffer_view->storage_surface_state),
+ .write_only = anv_surface_state_to_handle(
+ buffer_view->writeonly_storage_surface_state),
+ };
+ memcpy(desc_map, &desc_data, sizeof(desc_data));
+ }
+
+ if (bind_layout->data & ANV_DESCRIPTOR_IMAGE_PARAM) {
+ anv_descriptor_set_write_image_param(desc_map,
+ &buffer_view->storage_image_param);
+ }
+}
+
+void
+anv_descriptor_set_write_buffer(struct anv_device *device,
+ struct anv_descriptor_set *set,
+ struct anv_state_stream *alloc_stream,
+ VkDescriptorType type,
+ struct anv_buffer *buffer,
+ uint32_t binding,
+ uint32_t element,
+ VkDeviceSize offset,
+ VkDeviceSize range)
+{
+ const struct anv_descriptor_set_binding_layout *bind_layout =
+ &set->layout->binding[binding];
+ struct anv_descriptor *desc =
+ &set->descriptors[bind_layout->descriptor_index + element];
+
+ assert(type == bind_layout->type);
+
+ struct anv_address bind_addr = anv_address_add(buffer->address, offset);
+ uint64_t bind_range = anv_buffer_get_range(buffer, offset, range);
+
+ if (type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
+ type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
+ *desc = (struct anv_descriptor) {
+ .type = type,
+ .buffer = buffer,
+ .offset = offset,
+ .range = range,
+ };
+ } else {
+ assert(bind_layout->data & ANV_DESCRIPTOR_BUFFER_VIEW);
+ struct anv_buffer_view *bview =
+ &set->buffer_views[bind_layout->buffer_view_index + element];
+
+ bview->format = anv_isl_format_for_descriptor_type(type);
+ bview->range = bind_range;
+ bview->address = bind_addr;
+
+ /* If we're writing descriptors through a push command, we need to
+ * allocate the surface state from the command buffer. Otherwise it will
+ * be allocated by the descriptor pool when calling
+ * vkAllocateDescriptorSets. */
+ if (alloc_stream)
+ bview->surface_state = anv_state_stream_alloc(alloc_stream, 64, 64);
+
+ anv_fill_buffer_surface_state(device, bview->surface_state,
+ bview->format, bind_addr, bind_range, 1);
+
+ *desc = (struct anv_descriptor) {
+ .type = type,
+ .buffer_view = bview,
+ };
+ }
+
+ void *desc_map = set->desc_mem.map + bind_layout->descriptor_offset +
+ element * anv_descriptor_size(bind_layout);
+
+ if (bind_layout->data & ANV_DESCRIPTOR_ADDRESS_RANGE) {
+ struct anv_address_range_descriptor desc = {
+ .address = anv_address_physical(bind_addr),
+ .range = bind_range,
+ };
+ memcpy(desc_map, &desc, sizeof(desc));
+ }
+}
+
+void
+anv_descriptor_set_write_inline_uniform_data(struct anv_device *device,
+ struct anv_descriptor_set *set,
+ uint32_t binding,
+ const void *data,
+ size_t offset,
+ size_t size)
+{
+ const struct anv_descriptor_set_binding_layout *bind_layout =
+ &set->layout->binding[binding];
+
+ assert(bind_layout->data & ANV_DESCRIPTOR_INLINE_UNIFORM);
+
+ void *desc_map = set->desc_mem.map + bind_layout->descriptor_offset;
+
+ memcpy(desc_map + offset, data, size);
+}
+