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(
struct nvk_image *img,
VkOffset3D offset_px,
const VkImageSubresourceLayers *sub_res)
const VkImageSubresourceLayers *sub_res,
const uint8_t plane)
{
const VkExtent3D lvl_extent_px =
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);
struct nouveau_copy_buffer buf = {
.base_addr = nvk_image_base_address(img) +
img->nil.levels[sub_res->mipLevel].offset_B,
.base_addr = nvk_image_base_address(img, plane) +
img->planes[plane].nil.levels[sub_res->mipLevel].offset_B,
.image_type = img->vk.image_type,
.offset_el = nil_offset4d_px_to_el(offset4d_px, img->nil.format,
img->nil.sample_layout),
.extent_el = nil_extent4d_px_to_el(lvl_extent4d_px, img->nil.format,
img->nil.sample_layout),
.bpp = vk_format_get_blocksize(img->vk.format),
.row_stride = img->nil.levels[sub_res->mipLevel].row_stride_B,
.array_stride = img->nil.array_stride_B,
.tiling = img->nil.levels[sub_res->mipLevel].tiling,
.offset_el = nil_offset4d_px_to_el(offset4d_px, img->planes[plane].nil.format,
img->planes[plane].nil.sample_layout),
.extent_el = nil_extent4d_px_to_el(lvl_extent4d_px, img->planes[plane].nil.format,
img->planes[plane].nil.sample_layout),
.bpp = util_format_get_blocksize(img->planes[plane].nil.format),
.row_stride = img->planes[plane].nil.levels[sub_res->mipLevel].row_stride_B,
.array_stride = img->planes[plane].nil.array_stride_B,
.tiling = img->planes[plane].nil.levels[sub_res->mipLevel].tiling,
};
return buf;
@ -366,16 +367,18 @@ nvk_CmdCopyBufferToImage2(VkCommandBuffer commandBuffer,
const struct nil_extent4d extent4d_px =
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 = {
.src = nouveau_copy_rect_buffer(src, region->bufferOffset,
buffer_layout),
.dst = nouveau_copy_rect_image(dst, region->imageOffset,
&region->imageSubresource),
.extent_el = nil_extent4d_px_to_el(extent4d_px, dst->nil.format,
dst->nil.sample_layout),
&region->imageSubresource, plane),
.extent_el = nil_extent4d_px_to_el(extent4d_px, dst->planes[plane].nil.format,
dst->planes[plane].nil.sample_layout),
};
const VkImageAspectFlagBits aspects = region->imageSubresource.aspectMask;
switch (dst->vk.format) {
case VK_FORMAT_D24_UNORM_S8_UINT:
if (aspects == VK_IMAGE_ASPECT_DEPTH_BIT) {
@ -436,16 +439,18 @@ nvk_CmdCopyImageToBuffer2(VkCommandBuffer commandBuffer,
const struct nil_extent4d extent4d_px =
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 = {
.src = nouveau_copy_rect_image(src, region->imageOffset,
&region->imageSubresource),
&region->imageSubresource, plane),
.dst = nouveau_copy_rect_buffer(dst, region->bufferOffset,
buffer_layout),
.extent_el = nil_extent4d_px_to_el(extent4d_px, src->nil.format,
src->nil.sample_layout),
.extent_el = nil_extent4d_px_to_el(extent4d_px, src->planes[plane].nil.format,
src->planes[plane].nil.sample_layout),
};
const VkImageAspectFlagBits aspects = region->imageSubresource.aspectMask;
switch (src->vk.format) {
case VK_FORMAT_D24_UNORM_S8_UINT:
if (aspects == VK_IMAGE_ASPECT_DEPTH_BIT) {
@ -510,26 +515,31 @@ nvk_CmdCopyImage2(VkCommandBuffer commandBuffer,
const struct nil_extent4d extent4d_px =
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 = {
.src = nouveau_copy_rect_image(src, region->srcOffset,
&region->srcSubresource),
&region->srcSubresource, src_plane),
.dst = nouveau_copy_rect_image(dst, region->dstOffset,
&region->dstSubresource),
.extent_el = nil_extent4d_px_to_el(extent4d_px, src->nil.format,
src->nil.sample_layout),
&region->dstSubresource, dst_plane),
.extent_el = nil_extent4d_px_to_el(extent4d_px, src->planes[src_plane].nil.format,
src->planes[src_plane].nil.sample_layout),
};
const VkImageAspectFlagBits aspects = region->srcSubresource.aspectMask;
assert(aspects == region->dstSubresource.aspectMask);
assert(src_aspects == region->srcSubresource.aspectMask);
switch (src->vk.format) {
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.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[2] = NV90B5_SET_REMAP_COMPONENTS_DST_Z_SRC_Z;
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.dst[0] = NV90B5_SET_REMAP_COMPONENTS_DST_X_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;
} else {
/* 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));
}
break;

View file

@ -560,16 +560,23 @@ nvk_CmdBeginRendering(VkCommandBuffer commandBuffer,
if (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;
/* 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 =
&image->nil.levels[iview->vk.base_mip_level];
&image->planes[ip].nil.levels[iview->vk.base_mip_level];
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 ||
sample_layout == image->nil.sample_layout);
sample_layout = image->nil.sample_layout;
sample_layout == image->planes[ip].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_NV9097_SET_COLOR_TARGET_A(p, i, addr >> 32);
@ -587,14 +594,14 @@ nvk_CmdBeginRendering(VkCommandBuffer commandBuffer,
.block_depth = level->tiling.z_log2,
.layout = LAYOUT_BLOCKLINEAR,
.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_ARRAY_SIZE,
});
P_NV9097_SET_COLOR_TARGET_THIRD_DIMENSION(p, i,
iview->vk.base_array_layer + layer_count);
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);
} else {
P_MTHD(p, NV9097, SET_COLOR_TARGET_A(i));
@ -629,16 +636,19 @@ nvk_CmdBeginRendering(VkCommandBuffer commandBuffer,
render->depth_att.iview :
render->stencil_att.iview;
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 =
&image->nil.levels[iview->vk.base_mip_level];
&image->planes[ip].nil.levels[iview->vk.base_mip_level];
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 ||
sample_layout == image->nil.sample_layout);
sample_layout = image->nil.sample_layout;
sample_layout == image->planes[ip].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_NV9097_SET_ZT_A(p, addr >> 32);
@ -647,14 +657,14 @@ nvk_CmdBeginRendering(VkCommandBuffer commandBuffer,
vk_format_to_pipe_format(iview->vk.format);
const uint8_t zs_format = nil_format_to_depth_stencil(p_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);
P_NV9097_SET_ZT_BLOCK_SIZE(p, {
.width = WIDTH_ONE_GOB,
.height = level->tiling.y_log2,
.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 */);
@ -663,7 +673,7 @@ nvk_CmdBeginRendering(VkCommandBuffer commandBuffer,
P_NV9097_SET_ZT_SIZE_B(p, level_extent_sa.h);
P_NV9097_SET_ZT_SIZE_C(p, {
.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_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,
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 &&
info && info->imageView != VK_NULL_HANDLE) {
VK_FROM_HANDLE(nvk_image_view, view, info->imageView);
plane_count = view->plane_count;
if (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
assert(view->storage_desc_index > 0);
assert(view->storage_desc_index < (1 << 20));
/* Storage images are always single plane */
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.
* For now, just assert that we never do storage on 3D images and
* 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 {
assert(view->sampled_desc_index > 0);
assert(view->sampled_desc_index < (1 << 20));
desc.image_index = view->sampled_desc_index;
for (uint8_t plane = 0; plane < plane_count; plane++) {
assert(view->planes[plane].sampled_desc_index > 0);
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);
}
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

View file

@ -193,6 +193,21 @@ nvk_CreateDescriptorSetLayout(VkDevice _device,
nvk_descriptor_stride_align_for_type(binding->descriptorType, type_list,
&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) {
assert(stride <= UINT8_MAX);
assert(util_is_power_of_two_nonzero(align));
@ -202,14 +217,6 @@ nvk_CreateDescriptorSetLayout(VkDevice _device,
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;

View file

@ -249,23 +249,37 @@ nvk_image_init(struct nvk_device *device,
if (image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT)
usage |= NIL_IMAGE_USAGE_2D_VIEW_BIT;
struct nil_image_init_info nil_info = {
.dim = vk_image_type_to_nil_dim(pCreateInfo->imageType),
.format = vk_format_to_pipe_format(pCreateInfo->format),
.extent_px = {
.w = pCreateInfo->extent.width,
.h = pCreateInfo->extent.height,
.d = pCreateInfo->extent.depth,
.a = pCreateInfo->arrayLayers,
},
.levels = pCreateInfo->mipLevels,
.samples = pCreateInfo->samples,
.usage = usage,
};
image->plane_count = vk_format_get_plane_count(pCreateInfo->format);
image->disjoint = image->plane_count > 1 &&
(pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT);
ASSERTED bool ok = nil_image_init(&nvk_device_physical(device)->info,
&image->nil, &nil_info);
assert(ok);
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 = {
.dim = vk_image_type_to_nil_dim(pCreateInfo->imageType),
.format = vk_format_to_pipe_format(format),
.extent_px = {
.w = pCreateInfo->extent.width / width_scale,
.h = pCreateInfo->extent.height / height_scale,
.d = pCreateInfo->extent.depth,
.a = pCreateInfo->arrayLayers,
},
.levels = pCreateInfo->mipLevels,
.samples = pCreateInfo->samples,
.usage = usage,
};
ASSERTED bool ok = nil_image_init(&nvk_device_physical(device)->info,
&image->planes[plane].nil, &nil_info);
assert(ok);
}
return VK_SUCCESS;
}
@ -295,31 +309,31 @@ nvk_CreateImage(VkDevice _device,
vk_free2(&device->vk.alloc, pAllocator, image);
return result;
}
if (image->nil.pte_kind) {
assert(device->pdev->mem_heaps[0].flags &
for (uint8_t plane = 0; plane < image->plane_count; plane++) {
if (image->planes[plane].nil.pte_kind) {
assert(device->pdev->mem_heaps[0].flags &
VK_MEMORY_HEAP_DEVICE_LOCAL_BIT);
const VkMemoryAllocateInfo alloc_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = image->nil.size_B,
.memoryTypeIndex = 0,
};
const struct nvk_memory_tiling_info tile_info = {
.tile_mode = image->nil.tile_mode,
.pte_kind = image->nil.pte_kind,
};
const VkMemoryAllocateInfo alloc_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = image->planes[plane].nil.size_B,
.memoryTypeIndex = 0,
};
const struct nvk_memory_tiling_info tile_info = {
.tile_mode = image->planes[plane].nil.tile_mode,
.pte_kind = image->planes[plane].nil.pte_kind,
};
result = nvk_allocate_memory(device, &alloc_info, &tile_info,
pAllocator, &image->planes[plane].internal);
if (result != VK_SUCCESS) {
nvk_image_finish(image);
vk_free2(&device->vk.alloc, pAllocator, image);
return result;
}
result = nvk_allocate_memory(device, &alloc_info, &tile_info,
pAllocator, &image->internal);
if (result != VK_SUCCESS) {
nvk_image_finish(image);
vk_free2(&device->vk.alloc, pAllocator, image);
return result;
image->planes[plane].mem = image->planes[plane].internal;
image->planes[plane].offset = 0;
}
image->mem = image->internal;
image->offset = 0;
}
*pImage = nvk_image_to_handle(image);
@ -338,8 +352,10 @@ nvk_DestroyImage(VkDevice _device,
if (!image)
return;
if (image->internal)
nvk_free_memory(device, image->internal, pAllocator);
for (uint8_t plane = 0; plane < image->plane_count; plane++) {
if (image->planes[plane].internal)
nvk_free_memory(device, image->planes[plane].internal, pAllocator);
}
nvk_image_finish(image);
vk_free2(&device->vk.alloc, pAllocator, image);
@ -357,9 +373,28 @@ nvk_GetImageMemoryRequirements2(VkDevice _device,
// 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.alignment = image->nil.align_B;
pMemoryRequirements->memoryRequirements.size = image->nil.size_B;
pMemoryRequirements->memoryRequirements.alignment = align_B;
pMemoryRequirements->memoryRequirements.size = size_B;
vk_foreach_struct_const(ext, pMemoryRequirements->pNext) {
switch (ext->sType) {
@ -425,14 +460,16 @@ nvk_GetImageSubresourceLayout(VkDevice device,
{
VK_FROM_HANDLE(nvk_image, image, _image);
uint8_t plane = nvk_image_aspects_to_plane(image, pSubresource->aspectMask);
*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->arrayLayer),
.size = nil_image_level_size_B(&image->nil, pSubresource->mipLevel),
.rowPitch = image->nil.levels[pSubresource->mipLevel].row_stride_B,
.arrayPitch = image->nil.array_stride_B,
.depthPitch = nil_image_level_depth_stride_B(&image->nil,
.size = nil_image_level_size_B(&image->planes[plane].nil, pSubresource->mipLevel),
.rowPitch = image->planes[plane].nil.levels[pSubresource->mipLevel].row_stride_B,
.arrayPitch = image->planes[plane].nil.array_stride_B,
.depthPitch = nil_image_level_depth_stride_B(&image->planes[plane].nil,
pSubresource->mipLevel),
};
}
@ -446,11 +483,26 @@ nvk_BindImageMemory2(VkDevice _device,
VK_FROM_HANDLE(nvk_device_memory, mem, pBindInfos[i].memory);
VK_FROM_HANDLE(nvk_image, image, pBindInfos[i].image);
if (image->internal)
continue;
image->mem = mem;
image->offset = pBindInfos[i].memoryOffset;
if (image->disjoint) {
const VkBindImagePlaneMemoryInfo *plane_info =
vk_find_struct_const(pBindInfos[i].pNext, BIND_IMAGE_PLANE_MEMORY_INFO);
uint8_t plane = nvk_image_aspects_to_plane(image, plane_info->planeAspect);
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;
}

View file

@ -14,24 +14,53 @@ VkFormatFeatureFlags2
nvk_get_image_format_features(struct nvk_physical_device *pdevice,
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;
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)
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

View file

@ -90,81 +90,114 @@ nvk_image_view_init(struct nvk_device *device,
vk_image_view_init(&device->vk, &view->vk, driver_internal, pCreateInfo);
struct nil_image nil_image = image->nil;
uint64_t base_addr = nvk_image_base_address(image);
enum pipe_format p_format = vk_format_to_pipe_format(view->vk.format);
if (view->vk.aspects == VK_IMAGE_ASPECT_STENCIL_BIT)
p_format = get_stencil_format(p_format);
struct nil_view nil_view = {
.type = vk_image_view_type_to_nil_view_type(view->vk.view_type),
.format = p_format,
.base_level = view->vk.base_mip_level,
.num_levels = view->vk.level_count,
.base_array_layer = view->vk.base_array_layer,
.array_len = view->vk.layer_count,
.swizzle = {
vk_swizzle_to_pipe(view->vk.swizzle.r),
vk_swizzle_to_pipe(view->vk.swizzle.g),
vk_swizzle_to_pipe(view->vk.swizzle.b),
vk_swizzle_to_pipe(view->vk.swizzle.a),
},
.min_lod_clamp = view->vk.min_lod,
};
if (util_format_is_compressed(nil_image.format) &&
!util_format_is_compressed(nil_view.format))
image_uncompressed_view(&nil_image, &nil_view, &base_addr);
if (nil_image.dim == NIL_IMAGE_DIM_3D &&
nil_view.type != NIL_VIEW_TYPE_3D)
image_3d_view_as_2d_array(&nil_image, &nil_view, &base_addr);
if (view->vk.usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
uint32_t tic[8];
nil_image_fill_tic(&nvk_device_physical(device)->info,
&nil_image, &nil_view, base_addr, tic);
result = nvk_descriptor_table_add(device, &device->images,
tic, sizeof(tic),
&view->sampled_desc_index);
if (result != VK_SUCCESS) {
nvk_image_view_finish(device, view);
return result;
/* First, figure out which image planes we need.
* 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;
}
}
if (view->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) {
/* For storage images, we can't have any cubes */
if (view->vk.view_type == VK_IMAGE_VIEW_TYPE_CUBE ||
view->vk.view_type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
nil_view.type = NIL_VIEW_TYPE_2D_ARRAY;
/* 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);
if (view->vk.view_type == VK_IMAGE_VIEW_TYPE_3D) {
/* Without VK_AMD_shader_image_load_store_lod, the client can only
* get at the first LOD from the shader anyway.
*/
assert(view->vk.base_array_layer == 0);
assert(view->vk.layer_count = 1);
nil_view.type = NIL_VIEW_TYPE_2D_ARRAY;
nil_view.num_levels = 1;
nil_view.base_array_layer = 0;
nil_view.array_len = view->vk.extent.depth;
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)
p_format = get_stencil_format(p_format);
struct nil_view nil_view = {
.type = vk_image_view_type_to_nil_view_type(view->vk.view_type),
.format = p_format,
.base_level = view->vk.base_mip_level,
.num_levels = view->vk.level_count,
.base_array_layer = view->vk.base_array_layer,
.array_len = view->vk.layer_count,
.swizzle = {
vk_swizzle_to_pipe(view->vk.swizzle.r),
vk_swizzle_to_pipe(view->vk.swizzle.g),
vk_swizzle_to_pipe(view->vk.swizzle.b),
vk_swizzle_to_pipe(view->vk.swizzle.a),
},
.min_lod_clamp = view->vk.min_lod,
};
if (util_format_is_compressed(nil_image.format) &&
!util_format_is_compressed(nil_view.format))
image_uncompressed_view(&nil_image, &nil_view, &base_addr);
if (nil_image.dim == NIL_IMAGE_DIM_3D &&
nil_view.type != NIL_VIEW_TYPE_3D)
image_3d_view_as_2d_array(&nil_image, &nil_view, &base_addr);
if (view->vk.usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
uint32_t tic[8];
nil_image_fill_tic(&nvk_device_physical(device)->info,
&nil_image, &nil_view, base_addr, tic);
result = nvk_descriptor_table_add(device, &device->images,
tic, sizeof(tic),
&view->planes[view_plane].sampled_desc_index);
if (result != VK_SUCCESS) {
nvk_image_view_finish(device, view);
return result;
}
}
uint32_t tic[8];
nil_image_fill_tic(&nvk_device_physical(device)->info,
&nil_image, &nil_view, base_addr, tic);
if (view->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) {
/* For storage images, we can't have any cubes */
if (view->vk.view_type == VK_IMAGE_VIEW_TYPE_CUBE ||
view->vk.view_type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
nil_view.type = NIL_VIEW_TYPE_2D_ARRAY;
result = nvk_descriptor_table_add(device, &device->images,
tic, sizeof(tic),
&view->storage_desc_index);
if (result != VK_SUCCESS) {
nvk_image_view_finish(device, view);
return result;
if (view->vk.view_type == VK_IMAGE_VIEW_TYPE_3D) {
/* Without VK_AMD_shader_image_load_store_lod, the client can only
* get at the first LOD from the shader anyway.
*/
assert(view->vk.base_array_layer == 0);
assert(view->vk.layer_count = 1);
nil_view.type = NIL_VIEW_TYPE_2D_ARRAY;
nil_view.num_levels = 1;
nil_view.base_array_layer = 0;
nil_view.array_len = view->vk.extent.depth;
image_3d_view_as_2d_array(&nil_image, &nil_view, &base_addr);
}
uint32_t tic[8];
nil_image_fill_tic(&nvk_device_physical(device)->info,
&nil_image, &nil_view, base_addr, tic);
result = nvk_descriptor_table_add(device, &device->images,
tic, sizeof(tic),
&view->planes[view_plane].storage_desc_index);
if (result != VK_SUCCESS) {
nvk_image_view_finish(device, view);
return result;
}
}
}
@ -175,14 +208,16 @@ void
nvk_image_view_finish(struct nvk_device *device,
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,
view->sampled_desc_index);
}
view->planes[plane].sampled_desc_index);
}
if (view->storage_desc_index) {
nvk_descriptor_table_remove(device, &device->images,
view->storage_desc_index);
if (view->planes[plane].storage_desc_index) {
nvk_descriptor_table_remove(device, &device->images,
view->planes[plane].storage_desc_index);
}
}
vk_image_view_finish(&view->vk);

View file

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

View file

@ -164,6 +164,11 @@ nvk_CreateSampler(VkDevice _device,
if (!sampler)
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] = {};
SAMP_SET_U(samp, NV9097, 0, ADDRESS_U,
vk_to_9097_address_mode(pCreateInfo->addressModeU));

View file

@ -9,6 +9,12 @@ struct nvk_sampler {
struct vk_object_base base;
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)