xref: /aosp_15_r20/external/mesa3d/src/imagination/vulkan/pvr_image.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2022 Imagination Technologies Ltd.
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
5*61046927SAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to deal
6*61046927SAndroid Build Coastguard Worker  * in the Software without restriction, including without limitation the rights
7*61046927SAndroid Build Coastguard Worker  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8*61046927SAndroid Build Coastguard Worker  * copies of the Software, and to permit persons to whom the Software is
9*61046927SAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18*61046927SAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20*61046927SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21*61046927SAndroid Build Coastguard Worker  * SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #include <assert.h>
25*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
26*61046927SAndroid Build Coastguard Worker #include <stdint.h>
27*61046927SAndroid Build Coastguard Worker #include <string.h>
28*61046927SAndroid Build Coastguard Worker 
29*61046927SAndroid Build Coastguard Worker #include "pvr_csb.h"
30*61046927SAndroid Build Coastguard Worker #include "pvr_device_info.h"
31*61046927SAndroid Build Coastguard Worker #include "pvr_formats.h"
32*61046927SAndroid Build Coastguard Worker #include "pvr_private.h"
33*61046927SAndroid Build Coastguard Worker #include "pvr_tex_state.h"
34*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
35*61046927SAndroid Build Coastguard Worker #include "util/u_math.h"
36*61046927SAndroid Build Coastguard Worker #include "vk_format.h"
37*61046927SAndroid Build Coastguard Worker #include "vk_image.h"
38*61046927SAndroid Build Coastguard Worker #include "vk_log.h"
39*61046927SAndroid Build Coastguard Worker #include "vk_object.h"
40*61046927SAndroid Build Coastguard Worker #include "vk_util.h"
41*61046927SAndroid Build Coastguard Worker #include "wsi_common.h"
42*61046927SAndroid Build Coastguard Worker 
pvr_image_init_memlayout(struct pvr_image * image)43*61046927SAndroid Build Coastguard Worker static void pvr_image_init_memlayout(struct pvr_image *image)
44*61046927SAndroid Build Coastguard Worker {
45*61046927SAndroid Build Coastguard Worker    switch (image->vk.tiling) {
46*61046927SAndroid Build Coastguard Worker    default:
47*61046927SAndroid Build Coastguard Worker       unreachable("bad VkImageTiling");
48*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_TILING_OPTIMAL:
49*61046927SAndroid Build Coastguard Worker       if (image->vk.wsi_legacy_scanout)
50*61046927SAndroid Build Coastguard Worker          image->memlayout = PVR_MEMLAYOUT_LINEAR;
51*61046927SAndroid Build Coastguard Worker       else if (image->vk.image_type == VK_IMAGE_TYPE_3D)
52*61046927SAndroid Build Coastguard Worker          image->memlayout = PVR_MEMLAYOUT_3DTWIDDLED;
53*61046927SAndroid Build Coastguard Worker       else
54*61046927SAndroid Build Coastguard Worker          image->memlayout = PVR_MEMLAYOUT_TWIDDLED;
55*61046927SAndroid Build Coastguard Worker       break;
56*61046927SAndroid Build Coastguard Worker    case VK_IMAGE_TILING_LINEAR:
57*61046927SAndroid Build Coastguard Worker       image->memlayout = PVR_MEMLAYOUT_LINEAR;
58*61046927SAndroid Build Coastguard Worker       break;
59*61046927SAndroid Build Coastguard Worker    }
60*61046927SAndroid Build Coastguard Worker }
61*61046927SAndroid Build Coastguard Worker 
pvr_image_init_physical_extent(struct pvr_image * image)62*61046927SAndroid Build Coastguard Worker static void pvr_image_init_physical_extent(struct pvr_image *image)
63*61046927SAndroid Build Coastguard Worker {
64*61046927SAndroid Build Coastguard Worker    assert(image->memlayout != PVR_MEMLAYOUT_UNDEFINED);
65*61046927SAndroid Build Coastguard Worker 
66*61046927SAndroid Build Coastguard Worker    /* clang-format off */
67*61046927SAndroid Build Coastguard Worker    if (image->vk.mip_levels > 1 ||
68*61046927SAndroid Build Coastguard Worker       image->memlayout == PVR_MEMLAYOUT_TWIDDLED ||
69*61046927SAndroid Build Coastguard Worker       image->memlayout == PVR_MEMLAYOUT_3DTWIDDLED) {
70*61046927SAndroid Build Coastguard Worker       /* clang-format on */
71*61046927SAndroid Build Coastguard Worker       image->physical_extent.width =
72*61046927SAndroid Build Coastguard Worker          util_next_power_of_two(image->vk.extent.width);
73*61046927SAndroid Build Coastguard Worker       image->physical_extent.height =
74*61046927SAndroid Build Coastguard Worker          util_next_power_of_two(image->vk.extent.height);
75*61046927SAndroid Build Coastguard Worker       image->physical_extent.depth =
76*61046927SAndroid Build Coastguard Worker          util_next_power_of_two(image->vk.extent.depth);
77*61046927SAndroid Build Coastguard Worker    } else {
78*61046927SAndroid Build Coastguard Worker       assert(image->memlayout == PVR_MEMLAYOUT_LINEAR);
79*61046927SAndroid Build Coastguard Worker       image->physical_extent = image->vk.extent;
80*61046927SAndroid Build Coastguard Worker    }
81*61046927SAndroid Build Coastguard Worker }
82*61046927SAndroid Build Coastguard Worker 
pvr_image_setup_mip_levels(struct pvr_image * image)83*61046927SAndroid Build Coastguard Worker static void pvr_image_setup_mip_levels(struct pvr_image *image)
84*61046927SAndroid Build Coastguard Worker {
85*61046927SAndroid Build Coastguard Worker    const uint32_t extent_alignment =
86*61046927SAndroid Build Coastguard Worker       image->vk.image_type == VK_IMAGE_TYPE_3D ? 4 : 1;
87*61046927SAndroid Build Coastguard Worker    const unsigned int cpp = vk_format_get_blocksize(image->vk.format);
88*61046927SAndroid Build Coastguard Worker    VkExtent3D extent =
89*61046927SAndroid Build Coastguard Worker       vk_image_extent_to_elements(&image->vk, image->physical_extent);
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker    /* Mip-mapped textures that are non-dword aligned need dword-aligned levels
92*61046927SAndroid Build Coastguard Worker     * so they can be TQd from.
93*61046927SAndroid Build Coastguard Worker     */
94*61046927SAndroid Build Coastguard Worker    const uint32_t level_alignment = image->vk.mip_levels > 1 ? 4 : 1;
95*61046927SAndroid Build Coastguard Worker 
96*61046927SAndroid Build Coastguard Worker    assert(image->vk.mip_levels <= ARRAY_SIZE(image->mip_levels));
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker    image->layer_size = 0;
99*61046927SAndroid Build Coastguard Worker 
100*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < image->vk.mip_levels; i++) {
101*61046927SAndroid Build Coastguard Worker       struct pvr_mip_level *mip_level = &image->mip_levels[i];
102*61046927SAndroid Build Coastguard Worker 
103*61046927SAndroid Build Coastguard Worker       mip_level->pitch = cpp * ALIGN(extent.width, extent_alignment);
104*61046927SAndroid Build Coastguard Worker       mip_level->height_pitch = ALIGN(extent.height, extent_alignment);
105*61046927SAndroid Build Coastguard Worker       mip_level->size = image->vk.samples * mip_level->pitch *
106*61046927SAndroid Build Coastguard Worker                         mip_level->height_pitch *
107*61046927SAndroid Build Coastguard Worker                         ALIGN(extent.depth, extent_alignment);
108*61046927SAndroid Build Coastguard Worker       mip_level->size = ALIGN(mip_level->size, level_alignment);
109*61046927SAndroid Build Coastguard Worker       mip_level->offset = image->layer_size;
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker       image->layer_size += mip_level->size;
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker       extent.height = u_minify(extent.height, 1);
114*61046927SAndroid Build Coastguard Worker       extent.width = u_minify(extent.width, 1);
115*61046927SAndroid Build Coastguard Worker       extent.depth = u_minify(extent.depth, 1);
116*61046927SAndroid Build Coastguard Worker    }
117*61046927SAndroid Build Coastguard Worker 
118*61046927SAndroid Build Coastguard Worker    /* The hw calculates layer strides as if a full mip chain up until 1x1x1
119*61046927SAndroid Build Coastguard Worker     * were present so we need to account for that in the `layer_size`.
120*61046927SAndroid Build Coastguard Worker     */
121*61046927SAndroid Build Coastguard Worker    while (extent.height != 1 || extent.width != 1 || extent.depth != 1) {
122*61046927SAndroid Build Coastguard Worker       const uint32_t height_pitch = ALIGN(extent.height, extent_alignment);
123*61046927SAndroid Build Coastguard Worker       const uint32_t pitch = cpp * ALIGN(extent.width, extent_alignment);
124*61046927SAndroid Build Coastguard Worker 
125*61046927SAndroid Build Coastguard Worker       image->layer_size += image->vk.samples * pitch * height_pitch *
126*61046927SAndroid Build Coastguard Worker                            ALIGN(extent.depth, extent_alignment);
127*61046927SAndroid Build Coastguard Worker 
128*61046927SAndroid Build Coastguard Worker       extent.height = u_minify(extent.height, 1);
129*61046927SAndroid Build Coastguard Worker       extent.width = u_minify(extent.width, 1);
130*61046927SAndroid Build Coastguard Worker       extent.depth = u_minify(extent.depth, 1);
131*61046927SAndroid Build Coastguard Worker    }
132*61046927SAndroid Build Coastguard Worker 
133*61046927SAndroid Build Coastguard Worker    /* TODO: It might be useful to store the alignment in the image so it can be
134*61046927SAndroid Build Coastguard Worker     * checked (via an assert?) when setting
135*61046927SAndroid Build Coastguard Worker     * RGX_CR_TPU_TAG_CEM_4K_FACE_PACKING_EN, assuming this is where the
136*61046927SAndroid Build Coastguard Worker     * requirement comes from.
137*61046927SAndroid Build Coastguard Worker     */
138*61046927SAndroid Build Coastguard Worker    if (image->vk.array_layers > 1)
139*61046927SAndroid Build Coastguard Worker       image->layer_size = align64(image->layer_size, image->alignment);
140*61046927SAndroid Build Coastguard Worker 
141*61046927SAndroid Build Coastguard Worker    image->size = image->layer_size * image->vk.array_layers;
142*61046927SAndroid Build Coastguard Worker }
143*61046927SAndroid Build Coastguard Worker 
pvr_CreateImage(VkDevice _device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * pImage)144*61046927SAndroid Build Coastguard Worker VkResult pvr_CreateImage(VkDevice _device,
145*61046927SAndroid Build Coastguard Worker                          const VkImageCreateInfo *pCreateInfo,
146*61046927SAndroid Build Coastguard Worker                          const VkAllocationCallbacks *pAllocator,
147*61046927SAndroid Build Coastguard Worker                          VkImage *pImage)
148*61046927SAndroid Build Coastguard Worker {
149*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_device, device, _device);
150*61046927SAndroid Build Coastguard Worker    struct pvr_image *image;
151*61046927SAndroid Build Coastguard Worker 
152*61046927SAndroid Build Coastguard Worker    image =
153*61046927SAndroid Build Coastguard Worker       vk_image_create(&device->vk, pCreateInfo, pAllocator, sizeof(*image));
154*61046927SAndroid Build Coastguard Worker    if (!image)
155*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker    /* All images aligned to 4k, in case of arrays/CEM.
158*61046927SAndroid Build Coastguard Worker     * Refer: pvr_GetImageMemoryRequirements for further details.
159*61046927SAndroid Build Coastguard Worker     */
160*61046927SAndroid Build Coastguard Worker    image->alignment = 4096U;
161*61046927SAndroid Build Coastguard Worker 
162*61046927SAndroid Build Coastguard Worker    /* Initialize the image using the saved information from pCreateInfo */
163*61046927SAndroid Build Coastguard Worker    pvr_image_init_memlayout(image);
164*61046927SAndroid Build Coastguard Worker    pvr_image_init_physical_extent(image);
165*61046927SAndroid Build Coastguard Worker    pvr_image_setup_mip_levels(image);
166*61046927SAndroid Build Coastguard Worker 
167*61046927SAndroid Build Coastguard Worker    *pImage = pvr_image_to_handle(image);
168*61046927SAndroid Build Coastguard Worker 
169*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
170*61046927SAndroid Build Coastguard Worker }
171*61046927SAndroid Build Coastguard Worker 
pvr_DestroyImage(VkDevice _device,VkImage _image,const VkAllocationCallbacks * pAllocator)172*61046927SAndroid Build Coastguard Worker void pvr_DestroyImage(VkDevice _device,
173*61046927SAndroid Build Coastguard Worker                       VkImage _image,
174*61046927SAndroid Build Coastguard Worker                       const VkAllocationCallbacks *pAllocator)
175*61046927SAndroid Build Coastguard Worker {
176*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_device, device, _device);
177*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_image, image, _image);
178*61046927SAndroid Build Coastguard Worker 
179*61046927SAndroid Build Coastguard Worker    if (!image)
180*61046927SAndroid Build Coastguard Worker       return;
181*61046927SAndroid Build Coastguard Worker 
182*61046927SAndroid Build Coastguard Worker    if (image->vma)
183*61046927SAndroid Build Coastguard Worker       pvr_unbind_memory(device, image->vma);
184*61046927SAndroid Build Coastguard Worker 
185*61046927SAndroid Build Coastguard Worker    vk_image_destroy(&device->vk, pAllocator, &image->vk);
186*61046927SAndroid Build Coastguard Worker }
187*61046927SAndroid Build Coastguard Worker 
188*61046927SAndroid Build Coastguard Worker /* clang-format off */
189*61046927SAndroid Build Coastguard Worker /* Consider a 4 page buffer object.
190*61046927SAndroid Build Coastguard Worker  *   _________________________________________
191*61046927SAndroid Build Coastguard Worker  *  |         |          |         |          |
192*61046927SAndroid Build Coastguard Worker  *  |_________|__________|_________|__________|
193*61046927SAndroid Build Coastguard Worker  *                  |
194*61046927SAndroid Build Coastguard Worker  *                  \__ offset (0.5 page size)
195*61046927SAndroid Build Coastguard Worker  *
196*61046927SAndroid Build Coastguard Worker  *                  |___size(2 pages)____|
197*61046927SAndroid Build Coastguard Worker  *
198*61046927SAndroid Build Coastguard Worker  *            |__VMA size required (3 pages)__|
199*61046927SAndroid Build Coastguard Worker  *
200*61046927SAndroid Build Coastguard Worker  *                  |
201*61046927SAndroid Build Coastguard Worker  *                  \__ returned dev_addr = vma + offset % page_size
202*61046927SAndroid Build Coastguard Worker  *
203*61046927SAndroid Build Coastguard Worker  *   VMA size = align(size + offset % page_size, page_size);
204*61046927SAndroid Build Coastguard Worker  *
205*61046927SAndroid Build Coastguard Worker  *   Note: the above handling is currently divided between generic
206*61046927SAndroid Build Coastguard Worker  *   driver code and winsys layer. Given are the details of how this is
207*61046927SAndroid Build Coastguard Worker  *   being handled.
208*61046927SAndroid Build Coastguard Worker  *   * As winsys vma allocation interface does not have offset information,
209*61046927SAndroid Build Coastguard Worker  *     it can not calculate the extra size needed to adjust for the unaligned
210*61046927SAndroid Build Coastguard Worker  *     offset. So generic code is responsible for allocating a VMA that has
211*61046927SAndroid Build Coastguard Worker  *     extra space to deal with the above scenario.
212*61046927SAndroid Build Coastguard Worker  *   * Remaining work of mapping the vma to bo is done by vma_map interface,
213*61046927SAndroid Build Coastguard Worker  *     as it contains offset information, we don't need to do any adjustments
214*61046927SAndroid Build Coastguard Worker  *     in the generic code for this part.
215*61046927SAndroid Build Coastguard Worker  *
216*61046927SAndroid Build Coastguard Worker  *  TODO: Look into merging heap_alloc and vma_map into single interface.
217*61046927SAndroid Build Coastguard Worker  */
218*61046927SAndroid Build Coastguard Worker /* clang-format on */
219*61046927SAndroid Build Coastguard Worker 
pvr_BindImageMemory2(VkDevice _device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)220*61046927SAndroid Build Coastguard Worker VkResult pvr_BindImageMemory2(VkDevice _device,
221*61046927SAndroid Build Coastguard Worker                               uint32_t bindInfoCount,
222*61046927SAndroid Build Coastguard Worker                               const VkBindImageMemoryInfo *pBindInfos)
223*61046927SAndroid Build Coastguard Worker {
224*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_device, device, _device);
225*61046927SAndroid Build Coastguard Worker    uint32_t i;
226*61046927SAndroid Build Coastguard Worker 
227*61046927SAndroid Build Coastguard Worker    for (i = 0; i < bindInfoCount; i++) {
228*61046927SAndroid Build Coastguard Worker       PVR_FROM_HANDLE(pvr_device_memory, mem, pBindInfos[i].memory);
229*61046927SAndroid Build Coastguard Worker       PVR_FROM_HANDLE(pvr_image, image, pBindInfos[i].image);
230*61046927SAndroid Build Coastguard Worker 
231*61046927SAndroid Build Coastguard Worker       VkResult result = pvr_bind_memory(device,
232*61046927SAndroid Build Coastguard Worker                                         mem,
233*61046927SAndroid Build Coastguard Worker                                         pBindInfos[i].memoryOffset,
234*61046927SAndroid Build Coastguard Worker                                         image->size,
235*61046927SAndroid Build Coastguard Worker                                         image->alignment,
236*61046927SAndroid Build Coastguard Worker                                         &image->vma,
237*61046927SAndroid Build Coastguard Worker                                         &image->dev_addr);
238*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS) {
239*61046927SAndroid Build Coastguard Worker          while (i--) {
240*61046927SAndroid Build Coastguard Worker             PVR_FROM_HANDLE(pvr_image, image, pBindInfos[i].image);
241*61046927SAndroid Build Coastguard Worker 
242*61046927SAndroid Build Coastguard Worker             pvr_unbind_memory(device, image->vma);
243*61046927SAndroid Build Coastguard Worker          }
244*61046927SAndroid Build Coastguard Worker 
245*61046927SAndroid Build Coastguard Worker          return result;
246*61046927SAndroid Build Coastguard Worker       }
247*61046927SAndroid Build Coastguard Worker    }
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
250*61046927SAndroid Build Coastguard Worker }
251*61046927SAndroid Build Coastguard Worker 
pvr_get_image_subresource_layout(const struct pvr_image * image,const VkImageSubresource * subresource,VkSubresourceLayout * layout)252*61046927SAndroid Build Coastguard Worker void pvr_get_image_subresource_layout(const struct pvr_image *image,
253*61046927SAndroid Build Coastguard Worker                                       const VkImageSubresource *subresource,
254*61046927SAndroid Build Coastguard Worker                                       VkSubresourceLayout *layout)
255*61046927SAndroid Build Coastguard Worker {
256*61046927SAndroid Build Coastguard Worker    const struct pvr_mip_level *mip_level =
257*61046927SAndroid Build Coastguard Worker       &image->mip_levels[subresource->mipLevel];
258*61046927SAndroid Build Coastguard Worker 
259*61046927SAndroid Build Coastguard Worker    pvr_assert(subresource->mipLevel < image->vk.mip_levels);
260*61046927SAndroid Build Coastguard Worker    pvr_assert(subresource->arrayLayer < image->vk.array_layers);
261*61046927SAndroid Build Coastguard Worker 
262*61046927SAndroid Build Coastguard Worker    layout->offset =
263*61046927SAndroid Build Coastguard Worker       subresource->arrayLayer * image->layer_size + mip_level->offset;
264*61046927SAndroid Build Coastguard Worker    layout->rowPitch = mip_level->pitch;
265*61046927SAndroid Build Coastguard Worker    layout->depthPitch = mip_level->pitch * mip_level->height_pitch;
266*61046927SAndroid Build Coastguard Worker    layout->arrayPitch = image->layer_size;
267*61046927SAndroid Build Coastguard Worker    layout->size = mip_level->size;
268*61046927SAndroid Build Coastguard Worker }
269*61046927SAndroid Build Coastguard Worker 
pvr_GetImageSubresourceLayout(VkDevice device,VkImage _image,const VkImageSubresource * subresource,VkSubresourceLayout * layout)270*61046927SAndroid Build Coastguard Worker void pvr_GetImageSubresourceLayout(VkDevice device,
271*61046927SAndroid Build Coastguard Worker                                    VkImage _image,
272*61046927SAndroid Build Coastguard Worker                                    const VkImageSubresource *subresource,
273*61046927SAndroid Build Coastguard Worker                                    VkSubresourceLayout *layout)
274*61046927SAndroid Build Coastguard Worker {
275*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_image, image, _image);
276*61046927SAndroid Build Coastguard Worker 
277*61046927SAndroid Build Coastguard Worker    pvr_get_image_subresource_layout(image, subresource, layout);
278*61046927SAndroid Build Coastguard Worker }
279*61046927SAndroid Build Coastguard Worker 
pvr_CreateImageView(VkDevice _device,const VkImageViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImageView * pView)280*61046927SAndroid Build Coastguard Worker VkResult pvr_CreateImageView(VkDevice _device,
281*61046927SAndroid Build Coastguard Worker                              const VkImageViewCreateInfo *pCreateInfo,
282*61046927SAndroid Build Coastguard Worker                              const VkAllocationCallbacks *pAllocator,
283*61046927SAndroid Build Coastguard Worker                              VkImageView *pView)
284*61046927SAndroid Build Coastguard Worker {
285*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_device, device, _device);
286*61046927SAndroid Build Coastguard Worker    struct pvr_texture_state_info info;
287*61046927SAndroid Build Coastguard Worker    unsigned char input_swizzle[4];
288*61046927SAndroid Build Coastguard Worker    const uint8_t *format_swizzle;
289*61046927SAndroid Build Coastguard Worker    const struct pvr_image *image;
290*61046927SAndroid Build Coastguard Worker    struct pvr_image_view *iview;
291*61046927SAndroid Build Coastguard Worker    VkResult result;
292*61046927SAndroid Build Coastguard Worker 
293*61046927SAndroid Build Coastguard Worker    iview = vk_image_view_create(&device->vk,
294*61046927SAndroid Build Coastguard Worker                                 false /* driver_internal */,
295*61046927SAndroid Build Coastguard Worker                                 pCreateInfo,
296*61046927SAndroid Build Coastguard Worker                                 pAllocator,
297*61046927SAndroid Build Coastguard Worker                                 sizeof(*iview));
298*61046927SAndroid Build Coastguard Worker    if (!iview)
299*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
300*61046927SAndroid Build Coastguard Worker 
301*61046927SAndroid Build Coastguard Worker    image = pvr_image_view_get_image(iview);
302*61046927SAndroid Build Coastguard Worker 
303*61046927SAndroid Build Coastguard Worker    info.type = iview->vk.view_type;
304*61046927SAndroid Build Coastguard Worker    info.base_level = iview->vk.base_mip_level;
305*61046927SAndroid Build Coastguard Worker    info.mip_levels = iview->vk.level_count;
306*61046927SAndroid Build Coastguard Worker    info.extent = image->vk.extent;
307*61046927SAndroid Build Coastguard Worker    info.aspect_mask = image->vk.aspects;
308*61046927SAndroid Build Coastguard Worker    info.is_cube = (info.type == VK_IMAGE_VIEW_TYPE_CUBE ||
309*61046927SAndroid Build Coastguard Worker                    info.type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
310*61046927SAndroid Build Coastguard Worker    info.array_size = iview->vk.layer_count;
311*61046927SAndroid Build Coastguard Worker    info.offset = iview->vk.base_array_layer * image->layer_size +
312*61046927SAndroid Build Coastguard Worker                  image->mip_levels[info.base_level].offset;
313*61046927SAndroid Build Coastguard Worker    info.mipmaps_present = (image->vk.mip_levels > 1) ? true : false;
314*61046927SAndroid Build Coastguard Worker    info.stride = image->physical_extent.width;
315*61046927SAndroid Build Coastguard Worker    info.tex_state_type = PVR_TEXTURE_STATE_SAMPLE;
316*61046927SAndroid Build Coastguard Worker    info.mem_layout = image->memlayout;
317*61046927SAndroid Build Coastguard Worker    info.flags = 0;
318*61046927SAndroid Build Coastguard Worker    info.sample_count = image->vk.samples;
319*61046927SAndroid Build Coastguard Worker    info.addr = image->dev_addr;
320*61046927SAndroid Build Coastguard Worker 
321*61046927SAndroid Build Coastguard Worker    info.format = pCreateInfo->format;
322*61046927SAndroid Build Coastguard Worker 
323*61046927SAndroid Build Coastguard Worker    vk_component_mapping_to_pipe_swizzle(iview->vk.swizzle, input_swizzle);
324*61046927SAndroid Build Coastguard Worker    format_swizzle = pvr_get_format_swizzle(info.format);
325*61046927SAndroid Build Coastguard Worker    util_format_compose_swizzles(format_swizzle, input_swizzle, info.swizzle);
326*61046927SAndroid Build Coastguard Worker 
327*61046927SAndroid Build Coastguard Worker    result = pvr_pack_tex_state(device,
328*61046927SAndroid Build Coastguard Worker                                &info,
329*61046927SAndroid Build Coastguard Worker                                iview->texture_state[info.tex_state_type]);
330*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
331*61046927SAndroid Build Coastguard Worker       goto err_vk_image_view_destroy;
332*61046927SAndroid Build Coastguard Worker 
333*61046927SAndroid Build Coastguard Worker    /* Create an additional texture state for cube type if storage
334*61046927SAndroid Build Coastguard Worker     * usage flag is set.
335*61046927SAndroid Build Coastguard Worker     */
336*61046927SAndroid Build Coastguard Worker    if (info.is_cube && image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) {
337*61046927SAndroid Build Coastguard Worker       info.tex_state_type = PVR_TEXTURE_STATE_STORAGE;
338*61046927SAndroid Build Coastguard Worker 
339*61046927SAndroid Build Coastguard Worker       result = pvr_pack_tex_state(device,
340*61046927SAndroid Build Coastguard Worker                                   &info,
341*61046927SAndroid Build Coastguard Worker                                   iview->texture_state[info.tex_state_type]);
342*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
343*61046927SAndroid Build Coastguard Worker          goto err_vk_image_view_destroy;
344*61046927SAndroid Build Coastguard Worker    }
345*61046927SAndroid Build Coastguard Worker 
346*61046927SAndroid Build Coastguard Worker    if (image->vk.usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
347*61046927SAndroid Build Coastguard Worker       /* Attachment state is created as if the mipmaps are not supported, so the
348*61046927SAndroid Build Coastguard Worker        * baselevel is set to zero and num_mip_levels is set to 1. Which gives an
349*61046927SAndroid Build Coastguard Worker        * impression that this is the only level in the image. This also requires
350*61046927SAndroid Build Coastguard Worker        * that width, height and depth be adjusted as well. Given
351*61046927SAndroid Build Coastguard Worker        * iview->vk.extent is already adjusted for base mip map level we use it
352*61046927SAndroid Build Coastguard Worker        * here.
353*61046927SAndroid Build Coastguard Worker        */
354*61046927SAndroid Build Coastguard Worker       /* TODO: Investigate and document the reason for above approach. */
355*61046927SAndroid Build Coastguard Worker       info.extent = iview->vk.extent;
356*61046927SAndroid Build Coastguard Worker 
357*61046927SAndroid Build Coastguard Worker       info.mip_levels = 1;
358*61046927SAndroid Build Coastguard Worker       info.mipmaps_present = false;
359*61046927SAndroid Build Coastguard Worker       info.stride = u_minify(image->physical_extent.width, info.base_level);
360*61046927SAndroid Build Coastguard Worker       info.base_level = 0;
361*61046927SAndroid Build Coastguard Worker       info.tex_state_type = PVR_TEXTURE_STATE_ATTACHMENT;
362*61046927SAndroid Build Coastguard Worker 
363*61046927SAndroid Build Coastguard Worker       if (image->vk.image_type == VK_IMAGE_TYPE_3D &&
364*61046927SAndroid Build Coastguard Worker           iview->vk.view_type == VK_IMAGE_VIEW_TYPE_2D) {
365*61046927SAndroid Build Coastguard Worker          info.type = VK_IMAGE_VIEW_TYPE_3D;
366*61046927SAndroid Build Coastguard Worker       } else {
367*61046927SAndroid Build Coastguard Worker          info.type = iview->vk.view_type;
368*61046927SAndroid Build Coastguard Worker       }
369*61046927SAndroid Build Coastguard Worker 
370*61046927SAndroid Build Coastguard Worker       result = pvr_pack_tex_state(device,
371*61046927SAndroid Build Coastguard Worker                                   &info,
372*61046927SAndroid Build Coastguard Worker                                   iview->texture_state[info.tex_state_type]);
373*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
374*61046927SAndroid Build Coastguard Worker          goto err_vk_image_view_destroy;
375*61046927SAndroid Build Coastguard Worker    }
376*61046927SAndroid Build Coastguard Worker 
377*61046927SAndroid Build Coastguard Worker    *pView = pvr_image_view_to_handle(iview);
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
380*61046927SAndroid Build Coastguard Worker 
381*61046927SAndroid Build Coastguard Worker err_vk_image_view_destroy:
382*61046927SAndroid Build Coastguard Worker    vk_image_view_destroy(&device->vk, pAllocator, &iview->vk);
383*61046927SAndroid Build Coastguard Worker 
384*61046927SAndroid Build Coastguard Worker    return result;
385*61046927SAndroid Build Coastguard Worker }
386*61046927SAndroid Build Coastguard Worker 
pvr_DestroyImageView(VkDevice _device,VkImageView _iview,const VkAllocationCallbacks * pAllocator)387*61046927SAndroid Build Coastguard Worker void pvr_DestroyImageView(VkDevice _device,
388*61046927SAndroid Build Coastguard Worker                           VkImageView _iview,
389*61046927SAndroid Build Coastguard Worker                           const VkAllocationCallbacks *pAllocator)
390*61046927SAndroid Build Coastguard Worker {
391*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_device, device, _device);
392*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_image_view, iview, _iview);
393*61046927SAndroid Build Coastguard Worker 
394*61046927SAndroid Build Coastguard Worker    if (!iview)
395*61046927SAndroid Build Coastguard Worker       return;
396*61046927SAndroid Build Coastguard Worker 
397*61046927SAndroid Build Coastguard Worker    vk_image_view_destroy(&device->vk, pAllocator, &iview->vk);
398*61046927SAndroid Build Coastguard Worker }
399*61046927SAndroid Build Coastguard Worker 
pvr_CreateBufferView(VkDevice _device,const VkBufferViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBufferView * pView)400*61046927SAndroid Build Coastguard Worker VkResult pvr_CreateBufferView(VkDevice _device,
401*61046927SAndroid Build Coastguard Worker                               const VkBufferViewCreateInfo *pCreateInfo,
402*61046927SAndroid Build Coastguard Worker                               const VkAllocationCallbacks *pAllocator,
403*61046927SAndroid Build Coastguard Worker                               VkBufferView *pView)
404*61046927SAndroid Build Coastguard Worker {
405*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_buffer, buffer, pCreateInfo->buffer);
406*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_device, device, _device);
407*61046927SAndroid Build Coastguard Worker    struct pvr_texture_state_info info;
408*61046927SAndroid Build Coastguard Worker    const uint8_t *format_swizzle;
409*61046927SAndroid Build Coastguard Worker    struct pvr_buffer_view *bview;
410*61046927SAndroid Build Coastguard Worker    VkResult result;
411*61046927SAndroid Build Coastguard Worker 
412*61046927SAndroid Build Coastguard Worker    bview = vk_object_alloc(&device->vk,
413*61046927SAndroid Build Coastguard Worker                            pAllocator,
414*61046927SAndroid Build Coastguard Worker                            sizeof(*bview),
415*61046927SAndroid Build Coastguard Worker                            VK_OBJECT_TYPE_BUFFER_VIEW);
416*61046927SAndroid Build Coastguard Worker    if (!bview)
417*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
418*61046927SAndroid Build Coastguard Worker 
419*61046927SAndroid Build Coastguard Worker    bview->format = pCreateInfo->format;
420*61046927SAndroid Build Coastguard Worker    bview->range =
421*61046927SAndroid Build Coastguard Worker       vk_buffer_range(&buffer->vk, pCreateInfo->offset, pCreateInfo->range);
422*61046927SAndroid Build Coastguard Worker 
423*61046927SAndroid Build Coastguard Worker    /* If the remaining size of the buffer is not a multiple of the element
424*61046927SAndroid Build Coastguard Worker     * size of the format, the nearest smaller multiple is used.
425*61046927SAndroid Build Coastguard Worker     */
426*61046927SAndroid Build Coastguard Worker    bview->range -= bview->range % vk_format_get_blocksize(bview->format);
427*61046927SAndroid Build Coastguard Worker 
428*61046927SAndroid Build Coastguard Worker    /* The range of the buffer view shouldn't be smaller than one texel. */
429*61046927SAndroid Build Coastguard Worker    assert(bview->range >= vk_format_get_blocksize(bview->format));
430*61046927SAndroid Build Coastguard Worker 
431*61046927SAndroid Build Coastguard Worker    info.base_level = 0U;
432*61046927SAndroid Build Coastguard Worker    info.mip_levels = 1U;
433*61046927SAndroid Build Coastguard Worker    info.mipmaps_present = false;
434*61046927SAndroid Build Coastguard Worker    info.extent.width = 8192U;
435*61046927SAndroid Build Coastguard Worker    info.extent.height = bview->range / vk_format_get_blocksize(bview->format);
436*61046927SAndroid Build Coastguard Worker    info.extent.height = DIV_ROUND_UP(info.extent.height, info.extent.width);
437*61046927SAndroid Build Coastguard Worker    info.extent.depth = 0U;
438*61046927SAndroid Build Coastguard Worker    info.sample_count = 1U;
439*61046927SAndroid Build Coastguard Worker    info.stride = info.extent.width;
440*61046927SAndroid Build Coastguard Worker    info.offset = 0U;
441*61046927SAndroid Build Coastguard Worker    info.addr = PVR_DEV_ADDR_OFFSET(buffer->dev_addr, pCreateInfo->offset);
442*61046927SAndroid Build Coastguard Worker    info.mem_layout = PVR_MEMLAYOUT_LINEAR;
443*61046927SAndroid Build Coastguard Worker    info.is_cube = false;
444*61046927SAndroid Build Coastguard Worker    info.type = VK_IMAGE_VIEW_TYPE_2D;
445*61046927SAndroid Build Coastguard Worker    info.tex_state_type = PVR_TEXTURE_STATE_SAMPLE;
446*61046927SAndroid Build Coastguard Worker    info.format = bview->format;
447*61046927SAndroid Build Coastguard Worker    info.flags = PVR_TEXFLAGS_INDEX_LOOKUP;
448*61046927SAndroid Build Coastguard Worker    info.aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT;
449*61046927SAndroid Build Coastguard Worker 
450*61046927SAndroid Build Coastguard Worker    if (PVR_HAS_FEATURE(&device->pdevice->dev_info, tpu_array_textures))
451*61046927SAndroid Build Coastguard Worker       info.array_size = 1U;
452*61046927SAndroid Build Coastguard Worker 
453*61046927SAndroid Build Coastguard Worker    format_swizzle = pvr_get_format_swizzle(info.format);
454*61046927SAndroid Build Coastguard Worker    memcpy(info.swizzle, format_swizzle, sizeof(info.swizzle));
455*61046927SAndroid Build Coastguard Worker 
456*61046927SAndroid Build Coastguard Worker    result = pvr_pack_tex_state(device, &info, bview->texture_state);
457*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
458*61046927SAndroid Build Coastguard Worker       goto err_vk_buffer_view_destroy;
459*61046927SAndroid Build Coastguard Worker 
460*61046927SAndroid Build Coastguard Worker    *pView = pvr_buffer_view_to_handle(bview);
461*61046927SAndroid Build Coastguard Worker 
462*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
463*61046927SAndroid Build Coastguard Worker 
464*61046927SAndroid Build Coastguard Worker err_vk_buffer_view_destroy:
465*61046927SAndroid Build Coastguard Worker    vk_object_free(&device->vk, pAllocator, bview);
466*61046927SAndroid Build Coastguard Worker 
467*61046927SAndroid Build Coastguard Worker    return result;
468*61046927SAndroid Build Coastguard Worker }
469*61046927SAndroid Build Coastguard Worker 
pvr_DestroyBufferView(VkDevice _device,VkBufferView bufferView,const VkAllocationCallbacks * pAllocator)470*61046927SAndroid Build Coastguard Worker void pvr_DestroyBufferView(VkDevice _device,
471*61046927SAndroid Build Coastguard Worker                            VkBufferView bufferView,
472*61046927SAndroid Build Coastguard Worker                            const VkAllocationCallbacks *pAllocator)
473*61046927SAndroid Build Coastguard Worker {
474*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_buffer_view, bview, bufferView);
475*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_device, device, _device);
476*61046927SAndroid Build Coastguard Worker 
477*61046927SAndroid Build Coastguard Worker    if (!bview)
478*61046927SAndroid Build Coastguard Worker       return;
479*61046927SAndroid Build Coastguard Worker 
480*61046927SAndroid Build Coastguard Worker    vk_object_free(&device->vk, pAllocator, bview);
481*61046927SAndroid Build Coastguard Worker }
482