anv: Add initial support for cube maps
[mesa.git] / src / vulkan / anv_image.c
index f99155cad6ac20dc8efaaa0fb280edef4e7b816a..dcad2affb2c497cd10dfab9680c05c5eed2ea9bf 100644 (file)
  */
 #include "gen8_pack.h"
 
-static const uint8_t anv_halign[] = {
-    [4] = HALIGN4,
-    [8] = HALIGN8,
-    [16] = HALIGN16,
-};
-
-static const uint8_t anv_valign[] = {
-    [4] = VALIGN4,
-    [8] = VALIGN8,
-    [16] = VALIGN16,
-};
-
-static const uint8_t anv_surf_type_from_image_type[] = {
-   [VK_IMAGE_TYPE_1D] = SURFTYPE_1D,
-   [VK_IMAGE_TYPE_2D] = SURFTYPE_2D,
-   [VK_IMAGE_TYPE_3D] = SURFTYPE_3D,
-};
-
-static const struct anv_image_view_info
-anv_image_view_info_table[] = {
-   #define INFO(s, ...) { .surface_type = s, __VA_ARGS__ }
-   [VK_IMAGE_VIEW_TYPE_1D]          = INFO(SURFTYPE_1D),
-   [VK_IMAGE_VIEW_TYPE_2D]          = INFO(SURFTYPE_2D),
-   [VK_IMAGE_VIEW_TYPE_3D]          = INFO(SURFTYPE_3D),
-   [VK_IMAGE_VIEW_TYPE_CUBE]        = INFO(SURFTYPE_CUBE,                  .is_cube = 1),
-   [VK_IMAGE_VIEW_TYPE_1D_ARRAY]    = INFO(SURFTYPE_1D,     .is_array = 1),
-   [VK_IMAGE_VIEW_TYPE_2D_ARRAY]    = INFO(SURFTYPE_2D,     .is_array = 1),
-   [VK_IMAGE_VIEW_TYPE_CUBE_ARRAY]  = INFO(SURFTYPE_CUBE,   .is_array = 1, .is_cube = 1),
-   #undef INFO
-};
-
-struct anv_image_view_info
-anv_image_view_info_for_vk_image_view_type(VkImageViewType type)
-{
-   return anv_image_view_info_table[type];
-}
-
-static isl_tiling_flags_t
-choose_isl_tiling_flags(const struct anv_image_create_info *anv_info)
-{
-   const VkImageCreateInfo *vk_info = anv_info->vk_info;
-
-   if (anv_info->force_tiling) {
-      return 1u << anv_info->tiling;
-   } else if (vk_info->tiling == VK_IMAGE_TILING_LINEAR) {
-      return ISL_TILING_LINEAR_BIT;
-   } else if (vk_info->tiling == VK_IMAGE_TILING_OPTIMAL) {
-      return ISL_TILING_ANY_MASK;
-   } else {
-      unreachable("bad anv_image_create_info");
-      return 0;
-   }
-}
-
 /**
  * The \a format argument is required and overrides any format found in struct
- * anv_image_create_info.
+ * anv_image_create_info. Exactly one bit must be set in \a aspect.
  */
 static isl_surf_usage_flags_t
 choose_isl_surf_usage(const struct anv_image_create_info *info,
-                      const struct anv_format *format)
+                      VkImageAspectFlags aspect)
 {
    const VkImageCreateInfo *vk_info = info->vk_info;
    isl_surf_usage_flags_t isl_flags = 0;
@@ -115,12 +61,15 @@ choose_isl_surf_usage(const struct anv_image_create_info *info,
       isl_flags |= ISL_SURF_USAGE_CUBE_BIT;
 
    if (vk_info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
-      assert((format->depth_format != 0) ^ format->has_stencil);
-
-      if (format->depth_format) {
+      switch (aspect) {
+      default:
+         unreachable("bad VkImageAspect");
+      case VK_IMAGE_ASPECT_DEPTH_BIT:
          isl_flags |= ISL_SURF_USAGE_DEPTH_BIT;
-      } else if (format->has_stencil) {
+         break;
+      case VK_IMAGE_ASPECT_STENCIL_BIT:
          isl_flags |= ISL_SURF_USAGE_STENCIL_BIT;
+         break;
       }
    }
 
@@ -138,18 +87,37 @@ choose_isl_surf_usage(const struct anv_image_create_info *info,
 }
 
 /**
- * The \a format argument is required and overrides any format in
- * struct anv_image_create_info.
+ * Exactly one bit must be set in \a aspect.
+ */
+static struct anv_surface *
+get_surface(struct anv_image *image, VkImageAspectFlags aspect)
+{
+   switch (aspect) {
+   default:
+      unreachable("bad VkImageAspect");
+   case VK_IMAGE_ASPECT_COLOR_BIT:
+      return &image->color_surface;
+   case VK_IMAGE_ASPECT_DEPTH_BIT:
+      return &image->depth_surface;
+   case VK_IMAGE_ASPECT_STENCIL_BIT:
+      return &image->stencil_surface;
+   }
+}
+
+/**
+ * Initialize the anv_image::*_surface selected by \a aspect. Then update the
+ * image's memory requirements (that is, the image's size and alignment).
+ *
+ * Exactly one bit must be set in \a aspect.
  */
 static VkResult
-anv_image_make_surface(const struct anv_device *dev,
-                       const struct anv_image_create_info *anv_info,
-                       const struct anv_format *format,
-                       uint64_t *inout_image_size,
-                       uint32_t *inout_image_alignment,
-                       struct anv_surface *out_anv_surf)
+make_surface(const struct anv_device *dev,
+             struct anv_image *image,
+             const struct anv_image_create_info *anv_info,
+             VkImageAspectFlags aspect)
 {
    const VkImageCreateInfo *vk_info = anv_info->vk_info;
+   bool ok UNUSED;
 
    static const enum isl_surf_dim vk_to_isl_surf_dim[] = {
       [VK_IMAGE_TYPE_1D] = ISL_SURF_DIM_1D,
@@ -157,9 +125,15 @@ anv_image_make_surface(const struct anv_device *dev,
       [VK_IMAGE_TYPE_3D] = ISL_SURF_DIM_3D,
    };
 
-   isl_surf_init(&dev->isl_dev, &out_anv_surf->isl,
+   isl_tiling_flags_t tiling_flags = anv_info->isl_tiling_flags;
+   if (vk_info->tiling == VK_IMAGE_TILING_LINEAR)
+      tiling_flags &= ISL_TILING_LINEAR_BIT;
+
+   struct anv_surface *anv_surf = get_surface(image, aspect);
+
+   ok = isl_surf_init(&dev->isl_dev, &anv_surf->isl,
       .dim = vk_to_isl_surf_dim[vk_info->imageType],
-      .format = format->surface_format,
+      .format = anv_get_isl_format(vk_info->format, aspect),
       .width = vk_info->extent.width,
       .height = vk_info->extent.height,
       .depth = vk_info->extent.depth,
@@ -168,15 +142,17 @@ anv_image_make_surface(const struct anv_device *dev,
       .samples = vk_info->samples,
       .min_alignment = 0,
       .min_pitch = 0,
-      .usage = choose_isl_surf_usage(anv_info, format),
-      .tiling_flags = choose_isl_tiling_flags(anv_info));
+      .usage = choose_isl_surf_usage(anv_info, aspect),
+      .tiling_flags = tiling_flags);
 
-   out_anv_surf->offset = align_u32(*inout_image_size,
-                                    out_anv_surf->isl.alignment);
+   /* isl_surf_init() will fail only if provided invalid input. Invalid input
+    * is illegal in Vulkan.
+    */
+   assert(ok);
 
-   *inout_image_size = out_anv_surf->offset + out_anv_surf->isl.size;
-   *inout_image_alignment = MAX(*inout_image_alignment,
-                                out_anv_surf->isl.alignment);
+   anv_surf->offset = align_u32(image->size, anv_surf->isl.alignment);
+   image->size = anv_surf->offset + anv_surf->isl.size;
+   image->alignment = MAX(image->alignment, anv_surf->isl.alignment);
 
    return VK_SUCCESS;
 }
@@ -221,10 +197,6 @@ anv_image_create(VkDevice _device,
    anv_assert(pCreateInfo->extent.height > 0);
    anv_assert(pCreateInfo->extent.depth > 0);
 
-   /* TODO(chadv): How should we validate inputs? */
-   const uint8_t surf_type =
-      anv_surf_type_from_image_type[pCreateInfo->imageType];
-
    image = anv_alloc2(&device->alloc, alloc, sizeof(*image), 8,
                       VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    if (!image)
@@ -237,10 +209,8 @@ anv_image_create(VkDevice _device,
    image->levels = pCreateInfo->mipLevels;
    image->array_size = pCreateInfo->arrayLayers;
    image->usage = anv_image_get_full_usage(pCreateInfo);
-   image->surface_type = surf_type;
 
-   if (image->usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
-                       VK_IMAGE_USAGE_STORAGE_BIT)) {
+   if (image->usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
       image->needs_nonrt_surface_state = true;
    }
 
@@ -248,25 +218,26 @@ anv_image_create(VkDevice _device,
       image->needs_color_rt_surface_state = true;
    }
 
+   if (image->usage & VK_IMAGE_USAGE_STORAGE_BIT) {
+      image->needs_storage_surface_state = true;
+   }
+
    if (likely(anv_format_is_color(image->format))) {
-      r = anv_image_make_surface(device, create_info, image->format,
-                                 &image->size, &image->alignment,
-                                 &image->color_surface);
+      r = make_surface(device, image, create_info,
+                       VK_IMAGE_ASPECT_COLOR_BIT);
       if (r != VK_SUCCESS)
          goto fail;
    } else {
       if (image->format->depth_format) {
-         r = anv_image_make_surface(device, create_info, image->format,
-                                    &image->size, &image->alignment,
-                                    &image->depth_surface);
+         r = make_surface(device, image, create_info,
+                          VK_IMAGE_ASPECT_DEPTH_BIT);
          if (r != VK_SUCCESS)
             goto fail;
       }
 
       if (image->format->has_stencil) {
-         r = anv_image_make_surface(device, create_info, anv_format_s8_uint,
-                                    &image->size, &image->alignment,
-                                    &image->stencil_surface);
+         r = make_surface(device, image, create_info,
+                          VK_IMAGE_ASPECT_STENCIL_BIT);
          if (r != VK_SUCCESS)
             goto fail;
       }
@@ -292,6 +263,7 @@ anv_CreateImage(VkDevice device,
    return anv_image_create(device,
       &(struct anv_image_create_info) {
          .vk_info = pCreateInfo,
+         .isl_tiling_flags = ISL_TILING_ANY_MASK,
       },
       pAllocator,
       pImage);
@@ -360,7 +332,6 @@ anv_validate_CreateImageView(VkDevice _device,
 {
    ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
    const VkImageSubresourceRange *subresource;
-   const struct anv_image_view_info *view_info;
    const struct anv_format *view_format_info;
 
    /* Validate structure type before dereferencing it. */
@@ -371,7 +342,6 @@ anv_validate_CreateImageView(VkDevice _device,
    /* Validate viewType is in range before using it. */
    assert(pCreateInfo->viewType >= VK_IMAGE_VIEW_TYPE_BEGIN_RANGE);
    assert(pCreateInfo->viewType <= VK_IMAGE_VIEW_TYPE_END_RANGE);
-   view_info = &anv_image_view_info_table[pCreateInfo->viewType];
 
    /* Validate format is in range before using it. */
    assert(pCreateInfo->format >= VK_FORMAT_BEGIN_RANGE);
@@ -398,11 +368,6 @@ anv_validate_CreateImageView(VkDevice _device,
    assert(subresource->baseArrayLayer + subresource->layerCount <= image->array_size);
    assert(pView);
 
-   if (view_info->is_cube) {
-      assert(subresource->baseArrayLayer % 6 == 0);
-      assert(subresource->layerCount % 6 == 0);
-   }
-
    const VkImageAspectFlags ds_flags = VK_IMAGE_ASPECT_DEPTH_BIT
                                      | VK_IMAGE_ASPECT_STENCIL_BIT;
 
@@ -522,9 +487,60 @@ anv_DestroyImageView(VkDevice _device, VkImageView _iview,
                           iview->nonrt_surface_state);
    }
 
+   if (iview->image->needs_storage_surface_state) {
+      anv_state_pool_free(&device->surface_state_pool,
+                          iview->storage_surface_state);
+   }
+
    anv_free2(&device->alloc, pAllocator, iview);
 }
 
+VkResult
+anv_CreateBufferView(VkDevice _device,
+                     const VkBufferViewCreateInfo *pCreateInfo,
+                     const VkAllocationCallbacks *pAllocator,
+                     VkBufferView *pView)
+{
+   ANV_FROM_HANDLE(anv_device, device, _device);
+   ANV_FROM_HANDLE(anv_buffer, buffer, pCreateInfo->buffer);
+   struct anv_buffer_view *view;
+
+   /* TODO: Storage texel buffers */
+
+   view = anv_alloc2(&device->alloc, pAllocator, sizeof(*view), 8,
+                     VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (!view)
+      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+   view->bo = buffer->bo;
+   view->offset = buffer->offset + pCreateInfo->offset;
+
+   view->surface_state =
+      anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
+
+   const struct anv_format *format =
+      anv_format_for_vk_format(pCreateInfo->format);
+
+   anv_fill_buffer_surface_state(device, view->surface_state.map, format,
+                                 view->offset, pCreateInfo->range,
+                                 format->isl_layout->bpb / 8);
+
+   *pView = anv_buffer_view_to_handle(view);
+
+   return VK_SUCCESS;
+}
+
+void
+anv_DestroyBufferView(VkDevice _device, VkBufferView bufferView,
+                      const VkAllocationCallbacks *pAllocator)
+{
+   ANV_FROM_HANDLE(anv_device, device, _device);
+   ANV_FROM_HANDLE(anv_buffer_view, view, bufferView);
+
+   anv_state_pool_free(&device->surface_state_pool, view->surface_state);
+   anv_free2(&device->alloc, pAllocator, view);
+}
+
 struct anv_surface *
 anv_image_get_surface_for_aspect_mask(struct anv_image *image, VkImageAspectFlags aspect_mask)
 {
@@ -574,34 +590,11 @@ anv_image_get_surface_for_aspect_mask(struct anv_image *image, VkImageAspectFlag
    }
 }
 
-#if 0
-   VkImageAspectFlags aspect_mask = 0;
-   if (format->depth_format)
-      aspect_mask |= VK_IMAGE_ASPECT_DEPTH_BIT;
-   if (format->has_stencil)
-      aspect_mask |= VK_IMAGE_ASPECT_STENCIL_BIT;
-   if (!aspect_mask)
-      aspect_mask |= VK_IMAGE_ASPECT_COLOR_BIT;
-
-   anv_image_view_init(iview, device,
-      &(VkImageViewCreateInfo) {
-         .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
-         .image = info->image,
-         .viewType = VK_IMAGE_VIEW_TYPE_2D,
-         .format = info->format,
-         .channels = {
-            .r = VK_CHANNEL_SWIZZLE_R,
-            .g = VK_CHANNEL_SWIZZLE_G,
-            .b = VK_CHANNEL_SWIZZLE_B,
-            .a = VK_CHANNEL_SWIZZLE_A,
-         },
-         .subresourceRange = {
-            .aspectMask = aspect_mask,
-            .baseMipLevel = info->mipLevel,
-            .mipLevels = 1,
-            .baseArrayLayer = info->baseArraySlice,
-            .arraySize = info->arraySize,
-         },
-      },
-      NULL);
-#endif
+void
+anv_image_view_fill_image_param(struct anv_device *device,
+                                struct anv_image_view *view,
+                                struct brw_image_param *param)
+{
+   memset(param, 0, sizeof *param);
+   anv_finishme("Actually fill out brw_image_param");
+}