~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/freedreno/vulkan/tu_image.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright © 2016 Red Hat.
3
 
 * Copyright © 2016 Bas Nieuwenhuizen
4
 
 *
5
 
 * based in part on anv driver which is:
6
 
 * Copyright © 2015 Intel Corporation
7
 
 *
8
 
 * Permission is hereby granted, free of charge, to any person obtaining a
9
 
 * copy of this software and associated documentation files (the "Software"),
10
 
 * to deal in the Software without restriction, including without limitation
11
 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
 
 * and/or sell copies of the Software, and to permit persons to whom the
13
 
 * Software is furnished to do so, subject to the following conditions:
14
 
 *
15
 
 * The above copyright notice and this permission notice (including the next
16
 
 * paragraph) shall be included in all copies or substantial portions of the
17
 
 * Software.
18
 
 *
19
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22
 
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
 
 * DEALINGS IN THE SOFTWARE.
26
 
 */
27
 
 
28
 
#include "tu_private.h"
29
 
#include "fdl/fd6_format_table.h"
30
 
 
31
 
#include "util/debug.h"
32
 
#include "util/u_atomic.h"
33
 
#include "util/format/u_format.h"
34
 
#include "vk_format.h"
35
 
#include "vk_util.h"
36
 
#include "drm-uapi/drm_fourcc.h"
37
 
 
38
 
#include "tu_cs.h"
39
 
 
40
 
static uint32_t
41
 
tu6_plane_count(VkFormat format)
42
 
{
43
 
   switch (format) {
44
 
   default:
45
 
      return 1;
46
 
   case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
47
 
   case VK_FORMAT_D32_SFLOAT_S8_UINT:
48
 
      return 2;
49
 
   case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
50
 
      return 3;
51
 
   }
52
 
}
53
 
 
54
 
enum pipe_format
55
 
tu6_plane_format(VkFormat format, uint32_t plane)
56
 
{
57
 
   switch (format) {
58
 
   case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
59
 
      return plane ? PIPE_FORMAT_R8G8_UNORM : PIPE_FORMAT_Y8_UNORM;
60
 
   case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
61
 
      return PIPE_FORMAT_R8_UNORM;
62
 
   case VK_FORMAT_D32_SFLOAT_S8_UINT:
63
 
      return plane ? PIPE_FORMAT_S8_UINT : PIPE_FORMAT_Z32_FLOAT;
64
 
   default:
65
 
      return tu_vk_format_to_pipe_format(format);
66
 
   }
67
 
}
68
 
 
69
 
uint32_t
70
 
tu6_plane_index(VkFormat format, VkImageAspectFlags aspect_mask)
71
 
{
72
 
   switch (aspect_mask) {
73
 
   default:
74
 
      return 0;
75
 
   case VK_IMAGE_ASPECT_PLANE_1_BIT:
76
 
      return 1;
77
 
   case VK_IMAGE_ASPECT_PLANE_2_BIT:
78
 
      return 2;
79
 
   case VK_IMAGE_ASPECT_STENCIL_BIT:
80
 
      return format == VK_FORMAT_D32_SFLOAT_S8_UINT;
81
 
   }
82
 
}
83
 
 
84
 
enum pipe_format
85
 
tu_format_for_aspect(enum pipe_format format, VkImageAspectFlags aspect_mask)
86
 
{
87
 
   switch (format) {
88
 
   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
89
 
      if (aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT)
90
 
         return PIPE_FORMAT_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
91
 
      if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
92
 
         if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT)
93
 
            return PIPE_FORMAT_Z24_UNORM_S8_UINT;
94
 
         else
95
 
            return PIPE_FORMAT_X24S8_UINT;
96
 
      } else {
97
 
         return PIPE_FORMAT_Z24X8_UNORM;
98
 
      }
99
 
   case PIPE_FORMAT_Z24X8_UNORM:
100
 
      if (aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT)
101
 
         return PIPE_FORMAT_Z24_UNORM_S8_UINT_AS_R8G8B8A8;
102
 
      return PIPE_FORMAT_Z24X8_UNORM;
103
 
   default:
104
 
      return format;
105
 
   }
106
 
}
107
 
 
108
 
static bool
109
 
tu_is_r8g8(enum pipe_format format)
110
 
{
111
 
   return (util_format_get_blocksize(format) == 2) &&
112
 
          (util_format_get_nr_components(format) == 2);
113
 
}
114
 
 
115
 
static bool
116
 
tu_is_r8g8_compatible(enum pipe_format format)
117
 
{
118
 
   return (util_format_get_blocksize(format) == 2) &&
119
 
          !util_format_is_depth_or_stencil(format);
120
 
}
121
 
 
122
 
void
123
 
tu_cs_image_ref(struct tu_cs *cs, const struct fdl6_view *iview, uint32_t layer)
124
 
{
125
 
   tu_cs_emit(cs, iview->PITCH);
126
 
   tu_cs_emit(cs, iview->layer_size >> 6);
127
 
   tu_cs_emit_qw(cs, iview->base_addr + iview->layer_size * layer);
128
 
}
129
 
 
130
 
void
131
 
tu_cs_image_stencil_ref(struct tu_cs *cs, const struct tu_image_view *iview, uint32_t layer)
132
 
{
133
 
   tu_cs_emit(cs, iview->stencil_PITCH);
134
 
   tu_cs_emit(cs, iview->stencil_layer_size >> 6);
135
 
   tu_cs_emit_qw(cs, iview->stencil_base_addr + iview->stencil_layer_size * layer);
136
 
}
137
 
 
138
 
void
139
 
tu_cs_image_depth_ref(struct tu_cs *cs, const struct tu_image_view *iview, uint32_t layer)
140
 
{
141
 
   tu_cs_emit(cs, iview->depth_PITCH);
142
 
   tu_cs_emit(cs, iview->depth_layer_size >> 6);
143
 
   tu_cs_emit_qw(cs, iview->depth_base_addr + iview->depth_layer_size * layer);
144
 
}
145
 
 
146
 
void
147
 
tu_cs_image_ref_2d(struct tu_cs *cs, const struct fdl6_view *iview, uint32_t layer, bool src)
148
 
{
149
 
   tu_cs_emit_qw(cs, iview->base_addr + iview->layer_size * layer);
150
 
   /* SP_PS_2D_SRC_PITCH has shifted pitch field */
151
 
   tu_cs_emit(cs, iview->PITCH << (src ? 9 : 0));
152
 
}
153
 
 
154
 
void
155
 
tu_cs_image_flag_ref(struct tu_cs *cs, const struct fdl6_view *iview, uint32_t layer)
156
 
{
157
 
   tu_cs_emit_qw(cs, iview->ubwc_addr + iview->ubwc_layer_size * layer);
158
 
   tu_cs_emit(cs, iview->FLAG_BUFFER_PITCH);
159
 
}
160
 
 
161
 
void
162
 
tu_image_view_init(struct tu_image_view *iview,
163
 
                   const VkImageViewCreateInfo *pCreateInfo,
164
 
                   bool has_z24uint_s8uint)
165
 
{
166
 
   TU_FROM_HANDLE(tu_image, image, pCreateInfo->image);
167
 
   const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
168
 
   VkFormat vk_format = pCreateInfo->format;
169
 
   VkImageAspectFlagBits aspect_mask = pCreateInfo->subresourceRange.aspectMask;
170
 
 
171
 
   const struct VkSamplerYcbcrConversionInfo *ycbcr_conversion =
172
 
      vk_find_struct_const(pCreateInfo->pNext, SAMPLER_YCBCR_CONVERSION_INFO);
173
 
   const struct tu_sampler_ycbcr_conversion *conversion = ycbcr_conversion ?
174
 
      tu_sampler_ycbcr_conversion_from_handle(ycbcr_conversion->conversion) : NULL;
175
 
 
176
 
   iview->image = image;
177
 
 
178
 
   const struct fdl_layout *layouts[3];
179
 
 
180
 
   layouts[0] = &image->layout[tu6_plane_index(image->vk_format, aspect_mask)];
181
 
 
182
 
   enum pipe_format format;
183
 
   if (aspect_mask != VK_IMAGE_ASPECT_COLOR_BIT)
184
 
      format = tu6_plane_format(vk_format, tu6_plane_index(vk_format, aspect_mask));
185
 
   else
186
 
      format = tu_vk_format_to_pipe_format(vk_format);
187
 
 
188
 
   if (image->vk_format == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM &&
189
 
       aspect_mask == VK_IMAGE_ASPECT_PLANE_0_BIT) {
190
 
      if (vk_format == VK_FORMAT_R8_UNORM) {
191
 
         /* The 0'th plane of this format has a different UBWC compression. */
192
 
         format = PIPE_FORMAT_Y8_UNORM;
193
 
      } else {
194
 
         /* If the user wants to reinterpret this plane, then they should've
195
 
          * set MUTABLE_FORMAT_BIT which should disable UBWC and tiling.
196
 
          */
197
 
         assert(!layouts[0]->ubwc);
198
 
      }
199
 
   }
200
 
 
201
 
   if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT &&
202
 
       (vk_format == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM ||
203
 
        vk_format == VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM)) {
204
 
      layouts[1] = &image->layout[1];
205
 
      layouts[2] = &image->layout[2];
206
 
   }
207
 
 
208
 
   struct fdl_view_args args = {};
209
 
   args.iova = image->iova;
210
 
   args.base_array_layer = range->baseArrayLayer;
211
 
   args.base_miplevel = range->baseMipLevel;
212
 
   args.layer_count = tu_get_layerCount(image, range);
213
 
   args.level_count = tu_get_levelCount(image, range);
214
 
   args.format = tu_format_for_aspect(format, aspect_mask);
215
 
   vk_component_mapping_to_pipe_swizzle(pCreateInfo->components, args.swiz);
216
 
   if (conversion) {
217
 
      unsigned char conversion_swiz[4], create_swiz[4];
218
 
      memcpy(create_swiz, args.swiz, sizeof(create_swiz));
219
 
      vk_component_mapping_to_pipe_swizzle(conversion->components,
220
 
                                           conversion_swiz);
221
 
      util_format_compose_swizzles(create_swiz, conversion_swiz, args.swiz);
222
 
   }
223
 
 
224
 
   switch (pCreateInfo->viewType) {
225
 
   case VK_IMAGE_VIEW_TYPE_1D:
226
 
   case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
227
 
      args.type = FDL_VIEW_TYPE_1D;
228
 
      break;
229
 
   case VK_IMAGE_VIEW_TYPE_2D:
230
 
   case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
231
 
      args.type = FDL_VIEW_TYPE_2D;
232
 
      break;
233
 
   case VK_IMAGE_VIEW_TYPE_CUBE:
234
 
   case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
235
 
      args.type = FDL_VIEW_TYPE_CUBE;
236
 
      break;
237
 
   case VK_IMAGE_VIEW_TYPE_3D:
238
 
      args.type = FDL_VIEW_TYPE_3D;
239
 
      break;
240
 
   default:
241
 
      unreachable("unknown view type");
242
 
   }
243
 
 
244
 
   STATIC_ASSERT((unsigned)VK_CHROMA_LOCATION_COSITED_EVEN == (unsigned)FDL_CHROMA_LOCATION_COSITED_EVEN);
245
 
   STATIC_ASSERT((unsigned)VK_CHROMA_LOCATION_MIDPOINT == (unsigned)FDL_CHROMA_LOCATION_MIDPOINT);
246
 
   if (conversion) {
247
 
      args.chroma_offsets[0] = (enum fdl_chroma_location) conversion->chroma_offsets[0];
248
 
      args.chroma_offsets[1] = (enum fdl_chroma_location) conversion->chroma_offsets[1];
249
 
   }
250
 
 
251
 
   fdl6_view_init(&iview->view, layouts, &args, has_z24uint_s8uint);
252
 
 
253
 
   if (image->vk_format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
254
 
      struct fdl_layout *layout = &image->layout[0];
255
 
      iview->depth_base_addr = image->iova +
256
 
         fdl_surface_offset(layout, range->baseMipLevel, range->baseArrayLayer);
257
 
      iview->depth_layer_size = fdl_layer_stride(layout, range->baseMipLevel);
258
 
      iview->depth_PITCH = A6XX_RB_DEPTH_BUFFER_PITCH(fdl_pitch(layout, range->baseMipLevel)).value;
259
 
 
260
 
      layout = &image->layout[1];
261
 
      iview->stencil_base_addr = image->iova +
262
 
         fdl_surface_offset(layout, range->baseMipLevel, range->baseArrayLayer);
263
 
      iview->stencil_layer_size = fdl_layer_stride(layout, range->baseMipLevel);
264
 
      iview->stencil_PITCH = A6XX_RB_STENCIL_BUFFER_PITCH(fdl_pitch(layout, range->baseMipLevel)).value;
265
 
   }
266
 
}
267
 
 
268
 
bool
269
 
tiling_possible(VkFormat format)
270
 
{
271
 
   if (format == VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM ||
272
 
       format == VK_FORMAT_G8B8G8R8_422_UNORM ||
273
 
       format == VK_FORMAT_B8G8R8G8_422_UNORM)
274
 
      return false;
275
 
 
276
 
   return true;
277
 
}
278
 
 
279
 
bool
280
 
ubwc_possible(VkFormat format, VkImageType type, VkImageUsageFlags usage,
281
 
              VkImageUsageFlags stencil_usage, const struct fd_dev_info *info,
282
 
              VkSampleCountFlagBits samples)
283
 
{
284
 
   /* no UBWC with compressed formats, E5B9G9R9, S8_UINT
285
 
    * (S8_UINT because separate stencil doesn't have UBWC-enable bit)
286
 
    */
287
 
   if (vk_format_is_compressed(format) ||
288
 
       format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 ||
289
 
       format == VK_FORMAT_S8_UINT)
290
 
      return false;
291
 
 
292
 
   if (!info->a6xx.has_8bpp_ubwc &&
293
 
       (format == VK_FORMAT_R8_UNORM ||
294
 
        format == VK_FORMAT_R8_SNORM ||
295
 
        format == VK_FORMAT_R8_UINT ||
296
 
        format == VK_FORMAT_R8_SINT ||
297
 
        format == VK_FORMAT_R8_SRGB))
298
 
      return false;
299
 
 
300
 
   if (type == VK_IMAGE_TYPE_3D) {
301
 
      tu_finishme("UBWC with 3D textures");
302
 
      return false;
303
 
   }
304
 
 
305
 
   /* Disable UBWC for storage images.
306
 
    *
307
 
    * The closed GL driver skips UBWC for storage images (and additionally
308
 
    * uses linear for writeonly images).  We seem to have image tiling working
309
 
    * in freedreno in general, so turnip matches that.  freedreno also enables
310
 
    * UBWC on images, but it's not really tested due to the lack of
311
 
    * UBWC-enabled mipmaps in freedreno currently.  Just match the closed GL
312
 
    * behavior of no UBWC.
313
 
   */
314
 
   if ((usage | stencil_usage) & VK_IMAGE_USAGE_STORAGE_BIT)
315
 
      return false;
316
 
 
317
 
   /* Disable UBWC for D24S8 on A630 in some cases
318
 
    *
319
 
    * VK_IMAGE_ASPECT_STENCIL_BIT image view requires to be able to sample
320
 
    * from the stencil component as UINT, however no format allows this
321
 
    * on a630 (the special FMT6_Z24_UINT_S8_UINT format is missing)
322
 
    *
323
 
    * It must be sampled as FMT6_8_8_8_8_UINT, which is not UBWC-compatible
324
 
    *
325
 
    * Additionally, the special AS_R8G8B8A8 format is broken without UBWC,
326
 
    * so we have to fallback to 8_8_8_8_UNORM when UBWC is disabled
327
 
    */
328
 
   if (!info->a6xx.has_z24uint_s8uint &&
329
 
       format == VK_FORMAT_D24_UNORM_S8_UINT &&
330
 
       (stencil_usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)))
331
 
      return false;
332
 
 
333
 
   if (!info->a6xx.has_z24uint_s8uint && samples > VK_SAMPLE_COUNT_1_BIT)
334
 
      return false;
335
 
 
336
 
   return true;
337
 
}
338
 
 
339
 
static VkResult
340
 
tu_image_init(struct tu_device *device, struct tu_image *image,
341
 
              const VkImageCreateInfo *pCreateInfo, uint64_t modifier,
342
 
              const VkSubresourceLayout *plane_layouts)
343
 
{
344
 
   const VkExternalMemoryImageCreateInfo *external_info =
345
 
      vk_find_struct_const(pCreateInfo->pNext, EXTERNAL_MEMORY_IMAGE_CREATE_INFO);
346
 
   image->shareable = external_info != NULL;
347
 
 
348
 
   image->vk_format = pCreateInfo->format;
349
 
   image->level_count = pCreateInfo->mipLevels;
350
 
   image->layer_count = pCreateInfo->arrayLayers;
351
 
 
352
 
   enum a6xx_tile_mode tile_mode = TILE6_3;
353
 
   bool ubwc_enabled =
354
 
      !(device->physical_device->instance->debug_flags & TU_DEBUG_NOUBWC);
355
 
 
356
 
   /* use linear tiling if requested */
357
 
   if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR || modifier == DRM_FORMAT_MOD_LINEAR) {
358
 
      tile_mode = TILE6_LINEAR;
359
 
      ubwc_enabled = false;
360
 
   }
361
 
 
362
 
   /* Force linear tiling for formats with "fake" optimalTilingFeatures */
363
 
   if (!tiling_possible(image->vk_format)) {
364
 
      tile_mode = TILE6_LINEAR;
365
 
      ubwc_enabled = false;
366
 
   }
367
 
 
368
 
   /* No sense in tiling a 1D image, you'd just waste space and cache locality. */
369
 
   if (pCreateInfo->imageType == VK_IMAGE_TYPE_1D) {
370
 
      tile_mode = TILE6_LINEAR;
371
 
      ubwc_enabled = false;
372
 
   }
373
 
 
374
 
   enum pipe_format format =
375
 
      tu_vk_format_to_pipe_format(image->vk_format);
376
 
   /* Whether a view of the image with an R8G8 format could be made. */
377
 
   bool has_r8g8 = tu_is_r8g8(format);
378
 
 
379
 
   /* Mutable images can be reinterpreted as any other compatible format.
380
 
    * This is a problem with UBWC (compression for different formats is different),
381
 
    * but also tiling ("swap" affects how tiled formats are stored in memory)
382
 
    * Depth and stencil formats cannot be reintepreted as another format, and
383
 
    * cannot be linear with sysmem rendering, so don't fall back for those.
384
 
    *
385
 
    * TODO:
386
 
    * - if the fmt_list contains only formats which are swapped, but compatible
387
 
    *   with each other (B8G8R8A8_UNORM and B8G8R8A8_UINT for example), then
388
 
    *   tiling is still possible
389
 
    * - figure out which UBWC compressions are compatible to keep it enabled
390
 
    */
391
 
   if ((pCreateInfo->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) &&
392
 
       !vk_format_is_depth_or_stencil(image->vk_format)) {
393
 
      const VkImageFormatListCreateInfo *fmt_list =
394
 
         vk_find_struct_const(pCreateInfo->pNext, IMAGE_FORMAT_LIST_CREATE_INFO);
395
 
      bool may_be_swapped = true;
396
 
      /* Whether a view of the image with a non-R8G8 but R8G8 compatible format
397
 
       * could be made.
398
 
       */
399
 
      bool has_r8g8_compatible = false;
400
 
      if (fmt_list) {
401
 
         may_be_swapped = false;
402
 
         has_r8g8_compatible = !has_r8g8 && tu_is_r8g8_compatible(format);
403
 
         for (uint32_t i = 0; i < fmt_list->viewFormatCount; i++) {
404
 
            enum pipe_format format =
405
 
               tu_vk_format_to_pipe_format(fmt_list->pViewFormats[i]);
406
 
            bool is_r8g8 = tu_is_r8g8(format);
407
 
            has_r8g8 = has_r8g8 || is_r8g8;
408
 
            has_r8g8_compatible = has_r8g8_compatible ||
409
 
                                  (!is_r8g8 && tu_is_r8g8_compatible(format));
410
 
 
411
 
            if (tu6_format_texture(format, TILE6_LINEAR).swap) {
412
 
               may_be_swapped = true;
413
 
               break;
414
 
            }
415
 
         }
416
 
      } else {
417
 
         /* If there is no format list it could be reinterpreted as
418
 
          * any compatible format.
419
 
          */
420
 
         has_r8g8 = tu_is_r8g8_compatible(format);
421
 
         has_r8g8_compatible = has_r8g8;
422
 
      }
423
 
 
424
 
      if (may_be_swapped)
425
 
         tile_mode = TILE6_LINEAR;
426
 
 
427
 
      /* R8G8 have a different block width/height and height alignment from other
428
 
       * formats that would normally be compatible (like R16), and so if we are
429
 
       * trying to, for example, sample R16 as R8G8 we need to demote to linear.
430
 
       */
431
 
      if (has_r8g8 && has_r8g8_compatible)
432
 
         tile_mode = TILE6_LINEAR;
433
 
 
434
 
      ubwc_enabled = false;
435
 
   }
436
 
 
437
 
   const VkImageStencilUsageCreateInfo *stencil_usage_info =
438
 
      vk_find_struct_const(pCreateInfo->pNext, IMAGE_STENCIL_USAGE_CREATE_INFO);
439
 
 
440
 
   if (!ubwc_possible(image->vk_format, pCreateInfo->imageType, pCreateInfo->usage,
441
 
                      stencil_usage_info ? stencil_usage_info->stencilUsage : pCreateInfo->usage,
442
 
                      device->physical_device->info, pCreateInfo->samples))
443
 
      ubwc_enabled = false;
444
 
 
445
 
   /* expect UBWC enabled if we asked for it */
446
 
   assert(modifier != DRM_FORMAT_MOD_QCOM_COMPRESSED || ubwc_enabled);
447
 
 
448
 
   /* Non-UBWC tiled R8G8 is probably buggy since media formats are always
449
 
    * either linear or UBWC. There is no simple test to reproduce the bug.
450
 
    * However it was observed in the wild leading to an unrecoverable hang
451
 
    * on a650/a660.
452
 
    */
453
 
   if (has_r8g8 && tile_mode == TILE6_3 && !ubwc_enabled) {
454
 
      tile_mode = TILE6_LINEAR;
455
 
   }
456
 
 
457
 
   for (uint32_t i = 0; i < tu6_plane_count(image->vk_format); i++) {
458
 
      struct fdl_layout *layout = &image->layout[i];
459
 
      enum pipe_format format = tu6_plane_format(image->vk_format, i);
460
 
      uint32_t width0 = pCreateInfo->extent.width;
461
 
      uint32_t height0 = pCreateInfo->extent.height;
462
 
 
463
 
      if (i > 0) {
464
 
         switch (image->vk_format) {
465
 
         case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
466
 
         case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
467
 
            /* half width/height on chroma planes */
468
 
            width0 = (width0 + 1) >> 1;
469
 
            height0 = (height0 + 1) >> 1;
470
 
            break;
471
 
         case VK_FORMAT_D32_SFLOAT_S8_UINT:
472
 
            /* no UBWC for separate stencil */
473
 
            ubwc_enabled = false;
474
 
            break;
475
 
         default:
476
 
            break;
477
 
         }
478
 
      }
479
 
 
480
 
      struct fdl_explicit_layout plane_layout;
481
 
 
482
 
      if (plane_layouts) {
483
 
         /* only expect simple 2D images for now */
484
 
         if (pCreateInfo->mipLevels != 1 ||
485
 
            pCreateInfo->arrayLayers != 1 ||
486
 
            pCreateInfo->extent.depth != 1)
487
 
            return vk_error(device, VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT);
488
 
 
489
 
         plane_layout.offset = plane_layouts[i].offset;
490
 
         plane_layout.pitch = plane_layouts[i].rowPitch;
491
 
         /* note: use plane_layouts[0].arrayPitch to support array formats */
492
 
      }
493
 
 
494
 
      layout->tile_mode = tile_mode;
495
 
      layout->ubwc = ubwc_enabled;
496
 
 
497
 
      if (!fdl6_layout(layout, format,
498
 
                       pCreateInfo->samples,
499
 
                       width0, height0,
500
 
                       pCreateInfo->extent.depth,
501
 
                       pCreateInfo->mipLevels,
502
 
                       pCreateInfo->arrayLayers,
503
 
                       pCreateInfo->imageType == VK_IMAGE_TYPE_3D,
504
 
                       plane_layouts ? &plane_layout : NULL)) {
505
 
         assert(plane_layouts); /* can only fail with explicit layout */
506
 
         return vk_error(device, VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT);
507
 
      }
508
 
 
509
 
      /* fdl6_layout can't take explicit offset without explicit pitch
510
 
       * add offset manually for extra layouts for planes
511
 
       */
512
 
      if (!plane_layouts && i > 0) {
513
 
         uint32_t offset = ALIGN_POT(image->total_size, 4096);
514
 
         for (int i = 0; i < pCreateInfo->mipLevels; i++) {
515
 
            layout->slices[i].offset += offset;
516
 
            layout->ubwc_slices[i].offset += offset;
517
 
         }
518
 
         layout->size += offset;
519
 
      }
520
 
 
521
 
      image->total_size = MAX2(image->total_size, layout->size);
522
 
   }
523
 
 
524
 
   const struct util_format_description *desc = util_format_description(image->layout[0].format);
525
 
   if (util_format_has_depth(desc) && !(device->instance->debug_flags & TU_DEBUG_NOLRZ))
526
 
   {
527
 
      /* Depth plane is the first one */
528
 
      struct fdl_layout *layout = &image->layout[0];
529
 
      unsigned width = layout->width0;
530
 
      unsigned height = layout->height0;
531
 
 
532
 
      /* LRZ buffer is super-sampled */
533
 
      switch (layout->nr_samples) {
534
 
      case 4:
535
 
         width *= 2;
536
 
         FALLTHROUGH;
537
 
      case 2:
538
 
         height *= 2;
539
 
         break;
540
 
      default:
541
 
         break;
542
 
      }
543
 
 
544
 
      unsigned lrz_pitch  = align(DIV_ROUND_UP(width, 8), 32);
545
 
      unsigned lrz_height = align(DIV_ROUND_UP(height, 8), 16);
546
 
 
547
 
      image->lrz_height = lrz_height;
548
 
      image->lrz_pitch = lrz_pitch;
549
 
      image->lrz_offset = image->total_size;
550
 
      unsigned lrz_size = lrz_pitch * lrz_height * 2;
551
 
      image->total_size += lrz_size;
552
 
   }
553
 
 
554
 
   return VK_SUCCESS;
555
 
}
556
 
 
557
 
VKAPI_ATTR VkResult VKAPI_CALL
558
 
tu_CreateImage(VkDevice _device,
559
 
               const VkImageCreateInfo *pCreateInfo,
560
 
               const VkAllocationCallbacks *alloc,
561
 
               VkImage *pImage)
562
 
{
563
 
   uint64_t modifier = DRM_FORMAT_MOD_INVALID;
564
 
   const VkSubresourceLayout *plane_layouts = NULL;
565
 
 
566
 
   TU_FROM_HANDLE(tu_device, device, _device);
567
 
   struct tu_image *image =
568
 
      vk_object_zalloc(&device->vk, alloc, sizeof(*image), VK_OBJECT_TYPE_IMAGE);
569
 
 
570
 
   if (!image)
571
 
      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
572
 
 
573
 
   if (pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
574
 
      const VkImageDrmFormatModifierListCreateInfoEXT *mod_info =
575
 
         vk_find_struct_const(pCreateInfo->pNext,
576
 
                              IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
577
 
      const VkImageDrmFormatModifierExplicitCreateInfoEXT *drm_explicit_info =
578
 
         vk_find_struct_const(pCreateInfo->pNext,
579
 
                              IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
580
 
 
581
 
      assert(mod_info || drm_explicit_info);
582
 
 
583
 
      if (mod_info) {
584
 
         modifier = DRM_FORMAT_MOD_LINEAR;
585
 
         for (unsigned i = 0; i < mod_info->drmFormatModifierCount; i++) {
586
 
            if (mod_info->pDrmFormatModifiers[i] == DRM_FORMAT_MOD_QCOM_COMPRESSED)
587
 
               modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
588
 
         }
589
 
      } else {
590
 
         modifier = drm_explicit_info->drmFormatModifier;
591
 
         assert(modifier == DRM_FORMAT_MOD_LINEAR ||
592
 
                modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED);
593
 
         plane_layouts = drm_explicit_info->pPlaneLayouts;
594
 
      }
595
 
   } else {
596
 
      const struct wsi_image_create_info *wsi_info =
597
 
         vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);
598
 
      if (wsi_info && wsi_info->scanout)
599
 
         modifier = DRM_FORMAT_MOD_LINEAR;
600
 
   }
601
 
 
602
 
#ifdef ANDROID
603
 
   const VkNativeBufferANDROID *gralloc_info =
604
 
      vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID);
605
 
   int dma_buf;
606
 
   if (gralloc_info) {
607
 
      VkResult result = tu_gralloc_info(device, gralloc_info, &dma_buf, &modifier);
608
 
      if (result != VK_SUCCESS)
609
 
         return result;
610
 
   }
611
 
#endif
612
 
 
613
 
   VkResult result = tu_image_init(device, image, pCreateInfo, modifier,
614
 
                                   plane_layouts);
615
 
   if (result != VK_SUCCESS) {
616
 
      vk_object_free(&device->vk, alloc, image);
617
 
      return result;
618
 
   }
619
 
 
620
 
   *pImage = tu_image_to_handle(image);
621
 
 
622
 
#ifdef ANDROID
623
 
   if (gralloc_info)
624
 
      return tu_import_memory_from_gralloc_handle(_device, dma_buf, alloc,
625
 
                                                  *pImage);
626
 
#endif
627
 
   return VK_SUCCESS;
628
 
}
629
 
 
630
 
VKAPI_ATTR void VKAPI_CALL
631
 
tu_DestroyImage(VkDevice _device,
632
 
                VkImage _image,
633
 
                const VkAllocationCallbacks *pAllocator)
634
 
{
635
 
   TU_FROM_HANDLE(tu_device, device, _device);
636
 
   TU_FROM_HANDLE(tu_image, image, _image);
637
 
 
638
 
   if (!image)
639
 
      return;
640
 
 
641
 
#ifdef ANDROID
642
 
   if (image->owned_memory != VK_NULL_HANDLE)
643
 
      tu_FreeMemory(_device, image->owned_memory, pAllocator);
644
 
#endif
645
 
 
646
 
   vk_object_free(&device->vk, pAllocator, image);
647
 
}
648
 
 
649
 
static void
650
 
tu_get_image_memory_requirements(struct tu_image *image,
651
 
                                 VkMemoryRequirements2 *pMemoryRequirements)
652
 
{
653
 
   pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
654
 
      .memoryTypeBits = 1,
655
 
      .alignment = image->layout[0].base_align,
656
 
      .size = image->total_size
657
 
   };
658
 
 
659
 
   vk_foreach_struct(ext, pMemoryRequirements->pNext) {
660
 
      switch (ext->sType) {
661
 
      case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
662
 
         VkMemoryDedicatedRequirements *req =
663
 
            (VkMemoryDedicatedRequirements *) ext;
664
 
         req->requiresDedicatedAllocation = image->shareable;
665
 
         req->prefersDedicatedAllocation = req->requiresDedicatedAllocation;
666
 
         break;
667
 
      }
668
 
      default:
669
 
         break;
670
 
      }
671
 
   }
672
 
}
673
 
 
674
 
VKAPI_ATTR void VKAPI_CALL
675
 
tu_GetImageMemoryRequirements2(VkDevice device,
676
 
                               const VkImageMemoryRequirementsInfo2 *pInfo,
677
 
                               VkMemoryRequirements2 *pMemoryRequirements)
678
 
{
679
 
   TU_FROM_HANDLE(tu_image, image, pInfo->image);
680
 
 
681
 
   tu_get_image_memory_requirements(image, pMemoryRequirements);
682
 
}
683
 
 
684
 
VKAPI_ATTR void VKAPI_CALL
685
 
tu_GetImageSparseMemoryRequirements2(
686
 
   VkDevice device,
687
 
   const VkImageSparseMemoryRequirementsInfo2 *pInfo,
688
 
   uint32_t *pSparseMemoryRequirementCount,
689
 
   VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
690
 
{
691
 
   tu_stub();
692
 
}
693
 
 
694
 
VKAPI_ATTR void VKAPI_CALL
695
 
tu_GetDeviceImageMemoryRequirements(
696
 
   VkDevice _device,
697
 
   const VkDeviceImageMemoryRequirements *pInfo,
698
 
   VkMemoryRequirements2 *pMemoryRequirements)
699
 
{
700
 
   TU_FROM_HANDLE(tu_device, device, _device);
701
 
 
702
 
   struct tu_image image = {0};
703
 
 
704
 
   tu_image_init(device, &image, pInfo->pCreateInfo, DRM_FORMAT_MOD_INVALID,
705
 
                 NULL);
706
 
 
707
 
   tu_get_image_memory_requirements(&image, pMemoryRequirements);
708
 
}
709
 
 
710
 
VKAPI_ATTR void VKAPI_CALL
711
 
tu_GetDeviceImageSparseMemoryRequirements(
712
 
    VkDevice device,
713
 
    const VkDeviceImageMemoryRequirements *pInfo,
714
 
    uint32_t *pSparseMemoryRequirementCount,
715
 
    VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
716
 
{
717
 
   tu_stub();
718
 
}
719
 
 
720
 
VKAPI_ATTR void VKAPI_CALL
721
 
tu_GetImageSubresourceLayout(VkDevice _device,
722
 
                             VkImage _image,
723
 
                             const VkImageSubresource *pSubresource,
724
 
                             VkSubresourceLayout *pLayout)
725
 
{
726
 
   TU_FROM_HANDLE(tu_image, image, _image);
727
 
 
728
 
   struct fdl_layout *layout =
729
 
      &image->layout[tu6_plane_index(image->vk_format, pSubresource->aspectMask)];
730
 
   const struct fdl_slice *slice = layout->slices + pSubresource->mipLevel;
731
 
 
732
 
   pLayout->offset =
733
 
      fdl_surface_offset(layout, pSubresource->mipLevel, pSubresource->arrayLayer);
734
 
   pLayout->rowPitch = fdl_pitch(layout, pSubresource->mipLevel);
735
 
   pLayout->arrayPitch = fdl_layer_stride(layout, pSubresource->mipLevel);
736
 
   pLayout->depthPitch = slice->size0;
737
 
   pLayout->size = pLayout->depthPitch * layout->depth0;
738
 
 
739
 
   if (fdl_ubwc_enabled(layout, pSubresource->mipLevel)) {
740
 
      /* UBWC starts at offset 0 */
741
 
      pLayout->offset = 0;
742
 
      /* UBWC scanout won't match what the kernel wants if we have levels/layers */
743
 
      assert(image->level_count == 1 && image->layer_count == 1);
744
 
   }
745
 
}
746
 
 
747
 
VKAPI_ATTR VkResult VKAPI_CALL
748
 
tu_GetImageDrmFormatModifierPropertiesEXT(
749
 
    VkDevice                                    device,
750
 
    VkImage                                     _image,
751
 
    VkImageDrmFormatModifierPropertiesEXT*      pProperties)
752
 
{
753
 
   TU_FROM_HANDLE(tu_image, image, _image);
754
 
 
755
 
   /* TODO invent a modifier for tiled but not UBWC buffers */
756
 
 
757
 
   if (!image->layout[0].tile_mode)
758
 
      pProperties->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
759
 
   else if (image->layout[0].ubwc_layer_size)
760
 
      pProperties->drmFormatModifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
761
 
   else
762
 
      pProperties->drmFormatModifier = DRM_FORMAT_MOD_INVALID;
763
 
 
764
 
   return VK_SUCCESS;
765
 
}
766
 
 
767
 
 
768
 
VKAPI_ATTR VkResult VKAPI_CALL
769
 
tu_CreateImageView(VkDevice _device,
770
 
                   const VkImageViewCreateInfo *pCreateInfo,
771
 
                   const VkAllocationCallbacks *pAllocator,
772
 
                   VkImageView *pView)
773
 
{
774
 
   TU_FROM_HANDLE(tu_device, device, _device);
775
 
   struct tu_image_view *view;
776
 
 
777
 
   view = vk_object_alloc(&device->vk, pAllocator, sizeof(*view),
778
 
                          VK_OBJECT_TYPE_IMAGE_VIEW);
779
 
   if (view == NULL)
780
 
      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
781
 
 
782
 
   tu_image_view_init(view, pCreateInfo, device->physical_device->info->a6xx.has_z24uint_s8uint);
783
 
 
784
 
   *pView = tu_image_view_to_handle(view);
785
 
 
786
 
   return VK_SUCCESS;
787
 
}
788
 
 
789
 
VKAPI_ATTR void VKAPI_CALL
790
 
tu_DestroyImageView(VkDevice _device,
791
 
                    VkImageView _iview,
792
 
                    const VkAllocationCallbacks *pAllocator)
793
 
{
794
 
   TU_FROM_HANDLE(tu_device, device, _device);
795
 
   TU_FROM_HANDLE(tu_image_view, iview, _iview);
796
 
 
797
 
   if (!iview)
798
 
      return;
799
 
 
800
 
   vk_object_free(&device->vk, pAllocator, iview);
801
 
}
802
 
 
803
 
void
804
 
tu_buffer_view_init(struct tu_buffer_view *view,
805
 
                    struct tu_device *device,
806
 
                    const VkBufferViewCreateInfo *pCreateInfo)
807
 
{
808
 
   TU_FROM_HANDLE(tu_buffer, buffer, pCreateInfo->buffer);
809
 
 
810
 
   view->buffer = buffer;
811
 
 
812
 
   uint32_t range;
813
 
   if (pCreateInfo->range == VK_WHOLE_SIZE)
814
 
      range = buffer->size - pCreateInfo->offset;
815
 
   else
816
 
      range = pCreateInfo->range;
817
 
 
818
 
   uint8_t swiz[4] = { PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z,
819
 
                       PIPE_SWIZZLE_W };
820
 
 
821
 
   fdl6_buffer_view_init(
822
 
      view->descriptor, tu_vk_format_to_pipe_format(pCreateInfo->format),
823
 
      swiz, buffer->iova + pCreateInfo->offset, range);
824
 
}
825
 
 
826
 
VKAPI_ATTR VkResult VKAPI_CALL
827
 
tu_CreateBufferView(VkDevice _device,
828
 
                    const VkBufferViewCreateInfo *pCreateInfo,
829
 
                    const VkAllocationCallbacks *pAllocator,
830
 
                    VkBufferView *pView)
831
 
{
832
 
   TU_FROM_HANDLE(tu_device, device, _device);
833
 
   struct tu_buffer_view *view;
834
 
 
835
 
   view = vk_object_alloc(&device->vk, pAllocator, sizeof(*view),
836
 
                          VK_OBJECT_TYPE_BUFFER_VIEW);
837
 
   if (!view)
838
 
      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
839
 
 
840
 
   tu_buffer_view_init(view, device, pCreateInfo);
841
 
 
842
 
   *pView = tu_buffer_view_to_handle(view);
843
 
 
844
 
   return VK_SUCCESS;
845
 
}
846
 
 
847
 
VKAPI_ATTR void VKAPI_CALL
848
 
tu_DestroyBufferView(VkDevice _device,
849
 
                     VkBufferView bufferView,
850
 
                     const VkAllocationCallbacks *pAllocator)
851
 
{
852
 
   TU_FROM_HANDLE(tu_device, device, _device);
853
 
   TU_FROM_HANDLE(tu_buffer_view, view, bufferView);
854
 
 
855
 
   if (!view)
856
 
      return;
857
 
 
858
 
   vk_object_free(&device->vk, pAllocator, view);
859
 
}