turnip: fix VkClearValue packing
authorChia-I Wu <olvaffe@gmail.com>
Wed, 13 Feb 2019 18:23:32 +0000 (10:23 -0800)
committerChia-I Wu <olvaffe@gmail.com>
Mon, 11 Mar 2019 17:02:13 +0000 (10:02 -0700)
Add tu_pack_clear_value to correctly pack VkClearValue according to
VkFormat.  It ignores the component order defined by VkFormat, and
always packs to WZYX order.

src/freedreno/vulkan/tu_cmd_buffer.c
src/freedreno/vulkan/tu_formats.c
src/freedreno/vulkan/tu_private.h

index 59e31b39b7be5f0e21f2159b04f0258274226476..51f97971335328346ab242549cc0dd94e0d756c7 100644 (file)
@@ -617,17 +617,21 @@ tu6_emit_blit_info(struct tu_cmd_buffer *cmd,
 static void
 tu6_emit_blit_clear(struct tu_cmd_buffer *cmd,
                     struct tu_cs *cs,
+                    const struct tu_image_view *iview,
                     uint32_t gmem_offset,
                     const VkClearValue *clear_value)
 {
    const enum a6xx_tile_mode tile_mode = TILE6_LINEAR;
    const enum a3xx_msaa_samples samples = tu6_msaa_samples(1);
    const enum a6xx_color_fmt format = RB6_R8G8B8A8_UNORM;
+   /* must be WZYX; other values are ignored */
+   const enum a3xx_color_swap swap = WZYX;
 
    tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLIT_DST_INFO, 1);
    tu_cs_emit(cs, A6XX_RB_BLIT_DST_INFO_TILE_MODE(tile_mode) |
                      A6XX_RB_BLIT_DST_INFO_SAMPLES(samples) |
-                     A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(format));
+                     A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(format) |
+                     A6XX_RB_BLIT_DST_INFO_COLOR_SWAP(swap));
 
    tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLIT_INFO, 1);
    tu_cs_emit(cs, A6XX_RB_BLIT_INFO_GMEM | A6XX_RB_BLIT_INFO_CLEAR_MASK(0xf));
@@ -638,14 +642,10 @@ tu6_emit_blit_clear(struct tu_cmd_buffer *cmd,
    tu_cs_emit_pkt4(cs, REG_A6XX_RB_UNKNOWN_88D0, 1);
    tu_cs_emit(cs, 0);
 
-   /* att->clear_value? */
-   uint32_t clear_vals[4] = {
-      ((int) (clear_value->color.float32[0] * 255) << 24) |
-         ((int) (clear_value->color.float32[1] * 255) << 16) |
-         ((int) (clear_value->color.float32[2] * 255) << 8) |
-         ((int) (clear_value->color.float32[3] * 255) << 0),
-      0, 0, 0
-   };
+   /* pack clear_value into WZYX order */
+   uint32_t clear_vals[4] = { 0 };
+   tu_pack_clear_value(clear_value, iview->vk_format, clear_vals);
+
    tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLIT_CLEAR_COLOR_DW0, 4);
    tu_cs_emit(cs, clear_vals[0]);
    tu_cs_emit(cs, clear_vals[1]);
@@ -753,13 +753,14 @@ tu6_emit_tile_load(struct tu_cmd_buffer *cmd, struct tu_cs *cs)
       if (a == VK_ATTACHMENT_UNUSED)
          continue;
 
+      const struct tu_image_view *iview = fb->attachments[a].attachment;
       const struct tu_attachment_state *att = attachments + a;
       if (att->pending_clear_aspects) {
          assert(att->pending_clear_aspects == VK_IMAGE_ASPECT_COLOR_BIT);
-         tu6_emit_blit_clear(cmd, cs, tiling->gmem_offsets[gmem_index++],
+         tu6_emit_blit_clear(cmd, cs, iview,
+                             tiling->gmem_offsets[gmem_index++],
                              &att->clear_value);
       } else {
-         const struct tu_image_view *iview = fb->attachments[a].attachment;
          tu6_emit_blit_info(cmd, cs, iview,
                             tiling->gmem_offsets[gmem_index++],
                             A6XX_RB_BLIT_INFO_UNK0 | A6XX_RB_BLIT_INFO_GMEM);
index 7f936f5f114784e992da489d43895192d29a9d14..00a45aaac0102907ac45173cd27b3599d6793fa0 100644 (file)
@@ -337,6 +337,216 @@ tu6_get_native_format(VkFormat format)
    return (fmt && fmt->present) ? fmt : NULL;
 }
 
+static uint32_t
+tu_pack_mask(int bits)
+{
+   assert(bits <= 32);
+   return (1ull << bits) - 1;
+}
+
+static uint32_t
+tu_pack_float32_for_unorm(float val, int bits)
+{
+   const uint32_t max = tu_pack_mask(bits);
+   if (val < 0.0f)
+      return 0;
+   else if (val > 1.0f)
+      return max;
+   else
+      return _mesa_lroundevenf(val * (float) max);
+}
+
+static uint32_t
+tu_pack_float32_for_snorm(float val, int bits)
+{
+   const int32_t max = tu_pack_mask(bits - 1);
+   int32_t tmp;
+   if (val < -1.0f)
+      tmp = -max;
+   else if (val > 1.0f)
+      tmp = max;
+   else
+      tmp = _mesa_lroundevenf(val * (float) max);
+
+   return tmp & tu_pack_mask(bits);
+}
+
+static uint32_t
+tu_pack_float32_for_uscaled(float val, int bits)
+{
+   const uint32_t max = tu_pack_mask(bits);
+   if (val < 0.0f)
+      return 0;
+   else if (val > (float) max)
+      return max;
+   else
+      return (uint32_t) val;
+}
+
+static uint32_t
+tu_pack_float32_for_sscaled(float val, int bits)
+{
+   const int32_t max = tu_pack_mask(bits - 1);
+   const int32_t min = -max - 1;
+   int32_t tmp;
+   if (val < (float) min)
+      tmp = min;
+   else if (val > (float) max)
+      tmp = max;
+   else
+      tmp = (int32_t) val;
+
+   return tmp & tu_pack_mask(bits);
+}
+
+static uint32_t
+tu_pack_uint32_for_uint(uint32_t val, int bits)
+{
+   return val & tu_pack_mask(bits);
+}
+
+static uint32_t
+tu_pack_int32_for_sint(int32_t val, int bits)
+{
+   return val & tu_pack_mask(bits);
+}
+
+static uint32_t
+tu_pack_float32_for_sfloat(float val, int bits)
+{
+   assert(bits == 16 || bits == 32);
+   return bits == 16 ? util_float_to_half(val) : fui(val);
+}
+
+union tu_clear_component_value {
+   float float32;
+   int32_t int32;
+   uint32_t uint32;
+};
+
+static uint32_t
+tu_pack_clear_component_value(union tu_clear_component_value val,
+                              const struct vk_format_channel_description *ch)
+{
+   uint32_t packed;
+
+   switch (ch->type) {
+   case VK_FORMAT_TYPE_UNSIGNED:
+      /* normalized, scaled, or pure integer */
+      assert(ch->normalized + ch->scaled + ch->pure_integer == 1);
+      if (ch->normalized)
+         packed = tu_pack_float32_for_unorm(val.float32, ch->size);
+      else if (ch->scaled)
+         packed = tu_pack_float32_for_uscaled(val.float32, ch->size);
+      else
+         packed = tu_pack_uint32_for_uint(val.uint32, ch->size);
+      break;
+   case VK_FORMAT_TYPE_SIGNED:
+      /* normalized, scaled, or pure integer */
+      assert(ch->normalized + ch->scaled + ch->pure_integer == 1);
+      if (ch->normalized)
+         packed = tu_pack_float32_for_snorm(val.float32, ch->size);
+      else if (ch->scaled)
+         packed = tu_pack_float32_for_sscaled(val.float32, ch->size);
+      else
+         packed = tu_pack_int32_for_sint(val.int32, ch->size);
+      break;
+   case VK_FORMAT_TYPE_FLOAT:
+      packed = tu_pack_float32_for_sfloat(val.float32, ch->size);
+      break;
+   default:
+      unreachable("unexpected channel type");
+      packed = 0;
+      break;
+   }
+
+   assert((packed & tu_pack_mask(ch->size)) == packed);
+   return packed;
+}
+
+static const struct vk_format_channel_description *
+tu_get_format_channel_description(const struct vk_format_description *desc,
+                                  int comp)
+{
+   switch (desc->swizzle[comp]) {
+   case VK_SWIZZLE_X:
+      return &desc->channel[0];
+   case VK_SWIZZLE_Y:
+      return &desc->channel[1];
+   case VK_SWIZZLE_Z:
+      return &desc->channel[2];
+   case VK_SWIZZLE_W:
+      return &desc->channel[3];
+   default:
+      return NULL;
+   }
+}
+
+static union tu_clear_component_value
+tu_get_clear_component_value(const VkClearValue *val, int comp, bool color)
+{
+   union tu_clear_component_value tmp;
+   if (color) {
+      assert(comp < 4);
+      tmp.uint32 = val->color.uint32[comp];
+   } else {
+      assert(comp < 2);
+      if (comp == 0)
+         tmp.float32 = val->depthStencil.depth;
+      else
+         tmp.uint32 = val->depthStencil.stencil;
+   }
+
+   return tmp;
+}
+
+/**
+ * Pack a VkClearValue into a 128-bit buffer.  \a format is respected except
+ * for the component order.  The components are always packed in WZYX order
+ * (i.e., msb is white and lsb is red).
+ *
+ * Return the number of uint32_t's used.
+ */
+int
+tu_pack_clear_value(const VkClearValue *val, VkFormat format, uint32_t buf[4])
+{
+   const struct vk_format_description *desc = vk_format_description(format);
+   assert(desc && desc->layout == VK_FORMAT_LAYOUT_PLAIN);
+
+   /* S8_UINT is special and has no depth */
+   const int max_components =
+      format == VK_FORMAT_S8_UINT ? 2 : desc->nr_channels;
+
+   int buf_offset = 0;
+   int bit_shift = 0;
+   for (int comp = 0; comp < max_components; comp++) {
+      const struct vk_format_channel_description *ch =
+         tu_get_format_channel_description(desc, comp);
+      if (!ch) {
+         assert(format == VK_FORMAT_S8_UINT && comp == 0);
+         continue;
+      }
+
+      union tu_clear_component_value v = tu_get_clear_component_value(
+         val, comp, desc->colorspace != VK_FORMAT_COLORSPACE_ZS);
+
+      /* move to the next uint32_t when there is not enough space */
+      assert(ch->size <= 32);
+      if (bit_shift + ch->size > 32) {
+         buf_offset++;
+         bit_shift = 0;
+      }
+
+      if (bit_shift == 0)
+         buf[buf_offset] = 0;
+
+      buf[buf_offset] |= tu_pack_clear_component_value(v, ch) << bit_shift;
+      bit_shift += ch->size;
+   }
+
+   return buf_offset + 1;
+}
+
 static void
 tu_physical_device_get_format_properties(
    struct tu_physical_device *physical_device,
index 62f7cf280042d7ec0fae3239332f3e3ad5b1acc6..808fee6cbe896bd4a52dea9936c15a86f59d4739 100644 (file)
@@ -983,41 +983,8 @@ tu_graphics_pipeline_create(
    const VkAllocationCallbacks *alloc,
    VkPipeline *pPipeline);
 
-struct vk_format_description;
-uint32_t
-tu_translate_buffer_dataformat(const struct vk_format_description *desc,
-                               int first_non_void);
-uint32_t
-tu_translate_buffer_numformat(const struct vk_format_description *desc,
-                              int first_non_void);
-uint32_t
-tu_translate_colorformat(VkFormat format);
-uint32_t
-tu_translate_color_numformat(VkFormat format,
-                             const struct vk_format_description *desc,
-                             int first_non_void);
-uint32_t
-tu_colorformat_endian_swap(uint32_t colorformat);
-unsigned
-tu_translate_colorswap(VkFormat format, bool do_endian_swap);
-uint32_t
-tu_translate_dbformat(VkFormat format);
-uint32_t
-tu_translate_tex_dataformat(VkFormat format,
-                            const struct vk_format_description *desc,
-                            int first_non_void);
-uint32_t
-tu_translate_tex_numformat(VkFormat format,
-                           const struct vk_format_description *desc,
-                           int first_non_void);
-bool
-tu_format_pack_clear_color(VkFormat format,
-                           uint32_t clear_vals[2],
-                           VkClearColorValue *value);
-bool
-tu_is_colorbuffer_format_supported(VkFormat format, bool *blendable);
-bool
-tu_dcc_formats_compatible(VkFormat format1, VkFormat format2);
+int
+tu_pack_clear_value(const VkClearValue *val, VkFormat format, uint32_t buf[4]);
 
 struct tu_image_level
 {