#include "util/debug.h"
#include "util/u_atomic.h"
+#include "util/format/u_format.h"
#include "vk_format.h"
#include "vk_util.h"
#include "drm-uapi/drm_fourcc.h"
enum a6xx_tile_mode
tu6_get_image_tile_mode(struct tu_image *image, int level)
{
- if (image_level_linear(image, level, !!image->layout.ubwc_size))
+ if (image_level_linear(image, level, !!image->layout.ubwc_layer_size))
return TILE6_LINEAR;
else
return image->layout.tile_mode;
ubwc_enabled = false;
}
+ /* Disable UBWC for storage images.
+ *
+ * The closed GL driver skips UBWC for storage images (and additionally
+ * uses linear for writeonly images). We seem to have image tiling working
+ * in freedreno in general, so turnip matches that. freedreno also enables
+ * UBWC on images, but it's not really tested due to the lack of
+ * UBWC-enabled mipmaps in freedreno currently. Just match the closed GL
+ * behavior of no UBWC.
+ */
+ if (image->usage & VK_IMAGE_USAGE_STORAGE_BIT)
+ ubwc_enabled = false;
+
uint32_t ubwc_blockwidth, ubwc_blockheight;
fdl6_get_ubwc_blockwidth(&image->layout,
&ubwc_blockwidth, &ubwc_blockheight);
/* expect UBWC enabled if we asked for it */
assert(modifier != DRM_FORMAT_MOD_QCOM_COMPRESSED || ubwc_enabled);
+ image->layout.ubwc = ubwc_enabled;
+
fdl6_layout(&image->layout, vk_format_to_pipe_format(image->vk_format),
image->samples,
pCreateInfo->extent.width,
pCreateInfo->extent.depth,
pCreateInfo->mipLevels,
pCreateInfo->arrayLayers,
- pCreateInfo->imageType == VK_IMAGE_TYPE_3D,
- ubwc_enabled);
+ pCreateInfo->imageType == VK_IMAGE_TYPE_3D);
*pImage = tu_image_to_handle(image);
}
static uint32_t
-tu6_texswiz(const VkComponentMapping *comps, const unsigned char *fmt_swiz)
+tu6_texswiz(const VkComponentMapping *comps,
+ VkFormat format,
+ VkImageAspectFlagBits aspect_mask)
{
unsigned char swiz[4] = {comps->r, comps->g, comps->b, comps->a};
unsigned char vk_swizzle[] = {
[VK_COMPONENT_SWIZZLE_B] = A6XX_TEX_Z,
[VK_COMPONENT_SWIZZLE_A] = A6XX_TEX_W,
};
+ const unsigned char *fmt_swiz = vk_format_description(format)->swizzle;
+
for (unsigned i = 0; i < 4; i++) {
swiz[i] = (swiz[i] == VK_COMPONENT_SWIZZLE_IDENTITY) ? i : vk_swizzle[swiz[i]];
/* if format has 0/1 in channel, use that (needed for bc1_rgb) */
if (swiz[i] < 4) {
+ if (aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT &&
+ format == VK_FORMAT_D24_UNORM_S8_UINT)
+ swiz[i] = A6XX_TEX_Y;
switch (fmt_swiz[swiz[i]]) {
case PIPE_SWIZZLE_0: swiz[i] = A6XX_TEX_ZERO; break;
case PIPE_SWIZZLE_1: swiz[i] = A6XX_TEX_ONE; break;
iview->vk_format = pCreateInfo->format;
iview->aspect_mask = pCreateInfo->subresourceRange.aspectMask;
- if (iview->aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT) {
- iview->vk_format = vk_format_stencil_only(iview->vk_format);
- } else if (iview->aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT) {
- iview->vk_format = vk_format_depth_only(iview->vk_format);
- }
-
- // should we minify?
- iview->extent = image->extent;
-
iview->base_layer = range->baseArrayLayer;
iview->layer_count = tu_get_layerCount(image, range);
iview->base_mip = range->baseMipLevel;
iview->level_count = tu_get_levelCount(image, range);
+ iview->extent.width = u_minify(image->extent.width, iview->base_mip);
+ iview->extent.height = u_minify(image->extent.height, iview->base_mip);
+ iview->extent.depth = u_minify(image->extent.depth, iview->base_mip);
+
memset(iview->descriptor, 0, sizeof(iview->descriptor));
- const struct tu_native_format *fmt = tu6_get_native_format(iview->vk_format);
+ struct tu_native_format fmt =
+ tu6_format_texture(iview->vk_format, image->layout.tile_mode);
uint64_t base_addr = tu_image_base(image, iview->base_mip, iview->base_layer);
uint64_t ubwc_addr = tu_image_ubwc_base(image, iview->base_mip, iview->base_layer);
uint32_t pitch = tu_image_stride(image, iview->base_mip) / vk_format_get_blockwidth(iview->vk_format);
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 width = iview->extent.width;
+ uint32_t height = iview->extent.height;
+ uint32_t depth = pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_3D ?
+ iview->extent.depth : iview->layer_count;
+
+ unsigned fmt_tex = fmt.fmt;
+ if (iview->aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT &&
+ iview->vk_format == VK_FORMAT_D24_UNORM_S8_UINT)
+ fmt_tex = FMT6_S8Z24_UINT;
iview->descriptor[0] =
A6XX_TEX_CONST_0_TILE_MODE(tile_mode) |
COND(vk_format_is_srgb(iview->vk_format), A6XX_TEX_CONST_0_SRGB) |
- A6XX_TEX_CONST_0_FMT(fmt->tex) |
+ A6XX_TEX_CONST_0_FMT(fmt_tex) |
A6XX_TEX_CONST_0_SAMPLES(tu_msaa_samples(image->samples)) |
- A6XX_TEX_CONST_0_SWAP(image->layout.tile_mode ? WZYX : fmt->swap) |
- tu6_texswiz(&pCreateInfo->components, vk_format_description(iview->vk_format)->swizzle) |
+ A6XX_TEX_CONST_0_SWAP(fmt.swap) |
+ tu6_texswiz(&pCreateInfo->components, iview->vk_format, iview->aspect_mask) |
A6XX_TEX_CONST_0_MIPLVLS(iview->level_count - 1);
iview->descriptor[1] = A6XX_TEX_CONST_1_WIDTH(width) | A6XX_TEX_CONST_1_HEIGHT(height);
iview->descriptor[2] =
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) {
+ if (image->layout.ubwc_layer_size) {
uint32_t block_width, block_height;
fdl6_get_ubwc_blockwidth(&image->layout,
&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.fmt) |
+ 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_layer_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));
+ }
}
}
pAllocator, pImage);
#endif
- const struct wsi_image_create_info *wsi_info =
- vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);
uint64_t modifier = DRM_FORMAT_MOD_INVALID;
+ if (pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
+ const VkImageDrmFormatModifierListCreateInfoEXT *mod_info =
+ vk_find_struct_const(pCreateInfo->pNext,
+ IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
- if (wsi_info) {
modifier = DRM_FORMAT_MOD_LINEAR;
- for (unsigned i = 0; i < wsi_info->modifier_count; i++) {
- if (wsi_info->modifiers[i] == DRM_FORMAT_MOD_QCOM_COMPRESSED)
+ for (unsigned i = 0; i < mod_info->drmFormatModifierCount; i++) {
+ if (mod_info->pDrmFormatModifiers[i] == DRM_FORMAT_MOD_QCOM_COMPRESSED)
modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
}
+ } else {
+ const struct wsi_image_create_info *wsi_info =
+ vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);
+ if (wsi_info && wsi_info->scanout)
+ modifier = DRM_FORMAT_MOD_LINEAR;
}
return tu_image_create(device, pCreateInfo, pAllocator, pImage, modifier);
pLayout->arrayPitch = image->layout.layer_size;
pLayout->depthPitch = slice->size0;
- if (image->layout.ubwc_size) {
+ if (image->layout.ubwc_layer_size) {
/* UBWC starts at offset 0 */
pLayout->offset = 0;
/* UBWC scanout won't match what the kernel wants if we have levels/layers */
}
}
+VkResult tu_GetImageDrmFormatModifierPropertiesEXT(
+ VkDevice device,
+ VkImage _image,
+ VkImageDrmFormatModifierPropertiesEXT* pProperties)
+{
+ TU_FROM_HANDLE(tu_image, image, _image);
+
+ assert(pProperties->sType ==
+ VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT);
+
+ /* TODO invent a modifier for tiled but not UBWC buffers */
+
+ if (!image->layout.tile_mode)
+ pProperties->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
+ else if (image->layout.ubwc_layer_size)
+ pProperties->drmFormatModifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+ else
+ pProperties->drmFormatModifier = DRM_FORMAT_MOD_INVALID;
+
+ return VK_SUCCESS;
+}
+
+
VkResult
tu_CreateImageView(VkDevice _device,
const VkImageViewCreateInfo *pCreateInfo,
{
TU_FROM_HANDLE(tu_buffer, buffer, pCreateInfo->buffer);
- view->range = pCreateInfo->range == VK_WHOLE_SIZE
- ? buffer->size - pCreateInfo->offset
- : pCreateInfo->range;
- view->vk_format = pCreateInfo->format;
+ view->buffer = buffer;
+
+ enum VkFormat vfmt = pCreateInfo->format;
+ enum pipe_format pfmt = vk_format_to_pipe_format(vfmt);
+ const struct tu_native_format fmt = tu6_format_texture(vfmt, TILE6_LINEAR);
+
+ uint32_t range;
+ if (pCreateInfo->range == VK_WHOLE_SIZE)
+ range = buffer->size - pCreateInfo->offset;
+ else
+ range = pCreateInfo->range;
+ uint32_t elements = range / util_format_get_blocksize(pfmt);
+
+ static const VkComponentMapping components = {
+ .r = VK_COMPONENT_SWIZZLE_R,
+ .g = VK_COMPONENT_SWIZZLE_G,
+ .b = VK_COMPONENT_SWIZZLE_B,
+ .a = VK_COMPONENT_SWIZZLE_A,
+ };
+
+ uint64_t iova = tu_buffer_iova(buffer) + pCreateInfo->offset;
+
+ memset(&view->descriptor, 0, sizeof(view->descriptor));
+
+ view->descriptor[0] =
+ A6XX_TEX_CONST_0_TILE_MODE(TILE6_LINEAR) |
+ A6XX_TEX_CONST_0_SWAP(fmt.swap) |
+ A6XX_TEX_CONST_0_FMT(fmt.fmt) |
+ A6XX_TEX_CONST_0_MIPLVLS(0) |
+ tu6_texswiz(&components, vfmt, VK_IMAGE_ASPECT_COLOR_BIT);
+ COND(vk_format_is_srgb(vfmt), A6XX_TEX_CONST_0_SRGB);
+ view->descriptor[1] =
+ A6XX_TEX_CONST_1_WIDTH(elements & MASK(15)) |
+ A6XX_TEX_CONST_1_HEIGHT(elements >> 15);
+ view->descriptor[2] =
+ A6XX_TEX_CONST_2_UNK4 |
+ A6XX_TEX_CONST_2_UNK31;
+ view->descriptor[4] = iova;
+ view->descriptor[5] = iova >> 32;
}
VkResult