diff --git a/src/nouveau/vulkan/nvk_cmd_copy.c b/src/nouveau/vulkan/nvk_cmd_copy.c index 6bdd204feba..bb2d833a989 100644 --- a/src/nouveau/vulkan/nvk_cmd_copy.c +++ b/src/nouveau/vulkan/nvk_cmd_copy.c @@ -712,77 +712,109 @@ nvk_CmdCopyImage2(VkCommandBuffer commandBuffer, const VkImageAspectFlagBits src_aspects = region->srcSubresource.aspectMask; - uint8_t src_plane = nvk_image_aspects_to_plane(src, src_aspects); - const VkImageAspectFlagBits dst_aspects = region->dstSubresource.aspectMask; - uint8_t dst_plane = nvk_image_aspects_to_plane(dst, dst_aspects); - const struct nil_format src_format = src->planes[src_plane].nil.format; - const enum nil_sample_layout src_sample_layout = - src->planes[src_plane].nil.sample_layout; + const bool src_separate_zs = src->separate_zs && + src_aspects == (VK_IMAGE_ASPECT_DEPTH_BIT | + VK_IMAGE_ASPECT_STENCIL_BIT); + const bool dst_separate_zs = dst->separate_zs && + dst_aspects == (VK_IMAGE_ASPECT_DEPTH_BIT | + VK_IMAGE_ASPECT_STENCIL_BIT); + assert(src_separate_zs == dst_separate_zs); - struct nouveau_copy copy = { - .src = nouveau_copy_rect_image(src, &src->planes[src_plane], - region->srcOffset, - ®ion->srcSubresource), - .dst = nouveau_copy_rect_image(dst, &dst->planes[dst_plane], - region->dstOffset, - ®ion->dstSubresource), - .extent_el = nil_extent4d_px_to_el(extent4d_px, src_format, - src_sample_layout), - }; + if (src_separate_zs && dst_separate_zs) { + assert(src->plane_count == 2); + assert(dst->plane_count == 2); - assert(src_aspects == region->srcSubresource.aspectMask); - switch (src_format.p_format) { - case PIPE_FORMAT_Z24_UNORM_S8_UINT: - if (src_aspects == VK_IMAGE_ASPECT_DEPTH_BIT) { - copy.remap.comp_size = 1; - copy.remap.dst[0] = NV90B5_SET_REMAP_COMPONENTS_DST_X_SRC_X; - copy.remap.dst[1] = NV90B5_SET_REMAP_COMPONENTS_DST_Y_SRC_Y; - copy.remap.dst[2] = NV90B5_SET_REMAP_COMPONENTS_DST_Z_SRC_Z; - copy.remap.dst[3] = NV90B5_SET_REMAP_COMPONENTS_DST_W_NO_WRITE; - } else if (src_aspects == VK_IMAGE_ASPECT_STENCIL_BIT) { - copy.remap.comp_size = 1; - copy.remap.dst[0] = NV90B5_SET_REMAP_COMPONENTS_DST_X_NO_WRITE; - copy.remap.dst[1] = NV90B5_SET_REMAP_COMPONENTS_DST_Y_NO_WRITE; - copy.remap.dst[2] = NV90B5_SET_REMAP_COMPONENTS_DST_Z_NO_WRITE; - copy.remap.dst[3] = NV90B5_SET_REMAP_COMPONENTS_DST_W_SRC_W; - } else { - /* If we're copying both, there's nothing special to do */ - assert(src_aspects == (VK_IMAGE_ASPECT_DEPTH_BIT | - VK_IMAGE_ASPECT_STENCIL_BIT)); + for (unsigned plane = 0; plane < 2; plane++) { + const struct nil_format format = src->planes[plane].nil.format; + const enum nil_sample_layout sample_layout = + src->planes[plane].nil.sample_layout; + assert(dst->planes[plane].nil.format.p_format == format.p_format); + assert(dst->planes[plane].nil.sample_layout == sample_layout); + + struct nouveau_copy copy = { + .src = nouveau_copy_rect_image(src, &src->planes[plane], + region->srcOffset, + ®ion->srcSubresource), + .dst = nouveau_copy_rect_image(dst, &dst->planes[plane], + region->dstOffset, + ®ion->dstSubresource), + .extent_el = nil_extent4d_px_to_el(extent4d_px, format, + sample_layout), + }; + nouveau_copy_rect(cmd, ©); } - break; - case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: - if (src_aspects == VK_IMAGE_ASPECT_DEPTH_BIT) { - copy.remap.comp_size = 4; - copy.remap.dst[0] = NV90B5_SET_REMAP_COMPONENTS_DST_X_SRC_X; - copy.remap.dst[1] = NV90B5_SET_REMAP_COMPONENTS_DST_Y_NO_WRITE; - copy.remap.dst[2] = NV90B5_SET_REMAP_COMPONENTS_DST_Z_NO_WRITE; - copy.remap.dst[3] = NV90B5_SET_REMAP_COMPONENTS_DST_W_NO_WRITE; - } else if (src_aspects == VK_IMAGE_ASPECT_STENCIL_BIT) { - copy.remap.comp_size = 4; - copy.remap.dst[0] = NV90B5_SET_REMAP_COMPONENTS_DST_X_NO_WRITE; - copy.remap.dst[1] = NV90B5_SET_REMAP_COMPONENTS_DST_Y_SRC_Y; - copy.remap.dst[2] = NV90B5_SET_REMAP_COMPONENTS_DST_Z_NO_WRITE; - copy.remap.dst[3] = NV90B5_SET_REMAP_COMPONENTS_DST_W_NO_WRITE; - } else { - /* If we're copying both, there's nothing special to do */ - assert(src_aspects == (VK_IMAGE_ASPECT_DEPTH_BIT | - VK_IMAGE_ASPECT_STENCIL_BIT)); + } else { + uint8_t src_plane = nvk_image_aspects_to_plane(src, src_aspects); + uint8_t dst_plane = nvk_image_aspects_to_plane(dst, dst_aspects); + + const struct nil_format src_format = src->planes[src_plane].nil.format; + const enum nil_sample_layout src_sample_layout = + src->planes[src_plane].nil.sample_layout; + + struct nouveau_copy copy = { + .src = nouveau_copy_rect_image(src, &src->planes[src_plane], + region->srcOffset, + ®ion->srcSubresource), + .dst = nouveau_copy_rect_image(dst, &dst->planes[dst_plane], + region->dstOffset, + ®ion->dstSubresource), + .extent_el = nil_extent4d_px_to_el(extent4d_px, src_format, + src_sample_layout), + }; + + switch (src_format.p_format) { + case PIPE_FORMAT_Z24_UNORM_S8_UINT: + if (src_aspects == VK_IMAGE_ASPECT_DEPTH_BIT) { + copy.remap.comp_size = 1; + copy.remap.dst[0] = NV90B5_SET_REMAP_COMPONENTS_DST_X_SRC_X; + copy.remap.dst[1] = NV90B5_SET_REMAP_COMPONENTS_DST_Y_SRC_Y; + copy.remap.dst[2] = NV90B5_SET_REMAP_COMPONENTS_DST_Z_SRC_Z; + copy.remap.dst[3] = NV90B5_SET_REMAP_COMPONENTS_DST_W_NO_WRITE; + } else if (src_aspects == VK_IMAGE_ASPECT_STENCIL_BIT) { + copy.remap.comp_size = 1; + copy.remap.dst[0] = NV90B5_SET_REMAP_COMPONENTS_DST_X_NO_WRITE; + copy.remap.dst[1] = NV90B5_SET_REMAP_COMPONENTS_DST_Y_NO_WRITE; + copy.remap.dst[2] = NV90B5_SET_REMAP_COMPONENTS_DST_Z_NO_WRITE; + copy.remap.dst[3] = NV90B5_SET_REMAP_COMPONENTS_DST_W_SRC_W; + } else { + /* If we're copying both, there's nothing special to do */ + assert(src_aspects == (VK_IMAGE_ASPECT_DEPTH_BIT | + VK_IMAGE_ASPECT_STENCIL_BIT)); + } + break; + case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: + if (src_aspects == VK_IMAGE_ASPECT_DEPTH_BIT) { + copy.remap.comp_size = 4; + copy.remap.dst[0] = NV90B5_SET_REMAP_COMPONENTS_DST_X_SRC_X; + copy.remap.dst[1] = NV90B5_SET_REMAP_COMPONENTS_DST_Y_NO_WRITE; + copy.remap.dst[2] = NV90B5_SET_REMAP_COMPONENTS_DST_Z_NO_WRITE; + copy.remap.dst[3] = NV90B5_SET_REMAP_COMPONENTS_DST_W_NO_WRITE; + } else if (src_aspects == VK_IMAGE_ASPECT_STENCIL_BIT) { + copy.remap.comp_size = 4; + copy.remap.dst[0] = NV90B5_SET_REMAP_COMPONENTS_DST_X_NO_WRITE; + copy.remap.dst[1] = NV90B5_SET_REMAP_COMPONENTS_DST_Y_SRC_Y; + copy.remap.dst[2] = NV90B5_SET_REMAP_COMPONENTS_DST_Z_NO_WRITE; + copy.remap.dst[3] = NV90B5_SET_REMAP_COMPONENTS_DST_W_NO_WRITE; + } else { + /* If we're copying both, there's nothing special to do */ + assert(src_aspects == (VK_IMAGE_ASPECT_DEPTH_BIT | + VK_IMAGE_ASPECT_STENCIL_BIT)); + } + break; + case PIPE_FORMAT_Z16_UNORM_S8_UINT: + case PIPE_FORMAT_S8_UINT_Z24_UNORM: + unreachable("Unsupported packed depth/stencil format"); + break; + default: + copy.remap = nouveau_copy_remap_format(src_format.p_format); + break; } - break; - case PIPE_FORMAT_Z16_UNORM_S8_UINT: - case PIPE_FORMAT_S8_UINT_Z24_UNORM: - unreachable("Unsupported packed depth/stencil format"); - break; - default: - copy.remap = nouveau_copy_remap_format(src_format.p_format); - break; + + nouveau_copy_rect(cmd, ©); } - - nouveau_copy_rect(cmd, ©); } } diff --git a/src/nouveau/vulkan/nvk_image.c b/src/nouveau/vulkan/nvk_image.c index 22745a45427..ef3b1227071 100644 --- a/src/nouveau/vulkan/nvk_image.c +++ b/src/nouveau/vulkan/nvk_image.c @@ -23,6 +23,21 @@ #include "clb197.h" #include "clc197.h" #include "clc597.h" +#include "clcd97.h" + +static bool +nvk_use_separate_zs(const struct nvk_physical_device *pdev, VkFormat vk_format) +{ + /* Separate depth/stencil doesn't exist pre-Blackwell */ + if (pdev->info.cls_eng3d < BLACKWELL_A) + return false; + + const VkImageAspectFlags format_aspects = vk_format_aspects(vk_format); + + /* Just depth or just stencil is still a single plane */ + return format_aspects == (VK_IMAGE_ASPECT_DEPTH_BIT | + VK_IMAGE_ASPECT_STENCIL_BIT); +} static VkFormatFeatureFlags2 nvk_get_image_plane_format_features(const struct nvk_physical_device *pdev, @@ -566,8 +581,9 @@ nvk_GetPhysicalDeviceImageFormatProperties2( } } - const unsigned plane_count = - vk_format_get_plane_count(pImageFormatInfo->format); + unsigned plane_count = vk_format_get_plane_count(pImageFormatInfo->format); + if (nvk_use_separate_zs(pdev, pImageFormatInfo->format)) + plane_count = 2; /* From the Vulkan 1.3.259 spec, VkImageCreateInfo: * @@ -596,7 +612,7 @@ nvk_GetPhysicalDeviceImageFormatProperties2( * could probably support sparse for VK_FORMAT_B8G8R8G8_422_UNORM, we * disable it because the standard block sizes are funky. */ - if (ycbcr_info && + if ((plane_count > 1 || ycbcr_info != NULL) && (pImageFormatInfo->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT)) return VK_ERROR_FORMAT_NOT_SUPPORTED; @@ -784,6 +800,11 @@ nvk_image_init(struct nvk_device *dev, image->disjoint = image->plane_count > 1 && (image->vk.create_flags & VK_IMAGE_CREATE_DISJOINT_BIT); + if (nvk_use_separate_zs(pdev, image->vk.format)) { + image->separate_zs = true; + image->plane_count = 2; + } + if (image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) { /* Sparse multiplane is not supported */ assert(image->plane_count == 1); @@ -894,6 +915,13 @@ nvk_image_init(struct nvk_device *dev, const uint8_t height_scale = ycbcr_info ? ycbcr_info->planes[plane].denominator_scales[1] : 1; + if (image->separate_zs) { + if (plane == 0) + format = vk_format_depth_only(format); + else if (plane == 1) + format = vk_format_stencil_only(format); + } + nil_info[plane] = (struct nil_image_init_info) { .dim = vk_image_type_to_nil_dim(image->vk.image_type), .format = nil_format(nvk_format_to_pipe_format(format)), diff --git a/src/nouveau/vulkan/nvk_image.h b/src/nouveau/vulkan/nvk_image.h index 99d3f9921f1..6d7cdc2760a 100644 --- a/src/nouveau/vulkan/nvk_image.h +++ b/src/nouveau/vulkan/nvk_image.h @@ -79,6 +79,12 @@ struct nvk_image { */ bool disjoint; + /** True if this image uses separate depth/stencil + * + * In this case, stencil will be in planes[1]. + */ + bool separate_zs; + uint8_t plane_count; struct nvk_image_plane planes[NVK_MAX_IMAGE_PLANES]; @@ -114,7 +120,7 @@ nvk_image_base_address(const struct nvk_image *image, uint8_t plane) } static inline uint8_t -nvk_image_aspects_to_plane(ASSERTED const struct nvk_image *image, +nvk_image_aspects_to_plane(const struct nvk_image *image, VkImageAspectFlags aspectMask) { /* Memory planes are only allowed for memory operations */ @@ -131,6 +137,15 @@ nvk_image_aspects_to_plane(ASSERTED const struct nvk_image *image, VK_IMAGE_ASPECT_STENCIL_BIT) || util_bitcount(aspectMask) == 1); + if (image->separate_zs) { + assert(util_bitcount(aspectMask) == 1); + switch(aspectMask) { + case VK_IMAGE_ASPECT_DEPTH_BIT: return 0; + case VK_IMAGE_ASPECT_STENCIL_BIT: return 1; + default: unreachable("Not a depth/stencil aspect"); + } + } + switch(aspectMask) { case VK_IMAGE_ASPECT_PLANE_1_BIT: return 1; case VK_IMAGE_ASPECT_PLANE_2_BIT: return 2; diff --git a/src/nouveau/vulkan/nvk_image_view.c b/src/nouveau/vulkan/nvk_image_view.c index 41c1dad9a52..e179010dbf9 100644 --- a/src/nouveau/vulkan/nvk_image_view.c +++ b/src/nouveau/vulkan/nvk_image_view.c @@ -108,15 +108,26 @@ nvk_image_view_init(struct nvk_device *dev, vk_image_view_init(&dev->vk, &view->vk, driver_internal, pCreateInfo); /* First, figure out which image planes we need. - * For depth/stencil, we only have plane so simply assert + * For depth/stencil, we may only have plane so simply assert * and then map directly betweeen the image and view plane */ if (image->vk.aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { - assert(image->plane_count == 1); - assert(nvk_image_aspects_to_plane(image, view->vk.aspects) == 0); - view->plane_count = 1; - view->planes[0].image_plane = 0; + view->separate_zs = + image->separate_zs && + view->vk.aspects == (VK_IMAGE_ASPECT_DEPTH_BIT | + VK_IMAGE_ASPECT_STENCIL_BIT); + + if (view->separate_zs) { + assert(image->plane_count == 2); + view->plane_count = 2; + view->planes[0].image_plane = 0; + view->planes[1].image_plane = 1; + } else { + view->plane_count = 1; + view->planes[0].image_plane = + nvk_image_aspects_to_plane(image, view->vk.aspects); + } } else { /* For other formats, retrieve the plane count from the aspect mask * and then walk through the aspect mask to map each image plane @@ -139,11 +150,14 @@ nvk_image_view_init(struct nvk_device *dev, const struct vk_format_ycbcr_info *ycbcr_info = vk_format_get_ycbcr_info(view->vk.format); - assert(ycbcr_info || view_plane == 0); + assert(ycbcr_info || view_plane == 0 || view->separate_zs); VkFormat plane_format = ycbcr_info ? ycbcr_info->planes[view_plane].format : view->vk.format; + enum pipe_format p_format = nvk_format_to_pipe_format(plane_format); - if (view->vk.aspects == VK_IMAGE_ASPECT_STENCIL_BIT) + if (image->separate_zs) + p_format = nil_image.format.p_format; + else if (view->vk.aspects == VK_IMAGE_ASPECT_STENCIL_BIT) p_format = util_format_stencil_only(p_format); struct nil_view nil_view = { diff --git a/src/nouveau/vulkan/nvk_image_view.h b/src/nouveau/vulkan/nvk_image_view.h index 91f5015183e..ec0ba458ff9 100644 --- a/src/nouveau/vulkan/nvk_image_view.h +++ b/src/nouveau/vulkan/nvk_image_view.h @@ -16,6 +16,8 @@ struct nvk_device; struct nvk_image_view { struct vk_image_view vk; + bool separate_zs; + uint8_t plane_count; struct { uint8_t image_plane;