From e41031d8ffdd46c223fcf383e40e615aa073e102 Mon Sep 17 00:00:00 2001 From: Mohamed Ahmed Date: Wed, 12 Jul 2023 14:18:49 -0500 Subject: [PATCH] nvk: Enable multiplane images and image views Part-of: --- src/nouveau/vulkan/nvk_cmd_copy.c | 66 +++++---- src/nouveau/vulkan/nvk_cmd_draw.c | 40 ++++-- src/nouveau/vulkan/nvk_descriptor_set.c | 32 +++-- src/nouveau/vulkan/nvk_descriptor_set_layout.c | 23 +-- src/nouveau/vulkan/nvk_image.c | 156 ++++++++++++++------- src/nouveau/vulkan/nvk_image.h | 43 +++++- src/nouveau/vulkan/nvk_image_view.c | 185 +++++++++++++++---------- src/nouveau/vulkan/nvk_image_view.h | 13 +- src/nouveau/vulkan/nvk_sampler.c | 5 + src/nouveau/vulkan/nvk_sampler.h | 6 + 10 files changed, 369 insertions(+), 200 deletions(-) diff --git a/src/nouveau/vulkan/nvk_cmd_copy.c b/src/nouveau/vulkan/nvk_cmd_copy.c index 6623189..7e8ac70 100644 --- a/src/nouveau/vulkan/nvk_cmd_copy.c +++ b/src/nouveau/vulkan/nvk_cmd_copy.c @@ -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, - ®ion->imageSubresource), - .extent_el = nil_extent4d_px_to_el(extent4d_px, dst->nil.format, - dst->nil.sample_layout), + ®ion->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, - ®ion->imageSubresource), + ®ion->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, - ®ion->srcSubresource), + ®ion->srcSubresource, src_plane), .dst = nouveau_copy_rect_image(dst, region->dstOffset, - ®ion->dstSubresource), - .extent_el = nil_extent4d_px_to_el(extent4d_px, src->nil.format, - src->nil.sample_layout), + ®ion->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; diff --git a/src/nouveau/vulkan/nvk_cmd_draw.c b/src/nouveau/vulkan/nvk_cmd_draw.c index ab583b5..6cfc5c4 100644 --- a/src/nouveau/vulkan/nvk_cmd_draw.c +++ b/src/nouveau/vulkan/nvk_cmd_draw.c @@ -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, }); diff --git a/src/nouveau/vulkan/nvk_descriptor_set.c b/src/nouveau/vulkan/nvk_descriptor_set.c index ccfa3f3..815ee5f 100644 --- a/src/nouveau/vulkan/nvk_descriptor_set.c +++ b/src/nouveau/vulkan/nvk_descriptor_set.c @@ -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 diff --git a/src/nouveau/vulkan/nvk_descriptor_set_layout.c b/src/nouveau/vulkan/nvk_descriptor_set_layout.c index 5a4f620..67bc850 100644 --- a/src/nouveau/vulkan/nvk_descriptor_set_layout.c +++ b/src/nouveau/vulkan/nvk_descriptor_set_layout.c @@ -193,14 +193,7 @@ nvk_CreateDescriptorSetLayout(VkDevice _device, nvk_descriptor_stride_align_for_type(binding->descriptorType, type_list, &stride, &align); - if (stride > 0) { - assert(stride <= UINT8_MAX); - assert(util_is_power_of_two_nonzero(align)); - buffer_size = ALIGN_POT(buffer_size, align); - layout->binding[b].offset = buffer_size; - layout->binding[b].stride = stride; - buffer_size += stride * binding->descriptorCount; - } + uint8_t max_plane_count = 1; if (binding_has_immutable_samplers(binding)) { layout->binding[b].immutable_samplers = samplers; @@ -208,8 +201,22 @@ nvk_CreateDescriptorSetLayout(VkDevice _device, 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)); + buffer_size = ALIGN_POT(buffer_size, align); + layout->binding[b].offset = buffer_size; + layout->binding[b].stride = stride; + buffer_size += stride * binding->descriptorCount; + } + } layout->descriptor_buffer_size = buffer_size; diff --git a/src/nouveau/vulkan/nvk_image.c b/src/nouveau/vulkan/nvk_image.c index 1c9a2da..afe2621 100644 --- a/src/nouveau/vulkan/nvk_image.c +++ b/src/nouveau/vulkan/nvk_image.c @@ -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); + + 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->nil, &nil_info); - assert(ok); + 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, - }; - - 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; + 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; + } + + 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; } diff --git a/src/nouveau/vulkan/nvk_image.h b/src/nouveau/vulkan/nvk_image.h index 76d8593..bb67f9d 100644 --- a/src/nouveau/vulkan/nvk_image.h +++ b/src/nouveau/vulkan/nvk_image.h @@ -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; + +struct nvk_image_plane { + struct nil_image nil; + struct nvk_device_memory *mem; + VkDeviceSize offset; /* Used for internal dedicated allocations */ struct nvk_device_memory *internal; +}; +struct nvk_image { + struct vk_image vk; - struct nvk_device_memory *mem; - VkDeviceSize offset; + /** True if the planes are bound separately + * + * This is set based on VK_IMAGE_CREATE_DISJOINT_BIT + */ + bool disjoint; - struct nil_image nil; + 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->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) { - return image->mem->bo->offset + image->offset; + /* 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 diff --git a/src/nouveau/vulkan/nvk_image_view.c b/src/nouveau/vulkan/nvk_image_view.c index f9379a6..6e423a2 100644 --- a/src/nouveau/vulkan/nvk_image_view.c +++ b/src/nouveau/vulkan/nvk_image_view.c @@ -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; - - 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; + /* 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) + 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); - } - 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_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; + } + } - 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.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; + + 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); diff --git a/src/nouveau/vulkan/nvk_image_view.h b/src/nouveau/vulkan/nvk_image_view.h index 99f6e6c..269ba91 100644 --- a/src/nouveau/vulkan/nvk_image_view.h +++ b/src/nouveau/vulkan/nvk_image_view.h @@ -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, diff --git a/src/nouveau/vulkan/nvk_sampler.c b/src/nouveau/vulkan/nvk_sampler.c index a0b8002..efdbec6 100644 --- a/src/nouveau/vulkan/nvk_sampler.c +++ b/src/nouveau/vulkan/nvk_sampler.c @@ -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)); diff --git a/src/nouveau/vulkan/nvk_sampler.h b/src/nouveau/vulkan/nvk_sampler.h index de124ed..30ec4ea 100644 --- a/src/nouveau/vulkan/nvk_sampler.h +++ b/src/nouveau/vulkan/nvk_sampler.h @@ -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) -- 2.7.4