turnip: parse VkPipelineVertexInputStateCreateInfo
[mesa.git] / src / freedreno / vulkan / tu_formats.c
index e0a2d39436f6dddc5e0bb4d200697859bb1f207d..ce013e65c226c04d65c48250f213315d49b886bd 100644 (file)
 #include "vk_format.h"
 #include "vk_util.h"
 
-struct tu_native_format
-{
-   int vtx; /* VFMTn_xxx or -1 */
-   int tex; /* TFMTn_xxx or -1 */
-   int rb;  /* RBn_xxx or -1 */
-   enum a3xx_color_swap swap;
-   bool present;
-};
-
 /**
  * Declare a format table.  A format table is an array of tu_native_format.
  * It can map a consecutive range of VkFormat to the corresponding
@@ -325,7 +316,7 @@ TU_FORMAT_TABLE(tu6_format_table0) = {
 #undef TU_FORMAT_TABLE_FIRST
 #undef TU_FORMAT_TABLE_LAST
 
-static const struct tu_native_format *
+const struct tu_native_format *
 tu6_get_native_format(VkFormat format)
 {
    const struct tu_native_format *fmt = NULL;
@@ -337,6 +328,285 @@ tu6_get_native_format(VkFormat format)
    return (fmt && fmt->present) ? fmt : NULL;
 }
 
+enum a6xx_2d_ifmt
+tu6_rb_fmt_to_ifmt(enum a6xx_color_fmt fmt)
+{
+   switch (fmt) {
+   case RB6_A8_UNORM:
+   case RB6_R8_UNORM:
+   case RB6_R8_SNORM:
+   case RB6_R8G8_UNORM:
+   case RB6_R8G8_SNORM:
+   case RB6_R8G8B8A8_UNORM:
+   case RB6_R8G8B8_UNORM:
+   case RB6_R8G8B8A8_SNORM:
+      return R2D_UNORM8;
+
+   case RB6_R32_UINT:
+   case RB6_R32_SINT:
+   case RB6_R32G32_UINT:
+   case RB6_R32G32_SINT:
+   case RB6_R32G32B32A32_UINT:
+   case RB6_R32G32B32A32_SINT:
+      return R2D_INT32;
+
+   case RB6_R16_UINT:
+   case RB6_R16_SINT:
+   case RB6_R16G16_UINT:
+   case RB6_R16G16_SINT:
+   case RB6_R16G16B16A16_UINT:
+   case RB6_R16G16B16A16_SINT:
+      return R2D_INT16;
+
+   case RB6_R8_UINT:
+   case RB6_R8_SINT:
+   case RB6_R8G8_UINT:
+   case RB6_R8G8_SINT:
+   case RB6_R8G8B8A8_UINT:
+   case RB6_R8G8B8A8_SINT:
+      return R2D_INT8;
+
+   case RB6_R16_UNORM:
+   case RB6_R16_SNORM:
+   case RB6_R16G16_UNORM:
+   case RB6_R16G16_SNORM:
+   case RB6_R16G16B16A16_UNORM:
+   case RB6_R16G16B16A16_SNORM:
+   case RB6_R32_FLOAT:
+   case RB6_R32G32_FLOAT:
+   case RB6_R32G32B32A32_FLOAT:
+      return R2D_FLOAT32;
+
+   case RB6_R16_FLOAT:
+   case RB6_R16G16_FLOAT:
+   case RB6_R16G16B16A16_FLOAT:
+      return R2D_FLOAT16;
+
+   case RB6_R4G4B4A4_UNORM:
+   case RB6_R5G5B5A1_UNORM:
+   case RB6_R5G6B5_UNORM:
+   case RB6_R10G10B10A2_UNORM:
+   case RB6_R10G10B10A2_UINT:
+   case RB6_R11G11B10_FLOAT:
+   case RB6_X8Z24_UNORM:
+      // ???
+      return 0;
+   default:
+      unreachable("bad format");
+      return 0;
+   }
+}
+
+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,
@@ -544,8 +814,9 @@ tu_GetPhysicalDeviceImageFormatProperties(
                                          pImageFormatProperties);
 }
 
-static void
-get_external_image_format_properties(
+static VkResult
+tu_get_external_image_format_properties(
+   const struct tu_physical_device *physical_device,
    const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo,
    VkExternalMemoryHandleTypeFlagBitsKHR handleType,
    VkExternalMemoryPropertiesKHR *external_properties)
@@ -553,6 +824,15 @@ get_external_image_format_properties(
    VkExternalMemoryFeatureFlagBitsKHR flags = 0;
    VkExternalMemoryHandleTypeFlagsKHR export_flags = 0;
    VkExternalMemoryHandleTypeFlagsKHR compat_flags = 0;
+
+   /* From the Vulkan 1.1.98 spec:
+    *
+    *    If handleType is not compatible with the format, type, tiling,
+    *    usage, and flags specified in VkPhysicalDeviceImageFormatInfo2,
+    *    then vkGetPhysicalDeviceImageFormatProperties2 returns
+    *    VK_ERROR_FORMAT_NOT_SUPPORTED.
+    */
+
    switch (handleType) {
    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
@@ -566,7 +846,9 @@ get_external_image_format_properties(
             VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
          break;
       default:
-         break;
+         return vk_errorf(physical_device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,
+                          "VkExternalMemoryTypeFlagBits(0x%x) unsupported for VkImageType(%d)",
+                          handleType, pImageFormatInfo->type);
       }
       break;
    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
@@ -574,7 +856,9 @@ get_external_image_format_properties(
       compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
       break;
    default:
-      break;
+      return vk_errorf(physical_device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,
+                       "VkExternalMemoryTypeFlagBits(0x%x) unsupported",
+                       handleType);
    }
 
    *external_properties = (VkExternalMemoryPropertiesKHR) {
@@ -582,6 +866,8 @@ get_external_image_format_properties(
       .exportFromImportedHandleTypes = export_flags,
       .compatibleHandleTypes = compat_flags,
    };
+
+   return VK_SUCCESS;
 }
 
 VkResult
@@ -631,29 +917,11 @@ tu_GetPhysicalDeviceImageFormatProperties2(
     *    present and VkExternalImageFormatPropertiesKHR will be ignored.
     */
    if (external_info && external_info->handleType != 0) {
-      switch (external_info->handleType) {
-      case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
-      case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
-      case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
-         get_external_image_format_properties(
-            base_info, external_info->handleType,
-            &external_props->externalMemoryProperties);
-         break;
-      default:
-         /* From the Vulkan 1.0.42 spec:
-          *
-          *    If handleType is not compatible with the [parameters]
-          * specified
-          *    in VkPhysicalDeviceImageFormatInfo2KHR, then
-          *    vkGetPhysicalDeviceImageFormatProperties2KHR returns
-          *    VK_ERROR_FORMAT_NOT_SUPPORTED.
-          */
-         result = vk_errorf(
-            physical_device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,
-            "unsupported VkExternalMemoryTypeFlagBitsKHR 0x%x",
-            external_info->handleType);
+      result = tu_get_external_image_format_properties(
+         physical_device, base_info, external_info->handleType,
+         &external_props->externalMemoryProperties);
+      if (result != VK_SUCCESS)
          goto fail;
-      }
    }
 
    return VK_SUCCESS;