nvk: Enable multiplane images and image views

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>
This commit is contained in:
Mohamed Ahmed 2023-07-12 14:18:49 -05:00 committed by Marge Bot
parent 39d8d3811d
commit e41031d8ff
10 changed files with 367 additions and 198 deletions

View file

@ -69,7 +69,8 @@ static struct nouveau_copy_buffer
nouveau_copy_rect_image( nouveau_copy_rect_image(
struct nvk_image *img, struct nvk_image *img,
VkOffset3D offset_px, VkOffset3D offset_px,
const VkImageSubresourceLayers *sub_res) const VkImageSubresourceLayers *sub_res,
const uint8_t plane)
{ {
const VkExtent3D lvl_extent_px = const VkExtent3D lvl_extent_px =
vk_image_mip_level_extent(&img->vk, sub_res->mipLevel); vk_image_mip_level_extent(&img->vk, sub_res->mipLevel);
@ -81,17 +82,17 @@ nouveau_copy_rect_image(
vk_to_nil_offset(offset_px, sub_res->baseArrayLayer); vk_to_nil_offset(offset_px, sub_res->baseArrayLayer);
struct nouveau_copy_buffer buf = { struct nouveau_copy_buffer buf = {
.base_addr = nvk_image_base_address(img) + .base_addr = nvk_image_base_address(img, plane) +
img->nil.levels[sub_res->mipLevel].offset_B, img->planes[plane].nil.levels[sub_res->mipLevel].offset_B,
.image_type = img->vk.image_type, .image_type = img->vk.image_type,
.offset_el = nil_offset4d_px_to_el(offset4d_px, img->nil.format, .offset_el = nil_offset4d_px_to_el(offset4d_px, img->planes[plane].nil.format,
img->nil.sample_layout), img->planes[plane].nil.sample_layout),
.extent_el = nil_extent4d_px_to_el(lvl_extent4d_px, img->nil.format, .extent_el = nil_extent4d_px_to_el(lvl_extent4d_px, img->planes[plane].nil.format,
img->nil.sample_layout), img->planes[plane].nil.sample_layout),
.bpp = vk_format_get_blocksize(img->vk.format), .bpp = util_format_get_blocksize(img->planes[plane].nil.format),
.row_stride = img->nil.levels[sub_res->mipLevel].row_stride_B, .row_stride = img->planes[plane].nil.levels[sub_res->mipLevel].row_stride_B,
.array_stride = img->nil.array_stride_B, .array_stride = img->planes[plane].nil.array_stride_B,
.tiling = img->nil.levels[sub_res->mipLevel].tiling, .tiling = img->planes[plane].nil.levels[sub_res->mipLevel].tiling,
}; };
return buf; return buf;
@ -366,16 +367,18 @@ nvk_CmdCopyBufferToImage2(VkCommandBuffer commandBuffer,
const struct nil_extent4d extent4d_px = const struct nil_extent4d extent4d_px =
vk_to_nil_extent(extent_px, region->imageSubresource.layerCount); vk_to_nil_extent(extent_px, region->imageSubresource.layerCount);
const VkImageAspectFlagBits aspects = region->imageSubresource.aspectMask;
uint8_t plane = nvk_image_aspects_to_plane(dst, aspects);
struct nouveau_copy copy = { struct nouveau_copy copy = {
.src = nouveau_copy_rect_buffer(src, region->bufferOffset, .src = nouveau_copy_rect_buffer(src, region->bufferOffset,
buffer_layout), buffer_layout),
.dst = nouveau_copy_rect_image(dst, region->imageOffset, .dst = nouveau_copy_rect_image(dst, region->imageOffset,
&region->imageSubresource), &region->imageSubresource, plane),
.extent_el = nil_extent4d_px_to_el(extent4d_px, dst->nil.format, .extent_el = nil_extent4d_px_to_el(extent4d_px, dst->planes[plane].nil.format,
dst->nil.sample_layout), dst->planes[plane].nil.sample_layout),
}; };
const VkImageAspectFlagBits aspects = region->imageSubresource.aspectMask;
switch (dst->vk.format) { switch (dst->vk.format) {
case VK_FORMAT_D24_UNORM_S8_UINT: case VK_FORMAT_D24_UNORM_S8_UINT:
if (aspects == VK_IMAGE_ASPECT_DEPTH_BIT) { if (aspects == VK_IMAGE_ASPECT_DEPTH_BIT) {
@ -436,16 +439,18 @@ nvk_CmdCopyImageToBuffer2(VkCommandBuffer commandBuffer,
const struct nil_extent4d extent4d_px = const struct nil_extent4d extent4d_px =
vk_to_nil_extent(extent_px, region->imageSubresource.layerCount); vk_to_nil_extent(extent_px, region->imageSubresource.layerCount);
const VkImageAspectFlagBits aspects = region->imageSubresource.aspectMask;
uint8_t plane = nvk_image_aspects_to_plane(src, aspects);
struct nouveau_copy copy = { struct nouveau_copy copy = {
.src = nouveau_copy_rect_image(src, region->imageOffset, .src = nouveau_copy_rect_image(src, region->imageOffset,
&region->imageSubresource), &region->imageSubresource, plane),
.dst = nouveau_copy_rect_buffer(dst, region->bufferOffset, .dst = nouveau_copy_rect_buffer(dst, region->bufferOffset,
buffer_layout), buffer_layout),
.extent_el = nil_extent4d_px_to_el(extent4d_px, src->nil.format, .extent_el = nil_extent4d_px_to_el(extent4d_px, src->planes[plane].nil.format,
src->nil.sample_layout), src->planes[plane].nil.sample_layout),
}; };
const VkImageAspectFlagBits aspects = region->imageSubresource.aspectMask;
switch (src->vk.format) { switch (src->vk.format) {
case VK_FORMAT_D24_UNORM_S8_UINT: case VK_FORMAT_D24_UNORM_S8_UINT:
if (aspects == VK_IMAGE_ASPECT_DEPTH_BIT) { if (aspects == VK_IMAGE_ASPECT_DEPTH_BIT) {
@ -510,26 +515,31 @@ nvk_CmdCopyImage2(VkCommandBuffer commandBuffer,
const struct nil_extent4d extent4d_px = const struct nil_extent4d extent4d_px =
vk_to_nil_extent(extent_px, region->srcSubresource.layerCount); vk_to_nil_extent(extent_px, region->srcSubresource.layerCount);
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);
struct nouveau_copy copy = { struct nouveau_copy copy = {
.src = nouveau_copy_rect_image(src, region->srcOffset, .src = nouveau_copy_rect_image(src, region->srcOffset,
&region->srcSubresource), &region->srcSubresource, src_plane),
.dst = nouveau_copy_rect_image(dst, region->dstOffset, .dst = nouveau_copy_rect_image(dst, region->dstOffset,
&region->dstSubresource), &region->dstSubresource, dst_plane),
.extent_el = nil_extent4d_px_to_el(extent4d_px, src->nil.format, .extent_el = nil_extent4d_px_to_el(extent4d_px, src->planes[src_plane].nil.format,
src->nil.sample_layout), src->planes[src_plane].nil.sample_layout),
}; };
const VkImageAspectFlagBits aspects = region->srcSubresource.aspectMask; assert(src_aspects == region->srcSubresource.aspectMask);
assert(aspects == region->dstSubresource.aspectMask);
switch (src->vk.format) { switch (src->vk.format) {
case VK_FORMAT_D24_UNORM_S8_UINT: case VK_FORMAT_D24_UNORM_S8_UINT:
if (aspects == VK_IMAGE_ASPECT_DEPTH_BIT) { if (src_aspects == VK_IMAGE_ASPECT_DEPTH_BIT) {
copy.remap.comp_size = 1; copy.remap.comp_size = 1;
copy.remap.dst[0] = NV90B5_SET_REMAP_COMPONENTS_DST_W_SRC_X; copy.remap.dst[0] = NV90B5_SET_REMAP_COMPONENTS_DST_W_SRC_X;
copy.remap.dst[1] = NV90B5_SET_REMAP_COMPONENTS_DST_Y_SRC_Y; 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[2] = NV90B5_SET_REMAP_COMPONENTS_DST_Z_SRC_Z;
copy.remap.dst[3] = NV90B5_SET_REMAP_COMPONENTS_DST_W_NO_WRITE; copy.remap.dst[3] = NV90B5_SET_REMAP_COMPONENTS_DST_W_NO_WRITE;
} else if (aspects == VK_IMAGE_ASPECT_STENCIL_BIT) { } else if (src_aspects == VK_IMAGE_ASPECT_STENCIL_BIT) {
copy.remap.comp_size = 1; copy.remap.comp_size = 1;
copy.remap.dst[0] = NV90B5_SET_REMAP_COMPONENTS_DST_X_NO_WRITE; 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[1] = NV90B5_SET_REMAP_COMPONENTS_DST_Y_NO_WRITE;
@ -537,7 +547,7 @@ nvk_CmdCopyImage2(VkCommandBuffer commandBuffer,
copy.remap.dst[3] = NV90B5_SET_REMAP_COMPONENTS_DST_W_SRC_W; copy.remap.dst[3] = NV90B5_SET_REMAP_COMPONENTS_DST_W_SRC_W;
} else { } else {
/* If we're copying both, there's nothing special to do */ /* If we're copying both, there's nothing special to do */
assert(aspects == (VK_IMAGE_ASPECT_DEPTH_BIT | assert(src_aspects == (VK_IMAGE_ASPECT_DEPTH_BIT |
VK_IMAGE_ASPECT_STENCIL_BIT)); VK_IMAGE_ASPECT_STENCIL_BIT));
} }
break; break;

View file

@ -560,16 +560,23 @@ nvk_CmdBeginRendering(VkCommandBuffer commandBuffer,
if (render->color_att[i].iview) { if (render->color_att[i].iview) {
const struct nvk_image_view *iview = render->color_att[i].iview; const struct nvk_image_view *iview = render->color_att[i].iview;
const struct nvk_image *image = (struct nvk_image *)iview->vk.image; const struct nvk_image *image = (struct nvk_image *)iview->vk.image;
/* Rendering to multi-planar images is valid for a specific single plane
* only, so assert that what we have is a single-plane, obtain its index,
* and begin rendering
*/
assert(iview->plane_count == 1);
const uint8_t ip = iview->planes[0].image_plane;
const struct nil_image_level *level = const struct nil_image_level *level =
&image->nil.levels[iview->vk.base_mip_level]; &image->planes[ip].nil.levels[iview->vk.base_mip_level];
struct nil_extent4d level_extent_sa = struct nil_extent4d level_extent_sa =
nil_image_level_extent_sa(&image->nil, iview->vk.base_mip_level); nil_image_level_extent_sa(&image->planes[ip].nil, iview->vk.base_mip_level);
assert(sample_layout == NIL_SAMPLE_LAYOUT_INVALID || assert(sample_layout == NIL_SAMPLE_LAYOUT_INVALID ||
sample_layout == image->nil.sample_layout); sample_layout == image->planes[ip].nil.sample_layout);
sample_layout = image->nil.sample_layout; sample_layout = image->planes[ip].nil.sample_layout;
uint64_t addr = nvk_image_base_address(image) + level->offset_B; uint64_t addr = nvk_image_base_address(image, ip) + level->offset_B;
P_MTHD(p, NV9097, SET_COLOR_TARGET_A(i)); P_MTHD(p, NV9097, SET_COLOR_TARGET_A(i));
P_NV9097_SET_COLOR_TARGET_A(p, i, addr >> 32); P_NV9097_SET_COLOR_TARGET_A(p, i, addr >> 32);
@ -587,14 +594,14 @@ nvk_CmdBeginRendering(VkCommandBuffer commandBuffer,
.block_depth = level->tiling.z_log2, .block_depth = level->tiling.z_log2,
.layout = LAYOUT_BLOCKLINEAR, .layout = LAYOUT_BLOCKLINEAR,
.third_dimension_control = .third_dimension_control =
(image->nil.dim == NIL_IMAGE_DIM_3D) ? (image->planes[ip].nil.dim == NIL_IMAGE_DIM_3D) ?
THIRD_DIMENSION_CONTROL_THIRD_DIMENSION_DEFINES_DEPTH_SIZE : THIRD_DIMENSION_CONTROL_THIRD_DIMENSION_DEFINES_DEPTH_SIZE :
THIRD_DIMENSION_CONTROL_THIRD_DIMENSION_DEFINES_ARRAY_SIZE, THIRD_DIMENSION_CONTROL_THIRD_DIMENSION_DEFINES_ARRAY_SIZE,
}); });
P_NV9097_SET_COLOR_TARGET_THIRD_DIMENSION(p, i, P_NV9097_SET_COLOR_TARGET_THIRD_DIMENSION(p, i,
iview->vk.base_array_layer + layer_count); iview->vk.base_array_layer + layer_count);
P_NV9097_SET_COLOR_TARGET_ARRAY_PITCH(p, i, P_NV9097_SET_COLOR_TARGET_ARRAY_PITCH(p, i,
image->nil.array_stride_B >> 2); image->planes[ip].nil.array_stride_B >> 2);
P_NV9097_SET_COLOR_TARGET_LAYER(p, i, iview->vk.base_array_layer); P_NV9097_SET_COLOR_TARGET_LAYER(p, i, iview->vk.base_array_layer);
} else { } else {
P_MTHD(p, NV9097, SET_COLOR_TARGET_A(i)); P_MTHD(p, NV9097, SET_COLOR_TARGET_A(i));
@ -629,16 +636,19 @@ nvk_CmdBeginRendering(VkCommandBuffer commandBuffer,
render->depth_att.iview : render->depth_att.iview :
render->stencil_att.iview; render->stencil_att.iview;
const struct nvk_image *image = (struct nvk_image *)iview->vk.image; const struct nvk_image *image = (struct nvk_image *)iview->vk.image;
/* Depth/stencil are always single-plane */
assert(iview->plane_count == 1);
const uint8_t ip = iview->planes[0].image_plane;
const struct nil_image_level *level = const struct nil_image_level *level =
&image->nil.levels[iview->vk.base_mip_level]; &image->planes[ip].nil.levels[iview->vk.base_mip_level];
struct nil_extent4d level_extent_sa = struct nil_extent4d level_extent_sa =
nil_image_level_extent_sa(&image->nil, iview->vk.base_mip_level); nil_image_level_extent_sa(&image->planes[ip].nil, iview->vk.base_mip_level);
assert(sample_layout == NIL_SAMPLE_LAYOUT_INVALID || assert(sample_layout == NIL_SAMPLE_LAYOUT_INVALID ||
sample_layout == image->nil.sample_layout); sample_layout == image->planes[ip].nil.sample_layout);
sample_layout = image->nil.sample_layout; sample_layout = image->planes[ip].nil.sample_layout;
uint64_t addr = nvk_image_base_address(image) + level->offset_B; uint64_t addr = nvk_image_base_address(image, ip) + level->offset_B;
P_MTHD(p, NV9097, SET_ZT_A); P_MTHD(p, NV9097, SET_ZT_A);
P_NV9097_SET_ZT_A(p, addr >> 32); P_NV9097_SET_ZT_A(p, addr >> 32);
@ -647,14 +657,14 @@ nvk_CmdBeginRendering(VkCommandBuffer commandBuffer,
vk_format_to_pipe_format(iview->vk.format); vk_format_to_pipe_format(iview->vk.format);
const uint8_t zs_format = nil_format_to_depth_stencil(p_format); const uint8_t zs_format = nil_format_to_depth_stencil(p_format);
P_NV9097_SET_ZT_FORMAT(p, zs_format); P_NV9097_SET_ZT_FORMAT(p, zs_format);
assert(image->nil.dim != NIL_IMAGE_DIM_3D); assert(image->planes[ip].nil.dim != NIL_IMAGE_DIM_3D);
assert(level->tiling.z_log2 == 0); assert(level->tiling.z_log2 == 0);
P_NV9097_SET_ZT_BLOCK_SIZE(p, { P_NV9097_SET_ZT_BLOCK_SIZE(p, {
.width = WIDTH_ONE_GOB, .width = WIDTH_ONE_GOB,
.height = level->tiling.y_log2, .height = level->tiling.y_log2,
.depth = DEPTH_ONE_GOB, .depth = DEPTH_ONE_GOB,
}); });
P_NV9097_SET_ZT_ARRAY_PITCH(p, image->nil.array_stride_B >> 2); P_NV9097_SET_ZT_ARRAY_PITCH(p, image->planes[ip].nil.array_stride_B >> 2);
P_IMMD(p, NV9097, SET_ZT_SELECT, 1 /* target_count */); P_IMMD(p, NV9097, SET_ZT_SELECT, 1 /* target_count */);
@ -663,7 +673,7 @@ nvk_CmdBeginRendering(VkCommandBuffer commandBuffer,
P_NV9097_SET_ZT_SIZE_B(p, level_extent_sa.h); P_NV9097_SET_ZT_SIZE_B(p, level_extent_sa.h);
P_NV9097_SET_ZT_SIZE_C(p, { P_NV9097_SET_ZT_SIZE_C(p, {
.third_dimension = iview->vk.base_array_layer + layer_count, .third_dimension = iview->vk.base_array_layer + layer_count,
.control = (image->nil.dim == NIL_IMAGE_DIM_3D) ? .control = (image->planes[ip].nil.dim == NIL_IMAGE_DIM_3D) ?
CONTROL_ARRAY_SIZE_IS_ONE : CONTROL_ARRAY_SIZE_IS_ONE :
CONTROL_THIRD_DIMENSION_DEFINES_ARRAY_SIZE, CONTROL_THIRD_DIMENSION_DEFINES_ARRAY_SIZE,
}); });

View file

@ -48,26 +48,34 @@ write_image_view_desc(struct nvk_descriptor_set *set,
uint32_t binding, uint32_t elem, uint32_t binding, uint32_t elem,
VkDescriptorType descriptor_type) VkDescriptorType descriptor_type)
{ {
struct nvk_image_descriptor desc = { }; struct nvk_image_descriptor desc[3] = { };
uint8_t plane_count = 1;
if (descriptor_type != VK_DESCRIPTOR_TYPE_SAMPLER && if (descriptor_type != VK_DESCRIPTOR_TYPE_SAMPLER &&
info && info->imageView != VK_NULL_HANDLE) { info && info->imageView != VK_NULL_HANDLE) {
VK_FROM_HANDLE(nvk_image_view, view, info->imageView); VK_FROM_HANDLE(nvk_image_view, view, info->imageView);
plane_count = view->plane_count;
if (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) { if (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
assert(view->storage_desc_index > 0); /* Storage images are always single plane */
assert(view->storage_desc_index < (1 << 20)); assert(plane_count == 1);
uint8_t plane = 0;
assert(view->planes[plane].storage_desc_index > 0);
assert(view->planes[plane].storage_desc_index < (1 << 20));
/* The nv50 compiler currently does some whacky stuff with images. /* The nv50 compiler currently does some whacky stuff with images.
* For now, just assert that we never do storage on 3D images and * For now, just assert that we never do storage on 3D images and
* that our descriptor index is at most 11 bits. * that our descriptor index is at most 11 bits.
*/ */
assert(view->storage_desc_index < (1 << 11)); assert(view->planes[plane].storage_desc_index < (1 << 11));
desc.image_index = view->storage_desc_index; desc[plane].image_index = view->planes[plane].storage_desc_index;
} else { } else {
assert(view->sampled_desc_index > 0); for (uint8_t plane = 0; plane < plane_count; plane++) {
assert(view->sampled_desc_index < (1 << 20)); assert(view->planes[plane].sampled_desc_index > 0);
desc.image_index = view->sampled_desc_index; assert(view->planes[plane].sampled_desc_index < (1 << 20));
desc[plane].image_index = view->planes[plane].sampled_desc_index;
}
} }
} }
@ -83,10 +91,12 @@ write_image_view_desc(struct nvk_descriptor_set *set,
sampler = nvk_sampler_from_handle(info->sampler); sampler = nvk_sampler_from_handle(info->sampler);
} }
assert(sampler->desc_index < (1 << 12)); assert(sampler->desc_index < (1 << 12));
desc.sampler_index = sampler->desc_index; assert(sampler->plane_count == plane_count);
for (uint8_t plane = 0; plane < plane_count; plane++) {
desc[plane].sampler_index = sampler->desc_index;
} }
}
write_desc(set, binding, elem, &desc, sizeof(desc)); write_desc(set, binding, elem, desc, sizeof(desc[0]) * plane_count);
} }
static void static void

View file

@ -193,6 +193,21 @@ nvk_CreateDescriptorSetLayout(VkDevice _device,
nvk_descriptor_stride_align_for_type(binding->descriptorType, type_list, nvk_descriptor_stride_align_for_type(binding->descriptorType, type_list,
&stride, &align); &stride, &align);
uint8_t max_plane_count = 1;
if (binding_has_immutable_samplers(binding)) {
layout->binding[b].immutable_samplers = samplers;
samplers += binding->descriptorCount;
for (uint32_t i = 0; i < binding->descriptorCount; i++) {
VK_FROM_HANDLE(nvk_sampler, sampler, binding->pImmutableSamplers[i]);
layout->binding[b].immutable_samplers[i] = sampler;
if (max_plane_count < sampler->plane_count)
max_plane_count = sampler->plane_count;
}
}
stride *= max_plane_count;
if (stride > 0) { if (stride > 0) {
assert(stride <= UINT8_MAX); assert(stride <= UINT8_MAX);
assert(util_is_power_of_two_nonzero(align)); assert(util_is_power_of_two_nonzero(align));
@ -202,14 +217,6 @@ nvk_CreateDescriptorSetLayout(VkDevice _device,
buffer_size += stride * binding->descriptorCount; buffer_size += stride * binding->descriptorCount;
} }
if (binding_has_immutable_samplers(binding)) {
layout->binding[b].immutable_samplers = samplers;
samplers += binding->descriptorCount;
for (uint32_t i = 0; i < binding->descriptorCount; i++) {
VK_FROM_HANDLE(nvk_sampler, sampler, binding->pImmutableSamplers[i]);
layout->binding[b].immutable_samplers[i] = sampler;
}
}
} }
layout->descriptor_buffer_size = buffer_size; layout->descriptor_buffer_size = buffer_size;

View file

@ -249,12 +249,25 @@ nvk_image_init(struct nvk_device *device,
if (image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) if (image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT)
usage |= NIL_IMAGE_USAGE_2D_VIEW_BIT; usage |= NIL_IMAGE_USAGE_2D_VIEW_BIT;
image->plane_count = vk_format_get_plane_count(pCreateInfo->format);
image->disjoint = image->plane_count > 1 &&
(pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT);
const struct vk_format_ycbcr_info *ycbcr_info =
vk_format_get_ycbcr_info(pCreateInfo->format);
for (uint8_t plane = 0; plane < image->plane_count; plane++) {
VkFormat format = ycbcr_info ?
ycbcr_info->planes[plane].format : pCreateInfo->format;
const uint8_t width_scale = ycbcr_info ?
ycbcr_info->planes[plane].denominator_scales[0] : 1;
const uint8_t height_scale = ycbcr_info ?
ycbcr_info->planes[plane].denominator_scales[1] : 1;
struct nil_image_init_info nil_info = { struct nil_image_init_info nil_info = {
.dim = vk_image_type_to_nil_dim(pCreateInfo->imageType), .dim = vk_image_type_to_nil_dim(pCreateInfo->imageType),
.format = vk_format_to_pipe_format(pCreateInfo->format), .format = vk_format_to_pipe_format(format),
.extent_px = { .extent_px = {
.w = pCreateInfo->extent.width, .w = pCreateInfo->extent.width / width_scale,
.h = pCreateInfo->extent.height, .h = pCreateInfo->extent.height / height_scale,
.d = pCreateInfo->extent.depth, .d = pCreateInfo->extent.depth,
.a = pCreateInfo->arrayLayers, .a = pCreateInfo->arrayLayers,
}, },
@ -264,8 +277,9 @@ nvk_image_init(struct nvk_device *device,
}; };
ASSERTED bool ok = nil_image_init(&nvk_device_physical(device)->info, ASSERTED bool ok = nil_image_init(&nvk_device_physical(device)->info,
&image->nil, &nil_info); &image->planes[plane].nil, &nil_info);
assert(ok); assert(ok);
}
return VK_SUCCESS; return VK_SUCCESS;
} }
@ -295,31 +309,31 @@ nvk_CreateImage(VkDevice _device,
vk_free2(&device->vk.alloc, pAllocator, image); vk_free2(&device->vk.alloc, pAllocator, image);
return result; return result;
} }
for (uint8_t plane = 0; plane < image->plane_count; plane++) {
if (image->nil.pte_kind) { if (image->planes[plane].nil.pte_kind) {
assert(device->pdev->mem_heaps[0].flags & assert(device->pdev->mem_heaps[0].flags &
VK_MEMORY_HEAP_DEVICE_LOCAL_BIT); VK_MEMORY_HEAP_DEVICE_LOCAL_BIT);
const VkMemoryAllocateInfo alloc_info = { const VkMemoryAllocateInfo alloc_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = image->nil.size_B, .allocationSize = image->planes[plane].nil.size_B,
.memoryTypeIndex = 0, .memoryTypeIndex = 0,
}; };
const struct nvk_memory_tiling_info tile_info = { const struct nvk_memory_tiling_info tile_info = {
.tile_mode = image->nil.tile_mode, .tile_mode = image->planes[plane].nil.tile_mode,
.pte_kind = image->nil.pte_kind, .pte_kind = image->planes[plane].nil.pte_kind,
}; };
result = nvk_allocate_memory(device, &alloc_info, &tile_info, result = nvk_allocate_memory(device, &alloc_info, &tile_info,
pAllocator, &image->internal); pAllocator, &image->planes[plane].internal);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
nvk_image_finish(image); nvk_image_finish(image);
vk_free2(&device->vk.alloc, pAllocator, image); vk_free2(&device->vk.alloc, pAllocator, image);
return result; return result;
} }
image->mem = image->internal; image->planes[plane].mem = image->planes[plane].internal;
image->offset = 0; image->planes[plane].offset = 0;
}
} }
*pImage = nvk_image_to_handle(image); *pImage = nvk_image_to_handle(image);
@ -338,8 +352,10 @@ nvk_DestroyImage(VkDevice _device,
if (!image) if (!image)
return; return;
if (image->internal) for (uint8_t plane = 0; plane < image->plane_count; plane++) {
nvk_free_memory(device, image->internal, pAllocator); if (image->planes[plane].internal)
nvk_free_memory(device, image->planes[plane].internal, pAllocator);
}
nvk_image_finish(image); nvk_image_finish(image);
vk_free2(&device->vk.alloc, pAllocator, image); vk_free2(&device->vk.alloc, pAllocator, image);
@ -357,9 +373,28 @@ nvk_GetImageMemoryRequirements2(VkDevice _device,
// TODO hope for the best? // TODO hope for the best?
VkImageAspectFlags aspects = image->vk.aspects;
uint64_t size_B, align_B;
if (image->disjoint) {
const VkImagePlaneMemoryRequirementsInfo *plane_memory_req_info =
vk_find_struct_const(pInfo->pNext, IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO);
aspects = plane_memory_req_info->planeAspect;
uint8_t plane = nvk_image_aspects_to_plane(image, aspects);
size_B = image->planes[plane].nil.size_B;
align_B = image->planes[plane].nil.align_B;
} else {
size_B = align_B = 0;
for (unsigned plane = 0; plane < image->plane_count; plane++) {
align_B = MAX2(align_B, image->planes[plane].nil.align_B);
size_B = ALIGN_POT(size_B, image->planes[plane].nil.align_B);
size_B += image->planes[plane].nil.size_B;
}
}
pMemoryRequirements->memoryRequirements.memoryTypeBits = memory_types; pMemoryRequirements->memoryRequirements.memoryTypeBits = memory_types;
pMemoryRequirements->memoryRequirements.alignment = image->nil.align_B; pMemoryRequirements->memoryRequirements.alignment = align_B;
pMemoryRequirements->memoryRequirements.size = image->nil.size_B; pMemoryRequirements->memoryRequirements.size = size_B;
vk_foreach_struct_const(ext, pMemoryRequirements->pNext) { vk_foreach_struct_const(ext, pMemoryRequirements->pNext) {
switch (ext->sType) { switch (ext->sType) {
@ -425,14 +460,16 @@ nvk_GetImageSubresourceLayout(VkDevice device,
{ {
VK_FROM_HANDLE(nvk_image, image, _image); VK_FROM_HANDLE(nvk_image, image, _image);
uint8_t plane = nvk_image_aspects_to_plane(image, pSubresource->aspectMask);
*pLayout = (VkSubresourceLayout) { *pLayout = (VkSubresourceLayout) {
.offset = nil_image_level_layer_offset_B(&image->nil, .offset = nil_image_level_layer_offset_B(&image->planes[plane].nil,
pSubresource->mipLevel, pSubresource->mipLevel,
pSubresource->arrayLayer), pSubresource->arrayLayer),
.size = nil_image_level_size_B(&image->nil, pSubresource->mipLevel), .size = nil_image_level_size_B(&image->planes[plane].nil, pSubresource->mipLevel),
.rowPitch = image->nil.levels[pSubresource->mipLevel].row_stride_B, .rowPitch = image->planes[plane].nil.levels[pSubresource->mipLevel].row_stride_B,
.arrayPitch = image->nil.array_stride_B, .arrayPitch = image->planes[plane].nil.array_stride_B,
.depthPitch = nil_image_level_depth_stride_B(&image->nil, .depthPitch = nil_image_level_depth_stride_B(&image->planes[plane].nil,
pSubresource->mipLevel), pSubresource->mipLevel),
}; };
} }
@ -446,11 +483,26 @@ nvk_BindImageMemory2(VkDevice _device,
VK_FROM_HANDLE(nvk_device_memory, mem, pBindInfos[i].memory); VK_FROM_HANDLE(nvk_device_memory, mem, pBindInfos[i].memory);
VK_FROM_HANDLE(nvk_image, image, pBindInfos[i].image); VK_FROM_HANDLE(nvk_image, image, pBindInfos[i].image);
if (image->internal) if (image->disjoint) {
continue; const VkBindImagePlaneMemoryInfo *plane_info =
vk_find_struct_const(pBindInfos[i].pNext, BIND_IMAGE_PLANE_MEMORY_INFO);
image->mem = mem; uint8_t plane = nvk_image_aspects_to_plane(image, plane_info->planeAspect);
image->offset = pBindInfos[i].memoryOffset; if (image->planes[plane].internal == NULL) {
image->planes[plane].mem = mem;
image->planes[plane].offset = pBindInfos[i].memoryOffset;
} }
} else {
uint64_t offset_B = 0;
for (unsigned plane = 0; plane < image->plane_count; plane++) {
offset_B = ALIGN_POT(offset_B, image->planes[plane].nil.align_B);
if (image->planes[plane].internal == NULL) {
image->planes[plane].mem = mem;
image->planes[plane].offset = pBindInfos[i].memoryOffset + offset_B;
}
offset_B += image->planes[plane].nil.size_B;
}
}
}
return VK_SUCCESS; return VK_SUCCESS;
} }

View file

@ -14,24 +14,53 @@ VkFormatFeatureFlags2
nvk_get_image_format_features(struct nvk_physical_device *pdevice, nvk_get_image_format_features(struct nvk_physical_device *pdevice,
VkFormat format, VkImageTiling tiling); VkFormat format, VkImageTiling tiling);
struct nvk_image {
struct vk_image vk;
/* Used for internal dedicated allocations */
struct nvk_device_memory *internal;
struct nvk_image_plane {
struct nil_image nil;
struct nvk_device_memory *mem; struct nvk_device_memory *mem;
VkDeviceSize offset; VkDeviceSize offset;
struct nil_image nil; /* Used for internal dedicated allocations */
struct nvk_device_memory *internal;
};
struct nvk_image {
struct vk_image vk;
/** True if the planes are bound separately
*
* This is set based on VK_IMAGE_CREATE_DISJOINT_BIT
*/
bool disjoint;
uint8_t plane_count;
struct nvk_image_plane planes[3];
}; };
VK_DEFINE_NONDISP_HANDLE_CASTS(nvk_image, vk.base, VkImage, VK_OBJECT_TYPE_IMAGE) VK_DEFINE_NONDISP_HANDLE_CASTS(nvk_image, vk.base, VkImage, VK_OBJECT_TYPE_IMAGE)
static inline uint64_t static inline uint64_t
nvk_image_base_address(const struct nvk_image *image) nvk_image_base_address(const struct nvk_image *image, uint8_t plane)
{ {
return image->mem->bo->offset + image->offset; return image->planes[plane].mem->bo->offset + image->planes[plane].offset;
}
static inline uint8_t
nvk_image_aspects_to_plane(ASSERTED const struct nvk_image *image,
VkImageAspectFlags aspectMask)
{
/* Verify that the aspects are actually in the image */
assert(!(aspectMask & ~image->vk.aspects));
/* Must only be one aspect unless it's depth/stencil */
assert(aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT |
VK_IMAGE_ASPECT_STENCIL_BIT) ||
util_bitcount(aspectMask) == 1);
switch(aspectMask) {
case VK_IMAGE_ASPECT_PLANE_1_BIT: return 1;
case VK_IMAGE_ASPECT_PLANE_2_BIT: return 2;
default: return 0;
}
} }
#endif #endif

View file

@ -90,10 +90,42 @@ nvk_image_view_init(struct nvk_device *device,
vk_image_view_init(&device->vk, &view->vk, driver_internal, pCreateInfo); vk_image_view_init(&device->vk, &view->vk, driver_internal, pCreateInfo);
struct nil_image nil_image = image->nil; /* First, figure out which image planes we need.
uint64_t base_addr = nvk_image_base_address(image); * For depth/stencil, we 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;
} else {
/* For other formats, retrieve the plane count from the aspect mask
* and then walk through the aspect mask to map each image plane
* to its corresponding view plane
*/
assert(util_bitcount(view->vk.aspects) ==
vk_format_get_plane_count(view->vk.format));
view->plane_count = 0;
u_foreach_bit(aspect_bit, view->vk.aspects) {
uint8_t image_plane = nvk_image_aspects_to_plane(image, 1u << aspect_bit);
view->planes[view->plane_count++].image_plane = image_plane;
}
}
enum pipe_format p_format = vk_format_to_pipe_format(view->vk.format); /* Finally, fill in each view plane separately */
for (unsigned view_plane = 0; view_plane < view->plane_count; view_plane++) {
const uint8_t image_plane = view->planes[view_plane].image_plane;
struct nil_image nil_image = image->planes[image_plane].nil;
uint64_t base_addr = nvk_image_base_address(image, image_plane);
const struct vk_format_ycbcr_info *ycbcr_info =
vk_format_get_ycbcr_info(view->vk.format);
assert(ycbcr_info || view_plane == 0);
VkFormat plane_format = ycbcr_info ?
ycbcr_info->planes[view_plane].format : view->vk.format;
enum pipe_format p_format = vk_format_to_pipe_format(plane_format);
if (view->vk.aspects == VK_IMAGE_ASPECT_STENCIL_BIT) if (view->vk.aspects == VK_IMAGE_ASPECT_STENCIL_BIT)
p_format = get_stencil_format(p_format); p_format = get_stencil_format(p_format);
@ -129,7 +161,7 @@ nvk_image_view_init(struct nvk_device *device,
result = nvk_descriptor_table_add(device, &device->images, result = nvk_descriptor_table_add(device, &device->images,
tic, sizeof(tic), tic, sizeof(tic),
&view->sampled_desc_index); &view->planes[view_plane].sampled_desc_index);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
nvk_image_view_finish(device, view); nvk_image_view_finish(device, view);
return result; return result;
@ -161,12 +193,13 @@ nvk_image_view_init(struct nvk_device *device,
result = nvk_descriptor_table_add(device, &device->images, result = nvk_descriptor_table_add(device, &device->images,
tic, sizeof(tic), tic, sizeof(tic),
&view->storage_desc_index); &view->planes[view_plane].storage_desc_index);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
nvk_image_view_finish(device, view); nvk_image_view_finish(device, view);
return result; return result;
} }
} }
}
return VK_SUCCESS; return VK_SUCCESS;
} }
@ -175,14 +208,16 @@ void
nvk_image_view_finish(struct nvk_device *device, nvk_image_view_finish(struct nvk_device *device,
struct nvk_image_view *view) struct nvk_image_view *view)
{ {
if (view->sampled_desc_index) { for (uint8_t plane = 0; plane < view->plane_count; plane++) {
if (view->planes[plane].sampled_desc_index) {
nvk_descriptor_table_remove(device, &device->images, nvk_descriptor_table_remove(device, &device->images,
view->sampled_desc_index); view->planes[plane].sampled_desc_index);
} }
if (view->storage_desc_index) { if (view->planes[plane].storage_desc_index) {
nvk_descriptor_table_remove(device, &device->images, nvk_descriptor_table_remove(device, &device->images,
view->storage_desc_index); view->planes[plane].storage_desc_index);
}
} }
vk_image_view_finish(&view->vk); vk_image_view_finish(&view->vk);

View file

@ -10,11 +10,16 @@ struct nvk_device;
struct nvk_image_view { struct nvk_image_view {
struct vk_image_view vk; struct vk_image_view vk;
uint8_t plane_count;
struct {
uint8_t image_plane;
/** Index in the image descriptor table for the sampled image descriptor */ /** Index in the image descriptor table for the sampled image descriptor */
uint32_t sampled_desc_index; uint32_t sampled_desc_index;
/** Index in the image descriptor table for the storage image descriptor */ /** Index in the image descriptor table for the storage image descriptor */
uint32_t storage_desc_index; uint32_t storage_desc_index;
} planes[3];
}; };
VK_DEFINE_NONDISP_HANDLE_CASTS(nvk_image_view, vk.base, VkImageView, VK_DEFINE_NONDISP_HANDLE_CASTS(nvk_image_view, vk.base, VkImageView,

View file

@ -164,6 +164,11 @@ nvk_CreateSampler(VkDevice _device,
if (!sampler) if (!sampler)
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
/* Hard-coded as 1 as a placeholder until YCbCr conversion
* structs are implemented
*/
sampler->plane_count = 1;
uint32_t samp[8] = {}; uint32_t samp[8] = {};
SAMP_SET_U(samp, NV9097, 0, ADDRESS_U, SAMP_SET_U(samp, NV9097, 0, ADDRESS_U,
vk_to_9097_address_mode(pCreateInfo->addressModeU)); vk_to_9097_address_mode(pCreateInfo->addressModeU));

View file

@ -9,6 +9,12 @@ struct nvk_sampler {
struct vk_object_base base; struct vk_object_base base;
uint32_t desc_index; uint32_t desc_index;
/** Number of planes for multi-plane images.
* Hard-coded as 1 as a placeholder until YCbCr conversion
* structs are implemented
*/
uint8_t plane_count;
}; };
VK_DEFINE_NONDISP_HANDLE_CASTS(nvk_sampler, base, VkSampler, VK_OBJECT_TYPE_SAMPLER) VK_DEFINE_NONDISP_HANDLE_CASTS(nvk_sampler, base, VkSampler, VK_OBJECT_TYPE_SAMPLER)