ac: use 1D GEPs for descriptors and constants
[mesa.git] / src / amd / vulkan / radv_formats.c
index ee408b55334cc4e5e3a15658a7b37d5fe814dd87..9883002fa42df81c46459d7495de368166aa7356 100644 (file)
@@ -39,6 +39,8 @@ uint32_t radv_translate_buffer_dataformat(const struct vk_format_description *de
        unsigned type;
        int i;
 
+       assert(desc->layout != VK_FORMAT_LAYOUT_MULTIPLANE);
+
        if (desc->format == VK_FORMAT_B10G11R11_UFLOAT_PACK32)
                return V_008F0C_BUF_DATA_FORMAT_10_11_11;
 
@@ -110,6 +112,8 @@ uint32_t radv_translate_buffer_dataformat(const struct vk_format_description *de
 uint32_t radv_translate_buffer_numformat(const struct vk_format_description *desc,
                                         int first_non_void)
 {
+       assert(desc->layout != VK_FORMAT_LAYOUT_MULTIPLANE);
+
        if (desc->format == VK_FORMAT_B10G11R11_UFLOAT_PACK32)
                return V_008F0C_BUF_NUM_FORMAT_FLOAT;
 
@@ -146,6 +150,8 @@ uint32_t radv_translate_tex_dataformat(VkFormat format,
        bool uniform = true;
        int i;
 
+       assert(vk_format_get_plane_count(format) == 1);
+
        if (!desc)
                return ~0;
        /* Colorspace (return non-RGB formats directly). */
@@ -180,6 +186,18 @@ uint32_t radv_translate_tex_dataformat(VkFormat format,
                break;
        }
 
+       if (desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) {
+               switch(format) {
+               /* Don't ask me why this looks inverted. PAL does the same. */
+               case VK_FORMAT_G8B8G8R8_422_UNORM:
+                       return V_008F14_IMG_DATA_FORMAT_BG_RG;
+               case VK_FORMAT_B8G8R8G8_422_UNORM:
+                       return V_008F14_IMG_DATA_FORMAT_GB_GR;
+               default:
+                       goto out_unknown;
+               }
+       }
+
        if (desc->layout == VK_FORMAT_LAYOUT_RGTC) {
                switch(format) {
                case VK_FORMAT_BC4_UNORM_BLOCK:
@@ -359,6 +377,8 @@ uint32_t radv_translate_tex_numformat(VkFormat format,
                                      const struct vk_format_description *desc,
                                      int first_non_void)
 {
+       assert(vk_format_get_plane_count(format) == 1);
+
        switch (format) {
        case VK_FORMAT_D24_UNORM_S8_UINT:
                return V_008F14_IMG_NUM_FORMAT_UNORM;
@@ -421,6 +441,9 @@ uint32_t radv_translate_color_numformat(VkFormat format,
                                        int first_non_void)
 {
        unsigned ntype;
+
+       assert(vk_format_get_plane_count(format) == 1);
+
        if (first_non_void == -1 || desc->channel[first_non_void].type == VK_FORMAT_TYPE_FLOAT)
                ntype = V_028C70_NUMBER_FLOAT;
        else {
@@ -595,6 +618,14 @@ static bool radv_is_filter_minmax_format_supported(VkFormat format)
        }
 }
 
+bool
+radv_device_supports_etc(struct radv_physical_device *physical_device)
+{
+       return physical_device->rad_info.family == CHIP_VEGA10 ||
+              physical_device->rad_info.family == CHIP_RAVEN ||
+              physical_device->rad_info.family == CHIP_STONEY;
+}
+
 static void
 radv_physical_device_get_format_properties(struct radv_physical_device *physical_device,
                                           VkFormat format,
@@ -604,7 +635,8 @@ radv_physical_device_get_format_properties(struct radv_physical_device *physical
        const struct vk_format_description *desc = vk_format_description(format);
        bool blendable;
        bool scaled = false;
-       if (!desc) {
+       /* TODO: implement some software emulation of SUBSAMPLED formats. */
+       if (!desc || desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) {
                out_properties->linearTilingFeatures = linear;
                out_properties->optimalTilingFeatures = tiled;
                out_properties->bufferFeatures = buffer;
@@ -612,15 +644,33 @@ radv_physical_device_get_format_properties(struct radv_physical_device *physical
        }
 
        if (desc->layout == VK_FORMAT_LAYOUT_ETC &&
-           physical_device->rad_info.family != CHIP_VEGA10 &&
-           physical_device->rad_info.family != CHIP_RAVEN &&
-           physical_device->rad_info.family != CHIP_STONEY) {
+           !radv_device_supports_etc(physical_device)) {
                out_properties->linearTilingFeatures = linear;
                out_properties->optimalTilingFeatures = tiled;
                out_properties->bufferFeatures = buffer;
                return;
        }
 
+       if (desc->layout == VK_FORMAT_LAYOUT_MULTIPLANE ||
+           desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) {
+               uint32_t tiling = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
+                                 VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
+                                 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
+                                 VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT |
+                                 VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
+
+               /* The subsampled formats have no support for linear filters. */
+               if (desc->layout != VK_FORMAT_LAYOUT_SUBSAMPLED) {
+                       tiling |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT;
+               }
+
+               /* Fails for unknown reasons with linear tiling & subsampled formats. */
+               out_properties->linearTilingFeatures = desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED ? 0 : tiling;
+               out_properties->optimalTilingFeatures = tiling;
+               out_properties->bufferFeatures = 0;
+               return;
+       }
+
        if (radv_is_storage_image_format_supported(physical_device, format)) {
                tiled |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
                linear |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
@@ -984,10 +1034,22 @@ bool radv_format_pack_clear_color(VkFormat format,
                                assert(channel->size == 8);
 
                                v = util_format_linear_float_to_srgb_8unorm(value->float32[c]);
-                       } else if (channel->type == VK_FORMAT_TYPE_UNSIGNED) {
-                               v = MAX2(MIN2(value->float32[c], 1.0f), 0.0f) * ((1ULL << channel->size) - 1);
-                       } else  {
-                               v = MAX2(MIN2(value->float32[c], 1.0f), -1.0f) * ((1ULL << (channel->size - 1)) - 1);
+                       } else {
+                               float f = MIN2(value->float32[c], 1.0f);
+
+                               if (channel->type == VK_FORMAT_TYPE_UNSIGNED) {
+                                       f = MAX2(f, 0.0f) * ((1ULL << channel->size) - 1);
+                               } else {
+                                       f = MAX2(f, -1.0f) * ((1ULL << (channel->size - 1)) - 1);
+                               }
+
+                               /* The hardware rounds before conversion. */
+                               if (f > 0)
+                                       f += 0.5f;
+                               else
+                                       f -= 0.5f;
+
+                               v = (uint64_t)f;
                        }
                } else if (channel->type == VK_FORMAT_TYPE_FLOAT) {
                        if (channel->size == 32) {
@@ -1046,6 +1108,7 @@ static VkResult radv_get_image_format_properties(struct radv_physical_device *ph
        uint32_t maxMipLevels;
        uint32_t maxArraySize;
        VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;
+       const struct vk_format_description *desc = vk_format_description(info->format);
 
        radv_physical_device_get_format_properties(physical_device, info->format,
                                                   &format_props);
@@ -1089,6 +1152,12 @@ static VkResult radv_get_image_format_properties(struct radv_physical_device *ph
                break;
        }
 
+       if (desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) {
+               /* Might be able to support but the entire format support is
+                * messy, so taking the lazy way out. */
+               maxArraySize = 1;
+       }
+
        if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
            info->type == VK_IMAGE_TYPE_2D &&
            (format_feature_flags & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
@@ -1260,6 +1329,7 @@ VkResult radv_GetPhysicalDeviceImageFormatProperties2(
        RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice);
        const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
        VkExternalImageFormatProperties *external_props = NULL;
+       VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;
        VkResult result;
 
        result = radv_get_image_format_properties(physical_device, base_info,
@@ -1284,16 +1354,19 @@ VkResult radv_GetPhysicalDeviceImageFormatProperties2(
                case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
                        external_props = (void *) s;
                        break;
+               case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:
+                       ycbcr_props = (void *) s;
+                       break;
                default:
                        break;
                }
        }
 
-       /* From the Vulkan 1.0.42 spec:
+       /* From the Vulkan 1.0.97 spec:
         *
-        *    If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2KHR will
-        *    behave as if VkPhysicalDeviceExternalImageFormatInfoKHR was not
-        *    present and VkExternalImageFormatPropertiesKHR will be ignored.
+        *    If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will
+        *    behave as if VkPhysicalDeviceExternalImageFormatInfo was not
+        *    present and VkExternalImageFormatProperties will be ignored.
         */
        if (external_info && external_info->handleType != 0) {
                switch (external_info->handleType) {
@@ -1304,11 +1377,11 @@ VkResult radv_GetPhysicalDeviceImageFormatProperties2(
                                                             &external_props->externalMemoryProperties);
                        break;
                default:
-                       /* From the Vulkan 1.0.42 spec:
+                       /* From the Vulkan 1.0.97 spec:
                         *
                         *    If handleType is not compatible with the [parameters] specified
-                        *    in VkPhysicalDeviceImageFormatInfo2KHR, then
-                        *    vkGetPhysicalDeviceImageFormatProperties2KHR returns
+                        *    in VkPhysicalDeviceImageFormatInfo2, then
+                        *    vkGetPhysicalDeviceImageFormatProperties2 returns
                         *    VK_ERROR_FORMAT_NOT_SUPPORTED.
                         */
                        result = vk_errorf(physical_device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,
@@ -1318,14 +1391,18 @@ VkResult radv_GetPhysicalDeviceImageFormatProperties2(
                }
        }
 
+       if (ycbcr_props) {
+               ycbcr_props->combinedImageSamplerDescriptorCount = vk_format_get_plane_count(base_info->format);
+       }
+
        return VK_SUCCESS;
 
 fail:
        if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) {
-               /* From the Vulkan 1.0.42 spec:
+               /* From the Vulkan 1.0.97 spec:
                 *
                 *    If the combination of parameters to
-                *    vkGetPhysicalDeviceImageFormatProperties2KHR is not supported by
+                *    vkGetPhysicalDeviceImageFormatProperties2 is not supported by
                 *    the implementation for use in vkCreateImage, then all members of
                 *    imageFormatProperties will be filled with zero.
                 */