1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2022 Imagination Technologies Ltd.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * based in part on anv driver which is:
5bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation
6bf215546Sopenharmony_ci *
7bf215546Sopenharmony_ci * based in part on v3dv driver which is:
8bf215546Sopenharmony_ci * Copyright © 2019 Raspberry Pi
9bf215546Sopenharmony_ci *
10bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
11bf215546Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal
12bf215546Sopenharmony_ci * in the Software without restriction, including without limitation the rights
13bf215546Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14bf215546Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is
15bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions:
16bf215546Sopenharmony_ci *
17bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
18bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
19bf215546Sopenharmony_ci * Software.
20bf215546Sopenharmony_ci *
21bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24bf215546Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27bf215546Sopenharmony_ci * SOFTWARE.
28bf215546Sopenharmony_ci */
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include <assert.h>
31bf215546Sopenharmony_ci#include <fcntl.h>
32bf215546Sopenharmony_ci#include <inttypes.h>
33bf215546Sopenharmony_ci#include <stdbool.h>
34bf215546Sopenharmony_ci#include <stddef.h>
35bf215546Sopenharmony_ci#include <stdint.h>
36bf215546Sopenharmony_ci#include <stdlib.h>
37bf215546Sopenharmony_ci#include <string.h>
38bf215546Sopenharmony_ci#include <vulkan/vulkan.h>
39bf215546Sopenharmony_ci#include <xf86drm.h>
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci#include "hwdef/rogue_hw_utils.h"
42bf215546Sopenharmony_ci#include "pipe/p_defines.h"
43bf215546Sopenharmony_ci#include "pvr_bo.h"
44bf215546Sopenharmony_ci#include "pvr_csb.h"
45bf215546Sopenharmony_ci#include "pvr_csb_enum_helpers.h"
46bf215546Sopenharmony_ci#include "pvr_debug.h"
47bf215546Sopenharmony_ci#include "pvr_device_info.h"
48bf215546Sopenharmony_ci#include "pvr_hardcode.h"
49bf215546Sopenharmony_ci#include "pvr_job_render.h"
50bf215546Sopenharmony_ci#include "pvr_limits.h"
51bf215546Sopenharmony_ci#include "pvr_nop_usc.h"
52bf215546Sopenharmony_ci#include "pvr_pds.h"
53bf215546Sopenharmony_ci#include "pvr_private.h"
54bf215546Sopenharmony_ci#include "pvr_tex_state.h"
55bf215546Sopenharmony_ci#include "pvr_types.h"
56bf215546Sopenharmony_ci#include "pvr_winsys.h"
57bf215546Sopenharmony_ci#include "rogue/rogue_compiler.h"
58bf215546Sopenharmony_ci#include "util/build_id.h"
59bf215546Sopenharmony_ci#include "util/log.h"
60bf215546Sopenharmony_ci#include "util/mesa-sha1.h"
61bf215546Sopenharmony_ci#include "util/os_misc.h"
62bf215546Sopenharmony_ci#include "util/u_math.h"
63bf215546Sopenharmony_ci#include "vk_alloc.h"
64bf215546Sopenharmony_ci#include "vk_log.h"
65bf215546Sopenharmony_ci#include "vk_object.h"
66bf215546Sopenharmony_ci#include "vk_util.h"
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci#define PVR_GLOBAL_FREE_LIST_INITIAL_SIZE (2U * 1024U * 1024U)
69bf215546Sopenharmony_ci#define PVR_GLOBAL_FREE_LIST_MAX_SIZE (256U * 1024U * 1024U)
70bf215546Sopenharmony_ci#define PVR_GLOBAL_FREE_LIST_GROW_SIZE (1U * 1024U * 1024U)
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci/* The grow threshold is a percentage. This is intended to be 12.5%, but has
73bf215546Sopenharmony_ci * been rounded up since the percentage is treated as an integer.
74bf215546Sopenharmony_ci */
75bf215546Sopenharmony_ci#define PVR_GLOBAL_FREE_LIST_GROW_THRESHOLD 13U
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_ci#if defined(VK_USE_PLATFORM_DISPLAY_KHR)
78bf215546Sopenharmony_ci#   define PVR_USE_WSI_PLATFORM
79bf215546Sopenharmony_ci#endif
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci#define PVR_API_VERSION VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION)
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci#define DEF_DRIVER(str_name)                        \
84bf215546Sopenharmony_ci   {                                                \
85bf215546Sopenharmony_ci      .name = str_name, .len = sizeof(str_name) - 1 \
86bf215546Sopenharmony_ci   }
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_cistruct pvr_drm_device_info {
89bf215546Sopenharmony_ci   const char *name;
90bf215546Sopenharmony_ci   size_t len;
91bf215546Sopenharmony_ci};
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci/* This is the list of supported DRM display drivers. */
94bf215546Sopenharmony_cistatic const struct pvr_drm_device_info pvr_display_devices[] = {
95bf215546Sopenharmony_ci   DEF_DRIVER("mediatek-drm"),
96bf215546Sopenharmony_ci   DEF_DRIVER("ti,am65x-dss"),
97bf215546Sopenharmony_ci};
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci/* This is the list of supported DRM render drivers. */
100bf215546Sopenharmony_cistatic const struct pvr_drm_device_info pvr_render_devices[] = {
101bf215546Sopenharmony_ci   DEF_DRIVER("mediatek,mt8173-gpu"),
102bf215546Sopenharmony_ci   DEF_DRIVER("ti,am62-gpu"),
103bf215546Sopenharmony_ci};
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci#undef DEF_DRIVER
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_cistatic const struct vk_instance_extension_table pvr_instance_extensions = {
108bf215546Sopenharmony_ci#if defined(VK_USE_PLATFORM_DISPLAY_KHR)
109bf215546Sopenharmony_ci   .KHR_display = true,
110bf215546Sopenharmony_ci#endif
111bf215546Sopenharmony_ci   .KHR_external_memory_capabilities = true,
112bf215546Sopenharmony_ci   .KHR_get_physical_device_properties2 = true,
113bf215546Sopenharmony_ci#if defined(PVR_USE_WSI_PLATFORM)
114bf215546Sopenharmony_ci   .KHR_surface = true,
115bf215546Sopenharmony_ci#endif
116bf215546Sopenharmony_ci   .EXT_debug_report = true,
117bf215546Sopenharmony_ci   .EXT_debug_utils = true,
118bf215546Sopenharmony_ci};
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_cistatic void pvr_physical_device_get_supported_extensions(
121bf215546Sopenharmony_ci   const struct pvr_physical_device *pdevice,
122bf215546Sopenharmony_ci   struct vk_device_extension_table *extensions)
123bf215546Sopenharmony_ci{
124bf215546Sopenharmony_ci   /* clang-format off */
125bf215546Sopenharmony_ci   *extensions = (struct vk_device_extension_table){
126bf215546Sopenharmony_ci      .KHR_external_memory = true,
127bf215546Sopenharmony_ci      .KHR_external_memory_fd = true,
128bf215546Sopenharmony_ci#if defined(PVR_USE_WSI_PLATFORM)
129bf215546Sopenharmony_ci      .KHR_swapchain = true,
130bf215546Sopenharmony_ci#endif
131bf215546Sopenharmony_ci      .EXT_external_memory_dma_buf = true,
132bf215546Sopenharmony_ci      .EXT_private_data = true,
133bf215546Sopenharmony_ci   };
134bf215546Sopenharmony_ci   /* clang-format on */
135bf215546Sopenharmony_ci}
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ciVkResult pvr_EnumerateInstanceVersion(uint32_t *pApiVersion)
138bf215546Sopenharmony_ci{
139bf215546Sopenharmony_ci   *pApiVersion = PVR_API_VERSION;
140bf215546Sopenharmony_ci   return VK_SUCCESS;
141bf215546Sopenharmony_ci}
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ciVkResult
144bf215546Sopenharmony_cipvr_EnumerateInstanceExtensionProperties(const char *pLayerName,
145bf215546Sopenharmony_ci                                         uint32_t *pPropertyCount,
146bf215546Sopenharmony_ci                                         VkExtensionProperties *pProperties)
147bf215546Sopenharmony_ci{
148bf215546Sopenharmony_ci   if (pLayerName)
149bf215546Sopenharmony_ci      return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci   return vk_enumerate_instance_extension_properties(&pvr_instance_extensions,
152bf215546Sopenharmony_ci                                                     pPropertyCount,
153bf215546Sopenharmony_ci                                                     pProperties);
154bf215546Sopenharmony_ci}
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ciVkResult pvr_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
157bf215546Sopenharmony_ci                            const VkAllocationCallbacks *pAllocator,
158bf215546Sopenharmony_ci                            VkInstance *pInstance)
159bf215546Sopenharmony_ci{
160bf215546Sopenharmony_ci   struct vk_instance_dispatch_table dispatch_table;
161bf215546Sopenharmony_ci   struct pvr_instance *instance;
162bf215546Sopenharmony_ci   VkResult result;
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci   if (!pAllocator)
167bf215546Sopenharmony_ci      pAllocator = vk_default_allocator();
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci   instance = vk_alloc(pAllocator,
170bf215546Sopenharmony_ci                       sizeof(*instance),
171bf215546Sopenharmony_ci                       8,
172bf215546Sopenharmony_ci                       VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
173bf215546Sopenharmony_ci   if (!instance)
174bf215546Sopenharmony_ci      return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci   vk_instance_dispatch_table_from_entrypoints(&dispatch_table,
177bf215546Sopenharmony_ci                                               &pvr_instance_entrypoints,
178bf215546Sopenharmony_ci                                               true);
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci   vk_instance_dispatch_table_from_entrypoints(&dispatch_table,
181bf215546Sopenharmony_ci                                               &wsi_instance_entrypoints,
182bf215546Sopenharmony_ci                                               false);
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci   result = vk_instance_init(&instance->vk,
185bf215546Sopenharmony_ci                             &pvr_instance_extensions,
186bf215546Sopenharmony_ci                             &dispatch_table,
187bf215546Sopenharmony_ci                             pCreateInfo,
188bf215546Sopenharmony_ci                             pAllocator);
189bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
190bf215546Sopenharmony_ci      vk_free(pAllocator, instance);
191bf215546Sopenharmony_ci      return vk_error(NULL, result);
192bf215546Sopenharmony_ci   }
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci   pvr_process_debug_variable();
195bf215546Sopenharmony_ci
196bf215546Sopenharmony_ci   instance->physical_devices_count = -1;
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_ci   VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci   *pInstance = pvr_instance_to_handle(instance);
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci   return VK_SUCCESS;
203bf215546Sopenharmony_ci}
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_cistatic void pvr_physical_device_finish(struct pvr_physical_device *pdevice)
206bf215546Sopenharmony_ci{
207bf215546Sopenharmony_ci   /* Be careful here. The device might not have been initialized. This can
208bf215546Sopenharmony_ci    * happen since initialization is done in vkEnumeratePhysicalDevices() but
209bf215546Sopenharmony_ci    * finish is done in vkDestroyInstance(). Make sure that you check for NULL
210bf215546Sopenharmony_ci    * before freeing or that the freeing functions accept NULL pointers.
211bf215546Sopenharmony_ci    */
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci   if (pdevice->compiler)
214bf215546Sopenharmony_ci      rogue_compiler_destroy(pdevice->compiler);
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci   pvr_wsi_finish(pdevice);
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci   free(pdevice->name);
219bf215546Sopenharmony_ci
220bf215546Sopenharmony_ci   if (pdevice->ws)
221bf215546Sopenharmony_ci      pvr_winsys_destroy(pdevice->ws);
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci   if (pdevice->master_fd >= 0) {
224bf215546Sopenharmony_ci      vk_free(&pdevice->vk.instance->alloc, pdevice->master_path);
225bf215546Sopenharmony_ci      close(pdevice->master_fd);
226bf215546Sopenharmony_ci   }
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci   if (pdevice->render_fd >= 0) {
229bf215546Sopenharmony_ci      vk_free(&pdevice->vk.instance->alloc, pdevice->render_path);
230bf215546Sopenharmony_ci      close(pdevice->render_fd);
231bf215546Sopenharmony_ci   }
232bf215546Sopenharmony_ci   vk_physical_device_finish(&pdevice->vk);
233bf215546Sopenharmony_ci}
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_civoid pvr_DestroyInstance(VkInstance _instance,
236bf215546Sopenharmony_ci                         const VkAllocationCallbacks *pAllocator)
237bf215546Sopenharmony_ci{
238bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_instance, instance, _instance);
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_ci   if (!instance)
241bf215546Sopenharmony_ci      return;
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci   pvr_physical_device_finish(&instance->physical_device);
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci   VG(VALGRIND_DESTROY_MEMPOOL(instance));
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_ci   vk_instance_finish(&instance->vk);
248bf215546Sopenharmony_ci   vk_free(&instance->vk.alloc, instance);
249bf215546Sopenharmony_ci}
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_cistatic VkResult
252bf215546Sopenharmony_cipvr_physical_device_init_uuids(struct pvr_physical_device *pdevice)
253bf215546Sopenharmony_ci{
254bf215546Sopenharmony_ci   struct mesa_sha1 sha1_ctx;
255bf215546Sopenharmony_ci   unsigned build_id_len;
256bf215546Sopenharmony_ci   uint8_t sha1[20];
257bf215546Sopenharmony_ci   uint64_t bvnc;
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci   const struct build_id_note *note =
260bf215546Sopenharmony_ci      build_id_find_nhdr_for_addr(pvr_physical_device_init_uuids);
261bf215546Sopenharmony_ci   if (!note) {
262bf215546Sopenharmony_ci      return vk_errorf(pdevice,
263bf215546Sopenharmony_ci                       VK_ERROR_INITIALIZATION_FAILED,
264bf215546Sopenharmony_ci                       "Failed to find build-id");
265bf215546Sopenharmony_ci   }
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_ci   build_id_len = build_id_length(note);
268bf215546Sopenharmony_ci   if (build_id_len < 20) {
269bf215546Sopenharmony_ci      return vk_errorf(pdevice,
270bf215546Sopenharmony_ci                       VK_ERROR_INITIALIZATION_FAILED,
271bf215546Sopenharmony_ci                       "Build-id too short. It needs to be a SHA");
272bf215546Sopenharmony_ci   }
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci   bvnc = pvr_get_packed_bvnc(&pdevice->dev_info);
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_ci   _mesa_sha1_init(&sha1_ctx);
277bf215546Sopenharmony_ci   _mesa_sha1_update(&sha1_ctx, build_id_data(note), build_id_len);
278bf215546Sopenharmony_ci   _mesa_sha1_update(&sha1_ctx, &bvnc, sizeof(bvnc));
279bf215546Sopenharmony_ci   _mesa_sha1_final(&sha1_ctx, sha1);
280bf215546Sopenharmony_ci   memcpy(pdevice->pipeline_cache_uuid, sha1, VK_UUID_SIZE);
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_ci   return VK_SUCCESS;
283bf215546Sopenharmony_ci}
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_cistatic uint64_t pvr_compute_heap_size(void)
286bf215546Sopenharmony_ci{
287bf215546Sopenharmony_ci   /* Query the total ram from the system */
288bf215546Sopenharmony_ci   uint64_t total_ram;
289bf215546Sopenharmony_ci   if (!os_get_total_physical_memory(&total_ram))
290bf215546Sopenharmony_ci      return 0;
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci   /* We don't want to burn too much ram with the GPU. If the user has 4GiB
293bf215546Sopenharmony_ci    * or less, we use at most half. If they have more than 4GiB, we use 3/4.
294bf215546Sopenharmony_ci    */
295bf215546Sopenharmony_ci   uint64_t available_ram;
296bf215546Sopenharmony_ci   if (total_ram <= 4ULL * 1024ULL * 1024ULL * 1024ULL)
297bf215546Sopenharmony_ci      available_ram = total_ram / 2U;
298bf215546Sopenharmony_ci   else
299bf215546Sopenharmony_ci      available_ram = total_ram * 3U / 4U;
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci   return available_ram;
302bf215546Sopenharmony_ci}
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_cistatic VkResult pvr_physical_device_init(struct pvr_physical_device *pdevice,
305bf215546Sopenharmony_ci                                         struct pvr_instance *instance,
306bf215546Sopenharmony_ci                                         drmDevicePtr drm_render_device,
307bf215546Sopenharmony_ci                                         drmDevicePtr drm_primary_device)
308bf215546Sopenharmony_ci{
309bf215546Sopenharmony_ci   const char *path = drm_render_device->nodes[DRM_NODE_RENDER];
310bf215546Sopenharmony_ci   struct vk_device_extension_table supported_extensions;
311bf215546Sopenharmony_ci   struct vk_physical_device_dispatch_table dispatch_table;
312bf215546Sopenharmony_ci   const char *primary_path;
313bf215546Sopenharmony_ci   VkResult result;
314bf215546Sopenharmony_ci   int ret;
315bf215546Sopenharmony_ci
316bf215546Sopenharmony_ci   if (!getenv("PVR_I_WANT_A_BROKEN_VULKAN_DRIVER")) {
317bf215546Sopenharmony_ci      return vk_errorf(instance,
318bf215546Sopenharmony_ci                       VK_ERROR_INCOMPATIBLE_DRIVER,
319bf215546Sopenharmony_ci                       "WARNING: powervr is not a conformant Vulkan "
320bf215546Sopenharmony_ci                       "implementation. Pass "
321bf215546Sopenharmony_ci                       "PVR_I_WANT_A_BROKEN_VULKAN_DRIVER=1 if you know "
322bf215546Sopenharmony_ci                       "what you're doing.");
323bf215546Sopenharmony_ci   }
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_ci   pvr_physical_device_get_supported_extensions(pdevice, &supported_extensions);
326bf215546Sopenharmony_ci
327bf215546Sopenharmony_ci   vk_physical_device_dispatch_table_from_entrypoints(
328bf215546Sopenharmony_ci      &dispatch_table,
329bf215546Sopenharmony_ci      &pvr_physical_device_entrypoints,
330bf215546Sopenharmony_ci      true);
331bf215546Sopenharmony_ci
332bf215546Sopenharmony_ci   vk_physical_device_dispatch_table_from_entrypoints(
333bf215546Sopenharmony_ci      &dispatch_table,
334bf215546Sopenharmony_ci      &wsi_physical_device_entrypoints,
335bf215546Sopenharmony_ci      false);
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_ci   result = vk_physical_device_init(&pdevice->vk,
338bf215546Sopenharmony_ci                                    &instance->vk,
339bf215546Sopenharmony_ci                                    &supported_extensions,
340bf215546Sopenharmony_ci                                    &dispatch_table);
341bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
342bf215546Sopenharmony_ci      return result;
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci   pdevice->instance = instance;
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci   pdevice->render_fd = open(path, O_RDWR | O_CLOEXEC);
347bf215546Sopenharmony_ci   if (pdevice->render_fd < 0) {
348bf215546Sopenharmony_ci      result = vk_errorf(instance,
349bf215546Sopenharmony_ci                         VK_ERROR_INCOMPATIBLE_DRIVER,
350bf215546Sopenharmony_ci                         "Failed to open device %s",
351bf215546Sopenharmony_ci                         path);
352bf215546Sopenharmony_ci      goto err_vk_physical_device_finish;
353bf215546Sopenharmony_ci   }
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci   pdevice->render_path = vk_strdup(&pdevice->vk.instance->alloc,
356bf215546Sopenharmony_ci                                    path,
357bf215546Sopenharmony_ci                                    VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
358bf215546Sopenharmony_ci   if (!pdevice->render_path) {
359bf215546Sopenharmony_ci      result = VK_ERROR_OUT_OF_HOST_MEMORY;
360bf215546Sopenharmony_ci      goto err_close_render_fd;
361bf215546Sopenharmony_ci   }
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_ci   if (instance->vk.enabled_extensions.KHR_display) {
364bf215546Sopenharmony_ci      primary_path = drm_primary_device->nodes[DRM_NODE_PRIMARY];
365bf215546Sopenharmony_ci
366bf215546Sopenharmony_ci      pdevice->master_fd = open(primary_path, O_RDWR | O_CLOEXEC);
367bf215546Sopenharmony_ci   } else {
368bf215546Sopenharmony_ci      pdevice->master_fd = -1;
369bf215546Sopenharmony_ci   }
370bf215546Sopenharmony_ci
371bf215546Sopenharmony_ci   if (pdevice->master_fd >= 0) {
372bf215546Sopenharmony_ci      pdevice->master_path = vk_strdup(&pdevice->vk.instance->alloc,
373bf215546Sopenharmony_ci                                       primary_path,
374bf215546Sopenharmony_ci                                       VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
375bf215546Sopenharmony_ci      if (!pdevice->master_path) {
376bf215546Sopenharmony_ci         result = VK_ERROR_OUT_OF_HOST_MEMORY;
377bf215546Sopenharmony_ci         goto err_close_master_fd;
378bf215546Sopenharmony_ci      }
379bf215546Sopenharmony_ci   } else {
380bf215546Sopenharmony_ci      pdevice->master_path = NULL;
381bf215546Sopenharmony_ci   }
382bf215546Sopenharmony_ci
383bf215546Sopenharmony_ci   pdevice->ws = pvr_winsys_create(pdevice->master_fd,
384bf215546Sopenharmony_ci                                   pdevice->render_fd,
385bf215546Sopenharmony_ci                                   &pdevice->vk.instance->alloc);
386bf215546Sopenharmony_ci   if (!pdevice->ws) {
387bf215546Sopenharmony_ci      result = VK_ERROR_INITIALIZATION_FAILED;
388bf215546Sopenharmony_ci      goto err_vk_free_master_path;
389bf215546Sopenharmony_ci   }
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci   pdevice->vk.supported_sync_types = pdevice->ws->sync_types;
392bf215546Sopenharmony_ci
393bf215546Sopenharmony_ci   ret = pdevice->ws->ops->device_info_init(pdevice->ws,
394bf215546Sopenharmony_ci                                            &pdevice->dev_info,
395bf215546Sopenharmony_ci                                            &pdevice->dev_runtime_info);
396bf215546Sopenharmony_ci   if (ret) {
397bf215546Sopenharmony_ci      result = VK_ERROR_INITIALIZATION_FAILED;
398bf215546Sopenharmony_ci      goto err_pvr_winsys_destroy;
399bf215546Sopenharmony_ci   }
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci   result = pvr_physical_device_init_uuids(pdevice);
402bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
403bf215546Sopenharmony_ci      goto err_pvr_winsys_destroy;
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_ci   if (asprintf(&pdevice->name,
406bf215546Sopenharmony_ci                "Imagination PowerVR %s %s",
407bf215546Sopenharmony_ci                pdevice->dev_info.ident.series_name,
408bf215546Sopenharmony_ci                pdevice->dev_info.ident.public_name) < 0) {
409bf215546Sopenharmony_ci      result = vk_errorf(instance,
410bf215546Sopenharmony_ci                         VK_ERROR_OUT_OF_HOST_MEMORY,
411bf215546Sopenharmony_ci                         "Unable to allocate memory to store device name");
412bf215546Sopenharmony_ci      goto err_pvr_winsys_destroy;
413bf215546Sopenharmony_ci   }
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_ci   /* Setup available memory heaps and types */
416bf215546Sopenharmony_ci   pdevice->memory.memoryHeapCount = 1;
417bf215546Sopenharmony_ci   pdevice->memory.memoryHeaps[0].size = pvr_compute_heap_size();
418bf215546Sopenharmony_ci   pdevice->memory.memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
419bf215546Sopenharmony_ci
420bf215546Sopenharmony_ci   pdevice->memory.memoryTypeCount = 1;
421bf215546Sopenharmony_ci   pdevice->memory.memoryTypes[0].propertyFlags =
422bf215546Sopenharmony_ci      VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
423bf215546Sopenharmony_ci      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
424bf215546Sopenharmony_ci      VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
425bf215546Sopenharmony_ci   pdevice->memory.memoryTypes[0].heapIndex = 0;
426bf215546Sopenharmony_ci
427bf215546Sopenharmony_ci   result = pvr_wsi_init(pdevice);
428bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
429bf215546Sopenharmony_ci      vk_error(instance, result);
430bf215546Sopenharmony_ci      goto err_free_name;
431bf215546Sopenharmony_ci   }
432bf215546Sopenharmony_ci
433bf215546Sopenharmony_ci   pdevice->compiler = rogue_compiler_create(&pdevice->dev_info);
434bf215546Sopenharmony_ci   if (!pdevice->compiler) {
435bf215546Sopenharmony_ci      result = vk_errorf(instance,
436bf215546Sopenharmony_ci                         VK_ERROR_INITIALIZATION_FAILED,
437bf215546Sopenharmony_ci                         "Failed to initialize Rogue compiler");
438bf215546Sopenharmony_ci      goto err_wsi_finish;
439bf215546Sopenharmony_ci   }
440bf215546Sopenharmony_ci
441bf215546Sopenharmony_ci   return VK_SUCCESS;
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_cierr_wsi_finish:
444bf215546Sopenharmony_ci   pvr_wsi_finish(pdevice);
445bf215546Sopenharmony_ci
446bf215546Sopenharmony_cierr_free_name:
447bf215546Sopenharmony_ci   free(pdevice->name);
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_cierr_pvr_winsys_destroy:
450bf215546Sopenharmony_ci   pvr_winsys_destroy(pdevice->ws);
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_cierr_vk_free_master_path:
453bf215546Sopenharmony_ci   vk_free(&pdevice->vk.instance->alloc, pdevice->master_path);
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_cierr_close_master_fd:
456bf215546Sopenharmony_ci   if (pdevice->master_fd >= 0)
457bf215546Sopenharmony_ci      close(pdevice->master_fd);
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_ci   vk_free(&pdevice->vk.instance->alloc, pdevice->render_path);
460bf215546Sopenharmony_ci
461bf215546Sopenharmony_cierr_close_render_fd:
462bf215546Sopenharmony_ci   close(pdevice->render_fd);
463bf215546Sopenharmony_ci
464bf215546Sopenharmony_cierr_vk_physical_device_finish:
465bf215546Sopenharmony_ci   vk_physical_device_finish(&pdevice->vk);
466bf215546Sopenharmony_ci
467bf215546Sopenharmony_ci   return result;
468bf215546Sopenharmony_ci}
469bf215546Sopenharmony_ci
470bf215546Sopenharmony_cistatic bool pvr_drm_device_is_supported(drmDevicePtr drm_dev, int node_type)
471bf215546Sopenharmony_ci{
472bf215546Sopenharmony_ci   char **compat = drm_dev->deviceinfo.platform->compatible;
473bf215546Sopenharmony_ci
474bf215546Sopenharmony_ci   if (!(drm_dev->available_nodes & BITFIELD_BIT(node_type))) {
475bf215546Sopenharmony_ci      assert(node_type == DRM_NODE_RENDER || node_type == DRM_NODE_PRIMARY);
476bf215546Sopenharmony_ci      return false;
477bf215546Sopenharmony_ci   }
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci   if (node_type == DRM_NODE_RENDER) {
480bf215546Sopenharmony_ci      while (*compat) {
481bf215546Sopenharmony_ci         for (size_t i = 0U; i < ARRAY_SIZE(pvr_render_devices); i++) {
482bf215546Sopenharmony_ci            const char *const name = pvr_render_devices[i].name;
483bf215546Sopenharmony_ci            const size_t len = pvr_render_devices[i].len;
484bf215546Sopenharmony_ci
485bf215546Sopenharmony_ci            if (strncmp(*compat, name, len) == 0)
486bf215546Sopenharmony_ci               return true;
487bf215546Sopenharmony_ci         }
488bf215546Sopenharmony_ci
489bf215546Sopenharmony_ci         compat++;
490bf215546Sopenharmony_ci      }
491bf215546Sopenharmony_ci
492bf215546Sopenharmony_ci      return false;
493bf215546Sopenharmony_ci   } else if (node_type == DRM_NODE_PRIMARY) {
494bf215546Sopenharmony_ci      while (*compat) {
495bf215546Sopenharmony_ci         for (size_t i = 0U; i < ARRAY_SIZE(pvr_display_devices); i++) {
496bf215546Sopenharmony_ci            const char *const name = pvr_display_devices[i].name;
497bf215546Sopenharmony_ci            const size_t len = pvr_display_devices[i].len;
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_ci            if (strncmp(*compat, name, len) == 0)
500bf215546Sopenharmony_ci               return true;
501bf215546Sopenharmony_ci         }
502bf215546Sopenharmony_ci
503bf215546Sopenharmony_ci         compat++;
504bf215546Sopenharmony_ci      }
505bf215546Sopenharmony_ci
506bf215546Sopenharmony_ci      return false;
507bf215546Sopenharmony_ci   }
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci   unreachable("Incorrect node_type.");
510bf215546Sopenharmony_ci}
511bf215546Sopenharmony_ci
512bf215546Sopenharmony_cistatic VkResult pvr_enumerate_devices(struct pvr_instance *instance)
513bf215546Sopenharmony_ci{
514bf215546Sopenharmony_ci   /* FIXME: It should be possible to query the number of devices via
515bf215546Sopenharmony_ci    * drmGetDevices2 by passing in NULL for the 'devices' parameter. However,
516bf215546Sopenharmony_ci    * this was broken by libdrm commit
517bf215546Sopenharmony_ci    * 8cb12a2528d795c45bba5f03b3486b4040fb0f45, so, until this is fixed in
518bf215546Sopenharmony_ci    * upstream, hard-code the maximum number of devices.
519bf215546Sopenharmony_ci    */
520bf215546Sopenharmony_ci   drmDevicePtr drm_primary_device = NULL;
521bf215546Sopenharmony_ci   drmDevicePtr drm_render_device = NULL;
522bf215546Sopenharmony_ci   drmDevicePtr drm_devices[8];
523bf215546Sopenharmony_ci   int max_drm_devices;
524bf215546Sopenharmony_ci   VkResult result;
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_ci   instance->physical_devices_count = 0;
527bf215546Sopenharmony_ci
528bf215546Sopenharmony_ci   max_drm_devices = drmGetDevices2(0, drm_devices, ARRAY_SIZE(drm_devices));
529bf215546Sopenharmony_ci   if (max_drm_devices < 1)
530bf215546Sopenharmony_ci      return VK_SUCCESS;
531bf215546Sopenharmony_ci
532bf215546Sopenharmony_ci   for (unsigned i = 0; i < (unsigned)max_drm_devices; i++) {
533bf215546Sopenharmony_ci      if (drm_devices[i]->bustype != DRM_BUS_PLATFORM)
534bf215546Sopenharmony_ci         continue;
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci      if (pvr_drm_device_is_supported(drm_devices[i], DRM_NODE_RENDER)) {
537bf215546Sopenharmony_ci         drm_render_device = drm_devices[i];
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_ci         mesa_logd("Found compatible render device '%s'.",
540bf215546Sopenharmony_ci                   drm_render_device->nodes[DRM_NODE_RENDER]);
541bf215546Sopenharmony_ci      } else if (pvr_drm_device_is_supported(drm_devices[i],
542bf215546Sopenharmony_ci                                             DRM_NODE_PRIMARY)) {
543bf215546Sopenharmony_ci         drm_primary_device = drm_devices[i];
544bf215546Sopenharmony_ci
545bf215546Sopenharmony_ci         mesa_logd("Found compatible primary device '%s'.",
546bf215546Sopenharmony_ci                   drm_primary_device->nodes[DRM_NODE_PRIMARY]);
547bf215546Sopenharmony_ci      }
548bf215546Sopenharmony_ci   }
549bf215546Sopenharmony_ci
550bf215546Sopenharmony_ci   if (drm_render_device && drm_primary_device) {
551bf215546Sopenharmony_ci      result = pvr_physical_device_init(&instance->physical_device,
552bf215546Sopenharmony_ci                                        instance,
553bf215546Sopenharmony_ci                                        drm_render_device,
554bf215546Sopenharmony_ci                                        drm_primary_device);
555bf215546Sopenharmony_ci      if (result == VK_SUCCESS)
556bf215546Sopenharmony_ci         instance->physical_devices_count = 1;
557bf215546Sopenharmony_ci      else if (result == VK_ERROR_INCOMPATIBLE_DRIVER)
558bf215546Sopenharmony_ci         result = VK_SUCCESS;
559bf215546Sopenharmony_ci   } else {
560bf215546Sopenharmony_ci      result = VK_SUCCESS;
561bf215546Sopenharmony_ci   }
562bf215546Sopenharmony_ci
563bf215546Sopenharmony_ci   drmFreeDevices(drm_devices, max_drm_devices);
564bf215546Sopenharmony_ci
565bf215546Sopenharmony_ci   return result;
566bf215546Sopenharmony_ci}
567bf215546Sopenharmony_ci
568bf215546Sopenharmony_ciVkResult pvr_EnumeratePhysicalDevices(VkInstance _instance,
569bf215546Sopenharmony_ci                                      uint32_t *pPhysicalDeviceCount,
570bf215546Sopenharmony_ci                                      VkPhysicalDevice *pPhysicalDevices)
571bf215546Sopenharmony_ci{
572bf215546Sopenharmony_ci   VK_OUTARRAY_MAKE_TYPED(VkPhysicalDevice,
573bf215546Sopenharmony_ci                          out,
574bf215546Sopenharmony_ci                          pPhysicalDevices,
575bf215546Sopenharmony_ci                          pPhysicalDeviceCount);
576bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_instance, instance, _instance);
577bf215546Sopenharmony_ci   VkResult result;
578bf215546Sopenharmony_ci
579bf215546Sopenharmony_ci   if (instance->physical_devices_count < 0) {
580bf215546Sopenharmony_ci      result = pvr_enumerate_devices(instance);
581bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
582bf215546Sopenharmony_ci         return result;
583bf215546Sopenharmony_ci   }
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ci   if (instance->physical_devices_count == 0)
586bf215546Sopenharmony_ci      return VK_SUCCESS;
587bf215546Sopenharmony_ci
588bf215546Sopenharmony_ci   assert(instance->physical_devices_count == 1);
589bf215546Sopenharmony_ci   vk_outarray_append_typed (VkPhysicalDevice, &out, p) {
590bf215546Sopenharmony_ci      *p = pvr_physical_device_to_handle(&instance->physical_device);
591bf215546Sopenharmony_ci   }
592bf215546Sopenharmony_ci
593bf215546Sopenharmony_ci   return vk_outarray_status(&out);
594bf215546Sopenharmony_ci}
595bf215546Sopenharmony_ci
596bf215546Sopenharmony_civoid pvr_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
597bf215546Sopenharmony_ci                                    VkPhysicalDeviceFeatures2 *pFeatures)
598bf215546Sopenharmony_ci{
599bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_physical_device, pdevice, physicalDevice);
600bf215546Sopenharmony_ci
601bf215546Sopenharmony_ci   pFeatures->features = (VkPhysicalDeviceFeatures){
602bf215546Sopenharmony_ci      .robustBufferAccess =
603bf215546Sopenharmony_ci         PVR_HAS_FEATURE(&pdevice->dev_info, robust_buffer_access),
604bf215546Sopenharmony_ci      .fullDrawIndexUint32 = true,
605bf215546Sopenharmony_ci      .imageCubeArray = true,
606bf215546Sopenharmony_ci      .independentBlend = true,
607bf215546Sopenharmony_ci      .geometryShader = false,
608bf215546Sopenharmony_ci      .tessellationShader = false,
609bf215546Sopenharmony_ci      .sampleRateShading = true,
610bf215546Sopenharmony_ci      .dualSrcBlend = false,
611bf215546Sopenharmony_ci      .logicOp = true,
612bf215546Sopenharmony_ci      .multiDrawIndirect = true,
613bf215546Sopenharmony_ci      .drawIndirectFirstInstance = true,
614bf215546Sopenharmony_ci      .depthClamp = true,
615bf215546Sopenharmony_ci      .depthBiasClamp = true,
616bf215546Sopenharmony_ci      .fillModeNonSolid = false,
617bf215546Sopenharmony_ci      .depthBounds = false,
618bf215546Sopenharmony_ci      .wideLines = true,
619bf215546Sopenharmony_ci      .largePoints = true,
620bf215546Sopenharmony_ci      .alphaToOne = true,
621bf215546Sopenharmony_ci      .multiViewport = false,
622bf215546Sopenharmony_ci      .samplerAnisotropy = true,
623bf215546Sopenharmony_ci      .textureCompressionETC2 = true,
624bf215546Sopenharmony_ci      .textureCompressionASTC_LDR = PVR_HAS_FEATURE(&pdevice->dev_info, astc),
625bf215546Sopenharmony_ci      .textureCompressionBC = false,
626bf215546Sopenharmony_ci      .occlusionQueryPrecise = true,
627bf215546Sopenharmony_ci      .pipelineStatisticsQuery = false,
628bf215546Sopenharmony_ci      .vertexPipelineStoresAndAtomics = true,
629bf215546Sopenharmony_ci      .fragmentStoresAndAtomics = true,
630bf215546Sopenharmony_ci      .shaderTessellationAndGeometryPointSize = false,
631bf215546Sopenharmony_ci      .shaderImageGatherExtended = false,
632bf215546Sopenharmony_ci      .shaderStorageImageExtendedFormats = true,
633bf215546Sopenharmony_ci      .shaderStorageImageMultisample = false,
634bf215546Sopenharmony_ci      .shaderStorageImageReadWithoutFormat = true,
635bf215546Sopenharmony_ci      .shaderStorageImageWriteWithoutFormat = false,
636bf215546Sopenharmony_ci      .shaderUniformBufferArrayDynamicIndexing = true,
637bf215546Sopenharmony_ci      .shaderSampledImageArrayDynamicIndexing = true,
638bf215546Sopenharmony_ci      .shaderStorageBufferArrayDynamicIndexing = true,
639bf215546Sopenharmony_ci      .shaderStorageImageArrayDynamicIndexing = true,
640bf215546Sopenharmony_ci      .shaderClipDistance = true,
641bf215546Sopenharmony_ci      .shaderCullDistance = true,
642bf215546Sopenharmony_ci      .shaderFloat64 = false,
643bf215546Sopenharmony_ci      .shaderInt64 = true,
644bf215546Sopenharmony_ci      .shaderInt16 = true,
645bf215546Sopenharmony_ci      .shaderResourceResidency = false,
646bf215546Sopenharmony_ci      .shaderResourceMinLod = false,
647bf215546Sopenharmony_ci      .sparseBinding = false,
648bf215546Sopenharmony_ci      .sparseResidencyBuffer = false,
649bf215546Sopenharmony_ci      .sparseResidencyImage2D = false,
650bf215546Sopenharmony_ci      .sparseResidencyImage3D = false,
651bf215546Sopenharmony_ci      .sparseResidency2Samples = false,
652bf215546Sopenharmony_ci      .sparseResidency4Samples = false,
653bf215546Sopenharmony_ci      .sparseResidency8Samples = false,
654bf215546Sopenharmony_ci      .sparseResidency16Samples = false,
655bf215546Sopenharmony_ci      .sparseResidencyAliased = false,
656bf215546Sopenharmony_ci      .variableMultisampleRate = false,
657bf215546Sopenharmony_ci      .inheritedQueries = false,
658bf215546Sopenharmony_ci   };
659bf215546Sopenharmony_ci
660bf215546Sopenharmony_ci   vk_foreach_struct (ext, pFeatures->pNext) {
661bf215546Sopenharmony_ci      pvr_debug_ignored_stype(ext->sType);
662bf215546Sopenharmony_ci   }
663bf215546Sopenharmony_ci}
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_ci/* TODO: See if this function can be improved once fully implemented. */
666bf215546Sopenharmony_ciuint32_t pvr_calc_fscommon_size_and_tiles_in_flight(
667bf215546Sopenharmony_ci   const struct pvr_physical_device *pdevice,
668bf215546Sopenharmony_ci   uint32_t fs_common_size,
669bf215546Sopenharmony_ci   uint32_t min_tiles_in_flight)
670bf215546Sopenharmony_ci{
671bf215546Sopenharmony_ci   const struct pvr_device_runtime_info *dev_runtime_info =
672bf215546Sopenharmony_ci      &pdevice->dev_runtime_info;
673bf215546Sopenharmony_ci   const struct pvr_device_info *dev_info = &pdevice->dev_info;
674bf215546Sopenharmony_ci   uint32_t max_tiles_in_flight;
675bf215546Sopenharmony_ci   uint32_t num_allocs;
676bf215546Sopenharmony_ci
677bf215546Sopenharmony_ci   if (PVR_HAS_FEATURE(dev_info, s8xe)) {
678bf215546Sopenharmony_ci      num_allocs = PVR_GET_FEATURE_VALUE(dev_info, num_raster_pipes, 0U);
679bf215546Sopenharmony_ci   } else {
680bf215546Sopenharmony_ci      uint32_t min_cluster_per_phantom = 0;
681bf215546Sopenharmony_ci
682bf215546Sopenharmony_ci      if (dev_runtime_info->num_phantoms > 1) {
683bf215546Sopenharmony_ci         pvr_finishme("Unimplemented path!!");
684bf215546Sopenharmony_ci      } else {
685bf215546Sopenharmony_ci         min_cluster_per_phantom =
686bf215546Sopenharmony_ci            PVR_GET_FEATURE_VALUE(dev_info, num_clusters, 1U);
687bf215546Sopenharmony_ci      }
688bf215546Sopenharmony_ci
689bf215546Sopenharmony_ci      if (dev_runtime_info->num_phantoms > 1)
690bf215546Sopenharmony_ci         pvr_finishme("Unimplemented path!!");
691bf215546Sopenharmony_ci
692bf215546Sopenharmony_ci      if (dev_runtime_info->num_phantoms > 2)
693bf215546Sopenharmony_ci         pvr_finishme("Unimplemented path!!");
694bf215546Sopenharmony_ci
695bf215546Sopenharmony_ci      if (dev_runtime_info->num_phantoms > 3)
696bf215546Sopenharmony_ci         pvr_finishme("Unimplemented path!!");
697bf215546Sopenharmony_ci
698bf215546Sopenharmony_ci      if (min_cluster_per_phantom >= 4)
699bf215546Sopenharmony_ci         num_allocs = 1;
700bf215546Sopenharmony_ci      else if (min_cluster_per_phantom == 2)
701bf215546Sopenharmony_ci         num_allocs = 2;
702bf215546Sopenharmony_ci      else
703bf215546Sopenharmony_ci         num_allocs = 4;
704bf215546Sopenharmony_ci   }
705bf215546Sopenharmony_ci
706bf215546Sopenharmony_ci   max_tiles_in_flight =
707bf215546Sopenharmony_ci      PVR_GET_FEATURE_VALUE(dev_info, isp_max_tiles_in_flight, 1U);
708bf215546Sopenharmony_ci
709bf215546Sopenharmony_ci   if (fs_common_size == UINT_MAX) {
710bf215546Sopenharmony_ci      const struct pvr_device_runtime_info *dev_runtime_info =
711bf215546Sopenharmony_ci         &pdevice->dev_runtime_info;
712bf215546Sopenharmony_ci      uint32_t max_common_size;
713bf215546Sopenharmony_ci
714bf215546Sopenharmony_ci      num_allocs *= MIN2(min_tiles_in_flight, max_tiles_in_flight);
715bf215546Sopenharmony_ci
716bf215546Sopenharmony_ci      if (!PVR_HAS_ERN(dev_info, 38748)) {
717bf215546Sopenharmony_ci         /* Hardware needs space for one extra shared allocation. */
718bf215546Sopenharmony_ci         num_allocs += 1;
719bf215546Sopenharmony_ci      }
720bf215546Sopenharmony_ci
721bf215546Sopenharmony_ci      max_common_size =
722bf215546Sopenharmony_ci         dev_runtime_info->reserved_shared_size - dev_runtime_info->max_coeffs;
723bf215546Sopenharmony_ci
724bf215546Sopenharmony_ci      /* Double resource requirements to deal with fragmentation. */
725bf215546Sopenharmony_ci      max_common_size /= num_allocs * 2;
726bf215546Sopenharmony_ci      max_common_size =
727bf215546Sopenharmony_ci         ROUND_DOWN_TO(max_common_size,
728bf215546Sopenharmony_ci                       PVRX(TA_STATE_PDS_SIZEINFO2_USC_SHAREDSIZE_UNIT_SIZE));
729bf215546Sopenharmony_ci
730bf215546Sopenharmony_ci      return max_common_size;
731bf215546Sopenharmony_ci   } else if (fs_common_size == 0) {
732bf215546Sopenharmony_ci      return max_tiles_in_flight;
733bf215546Sopenharmony_ci   }
734bf215546Sopenharmony_ci
735bf215546Sopenharmony_ci   pvr_finishme("Unimplemented path!!");
736bf215546Sopenharmony_ci
737bf215546Sopenharmony_ci   return 0;
738bf215546Sopenharmony_ci}
739bf215546Sopenharmony_ci
740bf215546Sopenharmony_cistruct pvr_descriptor_limits {
741bf215546Sopenharmony_ci   uint32_t max_per_stage_resources;
742bf215546Sopenharmony_ci   uint32_t max_per_stage_samplers;
743bf215546Sopenharmony_ci   uint32_t max_per_stage_uniform_buffers;
744bf215546Sopenharmony_ci   uint32_t max_per_stage_storage_buffers;
745bf215546Sopenharmony_ci   uint32_t max_per_stage_sampled_images;
746bf215546Sopenharmony_ci   uint32_t max_per_stage_storage_images;
747bf215546Sopenharmony_ci   uint32_t max_per_stage_input_attachments;
748bf215546Sopenharmony_ci};
749bf215546Sopenharmony_ci
750bf215546Sopenharmony_cistatic const struct pvr_descriptor_limits *
751bf215546Sopenharmony_cipvr_get_physical_device_descriptor_limits(struct pvr_physical_device *pdevice)
752bf215546Sopenharmony_ci{
753bf215546Sopenharmony_ci   enum pvr_descriptor_cs_level {
754bf215546Sopenharmony_ci      /* clang-format off */
755bf215546Sopenharmony_ci      CS4096, /* 6XT and some XE cores with large CS. */
756bf215546Sopenharmony_ci      CS2560, /* Mid range Rogue XE cores. */
757bf215546Sopenharmony_ci      CS2048, /* Low end Rogue XE cores. */
758bf215546Sopenharmony_ci      CS1536, /* Ultra-low-end 9XEP. */
759bf215546Sopenharmony_ci      CS680,  /* lower limits for older devices. */
760bf215546Sopenharmony_ci      CS408,  /* 7XE. */
761bf215546Sopenharmony_ci      /* clang-format on */
762bf215546Sopenharmony_ci   };
763bf215546Sopenharmony_ci
764bf215546Sopenharmony_ci   static const struct pvr_descriptor_limits descriptor_limits[] = {
765bf215546Sopenharmony_ci      [CS4096] = { 1160U, 256U, 192U, 144U, 256U, 256U, 8U, },
766bf215546Sopenharmony_ci      [CS2560] = {  648U, 128U, 128U, 128U, 128U, 128U, 8U, },
767bf215546Sopenharmony_ci      [CS2048] = {  584U, 128U,  96U,  64U, 128U, 128U, 8U, },
768bf215546Sopenharmony_ci      [CS1536] = {  456U,  64U,  96U,  64U, 128U,  64U, 8U, },
769bf215546Sopenharmony_ci      [CS680]  = {  224U,  32U,  64U,  36U,  48U,   8U, 8U, },
770bf215546Sopenharmony_ci      [CS408]  = {  128U,  16U,  40U,  28U,  16U,   8U, 8U, },
771bf215546Sopenharmony_ci   };
772bf215546Sopenharmony_ci
773bf215546Sopenharmony_ci   const uint32_t common_size =
774bf215546Sopenharmony_ci      pvr_calc_fscommon_size_and_tiles_in_flight(pdevice, -1, 1);
775bf215546Sopenharmony_ci   enum pvr_descriptor_cs_level cs_level;
776bf215546Sopenharmony_ci
777bf215546Sopenharmony_ci   if (common_size >= 2048) {
778bf215546Sopenharmony_ci      cs_level = CS2048;
779bf215546Sopenharmony_ci   } else if (common_size >= 1526) {
780bf215546Sopenharmony_ci      cs_level = CS1536;
781bf215546Sopenharmony_ci   } else if (common_size >= 680) {
782bf215546Sopenharmony_ci      cs_level = CS680;
783bf215546Sopenharmony_ci   } else if (common_size >= 408) {
784bf215546Sopenharmony_ci      cs_level = CS408;
785bf215546Sopenharmony_ci   } else {
786bf215546Sopenharmony_ci      mesa_loge("This core appears to have a very limited amount of shared "
787bf215546Sopenharmony_ci                "register space and may not meet the Vulkan spec limits.");
788bf215546Sopenharmony_ci      abort();
789bf215546Sopenharmony_ci   }
790bf215546Sopenharmony_ci
791bf215546Sopenharmony_ci   return &descriptor_limits[cs_level];
792bf215546Sopenharmony_ci}
793bf215546Sopenharmony_ci
794bf215546Sopenharmony_civoid pvr_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
795bf215546Sopenharmony_ci                                      VkPhysicalDeviceProperties2 *pProperties)
796bf215546Sopenharmony_ci{
797bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_physical_device, pdevice, physicalDevice);
798bf215546Sopenharmony_ci   const struct pvr_descriptor_limits *descriptor_limits =
799bf215546Sopenharmony_ci      pvr_get_physical_device_descriptor_limits(pdevice);
800bf215546Sopenharmony_ci
801bf215546Sopenharmony_ci   /* Default value based on the minimum value found in all existing cores. */
802bf215546Sopenharmony_ci   const uint32_t max_multisample =
803bf215546Sopenharmony_ci      PVR_GET_FEATURE_VALUE(&pdevice->dev_info, max_multisample, 4);
804bf215546Sopenharmony_ci
805bf215546Sopenharmony_ci   /* Default value based on the minimum value found in all existing cores. */
806bf215546Sopenharmony_ci   const uint32_t uvs_banks =
807bf215546Sopenharmony_ci      PVR_GET_FEATURE_VALUE(&pdevice->dev_info, uvs_banks, 2);
808bf215546Sopenharmony_ci
809bf215546Sopenharmony_ci   /* Default value based on the minimum value found in all existing cores. */
810bf215546Sopenharmony_ci   const uint32_t uvs_pba_entries =
811bf215546Sopenharmony_ci      PVR_GET_FEATURE_VALUE(&pdevice->dev_info, uvs_pba_entries, 160);
812bf215546Sopenharmony_ci
813bf215546Sopenharmony_ci   /* Default value based on the minimum value found in all existing cores. */
814bf215546Sopenharmony_ci   const uint32_t num_user_clip_planes =
815bf215546Sopenharmony_ci      PVR_GET_FEATURE_VALUE(&pdevice->dev_info, num_user_clip_planes, 8);
816bf215546Sopenharmony_ci
817bf215546Sopenharmony_ci   const uint32_t sub_pixel_precision =
818bf215546Sopenharmony_ci      PVR_HAS_FEATURE(&pdevice->dev_info, simple_internal_parameter_format)
819bf215546Sopenharmony_ci         ? 4U
820bf215546Sopenharmony_ci         : 8U;
821bf215546Sopenharmony_ci
822bf215546Sopenharmony_ci   const uint32_t max_render_size =
823bf215546Sopenharmony_ci      rogue_get_render_size_max(&pdevice->dev_info);
824bf215546Sopenharmony_ci
825bf215546Sopenharmony_ci   const uint32_t max_sample_bits = ((max_multisample << 1) - 1);
826bf215546Sopenharmony_ci
827bf215546Sopenharmony_ci   const uint32_t max_user_vertex_components =
828bf215546Sopenharmony_ci      ((uvs_banks <= 8U) && (uvs_pba_entries == 160U)) ? 64U : 128U;
829bf215546Sopenharmony_ci
830bf215546Sopenharmony_ci   /* The workgroup invocations are limited by the case where we have a compute
831bf215546Sopenharmony_ci    * barrier - each slot has a fixed number of invocations, the whole workgroup
832bf215546Sopenharmony_ci    * may need to span multiple slots. As each slot will WAIT at the barrier
833bf215546Sopenharmony_ci    * until the last invocation completes, all have to be schedulable at the
834bf215546Sopenharmony_ci    * same time.
835bf215546Sopenharmony_ci    *
836bf215546Sopenharmony_ci    * Typically all Rogue cores have 16 slots. Some of the smallest cores are
837bf215546Sopenharmony_ci    * reduced to 14.
838bf215546Sopenharmony_ci    *
839bf215546Sopenharmony_ci    * The compute barrier slot exhaustion scenario can be tested with:
840bf215546Sopenharmony_ci    * dEQP-VK.memory_model.message_passing*u32.coherent.fence_fence
841bf215546Sopenharmony_ci    *    .atomicwrite*guard*comp
842bf215546Sopenharmony_ci    */
843bf215546Sopenharmony_ci
844bf215546Sopenharmony_ci   /* Default value based on the minimum value found in all existing cores. */
845bf215546Sopenharmony_ci   const uint32_t usc_slots =
846bf215546Sopenharmony_ci      PVR_GET_FEATURE_VALUE(&pdevice->dev_info, usc_slots, 14);
847bf215546Sopenharmony_ci
848bf215546Sopenharmony_ci   /* Default value based on the minimum value found in all existing cores. */
849bf215546Sopenharmony_ci   const uint32_t max_instances_per_pds_task =
850bf215546Sopenharmony_ci      PVR_GET_FEATURE_VALUE(&pdevice->dev_info,
851bf215546Sopenharmony_ci                            max_instances_per_pds_task,
852bf215546Sopenharmony_ci                            32U);
853bf215546Sopenharmony_ci
854bf215546Sopenharmony_ci   const uint32_t max_compute_work_group_invocations =
855bf215546Sopenharmony_ci      (usc_slots * max_instances_per_pds_task >= 512U) ? 512U : 384U;
856bf215546Sopenharmony_ci
857bf215546Sopenharmony_ci   VkPhysicalDeviceLimits limits = {
858bf215546Sopenharmony_ci      .maxImageDimension1D = max_render_size,
859bf215546Sopenharmony_ci      .maxImageDimension2D = max_render_size,
860bf215546Sopenharmony_ci      .maxImageDimension3D = 2U * 1024U,
861bf215546Sopenharmony_ci      .maxImageDimensionCube = max_render_size,
862bf215546Sopenharmony_ci      .maxImageArrayLayers = 2U * 1024U,
863bf215546Sopenharmony_ci      .maxTexelBufferElements = 64U * 1024U,
864bf215546Sopenharmony_ci      .maxUniformBufferRange = 128U * 1024U * 1024U,
865bf215546Sopenharmony_ci      .maxStorageBufferRange = 128U * 1024U * 1024U,
866bf215546Sopenharmony_ci      .maxPushConstantsSize = PVR_MAX_PUSH_CONSTANTS_SIZE,
867bf215546Sopenharmony_ci      .maxMemoryAllocationCount = UINT32_MAX,
868bf215546Sopenharmony_ci      .maxSamplerAllocationCount = UINT32_MAX,
869bf215546Sopenharmony_ci      .bufferImageGranularity = 1U,
870bf215546Sopenharmony_ci      .sparseAddressSpaceSize = 256ULL * 1024ULL * 1024ULL * 1024ULL,
871bf215546Sopenharmony_ci
872bf215546Sopenharmony_ci      /* Maximum number of descriptor sets that can be bound at the same time.
873bf215546Sopenharmony_ci       */
874bf215546Sopenharmony_ci      .maxBoundDescriptorSets = PVR_MAX_DESCRIPTOR_SETS,
875bf215546Sopenharmony_ci
876bf215546Sopenharmony_ci      .maxPerStageResources = descriptor_limits->max_per_stage_resources,
877bf215546Sopenharmony_ci      .maxPerStageDescriptorSamplers =
878bf215546Sopenharmony_ci         descriptor_limits->max_per_stage_samplers,
879bf215546Sopenharmony_ci      .maxPerStageDescriptorUniformBuffers =
880bf215546Sopenharmony_ci         descriptor_limits->max_per_stage_uniform_buffers,
881bf215546Sopenharmony_ci      .maxPerStageDescriptorStorageBuffers =
882bf215546Sopenharmony_ci         descriptor_limits->max_per_stage_storage_buffers,
883bf215546Sopenharmony_ci      .maxPerStageDescriptorSampledImages =
884bf215546Sopenharmony_ci         descriptor_limits->max_per_stage_sampled_images,
885bf215546Sopenharmony_ci      .maxPerStageDescriptorStorageImages =
886bf215546Sopenharmony_ci         descriptor_limits->max_per_stage_storage_images,
887bf215546Sopenharmony_ci      .maxPerStageDescriptorInputAttachments =
888bf215546Sopenharmony_ci         descriptor_limits->max_per_stage_input_attachments,
889bf215546Sopenharmony_ci
890bf215546Sopenharmony_ci      .maxDescriptorSetSamplers = 256U,
891bf215546Sopenharmony_ci      .maxDescriptorSetUniformBuffers = 256U,
892bf215546Sopenharmony_ci      .maxDescriptorSetUniformBuffersDynamic = 8U,
893bf215546Sopenharmony_ci      .maxDescriptorSetStorageBuffers = 256U,
894bf215546Sopenharmony_ci      .maxDescriptorSetStorageBuffersDynamic = 8U,
895bf215546Sopenharmony_ci      .maxDescriptorSetSampledImages = 256U,
896bf215546Sopenharmony_ci      .maxDescriptorSetStorageImages = 256U,
897bf215546Sopenharmony_ci      .maxDescriptorSetInputAttachments = 256U,
898bf215546Sopenharmony_ci
899bf215546Sopenharmony_ci      /* Vertex Shader Limits */
900bf215546Sopenharmony_ci      .maxVertexInputAttributes = PVR_MAX_VERTEX_INPUT_BINDINGS,
901bf215546Sopenharmony_ci      .maxVertexInputBindings = PVR_MAX_VERTEX_INPUT_BINDINGS,
902bf215546Sopenharmony_ci      .maxVertexInputAttributeOffset = 0xFFFF,
903bf215546Sopenharmony_ci      .maxVertexInputBindingStride = 1024U * 1024U * 1024U * 2U,
904bf215546Sopenharmony_ci      .maxVertexOutputComponents = max_user_vertex_components,
905bf215546Sopenharmony_ci
906bf215546Sopenharmony_ci      /* Tessellation Limits */
907bf215546Sopenharmony_ci      .maxTessellationGenerationLevel = 0,
908bf215546Sopenharmony_ci      .maxTessellationPatchSize = 0,
909bf215546Sopenharmony_ci      .maxTessellationControlPerVertexInputComponents = 0,
910bf215546Sopenharmony_ci      .maxTessellationControlPerVertexOutputComponents = 0,
911bf215546Sopenharmony_ci      .maxTessellationControlPerPatchOutputComponents = 0,
912bf215546Sopenharmony_ci      .maxTessellationControlTotalOutputComponents = 0,
913bf215546Sopenharmony_ci      .maxTessellationEvaluationInputComponents = 0,
914bf215546Sopenharmony_ci      .maxTessellationEvaluationOutputComponents = 0,
915bf215546Sopenharmony_ci
916bf215546Sopenharmony_ci      /* Geometry Shader Limits */
917bf215546Sopenharmony_ci      .maxGeometryShaderInvocations = 0,
918bf215546Sopenharmony_ci      .maxGeometryInputComponents = 0,
919bf215546Sopenharmony_ci      .maxGeometryOutputComponents = 0,
920bf215546Sopenharmony_ci      .maxGeometryOutputVertices = 0,
921bf215546Sopenharmony_ci      .maxGeometryTotalOutputComponents = 0,
922bf215546Sopenharmony_ci
923bf215546Sopenharmony_ci      /* Fragment Shader Limits */
924bf215546Sopenharmony_ci      .maxFragmentInputComponents = max_user_vertex_components,
925bf215546Sopenharmony_ci      .maxFragmentOutputAttachments = PVR_MAX_COLOR_ATTACHMENTS,
926bf215546Sopenharmony_ci      .maxFragmentDualSrcAttachments = 0,
927bf215546Sopenharmony_ci      .maxFragmentCombinedOutputResources =
928bf215546Sopenharmony_ci         descriptor_limits->max_per_stage_storage_buffers +
929bf215546Sopenharmony_ci         descriptor_limits->max_per_stage_storage_images +
930bf215546Sopenharmony_ci         PVR_MAX_COLOR_ATTACHMENTS,
931bf215546Sopenharmony_ci
932bf215546Sopenharmony_ci      /* Compute Shader Limits */
933bf215546Sopenharmony_ci      .maxComputeSharedMemorySize = 16U * 1024U,
934bf215546Sopenharmony_ci      .maxComputeWorkGroupCount = { 64U * 1024U, 64U * 1024U, 64U * 1024U },
935bf215546Sopenharmony_ci      .maxComputeWorkGroupInvocations = max_compute_work_group_invocations,
936bf215546Sopenharmony_ci      .maxComputeWorkGroupSize = { max_compute_work_group_invocations,
937bf215546Sopenharmony_ci                                   max_compute_work_group_invocations,
938bf215546Sopenharmony_ci                                   64U },
939bf215546Sopenharmony_ci
940bf215546Sopenharmony_ci      /* Rasterization Limits */
941bf215546Sopenharmony_ci      .subPixelPrecisionBits = sub_pixel_precision,
942bf215546Sopenharmony_ci      .subTexelPrecisionBits = 8U,
943bf215546Sopenharmony_ci      .mipmapPrecisionBits = 8U,
944bf215546Sopenharmony_ci
945bf215546Sopenharmony_ci      .maxDrawIndexedIndexValue = UINT32_MAX,
946bf215546Sopenharmony_ci      .maxDrawIndirectCount = 2U * 1024U * 1024U * 1024U,
947bf215546Sopenharmony_ci      .maxSamplerLodBias = 16.0f,
948bf215546Sopenharmony_ci      .maxSamplerAnisotropy = 1.0f,
949bf215546Sopenharmony_ci      .maxViewports = PVR_MAX_VIEWPORTS,
950bf215546Sopenharmony_ci
951bf215546Sopenharmony_ci      .maxViewportDimensions[0] = max_render_size,
952bf215546Sopenharmony_ci      .maxViewportDimensions[1] = max_render_size,
953bf215546Sopenharmony_ci      .viewportBoundsRange[0] = -(int32_t)(2U * max_render_size),
954bf215546Sopenharmony_ci      .viewportBoundsRange[1] = 2U * max_render_size,
955bf215546Sopenharmony_ci
956bf215546Sopenharmony_ci      .viewportSubPixelBits = 0,
957bf215546Sopenharmony_ci      .minMemoryMapAlignment = 64U,
958bf215546Sopenharmony_ci      .minTexelBufferOffsetAlignment = 16U,
959bf215546Sopenharmony_ci      .minUniformBufferOffsetAlignment = 4U,
960bf215546Sopenharmony_ci      .minStorageBufferOffsetAlignment = 4U,
961bf215546Sopenharmony_ci
962bf215546Sopenharmony_ci      .minTexelOffset = -8,
963bf215546Sopenharmony_ci      .maxTexelOffset = 7U,
964bf215546Sopenharmony_ci      .minTexelGatherOffset = -8,
965bf215546Sopenharmony_ci      .maxTexelGatherOffset = 7,
966bf215546Sopenharmony_ci      .minInterpolationOffset = -0.5,
967bf215546Sopenharmony_ci      .maxInterpolationOffset = 0.5,
968bf215546Sopenharmony_ci      .subPixelInterpolationOffsetBits = 4U,
969bf215546Sopenharmony_ci
970bf215546Sopenharmony_ci      .maxFramebufferWidth = max_render_size,
971bf215546Sopenharmony_ci      .maxFramebufferHeight = max_render_size,
972bf215546Sopenharmony_ci      .maxFramebufferLayers = PVR_MAX_FRAMEBUFFER_LAYERS,
973bf215546Sopenharmony_ci
974bf215546Sopenharmony_ci      .framebufferColorSampleCounts = max_sample_bits,
975bf215546Sopenharmony_ci      .framebufferDepthSampleCounts = max_sample_bits,
976bf215546Sopenharmony_ci      .framebufferStencilSampleCounts = max_sample_bits,
977bf215546Sopenharmony_ci      .framebufferNoAttachmentsSampleCounts = max_sample_bits,
978bf215546Sopenharmony_ci      .maxColorAttachments = PVR_MAX_COLOR_ATTACHMENTS,
979bf215546Sopenharmony_ci      .sampledImageColorSampleCounts = max_sample_bits,
980bf215546Sopenharmony_ci      .sampledImageIntegerSampleCounts = max_sample_bits,
981bf215546Sopenharmony_ci      .sampledImageDepthSampleCounts = max_sample_bits,
982bf215546Sopenharmony_ci      .sampledImageStencilSampleCounts = max_sample_bits,
983bf215546Sopenharmony_ci      .storageImageSampleCounts = max_sample_bits,
984bf215546Sopenharmony_ci      .maxSampleMaskWords = 1U,
985bf215546Sopenharmony_ci      .timestampComputeAndGraphics = false,
986bf215546Sopenharmony_ci      .timestampPeriod = 0.0f,
987bf215546Sopenharmony_ci      .maxClipDistances = num_user_clip_planes,
988bf215546Sopenharmony_ci      .maxCullDistances = num_user_clip_planes,
989bf215546Sopenharmony_ci      .maxCombinedClipAndCullDistances = num_user_clip_planes,
990bf215546Sopenharmony_ci      .discreteQueuePriorities = 2U,
991bf215546Sopenharmony_ci      .pointSizeRange[0] = 1.0f,
992bf215546Sopenharmony_ci      .pointSizeRange[1] = 511.0f,
993bf215546Sopenharmony_ci      .pointSizeGranularity = 0.0625f,
994bf215546Sopenharmony_ci      .lineWidthRange[0] = 1.0f / 16.0f,
995bf215546Sopenharmony_ci      .lineWidthRange[1] = 16.0f,
996bf215546Sopenharmony_ci      .lineWidthGranularity = 1.0f / 16.0f,
997bf215546Sopenharmony_ci      .strictLines = false,
998bf215546Sopenharmony_ci      .standardSampleLocations = true,
999bf215546Sopenharmony_ci      .optimalBufferCopyOffsetAlignment = 4U,
1000bf215546Sopenharmony_ci      .optimalBufferCopyRowPitchAlignment = 4U,
1001bf215546Sopenharmony_ci      .nonCoherentAtomSize = 1U,
1002bf215546Sopenharmony_ci   };
1003bf215546Sopenharmony_ci
1004bf215546Sopenharmony_ci   pProperties->properties = (VkPhysicalDeviceProperties){
1005bf215546Sopenharmony_ci      .apiVersion = PVR_API_VERSION,
1006bf215546Sopenharmony_ci      .driverVersion = vk_get_driver_version(),
1007bf215546Sopenharmony_ci      .vendorID = VK_VENDOR_ID_IMAGINATION,
1008bf215546Sopenharmony_ci      .deviceID = pdevice->dev_info.ident.device_id,
1009bf215546Sopenharmony_ci      .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
1010bf215546Sopenharmony_ci      .limits = limits,
1011bf215546Sopenharmony_ci      .sparseProperties = { 0 },
1012bf215546Sopenharmony_ci   };
1013bf215546Sopenharmony_ci
1014bf215546Sopenharmony_ci   snprintf(pProperties->properties.deviceName,
1015bf215546Sopenharmony_ci            sizeof(pProperties->properties.deviceName),
1016bf215546Sopenharmony_ci            "%s",
1017bf215546Sopenharmony_ci            pdevice->name);
1018bf215546Sopenharmony_ci
1019bf215546Sopenharmony_ci   memcpy(pProperties->properties.pipelineCacheUUID,
1020bf215546Sopenharmony_ci          pdevice->pipeline_cache_uuid,
1021bf215546Sopenharmony_ci          VK_UUID_SIZE);
1022bf215546Sopenharmony_ci
1023bf215546Sopenharmony_ci   vk_foreach_struct (ext, pProperties->pNext) {
1024bf215546Sopenharmony_ci      pvr_debug_ignored_stype(ext->sType);
1025bf215546Sopenharmony_ci   }
1026bf215546Sopenharmony_ci}
1027bf215546Sopenharmony_ci
1028bf215546Sopenharmony_ciconst static VkQueueFamilyProperties pvr_queue_family_properties = {
1029bf215546Sopenharmony_ci   .queueFlags = VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT |
1030bf215546Sopenharmony_ci                 VK_QUEUE_TRANSFER_BIT,
1031bf215546Sopenharmony_ci   .queueCount = PVR_MAX_QUEUES,
1032bf215546Sopenharmony_ci   .timestampValidBits = 0,
1033bf215546Sopenharmony_ci   .minImageTransferGranularity = { 1, 1, 1 },
1034bf215546Sopenharmony_ci};
1035bf215546Sopenharmony_ci
1036bf215546Sopenharmony_civoid pvr_GetPhysicalDeviceQueueFamilyProperties(
1037bf215546Sopenharmony_ci   VkPhysicalDevice physicalDevice,
1038bf215546Sopenharmony_ci   uint32_t *pCount,
1039bf215546Sopenharmony_ci   VkQueueFamilyProperties *pQueueFamilyProperties)
1040bf215546Sopenharmony_ci{
1041bf215546Sopenharmony_ci   VK_OUTARRAY_MAKE_TYPED(VkQueueFamilyProperties,
1042bf215546Sopenharmony_ci                          out,
1043bf215546Sopenharmony_ci                          pQueueFamilyProperties,
1044bf215546Sopenharmony_ci                          pCount);
1045bf215546Sopenharmony_ci
1046bf215546Sopenharmony_ci   vk_outarray_append_typed (VkQueueFamilyProperties, &out, p) {
1047bf215546Sopenharmony_ci      *p = pvr_queue_family_properties;
1048bf215546Sopenharmony_ci   }
1049bf215546Sopenharmony_ci}
1050bf215546Sopenharmony_ci
1051bf215546Sopenharmony_civoid pvr_GetPhysicalDeviceQueueFamilyProperties2(
1052bf215546Sopenharmony_ci   VkPhysicalDevice physicalDevice,
1053bf215546Sopenharmony_ci   uint32_t *pQueueFamilyPropertyCount,
1054bf215546Sopenharmony_ci   VkQueueFamilyProperties2 *pQueueFamilyProperties)
1055bf215546Sopenharmony_ci{
1056bf215546Sopenharmony_ci   VK_OUTARRAY_MAKE_TYPED(VkQueueFamilyProperties2,
1057bf215546Sopenharmony_ci                          out,
1058bf215546Sopenharmony_ci                          pQueueFamilyProperties,
1059bf215546Sopenharmony_ci                          pQueueFamilyPropertyCount);
1060bf215546Sopenharmony_ci
1061bf215546Sopenharmony_ci   vk_outarray_append_typed (VkQueueFamilyProperties2, &out, p) {
1062bf215546Sopenharmony_ci      p->queueFamilyProperties = pvr_queue_family_properties;
1063bf215546Sopenharmony_ci
1064bf215546Sopenharmony_ci      vk_foreach_struct (ext, p->pNext) {
1065bf215546Sopenharmony_ci         pvr_debug_ignored_stype(ext->sType);
1066bf215546Sopenharmony_ci      }
1067bf215546Sopenharmony_ci   }
1068bf215546Sopenharmony_ci}
1069bf215546Sopenharmony_ci
1070bf215546Sopenharmony_civoid pvr_GetPhysicalDeviceMemoryProperties2(
1071bf215546Sopenharmony_ci   VkPhysicalDevice physicalDevice,
1072bf215546Sopenharmony_ci   VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)
1073bf215546Sopenharmony_ci{
1074bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_physical_device, pdevice, physicalDevice);
1075bf215546Sopenharmony_ci
1076bf215546Sopenharmony_ci   pMemoryProperties->memoryProperties = pdevice->memory;
1077bf215546Sopenharmony_ci
1078bf215546Sopenharmony_ci   vk_foreach_struct (ext, pMemoryProperties->pNext) {
1079bf215546Sopenharmony_ci      pvr_debug_ignored_stype(ext->sType);
1080bf215546Sopenharmony_ci   }
1081bf215546Sopenharmony_ci}
1082bf215546Sopenharmony_ci
1083bf215546Sopenharmony_ciPFN_vkVoidFunction pvr_GetInstanceProcAddr(VkInstance _instance,
1084bf215546Sopenharmony_ci                                           const char *pName)
1085bf215546Sopenharmony_ci{
1086bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_instance, instance, _instance);
1087bf215546Sopenharmony_ci   return vk_instance_get_proc_addr(&instance->vk,
1088bf215546Sopenharmony_ci                                    &pvr_instance_entrypoints,
1089bf215546Sopenharmony_ci                                    pName);
1090bf215546Sopenharmony_ci}
1091bf215546Sopenharmony_ci
1092bf215546Sopenharmony_ci/* With version 1+ of the loader interface the ICD should expose
1093bf215546Sopenharmony_ci * vk_icdGetInstanceProcAddr to work around certain LD_PRELOAD issues seen in
1094bf215546Sopenharmony_ci * apps.
1095bf215546Sopenharmony_ci */
1096bf215546Sopenharmony_ciPUBLIC
1097bf215546Sopenharmony_ciVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1098bf215546Sopenharmony_civk_icdGetInstanceProcAddr(VkInstance instance, const char *pName)
1099bf215546Sopenharmony_ci{
1100bf215546Sopenharmony_ci   return pvr_GetInstanceProcAddr(instance, pName);
1101bf215546Sopenharmony_ci}
1102bf215546Sopenharmony_ci
1103bf215546Sopenharmony_ci/* With version 4+ of the loader interface the ICD should expose
1104bf215546Sopenharmony_ci * vk_icdGetPhysicalDeviceProcAddr().
1105bf215546Sopenharmony_ci */
1106bf215546Sopenharmony_ciPUBLIC
1107bf215546Sopenharmony_ciVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1108bf215546Sopenharmony_civk_icdGetPhysicalDeviceProcAddr(VkInstance _instance, const char *pName)
1109bf215546Sopenharmony_ci{
1110bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_instance, instance, _instance);
1111bf215546Sopenharmony_ci   return vk_instance_get_physical_device_proc_addr(&instance->vk, pName);
1112bf215546Sopenharmony_ci}
1113bf215546Sopenharmony_ci
1114bf215546Sopenharmony_cistatic VkResult pvr_device_init_compute_fence_program(struct pvr_device *device)
1115bf215546Sopenharmony_ci{
1116bf215546Sopenharmony_ci   const struct pvr_device_info *dev_info = &device->pdevice->dev_info;
1117bf215546Sopenharmony_ci   const uint32_t cache_line_size = rogue_get_slc_cache_line_size(dev_info);
1118bf215546Sopenharmony_ci   struct pvr_pds_compute_shader_program program = { 0U };
1119bf215546Sopenharmony_ci   size_t staging_buffer_size;
1120bf215546Sopenharmony_ci   uint32_t *staging_buffer;
1121bf215546Sopenharmony_ci   uint32_t *data_buffer;
1122bf215546Sopenharmony_ci   uint32_t *code_buffer;
1123bf215546Sopenharmony_ci   VkResult result;
1124bf215546Sopenharmony_ci
1125bf215546Sopenharmony_ci   STATIC_ASSERT(ARRAY_SIZE(program.local_input_regs) ==
1126bf215546Sopenharmony_ci                 ARRAY_SIZE(program.work_group_input_regs));
1127bf215546Sopenharmony_ci   STATIC_ASSERT(ARRAY_SIZE(program.local_input_regs) ==
1128bf215546Sopenharmony_ci                 ARRAY_SIZE(program.global_input_regs));
1129bf215546Sopenharmony_ci
1130bf215546Sopenharmony_ci   /* Initialize PDS structure. */
1131bf215546Sopenharmony_ci   for (uint32_t i = 0U; i < ARRAY_SIZE(program.local_input_regs); i++) {
1132bf215546Sopenharmony_ci      program.local_input_regs[i] = PVR_PDS_COMPUTE_INPUT_REG_UNUSED;
1133bf215546Sopenharmony_ci      program.work_group_input_regs[i] = PVR_PDS_COMPUTE_INPUT_REG_UNUSED;
1134bf215546Sopenharmony_ci      program.global_input_regs[i] = PVR_PDS_COMPUTE_INPUT_REG_UNUSED;
1135bf215546Sopenharmony_ci   }
1136bf215546Sopenharmony_ci
1137bf215546Sopenharmony_ci   program.barrier_coefficient = PVR_PDS_COMPUTE_INPUT_REG_UNUSED;
1138bf215546Sopenharmony_ci
1139bf215546Sopenharmony_ci   /* Fence kernel. */
1140bf215546Sopenharmony_ci   program.fence = true;
1141bf215546Sopenharmony_ci   program.clear_pds_barrier = true;
1142bf215546Sopenharmony_ci
1143bf215546Sopenharmony_ci   /* Calculate how much space we'll need for the compute shader PDS program.
1144bf215546Sopenharmony_ci    */
1145bf215546Sopenharmony_ci   pvr_pds_set_sizes_compute_shader(&program, dev_info);
1146bf215546Sopenharmony_ci
1147bf215546Sopenharmony_ci   /* FIXME: Fix the below inconsistency of code size being in bytes whereas
1148bf215546Sopenharmony_ci    * data size being in dwords.
1149bf215546Sopenharmony_ci    */
1150bf215546Sopenharmony_ci   /* Code size is in bytes, data size in dwords. */
1151bf215546Sopenharmony_ci   staging_buffer_size =
1152bf215546Sopenharmony_ci      program.data_size * sizeof(uint32_t) + program.code_size;
1153bf215546Sopenharmony_ci
1154bf215546Sopenharmony_ci   staging_buffer = vk_alloc(&device->vk.alloc,
1155bf215546Sopenharmony_ci                             staging_buffer_size,
1156bf215546Sopenharmony_ci                             8U,
1157bf215546Sopenharmony_ci                             VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1158bf215546Sopenharmony_ci   if (!staging_buffer)
1159bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1160bf215546Sopenharmony_ci
1161bf215546Sopenharmony_ci   data_buffer = staging_buffer;
1162bf215546Sopenharmony_ci   code_buffer = pvr_pds_generate_compute_shader_data_segment(&program,
1163bf215546Sopenharmony_ci                                                              data_buffer,
1164bf215546Sopenharmony_ci                                                              dev_info);
1165bf215546Sopenharmony_ci   pvr_pds_generate_compute_shader_code_segment(&program,
1166bf215546Sopenharmony_ci                                                code_buffer,
1167bf215546Sopenharmony_ci                                                dev_info);
1168bf215546Sopenharmony_ci   result = pvr_gpu_upload_pds(device,
1169bf215546Sopenharmony_ci                               data_buffer,
1170bf215546Sopenharmony_ci                               program.data_size,
1171bf215546Sopenharmony_ci                               PVRX(CDMCTRL_KERNEL1_DATA_ADDR_ALIGNMENT),
1172bf215546Sopenharmony_ci                               code_buffer,
1173bf215546Sopenharmony_ci                               program.code_size / sizeof(uint32_t),
1174bf215546Sopenharmony_ci                               PVRX(CDMCTRL_KERNEL2_CODE_ADDR_ALIGNMENT),
1175bf215546Sopenharmony_ci                               cache_line_size,
1176bf215546Sopenharmony_ci                               &device->pds_compute_fence_program);
1177bf215546Sopenharmony_ci
1178bf215546Sopenharmony_ci   vk_free(&device->vk.alloc, staging_buffer);
1179bf215546Sopenharmony_ci
1180bf215546Sopenharmony_ci   return result;
1181bf215546Sopenharmony_ci}
1182bf215546Sopenharmony_ci
1183bf215546Sopenharmony_cistatic VkResult pvr_pds_idfwdf_programs_create_and_upload(
1184bf215546Sopenharmony_ci   struct pvr_device *device,
1185bf215546Sopenharmony_ci   pvr_dev_addr_t usc_addr,
1186bf215546Sopenharmony_ci   uint32_t shareds,
1187bf215546Sopenharmony_ci   uint32_t temps,
1188bf215546Sopenharmony_ci   pvr_dev_addr_t shareds_buffer_addr,
1189bf215546Sopenharmony_ci   struct pvr_pds_upload *const upload_out,
1190bf215546Sopenharmony_ci   struct pvr_pds_upload *const sw_compute_barrier_upload_out)
1191bf215546Sopenharmony_ci{
1192bf215546Sopenharmony_ci   const struct pvr_device_info *dev_info = &device->pdevice->dev_info;
1193bf215546Sopenharmony_ci   struct pvr_pds_vertex_shader_sa_program program = {
1194bf215546Sopenharmony_ci      .kick_usc = true,
1195bf215546Sopenharmony_ci      .clear_pds_barrier = PVR_NEED_SW_COMPUTE_PDS_BARRIER(dev_info),
1196bf215546Sopenharmony_ci   };
1197bf215546Sopenharmony_ci   size_t staging_buffer_size;
1198bf215546Sopenharmony_ci   uint32_t *staging_buffer;
1199bf215546Sopenharmony_ci   VkResult result;
1200bf215546Sopenharmony_ci
1201bf215546Sopenharmony_ci   /* We'll need to DMA the shareds into the USC's Common Store. */
1202bf215546Sopenharmony_ci   program.num_dma_kicks = pvr_pds_encode_dma_burst(program.dma_control,
1203bf215546Sopenharmony_ci                                                    program.dma_address,
1204bf215546Sopenharmony_ci                                                    0,
1205bf215546Sopenharmony_ci                                                    shareds,
1206bf215546Sopenharmony_ci                                                    shareds_buffer_addr.addr,
1207bf215546Sopenharmony_ci                                                    dev_info);
1208bf215546Sopenharmony_ci
1209bf215546Sopenharmony_ci   /* DMA temp regs. */
1210bf215546Sopenharmony_ci   pvr_pds_setup_doutu(&program.usc_task_control,
1211bf215546Sopenharmony_ci                       usc_addr.addr,
1212bf215546Sopenharmony_ci                       temps,
1213bf215546Sopenharmony_ci                       PVRX(PDSINST_DOUTU_SAMPLE_RATE_INSTANCE),
1214bf215546Sopenharmony_ci                       false);
1215bf215546Sopenharmony_ci
1216bf215546Sopenharmony_ci   pvr_pds_vertex_shader_sa(&program, NULL, PDS_GENERATE_SIZES, dev_info);
1217bf215546Sopenharmony_ci
1218bf215546Sopenharmony_ci   staging_buffer_size =
1219bf215546Sopenharmony_ci      (program.code_size + program.data_size) * sizeof(*staging_buffer);
1220bf215546Sopenharmony_ci
1221bf215546Sopenharmony_ci   staging_buffer = vk_alloc(&device->vk.alloc,
1222bf215546Sopenharmony_ci                             staging_buffer_size,
1223bf215546Sopenharmony_ci                             8,
1224bf215546Sopenharmony_ci                             VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
1225bf215546Sopenharmony_ci   if (!staging_buffer)
1226bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1227bf215546Sopenharmony_ci
1228bf215546Sopenharmony_ci   /* FIXME: Add support for PDS_GENERATE_CODEDATA_SEGMENTS? */
1229bf215546Sopenharmony_ci   pvr_pds_vertex_shader_sa(&program,
1230bf215546Sopenharmony_ci                            staging_buffer,
1231bf215546Sopenharmony_ci                            PDS_GENERATE_DATA_SEGMENT,
1232bf215546Sopenharmony_ci                            dev_info);
1233bf215546Sopenharmony_ci   pvr_pds_vertex_shader_sa(&program,
1234bf215546Sopenharmony_ci                            &staging_buffer[program.data_size],
1235bf215546Sopenharmony_ci                            PDS_GENERATE_CODE_SEGMENT,
1236bf215546Sopenharmony_ci                            dev_info);
1237bf215546Sopenharmony_ci
1238bf215546Sopenharmony_ci   /* At the time of writing, the SW_COMPUTE_PDS_BARRIER variant of the program
1239bf215546Sopenharmony_ci    * is bigger so we handle it first (if needed) and realloc() for a smaller
1240bf215546Sopenharmony_ci    * size.
1241bf215546Sopenharmony_ci    */
1242bf215546Sopenharmony_ci   if (PVR_NEED_SW_COMPUTE_PDS_BARRIER(dev_info)) {
1243bf215546Sopenharmony_ci      /* FIXME: Figure out the define for alignment of 16. */
1244bf215546Sopenharmony_ci      result = pvr_gpu_upload_pds(device,
1245bf215546Sopenharmony_ci                                  &staging_buffer[0],
1246bf215546Sopenharmony_ci                                  program.data_size,
1247bf215546Sopenharmony_ci                                  16,
1248bf215546Sopenharmony_ci                                  &staging_buffer[program.data_size],
1249bf215546Sopenharmony_ci                                  program.code_size,
1250bf215546Sopenharmony_ci                                  16,
1251bf215546Sopenharmony_ci                                  16,
1252bf215546Sopenharmony_ci                                  sw_compute_barrier_upload_out);
1253bf215546Sopenharmony_ci      if (result != VK_SUCCESS) {
1254bf215546Sopenharmony_ci         vk_free(&device->vk.alloc, staging_buffer);
1255bf215546Sopenharmony_ci         return result;
1256bf215546Sopenharmony_ci      }
1257bf215546Sopenharmony_ci
1258bf215546Sopenharmony_ci      program.clear_pds_barrier = false;
1259bf215546Sopenharmony_ci
1260bf215546Sopenharmony_ci      pvr_pds_vertex_shader_sa(&program, NULL, PDS_GENERATE_SIZES, dev_info);
1261bf215546Sopenharmony_ci
1262bf215546Sopenharmony_ci      staging_buffer_size =
1263bf215546Sopenharmony_ci         (program.code_size + program.data_size) * sizeof(*staging_buffer);
1264bf215546Sopenharmony_ci
1265bf215546Sopenharmony_ci      staging_buffer = vk_realloc(&device->vk.alloc,
1266bf215546Sopenharmony_ci                                  staging_buffer,
1267bf215546Sopenharmony_ci                                  staging_buffer_size,
1268bf215546Sopenharmony_ci                                  8,
1269bf215546Sopenharmony_ci                                  VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
1270bf215546Sopenharmony_ci      if (!staging_buffer) {
1271bf215546Sopenharmony_ci         pvr_bo_free(device, sw_compute_barrier_upload_out->pvr_bo);
1272bf215546Sopenharmony_ci
1273bf215546Sopenharmony_ci         return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1274bf215546Sopenharmony_ci      }
1275bf215546Sopenharmony_ci
1276bf215546Sopenharmony_ci      /* FIXME: Add support for PDS_GENERATE_CODEDATA_SEGMENTS? */
1277bf215546Sopenharmony_ci      pvr_pds_vertex_shader_sa(&program,
1278bf215546Sopenharmony_ci                               staging_buffer,
1279bf215546Sopenharmony_ci                               PDS_GENERATE_DATA_SEGMENT,
1280bf215546Sopenharmony_ci                               dev_info);
1281bf215546Sopenharmony_ci      pvr_pds_vertex_shader_sa(&program,
1282bf215546Sopenharmony_ci                               &staging_buffer[program.data_size],
1283bf215546Sopenharmony_ci                               PDS_GENERATE_CODE_SEGMENT,
1284bf215546Sopenharmony_ci                               dev_info);
1285bf215546Sopenharmony_ci   } else {
1286bf215546Sopenharmony_ci      *sw_compute_barrier_upload_out = (struct pvr_pds_upload){
1287bf215546Sopenharmony_ci         .pvr_bo = NULL,
1288bf215546Sopenharmony_ci      };
1289bf215546Sopenharmony_ci   }
1290bf215546Sopenharmony_ci
1291bf215546Sopenharmony_ci   /* FIXME: Figure out the define for alignment of 16. */
1292bf215546Sopenharmony_ci   result = pvr_gpu_upload_pds(device,
1293bf215546Sopenharmony_ci                               &staging_buffer[0],
1294bf215546Sopenharmony_ci                               program.data_size,
1295bf215546Sopenharmony_ci                               16,
1296bf215546Sopenharmony_ci                               &staging_buffer[program.data_size],
1297bf215546Sopenharmony_ci                               program.code_size,
1298bf215546Sopenharmony_ci                               16,
1299bf215546Sopenharmony_ci                               16,
1300bf215546Sopenharmony_ci                               upload_out);
1301bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
1302bf215546Sopenharmony_ci      vk_free(&device->vk.alloc, staging_buffer);
1303bf215546Sopenharmony_ci      pvr_bo_free(device, sw_compute_barrier_upload_out->pvr_bo);
1304bf215546Sopenharmony_ci
1305bf215546Sopenharmony_ci      return result;
1306bf215546Sopenharmony_ci   }
1307bf215546Sopenharmony_ci
1308bf215546Sopenharmony_ci   vk_free(&device->vk.alloc, staging_buffer);
1309bf215546Sopenharmony_ci
1310bf215546Sopenharmony_ci   return VK_SUCCESS;
1311bf215546Sopenharmony_ci}
1312bf215546Sopenharmony_ci
1313bf215546Sopenharmony_cistatic VkResult pvr_device_init_compute_idfwdf_state(struct pvr_device *device)
1314bf215546Sopenharmony_ci{
1315bf215546Sopenharmony_ci   uint64_t sampler_state[ROGUE_NUM_TEXSTATE_SAMPLER_WORDS];
1316bf215546Sopenharmony_ci   uint64_t image_state[ROGUE_NUM_TEXSTATE_IMAGE_WORDS];
1317bf215546Sopenharmony_ci   const struct rogue_shader_binary *usc_program;
1318bf215546Sopenharmony_ci   struct pvr_texture_state_info tex_info;
1319bf215546Sopenharmony_ci   uint32_t *dword_ptr;
1320bf215546Sopenharmony_ci   uint32_t usc_shareds;
1321bf215546Sopenharmony_ci   uint32_t usc_temps;
1322bf215546Sopenharmony_ci   VkResult result;
1323bf215546Sopenharmony_ci
1324bf215546Sopenharmony_ci   pvr_hard_code_get_idfwdf_program(&device->pdevice->dev_info,
1325bf215546Sopenharmony_ci                                    &usc_program,
1326bf215546Sopenharmony_ci                                    &usc_shareds,
1327bf215546Sopenharmony_ci                                    &usc_temps);
1328bf215546Sopenharmony_ci
1329bf215546Sopenharmony_ci   device->idfwdf_state.usc_shareds = usc_shareds;
1330bf215546Sopenharmony_ci
1331bf215546Sopenharmony_ci   /* FIXME: Figure out the define for alignment of 16. */
1332bf215546Sopenharmony_ci   result = pvr_gpu_upload_usc(device,
1333bf215546Sopenharmony_ci                               usc_program->data,
1334bf215546Sopenharmony_ci                               usc_program->size,
1335bf215546Sopenharmony_ci                               16,
1336bf215546Sopenharmony_ci                               &device->idfwdf_state.usc);
1337bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1338bf215546Sopenharmony_ci      return result;
1339bf215546Sopenharmony_ci
1340bf215546Sopenharmony_ci   /* TODO: Get the store buffer size from the compiler? */
1341bf215546Sopenharmony_ci   /* TODO: How was the size derived here? */
1342bf215546Sopenharmony_ci   result = pvr_bo_alloc(device,
1343bf215546Sopenharmony_ci                         device->heaps.general_heap,
1344bf215546Sopenharmony_ci                         4 * sizeof(float) * 4 * 2,
1345bf215546Sopenharmony_ci                         4,
1346bf215546Sopenharmony_ci                         0,
1347bf215546Sopenharmony_ci                         &device->idfwdf_state.store_bo);
1348bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1349bf215546Sopenharmony_ci      goto err_free_usc_program;
1350bf215546Sopenharmony_ci
1351bf215546Sopenharmony_ci   result = pvr_bo_alloc(device,
1352bf215546Sopenharmony_ci                         device->heaps.general_heap,
1353bf215546Sopenharmony_ci                         usc_shareds * ROGUE_REG_SIZE_BYTES,
1354bf215546Sopenharmony_ci                         ROGUE_REG_SIZE_BYTES,
1355bf215546Sopenharmony_ci                         PVR_BO_ALLOC_FLAG_CPU_MAPPED,
1356bf215546Sopenharmony_ci                         &device->idfwdf_state.shareds_bo);
1357bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1358bf215546Sopenharmony_ci      goto err_free_store_buffer;
1359bf215546Sopenharmony_ci
1360bf215546Sopenharmony_ci   /* Pack state words. */
1361bf215546Sopenharmony_ci
1362bf215546Sopenharmony_ci   pvr_csb_pack (&sampler_state[0], TEXSTATE_SAMPLER, sampler) {
1363bf215546Sopenharmony_ci      sampler.dadjust = PVRX(TEXSTATE_DADJUST_ZERO_UINT);
1364bf215546Sopenharmony_ci      sampler.magfilter = PVRX(TEXSTATE_FILTER_POINT);
1365bf215546Sopenharmony_ci      sampler.addrmode_u = PVRX(TEXSTATE_ADDRMODE_CLAMP_TO_EDGE);
1366bf215546Sopenharmony_ci      sampler.addrmode_v = PVRX(TEXSTATE_ADDRMODE_CLAMP_TO_EDGE);
1367bf215546Sopenharmony_ci   }
1368bf215546Sopenharmony_ci
1369bf215546Sopenharmony_ci   /* clang-format off */
1370bf215546Sopenharmony_ci   pvr_csb_pack (&sampler_state[1], TEXSTATE_SAMPLER_WORD1, sampler_word1) {}
1371bf215546Sopenharmony_ci   /* clang-format on */
1372bf215546Sopenharmony_ci
1373bf215546Sopenharmony_ci   STATIC_ASSERT(1 + 1 == ROGUE_NUM_TEXSTATE_SAMPLER_WORDS);
1374bf215546Sopenharmony_ci
1375bf215546Sopenharmony_ci   tex_info = (struct pvr_texture_state_info){
1376bf215546Sopenharmony_ci      .format = VK_FORMAT_R32G32B32A32_SFLOAT,
1377bf215546Sopenharmony_ci      .mem_layout = PVR_MEMLAYOUT_LINEAR,
1378bf215546Sopenharmony_ci      .flags = PVR_TEXFLAGS_INDEX_LOOKUP,
1379bf215546Sopenharmony_ci      /* TODO: Is this correct? Is it 2D, 3D, or 2D_ARRAY? */
1380bf215546Sopenharmony_ci      .type = VK_IMAGE_VIEW_TYPE_2D,
1381bf215546Sopenharmony_ci      .extent = { .width = 4, .height = 2, .depth = 0 },
1382bf215546Sopenharmony_ci      .mip_levels = 1,
1383bf215546Sopenharmony_ci      .sample_count = 1,
1384bf215546Sopenharmony_ci      .stride = 4,
1385bf215546Sopenharmony_ci      .swizzle = { PIPE_SWIZZLE_X,
1386bf215546Sopenharmony_ci                   PIPE_SWIZZLE_Y,
1387bf215546Sopenharmony_ci                   PIPE_SWIZZLE_Z,
1388bf215546Sopenharmony_ci                   PIPE_SWIZZLE_W },
1389bf215546Sopenharmony_ci      .addr = device->idfwdf_state.store_bo->vma->dev_addr,
1390bf215546Sopenharmony_ci   };
1391bf215546Sopenharmony_ci
1392bf215546Sopenharmony_ci   result = pvr_pack_tex_state(device, &tex_info, image_state);
1393bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1394bf215546Sopenharmony_ci      goto err_free_shareds_buffer;
1395bf215546Sopenharmony_ci
1396bf215546Sopenharmony_ci   /* Fill the shareds buffer. */
1397bf215546Sopenharmony_ci
1398bf215546Sopenharmony_ci   dword_ptr = (uint32_t *)device->idfwdf_state.shareds_bo->bo->map;
1399bf215546Sopenharmony_ci
1400bf215546Sopenharmony_ci#define HIGH_32(val) ((uint32_t)((val) >> 32U))
1401bf215546Sopenharmony_ci#define LOW_32(val) ((uint32_t)(val))
1402bf215546Sopenharmony_ci
1403bf215546Sopenharmony_ci   /* TODO: Should we use compiler info to setup the shareds data instead of
1404bf215546Sopenharmony_ci    * assuming there's always 12 and this is how they should be setup?
1405bf215546Sopenharmony_ci    */
1406bf215546Sopenharmony_ci
1407bf215546Sopenharmony_ci   dword_ptr[0] = HIGH_32(device->idfwdf_state.store_bo->vma->dev_addr.addr);
1408bf215546Sopenharmony_ci   dword_ptr[1] = LOW_32(device->idfwdf_state.store_bo->vma->dev_addr.addr);
1409bf215546Sopenharmony_ci
1410bf215546Sopenharmony_ci   /* Pad the shareds as the texture/sample state words are 128 bit aligned. */
1411bf215546Sopenharmony_ci   dword_ptr[2] = 0U;
1412bf215546Sopenharmony_ci   dword_ptr[3] = 0U;
1413bf215546Sopenharmony_ci
1414bf215546Sopenharmony_ci   dword_ptr[4] = LOW_32(image_state[0]);
1415bf215546Sopenharmony_ci   dword_ptr[5] = HIGH_32(image_state[0]);
1416bf215546Sopenharmony_ci   dword_ptr[6] = LOW_32(image_state[1]);
1417bf215546Sopenharmony_ci   dword_ptr[7] = HIGH_32(image_state[1]);
1418bf215546Sopenharmony_ci
1419bf215546Sopenharmony_ci   dword_ptr[8] = LOW_32(sampler_state[0]);
1420bf215546Sopenharmony_ci   dword_ptr[9] = HIGH_32(sampler_state[0]);
1421bf215546Sopenharmony_ci   dword_ptr[10] = LOW_32(sampler_state[1]);
1422bf215546Sopenharmony_ci   dword_ptr[11] = HIGH_32(sampler_state[1]);
1423bf215546Sopenharmony_ci   assert(11 + 1 == usc_shareds);
1424bf215546Sopenharmony_ci
1425bf215546Sopenharmony_ci#undef HIGH_32
1426bf215546Sopenharmony_ci#undef LOW_32
1427bf215546Sopenharmony_ci
1428bf215546Sopenharmony_ci   pvr_bo_cpu_unmap(device, device->idfwdf_state.shareds_bo);
1429bf215546Sopenharmony_ci   dword_ptr = NULL;
1430bf215546Sopenharmony_ci
1431bf215546Sopenharmony_ci   /* Generate and upload PDS programs. */
1432bf215546Sopenharmony_ci   result = pvr_pds_idfwdf_programs_create_and_upload(
1433bf215546Sopenharmony_ci      device,
1434bf215546Sopenharmony_ci      device->idfwdf_state.usc->vma->dev_addr,
1435bf215546Sopenharmony_ci      usc_shareds,
1436bf215546Sopenharmony_ci      usc_temps,
1437bf215546Sopenharmony_ci      device->idfwdf_state.shareds_bo->vma->dev_addr,
1438bf215546Sopenharmony_ci      &device->idfwdf_state.pds,
1439bf215546Sopenharmony_ci      &device->idfwdf_state.sw_compute_barrier_pds);
1440bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1441bf215546Sopenharmony_ci      goto err_free_shareds_buffer;
1442bf215546Sopenharmony_ci
1443bf215546Sopenharmony_ci   return VK_SUCCESS;
1444bf215546Sopenharmony_ci
1445bf215546Sopenharmony_cierr_free_shareds_buffer:
1446bf215546Sopenharmony_ci   pvr_bo_free(device, device->idfwdf_state.shareds_bo);
1447bf215546Sopenharmony_ci
1448bf215546Sopenharmony_cierr_free_store_buffer:
1449bf215546Sopenharmony_ci   pvr_bo_free(device, device->idfwdf_state.store_bo);
1450bf215546Sopenharmony_ci
1451bf215546Sopenharmony_cierr_free_usc_program:
1452bf215546Sopenharmony_ci   pvr_bo_free(device, device->idfwdf_state.usc);
1453bf215546Sopenharmony_ci
1454bf215546Sopenharmony_ci   return result;
1455bf215546Sopenharmony_ci}
1456bf215546Sopenharmony_ci
1457bf215546Sopenharmony_cistatic void pvr_device_finish_compute_idfwdf_state(struct pvr_device *device)
1458bf215546Sopenharmony_ci{
1459bf215546Sopenharmony_ci   pvr_bo_free(device, device->idfwdf_state.pds.pvr_bo);
1460bf215546Sopenharmony_ci   pvr_bo_free(device, device->idfwdf_state.sw_compute_barrier_pds.pvr_bo);
1461bf215546Sopenharmony_ci   pvr_bo_free(device, device->idfwdf_state.shareds_bo);
1462bf215546Sopenharmony_ci   pvr_bo_free(device, device->idfwdf_state.store_bo);
1463bf215546Sopenharmony_ci   pvr_bo_free(device, device->idfwdf_state.usc);
1464bf215546Sopenharmony_ci}
1465bf215546Sopenharmony_ci
1466bf215546Sopenharmony_ci/* FIXME: We should be calculating the size when we upload the code in
1467bf215546Sopenharmony_ci * pvr_srv_setup_static_pixel_event_program().
1468bf215546Sopenharmony_ci */
1469bf215546Sopenharmony_cistatic void pvr_device_get_pixel_event_pds_program_data_size(
1470bf215546Sopenharmony_ci   const struct pvr_device_info *dev_info,
1471bf215546Sopenharmony_ci   uint32_t *const data_size_in_dwords_out)
1472bf215546Sopenharmony_ci{
1473bf215546Sopenharmony_ci   struct pvr_pds_event_program program = {
1474bf215546Sopenharmony_ci      /* No data to DMA, just a DOUTU needed. */
1475bf215546Sopenharmony_ci      .num_emit_word_pairs = 0,
1476bf215546Sopenharmony_ci   };
1477bf215546Sopenharmony_ci
1478bf215546Sopenharmony_ci   pvr_pds_set_sizes_pixel_event(&program, dev_info);
1479bf215546Sopenharmony_ci
1480bf215546Sopenharmony_ci   *data_size_in_dwords_out = program.data_size;
1481bf215546Sopenharmony_ci}
1482bf215546Sopenharmony_ci
1483bf215546Sopenharmony_cistatic VkResult pvr_device_init_nop_program(struct pvr_device *device)
1484bf215546Sopenharmony_ci{
1485bf215546Sopenharmony_ci   const uint32_t cache_line_size =
1486bf215546Sopenharmony_ci      rogue_get_slc_cache_line_size(&device->pdevice->dev_info);
1487bf215546Sopenharmony_ci   struct pvr_pds_kickusc_program program = { 0 };
1488bf215546Sopenharmony_ci   uint32_t staging_buffer_size;
1489bf215546Sopenharmony_ci   uint32_t *staging_buffer;
1490bf215546Sopenharmony_ci   VkResult result;
1491bf215546Sopenharmony_ci
1492bf215546Sopenharmony_ci   result = pvr_gpu_upload_usc(device,
1493bf215546Sopenharmony_ci                               pvr_nop_usc_code,
1494bf215546Sopenharmony_ci                               sizeof(pvr_nop_usc_code),
1495bf215546Sopenharmony_ci                               cache_line_size,
1496bf215546Sopenharmony_ci                               &device->nop_program.usc);
1497bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1498bf215546Sopenharmony_ci      return result;
1499bf215546Sopenharmony_ci
1500bf215546Sopenharmony_ci   /* Setup a PDS program that kicks the static USC program. */
1501bf215546Sopenharmony_ci   pvr_pds_setup_doutu(&program.usc_task_control,
1502bf215546Sopenharmony_ci                       device->nop_program.usc->vma->dev_addr.addr,
1503bf215546Sopenharmony_ci                       0U,
1504bf215546Sopenharmony_ci                       PVRX(PDSINST_DOUTU_SAMPLE_RATE_INSTANCE),
1505bf215546Sopenharmony_ci                       false);
1506bf215546Sopenharmony_ci
1507bf215546Sopenharmony_ci   pvr_pds_set_sizes_pixel_shader(&program);
1508bf215546Sopenharmony_ci
1509bf215546Sopenharmony_ci   staging_buffer_size =
1510bf215546Sopenharmony_ci      (program.code_size + program.data_size) * sizeof(*staging_buffer);
1511bf215546Sopenharmony_ci
1512bf215546Sopenharmony_ci   staging_buffer = vk_alloc(&device->vk.alloc,
1513bf215546Sopenharmony_ci                             staging_buffer_size,
1514bf215546Sopenharmony_ci                             8U,
1515bf215546Sopenharmony_ci                             VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
1516bf215546Sopenharmony_ci   if (!staging_buffer) {
1517bf215546Sopenharmony_ci      result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1518bf215546Sopenharmony_ci      goto err_free_nop_usc_bo;
1519bf215546Sopenharmony_ci   }
1520bf215546Sopenharmony_ci
1521bf215546Sopenharmony_ci   pvr_pds_generate_pixel_shader_program(&program, staging_buffer);
1522bf215546Sopenharmony_ci
1523bf215546Sopenharmony_ci   /* FIXME: Figure out the define for alignment of 16. */
1524bf215546Sopenharmony_ci   result = pvr_gpu_upload_pds(device,
1525bf215546Sopenharmony_ci                               staging_buffer,
1526bf215546Sopenharmony_ci                               program.data_size,
1527bf215546Sopenharmony_ci                               16U,
1528bf215546Sopenharmony_ci                               &staging_buffer[program.data_size],
1529bf215546Sopenharmony_ci                               program.code_size,
1530bf215546Sopenharmony_ci                               16U,
1531bf215546Sopenharmony_ci                               16U,
1532bf215546Sopenharmony_ci                               &device->nop_program.pds);
1533bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1534bf215546Sopenharmony_ci      goto err_free_staging_buffer;
1535bf215546Sopenharmony_ci
1536bf215546Sopenharmony_ci   vk_free(&device->vk.alloc, staging_buffer);
1537bf215546Sopenharmony_ci
1538bf215546Sopenharmony_ci   return VK_SUCCESS;
1539bf215546Sopenharmony_ci
1540bf215546Sopenharmony_cierr_free_staging_buffer:
1541bf215546Sopenharmony_ci   vk_free(&device->vk.alloc, staging_buffer);
1542bf215546Sopenharmony_ci
1543bf215546Sopenharmony_cierr_free_nop_usc_bo:
1544bf215546Sopenharmony_ci   pvr_bo_free(device, device->nop_program.usc);
1545bf215546Sopenharmony_ci
1546bf215546Sopenharmony_ci   return result;
1547bf215546Sopenharmony_ci}
1548bf215546Sopenharmony_ci
1549bf215546Sopenharmony_cistatic void pvr_device_init_default_sampler_state(struct pvr_device *device)
1550bf215546Sopenharmony_ci{
1551bf215546Sopenharmony_ci   pvr_csb_pack (&device->input_attachment_sampler, TEXSTATE_SAMPLER, sampler) {
1552bf215546Sopenharmony_ci      sampler.addrmode_u = PVRX(TEXSTATE_ADDRMODE_CLAMP_TO_EDGE);
1553bf215546Sopenharmony_ci      sampler.addrmode_v = PVRX(TEXSTATE_ADDRMODE_CLAMP_TO_EDGE);
1554bf215546Sopenharmony_ci      sampler.addrmode_w = PVRX(TEXSTATE_ADDRMODE_CLAMP_TO_EDGE);
1555bf215546Sopenharmony_ci      sampler.dadjust = PVRX(TEXSTATE_DADJUST_ZERO_UINT);
1556bf215546Sopenharmony_ci      sampler.magfilter = PVRX(TEXSTATE_FILTER_POINT);
1557bf215546Sopenharmony_ci      sampler.minfilter = PVRX(TEXSTATE_FILTER_POINT);
1558bf215546Sopenharmony_ci      sampler.anisoctl = PVRX(TEXSTATE_ANISOCTL_DISABLED);
1559bf215546Sopenharmony_ci      sampler.non_normalized_coords = true;
1560bf215546Sopenharmony_ci   }
1561bf215546Sopenharmony_ci}
1562bf215546Sopenharmony_ci
1563bf215546Sopenharmony_ciVkResult pvr_CreateDevice(VkPhysicalDevice physicalDevice,
1564bf215546Sopenharmony_ci                          const VkDeviceCreateInfo *pCreateInfo,
1565bf215546Sopenharmony_ci                          const VkAllocationCallbacks *pAllocator,
1566bf215546Sopenharmony_ci                          VkDevice *pDevice)
1567bf215546Sopenharmony_ci{
1568bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_physical_device, pdevice, physicalDevice);
1569bf215546Sopenharmony_ci   struct pvr_instance *instance = pdevice->instance;
1570bf215546Sopenharmony_ci   struct vk_device_dispatch_table dispatch_table;
1571bf215546Sopenharmony_ci   struct pvr_device *device;
1572bf215546Sopenharmony_ci   VkResult result;
1573bf215546Sopenharmony_ci
1574bf215546Sopenharmony_ci   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO);
1575bf215546Sopenharmony_ci
1576bf215546Sopenharmony_ci   device = vk_alloc2(&pdevice->vk.instance->alloc,
1577bf215546Sopenharmony_ci                      pAllocator,
1578bf215546Sopenharmony_ci                      sizeof(*device),
1579bf215546Sopenharmony_ci                      8,
1580bf215546Sopenharmony_ci                      VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1581bf215546Sopenharmony_ci   if (!device)
1582bf215546Sopenharmony_ci      return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1583bf215546Sopenharmony_ci
1584bf215546Sopenharmony_ci   vk_device_dispatch_table_from_entrypoints(&dispatch_table,
1585bf215546Sopenharmony_ci                                             &pvr_device_entrypoints,
1586bf215546Sopenharmony_ci                                             true);
1587bf215546Sopenharmony_ci
1588bf215546Sopenharmony_ci   vk_device_dispatch_table_from_entrypoints(&dispatch_table,
1589bf215546Sopenharmony_ci                                             &wsi_device_entrypoints,
1590bf215546Sopenharmony_ci                                             false);
1591bf215546Sopenharmony_ci
1592bf215546Sopenharmony_ci   result = vk_device_init(&device->vk,
1593bf215546Sopenharmony_ci                           &pdevice->vk,
1594bf215546Sopenharmony_ci                           &dispatch_table,
1595bf215546Sopenharmony_ci                           pCreateInfo,
1596bf215546Sopenharmony_ci                           pAllocator);
1597bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1598bf215546Sopenharmony_ci      goto err_free_device;
1599bf215546Sopenharmony_ci
1600bf215546Sopenharmony_ci   device->render_fd = open(pdevice->render_path, O_RDWR | O_CLOEXEC);
1601bf215546Sopenharmony_ci   if (device->render_fd < 0) {
1602bf215546Sopenharmony_ci      result = vk_errorf(instance,
1603bf215546Sopenharmony_ci                         VK_ERROR_INITIALIZATION_FAILED,
1604bf215546Sopenharmony_ci                         "Failed to open device %s",
1605bf215546Sopenharmony_ci                         pdevice->render_path);
1606bf215546Sopenharmony_ci      goto err_vk_device_finish;
1607bf215546Sopenharmony_ci   }
1608bf215546Sopenharmony_ci
1609bf215546Sopenharmony_ci   if (pdevice->master_path)
1610bf215546Sopenharmony_ci      device->master_fd = open(pdevice->master_path, O_RDWR | O_CLOEXEC);
1611bf215546Sopenharmony_ci   else
1612bf215546Sopenharmony_ci      device->master_fd = -1;
1613bf215546Sopenharmony_ci
1614bf215546Sopenharmony_ci   vk_device_set_drm_fd(&device->vk, device->render_fd);
1615bf215546Sopenharmony_ci
1616bf215546Sopenharmony_ci   device->instance = instance;
1617bf215546Sopenharmony_ci   device->pdevice = pdevice;
1618bf215546Sopenharmony_ci
1619bf215546Sopenharmony_ci   device->ws = pvr_winsys_create(device->master_fd,
1620bf215546Sopenharmony_ci                                  device->render_fd,
1621bf215546Sopenharmony_ci                                  &device->vk.alloc);
1622bf215546Sopenharmony_ci   if (!device->ws) {
1623bf215546Sopenharmony_ci      result = VK_ERROR_INITIALIZATION_FAILED;
1624bf215546Sopenharmony_ci      goto err_close_master_fd;
1625bf215546Sopenharmony_ci   }
1626bf215546Sopenharmony_ci
1627bf215546Sopenharmony_ci   device->ws->ops->get_heaps_info(device->ws, &device->heaps);
1628bf215546Sopenharmony_ci
1629bf215546Sopenharmony_ci   result = pvr_free_list_create(device,
1630bf215546Sopenharmony_ci                                 PVR_GLOBAL_FREE_LIST_INITIAL_SIZE,
1631bf215546Sopenharmony_ci                                 PVR_GLOBAL_FREE_LIST_MAX_SIZE,
1632bf215546Sopenharmony_ci                                 PVR_GLOBAL_FREE_LIST_GROW_SIZE,
1633bf215546Sopenharmony_ci                                 PVR_GLOBAL_FREE_LIST_GROW_THRESHOLD,
1634bf215546Sopenharmony_ci                                 NULL /* parent_free_list */,
1635bf215546Sopenharmony_ci                                 &device->global_free_list);
1636bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1637bf215546Sopenharmony_ci      goto err_pvr_winsys_destroy;
1638bf215546Sopenharmony_ci
1639bf215546Sopenharmony_ci   result = pvr_device_init_nop_program(device);
1640bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1641bf215546Sopenharmony_ci      goto err_pvr_free_list_destroy;
1642bf215546Sopenharmony_ci
1643bf215546Sopenharmony_ci   result = pvr_device_init_compute_fence_program(device);
1644bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1645bf215546Sopenharmony_ci      goto err_pvr_free_nop_program;
1646bf215546Sopenharmony_ci
1647bf215546Sopenharmony_ci   result = pvr_device_init_compute_idfwdf_state(device);
1648bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1649bf215546Sopenharmony_ci      goto err_pvr_free_compute_fence;
1650bf215546Sopenharmony_ci
1651bf215546Sopenharmony_ci   result = pvr_queues_create(device, pCreateInfo);
1652bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1653bf215546Sopenharmony_ci      goto err_pvr_finish_compute_idfwdf;
1654bf215546Sopenharmony_ci
1655bf215546Sopenharmony_ci   pvr_device_init_default_sampler_state(device);
1656bf215546Sopenharmony_ci
1657bf215546Sopenharmony_ci   if (pCreateInfo->pEnabledFeatures)
1658bf215546Sopenharmony_ci      memcpy(&device->features,
1659bf215546Sopenharmony_ci             pCreateInfo->pEnabledFeatures,
1660bf215546Sopenharmony_ci             sizeof(device->features));
1661bf215546Sopenharmony_ci
1662bf215546Sopenharmony_ci   /* FIXME: Move this to a later stage and possibly somewhere other than
1663bf215546Sopenharmony_ci    * pvr_device. The purpose of this is so that we don't have to get the size
1664bf215546Sopenharmony_ci    * on each kick.
1665bf215546Sopenharmony_ci    */
1666bf215546Sopenharmony_ci   pvr_device_get_pixel_event_pds_program_data_size(
1667bf215546Sopenharmony_ci      &pdevice->dev_info,
1668bf215546Sopenharmony_ci      &device->pixel_event_data_size_in_dwords);
1669bf215546Sopenharmony_ci
1670bf215546Sopenharmony_ci   device->global_queue_job_count = 0;
1671bf215546Sopenharmony_ci   device->global_queue_present_count = 0;
1672bf215546Sopenharmony_ci
1673bf215546Sopenharmony_ci   *pDevice = pvr_device_to_handle(device);
1674bf215546Sopenharmony_ci
1675bf215546Sopenharmony_ci   return VK_SUCCESS;
1676bf215546Sopenharmony_ci
1677bf215546Sopenharmony_cierr_pvr_finish_compute_idfwdf:
1678bf215546Sopenharmony_ci   pvr_device_finish_compute_idfwdf_state(device);
1679bf215546Sopenharmony_ci
1680bf215546Sopenharmony_cierr_pvr_free_compute_fence:
1681bf215546Sopenharmony_ci   pvr_bo_free(device, device->pds_compute_fence_program.pvr_bo);
1682bf215546Sopenharmony_ci
1683bf215546Sopenharmony_cierr_pvr_free_nop_program:
1684bf215546Sopenharmony_ci   pvr_bo_free(device, device->nop_program.pds.pvr_bo);
1685bf215546Sopenharmony_ci   pvr_bo_free(device, device->nop_program.usc);
1686bf215546Sopenharmony_ci
1687bf215546Sopenharmony_cierr_pvr_free_list_destroy:
1688bf215546Sopenharmony_ci   pvr_free_list_destroy(device->global_free_list);
1689bf215546Sopenharmony_ci
1690bf215546Sopenharmony_cierr_pvr_winsys_destroy:
1691bf215546Sopenharmony_ci   pvr_winsys_destroy(device->ws);
1692bf215546Sopenharmony_ci
1693bf215546Sopenharmony_cierr_close_master_fd:
1694bf215546Sopenharmony_ci   if (device->master_fd >= 0)
1695bf215546Sopenharmony_ci      close(device->master_fd);
1696bf215546Sopenharmony_ci
1697bf215546Sopenharmony_ci   close(device->render_fd);
1698bf215546Sopenharmony_ci
1699bf215546Sopenharmony_cierr_vk_device_finish:
1700bf215546Sopenharmony_ci   vk_device_finish(&device->vk);
1701bf215546Sopenharmony_ci
1702bf215546Sopenharmony_cierr_free_device:
1703bf215546Sopenharmony_ci   vk_free(&device->vk.alloc, device);
1704bf215546Sopenharmony_ci
1705bf215546Sopenharmony_ci   return result;
1706bf215546Sopenharmony_ci}
1707bf215546Sopenharmony_ci
1708bf215546Sopenharmony_civoid pvr_DestroyDevice(VkDevice _device,
1709bf215546Sopenharmony_ci                       const VkAllocationCallbacks *pAllocator)
1710bf215546Sopenharmony_ci{
1711bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device, device, _device);
1712bf215546Sopenharmony_ci
1713bf215546Sopenharmony_ci   pvr_queues_destroy(device);
1714bf215546Sopenharmony_ci   pvr_device_finish_compute_idfwdf_state(device);
1715bf215546Sopenharmony_ci   pvr_bo_free(device, device->pds_compute_fence_program.pvr_bo);
1716bf215546Sopenharmony_ci   pvr_bo_free(device, device->nop_program.pds.pvr_bo);
1717bf215546Sopenharmony_ci   pvr_bo_free(device, device->nop_program.usc);
1718bf215546Sopenharmony_ci   pvr_free_list_destroy(device->global_free_list);
1719bf215546Sopenharmony_ci   pvr_winsys_destroy(device->ws);
1720bf215546Sopenharmony_ci   close(device->render_fd);
1721bf215546Sopenharmony_ci   vk_device_finish(&device->vk);
1722bf215546Sopenharmony_ci   vk_free(&device->vk.alloc, device);
1723bf215546Sopenharmony_ci}
1724bf215546Sopenharmony_ci
1725bf215546Sopenharmony_ciVkResult pvr_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
1726bf215546Sopenharmony_ci                                              VkLayerProperties *pProperties)
1727bf215546Sopenharmony_ci{
1728bf215546Sopenharmony_ci   if (!pProperties) {
1729bf215546Sopenharmony_ci      *pPropertyCount = 0;
1730bf215546Sopenharmony_ci      return VK_SUCCESS;
1731bf215546Sopenharmony_ci   }
1732bf215546Sopenharmony_ci
1733bf215546Sopenharmony_ci   return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
1734bf215546Sopenharmony_ci}
1735bf215546Sopenharmony_ci
1736bf215546Sopenharmony_ciVkResult pvr_AllocateMemory(VkDevice _device,
1737bf215546Sopenharmony_ci                            const VkMemoryAllocateInfo *pAllocateInfo,
1738bf215546Sopenharmony_ci                            const VkAllocationCallbacks *pAllocator,
1739bf215546Sopenharmony_ci                            VkDeviceMemory *pMem)
1740bf215546Sopenharmony_ci{
1741bf215546Sopenharmony_ci   const VkImportMemoryFdInfoKHR *fd_info = NULL;
1742bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device, device, _device);
1743bf215546Sopenharmony_ci   enum pvr_winsys_bo_type type = PVR_WINSYS_BO_TYPE_GPU;
1744bf215546Sopenharmony_ci   struct pvr_device_memory *mem;
1745bf215546Sopenharmony_ci   VkResult result;
1746bf215546Sopenharmony_ci
1747bf215546Sopenharmony_ci   assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
1748bf215546Sopenharmony_ci   assert(pAllocateInfo->allocationSize > 0);
1749bf215546Sopenharmony_ci
1750bf215546Sopenharmony_ci   mem = vk_object_alloc(&device->vk,
1751bf215546Sopenharmony_ci                         pAllocator,
1752bf215546Sopenharmony_ci                         sizeof(*mem),
1753bf215546Sopenharmony_ci                         VK_OBJECT_TYPE_DEVICE_MEMORY);
1754bf215546Sopenharmony_ci   if (!mem)
1755bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1756bf215546Sopenharmony_ci
1757bf215546Sopenharmony_ci   vk_foreach_struct_const (ext, pAllocateInfo->pNext) {
1758bf215546Sopenharmony_ci      switch ((unsigned)ext->sType) {
1759bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA:
1760bf215546Sopenharmony_ci         type = PVR_WINSYS_BO_TYPE_DISPLAY;
1761bf215546Sopenharmony_ci         break;
1762bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR:
1763bf215546Sopenharmony_ci         fd_info = (void *)ext;
1764bf215546Sopenharmony_ci         break;
1765bf215546Sopenharmony_ci      default:
1766bf215546Sopenharmony_ci         pvr_debug_ignored_stype(ext->sType);
1767bf215546Sopenharmony_ci         break;
1768bf215546Sopenharmony_ci      }
1769bf215546Sopenharmony_ci   }
1770bf215546Sopenharmony_ci
1771bf215546Sopenharmony_ci   if (fd_info && fd_info->handleType) {
1772bf215546Sopenharmony_ci      VkDeviceSize aligned_alloc_size =
1773bf215546Sopenharmony_ci         ALIGN_POT(pAllocateInfo->allocationSize, device->ws->page_size);
1774bf215546Sopenharmony_ci
1775bf215546Sopenharmony_ci      assert(
1776bf215546Sopenharmony_ci         fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
1777bf215546Sopenharmony_ci         fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
1778bf215546Sopenharmony_ci
1779bf215546Sopenharmony_ci      result = device->ws->ops->buffer_create_from_fd(device->ws,
1780bf215546Sopenharmony_ci                                                      fd_info->fd,
1781bf215546Sopenharmony_ci                                                      &mem->bo);
1782bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
1783bf215546Sopenharmony_ci         goto err_vk_object_free_mem;
1784bf215546Sopenharmony_ci
1785bf215546Sopenharmony_ci      /* For security purposes, we reject importing the bo if it's smaller
1786bf215546Sopenharmony_ci       * than the requested allocation size. This prevents a malicious client
1787bf215546Sopenharmony_ci       * from passing a buffer to a trusted client, lying about the size, and
1788bf215546Sopenharmony_ci       * telling the trusted client to try and texture from an image that goes
1789bf215546Sopenharmony_ci       * out-of-bounds. This sort of thing could lead to GPU hangs or worse
1790bf215546Sopenharmony_ci       * in the trusted client. The trusted client can protect itself against
1791bf215546Sopenharmony_ci       * this sort of attack but only if it can trust the buffer size.
1792bf215546Sopenharmony_ci       */
1793bf215546Sopenharmony_ci      if (aligned_alloc_size > mem->bo->size) {
1794bf215546Sopenharmony_ci         result = vk_errorf(device,
1795bf215546Sopenharmony_ci                            VK_ERROR_INVALID_EXTERNAL_HANDLE,
1796bf215546Sopenharmony_ci                            "Aligned requested size too large for the given fd "
1797bf215546Sopenharmony_ci                            "%" PRIu64 "B > %" PRIu64 "B",
1798bf215546Sopenharmony_ci                            pAllocateInfo->allocationSize,
1799bf215546Sopenharmony_ci                            mem->bo->size);
1800bf215546Sopenharmony_ci         device->ws->ops->buffer_destroy(mem->bo);
1801bf215546Sopenharmony_ci         goto err_vk_object_free_mem;
1802bf215546Sopenharmony_ci      }
1803bf215546Sopenharmony_ci
1804bf215546Sopenharmony_ci      /* From the Vulkan spec:
1805bf215546Sopenharmony_ci       *
1806bf215546Sopenharmony_ci       *    "Importing memory from a file descriptor transfers ownership of
1807bf215546Sopenharmony_ci       *    the file descriptor from the application to the Vulkan
1808bf215546Sopenharmony_ci       *    implementation. The application must not perform any operations on
1809bf215546Sopenharmony_ci       *    the file descriptor after a successful import."
1810bf215546Sopenharmony_ci       *
1811bf215546Sopenharmony_ci       * If the import fails, we leave the file descriptor open.
1812bf215546Sopenharmony_ci       */
1813bf215546Sopenharmony_ci      close(fd_info->fd);
1814bf215546Sopenharmony_ci   } else {
1815bf215546Sopenharmony_ci      /* Align physical allocations to the page size of the heap that will be
1816bf215546Sopenharmony_ci       * used when binding device memory (see pvr_bind_memory()) to ensure the
1817bf215546Sopenharmony_ci       * entire allocation can be mapped.
1818bf215546Sopenharmony_ci       */
1819bf215546Sopenharmony_ci      const uint64_t alignment = device->heaps.general_heap->page_size;
1820bf215546Sopenharmony_ci
1821bf215546Sopenharmony_ci      /* FIXME: Need to determine the flags based on
1822bf215546Sopenharmony_ci       * device->pdevice->memory.memoryTypes[pAllocateInfo->memoryTypeIndex].propertyFlags.
1823bf215546Sopenharmony_ci       *
1824bf215546Sopenharmony_ci       * The alternative would be to store the flags alongside the memory
1825bf215546Sopenharmony_ci       * types as an array that's indexed by pAllocateInfo->memoryTypeIndex so
1826bf215546Sopenharmony_ci       * that they can be looked up.
1827bf215546Sopenharmony_ci       */
1828bf215546Sopenharmony_ci      result = device->ws->ops->buffer_create(device->ws,
1829bf215546Sopenharmony_ci                                              pAllocateInfo->allocationSize,
1830bf215546Sopenharmony_ci                                              alignment,
1831bf215546Sopenharmony_ci                                              type,
1832bf215546Sopenharmony_ci                                              PVR_WINSYS_BO_FLAG_CPU_ACCESS,
1833bf215546Sopenharmony_ci                                              &mem->bo);
1834bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
1835bf215546Sopenharmony_ci         goto err_vk_object_free_mem;
1836bf215546Sopenharmony_ci   }
1837bf215546Sopenharmony_ci
1838bf215546Sopenharmony_ci   *pMem = pvr_device_memory_to_handle(mem);
1839bf215546Sopenharmony_ci
1840bf215546Sopenharmony_ci   return VK_SUCCESS;
1841bf215546Sopenharmony_ci
1842bf215546Sopenharmony_cierr_vk_object_free_mem:
1843bf215546Sopenharmony_ci   vk_object_free(&device->vk, pAllocator, mem);
1844bf215546Sopenharmony_ci
1845bf215546Sopenharmony_ci   return result;
1846bf215546Sopenharmony_ci}
1847bf215546Sopenharmony_ci
1848bf215546Sopenharmony_ciVkResult pvr_GetMemoryFdKHR(VkDevice _device,
1849bf215546Sopenharmony_ci                            const VkMemoryGetFdInfoKHR *pGetFdInfo,
1850bf215546Sopenharmony_ci                            int *pFd)
1851bf215546Sopenharmony_ci{
1852bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device, device, _device);
1853bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device_memory, mem, pGetFdInfo->memory);
1854bf215546Sopenharmony_ci
1855bf215546Sopenharmony_ci   assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);
1856bf215546Sopenharmony_ci
1857bf215546Sopenharmony_ci   assert(
1858bf215546Sopenharmony_ci      pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
1859bf215546Sopenharmony_ci      pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
1860bf215546Sopenharmony_ci
1861bf215546Sopenharmony_ci   return device->ws->ops->buffer_get_fd(mem->bo, pFd);
1862bf215546Sopenharmony_ci}
1863bf215546Sopenharmony_ci
1864bf215546Sopenharmony_ciVkResult
1865bf215546Sopenharmony_cipvr_GetMemoryFdPropertiesKHR(VkDevice _device,
1866bf215546Sopenharmony_ci                             VkExternalMemoryHandleTypeFlagBits handleType,
1867bf215546Sopenharmony_ci                             int fd,
1868bf215546Sopenharmony_ci                             VkMemoryFdPropertiesKHR *pMemoryFdProperties)
1869bf215546Sopenharmony_ci{
1870bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device, device, _device);
1871bf215546Sopenharmony_ci
1872bf215546Sopenharmony_ci   switch (handleType) {
1873bf215546Sopenharmony_ci   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
1874bf215546Sopenharmony_ci      /* FIXME: This should only allow memory types having
1875bf215546Sopenharmony_ci       * VK_MEMORY_PROPERTY_HOST_CACHED_BIT flag set, as
1876bf215546Sopenharmony_ci       * dma-buf should be imported using cacheable memory types,
1877bf215546Sopenharmony_ci       * given exporter's mmap will always map it as cacheable.
1878bf215546Sopenharmony_ci       * Ref:
1879bf215546Sopenharmony_ci       * https://www.kernel.org/doc/html/latest/driver-api/dma-buf.html#c.dma_buf_ops
1880bf215546Sopenharmony_ci       */
1881bf215546Sopenharmony_ci      pMemoryFdProperties->memoryTypeBits =
1882bf215546Sopenharmony_ci         (1 << device->pdevice->memory.memoryTypeCount) - 1;
1883bf215546Sopenharmony_ci      return VK_SUCCESS;
1884bf215546Sopenharmony_ci   default:
1885bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_INVALID_EXTERNAL_HANDLE);
1886bf215546Sopenharmony_ci   }
1887bf215546Sopenharmony_ci}
1888bf215546Sopenharmony_ci
1889bf215546Sopenharmony_civoid pvr_FreeMemory(VkDevice _device,
1890bf215546Sopenharmony_ci                    VkDeviceMemory _mem,
1891bf215546Sopenharmony_ci                    const VkAllocationCallbacks *pAllocator)
1892bf215546Sopenharmony_ci{
1893bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device, device, _device);
1894bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device_memory, mem, _mem);
1895bf215546Sopenharmony_ci
1896bf215546Sopenharmony_ci   if (!mem)
1897bf215546Sopenharmony_ci      return;
1898bf215546Sopenharmony_ci
1899bf215546Sopenharmony_ci   device->ws->ops->buffer_destroy(mem->bo);
1900bf215546Sopenharmony_ci
1901bf215546Sopenharmony_ci   vk_object_free(&device->vk, pAllocator, mem);
1902bf215546Sopenharmony_ci}
1903bf215546Sopenharmony_ci
1904bf215546Sopenharmony_ciVkResult pvr_MapMemory(VkDevice _device,
1905bf215546Sopenharmony_ci                       VkDeviceMemory _memory,
1906bf215546Sopenharmony_ci                       VkDeviceSize offset,
1907bf215546Sopenharmony_ci                       VkDeviceSize size,
1908bf215546Sopenharmony_ci                       VkMemoryMapFlags flags,
1909bf215546Sopenharmony_ci                       void **ppData)
1910bf215546Sopenharmony_ci{
1911bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device, device, _device);
1912bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device_memory, mem, _memory);
1913bf215546Sopenharmony_ci   void *map;
1914bf215546Sopenharmony_ci
1915bf215546Sopenharmony_ci   if (!mem) {
1916bf215546Sopenharmony_ci      *ppData = NULL;
1917bf215546Sopenharmony_ci      return VK_SUCCESS;
1918bf215546Sopenharmony_ci   }
1919bf215546Sopenharmony_ci
1920bf215546Sopenharmony_ci   if (size == VK_WHOLE_SIZE)
1921bf215546Sopenharmony_ci      size = mem->bo->size - offset;
1922bf215546Sopenharmony_ci
1923bf215546Sopenharmony_ci   /* From the Vulkan spec version 1.0.32 docs for MapMemory:
1924bf215546Sopenharmony_ci    *
1925bf215546Sopenharmony_ci    *  * If size is not equal to VK_WHOLE_SIZE, size must be greater than 0
1926bf215546Sopenharmony_ci    *    assert(size != 0);
1927bf215546Sopenharmony_ci    *  * If size is not equal to VK_WHOLE_SIZE, size must be less than or
1928bf215546Sopenharmony_ci    *    equal to the size of the memory minus offset
1929bf215546Sopenharmony_ci    */
1930bf215546Sopenharmony_ci
1931bf215546Sopenharmony_ci   assert(size > 0);
1932bf215546Sopenharmony_ci   assert(offset + size <= mem->bo->size);
1933bf215546Sopenharmony_ci
1934bf215546Sopenharmony_ci   /* Check if already mapped */
1935bf215546Sopenharmony_ci   if (mem->bo->map) {
1936bf215546Sopenharmony_ci      *ppData = mem->bo->map + offset;
1937bf215546Sopenharmony_ci      return VK_SUCCESS;
1938bf215546Sopenharmony_ci   }
1939bf215546Sopenharmony_ci
1940bf215546Sopenharmony_ci   /* Map it all at once */
1941bf215546Sopenharmony_ci   map = device->ws->ops->buffer_map(mem->bo);
1942bf215546Sopenharmony_ci   if (!map)
1943bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_MEMORY_MAP_FAILED);
1944bf215546Sopenharmony_ci
1945bf215546Sopenharmony_ci   *ppData = map + offset;
1946bf215546Sopenharmony_ci
1947bf215546Sopenharmony_ci   return VK_SUCCESS;
1948bf215546Sopenharmony_ci}
1949bf215546Sopenharmony_ci
1950bf215546Sopenharmony_civoid pvr_UnmapMemory(VkDevice _device, VkDeviceMemory _memory)
1951bf215546Sopenharmony_ci{
1952bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device, device, _device);
1953bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device_memory, mem, _memory);
1954bf215546Sopenharmony_ci
1955bf215546Sopenharmony_ci   if (!mem || !mem->bo->map)
1956bf215546Sopenharmony_ci      return;
1957bf215546Sopenharmony_ci
1958bf215546Sopenharmony_ci   device->ws->ops->buffer_unmap(mem->bo);
1959bf215546Sopenharmony_ci}
1960bf215546Sopenharmony_ci
1961bf215546Sopenharmony_ciVkResult pvr_FlushMappedMemoryRanges(VkDevice _device,
1962bf215546Sopenharmony_ci                                     uint32_t memoryRangeCount,
1963bf215546Sopenharmony_ci                                     const VkMappedMemoryRange *pMemoryRanges)
1964bf215546Sopenharmony_ci{
1965bf215546Sopenharmony_ci   return VK_SUCCESS;
1966bf215546Sopenharmony_ci}
1967bf215546Sopenharmony_ci
1968bf215546Sopenharmony_ciVkResult
1969bf215546Sopenharmony_cipvr_InvalidateMappedMemoryRanges(VkDevice _device,
1970bf215546Sopenharmony_ci                                 uint32_t memoryRangeCount,
1971bf215546Sopenharmony_ci                                 const VkMappedMemoryRange *pMemoryRanges)
1972bf215546Sopenharmony_ci{
1973bf215546Sopenharmony_ci   return VK_SUCCESS;
1974bf215546Sopenharmony_ci}
1975bf215546Sopenharmony_ci
1976bf215546Sopenharmony_civoid pvr_GetImageSparseMemoryRequirements2(
1977bf215546Sopenharmony_ci   VkDevice device,
1978bf215546Sopenharmony_ci   const VkImageSparseMemoryRequirementsInfo2 *pInfo,
1979bf215546Sopenharmony_ci   uint32_t *pSparseMemoryRequirementCount,
1980bf215546Sopenharmony_ci   VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
1981bf215546Sopenharmony_ci{
1982bf215546Sopenharmony_ci   *pSparseMemoryRequirementCount = 0;
1983bf215546Sopenharmony_ci}
1984bf215546Sopenharmony_ci
1985bf215546Sopenharmony_civoid pvr_GetDeviceMemoryCommitment(VkDevice device,
1986bf215546Sopenharmony_ci                                   VkDeviceMemory memory,
1987bf215546Sopenharmony_ci                                   VkDeviceSize *pCommittedMemoryInBytes)
1988bf215546Sopenharmony_ci{
1989bf215546Sopenharmony_ci   *pCommittedMemoryInBytes = 0;
1990bf215546Sopenharmony_ci}
1991bf215546Sopenharmony_ci
1992bf215546Sopenharmony_ciVkResult pvr_bind_memory(struct pvr_device *device,
1993bf215546Sopenharmony_ci                         struct pvr_device_memory *mem,
1994bf215546Sopenharmony_ci                         VkDeviceSize offset,
1995bf215546Sopenharmony_ci                         VkDeviceSize size,
1996bf215546Sopenharmony_ci                         VkDeviceSize alignment,
1997bf215546Sopenharmony_ci                         struct pvr_winsys_vma **const vma_out,
1998bf215546Sopenharmony_ci                         pvr_dev_addr_t *const dev_addr_out)
1999bf215546Sopenharmony_ci{
2000bf215546Sopenharmony_ci   VkDeviceSize virt_size =
2001bf215546Sopenharmony_ci      size + (offset & (device->heaps.general_heap->page_size - 1));
2002bf215546Sopenharmony_ci   struct pvr_winsys_vma *vma;
2003bf215546Sopenharmony_ci   pvr_dev_addr_t dev_addr;
2004bf215546Sopenharmony_ci
2005bf215546Sopenharmony_ci   /* Valid usage:
2006bf215546Sopenharmony_ci    *
2007bf215546Sopenharmony_ci    *   "memoryOffset must be an integer multiple of the alignment member of
2008bf215546Sopenharmony_ci    *    the VkMemoryRequirements structure returned from a call to
2009bf215546Sopenharmony_ci    *    vkGetBufferMemoryRequirements with buffer"
2010bf215546Sopenharmony_ci    *
2011bf215546Sopenharmony_ci    *   "memoryOffset must be an integer multiple of the alignment member of
2012bf215546Sopenharmony_ci    *    the VkMemoryRequirements structure returned from a call to
2013bf215546Sopenharmony_ci    *    vkGetImageMemoryRequirements with image"
2014bf215546Sopenharmony_ci    */
2015bf215546Sopenharmony_ci   assert(offset % alignment == 0);
2016bf215546Sopenharmony_ci   assert(offset < mem->bo->size);
2017bf215546Sopenharmony_ci
2018bf215546Sopenharmony_ci   vma = device->ws->ops->heap_alloc(device->heaps.general_heap,
2019bf215546Sopenharmony_ci                                     virt_size,
2020bf215546Sopenharmony_ci                                     alignment);
2021bf215546Sopenharmony_ci   if (!vma)
2022bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
2023bf215546Sopenharmony_ci
2024bf215546Sopenharmony_ci   dev_addr = device->ws->ops->vma_map(vma, mem->bo, offset, size);
2025bf215546Sopenharmony_ci   if (!dev_addr.addr) {
2026bf215546Sopenharmony_ci      device->ws->ops->heap_free(vma);
2027bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
2028bf215546Sopenharmony_ci   }
2029bf215546Sopenharmony_ci
2030bf215546Sopenharmony_ci   *dev_addr_out = dev_addr;
2031bf215546Sopenharmony_ci   *vma_out = vma;
2032bf215546Sopenharmony_ci
2033bf215546Sopenharmony_ci   return VK_SUCCESS;
2034bf215546Sopenharmony_ci}
2035bf215546Sopenharmony_ci
2036bf215546Sopenharmony_civoid pvr_unbind_memory(struct pvr_device *device, struct pvr_winsys_vma *vma)
2037bf215546Sopenharmony_ci{
2038bf215546Sopenharmony_ci   device->ws->ops->vma_unmap(vma);
2039bf215546Sopenharmony_ci   device->ws->ops->heap_free(vma);
2040bf215546Sopenharmony_ci}
2041bf215546Sopenharmony_ci
2042bf215546Sopenharmony_ciVkResult pvr_BindBufferMemory2(VkDevice _device,
2043bf215546Sopenharmony_ci                               uint32_t bindInfoCount,
2044bf215546Sopenharmony_ci                               const VkBindBufferMemoryInfo *pBindInfos)
2045bf215546Sopenharmony_ci{
2046bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device, device, _device);
2047bf215546Sopenharmony_ci   uint32_t i;
2048bf215546Sopenharmony_ci
2049bf215546Sopenharmony_ci   for (i = 0; i < bindInfoCount; i++) {
2050bf215546Sopenharmony_ci      PVR_FROM_HANDLE(pvr_device_memory, mem, pBindInfos[i].memory);
2051bf215546Sopenharmony_ci      PVR_FROM_HANDLE(pvr_buffer, buffer, pBindInfos[i].buffer);
2052bf215546Sopenharmony_ci
2053bf215546Sopenharmony_ci      VkResult result = pvr_bind_memory(device,
2054bf215546Sopenharmony_ci                                        mem,
2055bf215546Sopenharmony_ci                                        pBindInfos[i].memoryOffset,
2056bf215546Sopenharmony_ci                                        buffer->vk.size,
2057bf215546Sopenharmony_ci                                        buffer->alignment,
2058bf215546Sopenharmony_ci                                        &buffer->vma,
2059bf215546Sopenharmony_ci                                        &buffer->dev_addr);
2060bf215546Sopenharmony_ci      if (result != VK_SUCCESS) {
2061bf215546Sopenharmony_ci         while (i--) {
2062bf215546Sopenharmony_ci            PVR_FROM_HANDLE(pvr_buffer, buffer, pBindInfos[i].buffer);
2063bf215546Sopenharmony_ci            pvr_unbind_memory(device, buffer->vma);
2064bf215546Sopenharmony_ci         }
2065bf215546Sopenharmony_ci
2066bf215546Sopenharmony_ci         return result;
2067bf215546Sopenharmony_ci      }
2068bf215546Sopenharmony_ci   }
2069bf215546Sopenharmony_ci
2070bf215546Sopenharmony_ci   return VK_SUCCESS;
2071bf215546Sopenharmony_ci}
2072bf215546Sopenharmony_ci
2073bf215546Sopenharmony_ciVkResult pvr_QueueBindSparse(VkQueue _queue,
2074bf215546Sopenharmony_ci                             uint32_t bindInfoCount,
2075bf215546Sopenharmony_ci                             const VkBindSparseInfo *pBindInfo,
2076bf215546Sopenharmony_ci                             VkFence fence)
2077bf215546Sopenharmony_ci{
2078bf215546Sopenharmony_ci   return VK_SUCCESS;
2079bf215546Sopenharmony_ci}
2080bf215546Sopenharmony_ci
2081bf215546Sopenharmony_ci/* Event functions. */
2082bf215546Sopenharmony_ci
2083bf215546Sopenharmony_ciVkResult pvr_CreateEvent(VkDevice _device,
2084bf215546Sopenharmony_ci                         const VkEventCreateInfo *pCreateInfo,
2085bf215546Sopenharmony_ci                         const VkAllocationCallbacks *pAllocator,
2086bf215546Sopenharmony_ci                         VkEvent *pEvent)
2087bf215546Sopenharmony_ci{
2088bf215546Sopenharmony_ci   assert(!"Unimplemented");
2089bf215546Sopenharmony_ci   return VK_SUCCESS;
2090bf215546Sopenharmony_ci}
2091bf215546Sopenharmony_ci
2092bf215546Sopenharmony_civoid pvr_DestroyEvent(VkDevice _device,
2093bf215546Sopenharmony_ci                      VkEvent _event,
2094bf215546Sopenharmony_ci                      const VkAllocationCallbacks *pAllocator)
2095bf215546Sopenharmony_ci{
2096bf215546Sopenharmony_ci   assert(!"Unimplemented");
2097bf215546Sopenharmony_ci}
2098bf215546Sopenharmony_ci
2099bf215546Sopenharmony_ciVkResult pvr_GetEventStatus(VkDevice _device, VkEvent _event)
2100bf215546Sopenharmony_ci{
2101bf215546Sopenharmony_ci   assert(!"Unimplemented");
2102bf215546Sopenharmony_ci   return VK_SUCCESS;
2103bf215546Sopenharmony_ci}
2104bf215546Sopenharmony_ci
2105bf215546Sopenharmony_ciVkResult pvr_SetEvent(VkDevice _device, VkEvent _event)
2106bf215546Sopenharmony_ci{
2107bf215546Sopenharmony_ci   assert(!"Unimplemented");
2108bf215546Sopenharmony_ci   return VK_SUCCESS;
2109bf215546Sopenharmony_ci}
2110bf215546Sopenharmony_ci
2111bf215546Sopenharmony_ciVkResult pvr_ResetEvent(VkDevice _device, VkEvent _event)
2112bf215546Sopenharmony_ci{
2113bf215546Sopenharmony_ci   assert(!"Unimplemented");
2114bf215546Sopenharmony_ci   return VK_SUCCESS;
2115bf215546Sopenharmony_ci}
2116bf215546Sopenharmony_ci
2117bf215546Sopenharmony_ci/* Buffer functions. */
2118bf215546Sopenharmony_ci
2119bf215546Sopenharmony_ciVkResult pvr_CreateBuffer(VkDevice _device,
2120bf215546Sopenharmony_ci                          const VkBufferCreateInfo *pCreateInfo,
2121bf215546Sopenharmony_ci                          const VkAllocationCallbacks *pAllocator,
2122bf215546Sopenharmony_ci                          VkBuffer *pBuffer)
2123bf215546Sopenharmony_ci{
2124bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device, device, _device);
2125bf215546Sopenharmony_ci   const uint32_t alignment = 4096;
2126bf215546Sopenharmony_ci   struct pvr_buffer *buffer;
2127bf215546Sopenharmony_ci
2128bf215546Sopenharmony_ci   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
2129bf215546Sopenharmony_ci   assert(pCreateInfo->usage != 0);
2130bf215546Sopenharmony_ci
2131bf215546Sopenharmony_ci   /* We check against (ULONG_MAX - alignment) to prevent overflow issues */
2132bf215546Sopenharmony_ci   if (pCreateInfo->size >= ULONG_MAX - alignment)
2133bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_DEVICE_MEMORY;
2134bf215546Sopenharmony_ci
2135bf215546Sopenharmony_ci   buffer =
2136bf215546Sopenharmony_ci      vk_buffer_create(&device->vk, pCreateInfo, pAllocator, sizeof(*buffer));
2137bf215546Sopenharmony_ci   if (!buffer)
2138bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2139bf215546Sopenharmony_ci
2140bf215546Sopenharmony_ci   buffer->alignment = alignment;
2141bf215546Sopenharmony_ci
2142bf215546Sopenharmony_ci   *pBuffer = pvr_buffer_to_handle(buffer);
2143bf215546Sopenharmony_ci
2144bf215546Sopenharmony_ci   return VK_SUCCESS;
2145bf215546Sopenharmony_ci}
2146bf215546Sopenharmony_ci
2147bf215546Sopenharmony_civoid pvr_DestroyBuffer(VkDevice _device,
2148bf215546Sopenharmony_ci                       VkBuffer _buffer,
2149bf215546Sopenharmony_ci                       const VkAllocationCallbacks *pAllocator)
2150bf215546Sopenharmony_ci{
2151bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device, device, _device);
2152bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_buffer, buffer, _buffer);
2153bf215546Sopenharmony_ci
2154bf215546Sopenharmony_ci   if (!buffer)
2155bf215546Sopenharmony_ci      return;
2156bf215546Sopenharmony_ci
2157bf215546Sopenharmony_ci   if (buffer->vma)
2158bf215546Sopenharmony_ci      pvr_unbind_memory(device, buffer->vma);
2159bf215546Sopenharmony_ci
2160bf215546Sopenharmony_ci   vk_buffer_destroy(&device->vk, pAllocator, &buffer->vk);
2161bf215546Sopenharmony_ci}
2162bf215546Sopenharmony_ci
2163bf215546Sopenharmony_ciVkResult pvr_gpu_upload(struct pvr_device *device,
2164bf215546Sopenharmony_ci                        struct pvr_winsys_heap *heap,
2165bf215546Sopenharmony_ci                        const void *data,
2166bf215546Sopenharmony_ci                        size_t size,
2167bf215546Sopenharmony_ci                        uint64_t alignment,
2168bf215546Sopenharmony_ci                        struct pvr_bo **const pvr_bo_out)
2169bf215546Sopenharmony_ci{
2170bf215546Sopenharmony_ci   struct pvr_bo *pvr_bo = NULL;
2171bf215546Sopenharmony_ci   VkResult result;
2172bf215546Sopenharmony_ci
2173bf215546Sopenharmony_ci   assert(size > 0);
2174bf215546Sopenharmony_ci
2175bf215546Sopenharmony_ci   result = pvr_bo_alloc(device,
2176bf215546Sopenharmony_ci                         heap,
2177bf215546Sopenharmony_ci                         size,
2178bf215546Sopenharmony_ci                         alignment,
2179bf215546Sopenharmony_ci                         PVR_BO_ALLOC_FLAG_CPU_MAPPED,
2180bf215546Sopenharmony_ci                         &pvr_bo);
2181bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
2182bf215546Sopenharmony_ci      return result;
2183bf215546Sopenharmony_ci
2184bf215546Sopenharmony_ci   memcpy(pvr_bo->bo->map, data, size);
2185bf215546Sopenharmony_ci   pvr_bo_cpu_unmap(device, pvr_bo);
2186bf215546Sopenharmony_ci
2187bf215546Sopenharmony_ci   *pvr_bo_out = pvr_bo;
2188bf215546Sopenharmony_ci
2189bf215546Sopenharmony_ci   return VK_SUCCESS;
2190bf215546Sopenharmony_ci}
2191bf215546Sopenharmony_ci
2192bf215546Sopenharmony_ciVkResult pvr_gpu_upload_usc(struct pvr_device *device,
2193bf215546Sopenharmony_ci                            const void *code,
2194bf215546Sopenharmony_ci                            size_t code_size,
2195bf215546Sopenharmony_ci                            uint64_t code_alignment,
2196bf215546Sopenharmony_ci                            struct pvr_bo **const pvr_bo_out)
2197bf215546Sopenharmony_ci{
2198bf215546Sopenharmony_ci   struct pvr_bo *pvr_bo = NULL;
2199bf215546Sopenharmony_ci   VkResult result;
2200bf215546Sopenharmony_ci
2201bf215546Sopenharmony_ci   assert(code_size > 0);
2202bf215546Sopenharmony_ci
2203bf215546Sopenharmony_ci   /* The USC will prefetch the next instruction, so over allocate by 1
2204bf215546Sopenharmony_ci    * instruction to prevent reading off the end of a page into a potentially
2205bf215546Sopenharmony_ci    * unallocated page.
2206bf215546Sopenharmony_ci    */
2207bf215546Sopenharmony_ci   result = pvr_bo_alloc(device,
2208bf215546Sopenharmony_ci                         device->heaps.usc_heap,
2209bf215546Sopenharmony_ci                         code_size + ROGUE_MAX_INSTR_BYTES,
2210bf215546Sopenharmony_ci                         code_alignment,
2211bf215546Sopenharmony_ci                         PVR_BO_ALLOC_FLAG_CPU_MAPPED,
2212bf215546Sopenharmony_ci                         &pvr_bo);
2213bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
2214bf215546Sopenharmony_ci      return result;
2215bf215546Sopenharmony_ci
2216bf215546Sopenharmony_ci   memcpy(pvr_bo->bo->map, code, code_size);
2217bf215546Sopenharmony_ci   pvr_bo_cpu_unmap(device, pvr_bo);
2218bf215546Sopenharmony_ci
2219bf215546Sopenharmony_ci   *pvr_bo_out = pvr_bo;
2220bf215546Sopenharmony_ci
2221bf215546Sopenharmony_ci   return VK_SUCCESS;
2222bf215546Sopenharmony_ci}
2223bf215546Sopenharmony_ci
2224bf215546Sopenharmony_ci/**
2225bf215546Sopenharmony_ci * \brief Upload PDS program data and code segments from host memory to device
2226bf215546Sopenharmony_ci * memory.
2227bf215546Sopenharmony_ci *
2228bf215546Sopenharmony_ci * \param[in] device            Logical device pointer.
2229bf215546Sopenharmony_ci * \param[in] data              Pointer to PDS data segment to upload.
2230bf215546Sopenharmony_ci * \param[in] data_size_dwords  Size of PDS data segment in dwords.
2231bf215546Sopenharmony_ci * \param[in] data_alignment    Required alignment of the PDS data segment in
2232bf215546Sopenharmony_ci *                              bytes. Must be a power of two.
2233bf215546Sopenharmony_ci * \param[in] code              Pointer to PDS code segment to upload.
2234bf215546Sopenharmony_ci * \param[in] code_size_dwords  Size of PDS code segment in dwords.
2235bf215546Sopenharmony_ci * \param[in] code_alignment    Required alignment of the PDS code segment in
2236bf215546Sopenharmony_ci *                              bytes. Must be a power of two.
2237bf215546Sopenharmony_ci * \param[in] min_alignment     Minimum alignment of the bo holding the PDS
2238bf215546Sopenharmony_ci *                              program in bytes.
2239bf215546Sopenharmony_ci * \param[out] pds_upload_out   On success will be initialized based on the
2240bf215546Sopenharmony_ci *                              uploaded PDS program.
2241bf215546Sopenharmony_ci * \return VK_SUCCESS on success, or error code otherwise.
2242bf215546Sopenharmony_ci */
2243bf215546Sopenharmony_ciVkResult pvr_gpu_upload_pds(struct pvr_device *device,
2244bf215546Sopenharmony_ci                            const uint32_t *data,
2245bf215546Sopenharmony_ci                            uint32_t data_size_dwords,
2246bf215546Sopenharmony_ci                            uint32_t data_alignment,
2247bf215546Sopenharmony_ci                            const uint32_t *code,
2248bf215546Sopenharmony_ci                            uint32_t code_size_dwords,
2249bf215546Sopenharmony_ci                            uint32_t code_alignment,
2250bf215546Sopenharmony_ci                            uint64_t min_alignment,
2251bf215546Sopenharmony_ci                            struct pvr_pds_upload *const pds_upload_out)
2252bf215546Sopenharmony_ci{
2253bf215546Sopenharmony_ci   /* All alignment and sizes below are in bytes. */
2254bf215546Sopenharmony_ci   const size_t data_size = data_size_dwords * sizeof(*data);
2255bf215546Sopenharmony_ci   const size_t code_size = code_size_dwords * sizeof(*code);
2256bf215546Sopenharmony_ci   const uint64_t data_aligned_size = ALIGN_POT(data_size, data_alignment);
2257bf215546Sopenharmony_ci   const uint64_t code_aligned_size = ALIGN_POT(code_size, code_alignment);
2258bf215546Sopenharmony_ci   const uint32_t code_offset = ALIGN_POT(data_aligned_size, code_alignment);
2259bf215546Sopenharmony_ci   const uint64_t bo_alignment = MAX2(min_alignment, data_alignment);
2260bf215546Sopenharmony_ci   const uint64_t bo_size = (!!code) ? (code_offset + code_aligned_size)
2261bf215546Sopenharmony_ci                                     : data_aligned_size;
2262bf215546Sopenharmony_ci   const uint64_t bo_flags = PVR_BO_ALLOC_FLAG_CPU_MAPPED |
2263bf215546Sopenharmony_ci                             PVR_BO_ALLOC_FLAG_ZERO_ON_ALLOC;
2264bf215546Sopenharmony_ci   VkResult result;
2265bf215546Sopenharmony_ci
2266bf215546Sopenharmony_ci   assert(code || data);
2267bf215546Sopenharmony_ci   assert(!code || (code_size_dwords != 0 && code_alignment != 0));
2268bf215546Sopenharmony_ci   assert(!data || (data_size_dwords != 0 && data_alignment != 0));
2269bf215546Sopenharmony_ci
2270bf215546Sopenharmony_ci   result = pvr_bo_alloc(device,
2271bf215546Sopenharmony_ci                         device->heaps.pds_heap,
2272bf215546Sopenharmony_ci                         bo_size,
2273bf215546Sopenharmony_ci                         bo_alignment,
2274bf215546Sopenharmony_ci                         bo_flags,
2275bf215546Sopenharmony_ci                         &pds_upload_out->pvr_bo);
2276bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
2277bf215546Sopenharmony_ci      return result;
2278bf215546Sopenharmony_ci
2279bf215546Sopenharmony_ci   if (data) {
2280bf215546Sopenharmony_ci      memcpy(pds_upload_out->pvr_bo->bo->map, data, data_size);
2281bf215546Sopenharmony_ci
2282bf215546Sopenharmony_ci      pds_upload_out->data_offset = pds_upload_out->pvr_bo->vma->dev_addr.addr -
2283bf215546Sopenharmony_ci                                    device->heaps.pds_heap->base_addr.addr;
2284bf215546Sopenharmony_ci
2285bf215546Sopenharmony_ci      /* Store data size in dwords. */
2286bf215546Sopenharmony_ci      assert(data_aligned_size % 4 == 0);
2287bf215546Sopenharmony_ci      pds_upload_out->data_size = data_aligned_size / 4;
2288bf215546Sopenharmony_ci   } else {
2289bf215546Sopenharmony_ci      pds_upload_out->data_offset = 0;
2290bf215546Sopenharmony_ci      pds_upload_out->data_size = 0;
2291bf215546Sopenharmony_ci   }
2292bf215546Sopenharmony_ci
2293bf215546Sopenharmony_ci   if (code) {
2294bf215546Sopenharmony_ci      memcpy((uint8_t *)pds_upload_out->pvr_bo->bo->map + code_offset,
2295bf215546Sopenharmony_ci             code,
2296bf215546Sopenharmony_ci             code_size);
2297bf215546Sopenharmony_ci
2298bf215546Sopenharmony_ci      pds_upload_out->code_offset =
2299bf215546Sopenharmony_ci         (pds_upload_out->pvr_bo->vma->dev_addr.addr + code_offset) -
2300bf215546Sopenharmony_ci         device->heaps.pds_heap->base_addr.addr;
2301bf215546Sopenharmony_ci
2302bf215546Sopenharmony_ci      /* Store code size in dwords. */
2303bf215546Sopenharmony_ci      assert(code_aligned_size % 4 == 0);
2304bf215546Sopenharmony_ci      pds_upload_out->code_size = code_aligned_size / 4;
2305bf215546Sopenharmony_ci   } else {
2306bf215546Sopenharmony_ci      pds_upload_out->code_offset = 0;
2307bf215546Sopenharmony_ci      pds_upload_out->code_size = 0;
2308bf215546Sopenharmony_ci   }
2309bf215546Sopenharmony_ci
2310bf215546Sopenharmony_ci   pvr_bo_cpu_unmap(device, pds_upload_out->pvr_bo);
2311bf215546Sopenharmony_ci
2312bf215546Sopenharmony_ci   return VK_SUCCESS;
2313bf215546Sopenharmony_ci}
2314bf215546Sopenharmony_ci
2315bf215546Sopenharmony_cistatic VkResult
2316bf215546Sopenharmony_cipvr_framebuffer_create_ppp_state(struct pvr_device *device,
2317bf215546Sopenharmony_ci                                 struct pvr_framebuffer *framebuffer)
2318bf215546Sopenharmony_ci{
2319bf215546Sopenharmony_ci   const uint32_t cache_line_size =
2320bf215546Sopenharmony_ci      rogue_get_slc_cache_line_size(&device->pdevice->dev_info);
2321bf215546Sopenharmony_ci   uint32_t ppp_state[3];
2322bf215546Sopenharmony_ci   VkResult result;
2323bf215546Sopenharmony_ci
2324bf215546Sopenharmony_ci   pvr_csb_pack (&ppp_state[0], TA_STATE_HEADER, header) {
2325bf215546Sopenharmony_ci      header.pres_terminate = true;
2326bf215546Sopenharmony_ci   }
2327bf215546Sopenharmony_ci
2328bf215546Sopenharmony_ci   pvr_csb_pack (&ppp_state[1], TA_STATE_TERMINATE0, term0) {
2329bf215546Sopenharmony_ci      term0.clip_right =
2330bf215546Sopenharmony_ci         DIV_ROUND_UP(
2331bf215546Sopenharmony_ci            framebuffer->width,
2332bf215546Sopenharmony_ci            PVRX(TA_STATE_TERMINATE0_CLIP_RIGHT_BLOCK_SIZE_IN_PIXELS)) -
2333bf215546Sopenharmony_ci         1;
2334bf215546Sopenharmony_ci      term0.clip_bottom =
2335bf215546Sopenharmony_ci         DIV_ROUND_UP(
2336bf215546Sopenharmony_ci            framebuffer->height,
2337bf215546Sopenharmony_ci            PVRX(TA_STATE_TERMINATE0_CLIP_BOTTOM_BLOCK_SIZE_IN_PIXELS)) -
2338bf215546Sopenharmony_ci         1;
2339bf215546Sopenharmony_ci   }
2340bf215546Sopenharmony_ci
2341bf215546Sopenharmony_ci   pvr_csb_pack (&ppp_state[2], TA_STATE_TERMINATE1, term1) {
2342bf215546Sopenharmony_ci      term1.render_target = 0;
2343bf215546Sopenharmony_ci      term1.clip_left = 0;
2344bf215546Sopenharmony_ci   }
2345bf215546Sopenharmony_ci
2346bf215546Sopenharmony_ci   result = pvr_gpu_upload(device,
2347bf215546Sopenharmony_ci                           device->heaps.general_heap,
2348bf215546Sopenharmony_ci                           ppp_state,
2349bf215546Sopenharmony_ci                           sizeof(ppp_state),
2350bf215546Sopenharmony_ci                           cache_line_size,
2351bf215546Sopenharmony_ci                           &framebuffer->ppp_state_bo);
2352bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
2353bf215546Sopenharmony_ci      return result;
2354bf215546Sopenharmony_ci
2355bf215546Sopenharmony_ci   /* Calculate the size of PPP state in dwords. */
2356bf215546Sopenharmony_ci   framebuffer->ppp_state_size = sizeof(ppp_state) / sizeof(uint32_t);
2357bf215546Sopenharmony_ci
2358bf215546Sopenharmony_ci   return VK_SUCCESS;
2359bf215546Sopenharmony_ci}
2360bf215546Sopenharmony_ci
2361bf215546Sopenharmony_cistatic bool pvr_render_targets_init(struct pvr_render_target *render_targets,
2362bf215546Sopenharmony_ci                                    uint32_t render_targets_count)
2363bf215546Sopenharmony_ci{
2364bf215546Sopenharmony_ci   uint32_t i;
2365bf215546Sopenharmony_ci
2366bf215546Sopenharmony_ci   for (i = 0; i < render_targets_count; i++) {
2367bf215546Sopenharmony_ci      if (pthread_mutex_init(&render_targets[i].mutex, NULL))
2368bf215546Sopenharmony_ci         goto err_mutex_destroy;
2369bf215546Sopenharmony_ci   }
2370bf215546Sopenharmony_ci
2371bf215546Sopenharmony_ci   return true;
2372bf215546Sopenharmony_ci
2373bf215546Sopenharmony_cierr_mutex_destroy:
2374bf215546Sopenharmony_ci   while (i--)
2375bf215546Sopenharmony_ci      pthread_mutex_destroy(&render_targets[i].mutex);
2376bf215546Sopenharmony_ci
2377bf215546Sopenharmony_ci   return false;
2378bf215546Sopenharmony_ci}
2379bf215546Sopenharmony_ci
2380bf215546Sopenharmony_cistatic void pvr_render_targets_fini(struct pvr_render_target *render_targets,
2381bf215546Sopenharmony_ci                                    uint32_t render_targets_count)
2382bf215546Sopenharmony_ci{
2383bf215546Sopenharmony_ci   for (uint32_t i = 0; i < render_targets_count; i++) {
2384bf215546Sopenharmony_ci      if (render_targets[i].valid) {
2385bf215546Sopenharmony_ci         pvr_render_target_dataset_destroy(render_targets[i].rt_dataset);
2386bf215546Sopenharmony_ci         render_targets[i].valid = false;
2387bf215546Sopenharmony_ci      }
2388bf215546Sopenharmony_ci
2389bf215546Sopenharmony_ci      pthread_mutex_destroy(&render_targets[i].mutex);
2390bf215546Sopenharmony_ci   }
2391bf215546Sopenharmony_ci}
2392bf215546Sopenharmony_ci
2393bf215546Sopenharmony_ciVkResult pvr_CreateFramebuffer(VkDevice _device,
2394bf215546Sopenharmony_ci                               const VkFramebufferCreateInfo *pCreateInfo,
2395bf215546Sopenharmony_ci                               const VkAllocationCallbacks *pAllocator,
2396bf215546Sopenharmony_ci                               VkFramebuffer *pFramebuffer)
2397bf215546Sopenharmony_ci{
2398bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device, device, _device);
2399bf215546Sopenharmony_ci   struct pvr_render_target *render_targets;
2400bf215546Sopenharmony_ci   struct pvr_framebuffer *framebuffer;
2401bf215546Sopenharmony_ci   struct pvr_image_view **attachments;
2402bf215546Sopenharmony_ci   uint32_t render_targets_count;
2403bf215546Sopenharmony_ci   VkResult result;
2404bf215546Sopenharmony_ci
2405bf215546Sopenharmony_ci   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
2406bf215546Sopenharmony_ci
2407bf215546Sopenharmony_ci   render_targets_count =
2408bf215546Sopenharmony_ci      PVR_RENDER_TARGETS_PER_FRAMEBUFFER(&device->pdevice->dev_info);
2409bf215546Sopenharmony_ci
2410bf215546Sopenharmony_ci   VK_MULTIALLOC(ma);
2411bf215546Sopenharmony_ci   vk_multialloc_add(&ma, &framebuffer, __typeof__(*framebuffer), 1);
2412bf215546Sopenharmony_ci   vk_multialloc_add(&ma,
2413bf215546Sopenharmony_ci                     &attachments,
2414bf215546Sopenharmony_ci                     __typeof__(*attachments),
2415bf215546Sopenharmony_ci                     pCreateInfo->attachmentCount);
2416bf215546Sopenharmony_ci   vk_multialloc_add(&ma,
2417bf215546Sopenharmony_ci                     &render_targets,
2418bf215546Sopenharmony_ci                     __typeof__(*render_targets),
2419bf215546Sopenharmony_ci                     render_targets_count);
2420bf215546Sopenharmony_ci
2421bf215546Sopenharmony_ci   if (!vk_multialloc_zalloc2(&ma,
2422bf215546Sopenharmony_ci                              &device->vk.alloc,
2423bf215546Sopenharmony_ci                              pAllocator,
2424bf215546Sopenharmony_ci                              VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
2425bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2426bf215546Sopenharmony_ci
2427bf215546Sopenharmony_ci   vk_object_base_init(&device->vk,
2428bf215546Sopenharmony_ci                       &framebuffer->base,
2429bf215546Sopenharmony_ci                       VK_OBJECT_TYPE_FRAMEBUFFER);
2430bf215546Sopenharmony_ci
2431bf215546Sopenharmony_ci   framebuffer->width = pCreateInfo->width;
2432bf215546Sopenharmony_ci   framebuffer->height = pCreateInfo->height;
2433bf215546Sopenharmony_ci   framebuffer->layers = pCreateInfo->layers;
2434bf215546Sopenharmony_ci
2435bf215546Sopenharmony_ci   framebuffer->attachments = attachments;
2436bf215546Sopenharmony_ci   framebuffer->attachment_count = pCreateInfo->attachmentCount;
2437bf215546Sopenharmony_ci   for (uint32_t i = 0; i < framebuffer->attachment_count; i++) {
2438bf215546Sopenharmony_ci      framebuffer->attachments[i] =
2439bf215546Sopenharmony_ci         pvr_image_view_from_handle(pCreateInfo->pAttachments[i]);
2440bf215546Sopenharmony_ci   }
2441bf215546Sopenharmony_ci
2442bf215546Sopenharmony_ci   result = pvr_framebuffer_create_ppp_state(device, framebuffer);
2443bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
2444bf215546Sopenharmony_ci      goto err_free_framebuffer;
2445bf215546Sopenharmony_ci
2446bf215546Sopenharmony_ci   framebuffer->render_targets = render_targets;
2447bf215546Sopenharmony_ci   framebuffer->render_targets_count = render_targets_count;
2448bf215546Sopenharmony_ci   if (!pvr_render_targets_init(framebuffer->render_targets,
2449bf215546Sopenharmony_ci                                render_targets_count)) {
2450bf215546Sopenharmony_ci      result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2451bf215546Sopenharmony_ci      goto err_free_ppp_state_bo;
2452bf215546Sopenharmony_ci   }
2453bf215546Sopenharmony_ci
2454bf215546Sopenharmony_ci   *pFramebuffer = pvr_framebuffer_to_handle(framebuffer);
2455bf215546Sopenharmony_ci
2456bf215546Sopenharmony_ci   return VK_SUCCESS;
2457bf215546Sopenharmony_ci
2458bf215546Sopenharmony_cierr_free_ppp_state_bo:
2459bf215546Sopenharmony_ci   pvr_bo_free(device, framebuffer->ppp_state_bo);
2460bf215546Sopenharmony_ci
2461bf215546Sopenharmony_cierr_free_framebuffer:
2462bf215546Sopenharmony_ci   vk_object_base_finish(&framebuffer->base);
2463bf215546Sopenharmony_ci   vk_free2(&device->vk.alloc, pAllocator, framebuffer);
2464bf215546Sopenharmony_ci
2465bf215546Sopenharmony_ci   return result;
2466bf215546Sopenharmony_ci}
2467bf215546Sopenharmony_ci
2468bf215546Sopenharmony_civoid pvr_DestroyFramebuffer(VkDevice _device,
2469bf215546Sopenharmony_ci                            VkFramebuffer _fb,
2470bf215546Sopenharmony_ci                            const VkAllocationCallbacks *pAllocator)
2471bf215546Sopenharmony_ci{
2472bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device, device, _device);
2473bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_framebuffer, framebuffer, _fb);
2474bf215546Sopenharmony_ci
2475bf215546Sopenharmony_ci   if (!framebuffer)
2476bf215546Sopenharmony_ci      return;
2477bf215546Sopenharmony_ci
2478bf215546Sopenharmony_ci   pvr_render_targets_fini(framebuffer->render_targets,
2479bf215546Sopenharmony_ci                           framebuffer->render_targets_count);
2480bf215546Sopenharmony_ci   pvr_bo_free(device, framebuffer->ppp_state_bo);
2481bf215546Sopenharmony_ci   vk_object_base_finish(&framebuffer->base);
2482bf215546Sopenharmony_ci   vk_free2(&device->vk.alloc, pAllocator, framebuffer);
2483bf215546Sopenharmony_ci}
2484bf215546Sopenharmony_ci
2485bf215546Sopenharmony_ciPUBLIC VKAPI_ATTR VkResult VKAPI_CALL
2486bf215546Sopenharmony_civk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion)
2487bf215546Sopenharmony_ci{
2488bf215546Sopenharmony_ci   /* For the full details on loader interface versioning, see
2489bf215546Sopenharmony_ci    * <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.
2490bf215546Sopenharmony_ci    * What follows is a condensed summary, to help you navigate the large and
2491bf215546Sopenharmony_ci    * confusing official doc.
2492bf215546Sopenharmony_ci    *
2493bf215546Sopenharmony_ci    *   - Loader interface v0 is incompatible with later versions. We don't
2494bf215546Sopenharmony_ci    *     support it.
2495bf215546Sopenharmony_ci    *
2496bf215546Sopenharmony_ci    *   - In loader interface v1:
2497bf215546Sopenharmony_ci    *       - The first ICD entrypoint called by the loader is
2498bf215546Sopenharmony_ci    *         vk_icdGetInstanceProcAddr(). The ICD must statically expose this
2499bf215546Sopenharmony_ci    *         entrypoint.
2500bf215546Sopenharmony_ci    *       - The ICD must statically expose no other Vulkan symbol unless it
2501bf215546Sopenharmony_ci    *         is linked with -Bsymbolic.
2502bf215546Sopenharmony_ci    *       - Each dispatchable Vulkan handle created by the ICD must be
2503bf215546Sopenharmony_ci    *         a pointer to a struct whose first member is VK_LOADER_DATA. The
2504bf215546Sopenharmony_ci    *         ICD must initialize VK_LOADER_DATA.loadMagic to ICD_LOADER_MAGIC.
2505bf215546Sopenharmony_ci    *       - The loader implements vkCreate{PLATFORM}SurfaceKHR() and
2506bf215546Sopenharmony_ci    *         vkDestroySurfaceKHR(). The ICD must be capable of working with
2507bf215546Sopenharmony_ci    *         such loader-managed surfaces.
2508bf215546Sopenharmony_ci    *
2509bf215546Sopenharmony_ci    *    - Loader interface v2 differs from v1 in:
2510bf215546Sopenharmony_ci    *       - The first ICD entrypoint called by the loader is
2511bf215546Sopenharmony_ci    *         vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must
2512bf215546Sopenharmony_ci    *         statically expose this entrypoint.
2513bf215546Sopenharmony_ci    *
2514bf215546Sopenharmony_ci    *    - Loader interface v3 differs from v2 in:
2515bf215546Sopenharmony_ci    *        - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),
2516bf215546Sopenharmony_ci    *          vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,
2517bf215546Sopenharmony_ci    *          because the loader no longer does so.
2518bf215546Sopenharmony_ci    *
2519bf215546Sopenharmony_ci    *    - Loader interface v4 differs from v3 in:
2520bf215546Sopenharmony_ci    *        - The ICD must implement vk_icdGetPhysicalDeviceProcAddr().
2521bf215546Sopenharmony_ci    */
2522bf215546Sopenharmony_ci   *pSupportedVersion = MIN2(*pSupportedVersion, 4u);
2523bf215546Sopenharmony_ci   return VK_SUCCESS;
2524bf215546Sopenharmony_ci}
2525bf215546Sopenharmony_ci
2526bf215546Sopenharmony_cistatic uint32_t
2527bf215546Sopenharmony_cipvr_sampler_get_hw_filter_from_vk(const struct pvr_device_info *dev_info,
2528bf215546Sopenharmony_ci                                  VkFilter filter)
2529bf215546Sopenharmony_ci{
2530bf215546Sopenharmony_ci   switch (filter) {
2531bf215546Sopenharmony_ci   case VK_FILTER_NEAREST:
2532bf215546Sopenharmony_ci      return PVRX(TEXSTATE_FILTER_POINT);
2533bf215546Sopenharmony_ci   case VK_FILTER_LINEAR:
2534bf215546Sopenharmony_ci      return PVRX(TEXSTATE_FILTER_LINEAR);
2535bf215546Sopenharmony_ci   default:
2536bf215546Sopenharmony_ci      unreachable("Unknown filter type.");
2537bf215546Sopenharmony_ci   }
2538bf215546Sopenharmony_ci}
2539bf215546Sopenharmony_ci
2540bf215546Sopenharmony_cistatic uint32_t
2541bf215546Sopenharmony_cipvr_sampler_get_hw_addr_mode_from_vk(VkSamplerAddressMode addr_mode)
2542bf215546Sopenharmony_ci{
2543bf215546Sopenharmony_ci   switch (addr_mode) {
2544bf215546Sopenharmony_ci   case VK_SAMPLER_ADDRESS_MODE_REPEAT:
2545bf215546Sopenharmony_ci      return PVRX(TEXSTATE_ADDRMODE_REPEAT);
2546bf215546Sopenharmony_ci   case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT:
2547bf215546Sopenharmony_ci      return PVRX(TEXSTATE_ADDRMODE_FLIP);
2548bf215546Sopenharmony_ci   case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
2549bf215546Sopenharmony_ci      return PVRX(TEXSTATE_ADDRMODE_CLAMP_TO_EDGE);
2550bf215546Sopenharmony_ci   case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE:
2551bf215546Sopenharmony_ci      return PVRX(TEXSTATE_ADDRMODE_FLIP_ONCE_THEN_CLAMP);
2552bf215546Sopenharmony_ci   case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER:
2553bf215546Sopenharmony_ci      return PVRX(TEXSTATE_ADDRMODE_CLAMP_TO_BORDER);
2554bf215546Sopenharmony_ci   default:
2555bf215546Sopenharmony_ci      unreachable("Invalid sampler address mode.");
2556bf215546Sopenharmony_ci   }
2557bf215546Sopenharmony_ci}
2558bf215546Sopenharmony_ci
2559bf215546Sopenharmony_ciVkResult pvr_CreateSampler(VkDevice _device,
2560bf215546Sopenharmony_ci                           const VkSamplerCreateInfo *pCreateInfo,
2561bf215546Sopenharmony_ci                           const VkAllocationCallbacks *pAllocator,
2562bf215546Sopenharmony_ci                           VkSampler *pSampler)
2563bf215546Sopenharmony_ci{
2564bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device, device, _device);
2565bf215546Sopenharmony_ci   struct pvr_sampler *sampler;
2566bf215546Sopenharmony_ci   float lod_rounding_bias;
2567bf215546Sopenharmony_ci   VkFilter min_filter;
2568bf215546Sopenharmony_ci   VkFilter mag_filter;
2569bf215546Sopenharmony_ci   float min_lod;
2570bf215546Sopenharmony_ci   float max_lod;
2571bf215546Sopenharmony_ci
2572bf215546Sopenharmony_ci   STATIC_ASSERT(sizeof(((union pvr_sampler_descriptor *)NULL)->data) ==
2573bf215546Sopenharmony_ci                 sizeof(((union pvr_sampler_descriptor *)NULL)->words));
2574bf215546Sopenharmony_ci
2575bf215546Sopenharmony_ci   sampler = vk_object_alloc(&device->vk,
2576bf215546Sopenharmony_ci                             pAllocator,
2577bf215546Sopenharmony_ci                             sizeof(*sampler),
2578bf215546Sopenharmony_ci                             VK_OBJECT_TYPE_SAMPLER);
2579bf215546Sopenharmony_ci   if (!sampler)
2580bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2581bf215546Sopenharmony_ci
2582bf215546Sopenharmony_ci   mag_filter = pCreateInfo->magFilter;
2583bf215546Sopenharmony_ci   min_filter = pCreateInfo->minFilter;
2584bf215546Sopenharmony_ci
2585bf215546Sopenharmony_ci   if (PVR_HAS_QUIRK(&device->pdevice->dev_info, 51025)) {
2586bf215546Sopenharmony_ci      /* The min/mag filters may need adjustment here, the GPU should decide
2587bf215546Sopenharmony_ci       * which of the two filters to use based on the clamped LOD value: LOD
2588bf215546Sopenharmony_ci       * <= 0 implies magnification, while LOD > 0 implies minification.
2589bf215546Sopenharmony_ci       *
2590bf215546Sopenharmony_ci       * As a workaround, we override magFilter with minFilter if we know that
2591bf215546Sopenharmony_ci       * the magnification filter will never be used due to clamping anyway
2592bf215546Sopenharmony_ci       * (i.e. minLod > 0). Conversely, we override minFilter with magFilter
2593bf215546Sopenharmony_ci       * if maxLod <= 0.
2594bf215546Sopenharmony_ci       */
2595bf215546Sopenharmony_ci      if (pCreateInfo->minLod > 0.0f) {
2596bf215546Sopenharmony_ci         /* The clamped LOD will always be positive => always minify. */
2597bf215546Sopenharmony_ci         mag_filter = pCreateInfo->minFilter;
2598bf215546Sopenharmony_ci      }
2599bf215546Sopenharmony_ci
2600bf215546Sopenharmony_ci      if (pCreateInfo->maxLod <= 0.0f) {
2601bf215546Sopenharmony_ci         /* The clamped LOD will always be negative or zero => always
2602bf215546Sopenharmony_ci          * magnify.
2603bf215546Sopenharmony_ci          */
2604bf215546Sopenharmony_ci         min_filter = pCreateInfo->magFilter;
2605bf215546Sopenharmony_ci      }
2606bf215546Sopenharmony_ci   }
2607bf215546Sopenharmony_ci
2608bf215546Sopenharmony_ci   if (pCreateInfo->compareEnable) {
2609bf215546Sopenharmony_ci      sampler->descriptor.data.compare_op =
2610bf215546Sopenharmony_ci         (uint32_t)pvr_texstate_cmpmode(pCreateInfo->compareOp);
2611bf215546Sopenharmony_ci   } else {
2612bf215546Sopenharmony_ci      sampler->descriptor.data.compare_op =
2613bf215546Sopenharmony_ci         (uint32_t)pvr_texstate_cmpmode(VK_COMPARE_OP_NEVER);
2614bf215546Sopenharmony_ci   }
2615bf215546Sopenharmony_ci
2616bf215546Sopenharmony_ci   sampler->descriptor.data.word3 = 0;
2617bf215546Sopenharmony_ci   pvr_csb_pack (&sampler->descriptor.data.sampler_word,
2618bf215546Sopenharmony_ci                 TEXSTATE_SAMPLER,
2619bf215546Sopenharmony_ci                 word) {
2620bf215546Sopenharmony_ci      const struct pvr_device_info *dev_info = &device->pdevice->dev_info;
2621bf215546Sopenharmony_ci      const float lod_clamp_max = (float)PVRX(TEXSTATE_CLAMP_MAX) /
2622bf215546Sopenharmony_ci                                  (1 << PVRX(TEXSTATE_CLAMP_FRACTIONAL_BITS));
2623bf215546Sopenharmony_ci      const float max_dadjust = ((float)(PVRX(TEXSTATE_DADJUST_MAX_UINT) -
2624bf215546Sopenharmony_ci                                         PVRX(TEXSTATE_DADJUST_ZERO_UINT))) /
2625bf215546Sopenharmony_ci                                (1 << PVRX(TEXSTATE_DADJUST_FRACTIONAL_BITS));
2626bf215546Sopenharmony_ci      const float min_dadjust = ((float)(PVRX(TEXSTATE_DADJUST_MIN_UINT) -
2627bf215546Sopenharmony_ci                                         PVRX(TEXSTATE_DADJUST_ZERO_UINT))) /
2628bf215546Sopenharmony_ci                                (1 << PVRX(TEXSTATE_DADJUST_FRACTIONAL_BITS));
2629bf215546Sopenharmony_ci
2630bf215546Sopenharmony_ci      word.magfilter = pvr_sampler_get_hw_filter_from_vk(dev_info, mag_filter);
2631bf215546Sopenharmony_ci      word.minfilter = pvr_sampler_get_hw_filter_from_vk(dev_info, min_filter);
2632bf215546Sopenharmony_ci
2633bf215546Sopenharmony_ci      if (pCreateInfo->mipmapMode == VK_SAMPLER_MIPMAP_MODE_LINEAR)
2634bf215546Sopenharmony_ci         word.mipfilter = true;
2635bf215546Sopenharmony_ci
2636bf215546Sopenharmony_ci      word.addrmode_u =
2637bf215546Sopenharmony_ci         pvr_sampler_get_hw_addr_mode_from_vk(pCreateInfo->addressModeU);
2638bf215546Sopenharmony_ci      word.addrmode_v =
2639bf215546Sopenharmony_ci         pvr_sampler_get_hw_addr_mode_from_vk(pCreateInfo->addressModeV);
2640bf215546Sopenharmony_ci      word.addrmode_w =
2641bf215546Sopenharmony_ci         pvr_sampler_get_hw_addr_mode_from_vk(pCreateInfo->addressModeW);
2642bf215546Sopenharmony_ci
2643bf215546Sopenharmony_ci      /* TODO: Figure out defines for these. */
2644bf215546Sopenharmony_ci      if (word.addrmode_u == PVRX(TEXSTATE_ADDRMODE_FLIP))
2645bf215546Sopenharmony_ci         sampler->descriptor.data.word3 |= 0x40000000;
2646bf215546Sopenharmony_ci
2647bf215546Sopenharmony_ci      if (word.addrmode_v == PVRX(TEXSTATE_ADDRMODE_FLIP))
2648bf215546Sopenharmony_ci         sampler->descriptor.data.word3 |= 0x20000000;
2649bf215546Sopenharmony_ci
2650bf215546Sopenharmony_ci      /* The Vulkan 1.0.205 spec says:
2651bf215546Sopenharmony_ci       *
2652bf215546Sopenharmony_ci       *    The absolute value of mipLodBias must be less than or equal to
2653bf215546Sopenharmony_ci       *    VkPhysicalDeviceLimits::maxSamplerLodBias.
2654bf215546Sopenharmony_ci       */
2655bf215546Sopenharmony_ci      word.dadjust =
2656bf215546Sopenharmony_ci         PVRX(TEXSTATE_DADJUST_ZERO_UINT) +
2657bf215546Sopenharmony_ci         util_signed_fixed(
2658bf215546Sopenharmony_ci            CLAMP(pCreateInfo->mipLodBias, min_dadjust, max_dadjust),
2659bf215546Sopenharmony_ci            PVRX(TEXSTATE_DADJUST_FRACTIONAL_BITS));
2660bf215546Sopenharmony_ci
2661bf215546Sopenharmony_ci      /* Anisotropy is not supported for now. */
2662bf215546Sopenharmony_ci      word.anisoctl = PVRX(TEXSTATE_ANISOCTL_DISABLED);
2663bf215546Sopenharmony_ci
2664bf215546Sopenharmony_ci      if (PVR_HAS_QUIRK(&device->pdevice->dev_info, 51025) &&
2665bf215546Sopenharmony_ci          pCreateInfo->mipmapMode == VK_SAMPLER_MIPMAP_MODE_NEAREST) {
2666bf215546Sopenharmony_ci         /* When MIPMAP_MODE_NEAREST is enabled, the LOD level should be
2667bf215546Sopenharmony_ci          * selected by adding 0.5 and then truncating the input LOD value.
2668bf215546Sopenharmony_ci          * This hardware adds the 0.5 bias before clamping against
2669bf215546Sopenharmony_ci          * lodmin/lodmax, while Vulkan specifies the bias to be added after
2670bf215546Sopenharmony_ci          * clamping. We compensate for this difference by adding the 0.5
2671bf215546Sopenharmony_ci          * bias to the LOD bounds, too.
2672bf215546Sopenharmony_ci          */
2673bf215546Sopenharmony_ci         lod_rounding_bias = 0.5f;
2674bf215546Sopenharmony_ci      } else {
2675bf215546Sopenharmony_ci         lod_rounding_bias = 0.0f;
2676bf215546Sopenharmony_ci      }
2677bf215546Sopenharmony_ci
2678bf215546Sopenharmony_ci      min_lod = pCreateInfo->minLod + lod_rounding_bias;
2679bf215546Sopenharmony_ci      word.minlod = util_unsigned_fixed(CLAMP(min_lod, 0.0f, lod_clamp_max),
2680bf215546Sopenharmony_ci                                        PVRX(TEXSTATE_CLAMP_FRACTIONAL_BITS));
2681bf215546Sopenharmony_ci
2682bf215546Sopenharmony_ci      max_lod = pCreateInfo->maxLod + lod_rounding_bias;
2683bf215546Sopenharmony_ci      word.maxlod = util_unsigned_fixed(CLAMP(max_lod, 0.0f, lod_clamp_max),
2684bf215546Sopenharmony_ci                                        PVRX(TEXSTATE_CLAMP_FRACTIONAL_BITS));
2685bf215546Sopenharmony_ci
2686bf215546Sopenharmony_ci      word.bordercolor_index = pCreateInfo->borderColor;
2687bf215546Sopenharmony_ci
2688bf215546Sopenharmony_ci      if (pCreateInfo->unnormalizedCoordinates)
2689bf215546Sopenharmony_ci         word.non_normalized_coords = true;
2690bf215546Sopenharmony_ci   }
2691bf215546Sopenharmony_ci
2692bf215546Sopenharmony_ci   *pSampler = pvr_sampler_to_handle(sampler);
2693bf215546Sopenharmony_ci
2694bf215546Sopenharmony_ci   return VK_SUCCESS;
2695bf215546Sopenharmony_ci}
2696bf215546Sopenharmony_ci
2697bf215546Sopenharmony_civoid pvr_DestroySampler(VkDevice _device,
2698bf215546Sopenharmony_ci                        VkSampler _sampler,
2699bf215546Sopenharmony_ci                        const VkAllocationCallbacks *pAllocator)
2700bf215546Sopenharmony_ci{
2701bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device, device, _device);
2702bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_sampler, sampler, _sampler);
2703bf215546Sopenharmony_ci
2704bf215546Sopenharmony_ci   if (!sampler)
2705bf215546Sopenharmony_ci      return;
2706bf215546Sopenharmony_ci
2707bf215546Sopenharmony_ci   vk_object_free(&device->vk, pAllocator, sampler);
2708bf215546Sopenharmony_ci}
2709bf215546Sopenharmony_ci
2710bf215546Sopenharmony_civoid pvr_GetBufferMemoryRequirements2(
2711bf215546Sopenharmony_ci   VkDevice _device,
2712bf215546Sopenharmony_ci   const VkBufferMemoryRequirementsInfo2 *pInfo,
2713bf215546Sopenharmony_ci   VkMemoryRequirements2 *pMemoryRequirements)
2714bf215546Sopenharmony_ci{
2715bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_buffer, buffer, pInfo->buffer);
2716bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device, device, _device);
2717bf215546Sopenharmony_ci
2718bf215546Sopenharmony_ci   /* The Vulkan 1.0.166 spec says:
2719bf215546Sopenharmony_ci    *
2720bf215546Sopenharmony_ci    *    memoryTypeBits is a bitmask and contains one bit set for every
2721bf215546Sopenharmony_ci    *    supported memory type for the resource. Bit 'i' is set if and only
2722bf215546Sopenharmony_ci    *    if the memory type 'i' in the VkPhysicalDeviceMemoryProperties
2723bf215546Sopenharmony_ci    *    structure for the physical device is supported for the resource.
2724bf215546Sopenharmony_ci    *
2725bf215546Sopenharmony_ci    * All types are currently supported for buffers.
2726bf215546Sopenharmony_ci    */
2727bf215546Sopenharmony_ci   pMemoryRequirements->memoryRequirements.memoryTypeBits =
2728bf215546Sopenharmony_ci      (1ul << device->pdevice->memory.memoryTypeCount) - 1;
2729bf215546Sopenharmony_ci
2730bf215546Sopenharmony_ci   pMemoryRequirements->memoryRequirements.alignment = buffer->alignment;
2731bf215546Sopenharmony_ci   pMemoryRequirements->memoryRequirements.size =
2732bf215546Sopenharmony_ci      ALIGN_POT(buffer->vk.size, buffer->alignment);
2733bf215546Sopenharmony_ci}
2734bf215546Sopenharmony_ci
2735bf215546Sopenharmony_civoid pvr_GetImageMemoryRequirements2(VkDevice _device,
2736bf215546Sopenharmony_ci                                     const VkImageMemoryRequirementsInfo2 *pInfo,
2737bf215546Sopenharmony_ci                                     VkMemoryRequirements2 *pMemoryRequirements)
2738bf215546Sopenharmony_ci{
2739bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_device, device, _device);
2740bf215546Sopenharmony_ci   PVR_FROM_HANDLE(pvr_image, image, pInfo->image);
2741bf215546Sopenharmony_ci
2742bf215546Sopenharmony_ci   /* The Vulkan 1.0.166 spec says:
2743bf215546Sopenharmony_ci    *
2744bf215546Sopenharmony_ci    *    memoryTypeBits is a bitmask and contains one bit set for every
2745bf215546Sopenharmony_ci    *    supported memory type for the resource. Bit 'i' is set if and only
2746bf215546Sopenharmony_ci    *    if the memory type 'i' in the VkPhysicalDeviceMemoryProperties
2747bf215546Sopenharmony_ci    *    structure for the physical device is supported for the resource.
2748bf215546Sopenharmony_ci    *
2749bf215546Sopenharmony_ci    * All types are currently supported for images.
2750bf215546Sopenharmony_ci    */
2751bf215546Sopenharmony_ci   const uint32_t memory_types =
2752bf215546Sopenharmony_ci      (1ul << device->pdevice->memory.memoryTypeCount) - 1;
2753bf215546Sopenharmony_ci
2754bf215546Sopenharmony_ci   /* TODO: The returned size is aligned here in case of arrays/CEM (as is done
2755bf215546Sopenharmony_ci    * in GetImageMemoryRequirements()), but this should be known at image
2756bf215546Sopenharmony_ci    * creation time (pCreateInfo->arrayLayers > 1). This is confirmed in
2757bf215546Sopenharmony_ci    * ImageCreate()/ImageGetMipMapOffsetInBytes() where it aligns the size to
2758bf215546Sopenharmony_ci    * 4096 if pCreateInfo->arrayLayers > 1. So is the alignment here actually
2759bf215546Sopenharmony_ci    * necessary? If not, what should it be when pCreateInfo->arrayLayers == 1?
2760bf215546Sopenharmony_ci    *
2761bf215546Sopenharmony_ci    * Note: Presumably the 4096 alignment requirement comes from the Vulkan
2762bf215546Sopenharmony_ci    * driver setting RGX_CR_TPU_TAG_CEM_4K_FACE_PACKING_EN when setting up
2763bf215546Sopenharmony_ci    * render and compute jobs.
2764bf215546Sopenharmony_ci    */
2765bf215546Sopenharmony_ci   pMemoryRequirements->memoryRequirements.alignment = image->alignment;
2766bf215546Sopenharmony_ci   pMemoryRequirements->memoryRequirements.size =
2767bf215546Sopenharmony_ci      ALIGN(image->size, image->alignment);
2768bf215546Sopenharmony_ci   pMemoryRequirements->memoryRequirements.memoryTypeBits = memory_types;
2769bf215546Sopenharmony_ci}
2770