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:
committed by
Marge Bot
parent
d396544fe1
commit
baffad9077
@@ -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, ©);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user