• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2022 Imagination Technologies Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 
24 #include <stdbool.h>
25 
26 #include "pvr_formats.h"
27 #include "pvr_private.h"
28 #include "vk_enum_to_str.h"
29 #include "vk_format.h"
30 #include "vk_log.h"
31 #include "vk_util.h"
32 
33 #define FORMAT(vk, tex_fmt, pack_mode)                     \
34    [VK_FORMAT_##vk] = {                                    \
35       .vk_format = VK_FORMAT_##vk,                         \
36       .tex_format = ROGUE_TEXSTATE_FORMAT_##tex_fmt,       \
37       .pbe_packmode = ROGUE_PBESTATE_PACKMODE_##pack_mode, \
38       .supported = true,                                   \
39    }
40 
41 struct pvr_format {
42    VkFormat vk_format;
43    uint32_t tex_format;
44    uint32_t pbe_packmode;
45    bool supported;
46 };
47 
48 /* TODO: add all supported core formats */
49 static const struct pvr_format pvr_format_table[] = {
50    /* VK_FORMAT_R8_UINT = 13. */
51    FORMAT(R8_UINT, U8, U8),
52    /* VK_FORMAT_B8G8R8A8_UNORM = 44. */
53    FORMAT(B8G8R8A8_UNORM, U8U8U8U8, U8U8U8U8),
54    /* VK_FORMAT_R32_UINT = 98. */
55    FORMAT(R32_UINT, U32, U32),
56    /* VK_FORMAT_R32G32B32A32_UINT = 107. */
57    FORMAT(R32G32B32A32_UINT, U32U32U32U32, U32U32U32U32),
58    /* VK_FORMAT_R32G32B32A32_SFLOAT = 109. */
59    FORMAT(R32G32B32A32_SFLOAT, F32F32F32F32, F32F32F32F32),
60    /* VK_FORMAT_D32_SFLOAT = 126. */
61    FORMAT(D32_SFLOAT, F32, F32),
62 };
63 
64 #undef FORMAT
65 
pvr_get_format(VkFormat vk_format)66 static inline const struct pvr_format *pvr_get_format(VkFormat vk_format)
67 {
68    if (vk_format < ARRAY_SIZE(pvr_format_table) &&
69        pvr_format_table[vk_format].supported) {
70       return &pvr_format_table[vk_format];
71    }
72 
73    mesa_logd("Format %s(%d) not supported\n",
74              vk_Format_to_str(vk_format),
75              vk_format);
76 
77    return NULL;
78 }
79 
pvr_get_tex_format(VkFormat vk_format)80 uint32_t pvr_get_tex_format(VkFormat vk_format)
81 {
82    const struct pvr_format *pvr_format = pvr_get_format(vk_format);
83    if (pvr_format) {
84       return pvr_format->tex_format;
85    }
86 
87    return ROGUE_TEXSTATE_FORMAT_INVALID;
88 }
89 
pvr_get_pbe_packmode(VkFormat vk_format)90 uint32_t pvr_get_pbe_packmode(VkFormat vk_format)
91 {
92    const struct pvr_format *pvr_format = pvr_get_format(vk_format);
93    if (pvr_format)
94       return pvr_format->pbe_packmode;
95 
96    return ROGUE_PBESTATE_PACKMODE_INVALID;
97 }
98 
99 static VkFormatFeatureFlags
pvr_get_image_format_features(const struct pvr_format * pvr_format,VkImageTiling vk_tiling)100 pvr_get_image_format_features(const struct pvr_format *pvr_format,
101                               VkImageTiling vk_tiling)
102 {
103    VkFormatFeatureFlags flags = 0;
104    VkImageAspectFlags aspects;
105 
106    if (!pvr_format)
107       return 0;
108 
109    aspects = vk_format_aspects(pvr_format->vk_format);
110    if (aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
111       flags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT |
112                VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
113                VK_FORMAT_FEATURE_BLIT_SRC_BIT;
114    }
115 
116    return flags;
117 }
118 
pvr_get_format_swizzle(VkFormat vk_format)119 const uint8_t *pvr_get_format_swizzle(VkFormat vk_format)
120 {
121    const struct util_format_description *vf = vk_format_description(vk_format);
122 
123    return vf->swizzle;
124 }
125 
126 static VkFormatFeatureFlags
pvr_get_buffer_format_features(const struct pvr_format * pvr_format)127 pvr_get_buffer_format_features(const struct pvr_format *pvr_format)
128 {
129    VkFormatFeatureFlags flags = 0;
130 
131    if (!pvr_format)
132       return 0;
133 
134    return flags;
135 }
136 
pvr_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties2 * pFormatProperties)137 void pvr_GetPhysicalDeviceFormatProperties2(
138    VkPhysicalDevice physicalDevice,
139    VkFormat format,
140    VkFormatProperties2 *pFormatProperties)
141 {
142    const struct pvr_format *pvr_format = pvr_get_format(format);
143 
144    pFormatProperties->formatProperties = (VkFormatProperties){
145       .linearTilingFeatures =
146          pvr_get_image_format_features(pvr_format, VK_IMAGE_TILING_LINEAR),
147       .optimalTilingFeatures =
148          pvr_get_image_format_features(pvr_format, VK_IMAGE_TILING_OPTIMAL),
149       .bufferFeatures = pvr_get_buffer_format_features(pvr_format),
150    };
151 
152    vk_foreach_struct (ext, pFormatProperties->pNext) {
153       pvr_debug_ignored_stype(ext->sType);
154    }
155 }
156 
157 static VkResult
pvr_get_image_format_properties(struct pvr_physical_device * pdevice,const VkPhysicalDeviceImageFormatInfo2 * info,VkImageFormatProperties * pImageFormatProperties)158 pvr_get_image_format_properties(struct pvr_physical_device *pdevice,
159                                 const VkPhysicalDeviceImageFormatInfo2 *info,
160                                 VkImageFormatProperties *pImageFormatProperties)
161 {
162    assert(!"Unimplemented");
163    return VK_SUCCESS;
164 }
165 
pvr_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * pImageFormatInfo,VkImageFormatProperties2 * pImageFormatProperties)166 VkResult pvr_GetPhysicalDeviceImageFormatProperties2(
167    VkPhysicalDevice physicalDevice,
168    const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
169    VkImageFormatProperties2 *pImageFormatProperties)
170 {
171    const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
172    PVR_FROM_HANDLE(pvr_physical_device, pdevice, physicalDevice);
173    VkExternalImageFormatProperties *external_props = NULL;
174    VkResult result;
175 
176    result = pvr_get_image_format_properties(
177       pdevice,
178       pImageFormatInfo,
179       &pImageFormatProperties->imageFormatProperties);
180    if (result != VK_SUCCESS)
181       return result;
182 
183    /* Extract input structs */
184    vk_foreach_struct_const (ext, pImageFormatInfo->pNext) {
185       switch (ext->sType) {
186       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
187          external_info = (const void *)ext;
188          break;
189       default:
190          pvr_debug_ignored_stype(ext->sType);
191          break;
192       }
193    }
194 
195    /* Extract output structs */
196    vk_foreach_struct (ext, pImageFormatProperties->pNext) {
197       switch (ext->sType) {
198       case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
199          external_props = (void *)ext;
200          break;
201       default:
202          pvr_debug_ignored_stype(ext->sType);
203          break;
204       }
205    }
206 
207    /* From the Vulkan 1.0.42 spec:
208     *
209     *    If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will
210     *    behave as if VkPhysicalDeviceExternalImageFormatInfo was not
211     *    present and VkExternalImageFormatProperties will be ignored.
212     */
213    if (external_info && external_info->handleType != 0) {
214       switch (external_info->handleType) {
215       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
216       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
217          if (!external_props)
218             break;
219 
220          external_props->externalMemoryProperties.externalMemoryFeatures =
221             VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
222             VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
223          external_props->externalMemoryProperties.compatibleHandleTypes =
224             VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
225             VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
226          external_props->externalMemoryProperties.exportFromImportedHandleTypes =
227             VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
228             VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
229          break;
230       default:
231          return vk_error(pdevice, VK_ERROR_FORMAT_NOT_SUPPORTED);
232       }
233    }
234 
235    return VK_SUCCESS;
236 }
237 
pvr_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,uint32_t samples,VkImageUsageFlags usage,VkImageTiling tiling,uint32_t * pNumProperties,VkSparseImageFormatProperties * pProperties)238 void pvr_GetPhysicalDeviceSparseImageFormatProperties(
239    VkPhysicalDevice physicalDevice,
240    VkFormat format,
241    VkImageType type,
242    uint32_t samples,
243    VkImageUsageFlags usage,
244    VkImageTiling tiling,
245    uint32_t *pNumProperties,
246    VkSparseImageFormatProperties *pProperties)
247 {
248    /* Sparse images are not yet supported. */
249    *pNumProperties = 0;
250 }
251 
pvr_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)252 void pvr_GetPhysicalDeviceSparseImageFormatProperties2(
253    VkPhysicalDevice physicalDevice,
254    const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
255    uint32_t *pPropertyCount,
256    VkSparseImageFormatProperties2 *pProperties)
257 {
258    /* Sparse images are not yet supported. */
259    *pPropertyCount = 0;
260 }
261 
pvr_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalBufferInfo * pExternalBufferInfo,VkExternalBufferProperties * pExternalBufferProperties)262 void pvr_GetPhysicalDeviceExternalBufferProperties(
263    VkPhysicalDevice physicalDevice,
264    const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
265    VkExternalBufferProperties *pExternalBufferProperties)
266 {
267    /* The Vulkan 1.0.42 spec says "handleType must be a valid
268     * VkExternalMemoryHandleTypeFlagBits value" in
269     * VkPhysicalDeviceExternalBufferInfo. This differs from
270     * VkPhysicalDeviceExternalImageFormatInfo, which surprisingly permits
271     * handleType == 0.
272     */
273    assert(pExternalBufferInfo->handleType != 0);
274 
275    /* All of the current flags are for sparse which we don't support. */
276    if (pExternalBufferInfo->flags)
277       goto unsupported;
278 
279    switch (pExternalBufferInfo->handleType) {
280    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
281    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
282       /* clang-format off */
283       pExternalBufferProperties->externalMemoryProperties.externalMemoryFeatures =
284          VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
285          VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
286       pExternalBufferProperties->externalMemoryProperties.exportFromImportedHandleTypes =
287          VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
288          VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
289       pExternalBufferProperties->externalMemoryProperties.compatibleHandleTypes =
290          VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
291          VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
292       /* clang-format on */
293       return;
294    default:
295       break;
296    }
297 
298 unsupported:
299    /* From the Vulkan 1.1.113 spec:
300     *
301     *    compatibleHandleTypes must include at least handleType.
302     */
303    pExternalBufferProperties->externalMemoryProperties =
304       (VkExternalMemoryProperties){
305          .compatibleHandleTypes = pExternalBufferInfo->handleType,
306       };
307 }
308 
pvr_format_is_pbe_downscalable(VkFormat vk_format)309 bool pvr_format_is_pbe_downscalable(VkFormat vk_format)
310 {
311    if (vk_format_is_int(vk_format)) {
312       /* PBE downscale behavior for integer formats does not match Vulkan
313        * spec. Vulkan requires a single sample to be chosen instead of
314        * taking the average sample color.
315        */
316       return false;
317    }
318 
319    switch (pvr_get_pbe_packmode(vk_format)) {
320    default:
321       return true;
322 
323    case ROGUE_PBESTATE_PACKMODE_U16U16U16U16:
324    case ROGUE_PBESTATE_PACKMODE_S16S16S16S16:
325    case ROGUE_PBESTATE_PACKMODE_U32U32U32U32:
326    case ROGUE_PBESTATE_PACKMODE_S32S32S32S32:
327    case ROGUE_PBESTATE_PACKMODE_F32F32F32F32:
328    case ROGUE_PBESTATE_PACKMODE_U16U16U16:
329    case ROGUE_PBESTATE_PACKMODE_S16S16S16:
330    case ROGUE_PBESTATE_PACKMODE_U32U32U32:
331    case ROGUE_PBESTATE_PACKMODE_S32S32S32:
332    case ROGUE_PBESTATE_PACKMODE_F32F32F32:
333    case ROGUE_PBESTATE_PACKMODE_U16U16:
334    case ROGUE_PBESTATE_PACKMODE_S16S16:
335    case ROGUE_PBESTATE_PACKMODE_U32U32:
336    case ROGUE_PBESTATE_PACKMODE_S32S32:
337    case ROGUE_PBESTATE_PACKMODE_F32F32:
338    case ROGUE_PBESTATE_PACKMODE_U24ST8:
339    case ROGUE_PBESTATE_PACKMODE_ST8U24:
340    case ROGUE_PBESTATE_PACKMODE_U16:
341    case ROGUE_PBESTATE_PACKMODE_S16:
342    case ROGUE_PBESTATE_PACKMODE_U32:
343    case ROGUE_PBESTATE_PACKMODE_S32:
344    case ROGUE_PBESTATE_PACKMODE_F32:
345    case ROGUE_PBESTATE_PACKMODE_X24U8F32:
346    case ROGUE_PBESTATE_PACKMODE_X24X8F32:
347    case ROGUE_PBESTATE_PACKMODE_X24G8X32:
348    case ROGUE_PBESTATE_PACKMODE_X8U24:
349    case ROGUE_PBESTATE_PACKMODE_U8X24:
350    case ROGUE_PBESTATE_PACKMODE_PBYTE:
351    case ROGUE_PBESTATE_PACKMODE_PWORD:
352    case ROGUE_PBESTATE_PACKMODE_INVALID:
353       return false;
354    }
355 }
356