tu: Use an input for the layer when lowering input attachments
[mesa.git] / src / freedreno / vulkan / tu_image.c
index 9087806fe47fd06f53421f6f755fcb96a3a6397f..6f2dc0421d064013b339d0ff90814e88e04e63a8 100644 (file)
@@ -43,6 +43,7 @@ tu6_plane_count(VkFormat format)
    default:
       return 1;
    case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+   case VK_FORMAT_D32_SFLOAT_S8_UINT:
       return 2;
    case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
       return 3;
@@ -58,13 +59,15 @@ tu6_plane_format(VkFormat format, uint32_t plane)
       return plane ? VK_FORMAT_R8G8_UNORM : VK_FORMAT_R8_UNORM;
    case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
       return VK_FORMAT_R8_UNORM;
+   case VK_FORMAT_D32_SFLOAT_S8_UINT:
+      return plane ? VK_FORMAT_S8_UINT : VK_FORMAT_D32_SFLOAT;
    default:
       return format;
    }
 }
 
 static uint32_t
-tu6_plane_index(VkImageAspectFlags aspect_mask)
+tu6_plane_index(VkFormat format, VkImageAspectFlags aspect_mask)
 {
    switch (aspect_mask) {
    default:
@@ -73,6 +76,8 @@ tu6_plane_index(VkImageAspectFlags aspect_mask)
       return 1;
    case VK_IMAGE_ASPECT_PLANE_2_BIT:
       return 2;
+   case VK_IMAGE_ASPECT_STENCIL_BIT:
+      return format == VK_FORMAT_D32_SFLOAT_S8_UINT;
    }
 }
 
@@ -194,6 +199,23 @@ tu_image_create(VkDevice _device,
    if (image->usage & VK_IMAGE_USAGE_STORAGE_BIT)
       ubwc_enabled = false;
 
+   /* Disable UBWC for D24S8 on A630 in some cases
+    *
+    * VK_IMAGE_ASPECT_STENCIL_BIT image view requires to be able to sample
+    * from the stencil component as UINT, however no format allows this
+    * on a630 (the special FMT6_Z24_UINT_S8_UINT format is missing)
+    *
+    * It must be sampled as FMT6_8_8_8_8_UINT, which is not UBWC-compatible
+    *
+    * Additionally, the special AS_R8G8B8A8 format is broken without UBWC,
+    * so we have to fallback to 8_8_8_8_UNORM when UBWC is disabled
+    */
+   if (device->physical_device->limited_z24s8 &&
+       image->vk_format == VK_FORMAT_D24_UNORM_S8_UINT &&
+       (image->usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))) {
+      ubwc_enabled = false;
+   }
+
    /* expect UBWC enabled if we asked for it */
    assert(modifier != DRM_FORMAT_MOD_QCOM_COMPRESSED || ubwc_enabled);
 
@@ -211,6 +233,10 @@ tu_image_create(VkDevice _device,
             width0 = (width0 + 1) >> 1;
             height0 = (height0 + 1) >> 1;
             break;
+         case VK_FORMAT_D32_SFLOAT_S8_UINT:
+            /* no UBWC for separate stencil */
+            ubwc_enabled = false;
+            break;
          default:
             break;
          }
@@ -300,7 +326,8 @@ static uint32_t
 tu6_texswiz(const VkComponentMapping *comps,
             const struct tu_sampler_ycbcr_conversion *conversion,
             VkFormat format,
-            VkImageAspectFlagBits aspect_mask)
+            VkImageAspectFlagBits aspect_mask,
+            bool limited_z24s8)
 {
    unsigned char swiz[4] = {
       A6XX_TEX_X, A6XX_TEX_Y, A6XX_TEX_Z, A6XX_TEX_W,
@@ -321,10 +348,16 @@ tu6_texswiz(const VkComponentMapping *comps,
       swiz[3] = A6XX_TEX_ONE;
       break;
    case VK_FORMAT_D24_UNORM_S8_UINT:
-      /* for D24S8, stencil is in the 2nd channel of the hardware format */
       if (aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT) {
-         swiz[0] = A6XX_TEX_Y;
-         swiz[1] = A6XX_TEX_ZERO;
+         if (limited_z24s8) {
+            /* using FMT6_8_8_8_8_UINT */
+            swiz[0] = A6XX_TEX_W;
+            swiz[1] = A6XX_TEX_ZERO;
+         } else {
+            /* using FMT6_Z24_UINT_S8_UINT */
+            swiz[0] = A6XX_TEX_Y;
+            swiz[1] = A6XX_TEX_ZERO;
+         }
       }
    default:
       break;
@@ -348,6 +381,14 @@ tu_cs_image_ref(struct tu_cs *cs, const struct tu_image_view *iview, uint32_t la
    tu_cs_emit_qw(cs, iview->base_addr + iview->layer_size * layer);
 }
 
+void
+tu_cs_image_stencil_ref(struct tu_cs *cs, const struct tu_image_view *iview, uint32_t layer)
+{
+   tu_cs_emit(cs, iview->stencil_PITCH);
+   tu_cs_emit(cs, iview->stencil_layer_size >> 6);
+   tu_cs_emit_qw(cs, iview->stencil_base_addr + iview->stencil_layer_size * layer);
+}
+
 void
 tu_cs_image_ref_2d(struct tu_cs *cs, const struct tu_image_view *iview, uint32_t layer, bool src)
 {
@@ -365,7 +406,8 @@ tu_cs_image_flag_ref(struct tu_cs *cs, const struct tu_image_view *iview, uint32
 
 void
 tu_image_view_init(struct tu_image_view *iview,
-                   const VkImageViewCreateInfo *pCreateInfo)
+                   const VkImageViewCreateInfo *pCreateInfo,
+                   bool limited_z24s8)
 {
    TU_FROM_HANDLE(tu_image, image, pCreateInfo->image);
    const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
@@ -385,7 +427,7 @@ tu_image_view_init(struct tu_image_view *iview,
       break;
    case VK_IMAGE_TYPE_3D:
       assert(range->baseArrayLayer + tu_get_layerCount(image, range) <=
-             tu_minify(image->extent.depth, range->baseMipLevel));
+             u_minify(image->extent.depth, range->baseMipLevel));
       break;
    default:
       unreachable("bad VkImageType");
@@ -395,7 +437,8 @@ tu_image_view_init(struct tu_image_view *iview,
 
    memset(iview->descriptor, 0, sizeof(iview->descriptor));
 
-   struct fdl_layout *layout = &image->layout[tu6_plane_index(aspect_mask)];
+   struct fdl_layout *layout =
+      &image->layout[tu6_plane_index(image->vk_format, aspect_mask)];
 
    uint32_t width = u_minify(layout->width0, range->baseMipLevel);
    uint32_t height = u_minify(layout->height0, range->baseMipLevel);
@@ -422,6 +465,9 @@ tu_image_view_init(struct tu_image_view *iview,
    uint32_t ubwc_pitch = fdl_ubwc_pitch(layout, range->baseMipLevel);
    uint32_t layer_size = fdl_layer_stride(layout, range->baseMipLevel);
 
+   if (aspect_mask != VK_IMAGE_ASPECT_COLOR_BIT)
+      format = tu6_plane_format(format, tu6_plane_index(format, aspect_mask));
+
    struct tu_native_format fmt = tu6_format_texture(format, layout->tile_mode);
    /* note: freedreno layout assumes no TILE_ALL bit for non-UBWC
     * this means smaller mipmap levels have a linear tile mode
@@ -430,12 +476,18 @@ tu_image_view_init(struct tu_image_view *iview,
 
    bool ubwc_enabled = fdl_ubwc_enabled(layout, range->baseMipLevel);
 
+   bool is_d24s8 = (format == VK_FORMAT_D24_UNORM_S8_UINT ||
+                    format == VK_FORMAT_X8_D24_UNORM_PACK32);
+
+   if (is_d24s8 && ubwc_enabled)
+      fmt.fmt = FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
+
    unsigned fmt_tex = fmt.fmt;
-   if (fmt_tex == FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8) {
+   if (is_d24s8) {
       if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT)
          fmt_tex = FMT6_Z24_UNORM_S8_UINT;
       if (aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT)
-         fmt_tex = FMT6_S8Z24_UINT;
+         fmt_tex = limited_z24s8 ? FMT6_8_8_8_8_UINT : FMT6_Z24_UINT_S8_UINT;
       /* TODO: also use this format with storage descriptor ? */
    }
 
@@ -445,7 +497,7 @@ tu_image_view_init(struct tu_image_view *iview,
       A6XX_TEX_CONST_0_FMT(fmt_tex) |
       A6XX_TEX_CONST_0_SAMPLES(tu_msaa_samples(image->samples)) |
       A6XX_TEX_CONST_0_SWAP(fmt.swap) |
-      tu6_texswiz(&pCreateInfo->components, conversion, format, aspect_mask) |
+      tu6_texswiz(&pCreateInfo->components, conversion, format, aspect_mask, limited_z24s8) |
       A6XX_TEX_CONST_0_MIPLVLS(tu_get_levelCount(image, range) - 1);
    iview->descriptor[1] = A6XX_TEX_CONST_1_WIDTH(width) | A6XX_TEX_CONST_1_HEIGHT(height);
    iview->descriptor[2] =
@@ -551,6 +603,9 @@ tu_image_view_init(struct tu_image_view *iview,
    struct tu_native_format cfmt = tu6_format_color(format, layout->tile_mode);
    cfmt.tile_mode = fmt.tile_mode;
 
+   if (is_d24s8 && ubwc_enabled)
+      cfmt.fmt = FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
+
    if (image->usage & VK_IMAGE_USAGE_STORAGE_BIT) {
       memset(iview->storage_descriptor, 0, sizeof(iview->storage_descriptor));
 
@@ -589,6 +644,7 @@ tu_image_view_init(struct tu_image_view *iview,
                               .color_tile_mode = cfmt.tile_mode,
                               .color_format = cfmt.fmt,
                               .color_swap = cfmt.swap).value;
+
    iview->SP_FS_MRT_REG = A6XX_SP_FS_MRT_REG(0,
                               .color_format = cfmt.fmt,
                               .color_sint = vk_format_is_sint(format),
@@ -607,6 +663,14 @@ tu_image_view_init(struct tu_image_view *iview,
       .color_format = cfmt.fmt,
       .color_swap = cfmt.swap,
       .flags = ubwc_enabled).value;
+
+   if (image->vk_format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
+      layout = &image->layout[1];
+      iview->stencil_base_addr = image->bo->iova + image->bo_offset +
+         fdl_surface_offset(layout, range->baseMipLevel, range->baseArrayLayer);
+      iview->stencil_layer_size = fdl_layer_stride(layout, range->baseMipLevel);
+      iview->stencil_PITCH = A6XX_RB_STENCIL_BUFFER_PITCH(fdl_pitch(layout, range->baseMipLevel)).value;
+   }
 }
 
 VkResult
@@ -685,7 +749,7 @@ tu_GetImageSubresourceLayout(VkDevice _device,
    TU_FROM_HANDLE(tu_image, image, _image);
 
    struct fdl_layout *layout =
-      &image->layout[tu6_plane_index(pSubresource->aspectMask)];
+      &image->layout[tu6_plane_index(image->vk_format, pSubresource->aspectMask)];
    const struct fdl_slice *slice = layout->slices + pSubresource->mipLevel;
 
    pLayout->offset =
@@ -740,7 +804,7 @@ tu_CreateImageView(VkDevice _device,
    if (view == NULL)
       return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
 
-   tu_image_view_init(view, pCreateInfo);
+   tu_image_view_init(view, pCreateInfo, device->physical_device->limited_z24s8);
 
    *pView = tu_image_view_to_handle(view);
 
@@ -797,7 +861,7 @@ tu_buffer_view_init(struct tu_buffer_view *view,
       A6XX_TEX_CONST_0_SWAP(fmt.swap) |
       A6XX_TEX_CONST_0_FMT(fmt.fmt) |
       A6XX_TEX_CONST_0_MIPLVLS(0) |
-      tu6_texswiz(&components, NULL, vfmt, VK_IMAGE_ASPECT_COLOR_BIT);
+      tu6_texswiz(&components, NULL, vfmt, VK_IMAGE_ASPECT_COLOR_BIT, false);
       COND(vk_format_is_srgb(vfmt), A6XX_TEX_CONST_0_SRGB);
    view->descriptor[1] =
       A6XX_TEX_CONST_1_WIDTH(elements & MASK(15)) |