From c20f78dc5d7e0fabd58c2d8548d5a6ead1ec1072 Mon Sep 17 00:00:00 2001 From: Jordan Justen Date: Tue, 26 Jan 2016 11:10:56 -0800 Subject: [PATCH] anv: Support swizzled formats. Some formats require a swizzle in order to map them to actual hardware formats. This allows us to turn on two new Vulkan formats. --- src/vulkan/anv_formats.c | 40 ++++++++++++++++++++++++--------- src/vulkan/anv_image.c | 39 +++++++++++++++++++++++--------- src/vulkan/anv_meta.c | 3 ++- src/vulkan/anv_private.h | 10 ++++++++- src/vulkan/genX_pipeline_util.h | 3 ++- 5 files changed, 71 insertions(+), 24 deletions(-) diff --git a/src/vulkan/anv_formats.c b/src/vulkan/anv_formats.c index 2cfcac45b9b..30e865c39b6 100644 --- a/src/vulkan/anv_formats.c +++ b/src/vulkan/anv_formats.c @@ -26,15 +26,22 @@ #include "gen7_pack.h" -#define fmt(__vk_fmt, __hw_fmt, ...) \ +#define RGBA ((struct anv_format_swizzle) { 0, 1, 2, 3 }) +#define BGRA ((struct anv_format_swizzle) { 2, 1, 0, 3 }) + +#define swiz_fmt(__vk_fmt, __hw_fmt, __swizzle, ...) \ [__vk_fmt] = { \ .vk_format = __vk_fmt, \ .name = #__vk_fmt, \ .surface_format = __hw_fmt, \ .isl_layout = &isl_format_layouts[__hw_fmt], \ + .swizzle = __swizzle, \ __VA_ARGS__ \ } +#define fmt(__vk_fmt, __hw_fmt, ...) \ + swiz_fmt(__vk_fmt, __hw_fmt, RGBA, __VA_ARGS__) + /* HINT: For array formats, the ISL name should match the VK name. For * packed formats, they should have the channels in reverse order from each * other. The reason for this is that, for packed formats, the ISL (and @@ -44,9 +51,9 @@ static const struct anv_format anv_formats[] = { fmt(VK_FORMAT_UNDEFINED, ISL_FORMAT_RAW), fmt(VK_FORMAT_R4G4_UNORM_PACK8, ISL_FORMAT_UNSUPPORTED), fmt(VK_FORMAT_R4G4B4A4_UNORM_PACK16, ISL_FORMAT_A4B4G4R4_UNORM), - fmt(VK_FORMAT_B4G4R4A4_UNORM_PACK16, ISL_FORMAT_UNSUPPORTED), + swiz_fmt(VK_FORMAT_B4G4R4A4_UNORM_PACK16, ISL_FORMAT_A4B4G4R4_UNORM, BGRA), fmt(VK_FORMAT_R5G6B5_UNORM_PACK16, ISL_FORMAT_B5G6R5_UNORM), - fmt(VK_FORMAT_B5G6R5_UNORM_PACK16, ISL_FORMAT_UNSUPPORTED), + swiz_fmt(VK_FORMAT_B5G6R5_UNORM_PACK16, ISL_FORMAT_B5G6R5_UNORM, BGRA), fmt(VK_FORMAT_R5G5B5A1_UNORM_PACK16, ISL_FORMAT_A1B5G5R5_UNORM), fmt(VK_FORMAT_B5G5R5A1_UNORM_PACK16, ISL_FORMAT_UNSUPPORTED), fmt(VK_FORMAT_A1R5G5B5_UNORM_PACK16, ISL_FORMAT_B5G5R5A1_UNORM), @@ -243,10 +250,13 @@ anv_format_for_vk_format(VkFormat format) */ enum isl_format anv_get_isl_format(VkFormat format, VkImageAspectFlags aspect, - VkImageTiling tiling) + VkImageTiling tiling, struct anv_format_swizzle *swizzle) { const struct anv_format *anv_fmt = &anv_formats[format]; + if (swizzle) + *swizzle = anv_fmt->swizzle; + switch (aspect) { case VK_IMAGE_ASPECT_COLOR_BIT: if (anv_fmt->surface_format == ISL_FORMAT_UNSUPPORTED) { @@ -296,7 +306,8 @@ void anv_validate_GetPhysicalDeviceFormatProperties( static VkFormatFeatureFlags get_image_format_properties(int gen, enum isl_format base, - enum isl_format actual) + enum isl_format actual, + struct anv_format_swizzle swizzle) { const struct brw_surface_format_info *info = &surface_formats[actual]; @@ -309,12 +320,16 @@ get_image_format_properties(int gen, enum isl_format base, VK_FORMAT_FEATURE_BLIT_SRC_BIT; } - if (info->render_target <= gen) { + /* We can render to swizzled formats. However, if the alpha channel is + * moved, then blending won't work correctly. The PRM tells us + * straight-up not to render to such a surface. + */ + if (info->render_target <= gen && swizzle.a == 3) { flags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT; } - if (info->alpha_blend <= gen) + if (info->alpha_blend <= gen && swizzle.a == 3) flags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT; /* Load/store is determined based on base format. This prevents RGB @@ -374,13 +389,16 @@ anv_physical_device_get_format_properties(struct anv_physical_device *physical_d } } else { enum isl_format linear_fmt, tiled_fmt; + struct anv_format_swizzle linear_swizzle, tiled_swizzle; linear_fmt = anv_get_isl_format(format, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_TILING_LINEAR); + VK_IMAGE_TILING_LINEAR, &linear_swizzle); tiled_fmt = anv_get_isl_format(format, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_TILING_OPTIMAL); + VK_IMAGE_TILING_OPTIMAL, &tiled_swizzle); - linear = get_image_format_properties(gen, linear_fmt, linear_fmt); - tiled = get_image_format_properties(gen, linear_fmt, tiled_fmt); + linear = get_image_format_properties(gen, linear_fmt, linear_fmt, + linear_swizzle); + tiled = get_image_format_properties(gen, linear_fmt, tiled_fmt, + tiled_swizzle); buffer = get_buffer_format_properties(gen, linear_fmt); /* XXX: We handle 3-channel formats by switching them out for RGBX or diff --git a/src/vulkan/anv_image.c b/src/vulkan/anv_image.c index 8417177105c..a0a1312f81d 100644 --- a/src/vulkan/anv_image.c +++ b/src/vulkan/anv_image.c @@ -128,7 +128,8 @@ make_surface(const struct anv_device *dev, ok = isl_surf_init(&dev->isl_dev, &anv_surf->isl, .dim = vk_to_isl_surf_dim[vk_info->imageType], - .format = anv_get_isl_format(vk_info->format, aspect, vk_info->tiling), + .format = anv_get_isl_format(vk_info->format, aspect, + vk_info->tiling, NULL), .width = vk_info->extent.width, .height = vk_info->extent.height, .depth = vk_info->extent.depth, @@ -454,12 +455,28 @@ has_matching_storage_typed_format(const struct anv_device *device, } static VkComponentSwizzle -remap_swizzle(VkComponentSwizzle swizzle, VkComponentSwizzle component) +remap_swizzle(VkComponentSwizzle swizzle, VkComponentSwizzle component, + struct anv_format_swizzle format_swizzle) { if (swizzle == VK_COMPONENT_SWIZZLE_IDENTITY) - return component; - else - return swizzle; + swizzle = component; + + switch (swizzle) { + case VK_COMPONENT_SWIZZLE_ZERO: + return VK_COMPONENT_SWIZZLE_ZERO; + case VK_COMPONENT_SWIZZLE_ONE: + return VK_COMPONENT_SWIZZLE_ONE; + case VK_COMPONENT_SWIZZLE_R: + return VK_COMPONENT_SWIZZLE_R + format_swizzle.r; + case VK_COMPONENT_SWIZZLE_G: + return VK_COMPONENT_SWIZZLE_R + format_swizzle.g; + case VK_COMPONENT_SWIZZLE_B: + return VK_COMPONENT_SWIZZLE_R + format_swizzle.b; + case VK_COMPONENT_SWIZZLE_A: + return VK_COMPONENT_SWIZZLE_R + format_swizzle.a; + default: + unreachable("Invalid swizzle"); + } } void @@ -500,16 +517,18 @@ anv_image_view_init(struct anv_image_view *iview, iview->aspect_mask = pCreateInfo->subresourceRange.aspectMask; iview->vk_format = pCreateInfo->format; + + struct anv_format_swizzle swizzle; iview->format = anv_get_isl_format(pCreateInfo->format, iview->aspect_mask, - image->tiling); + image->tiling, &swizzle); iview->swizzle.r = remap_swizzle(pCreateInfo->components.r, - VK_COMPONENT_SWIZZLE_R); + VK_COMPONENT_SWIZZLE_R, swizzle); iview->swizzle.g = remap_swizzle(pCreateInfo->components.g, - VK_COMPONENT_SWIZZLE_G); + VK_COMPONENT_SWIZZLE_G, swizzle); iview->swizzle.b = remap_swizzle(pCreateInfo->components.b, - VK_COMPONENT_SWIZZLE_B); + VK_COMPONENT_SWIZZLE_B, swizzle); iview->swizzle.a = remap_swizzle(pCreateInfo->components.a, - VK_COMPONENT_SWIZZLE_A); + VK_COMPONENT_SWIZZLE_A, swizzle); iview->base_layer = range->baseArrayLayer; iview->base_mip = range->baseMipLevel; diff --git a/src/vulkan/anv_meta.c b/src/vulkan/anv_meta.c index 7034f70d6ac..4fed2ea9d54 100644 --- a/src/vulkan/anv_meta.c +++ b/src/vulkan/anv_meta.c @@ -972,7 +972,8 @@ choose_buffer_format(struct anv_image *image, VkImageAspectFlagBits aspect) * work if the buffer is the destination. */ enum isl_format linear_format = anv_get_isl_format(image->vk_format, aspect, - VK_IMAGE_TILING_LINEAR); + VK_IMAGE_TILING_LINEAR, + NULL); return vk_format_for_size(isl_format_layouts[linear_format].bs); } diff --git a/src/vulkan/anv_private.h b/src/vulkan/anv_private.h index 1b3d80e61be..1ae7066f5fd 100644 --- a/src/vulkan/anv_private.h +++ b/src/vulkan/anv_private.h @@ -1472,12 +1472,20 @@ gen9_compute_pipeline_create(VkDevice _device, const VkAllocationCallbacks *alloc, VkPipeline *pPipeline); +struct anv_format_swizzle { + unsigned r:2; + unsigned g:2; + unsigned b:2; + unsigned a:2; +}; + struct anv_format { const VkFormat vk_format; const char *name; enum isl_format surface_format; /**< RENDER_SURFACE_STATE.SurfaceFormat */ const struct isl_format_layout *isl_layout; uint16_t depth_format; /**< 3DSTATE_DEPTH_BUFFER.SurfaceFormat */ + struct anv_format_swizzle swizzle; bool has_stencil; }; @@ -1486,7 +1494,7 @@ anv_format_for_vk_format(VkFormat format); enum isl_format anv_get_isl_format(VkFormat format, VkImageAspectFlags aspect, - VkImageTiling tiling); + VkImageTiling tiling, struct anv_format_swizzle *swizzle); static inline bool anv_format_is_color(const struct anv_format *format) diff --git a/src/vulkan/genX_pipeline_util.h b/src/vulkan/genX_pipeline_util.h index e9c7d16a985..da61a1e5d39 100644 --- a/src/vulkan/genX_pipeline_util.h +++ b/src/vulkan/genX_pipeline_util.h @@ -99,7 +99,8 @@ emit_vertex_input(struct anv_pipeline *pipeline, &info->pVertexAttributeDescriptions[i]; enum isl_format format = anv_get_isl_format(desc->format, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_TILING_LINEAR); + VK_IMAGE_TILING_LINEAR, + NULL); assert(desc->binding < 32); -- 2.30.2