From c6e76aed9dc28aae05cb11857201b5dab0c0cae8 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Fri, 26 Jun 2015 18:48:34 -0700 Subject: [PATCH] vk/image: Define anv_surface, refactor anv_image This prepares for upcoming miptree support. anv_surface is a proxy for color surfaces, depth surfaces, and stencil surfaces. Embed two instances of anv_surface into anv_image: the primary surface (color or depth), and an optional stencil surface. --- src/vulkan/image.c | 152 +++++++++++++++++++++++-------------------- src/vulkan/intel.c | 20 ++++-- src/vulkan/private.h | 52 +++++++++------ src/vulkan/x11.c | 7 +- 4 files changed, 131 insertions(+), 100 deletions(-) diff --git a/src/vulkan/image.c b/src/vulkan/image.c index 584e4bc62f3..4a42aecba41 100644 --- a/src/vulkan/image.c +++ b/src/vulkan/image.c @@ -96,6 +96,9 @@ anv_image_choose_tile_mode(const struct anv_image_create_info *anv_info) if (anv_info->force_tile_mode) return anv_info->tile_mode; + if (anv_info->vk_info->format == VK_FORMAT_S8_UINT) + return WMAJOR; + switch (anv_info->vk_info->tiling) { case VK_IMAGE_TILING_LINEAR: return LINEAR; @@ -107,6 +110,43 @@ anv_image_choose_tile_mode(const struct anv_image_create_info *anv_info) } } +static void +anv_image_make_surface(const struct anv_image_create_info *create_info, + uint64_t *inout_image_size, + uint32_t *inout_image_alignment, + struct anv_surface *out_surface) +{ + const VkExtent3D *restrict extent = &create_info->vk_info->extent; + + const uint8_t tile_mode = anv_image_choose_tile_mode(create_info); + + const struct anv_tile_info *tile_info = + &anv_tile_info_table[tile_mode]; + + const struct anv_format *format_info = + anv_format_for_vk_format(create_info->vk_info->format); + + uint32_t stride = align_u32(extent->width * format_info->cpp, + tile_info->width); + uint32_t size = stride * align_u32(extent->height, tile_info->height); + uint32_t offset = align_u32(*inout_image_size, + tile_info->surface_alignment); + + *inout_image_size = offset + size; + *inout_image_alignment = MAX(*inout_image_alignment, + tile_info->surface_alignment); + + *out_surface = (struct anv_surface) { + .offset = offset, + .stride = stride, + .tile_mode = tile_mode, + + /* FINISHME: Stop hardcoding miptree subimage alignment */ + .h_align = 4, + .v_align = 4, + }; +} + VkResult anv_image_create(VkDevice _device, const struct anv_image_create_info *create_info, @@ -115,6 +155,7 @@ anv_image_create(VkDevice _device, struct anv_device *device = (struct anv_device *) _device; const VkImageCreateInfo *pCreateInfo = create_info->vk_info; const VkExtent3D *restrict extent = &pCreateInfo->extent; + struct anv_image *image; assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO); @@ -127,8 +168,6 @@ anv_image_create(VkDevice _device, anv_assert(pCreateInfo->extent.height > 0); anv_assert(pCreateInfo->extent.depth == 1); - const uint32_t tile_mode = anv_image_choose_tile_mode(create_info); - /* TODO(chadv): How should we validate inputs? */ const uint8_t surf_type = anv_surf_type_from_image_type[pCreateInfo->imageType]; @@ -136,9 +175,6 @@ anv_image_create(VkDevice _device, const struct anv_surf_type_limits *limits = &anv_surf_type_limits[surf_type]; - const struct anv_tile_info *tile_info = - &anv_tile_info_table[tile_mode]; - if (extent->width > limits->width || extent->height > limits->height || extent->depth > limits->depth) { @@ -150,19 +186,21 @@ anv_image_create(VkDevice _device, const struct anv_format *format_info = anv_format_for_vk_format(pCreateInfo->format); - uint32_t image_stride = 0; - uint32_t image_size = 0; - uint32_t stencil_offset = 0; - uint32_t stencil_stride = 0; + image = anv_device_alloc(device, sizeof(*image), 8, + VK_SYSTEM_ALLOC_TYPE_API_OBJECT); + if (!image) + return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - if (!format_info->has_stencil || format_info->depth_format) { - /* The format has a color or depth component. Calculate space for it. */ - uint32_t aligned_height; + memset(image, 0, sizeof(*image)); + image->type = pCreateInfo->imageType; + image->extent = pCreateInfo->extent; + image->format = pCreateInfo->format; + image->surf_type = surf_type; - image_stride = align_i32(extent->width * format_info->cpp, - tile_info->width); - aligned_height = align_i32(extent->height, tile_info->height); - image_size = image_stride * aligned_height; + if (likely(!format_info->has_stencil || format_info->depth_format)) { + /* The image's primary surface is a color or depth surface. */ + anv_image_make_surface(create_info, &image->size, &image->alignment, + &image->primary_surface); } if (format_info->has_stencil) { @@ -171,51 +209,16 @@ anv_image_create(VkDevice _device, * stencil reside in the same image. To satisfy Vulkan and the GPU, we * place the depth and stencil buffers in the same bo. */ - const struct anv_tile_info *w_info = &anv_tile_info_table[WMAJOR]; - uint32_t aligned_height; - uint32_t stencil_size; - - stencil_offset = align_u32(image_size, w_info->surface_alignment); - stencil_stride = align_i32(extent->width, w_info->width); - aligned_height = align_i32(extent->height, w_info->height); - stencil_size = stencil_stride * aligned_height; - image_size = stencil_offset + stencil_size; + VkImageCreateInfo stencil_info = *pCreateInfo; + stencil_info.format = VK_FORMAT_S8_UINT; + + anv_image_make_surface( + &(struct anv_image_create_info) { + .vk_info = &stencil_info, + }, + &image->size, &image->alignment, &image->stencil_surface); } - struct anv_image *image = anv_device_alloc(device, sizeof(*image), 8, - VK_SYSTEM_ALLOC_TYPE_API_OBJECT); - if (!image) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - - /* To eliminate the risk of using unitialized struct members above, fill the - * image struct here at the function bottom instead of piecemeal throughout - * the function body. - */ - *image = (struct anv_image) { - .type = pCreateInfo->imageType, - .extent = pCreateInfo->extent, - .format = pCreateInfo->format, - - .size = image_size, - .alignment = tile_info->surface_alignment, - .stride = image_stride, - - .bo = NULL, - .offset = 0, - - .stencil_offset = stencil_offset, - .stencil_stride = stencil_stride, - - .tile_mode = tile_mode, - .surf_type = surf_type, - - /* FINISHME: Stop hardcoding miptree image alignment */ - .h_align = 4, - .v_align = 4, - - .swap_chain = NULL, - }; - *pImage = (VkImage) image; return VK_SUCCESS; @@ -266,6 +269,7 @@ anv_image_view_init(struct anv_surface_view *view, struct anv_cmd_buffer *cmd_buffer) { struct anv_image *image = (struct anv_image *) pCreateInfo->image; + struct anv_surface *surface = NULL; const struct anv_format *format_info = anv_format_for_vk_format(pCreateInfo->format); @@ -287,12 +291,15 @@ anv_image_view_init(struct anv_surface_view *view, case VK_IMAGE_ASPECT_DEPTH: case VK_IMAGE_ASPECT_COLOR: view->offset = image->offset; + surface = &image->primary_surface; break; default: unreachable(""); break; } + view->offset = image->offset + surface->offset; + /* TODO: Miplevels */ view->extent = image->extent; @@ -309,9 +316,9 @@ anv_image_view_init(struct anv_surface_view *view, .SurfaceType = anv_surf_type_from_image_view_type[pCreateInfo->viewType], .SurfaceArray = false, .SurfaceFormat = format_info->surface_format, - .SurfaceVerticalAlignment = anv_valign[image->v_align], - .SurfaceHorizontalAlignment = anv_halign[image->h_align], - .TileMode = image->tile_mode, + .SurfaceVerticalAlignment = anv_valign[surface->v_align], + .SurfaceHorizontalAlignment = anv_halign[surface->h_align], + .TileMode = surface->tile_mode, .VerticalLineStride = 0, .VerticalLineStrideOffset = 0, .SamplerL2BypassModeDisable = true, @@ -322,7 +329,7 @@ anv_image_view_init(struct anv_surface_view *view, .Height = image->extent.height - 1, .Width = image->extent.width - 1, .Depth = image->extent.depth - 1, - .SurfacePitch = image->stride - 1, + .SurfacePitch = surface->stride - 1, .MinimumArrayElement = 0, .NumberofMultisamples = MULTISAMPLECOUNT_1, .XOffset = 0, @@ -383,6 +390,7 @@ anv_color_attachment_view_init(struct anv_surface_view *view, struct anv_cmd_buffer *cmd_buffer) { struct anv_image *image = (struct anv_image *) pCreateInfo->image; + struct anv_surface *surface = &image->primary_surface; const struct anv_format *format = anv_format_for_vk_format(pCreateInfo->format); @@ -408,9 +416,9 @@ anv_color_attachment_view_init(struct anv_surface_view *view, .SurfaceType = SURFTYPE_2D, .SurfaceArray = false, .SurfaceFormat = format->surface_format, - .SurfaceVerticalAlignment = anv_valign[image->v_align], - .SurfaceHorizontalAlignment = anv_halign[image->h_align], - .TileMode = image->tile_mode, + .SurfaceVerticalAlignment = anv_valign[surface->v_align], + .SurfaceHorizontalAlignment = anv_halign[surface->h_align], + .TileMode = surface->tile_mode, .VerticalLineStride = 0, .VerticalLineStrideOffset = 0, .SamplerL2BypassModeDisable = true, @@ -421,7 +429,7 @@ anv_color_attachment_view_init(struct anv_surface_view *view, .Height = image->extent.height - 1, .Width = image->extent.width - 1, .Depth = image->extent.depth - 1, - .SurfacePitch = image->stride - 1, + .SurfacePitch = surface->stride - 1, .MinimumArrayElement = 0, .NumberofMultisamples = MULTISAMPLECOUNT_1, .XOffset = 0, @@ -476,6 +484,8 @@ anv_CreateDepthStencilView(VkDevice _device, struct anv_device *device = (struct anv_device *) _device; struct anv_depth_stencil_view *view; struct anv_image *image = (struct anv_image *) pCreateInfo->image; + struct anv_surface *depth_surface = &image->primary_surface; + struct anv_surface *stencil_surface = &image->stencil_surface; const struct anv_format *format = anv_format_for_vk_format(image->format); @@ -494,13 +504,13 @@ anv_CreateDepthStencilView(VkDevice _device, view->bo = image->bo; - view->depth_stride = image->stride; - view->depth_offset = image->offset; + view->depth_stride = depth_surface->stride; + view->depth_offset = image->offset + depth_surface->offset; view->depth_format = format->depth_format; view->depth_qpitch = 0; /* FINISHME: QPitch */ - view->stencil_stride = image->stencil_stride; - view->stencil_offset = image->offset + image->stencil_offset; + view->stencil_stride = stencil_surface->stride; + view->stencil_offset = image->offset + stencil_surface->offset; view->stencil_qpitch = 0; /* FINISHME: QPitch */ *pView = (VkDepthStencilView) view; diff --git a/src/vulkan/intel.c b/src/vulkan/intel.c index fbfed596397..06e79591ee4 100644 --- a/src/vulkan/intel.c +++ b/src/vulkan/intel.c @@ -65,13 +65,19 @@ VkResult anv_CreateDmaBufImageINTEL( goto fail_mem; } - image->bo = &mem->bo; - image->offset = 0; - image->type = VK_IMAGE_TYPE_2D; - image->extent = pCreateInfo->extent; - image->tile_mode = XMAJOR; - image->stride = pCreateInfo->strideInBytes; - image->size = mem->bo.size; + *image = (struct anv_image) { + .bo = &mem->bo, + .offset = 0, + .type = VK_IMAGE_TYPE_2D, + .extent = pCreateInfo->extent, + .size = mem->bo.size, + + .primary_surface = { + .offset = 0, + .stride = pCreateInfo->strideInBytes, + .tile_mode = XMAJOR, + }, + }; assert(image->extent.width > 0); assert(image->extent.height > 0); diff --git a/src/vulkan/private.h b/src/vulkan/private.h index d55912d7543..9a1d0a2c53a 100644 --- a/src/vulkan/private.h +++ b/src/vulkan/private.h @@ -784,17 +784,38 @@ struct anv_format { const struct anv_format * anv_format_for_vk_format(VkFormat format); +/** + * A proxy for the color surfaces, depth surfaces, and stencil surfaces. + */ +struct anv_surface { + /** + * Offset from VkImage's base address, as bound by vkBindImageMemory(). + */ + uint32_t offset; + + uint32_t stride; /**< RENDER_SURFACE_STATE.SurfacePitch */ + + /** + * \name Alignment of miptree images, in units of pixels. + * + * These fields contain the real alignment values, not the values to be + * given to the GPU. For example, if h_align is 4, then program the GPU + * with HALIGN_4. + * \{ + */ + uint8_t h_align; /**< RENDER_SURFACE_STATE.SurfaceHorizontalAlignment */ + uint8_t v_align; /**< RENDER_SURFACE_STATE.SurfaceVerticalAlignment */ + /** \} */ + + uint8_t tile_mode; /**< RENDER_SURFACE_STATE.TileMode */ +}; + struct anv_image { VkImageType type; VkExtent3D extent; VkFormat format; - uint32_t tile_mode; VkDeviceSize size; uint32_t alignment; - uint32_t stride; - - uint32_t stencil_offset; - uint32_t stencil_stride; /* Set when bound */ struct anv_bo *bo; @@ -802,23 +823,14 @@ struct anv_image { struct anv_swap_chain *swap_chain; - /** - * \name Alignment of miptree images, in units of pixels. - * - * These fields contain the actual alignment values, not the values the - * hardware expects. For example, if h_align is 4, then program the hardware - * with HALIGN_4. - * - * \see RENDER_SURFACE_STATE.SurfaceHorizontalAlignment - * \see RENDER_SURFACE_STATE.SurfaceVerticalAlignment - * \{ - */ - uint8_t h_align; - uint8_t v_align; - /** \} */ - /** RENDER_SURFACE_STATE.SurfaceType */ uint8_t surf_type; + + /** Primary surface is either color or depth. */ + struct anv_surface primary_surface; + + /** Stencil surface is optional. */ + struct anv_surface stencil_surface; }; struct anv_surface_view { diff --git a/src/vulkan/x11.c b/src/vulkan/x11.c index 6aeb34b9b56..d49b93331a8 100644 --- a/src/vulkan/x11.c +++ b/src/vulkan/x11.c @@ -104,6 +104,7 @@ VkResult anv_CreateSwapChainWSI( for (uint32_t i = 0; i < chain->count; i++) { struct anv_image *image; + struct anv_surface *surface; struct anv_device_memory *memory; anv_image_create((VkDevice) device, @@ -130,6 +131,8 @@ VkResult anv_CreateSwapChainWSI( }}, (VkImage *) &image); + surface = &image->primary_surface; + anv_AllocMemory((VkDevice) device, &(VkMemoryAllocInfo) { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO, @@ -143,7 +146,7 @@ VkResult anv_CreateSwapChainWSI( (VkDeviceMemory) memory, 0); ret = anv_gem_set_tiling(device, memory->bo.gem_handle, - image->stride, I915_TILING_X); + surface->stride, I915_TILING_X); if (ret) { result = vk_error(VK_ERROR_UNKNOWN); goto fail; @@ -166,7 +169,7 @@ VkResult anv_CreateSwapChainWSI( image->size, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, - image->stride, + surface->stride, depth, bpp, fd); chain->images[i].image = image; -- 2.30.2