anv: Support swizzled formats.
authorJordan Justen <jordan.l.justen@intel.com>
Tue, 26 Jan 2016 19:10:56 +0000 (11:10 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Wed, 27 Jan 2016 04:29:16 +0000 (20:29 -0800)
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
src/vulkan/anv_image.c
src/vulkan/anv_meta.c
src/vulkan/anv_private.h
src/vulkan/genX_pipeline_util.h

index 2cfcac45b9b7497169edd4648a7f712167a427ce..30e865c39b6bb3af895f6763ff8cb2ab8806914e 100644 (file)
 
 #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
index 8417177105c25cc690f6e303d3ffa2a267d893be..a0a1312f81dcb33405413055375a6dd3c6c1dfd4 100644 (file)
@@ -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;
index 7034f70d6ac32e8de0e50e8f820013892676138b..4fed2ea9d54dcb5b3b074c12323e64499a2616c6 100644 (file)
@@ -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);
 }
index 1b3d80e61bee6a22f887a53e9a16aa48e3426d23..1ae7066f5fddd1e5acf726df3a6201b5b7980ba1 100644 (file)
@@ -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)
index e9c7d16a985ac08ab502b12b2e1fb49d694f1cd4..da61a1e5d39a68d0b4a4e1514fb34992361f4460 100644 (file)
@@ -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);