Module: Mesa
Branch: main
Commit: 0265a231724b16bb86dd38b4ce0670da1e7ccd21
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=0265a231724b16bb86dd38b4ce0670da1e7ccd21

Author: Rajnesh Kanwal <[email protected]>
Date:   Fri Aug 12 16:23:05 2022 +0100

pvr: Implement vkGetPhysicalDeviceImageFormatProperties2 API.

Signed-off-by: Rajnesh Kanwal <[email protected]>
Reviewed-by: Frank Binns <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18487>

---

 docs/features.txt                             |   2 +-
 src/imagination/csbgen/rogue_texstate.xml     |   8 +-
 src/imagination/include/hwdef/rogue_hw_defs.h |   2 -
 src/imagination/vulkan/pvr_device.c           |   4 +-
 src/imagination/vulkan/pvr_formats.c          | 203 ++++++++++++++++++++++++--
 src/imagination/vulkan/pvr_formats.h          |  22 +++
 src/imagination/vulkan/pvr_limits.h           |   8 +-
 7 files changed, 227 insertions(+), 22 deletions(-)

diff --git a/docs/features.txt b/docs/features.txt
index 5cfea1a71d4..f34df845700 100644
--- a/docs/features.txt
+++ b/docs/features.txt
@@ -433,7 +433,7 @@ Vulkan 1.1 -- all DONE: anv, lvp, radv, tu, vn
   VK_KHR_external_semaphore                             DONE (anv, lvp, radv, 
tu, v3dv, vn)
   VK_KHR_external_semaphore_capabilities                DONE (anv, lvp, radv, 
tu, v3dv, vn)
   VK_KHR_get_memory_requirements2                       DONE (anv, lvp, radv, 
tu, v3dv, vn)
-  VK_KHR_get_physical_device_properties2                DONE (anv, dzn, lvp, 
panvk, radv, tu, v3dv, vn)
+  VK_KHR_get_physical_device_properties2                DONE (anv, dzn, lvp, 
panvk, pvr, radv, tu, v3dv, vn)
   VK_KHR_maintenance1                                   DONE (anv, lvp, radv, 
tu, v3dv, vn)
   VK_KHR_maintenance2                                   DONE (anv, lvp, radv, 
tu, v3dv, vn)
   VK_KHR_maintenance3                                   DONE (anv, lvp, radv, 
tu, v3dv, vn)
diff --git a/src/imagination/csbgen/rogue_texstate.xml 
b/src/imagination/csbgen/rogue_texstate.xml
index 860bcef28a1..79c91eb56f0 100644
--- a/src/imagination/csbgen/rogue_texstate.xml
+++ b/src/imagination/csbgen/rogue_texstate.xml
@@ -264,7 +264,9 @@ SOFTWARE.
   <struct name="IMAGE_WORD0" length="2">
     <field name="smpcnt" start="62" end="63" type="uint"/>
     <field name="height" start="48" end="61" type="uint"/>
-    <field name="width" start="34" end="47" type="uint"/>
+    <field name="width" start="34" end="47" type="uint">
+      <define name="MAX_SIZE" value="16383"/>
+    </field>
     <field name="texformat" start="27" end="33" type="FORMAT"/>
     <field name="texformat_compressed" start="27" end="33" 
type="FORMAT_COMPRESSED"/>
     <field name="minlod" start="17" end="26" type="uint"/>
@@ -294,7 +296,9 @@ SOFTWARE.
     <condition type="endif" check="TPU_IMAGE_STATE_V2"/>
     <field name="texaddr" start="16" end="53" shift="2" type="address"/>
     <field name="mipmaps_present" start="15" end="15" type="bool"/>
-    <field name="depth" start="4" end="14" type="uint"/>
+    <field name="depth" start="4" end="14" type="uint">
+      <define name="MAX_SIZE" value="2047"/>
+    </field>
     <field name="num_mip_levels" start="0" end="3" type="uint"/>
   </struct>
 
diff --git a/src/imagination/include/hwdef/rogue_hw_defs.h 
b/src/imagination/include/hwdef/rogue_hw_defs.h
index e66f50537a0..3642e6adcb0 100644
--- a/src/imagination/include/hwdef/rogue_hw_defs.h
+++ b/src/imagination/include/hwdef/rogue_hw_defs.h
@@ -93,8 +93,6 @@
 /* Number of TEXSTATE_SAMPLER state words that need setting up. */
 #define ROGUE_NUM_TEXSTATE_SAMPLER_WORDS 2U
 
-#define ROGUE_MAX_RENDER_TARGETS 2048U
-
 /* 12 dwords reserved for shared register management. The first dword is the
  * number of shared register blocks to reload. Should be a multiple of 4 
dwords,
  * size in bytes.
diff --git a/src/imagination/vulkan/pvr_device.c 
b/src/imagination/vulkan/pvr_device.c
index 8368c20113b..56b96788f4c 100644
--- a/src/imagination/vulkan/pvr_device.c
+++ b/src/imagination/vulkan/pvr_device.c
@@ -870,9 +870,9 @@ void pvr_GetPhysicalDeviceProperties2(VkPhysicalDevice 
physicalDevice,
    VkPhysicalDeviceLimits limits = {
       .maxImageDimension1D = max_render_size,
       .maxImageDimension2D = max_render_size,
-      .maxImageDimension3D = 2U * 1024U,
+      .maxImageDimension3D = PVR_MAX_TEXTURE_EXTENT_Z,
       .maxImageDimensionCube = max_render_size,
-      .maxImageArrayLayers = 2U * 1024U,
+      .maxImageArrayLayers = PVR_MAX_ARRAY_LAYERS,
       .maxTexelBufferElements = 64U * 1024U,
       .maxUniformBufferRange = 128U * 1024U * 1024U,
       .maxStorageBufferRange = 128U * 1024U * 1024U,
diff --git a/src/imagination/vulkan/pvr_formats.c 
b/src/imagination/vulkan/pvr_formats.c
index 9de590b51e6..8e32e54c6ca 100644
--- a/src/imagination/vulkan/pvr_formats.c
+++ b/src/imagination/vulkan/pvr_formats.c
@@ -21,44 +21,56 @@
  * SOFTWARE.
  */
 
+#include <assert.h>
 #include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <vulkan/vulkan.h>
 
+#include "hwdef/rogue_hw_utils.h"
 #include "pvr_formats.h"
 #include "pvr_private.h"
+#include "util/log.h"
+#include "util/macros.h"
+#include "util/u_math.h"
 #include "vk_enum_to_str.h"
 #include "vk_format.h"
 #include "vk_log.h"
 #include "vk_util.h"
 
-#define FORMAT(vk, tex_fmt, pack_mode)                     \
-   [VK_FORMAT_##vk] = {                                    \
-      .vk_format = VK_FORMAT_##vk,                         \
-      .tex_format = ROGUE_TEXSTATE_FORMAT_##tex_fmt,       \
-      .pbe_packmode = ROGUE_PBESTATE_PACKMODE_##pack_mode, \
-      .supported = true,                                   \
+#define FORMAT(vk, tex_fmt, pack_mode, accum_format)           \
+   [VK_FORMAT_##vk] = {                                        \
+      .vk_format = VK_FORMAT_##vk,                             \
+      .tex_format = ROGUE_TEXSTATE_FORMAT_##tex_fmt,           \
+      .pbe_packmode = ROGUE_PBESTATE_PACKMODE_##pack_mode,     \
+      .pbe_accum_format = PVR_PBE_ACCUM_FORMAT_##accum_format, \
+      .supported = true,                                       \
    }
 
 struct pvr_format {
    VkFormat vk_format;
    uint32_t tex_format;
    uint32_t pbe_packmode;
+   enum pvr_pbe_accum_format pbe_accum_format;
    bool supported;
 };
 
-/* TODO: add all supported core formats */
+/* TODO: Add all supported core formats. */
 static const struct pvr_format pvr_format_table[] = {
    /* VK_FORMAT_R8_UINT = 13. */
-   FORMAT(R8_UINT, U8, U8),
+   FORMAT(R8_UINT, U8, U8, UINT8),
+   /* VK_FORMAT_R8G8B8A8_UNORM = 37. */
+   FORMAT(R8G8B8A8_UNORM, U8U8U8U8, U8U8U8U8, U8),
    /* VK_FORMAT_B8G8R8A8_UNORM = 44. */
-   FORMAT(B8G8R8A8_UNORM, U8U8U8U8, U8U8U8U8),
+   FORMAT(B8G8R8A8_UNORM, U8U8U8U8, U8U8U8U8, U8),
    /* VK_FORMAT_R32_UINT = 98. */
-   FORMAT(R32_UINT, U32, U32),
+   FORMAT(R32_UINT, U32, U32, UINT32),
    /* VK_FORMAT_R32G32B32A32_UINT = 107. */
-   FORMAT(R32G32B32A32_UINT, U32U32U32U32, U32U32U32U32),
+   FORMAT(R32G32B32A32_UINT, U32U32U32U32, U32U32U32U32, UINT32),
    /* VK_FORMAT_R32G32B32A32_SFLOAT = 109. */
-   FORMAT(R32G32B32A32_SFLOAT, F32F32F32F32, F32F32F32F32),
+   FORMAT(R32G32B32A32_SFLOAT, F32F32F32F32, F32F32F32F32, F32),
    /* VK_FORMAT_D32_SFLOAT = 126. */
-   FORMAT(D32_SFLOAT, F32, F32),
+   FORMAT(D32_SFLOAT, F32, F32, F16),
 };
 
 #undef FORMAT
@@ -96,6 +108,15 @@ uint32_t pvr_get_pbe_packmode(VkFormat vk_format)
    return ROGUE_PBESTATE_PACKMODE_INVALID;
 }
 
+uint32_t pvr_get_pbe_accum_format(VkFormat vk_format)
+{
+   const struct pvr_format *pvr_format = pvr_get_format(vk_format);
+   if (pvr_format)
+      return pvr_format->pbe_accum_format;
+
+   return PVR_PBE_ACCUM_FORMAT_INVALID;
+}
+
 static VkFormatFeatureFlags
 pvr_get_image_format_features(const struct pvr_format *pvr_format,
                               VkImageTiling vk_tiling)
@@ -159,8 +180,162 @@ pvr_get_image_format_properties(struct 
pvr_physical_device *pdevice,
                                 const VkPhysicalDeviceImageFormatInfo2 *info,
                                 VkImageFormatProperties 
*pImageFormatProperties)
 {
-   assert(!"Unimplemented");
+   /* Input attachments aren't rendered but they must have the same size
+    * restrictions as any framebuffer attachment.
+    */
+   const VkImageUsageFlags render_usage =
+      VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
+      VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
+      VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
+      VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+   const struct pvr_format *pvr_format = pvr_get_format(info->format);
+   VkFormatFeatureFlags tiling_features;
+   VkResult result;
+
+   if (!pvr_format) {
+      result = vk_error(pdevice, VK_ERROR_FORMAT_NOT_SUPPORTED);
+      goto err_unsupported_format;
+   }
+
+   tiling_features = pvr_get_image_format_features(pvr_format, info->tiling);
+   if (tiling_features == 0) {
+      result = vk_error(pdevice, VK_ERROR_FORMAT_NOT_SUPPORTED);
+      goto err_unsupported_format;
+   }
+
+   /* If VK_IMAGE_CREATE_EXTENDED_USAGE_BIT is set, the driver can't decide if 
a
+    * specific format isn't supported based on the usage.
+    */
+   if ((info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT) == 0 &&
+       info->usage & (VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
+                      VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) &&
+       pvr_format->pbe_accum_format == PVR_PBE_ACCUM_FORMAT_INVALID) {
+      result = vk_error(pdevice, VK_ERROR_FORMAT_NOT_SUPPORTED);
+      goto err_unsupported_format;
+   }
+
+   if (info->type == VK_IMAGE_TYPE_3D) {
+      const VkImageUsageFlags transfer_usage =
+         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
+         VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
+
+      /* We don't support 3D depth/stencil images. */
+      if (tiling_features & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+         result = vk_error(pdevice, VK_ERROR_FORMAT_NOT_SUPPORTED);
+         goto err_unsupported_format;
+      }
+
+      /* Linear tiled 3D images may only be used for transfer or blit
+       * operations.
+       */
+      if (info->tiling == VK_IMAGE_TILING_LINEAR &&
+          info->usage & ~transfer_usage) {
+         result = vk_error(pdevice, VK_ERROR_FORMAT_NOT_SUPPORTED);
+         goto err_unsupported_format;
+      }
+   }
+
+   if (info->usage & render_usage) {
+      const uint32_t max_render_size =
+         rogue_get_render_size_max(&pdevice->dev_info);
+
+      pImageFormatProperties->maxExtent.width = max_render_size;
+      pImageFormatProperties->maxExtent.height = max_render_size;
+      pImageFormatProperties->maxExtent.depth = PVR_MAX_TEXTURE_EXTENT_Z;
+   } else {
+      const uint32_t max_texture_extent_xy =
+         PVRX(TEXSTATE_IMAGE_WORD0_WIDTH_MAX_SIZE) + 1U;
+
+      pImageFormatProperties->maxExtent.width = max_texture_extent_xy;
+      pImageFormatProperties->maxExtent.height = max_texture_extent_xy;
+      pImageFormatProperties->maxExtent.depth = PVR_MAX_TEXTURE_EXTENT_Z;
+   }
+
+   if (info->tiling == VK_IMAGE_TILING_LINEAR) {
+      pImageFormatProperties->maxExtent.depth = 1;
+      pImageFormatProperties->maxArrayLayers = 1;
+      pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
+   } else {
+      /* Default value is the minimum value found in all existing cores. */
+      const uint32_t max_multisample =
+         PVR_GET_FEATURE_VALUE(&pdevice->dev_info, max_multisample, 4);
+
+      const uint32_t max_sample_bits = ((max_multisample << 1) - 1);
+
+      pImageFormatProperties->maxArrayLayers = PVR_MAX_ARRAY_LAYERS;
+      pImageFormatProperties->sampleCounts = max_sample_bits;
+   }
+
+   if (!(tiling_features & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
+         tiling_features & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
+      pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
+   }
+
+   switch (info->type) {
+   case VK_IMAGE_TYPE_1D:
+      pImageFormatProperties->maxExtent.height = 1;
+      pImageFormatProperties->maxExtent.depth = 1;
+      pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
+      break;
+
+   case VK_IMAGE_TYPE_2D:
+      pImageFormatProperties->maxExtent.depth = 1;
+
+      /* If a 2D image is created to be used in a cube map, then the sample
+       * count must be restricted to 1 sample.
+       */
+      if (info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
+         pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
+
+      break;
+
+   case VK_IMAGE_TYPE_3D:
+      pImageFormatProperties->maxArrayLayers = 1;
+      pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
+      break;
+
+   default:
+      unreachable("Invalid image type.");
+   }
+
+   /* The spec says maxMipLevels may be 1 when tiling is VK_IMAGE_TILING_LINEAR
+    * or VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, so for simplicity don't
+    * support miplevels for these tilings.
+    */
+   if (info->tiling == VK_IMAGE_TILING_LINEAR) {
+      pImageFormatProperties->maxMipLevels = 1;
+   } else {
+      const uint32_t max_size = MAX3(pImageFormatProperties->maxExtent.width,
+                                     pImageFormatProperties->maxExtent.height,
+                                     pImageFormatProperties->maxExtent.depth);
+
+      pImageFormatProperties->maxMipLevels = util_logbase2(max_size) + 1U;
+   }
+
+   /* Return 2GB (minimum required from spec).
+    *
+    * From the Vulkan spec:
+    *
+    *    maxResourceSize is an upper bound on the total image size in bytes,
+    *    inclusive of all image subresources. Implementations may have an
+    *    address space limit on total size of a resource, which is advertised 
by
+    *    this property. maxResourceSize must be at least 2^31.
+    */
+   pImageFormatProperties->maxResourceSize = 2ULL * 1024 * 1024 * 1024;
+
    return VK_SUCCESS;
+
+err_unsupported_format:
+   /* From the Vulkan 1.0.42 spec:
+    *
+    *    If the combination of parameters to
+    *    vkGetPhysicalDeviceImageFormatProperties2 is not supported by the
+    *    implementation for use in vkCreateImage, then all members of
+    *    imageFormatProperties will be filled with zero.
+    */
+   *pImageFormatProperties = (VkImageFormatProperties){ 0 };
+
+   return result;
 }
 
 /* FIXME: Should this be returning VK_ERROR_FORMAT_NOT_SUPPORTED when tiling is
diff --git a/src/imagination/vulkan/pvr_formats.h 
b/src/imagination/vulkan/pvr_formats.h
index c038be7744b..f2c1ed127f9 100644
--- a/src/imagination/vulkan/pvr_formats.h
+++ b/src/imagination/vulkan/pvr_formats.h
@@ -28,9 +28,31 @@
 #include <stdint.h>
 #include <vulkan/vulkan.h>
 
+enum pvr_pbe_accum_format {
+   PVR_PBE_ACCUM_FORMAT_INVALID = 0, /* Explicitly treat 0 as invalid. */
+   PVR_PBE_ACCUM_FORMAT_U8,
+   PVR_PBE_ACCUM_FORMAT_S8,
+   PVR_PBE_ACCUM_FORMAT_U16,
+   PVR_PBE_ACCUM_FORMAT_S16,
+   PVR_PBE_ACCUM_FORMAT_F16,
+   PVR_PBE_ACCUM_FORMAT_F32,
+   PVR_PBE_ACCUM_FORMAT_UINT8,
+   PVR_PBE_ACCUM_FORMAT_UINT16,
+   PVR_PBE_ACCUM_FORMAT_UINT32,
+   PVR_PBE_ACCUM_FORMAT_SINT8,
+   PVR_PBE_ACCUM_FORMAT_SINT16,
+   PVR_PBE_ACCUM_FORMAT_SINT32,
+   /* Formats with medp shader output precision. */
+   PVR_PBE_ACCUM_FORMAT_UINT32_MEDP,
+   PVR_PBE_ACCUM_FORMAT_SINT32_MEDP,
+   PVR_PBE_ACCUM_FORMAT_U1010102,
+   PVR_PBE_ACCUM_FORMAT_U24,
+};
+
 const uint8_t *pvr_get_format_swizzle(VkFormat vk_format);
 uint32_t pvr_get_tex_format(VkFormat vk_format);
 uint32_t pvr_get_pbe_packmode(VkFormat vk_format);
+uint32_t pvr_get_pbe_accum_format(VkFormat vk_format);
 bool pvr_format_is_pbe_downscalable(VkFormat vk_format);
 
 #endif /* PVR_FORMATS_H */
diff --git a/src/imagination/vulkan/pvr_limits.h 
b/src/imagination/vulkan/pvr_limits.h
index 4a24701c11b..ec1fde15b8f 100644
--- a/src/imagination/vulkan/pvr_limits.h
+++ b/src/imagination/vulkan/pvr_limits.h
@@ -39,8 +39,14 @@
 
 #define PVR_MAX_PUSH_CONSTANTS_SIZE 256U
 
+#define PVR_MAX_TEXTURE_EXTENT_Z \
+   (PVRX(TEXSTATE_IMAGE_WORD1_DEPTH_MAX_SIZE) + 1U)
+
+#define PVR_MAX_ARRAY_LAYERS (PVRX(TEXSTATE_IMAGE_WORD1_DEPTH_MAX_SIZE) + 1U)
+
 #define PVR_MAX_DESCRIPTOR_SETS 4U
-#define PVR_MAX_FRAMEBUFFER_LAYERS ROGUE_MAX_RENDER_TARGETS
+
+#define PVR_MAX_FRAMEBUFFER_LAYERS PVR_MAX_ARRAY_LAYERS
 
 /* The limit is somewhat arbitrary, it just translates into more pds code
  * and larger arrays, 32 appears to be the popular (and highest choice) across

Reply via email to