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