nvk: Allocate separate planes for depth and stencil on Blackwell+

Blackwell adds separate depth/stencil support (finally!) and interleaved
depth/stencil no longer seems to work.  We employ the same trick as ANV
and several other drivers and put stencil in nil_image::planes[1].

Co-authored-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35843>
This commit is contained in:
Faith Ekstrand
2025-06-30 12:29:57 -04:00
committed by Marge Bot
parent d396544fe1
commit baffad9077
5 changed files with 165 additions and 74 deletions
+95 -63
View File
@@ -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,
&region->srcSubresource),
.dst = nouveau_copy_rect_image(dst, &dst->planes[dst_plane],
region->dstOffset,
&region->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,
&region->srcSubresource),
.dst = nouveau_copy_rect_image(dst, &dst->planes[plane],
region->dstOffset,
&region->dstSubresource),
.extent_el = nil_extent4d_px_to_el(extent4d_px, format,
sample_layout),
};
nouveau_copy_rect(cmd, &copy);
}
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,
&region->srcSubresource),
.dst = nouveau_copy_rect_image(dst, &dst->planes[dst_plane],
region->dstOffset,
&region->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, &copy);
}
nouveau_copy_rect(cmd, &copy);
}
}
+31 -3
View File
@@ -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)),
+16 -1
View File
@@ -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;
+21 -7
View File
@@ -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 = {
+2
View File
@@ -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;