Module: Mesa Branch: main Commit: d2671d3c1762fa18343784a96167aba0b5484f6b URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=d2671d3c1762fa18343784a96167aba0b5484f6b
Author: Dave Airlie <[email protected]> Date: Fri Oct 6 15:37:38 2023 +1000 lavapipe: allocate image and image view planes. This allocate planes and handles disjoint. Reviewed-by: Roland Scheidegger <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25609> --- src/gallium/frontends/lavapipe/lvp_device.c | 21 ++++-- src/gallium/frontends/lavapipe/lvp_image.c | 103 +++++++++++++++++++-------- src/gallium/frontends/lavapipe/lvp_private.h | 26 ++++++- 3 files changed, 112 insertions(+), 38 deletions(-) diff --git a/src/gallium/frontends/lavapipe/lvp_device.c b/src/gallium/frontends/lavapipe/lvp_device.c index b86489d484f..ddb31c5ebea 100644 --- a/src/gallium/frontends/lavapipe/lvp_device.c +++ b/src/gallium/frontends/lavapipe/lvp_device.c @@ -2074,11 +2074,22 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_BindImageMemory2(VkDevice _device, if (!did_bind) { uint64_t offset_B = 0; VkResult result; - - result = lvp_image_plane_bind(device, &image->planes[0], - mem, bind_info->memoryOffset, &offset_B); - if (result != VK_SUCCESS) - return result; + if (image->disjoint) { + const VkBindImagePlaneMemoryInfo *plane_info = + vk_find_struct_const(pBindInfos[i].pNext, BIND_IMAGE_PLANE_MEMORY_INFO); + uint8_t plane = lvp_image_aspects_to_plane(image, plane_info->planeAspect); + result = lvp_image_plane_bind(device, &image->planes[plane], + mem, bind_info->memoryOffset, &offset_B); + if (result != VK_SUCCESS) + return result; + } else { + for (unsigned plane = 0; plane < image->plane_count; plane++) { + result = lvp_image_plane_bind(device, &image->planes[plane], + mem, bind_info->memoryOffset, &offset_B); + if (result != VK_SUCCESS) + return result; + } + } } } return VK_SUCCESS; diff --git a/src/gallium/frontends/lavapipe/lvp_image.c b/src/gallium/frontends/lavapipe/lvp_image.c index 19fdba70273..8dbcd28abd7 100644 --- a/src/gallium/frontends/lavapipe/lvp_image.c +++ b/src/gallium/frontends/lavapipe/lvp_image.c @@ -43,10 +43,20 @@ lvp_image_create(VkDevice _device, return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); image->alignment = 16; + 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 (unsigned p = 0; p < image->plane_count; p++) { struct pipe_resource template; - VkFormat format = pCreateInfo->format; + VkFormat format = ycbcr_info ? + ycbcr_info->planes[p].format : pCreateInfo->format; + const uint8_t width_scale = ycbcr_info ? + ycbcr_info->planes[p].denominator_scales[0] : 1; + const uint8_t height_scale = ycbcr_info ? + ycbcr_info->planes[p].denominator_scales[1] : 1; memset(&template, 0, sizeof(template)); template.screen = device->pscreen; @@ -93,20 +103,20 @@ lvp_image_create(VkDevice _device, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) template.bind |= PIPE_BIND_SHADER_IMAGE; - template.width0 = pCreateInfo->extent.width; - template.height0 = pCreateInfo->extent.height; + template.width0 = pCreateInfo->extent.width / width_scale; + template.height0 = pCreateInfo->extent.height / height_scale; template.depth0 = pCreateInfo->extent.depth; template.array_size = pCreateInfo->arrayLayers; template.last_level = pCreateInfo->mipLevels - 1; template.nr_samples = pCreateInfo->samples; template.nr_storage_samples = pCreateInfo->samples; - image->planes[0].bo = device->pscreen->resource_create_unbacked(device->pscreen, + image->planes[p].bo = device->pscreen->resource_create_unbacked(device->pscreen, &template, - &image->planes[0].size); - if (!image->planes[0].bo) + &image->planes[p].size); + if (!image->planes[p].bo) return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); - image->size += image->planes[0].size; + image->size += image->planes[p].size; } *pImage = lvp_image_to_handle(image); @@ -170,7 +180,8 @@ lvp_DestroyImage(VkDevice _device, VkImage _image, if (!_image) return; - pipe_resource_reference(&image->planes[0].bo, NULL); + for (unsigned p = 0; p < image->plane_count; p++) + pipe_resource_reference(&image->planes[p].bo, NULL); vk_image_destroy(&device->vk, pAllocator, &image->vk); } @@ -191,7 +202,7 @@ static inline char conv_depth_swiz(char swiz) { } static struct pipe_sampler_view * -lvp_create_samplerview(struct pipe_context *pctx, struct lvp_image_view *iv) +lvp_create_samplerview(struct pipe_context *pctx, struct lvp_image_view *iv, VkFormat plane_format, unsigned image_plane) { if (!iv) return NULL; @@ -199,13 +210,13 @@ lvp_create_samplerview(struct pipe_context *pctx, struct lvp_image_view *iv) struct pipe_sampler_view templ; enum pipe_format pformat; if (iv->vk.aspects == VK_IMAGE_ASPECT_DEPTH_BIT) - pformat = lvp_vk_format_to_pipe_format(iv->vk.format); + pformat = lvp_vk_format_to_pipe_format(plane_format); else if (iv->vk.aspects == VK_IMAGE_ASPECT_STENCIL_BIT) - pformat = util_format_stencil_only(lvp_vk_format_to_pipe_format(iv->vk.format)); + pformat = util_format_stencil_only(lvp_vk_format_to_pipe_format(plane_format)); else - pformat = lvp_vk_format_to_pipe_format(iv->vk.format); + pformat = lvp_vk_format_to_pipe_format(plane_format); u_sampler_view_default_template(&templ, - iv->image->planes[0].bo, + iv->image->planes[image_plane].bo, pformat); if (iv->vk.view_type == VK_IMAGE_VIEW_TYPE_1D) templ.target = PIPE_TEXTURE_1D; @@ -238,23 +249,23 @@ lvp_create_samplerview(struct pipe_context *pctx, struct lvp_image_view *iv) templ.swizzle_a = conv_depth_swiz(templ.swizzle_a); } - return pctx->create_sampler_view(pctx, iv->image->planes[0].bo, &templ); + return pctx->create_sampler_view(pctx, iv->image->planes[image_plane].bo, &templ); } static struct pipe_image_view -lvp_create_imageview(const struct lvp_image_view *iv) +lvp_create_imageview(const struct lvp_image_view *iv, VkFormat plane_format, unsigned image_plane) { struct pipe_image_view view = {0}; if (!iv) return view; - view.resource = iv->image->planes[0].bo; + view.resource = iv->image->planes[image_plane].bo; if (iv->vk.aspects == VK_IMAGE_ASPECT_DEPTH_BIT) - view.format = lvp_vk_format_to_pipe_format(iv->vk.format); + view.format = lvp_vk_format_to_pipe_format(plane_format); else if (iv->vk.aspects == VK_IMAGE_ASPECT_STENCIL_BIT) - view.format = util_format_stencil_only(lvp_vk_format_to_pipe_format(iv->vk.format)); + view.format = util_format_stencil_only(lvp_vk_format_to_pipe_format(plane_format)); else - view.format = lvp_vk_format_to_pipe_format(iv->vk.format); + view.format = lvp_vk_format_to_pipe_format(plane_format); if (iv->vk.view_type == VK_IMAGE_VIEW_TYPE_3D) { view.u.tex.first_layer = iv->vk.storage.z_slice_offset; @@ -286,16 +297,45 @@ lvp_CreateImageView(VkDevice _device, view->image = image; view->surface = NULL; + if (image->vk.aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | + VK_IMAGE_ASPECT_STENCIL_BIT)) { + assert(image->plane_count == 1); + assert(lvp_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 = lvp_image_aspects_to_plane(image, 1u << aspect_bit); + view->planes[view->plane_count++].image_plane = image_plane; + } + } + simple_mtx_lock(&device->queue.lock); - if (image->planes[0].bo->bind & PIPE_BIND_SHADER_IMAGE) { - view->planes[0].iv = lvp_create_imageview(view); - view->planes[0].image_handle = (void *)(uintptr_t)device->queue.ctx->create_image_handle(device->queue.ctx, &view->planes[0].iv); - } + for (unsigned view_plane = 0; view_plane < view->plane_count; view_plane++) { + const uint8_t image_plane = view->planes[view_plane].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; + + if (image->planes[image_plane].bo->bind & PIPE_BIND_SHADER_IMAGE) { + view->planes[view_plane].iv = lvp_create_imageview(view, plane_format, image_plane); + view->planes[view_plane].image_handle = (void *)(uintptr_t)device->queue.ctx->create_image_handle(device->queue.ctx, &view->planes[view_plane].iv); + } - if (image->planes[0].bo->bind & PIPE_BIND_SAMPLER_VIEW) { - view->planes[0].sv = lvp_create_samplerview(device->queue.ctx, view); - view->planes[0].texture_handle = (void *)(uintptr_t)device->queue.ctx->create_texture_handle(device->queue.ctx, view->planes[0].sv, NULL); + if (image->planes[image_plane].bo->bind & PIPE_BIND_SAMPLER_VIEW) { + view->planes[view_plane].sv = lvp_create_samplerview(device->queue.ctx, view, plane_format, image_plane); + view->planes[view_plane].texture_handle = (void *)(uintptr_t)device->queue.ctx->create_texture_handle(device->queue.ctx, view->planes[view_plane].sv, NULL); + } } simple_mtx_unlock(&device->queue.lock); @@ -317,11 +357,12 @@ lvp_DestroyImageView(VkDevice _device, VkImageView _iview, simple_mtx_lock(&device->queue.lock); - device->queue.ctx->delete_image_handle(device->queue.ctx, (uint64_t)(uintptr_t)iview->planes[0].image_handle); - - pipe_sampler_view_reference(&iview->planes[0].sv, NULL); - device->queue.ctx->delete_texture_handle(device->queue.ctx, (uint64_t)(uintptr_t)iview->planes[0].texture_handle); + for (uint8_t plane = 0; plane < iview->plane_count; plane++) { + device->queue.ctx->delete_image_handle(device->queue.ctx, (uint64_t)(uintptr_t)iview->planes[plane].image_handle); + pipe_sampler_view_reference(&iview->planes[plane].sv, NULL); + device->queue.ctx->delete_texture_handle(device->queue.ctx, (uint64_t)(uintptr_t)iview->planes[plane].texture_handle); + } simple_mtx_unlock(&device->queue.lock); pipe_surface_reference(&iview->surface, NULL); diff --git a/src/gallium/frontends/lavapipe/lvp_private.h b/src/gallium/frontends/lavapipe/lvp_private.h index 92f799e188d..75d7a52e303 100644 --- a/src/gallium/frontends/lavapipe/lvp_private.h +++ b/src/gallium/frontends/lavapipe/lvp_private.h @@ -263,7 +263,9 @@ struct lvp_image { struct vk_image vk; VkDeviceSize size; uint32_t alignment; - struct lvp_image_plane planes[1]; + bool disjoint; + uint8_t plane_count; + struct lvp_image_plane planes[3]; }; struct lvp_image_view { @@ -277,11 +279,12 @@ struct lvp_image_view { uint8_t plane_count; struct { + unsigned image_plane; struct pipe_sampler_view *sv; struct pipe_image_view iv; struct lp_texture_handle *texture_handle; struct lp_texture_handle *image_handle; - } planes[1]; + } planes[3]; }; struct lvp_sampler { @@ -690,6 +693,25 @@ lvp_vk_format_to_pipe_format(VkFormat format) return vk_format_to_pipe_format(format); } +static inline uint8_t +lvp_image_aspects_to_plane(ASSERTED const struct lvp_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; + } +} + void lvp_pipeline_destroy(struct lvp_device *device, struct lvp_pipeline *pipeline, bool locked);
