VkImageAspectFlags aspect_mask,
enum a6xx_rotation rotation,
bool clear,
+ bool ubwc,
bool scissor)
{
enum a6xx_format format = tu6_base_format(vk_format);
enum a6xx_2d_ifmt ifmt = format_to_ifmt(format);
uint32_t unknown_8c01 = 0;
+ if ((vk_format == VK_FORMAT_D24_UNORM_S8_UINT ||
+ vk_format == VK_FORMAT_X8_D24_UNORM_PACK32) && ubwc) {
+ format = FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
+ }
+
/* note: the only format with partial clearing is D24S8 */
if (vk_format == VK_FORMAT_D24_UNORM_S8_UINT) {
/* preserve stencil channel */
VkFormat vk_format,
VkImageAspectFlags aspect_mask,
enum a6xx_rotation rotation,
- bool clear)
+ bool clear,
+ bool ubwc)
{
tu_emit_cache_flush_ccu(cmd, cs, TU_CMD_CCU_SYSMEM);
- r2d_setup_common(cmd, cs, vk_format, aspect_mask, rotation, clear, false);
+ r2d_setup_common(cmd, cs, vk_format, aspect_mask, rotation, clear, ubwc, false);
}
static void
VkFormat vk_format,
VkImageAspectFlags aspect_mask,
enum a6xx_rotation rotation,
- bool clear)
+ bool clear,
+ bool ubwc)
{
+ enum a6xx_format format = tu6_base_format(vk_format);
+
+ if ((vk_format == VK_FORMAT_D24_UNORM_S8_UINT ||
+ vk_format == VK_FORMAT_X8_D24_UNORM_PACK32) && ubwc) {
+ format = FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
+ }
+
if (!cmd->state.pass) {
tu_emit_cache_flush_ccu(cmd, cs, TU_CMD_CCU_SYSMEM);
tu6_emit_window_scissor(cs, 0, 0, 0x3fff, 0x3fff);
tu_cs_emit_regs(cs, A6XX_SP_FS_RENDER_COMPONENTS(.rt0 = 0xf));
tu_cs_emit_regs(cs, A6XX_SP_FS_MRT_REG(0,
- .color_format = tu6_base_format(vk_format),
+ .color_format = format,
.color_sint = vk_format_is_sint(vk_format),
.color_uint = vk_format_is_uint(vk_format)));
VkFormat vk_format,
VkImageAspectFlags aspect_mask,
enum a6xx_rotation rotation,
- bool clear);
+ bool clear,
+ bool ubwc);
void (*run)(struct tu_cmd_buffer *cmd, struct tu_cs *cs);
};
.baseArrayLayer = subres->baseArrayLayer + layer,
.layerCount = 1,
},
- });
+ }, false);
}
static void
*/
ops->setup(cmd, cs, dst_image->vk_format, info->dstSubresource.aspectMask,
- rotate[mirror_y][mirror_x], false);
+ rotate[mirror_y][mirror_x], false, dst_image->layout[0].ubwc);
if (ops == &r3d_ops) {
r3d_coords_raw(cs, (float[]) {
ops->setup(cmd, cs,
copy_format(dst_image->vk_format, info->imageSubresource.aspectMask, false),
- info->imageSubresource.aspectMask, ROTATE_0, false);
+ info->imageSubresource.aspectMask, ROTATE_0, false, dst_image->layout[0].ubwc);
struct tu_image_view dst;
tu_image_view_copy(&dst, dst_image, dst_image->vk_format, &info->imageSubresource, offset.z, false);
uint32_t pitch = dst_width * vk_format_get_blocksize(dst_format);
uint32_t layer_size = pitch * dst_height;
- ops->setup(cmd, cs, dst_format, VK_IMAGE_ASPECT_COLOR_BIT, ROTATE_0, false);
+ ops->setup(cmd, cs, dst_format, VK_IMAGE_ASPECT_COLOR_BIT, ROTATE_0, false, false);
struct tu_image_view src;
tu_image_view_copy(&src, src_image, src_image->vk_format, &info->imageSubresource, offset.z, stencil_read);
tu_image_view_copy(&staging, &staging_image, src_format,
&staging_subresource, 0, false);
- ops->setup(cmd, cs, src_format, VK_IMAGE_ASPECT_COLOR_BIT, ROTATE_0, false);
+ ops->setup(cmd, cs, src_format, VK_IMAGE_ASPECT_COLOR_BIT, ROTATE_0, false, false);
coords(ops, cs, &staging_offset, &src_offset, &extent);
for (uint32_t i = 0; i < info->extent.depth; i++) {
tu_image_view_copy(&staging, &staging_image, dst_format,
&staging_subresource, 0, false);
- ops->setup(cmd, cs, dst_format, info->dstSubresource.aspectMask, ROTATE_0, false);
+ ops->setup(cmd, cs, dst_format, info->dstSubresource.aspectMask,
+ ROTATE_0, false, dst_image->layout[0].ubwc);
coords(ops, cs, &dst_offset, &staging_offset, &extent);
for (uint32_t i = 0; i < info->extent.depth; i++) {
tu_image_view_copy(&dst, dst_image, format, &info->dstSubresource, dst_offset.z, false);
tu_image_view_copy(&src, src_image, format, &info->srcSubresource, src_offset.z, false);
- ops->setup(cmd, cs, format, info->dstSubresource.aspectMask, ROTATE_0, false);
+ ops->setup(cmd, cs, format, info->dstSubresource.aspectMask,
+ ROTATE_0, false, dst_image->layout[0].ubwc);
coords(ops, cs, &dst_offset, &src_offset, &extent);
for (uint32_t i = 0; i < info->extent.depth; i++) {
VkFormat format = block_size == 4 ? VK_FORMAT_R32_UINT : VK_FORMAT_R8_UNORM;
uint64_t blocks = size / block_size;
- ops->setup(cmd, cs, format, VK_IMAGE_ASPECT_COLOR_BIT, ROTATE_0, false);
+ ops->setup(cmd, cs, format, VK_IMAGE_ASPECT_COLOR_BIT, ROTATE_0, false, false);
while (blocks) {
uint32_t src_x = (src_va & 63) / block_size;
uint64_t dst_va = tu_buffer_iova(buffer) + dstOffset;
uint32_t blocks = fillSize / 4;
- ops->setup(cmd, cs, VK_FORMAT_R32_UINT, VK_IMAGE_ASPECT_COLOR_BIT, ROTATE_0, true);
+ ops->setup(cmd, cs, VK_FORMAT_R32_UINT, VK_IMAGE_ASPECT_COLOR_BIT, ROTATE_0, true, false);
ops->clear_value(cs, VK_FORMAT_R32_UINT, &(VkClearValue){.color = {.uint32[0] = data}});
while (blocks) {
tu_bo_list_add(&cmd->bo_list, src_image->bo, MSM_SUBMIT_BO_READ);
tu_bo_list_add(&cmd->bo_list, dst_image->bo, MSM_SUBMIT_BO_WRITE);
- ops->setup(cmd, cs, dst_image->vk_format, VK_IMAGE_ASPECT_COLOR_BIT, ROTATE_0, false);
+ ops->setup(cmd, cs, dst_image->vk_format, VK_IMAGE_ASPECT_COLOR_BIT,
+ ROTATE_0, false, dst_image->layout[0].ubwc);
for (uint32_t i = 0; i < regionCount; ++i) {
const VkImageResolve *info = &pRegions[i];
assert(src->image->vk_format == dst->image->vk_format);
- ops->setup(cmd, cs, dst->image->vk_format, VK_IMAGE_ASPECT_COLOR_BIT, ROTATE_0, false);
+ ops->setup(cmd, cs, dst->image->vk_format, VK_IMAGE_ASPECT_COLOR_BIT,
+ ROTATE_0, false, dst->ubwc_enabled);
ops->coords(cs, &rect->offset, &rect->offset, &rect->extent);
for (uint32_t i = 0; i < layers; i++) {
const struct blit_ops *ops = image->samples > 1 ? &r3d_ops : &r2d_ops;
- ops->setup(cmd, cs, format, range->aspectMask, ROTATE_0, true);
+ ops->setup(cmd, cs, format, range->aspectMask, ROTATE_0, true, image->layout[0].ubwc);
ops->clear_value(cs, image->vk_format, clear_value);
for (unsigned j = 0; j < level_count; j++) {
const struct tu_image_view *iview =
cmd->state.framebuffer->attachments[a].attachment;
- ops->setup(cmd, cs, iview->image->vk_format, attachments[j].aspectMask, ROTATE_0, true);
+ ops->setup(cmd, cs, iview->image->vk_format, attachments[j].aspectMask,
+ ROTATE_0, true, iview->ubwc_enabled);
ops->clear_value(cs, iview->image->vk_format, &attachments[j].clearValue);
/* Wait for the flushes we triggered manually to complete */
if (attachment->samples > 1)
ops = &r3d_ops;
- ops->setup(cmd, cs, attachment->format, attachment->clear_mask, ROTATE_0, true);
+ ops->setup(cmd, cs, attachment->format, attachment->clear_mask, ROTATE_0,
+ true, iview->ubwc_enabled);
ops->coords(cs, &info->renderArea.offset, NULL, &info->renderArea.extent);
ops->clear_value(cs, attachment->format, &info->pClearValues[a]);
return;
}
- r2d_setup_common(cmd, cs, dst->format, VK_IMAGE_ASPECT_COLOR_BIT, ROTATE_0, false, true);
+ r2d_setup_common(cmd, cs, dst->format, VK_IMAGE_ASPECT_COLOR_BIT,
+ ROTATE_0, false, iview->ubwc_enabled, true);
r2d_dst(cs, iview, 0);
r2d_coords(cs, &render_area->offset, &render_area->offset, &render_area->extent);
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);
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,
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;
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;
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 ? */
}
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] =
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));
.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),
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);
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)) |