v3dv/descriptor: support for UNIFORM/STORAGE_TEXEL_BUFFER
authorAlejandro Piñeiro <apinheiro@igalia.com>
Tue, 28 Jul 2020 22:28:28 +0000 (00:28 +0200)
committerMarge Bot <eric+marge@anholt.net>
Tue, 13 Oct 2020 21:21:32 +0000 (21:21 +0000)
This gets passing most uniform/storage_texel buffer tests.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>

src/broadcom/vulkan/v3dv_cmd_buffer.c
src/broadcom/vulkan/v3dv_descriptor_set.c
src/broadcom/vulkan/v3dv_image.c
src/broadcom/vulkan/v3dv_pipeline.c
src/broadcom/vulkan/v3dv_private.h
src/broadcom/vulkan/v3dv_uniforms.c

index b2a6635..01780c1 100644 (file)
@@ -2712,13 +2712,15 @@ cmd_buffer_populate_v3d_key(struct v3d_key *key,
          v3dv_pipeline_combined_index_key_unpack(combined_idx_key,
                                                  &texture_idx, &sampler_idx);
 
-         struct v3dv_image_view *image_view =
-            v3dv_descriptor_map_get_image_view(descriptor_state,
-                                               texture_map,
-                                               cmd_buffer->state.pipeline->layout,
-                                               texture_idx);
+         VkFormat vk_format;
+         const struct v3dv_format *format;
 
-         assert(image_view);
+         format =
+            v3dv_descriptor_map_get_texture_format(descriptor_state,
+                                                   texture_map,
+                                                   cmd_buffer->state.pipeline->layout,
+                                                   texture_idx,
+                                                   &vk_format);
 
          const struct v3dv_sampler *sampler = NULL;
          if (sampler_idx != V3DV_NO_SAMPLER_IDX) {
@@ -2731,7 +2733,7 @@ cmd_buffer_populate_v3d_key(struct v3d_key *key,
          }
 
          key->tex[combined_idx].return_size =
-            v3dv_get_tex_return_size(image_view->format,
+            v3dv_get_tex_return_size(format,
                                      sampler ? sampler->compare_enable : false);
 
          if (key->tex[combined_idx].return_size == 32) {
@@ -2749,7 +2751,7 @@ cmd_buffer_populate_v3d_key(struct v3d_key *key,
           * formats.
           */
          if (sampler && sampler->clamp_to_transparent_black_border) {
-            switch (image_view->vk_format) {
+            switch (vk_format) {
             case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
             case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
                key->tex[combined_idx].swizzle[3] = PIPE_SWIZZLE_1;
index 8746b67..d00c9db 100644 (file)
@@ -40,6 +40,8 @@ descriptor_bo_size(VkDescriptorType type)
    case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
    case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
    case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+   case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+   case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
       return sizeof(struct v3dv_sampled_image_descriptor);
    default:
       return 0;
@@ -237,6 +239,62 @@ v3dv_descriptor_map_get_sampler_state(struct v3dv_descriptor_state *descriptor_s
    return reloc;
 }
 
+const struct v3dv_format*
+v3dv_descriptor_map_get_texture_format(struct v3dv_descriptor_state *descriptor_state,
+                                       struct v3dv_descriptor_map *map,
+                                       struct v3dv_pipeline_layout *pipeline_layout,
+                                       uint32_t index,
+                                       VkFormat *out_vk_format)
+{
+   struct v3dv_descriptor *descriptor =
+      v3dv_descriptor_map_get_descriptor(descriptor_state, map,
+                                         pipeline_layout, index, NULL);
+
+   switch (descriptor->type) {
+   case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+   case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+      assert(descriptor->buffer_view);
+      *out_vk_format = descriptor->buffer_view->vk_format;
+      return descriptor->buffer_view->format;
+   case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+   case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+   case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+   case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+      assert(descriptor->image_view);
+      *out_vk_format = descriptor->image_view->vk_format;
+      return descriptor->image_view->format;
+   default:
+      unreachable("descriptor type doesn't has a texture format");
+   }
+}
+
+struct v3dv_bo*
+v3dv_descriptor_map_get_texture_bo(struct v3dv_descriptor_state *descriptor_state,
+                                   struct v3dv_descriptor_map *map,
+                                   struct v3dv_pipeline_layout *pipeline_layout,
+                                   uint32_t index)
+
+{
+   struct v3dv_descriptor *descriptor =
+      v3dv_descriptor_map_get_descriptor(descriptor_state, map,
+                                         pipeline_layout, index, NULL);
+
+   switch (descriptor->type) {
+   case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+   case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+      assert(descriptor->buffer_view);
+      return descriptor->buffer_view->buffer->mem->bo;
+   case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+   case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+   case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+   case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+      assert(descriptor->image_view);
+      return descriptor->image_view->image->mem->bo;
+   default:
+      unreachable("descriptor type doesn't has a texture bo");
+   }
+}
+
 struct v3dv_cl_reloc
 v3dv_descriptor_map_get_texture_shader_state(struct v3dv_descriptor_state *descriptor_state,
                                              struct v3dv_descriptor_map *map,
@@ -252,7 +310,9 @@ v3dv_descriptor_map_get_texture_shader_state(struct v3dv_descriptor_state *descr
    assert(type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
           type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
           type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT ||
-          type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
+          type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
+          type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
+          type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
 
    if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
       reloc.offset += offsetof(struct v3dv_combined_image_sampler_descriptor,
@@ -385,6 +445,8 @@ v3dv_CreateDescriptorPool(VkDevice _device,
       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
       case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
          break;
       default:
          unreachable("Unimplemented descriptor type");
@@ -634,6 +696,8 @@ v3dv_CreateDescriptorSetLayout(VkDevice _device,
       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
       case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
          /* Nothing here, just to keep the descriptor type filtering below */
          break;
       default:
@@ -913,6 +977,23 @@ write_image_descriptor(VkDescriptorType desc_type,
    }
 }
 
+
+static void
+write_buffer_view_descriptor(VkDescriptorType desc_type,
+                             struct v3dv_descriptor_set *set,
+                             const struct v3dv_descriptor_set_binding_layout *binding_layout,
+                             struct v3dv_buffer_view *bview,
+                             uint32_t array_index)
+{
+   void *desc_map = descriptor_bo_map(set, binding_layout, array_index);
+
+   assert(bview);
+
+   memcpy(desc_map,
+          bview->texture_shader_state,
+          sizeof(bview->texture_shader_state));
+}
+
 void
 v3dv_UpdateDescriptorSets(VkDevice  _device,
                           uint32_t descriptorWriteCount,
@@ -998,6 +1079,20 @@ v3dv_UpdateDescriptorSets(VkDevice  _device,
 
             break;
          }
+         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: {
+            V3DV_FROM_HANDLE(v3dv_buffer_view, buffer_view,
+                             writeset->pTexelBufferView[j]);
+
+            assert(buffer_view);
+
+            descriptor->buffer_view = buffer_view;
+
+            write_buffer_view_descriptor(writeset->descriptorType,
+                                         set, binding_layout, buffer_view,
+                                         writeset->dstArrayElement + j);
+            break;
+         }
          default:
             unreachable("unimplemented descriptor type");
             break;
index 801d859..68d444c 100644 (file)
@@ -684,6 +684,48 @@ v3dv_DestroyImageView(VkDevice _device,
    vk_free2(&device->alloc, pAllocator, image_view);
 }
 
+static void
+pack_texture_shader_state_from_buffer_view(struct v3dv_device *device,
+                                           struct v3dv_buffer_view *buffer_view)
+{
+   assert(buffer_view->buffer);
+   const struct v3dv_buffer *buffer = buffer_view->buffer;
+
+   v3dv_pack(buffer_view->texture_shader_state, TEXTURE_SHADER_STATE, tex) {
+      tex.swizzle_r = translate_swizzle(PIPE_SWIZZLE_X);
+      tex.swizzle_g = translate_swizzle(PIPE_SWIZZLE_Y);
+      tex.swizzle_b = translate_swizzle(PIPE_SWIZZLE_Z);
+      tex.swizzle_a = translate_swizzle(PIPE_SWIZZLE_W);
+
+      tex.image_depth = 1;
+
+      /* On 4.x, the height of a 1D texture is redefined to be the upper 14
+       * bits of the width (which is only usable with txf) (or in other words,
+       * we are providing a 28 bit field for size, but split on the usual
+       * 14bit height/width).
+       */
+      tex.image_width = buffer_view->size;
+      tex.image_height = tex.image_width >> 14;
+      tex.image_width &= (1 << 14) - 1;
+      tex.image_height &= (1 << 14) - 1;
+
+      tex.texture_type = buffer_view->format->tex_type;
+      tex.srgb = vk_format_is_srgb(buffer_view->vk_format);
+
+      /* At this point we don't have the job. That's the reason the first
+       * parameter is NULL, to avoid a crash when cl_pack_emit_reloc tries to
+       * add the bo to the job. This also means that we need to add manually
+       * the image bo to the job using the texture.
+       */
+      const uint32_t base_offset =
+         buffer->mem->bo->offset +
+         buffer->mem_offset +
+         buffer_view->offset;
+
+      tex.texture_base_pointer = v3dv_cl_address(NULL, base_offset);
+   }
+}
+
 VkResult
 v3dv_CreateBufferView(VkDevice _device,
                       const VkBufferViewCreateInfo *pCreateInfo,
@@ -721,6 +763,10 @@ v3dv_CreateBufferView(VkDevice _device,
                                                 &view->internal_type,
                                                 &view->internal_bpp);
 
+   if (buffer->usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT ||
+       buffer->usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)
+      pack_texture_shader_state_from_buffer_view(device, view);
+
    *pView = v3dv_buffer_view_to_handle(view);
 
    return VK_SUCCESS;
index 27bff6a..03ce280 100644 (file)
@@ -797,7 +797,8 @@ lower_image_deref(nir_builder *b,
 
    uint32_t array_index = deref->var->data.index + base_index;
 
-   assert(binding_layout->type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
+   assert(binding_layout->type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
+          binding_layout->type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
 
    int desc_index =
       descriptor_map_add(&pipeline->texture_map,
index 2c0d31c..a737e0d 100644 (file)
@@ -506,6 +506,9 @@ struct v3dv_buffer_view {
    uint32_t offset;
    uint32_t size;
    uint32_t num_elements;
+
+   /* Prepacked TEXTURE_SHADER_STATE. */
+   uint8_t texture_shader_state[cl_packet_length(TEXTURE_SHADER_STATE)];
 };
 
 struct v3dv_subpass_attachment {
@@ -1015,6 +1018,8 @@ struct v3dv_descriptor {
          uint32_t offset;
          uint32_t range;
       };
+
+      struct v3dv_buffer_view *buffer_view;
    };
 };
 
@@ -1814,6 +1819,19 @@ v3dv_descriptor_map_get_texture_shader_state(struct v3dv_descriptor_state *descr
                                              struct v3dv_pipeline_layout *pipeline_layout,
                                              uint32_t index);
 
+const struct v3dv_format*
+v3dv_descriptor_map_get_texture_format(struct v3dv_descriptor_state *descriptor_state,
+                                       struct v3dv_descriptor_map *map,
+                                       struct v3dv_pipeline_layout *pipeline_layout,
+                                       uint32_t index,
+                                       VkFormat *out_vk_format);
+
+struct v3dv_bo*
+v3dv_descriptor_map_get_texture_bo(struct v3dv_descriptor_state *descriptor_state,
+                                   struct v3dv_descriptor_map *map,
+                                   struct v3dv_pipeline_layout *pipeline_layout,
+                                   uint32_t index);
+
 static inline const struct v3dv_sampler *
 v3dv_immutable_samplers(const struct v3dv_descriptor_set_layout *set,
                         const struct v3dv_descriptor_set_binding_layout *binding)
index a3ad5c2..cca4490 100644 (file)
@@ -100,12 +100,11 @@ write_tmu_p0(struct v3dv_cmd_buffer *cmd_buffer,
                                            NULL);
 
    /* We need to ensure that the texture bo is added to the job */
-   struct v3dv_image_view *image_view =
-      v3dv_descriptor_map_get_image_view(descriptor_state, &pipeline->texture_map,
+   struct v3dv_bo *texture_bo =
+      v3dv_descriptor_map_get_texture_bo(descriptor_state, &pipeline->texture_map,
                                          pipeline->layout, texture_idx);
-
-   assert(image_view);
-   v3dv_job_add_bo(job, image_view->image->mem->bo);
+   assert(texture_bo);
+   v3dv_job_add_bo(job, texture_bo);
 
    struct v3dv_cl_reloc state_reloc =
       v3dv_descriptor_map_get_texture_shader_state(descriptor_state,