17ec681f3Smrg/* 27ec681f3Smrg * Copyright 2018 Collabora Ltd. 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub 87ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom 97ec681f3Smrg * the Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 197ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 207ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 217ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#include "zink_screen.h" 257ec681f3Smrg 267ec681f3Smrg#include "zink_compiler.h" 277ec681f3Smrg#include "zink_context.h" 287ec681f3Smrg#include "zink_device_info.h" 297ec681f3Smrg#include "zink_descriptors.h" 307ec681f3Smrg#include "zink_fence.h" 317ec681f3Smrg#include "zink_format.h" 327ec681f3Smrg#include "zink_framebuffer.h" 337ec681f3Smrg#include "zink_instance.h" 347ec681f3Smrg#include "zink_program.h" 357ec681f3Smrg#include "zink_public.h" 367ec681f3Smrg#include "zink_resource.h" 377ec681f3Smrg#include "nir_to_spirv/nir_to_spirv.h" // for SPIRV_VERSION 387ec681f3Smrg 397ec681f3Smrg#include "os/os_process.h" 407ec681f3Smrg#include "util/u_debug.h" 417ec681f3Smrg#include "util/format/u_format.h" 427ec681f3Smrg#include "util/hash_table.h" 437ec681f3Smrg#include "util/os_file.h" 447ec681f3Smrg#include "util/u_math.h" 457ec681f3Smrg#include "util/u_memory.h" 467ec681f3Smrg#include "util/u_screen.h" 477ec681f3Smrg#include "util/u_string.h" 487ec681f3Smrg#include "util/u_transfer_helper.h" 497ec681f3Smrg#include "util/xmlconfig.h" 507ec681f3Smrg 517ec681f3Smrg#include "util/u_cpu_detect.h" 527ec681f3Smrg 537ec681f3Smrg#include "frontend/sw_winsys.h" 547ec681f3Smrg 557ec681f3Smrg#if DETECT_OS_WINDOWS 567ec681f3Smrg#include <io.h> 577ec681f3Smrg#else 587ec681f3Smrg#include <unistd.h> 597ec681f3Smrg#endif 607ec681f3Smrg 617ec681f3Smrg#if defined(__APPLE__) 627ec681f3Smrg// Source of MVK_VERSION 637ec681f3Smrg#include "MoltenVK/vk_mvk_moltenvk.h" 647ec681f3Smrg#endif 657ec681f3Smrg 667ec681f3Smrgstatic const struct debug_named_value 677ec681f3Smrgzink_debug_options[] = { 687ec681f3Smrg { "nir", ZINK_DEBUG_NIR, "Dump NIR during program compile" }, 697ec681f3Smrg { "spirv", ZINK_DEBUG_SPIRV, "Dump SPIR-V during program compile" }, 707ec681f3Smrg { "tgsi", ZINK_DEBUG_TGSI, "Dump TGSI during program compile" }, 717ec681f3Smrg { "validation", ZINK_DEBUG_VALIDATION, "Dump Validation layer output" }, 727ec681f3Smrg DEBUG_NAMED_VALUE_END 737ec681f3Smrg}; 747ec681f3Smrg 757ec681f3SmrgDEBUG_GET_ONCE_FLAGS_OPTION(zink_debug, "ZINK_DEBUG", zink_debug_options, 0) 767ec681f3Smrg 777ec681f3Smrguint32_t 787ec681f3Smrgzink_debug; 797ec681f3Smrg 807ec681f3Smrg 817ec681f3Smrgstatic const struct debug_named_value 827ec681f3Smrgzink_descriptor_options[] = { 837ec681f3Smrg { "auto", ZINK_DESCRIPTOR_MODE_AUTO, "Automatically detect best mode" }, 847ec681f3Smrg { "lazy", ZINK_DESCRIPTOR_MODE_LAZY, "Don't cache, do least amount of updates" }, 857ec681f3Smrg { "nofallback", ZINK_DESCRIPTOR_MODE_NOFALLBACK, "Cache, never use lazy fallback" }, 867ec681f3Smrg { "notemplates", ZINK_DESCRIPTOR_MODE_NOTEMPLATES, "Cache, but disable templated updates" }, 877ec681f3Smrg DEBUG_NAMED_VALUE_END 887ec681f3Smrg}; 897ec681f3Smrg 907ec681f3SmrgDEBUG_GET_ONCE_FLAGS_OPTION(zink_descriptor_mode, "ZINK_DESCRIPTORS", zink_descriptor_options, ZINK_DESCRIPTOR_MODE_AUTO) 917ec681f3Smrg 927ec681f3Smrgstatic const char * 937ec681f3Smrgzink_get_vendor(struct pipe_screen *pscreen) 947ec681f3Smrg{ 957ec681f3Smrg return "Collabora Ltd"; 967ec681f3Smrg} 977ec681f3Smrg 987ec681f3Smrgstatic const char * 997ec681f3Smrgzink_get_device_vendor(struct pipe_screen *pscreen) 1007ec681f3Smrg{ 1017ec681f3Smrg struct zink_screen *screen = zink_screen(pscreen); 1027ec681f3Smrg static char buf[1000]; 1037ec681f3Smrg snprintf(buf, sizeof(buf), "Unknown (vendor-id: 0x%04x)", screen->info.props.vendorID); 1047ec681f3Smrg return buf; 1057ec681f3Smrg} 1067ec681f3Smrg 1077ec681f3Smrgstatic const char * 1087ec681f3Smrgzink_get_name(struct pipe_screen *pscreen) 1097ec681f3Smrg{ 1107ec681f3Smrg struct zink_screen *screen = zink_screen(pscreen); 1117ec681f3Smrg static char buf[1000]; 1127ec681f3Smrg snprintf(buf, sizeof(buf), "zink (%s)", screen->info.props.deviceName); 1137ec681f3Smrg return buf; 1147ec681f3Smrg} 1157ec681f3Smrg 1167ec681f3Smrgstatic uint32_t 1177ec681f3Smrghash_framebuffer_state(const void *key) 1187ec681f3Smrg{ 1197ec681f3Smrg struct zink_framebuffer_state* s = (struct zink_framebuffer_state*)key; 1207ec681f3Smrg return _mesa_hash_data(key, offsetof(struct zink_framebuffer_state, attachments) + sizeof(s->attachments[0]) * s->num_attachments); 1217ec681f3Smrg} 1227ec681f3Smrg 1237ec681f3Smrgstatic bool 1247ec681f3Smrgequals_framebuffer_state(const void *a, const void *b) 1257ec681f3Smrg{ 1267ec681f3Smrg struct zink_framebuffer_state *s = (struct zink_framebuffer_state*)a; 1277ec681f3Smrg return memcmp(a, b, offsetof(struct zink_framebuffer_state, attachments) + sizeof(s->attachments[0]) * s->num_attachments) == 0; 1287ec681f3Smrg} 1297ec681f3Smrg 1307ec681f3Smrgstatic VkDeviceSize 1317ec681f3Smrgget_video_mem(struct zink_screen *screen) 1327ec681f3Smrg{ 1337ec681f3Smrg VkDeviceSize size = 0; 1347ec681f3Smrg for (uint32_t i = 0; i < screen->info.mem_props.memoryHeapCount; ++i) { 1357ec681f3Smrg if (screen->info.mem_props.memoryHeaps[i].flags & 1367ec681f3Smrg VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) 1377ec681f3Smrg size += screen->info.mem_props.memoryHeaps[i].size; 1387ec681f3Smrg } 1397ec681f3Smrg return size; 1407ec681f3Smrg} 1417ec681f3Smrg 1427ec681f3Smrgstatic void 1437ec681f3Smrgdisk_cache_init(struct zink_screen *screen) 1447ec681f3Smrg{ 1457ec681f3Smrg#ifdef ENABLE_SHADER_CACHE 1467ec681f3Smrg static char buf[1000]; 1477ec681f3Smrg snprintf(buf, sizeof(buf), "zink_%x04x", screen->info.props.vendorID); 1487ec681f3Smrg 1497ec681f3Smrg screen->disk_cache = disk_cache_create(buf, screen->info.props.deviceName, 0); 1507ec681f3Smrg if (screen->disk_cache) { 1517ec681f3Smrg util_queue_init(&screen->cache_put_thread, "zcq", 8, 1, UTIL_QUEUE_INIT_RESIZE_IF_FULL, screen); 1527ec681f3Smrg util_queue_init(&screen->cache_get_thread, "zcfq", 8, 4, UTIL_QUEUE_INIT_RESIZE_IF_FULL, screen); 1537ec681f3Smrg } 1547ec681f3Smrg#endif 1557ec681f3Smrg} 1567ec681f3Smrg 1577ec681f3Smrg 1587ec681f3Smrgstatic void 1597ec681f3Smrgcache_put_job(void *data, void *gdata, int thread_index) 1607ec681f3Smrg{ 1617ec681f3Smrg struct zink_program *pg = data; 1627ec681f3Smrg struct zink_screen *screen = gdata; 1637ec681f3Smrg size_t size = 0; 1647ec681f3Smrg if (VKSCR(GetPipelineCacheData)(screen->dev, pg->pipeline_cache, &size, NULL) != VK_SUCCESS) 1657ec681f3Smrg return; 1667ec681f3Smrg if (pg->pipeline_cache_size == size) 1677ec681f3Smrg return; 1687ec681f3Smrg void *pipeline_data = malloc(size); 1697ec681f3Smrg if (!pipeline_data) 1707ec681f3Smrg return; 1717ec681f3Smrg if (VKSCR(GetPipelineCacheData)(screen->dev, pg->pipeline_cache, &size, pipeline_data) == VK_SUCCESS) { 1727ec681f3Smrg pg->pipeline_cache_size = size; 1737ec681f3Smrg 1747ec681f3Smrg cache_key key; 1757ec681f3Smrg disk_cache_compute_key(screen->disk_cache, pg->sha1, sizeof(pg->sha1), key); 1767ec681f3Smrg disk_cache_put_nocopy(screen->disk_cache, key, pipeline_data, size, NULL); 1777ec681f3Smrg } 1787ec681f3Smrg} 1797ec681f3Smrg 1807ec681f3Smrgvoid 1817ec681f3Smrgzink_screen_update_pipeline_cache(struct zink_screen *screen, struct zink_program *pg) 1827ec681f3Smrg{ 1837ec681f3Smrg util_queue_fence_init(&pg->cache_fence); 1847ec681f3Smrg if (!screen->disk_cache) 1857ec681f3Smrg return; 1867ec681f3Smrg 1877ec681f3Smrg util_queue_add_job(&screen->cache_put_thread, pg, NULL, cache_put_job, NULL, 0); 1887ec681f3Smrg} 1897ec681f3Smrg 1907ec681f3Smrgstatic void 1917ec681f3Smrgcache_get_job(void *data, void *gdata, int thread_index) 1927ec681f3Smrg{ 1937ec681f3Smrg struct zink_program *pg = data; 1947ec681f3Smrg struct zink_screen *screen = gdata; 1957ec681f3Smrg 1967ec681f3Smrg VkPipelineCacheCreateInfo pcci; 1977ec681f3Smrg pcci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; 1987ec681f3Smrg pcci.pNext = NULL; 1997ec681f3Smrg pcci.flags = screen->info.have_EXT_pipeline_creation_cache_control ? VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT : 0; 2007ec681f3Smrg pcci.initialDataSize = 0; 2017ec681f3Smrg pcci.pInitialData = NULL; 2027ec681f3Smrg 2037ec681f3Smrg cache_key key; 2047ec681f3Smrg disk_cache_compute_key(screen->disk_cache, pg->sha1, sizeof(pg->sha1), key); 2057ec681f3Smrg pcci.pInitialData = disk_cache_get(screen->disk_cache, key, &pg->pipeline_cache_size); 2067ec681f3Smrg pcci.initialDataSize = pg->pipeline_cache_size; 2077ec681f3Smrg VKSCR(CreatePipelineCache)(screen->dev, &pcci, NULL, &pg->pipeline_cache); 2087ec681f3Smrg free((void*)pcci.pInitialData); 2097ec681f3Smrg} 2107ec681f3Smrg 2117ec681f3Smrgvoid 2127ec681f3Smrgzink_screen_get_pipeline_cache(struct zink_screen *screen, struct zink_program *pg) 2137ec681f3Smrg{ 2147ec681f3Smrg util_queue_fence_init(&pg->cache_fence); 2157ec681f3Smrg if (!screen->disk_cache) 2167ec681f3Smrg return; 2177ec681f3Smrg 2187ec681f3Smrg util_queue_add_job(&screen->cache_get_thread, pg, &pg->cache_fence, cache_get_job, NULL, 0); 2197ec681f3Smrg} 2207ec681f3Smrg 2217ec681f3Smrgstatic int 2227ec681f3Smrgzink_get_compute_param(struct pipe_screen *pscreen, enum pipe_shader_ir ir_type, 2237ec681f3Smrg enum pipe_compute_cap param, void *ret) 2247ec681f3Smrg{ 2257ec681f3Smrg struct zink_screen *screen = zink_screen(pscreen); 2267ec681f3Smrg#define RET(x) do { \ 2277ec681f3Smrg if (ret) \ 2287ec681f3Smrg memcpy(ret, x, sizeof(x)); \ 2297ec681f3Smrg return sizeof(x); \ 2307ec681f3Smrg} while (0) 2317ec681f3Smrg 2327ec681f3Smrg switch (param) { 2337ec681f3Smrg case PIPE_COMPUTE_CAP_ADDRESS_BITS: 2347ec681f3Smrg RET((uint32_t []){ 32 }); 2357ec681f3Smrg 2367ec681f3Smrg case PIPE_COMPUTE_CAP_IR_TARGET: 2377ec681f3Smrg if (ret) 2387ec681f3Smrg strcpy(ret, "nir"); 2397ec681f3Smrg return 4; 2407ec681f3Smrg 2417ec681f3Smrg case PIPE_COMPUTE_CAP_GRID_DIMENSION: 2427ec681f3Smrg RET((uint64_t []) { 3 }); 2437ec681f3Smrg 2447ec681f3Smrg case PIPE_COMPUTE_CAP_MAX_GRID_SIZE: 2457ec681f3Smrg RET(((uint64_t []) { screen->info.props.limits.maxComputeWorkGroupCount[0], 2467ec681f3Smrg screen->info.props.limits.maxComputeWorkGroupCount[1], 2477ec681f3Smrg screen->info.props.limits.maxComputeWorkGroupCount[2] })); 2487ec681f3Smrg 2497ec681f3Smrg case PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE: 2507ec681f3Smrg /* MaxComputeWorkGroupSize[0..2] */ 2517ec681f3Smrg RET(((uint64_t []) {screen->info.props.limits.maxComputeWorkGroupSize[0], 2527ec681f3Smrg screen->info.props.limits.maxComputeWorkGroupSize[1], 2537ec681f3Smrg screen->info.props.limits.maxComputeWorkGroupSize[2]})); 2547ec681f3Smrg 2557ec681f3Smrg case PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK: 2567ec681f3Smrg case PIPE_COMPUTE_CAP_MAX_VARIABLE_THREADS_PER_BLOCK: 2577ec681f3Smrg RET((uint64_t []) { screen->info.props.limits.maxComputeWorkGroupInvocations }); 2587ec681f3Smrg 2597ec681f3Smrg case PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE: 2607ec681f3Smrg RET((uint64_t []) { screen->info.props.limits.maxComputeSharedMemorySize }); 2617ec681f3Smrg 2627ec681f3Smrg case PIPE_COMPUTE_CAP_IMAGES_SUPPORTED: 2637ec681f3Smrg RET((uint32_t []) { 1 }); 2647ec681f3Smrg 2657ec681f3Smrg case PIPE_COMPUTE_CAP_SUBGROUP_SIZE: 2667ec681f3Smrg RET((uint32_t []) { screen->info.props11.subgroupSize }); 2677ec681f3Smrg 2687ec681f3Smrg case PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE: 2697ec681f3Smrg case PIPE_COMPUTE_CAP_MAX_CLOCK_FREQUENCY: 2707ec681f3Smrg case PIPE_COMPUTE_CAP_MAX_COMPUTE_UNITS: 2717ec681f3Smrg case PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE: 2727ec681f3Smrg case PIPE_COMPUTE_CAP_MAX_PRIVATE_SIZE: 2737ec681f3Smrg case PIPE_COMPUTE_CAP_MAX_INPUT_SIZE: 2747ec681f3Smrg // XXX: I think these are for Clover... 2757ec681f3Smrg return 0; 2767ec681f3Smrg 2777ec681f3Smrg default: 2787ec681f3Smrg unreachable("unknown compute param"); 2797ec681f3Smrg } 2807ec681f3Smrg} 2817ec681f3Smrg 2827ec681f3Smrgstatic uint32_t 2837ec681f3Smrgget_smallest_buffer_heap(struct zink_screen *screen) 2847ec681f3Smrg{ 2857ec681f3Smrg enum zink_heap heaps[] = { 2867ec681f3Smrg ZINK_HEAP_DEVICE_LOCAL, 2877ec681f3Smrg ZINK_HEAP_DEVICE_LOCAL_VISIBLE, 2887ec681f3Smrg ZINK_HEAP_HOST_VISIBLE_COHERENT, 2897ec681f3Smrg ZINK_HEAP_HOST_VISIBLE_COHERENT 2907ec681f3Smrg }; 2917ec681f3Smrg unsigned size = UINT32_MAX; 2927ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(heaps); i++) { 2937ec681f3Smrg unsigned heap_idx = screen->info.mem_props.memoryTypes[screen->heap_map[i]].heapIndex; 2947ec681f3Smrg size = MIN2(screen->info.mem_props.memoryHeaps[heap_idx].size, size); 2957ec681f3Smrg } 2967ec681f3Smrg return size; 2977ec681f3Smrg} 2987ec681f3Smrg 2997ec681f3Smrgstatic int 3007ec681f3Smrgzink_get_param(struct pipe_screen *pscreen, enum pipe_cap param) 3017ec681f3Smrg{ 3027ec681f3Smrg struct zink_screen *screen = zink_screen(pscreen); 3037ec681f3Smrg 3047ec681f3Smrg switch (param) { 3057ec681f3Smrg case PIPE_CAP_ANISOTROPIC_FILTER: 3067ec681f3Smrg return screen->info.feats.features.samplerAnisotropy; 3077ec681f3Smrg case PIPE_CAP_EMULATE_NONFIXED_PRIMITIVE_RESTART: 3087ec681f3Smrg return 1; 3097ec681f3Smrg case PIPE_CAP_SUPPORTED_PRIM_MODES_WITH_RESTART: { 3107ec681f3Smrg uint32_t modes = BITFIELD_BIT(PIPE_PRIM_LINE_STRIP) | 3117ec681f3Smrg BITFIELD_BIT(PIPE_PRIM_TRIANGLE_STRIP) | 3127ec681f3Smrg BITFIELD_BIT(PIPE_PRIM_LINE_STRIP_ADJACENCY) | 3137ec681f3Smrg BITFIELD_BIT(PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY); 3147ec681f3Smrg if (screen->have_triangle_fans) 3157ec681f3Smrg modes |= BITFIELD_BIT(PIPE_PRIM_TRIANGLE_FAN); 3167ec681f3Smrg if (screen->info.have_EXT_primitive_topology_list_restart) { 3177ec681f3Smrg modes |= BITFIELD_BIT(PIPE_PRIM_POINTS) | 3187ec681f3Smrg BITFIELD_BIT(PIPE_PRIM_LINES) | 3197ec681f3Smrg BITFIELD_BIT(PIPE_PRIM_TRIANGLES) | 3207ec681f3Smrg BITFIELD_BIT(PIPE_PRIM_TRIANGLES_ADJACENCY); 3217ec681f3Smrg if (screen->info.list_restart_feats.primitiveTopologyPatchListRestart) 3227ec681f3Smrg modes |= BITFIELD_BIT(PIPE_PRIM_PATCHES); 3237ec681f3Smrg } 3247ec681f3Smrg return modes; 3257ec681f3Smrg } 3267ec681f3Smrg case PIPE_CAP_SUPPORTED_PRIM_MODES: { 3277ec681f3Smrg uint32_t modes = BITFIELD_MASK(PIPE_PRIM_MAX); 3287ec681f3Smrg modes &= ~BITFIELD_BIT(PIPE_PRIM_QUADS); 3297ec681f3Smrg modes &= ~BITFIELD_BIT(PIPE_PRIM_QUAD_STRIP); 3307ec681f3Smrg modes &= ~BITFIELD_BIT(PIPE_PRIM_POLYGON); 3317ec681f3Smrg modes &= ~BITFIELD_BIT(PIPE_PRIM_LINE_LOOP); 3327ec681f3Smrg if (!screen->have_triangle_fans) 3337ec681f3Smrg modes &= ~BITFIELD_BIT(PIPE_PRIM_TRIANGLE_FAN); 3347ec681f3Smrg return modes; 3357ec681f3Smrg } 3367ec681f3Smrg 3377ec681f3Smrg case PIPE_CAP_FBFETCH: 3387ec681f3Smrg return 1; 3397ec681f3Smrg 3407ec681f3Smrg case PIPE_CAP_QUERY_MEMORY_INFO: 3417ec681f3Smrg case PIPE_CAP_NPOT_TEXTURES: 3427ec681f3Smrg case PIPE_CAP_TGSI_TEXCOORD: 3437ec681f3Smrg case PIPE_CAP_DRAW_INDIRECT: 3447ec681f3Smrg case PIPE_CAP_TEXTURE_QUERY_LOD: 3457ec681f3Smrg case PIPE_CAP_GLSL_TESS_LEVELS_AS_INPUTS: 3467ec681f3Smrg case PIPE_CAP_CLEAR_TEXTURE: 3477ec681f3Smrg case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS: 3487ec681f3Smrg case PIPE_CAP_FORCE_PERSAMPLE_INTERP: 3497ec681f3Smrg case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT: 3507ec681f3Smrg case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT: 3517ec681f3Smrg case PIPE_CAP_TGSI_ARRAY_COMPONENTS: 3527ec681f3Smrg case PIPE_CAP_QUERY_BUFFER_OBJECT: 3537ec681f3Smrg case PIPE_CAP_CONDITIONAL_RENDER_INVERTED: 3547ec681f3Smrg case PIPE_CAP_CLIP_HALFZ: 3557ec681f3Smrg case PIPE_CAP_TGSI_TXQS: 3567ec681f3Smrg case PIPE_CAP_TEXTURE_BARRIER: 3577ec681f3Smrg case PIPE_CAP_QUERY_SO_OVERFLOW: 3587ec681f3Smrg case PIPE_CAP_GL_SPIRV: 3597ec681f3Smrg case PIPE_CAP_CLEAR_SCISSORED: 3607ec681f3Smrg case PIPE_CAP_INVALIDATE_BUFFER: 3617ec681f3Smrg case PIPE_CAP_PREFER_REAL_BUFFER_IN_CONSTBUF0: 3627ec681f3Smrg case PIPE_CAP_PACKED_UNIFORMS: 3637ec681f3Smrg case PIPE_CAP_TGSI_PACK_HALF_FLOAT: 3647ec681f3Smrg return 1; 3657ec681f3Smrg 3667ec681f3Smrg case PIPE_CAP_SURFACE_SAMPLE_COUNT: 3677ec681f3Smrg return screen->vk_version >= VK_MAKE_VERSION(1,2,0); 3687ec681f3Smrg 3697ec681f3Smrg case PIPE_CAP_DRAW_PARAMETERS: 3707ec681f3Smrg return screen->info.feats11.shaderDrawParameters || screen->info.have_KHR_shader_draw_parameters; 3717ec681f3Smrg 3727ec681f3Smrg case PIPE_CAP_TGSI_VOTE: 3737ec681f3Smrg return screen->spirv_version >= SPIRV_VERSION(1, 3); 3747ec681f3Smrg 3757ec681f3Smrg case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION: 3767ec681f3Smrg return screen->info.have_EXT_provoking_vertex; 3777ec681f3Smrg 3787ec681f3Smrg case PIPE_CAP_TEXTURE_MIRROR_CLAMP_TO_EDGE: 3797ec681f3Smrg return screen->info.have_KHR_sampler_mirror_clamp_to_edge; 3807ec681f3Smrg 3817ec681f3Smrg case PIPE_CAP_POLYGON_OFFSET_CLAMP: 3827ec681f3Smrg return screen->info.feats.features.depthBiasClamp; 3837ec681f3Smrg 3847ec681f3Smrg case PIPE_CAP_QUERY_PIPELINE_STATISTICS_SINGLE: 3857ec681f3Smrg return screen->info.feats.features.pipelineStatisticsQuery; 3867ec681f3Smrg 3877ec681f3Smrg case PIPE_CAP_ROBUST_BUFFER_ACCESS_BEHAVIOR: 3887ec681f3Smrg return screen->info.feats.features.robustBufferAccess; 3897ec681f3Smrg 3907ec681f3Smrg case PIPE_CAP_MULTI_DRAW_INDIRECT: 3917ec681f3Smrg return screen->info.feats.features.multiDrawIndirect; 3927ec681f3Smrg 3937ec681f3Smrg case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS: 3947ec681f3Smrg return screen->info.have_KHR_draw_indirect_count; 3957ec681f3Smrg 3967ec681f3Smrg case PIPE_CAP_START_INSTANCE: 3977ec681f3Smrg return (screen->info.have_vulkan12 && screen->info.feats11.shaderDrawParameters) || 3987ec681f3Smrg screen->info.have_KHR_shader_draw_parameters; 3997ec681f3Smrg 4007ec681f3Smrg case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: 4017ec681f3Smrg return screen->info.have_EXT_vertex_attribute_divisor; 4027ec681f3Smrg 4037ec681f3Smrg case PIPE_CAP_MAX_VERTEX_STREAMS: 4047ec681f3Smrg return screen->info.tf_props.maxTransformFeedbackStreams; 4057ec681f3Smrg 4067ec681f3Smrg case PIPE_CAP_INT64: 4077ec681f3Smrg case PIPE_CAP_INT64_DIVMOD: 4087ec681f3Smrg case PIPE_CAP_DOUBLES: 4097ec681f3Smrg return 1; 4107ec681f3Smrg 4117ec681f3Smrg case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: 4127ec681f3Smrg if (!screen->info.feats.features.dualSrcBlend) 4137ec681f3Smrg return 0; 4147ec681f3Smrg return screen->info.props.limits.maxFragmentDualSrcAttachments; 4157ec681f3Smrg 4167ec681f3Smrg case PIPE_CAP_MAX_RENDER_TARGETS: 4177ec681f3Smrg return screen->info.props.limits.maxColorAttachments; 4187ec681f3Smrg 4197ec681f3Smrg case PIPE_CAP_OCCLUSION_QUERY: 4207ec681f3Smrg return screen->info.feats.features.occlusionQueryPrecise; 4217ec681f3Smrg 4227ec681f3Smrg case PIPE_CAP_PROGRAMMABLE_SAMPLE_LOCATIONS: 4237ec681f3Smrg return screen->info.have_EXT_sample_locations && screen->info.have_EXT_extended_dynamic_state; 4247ec681f3Smrg 4257ec681f3Smrg case PIPE_CAP_QUERY_TIME_ELAPSED: 4267ec681f3Smrg return screen->timestamp_valid_bits > 0; 4277ec681f3Smrg 4287ec681f3Smrg case PIPE_CAP_TEXTURE_MULTISAMPLE: 4297ec681f3Smrg return 1; 4307ec681f3Smrg 4317ec681f3Smrg case PIPE_CAP_FRAGMENT_SHADER_INTERLOCK: 4327ec681f3Smrg return screen->info.have_EXT_fragment_shader_interlock; 4337ec681f3Smrg 4347ec681f3Smrg case PIPE_CAP_TGSI_CLOCK: 4357ec681f3Smrg return screen->info.have_KHR_shader_clock; 4367ec681f3Smrg 4377ec681f3Smrg case PIPE_CAP_POINT_SPRITE: 4387ec681f3Smrg return 1; 4397ec681f3Smrg 4407ec681f3Smrg case PIPE_CAP_TGSI_BALLOT: 4417ec681f3Smrg return screen->info.have_vulkan12 && screen->info.have_EXT_shader_subgroup_ballot && screen->info.props11.subgroupSize <= 64; 4427ec681f3Smrg 4437ec681f3Smrg case PIPE_CAP_SAMPLE_SHADING: 4447ec681f3Smrg return screen->info.feats.features.sampleRateShading; 4457ec681f3Smrg 4467ec681f3Smrg case PIPE_CAP_TEXTURE_SWIZZLE: 4477ec681f3Smrg return 1; 4487ec681f3Smrg 4497ec681f3Smrg case PIPE_CAP_GL_CLAMP: 4507ec681f3Smrg return 0; 4517ec681f3Smrg 4527ec681f3Smrg case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: 4537ec681f3Smrg /* This is also broken on the other AMD drivers for old HW, but 4547ec681f3Smrg * there's no obvious way to test for that. 4557ec681f3Smrg */ 4567ec681f3Smrg if (screen->info.driver_props.driverID == VK_DRIVER_ID_MESA_RADV || 4577ec681f3Smrg screen->info.driver_props.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY) 4587ec681f3Smrg return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50; 4597ec681f3Smrg return 0; 4607ec681f3Smrg 4617ec681f3Smrg case PIPE_CAP_MAX_TEXTURE_2D_SIZE: 4627ec681f3Smrg return screen->info.props.limits.maxImageDimension2D; 4637ec681f3Smrg case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: 4647ec681f3Smrg return 1 + util_logbase2(screen->info.props.limits.maxImageDimension3D); 4657ec681f3Smrg case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: 4667ec681f3Smrg return 1 + util_logbase2(screen->info.props.limits.maxImageDimensionCube); 4677ec681f3Smrg 4687ec681f3Smrg case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD: 4697ec681f3Smrg case PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES: 4707ec681f3Smrg case PIPE_CAP_VERTEX_SHADER_SATURATE: 4717ec681f3Smrg return 1; 4727ec681f3Smrg 4737ec681f3Smrg case PIPE_CAP_BLEND_EQUATION_SEPARATE: 4747ec681f3Smrg case PIPE_CAP_INDEP_BLEND_ENABLE: 4757ec681f3Smrg case PIPE_CAP_INDEP_BLEND_FUNC: 4767ec681f3Smrg return screen->info.feats.features.independentBlend; 4777ec681f3Smrg 4787ec681f3Smrg case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS: 4797ec681f3Smrg return screen->info.have_EXT_transform_feedback ? screen->info.tf_props.maxTransformFeedbackBuffers : 0; 4807ec681f3Smrg case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME: 4817ec681f3Smrg case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS: 4827ec681f3Smrg return screen->info.have_EXT_transform_feedback; 4837ec681f3Smrg 4847ec681f3Smrg case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: 4857ec681f3Smrg return screen->info.props.limits.maxImageArrayLayers; 4867ec681f3Smrg 4877ec681f3Smrg case PIPE_CAP_DEPTH_CLIP_DISABLE: 4887ec681f3Smrg return screen->info.feats.features.depthClamp; 4897ec681f3Smrg 4907ec681f3Smrg case PIPE_CAP_SHADER_STENCIL_EXPORT: 4917ec681f3Smrg return screen->info.have_EXT_shader_stencil_export; 4927ec681f3Smrg 4937ec681f3Smrg case PIPE_CAP_TGSI_INSTANCEID: 4947ec681f3Smrg case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: 4957ec681f3Smrg case PIPE_CAP_SEAMLESS_CUBE_MAP: 4967ec681f3Smrg return 1; 4977ec681f3Smrg 4987ec681f3Smrg case PIPE_CAP_MIN_TEXEL_OFFSET: 4997ec681f3Smrg return screen->info.props.limits.minTexelOffset; 5007ec681f3Smrg case PIPE_CAP_MAX_TEXEL_OFFSET: 5017ec681f3Smrg return screen->info.props.limits.maxTexelOffset; 5027ec681f3Smrg 5037ec681f3Smrg case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: 5047ec681f3Smrg return 1; 5057ec681f3Smrg 5067ec681f3Smrg case PIPE_CAP_CONDITIONAL_RENDER: 5077ec681f3Smrg return 1; 5087ec681f3Smrg 5097ec681f3Smrg case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY: 5107ec681f3Smrg case PIPE_CAP_GLSL_FEATURE_LEVEL: 5117ec681f3Smrg return 460; 5127ec681f3Smrg 5137ec681f3Smrg case PIPE_CAP_COMPUTE: 5147ec681f3Smrg return 1; 5157ec681f3Smrg 5167ec681f3Smrg case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: 5177ec681f3Smrg return screen->info.props.limits.minUniformBufferOffsetAlignment; 5187ec681f3Smrg 5197ec681f3Smrg case PIPE_CAP_QUERY_TIMESTAMP: 5207ec681f3Smrg return screen->info.have_EXT_calibrated_timestamps && 5217ec681f3Smrg screen->timestamp_valid_bits > 0; 5227ec681f3Smrg 5237ec681f3Smrg case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT: 5247ec681f3Smrg return screen->info.props.limits.minMemoryMapAlignment; 5257ec681f3Smrg 5267ec681f3Smrg case PIPE_CAP_CUBE_MAP_ARRAY: 5277ec681f3Smrg return screen->info.feats.features.imageCubeArray; 5287ec681f3Smrg 5297ec681f3Smrg case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: 5307ec681f3Smrg case PIPE_CAP_PRIMITIVE_RESTART: 5317ec681f3Smrg return 1; 5327ec681f3Smrg 5337ec681f3Smrg case PIPE_CAP_BINDLESS_TEXTURE: 5347ec681f3Smrg return screen->info.have_EXT_descriptor_indexing && 5357ec681f3Smrg /* push, 4 types, bindless */ 5367ec681f3Smrg screen->info.props.limits.maxBoundDescriptorSets >= 6; 5377ec681f3Smrg 5387ec681f3Smrg case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: 5397ec681f3Smrg return screen->info.props.limits.minTexelBufferOffsetAlignment; 5407ec681f3Smrg 5417ec681f3Smrg case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: 5427ec681f3Smrg return 1; 5437ec681f3Smrg 5447ec681f3Smrg case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE: 5457ec681f3Smrg return MIN2(get_smallest_buffer_heap(screen), 5467ec681f3Smrg screen->info.props.limits.maxTexelBufferElements); 5477ec681f3Smrg 5487ec681f3Smrg case PIPE_CAP_ENDIANNESS: 5497ec681f3Smrg return PIPE_ENDIAN_NATIVE; /* unsure */ 5507ec681f3Smrg 5517ec681f3Smrg case PIPE_CAP_MAX_VIEWPORTS: 5527ec681f3Smrg return MIN2(screen->info.props.limits.maxViewports, PIPE_MAX_VIEWPORTS); 5537ec681f3Smrg 5547ec681f3Smrg case PIPE_CAP_IMAGE_LOAD_FORMATTED: 5557ec681f3Smrg return screen->info.feats.features.shaderStorageImageReadWithoutFormat; 5567ec681f3Smrg 5577ec681f3Smrg case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES: 5587ec681f3Smrg return 1; 5597ec681f3Smrg 5607ec681f3Smrg case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES: 5617ec681f3Smrg return screen->info.props.limits.maxGeometryOutputVertices; 5627ec681f3Smrg case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS: 5637ec681f3Smrg return screen->info.props.limits.maxGeometryTotalOutputComponents; 5647ec681f3Smrg 5657ec681f3Smrg case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS: 5667ec681f3Smrg return 4; 5677ec681f3Smrg 5687ec681f3Smrg case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET: 5697ec681f3Smrg return screen->info.props.limits.minTexelGatherOffset; 5707ec681f3Smrg case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET: 5717ec681f3Smrg return screen->info.props.limits.maxTexelGatherOffset; 5727ec681f3Smrg 5737ec681f3Smrg case PIPE_CAP_SAMPLER_REDUCTION_MINMAX_ARB: 5747ec681f3Smrg return screen->vk_version >= VK_MAKE_VERSION(1,2,0) || screen->info.have_EXT_sampler_filter_minmax; 5757ec681f3Smrg 5767ec681f3Smrg case PIPE_CAP_TGSI_FS_FINE_DERIVATIVE: 5777ec681f3Smrg return 1; 5787ec681f3Smrg 5797ec681f3Smrg case PIPE_CAP_VENDOR_ID: 5807ec681f3Smrg return screen->info.props.vendorID; 5817ec681f3Smrg case PIPE_CAP_DEVICE_ID: 5827ec681f3Smrg return screen->info.props.deviceID; 5837ec681f3Smrg 5847ec681f3Smrg case PIPE_CAP_ACCELERATED: 5857ec681f3Smrg return 1; 5867ec681f3Smrg case PIPE_CAP_VIDEO_MEMORY: 5877ec681f3Smrg return get_video_mem(screen) >> 20; 5887ec681f3Smrg case PIPE_CAP_UMA: 5897ec681f3Smrg return screen->info.props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU; 5907ec681f3Smrg 5917ec681f3Smrg case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE: 5927ec681f3Smrg return screen->info.props.limits.maxVertexInputBindingStride; 5937ec681f3Smrg 5947ec681f3Smrg case PIPE_CAP_SAMPLER_VIEW_TARGET: 5957ec681f3Smrg return 1; 5967ec681f3Smrg 5977ec681f3Smrg case PIPE_CAP_TGSI_VS_LAYER_VIEWPORT: 5987ec681f3Smrg case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT: 5997ec681f3Smrg return screen->info.have_EXT_shader_viewport_index_layer || 6007ec681f3Smrg (screen->spirv_version >= SPIRV_VERSION(1, 5) && 6017ec681f3Smrg screen->info.feats12.shaderOutputLayer && 6027ec681f3Smrg screen->info.feats12.shaderOutputViewportIndex); 6037ec681f3Smrg 6047ec681f3Smrg case PIPE_CAP_TEXTURE_FLOAT_LINEAR: 6057ec681f3Smrg case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR: 6067ec681f3Smrg return 1; 6077ec681f3Smrg 6087ec681f3Smrg case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: 6097ec681f3Smrg return screen->info.props.limits.minStorageBufferOffsetAlignment; 6107ec681f3Smrg 6117ec681f3Smrg case PIPE_CAP_PCI_GROUP: 6127ec681f3Smrg case PIPE_CAP_PCI_BUS: 6137ec681f3Smrg case PIPE_CAP_PCI_DEVICE: 6147ec681f3Smrg case PIPE_CAP_PCI_FUNCTION: 6157ec681f3Smrg return 0; /* TODO: figure these out */ 6167ec681f3Smrg 6177ec681f3Smrg case PIPE_CAP_CULL_DISTANCE: 6187ec681f3Smrg return screen->info.feats.features.shaderCullDistance; 6197ec681f3Smrg 6207ec681f3Smrg case PIPE_CAP_SPARSE_BUFFER_PAGE_SIZE: 6217ec681f3Smrg 6227ec681f3Smrg return screen->info.feats.features.sparseBinding ? ZINK_SPARSE_BUFFER_PAGE_SIZE : 0; 6237ec681f3Smrg 6247ec681f3Smrg case PIPE_CAP_VIEWPORT_SUBPIXEL_BITS: 6257ec681f3Smrg return screen->info.props.limits.viewportSubPixelBits; 6267ec681f3Smrg 6277ec681f3Smrg case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY: 6287ec681f3Smrg return 0; /* not sure */ 6297ec681f3Smrg 6307ec681f3Smrg case PIPE_CAP_MAX_GS_INVOCATIONS: 6317ec681f3Smrg return screen->info.props.limits.maxGeometryShaderInvocations; 6327ec681f3Smrg 6337ec681f3Smrg case PIPE_CAP_MAX_COMBINED_SHADER_BUFFERS: 6347ec681f3Smrg /* gallium handles this automatically */ 6357ec681f3Smrg return 0; 6367ec681f3Smrg 6377ec681f3Smrg case PIPE_CAP_MAX_SHADER_BUFFER_SIZE: 6387ec681f3Smrg /* 1<<27 is required by VK spec */ 6397ec681f3Smrg assert(screen->info.props.limits.maxStorageBufferRange >= 1 << 27); 6407ec681f3Smrg /* but Gallium can't handle values that are too big, so clamp to VK spec minimum */ 6417ec681f3Smrg return MIN2(get_smallest_buffer_heap(screen), 1 << 27); 6427ec681f3Smrg 6437ec681f3Smrg case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: 6447ec681f3Smrg case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: 6457ec681f3Smrg return 1; 6467ec681f3Smrg 6477ec681f3Smrg case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: 6487ec681f3Smrg case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: 6497ec681f3Smrg return 0; 6507ec681f3Smrg 6517ec681f3Smrg case PIPE_CAP_NIR_COMPACT_ARRAYS: 6527ec681f3Smrg return 1; 6537ec681f3Smrg 6547ec681f3Smrg case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: 6557ec681f3Smrg return 1; 6567ec681f3Smrg 6577ec681f3Smrg case PIPE_CAP_VIEWPORT_TRANSFORM_LOWERED: 6587ec681f3Smrg return 1; 6597ec681f3Smrg 6607ec681f3Smrg case PIPE_CAP_FLATSHADE: 6617ec681f3Smrg case PIPE_CAP_ALPHA_TEST: 6627ec681f3Smrg case PIPE_CAP_CLIP_PLANES: 6637ec681f3Smrg case PIPE_CAP_POINT_SIZE_FIXED: 6647ec681f3Smrg case PIPE_CAP_TWO_SIDED_COLOR: 6657ec681f3Smrg return 0; 6667ec681f3Smrg 6677ec681f3Smrg case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS: 6687ec681f3Smrg return screen->info.props.limits.maxTessellationControlPerVertexOutputComponents / 4; 6697ec681f3Smrg case PIPE_CAP_MAX_VARYINGS: 6707ec681f3Smrg /* need to reserve up to 60 of our varying components and 16 slots for streamout */ 6717ec681f3Smrg return MIN2(screen->info.props.limits.maxVertexOutputComponents / 4 / 2, 16); 6727ec681f3Smrg 6737ec681f3Smrg case PIPE_CAP_DMABUF: 6747ec681f3Smrg return screen->info.have_KHR_external_memory_fd && 6757ec681f3Smrg screen->info.have_EXT_external_memory_dma_buf && 6767ec681f3Smrg screen->info.have_EXT_queue_family_foreign && 6777ec681f3Smrg screen->info.have_EXT_image_drm_format_modifier; 6787ec681f3Smrg 6797ec681f3Smrg case PIPE_CAP_DEPTH_BOUNDS_TEST: 6807ec681f3Smrg return screen->info.feats.features.depthBounds; 6817ec681f3Smrg 6827ec681f3Smrg case PIPE_CAP_POST_DEPTH_COVERAGE: 6837ec681f3Smrg return screen->info.have_EXT_post_depth_coverage; 6847ec681f3Smrg 6857ec681f3Smrg case PIPE_CAP_STRING_MARKER: 6867ec681f3Smrg return screen->instance_info.have_EXT_debug_utils; 6877ec681f3Smrg 6887ec681f3Smrg default: 6897ec681f3Smrg return u_pipe_screen_get_param_defaults(pscreen, param); 6907ec681f3Smrg } 6917ec681f3Smrg} 6927ec681f3Smrg 6937ec681f3Smrgstatic float 6947ec681f3Smrgzink_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param) 6957ec681f3Smrg{ 6967ec681f3Smrg struct zink_screen *screen = zink_screen(pscreen); 6977ec681f3Smrg 6987ec681f3Smrg switch (param) { 6997ec681f3Smrg case PIPE_CAPF_MAX_LINE_WIDTH: 7007ec681f3Smrg case PIPE_CAPF_MAX_LINE_WIDTH_AA: 7017ec681f3Smrg if (!screen->info.feats.features.wideLines) 7027ec681f3Smrg return 1.0f; 7037ec681f3Smrg return screen->info.props.limits.lineWidthRange[1]; 7047ec681f3Smrg 7057ec681f3Smrg case PIPE_CAPF_MAX_POINT_WIDTH: 7067ec681f3Smrg case PIPE_CAPF_MAX_POINT_WIDTH_AA: 7077ec681f3Smrg if (!screen->info.feats.features.largePoints) 7087ec681f3Smrg return 1.0f; 7097ec681f3Smrg return screen->info.props.limits.pointSizeRange[1]; 7107ec681f3Smrg 7117ec681f3Smrg case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY: 7127ec681f3Smrg if (!screen->info.feats.features.samplerAnisotropy) 7137ec681f3Smrg return 1.0f; 7147ec681f3Smrg return screen->info.props.limits.maxSamplerAnisotropy; 7157ec681f3Smrg 7167ec681f3Smrg case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS: 7177ec681f3Smrg return screen->info.props.limits.maxSamplerLodBias; 7187ec681f3Smrg 7197ec681f3Smrg case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE: 7207ec681f3Smrg case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE: 7217ec681f3Smrg case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY: 7227ec681f3Smrg return 0.0f; /* not implemented */ 7237ec681f3Smrg } 7247ec681f3Smrg 7257ec681f3Smrg /* should only get here on unhandled cases */ 7267ec681f3Smrg return 0.0f; 7277ec681f3Smrg} 7287ec681f3Smrg 7297ec681f3Smrgstatic int 7307ec681f3Smrgzink_get_shader_param(struct pipe_screen *pscreen, 7317ec681f3Smrg enum pipe_shader_type shader, 7327ec681f3Smrg enum pipe_shader_cap param) 7337ec681f3Smrg{ 7347ec681f3Smrg struct zink_screen *screen = zink_screen(pscreen); 7357ec681f3Smrg 7367ec681f3Smrg switch (param) { 7377ec681f3Smrg case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: 7387ec681f3Smrg switch (shader) { 7397ec681f3Smrg case PIPE_SHADER_FRAGMENT: 7407ec681f3Smrg case PIPE_SHADER_VERTEX: 7417ec681f3Smrg return INT_MAX; 7427ec681f3Smrg case PIPE_SHADER_TESS_CTRL: 7437ec681f3Smrg case PIPE_SHADER_TESS_EVAL: 7447ec681f3Smrg if (screen->info.feats.features.tessellationShader && 7457ec681f3Smrg screen->info.have_KHR_maintenance2) 7467ec681f3Smrg return INT_MAX; 7477ec681f3Smrg break; 7487ec681f3Smrg 7497ec681f3Smrg case PIPE_SHADER_GEOMETRY: 7507ec681f3Smrg if (screen->info.feats.features.geometryShader) 7517ec681f3Smrg return INT_MAX; 7527ec681f3Smrg break; 7537ec681f3Smrg 7547ec681f3Smrg case PIPE_SHADER_COMPUTE: 7557ec681f3Smrg return INT_MAX; 7567ec681f3Smrg default: 7577ec681f3Smrg break; 7587ec681f3Smrg } 7597ec681f3Smrg return 0; 7607ec681f3Smrg case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: 7617ec681f3Smrg case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS: 7627ec681f3Smrg case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS: 7637ec681f3Smrg case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH: 7647ec681f3Smrg return INT_MAX; 7657ec681f3Smrg 7667ec681f3Smrg case PIPE_SHADER_CAP_MAX_INPUTS: { 7677ec681f3Smrg uint32_t max = 0; 7687ec681f3Smrg switch (shader) { 7697ec681f3Smrg case PIPE_SHADER_VERTEX: 7707ec681f3Smrg max = MIN2(screen->info.props.limits.maxVertexInputAttributes, PIPE_MAX_ATTRIBS); 7717ec681f3Smrg break; 7727ec681f3Smrg case PIPE_SHADER_TESS_CTRL: 7737ec681f3Smrg max = screen->info.props.limits.maxTessellationControlPerVertexInputComponents / 4; 7747ec681f3Smrg break; 7757ec681f3Smrg case PIPE_SHADER_TESS_EVAL: 7767ec681f3Smrg max = screen->info.props.limits.maxTessellationEvaluationInputComponents / 4; 7777ec681f3Smrg break; 7787ec681f3Smrg case PIPE_SHADER_GEOMETRY: 7797ec681f3Smrg max = screen->info.props.limits.maxGeometryInputComponents; 7807ec681f3Smrg break; 7817ec681f3Smrg case PIPE_SHADER_FRAGMENT: 7827ec681f3Smrg /* intel drivers report fewer components, but it's a value that's compatible 7837ec681f3Smrg * with what we need for GL, so we can still force a conformant value here 7847ec681f3Smrg */ 7857ec681f3Smrg if (screen->info.driver_props.driverID == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR || 7867ec681f3Smrg screen->info.driver_props.driverID == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR) 7877ec681f3Smrg return 32; 7887ec681f3Smrg max = screen->info.props.limits.maxFragmentInputComponents / 4; 7897ec681f3Smrg break; 7907ec681f3Smrg default: 7917ec681f3Smrg return 0; /* unsupported stage */ 7927ec681f3Smrg } 7937ec681f3Smrg switch (shader) { 7947ec681f3Smrg case PIPE_SHADER_VERTEX: 7957ec681f3Smrg case PIPE_SHADER_TESS_EVAL: 7967ec681f3Smrg case PIPE_SHADER_GEOMETRY: 7977ec681f3Smrg /* last vertex stage must support streamout, and this is capped in glsl compiler */ 7987ec681f3Smrg return MIN2(max, MAX_VARYING); 7997ec681f3Smrg default: break; 8007ec681f3Smrg } 8017ec681f3Smrg return MIN2(max, 64); // prevent overflowing struct shader_info::inputs_read 8027ec681f3Smrg } 8037ec681f3Smrg 8047ec681f3Smrg case PIPE_SHADER_CAP_MAX_OUTPUTS: { 8057ec681f3Smrg uint32_t max = 0; 8067ec681f3Smrg switch (shader) { 8077ec681f3Smrg case PIPE_SHADER_VERTEX: 8087ec681f3Smrg max = screen->info.props.limits.maxVertexOutputComponents / 4; 8097ec681f3Smrg break; 8107ec681f3Smrg case PIPE_SHADER_TESS_CTRL: 8117ec681f3Smrg max = screen->info.props.limits.maxTessellationControlPerVertexOutputComponents / 4; 8127ec681f3Smrg break; 8137ec681f3Smrg case PIPE_SHADER_TESS_EVAL: 8147ec681f3Smrg max = screen->info.props.limits.maxTessellationEvaluationOutputComponents / 4; 8157ec681f3Smrg break; 8167ec681f3Smrg case PIPE_SHADER_GEOMETRY: 8177ec681f3Smrg max = screen->info.props.limits.maxGeometryOutputComponents / 4; 8187ec681f3Smrg break; 8197ec681f3Smrg case PIPE_SHADER_FRAGMENT: 8207ec681f3Smrg max = screen->info.props.limits.maxColorAttachments; 8217ec681f3Smrg break; 8227ec681f3Smrg default: 8237ec681f3Smrg return 0; /* unsupported stage */ 8247ec681f3Smrg } 8257ec681f3Smrg return MIN2(max, 64); // prevent overflowing struct shader_info::outputs_read/written 8267ec681f3Smrg } 8277ec681f3Smrg 8287ec681f3Smrg case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE: 8297ec681f3Smrg /* At least 16384 is guaranteed by VK spec */ 8307ec681f3Smrg assert(screen->info.props.limits.maxUniformBufferRange >= 16384); 8317ec681f3Smrg /* but Gallium can't handle values that are too big */ 8327ec681f3Smrg return MIN3(get_smallest_buffer_heap(screen), 8337ec681f3Smrg screen->info.props.limits.maxUniformBufferRange, 1 << 31); 8347ec681f3Smrg 8357ec681f3Smrg case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: 8367ec681f3Smrg return MIN2(screen->info.props.limits.maxPerStageDescriptorUniformBuffers, 8377ec681f3Smrg PIPE_MAX_CONSTANT_BUFFERS); 8387ec681f3Smrg 8397ec681f3Smrg case PIPE_SHADER_CAP_MAX_TEMPS: 8407ec681f3Smrg return INT_MAX; 8417ec681f3Smrg 8427ec681f3Smrg case PIPE_SHADER_CAP_INTEGERS: 8437ec681f3Smrg return 1; 8447ec681f3Smrg 8457ec681f3Smrg case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: 8467ec681f3Smrg return 1; 8477ec681f3Smrg 8487ec681f3Smrg case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR: 8497ec681f3Smrg case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR: 8507ec681f3Smrg case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: 8517ec681f3Smrg case PIPE_SHADER_CAP_SUBROUTINES: 8527ec681f3Smrg case PIPE_SHADER_CAP_INT64_ATOMICS: 8537ec681f3Smrg case PIPE_SHADER_CAP_GLSL_16BIT_CONSTS: 8547ec681f3Smrg return 0; /* not implemented */ 8557ec681f3Smrg 8567ec681f3Smrg case PIPE_SHADER_CAP_FP16_CONST_BUFFERS: 8577ec681f3Smrg //enabling this breaks GTF-GL46.gtf21.GL2Tests.glGetUniform.glGetUniform 8587ec681f3Smrg //return screen->info.feats11.uniformAndStorageBuffer16BitAccess || 8597ec681f3Smrg //(screen->info.have_KHR_16bit_storage && screen->info.storage_16bit_feats.uniformAndStorageBuffer16BitAccess); 8607ec681f3Smrg return 0; 8617ec681f3Smrg case PIPE_SHADER_CAP_FP16_DERIVATIVES: 8627ec681f3Smrg return 0; //spirv requires 32bit derivative srcs and dests 8637ec681f3Smrg case PIPE_SHADER_CAP_FP16: 8647ec681f3Smrg return screen->info.feats12.shaderFloat16 || 8657ec681f3Smrg (screen->info.have_KHR_shader_float16_int8 && 8667ec681f3Smrg screen->info.shader_float16_int8_feats.shaderFloat16); 8677ec681f3Smrg 8687ec681f3Smrg case PIPE_SHADER_CAP_INT16: 8697ec681f3Smrg return screen->info.feats.features.shaderInt16; 8707ec681f3Smrg 8717ec681f3Smrg case PIPE_SHADER_CAP_PREFERRED_IR: 8727ec681f3Smrg return PIPE_SHADER_IR_NIR; 8737ec681f3Smrg 8747ec681f3Smrg case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED: 8757ec681f3Smrg return 0; /* not implemented */ 8767ec681f3Smrg 8777ec681f3Smrg case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS: 8787ec681f3Smrg case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS: 8797ec681f3Smrg return MIN2(MIN2(screen->info.props.limits.maxPerStageDescriptorSamplers, 8807ec681f3Smrg screen->info.props.limits.maxPerStageDescriptorSampledImages), 8817ec681f3Smrg PIPE_MAX_SAMPLERS); 8827ec681f3Smrg 8837ec681f3Smrg case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED: 8847ec681f3Smrg case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED: 8857ec681f3Smrg case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED: 8867ec681f3Smrg return 0; /* not implemented */ 8877ec681f3Smrg 8887ec681f3Smrg case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE: 8897ec681f3Smrg return 0; /* no idea */ 8907ec681f3Smrg 8917ec681f3Smrg case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT: 8927ec681f3Smrg return 0; 8937ec681f3Smrg 8947ec681f3Smrg case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS: 8957ec681f3Smrg switch (shader) { 8967ec681f3Smrg case PIPE_SHADER_VERTEX: 8977ec681f3Smrg case PIPE_SHADER_TESS_CTRL: 8987ec681f3Smrg case PIPE_SHADER_TESS_EVAL: 8997ec681f3Smrg case PIPE_SHADER_GEOMETRY: 9007ec681f3Smrg if (!screen->info.feats.features.vertexPipelineStoresAndAtomics) 9017ec681f3Smrg return 0; 9027ec681f3Smrg break; 9037ec681f3Smrg 9047ec681f3Smrg case PIPE_SHADER_FRAGMENT: 9057ec681f3Smrg if (!screen->info.feats.features.fragmentStoresAndAtomics) 9067ec681f3Smrg return 0; 9077ec681f3Smrg break; 9087ec681f3Smrg 9097ec681f3Smrg default: 9107ec681f3Smrg break; 9117ec681f3Smrg } 9127ec681f3Smrg 9137ec681f3Smrg /* TODO: this limitation is dumb, and will need some fixes in mesa */ 9147ec681f3Smrg return MIN2(screen->info.props.limits.maxPerStageDescriptorStorageBuffers, PIPE_MAX_SHADER_BUFFERS); 9157ec681f3Smrg 9167ec681f3Smrg case PIPE_SHADER_CAP_SUPPORTED_IRS: 9177ec681f3Smrg return (1 << PIPE_SHADER_IR_NIR) | (1 << PIPE_SHADER_IR_TGSI); 9187ec681f3Smrg 9197ec681f3Smrg case PIPE_SHADER_CAP_MAX_SHADER_IMAGES: 9207ec681f3Smrg if (screen->info.feats.features.shaderStorageImageExtendedFormats && 9217ec681f3Smrg screen->info.feats.features.shaderStorageImageWriteWithoutFormat) 9227ec681f3Smrg return MIN2(screen->info.props.limits.maxPerStageDescriptorStorageImages, 9237ec681f3Smrg PIPE_MAX_SHADER_IMAGES); 9247ec681f3Smrg return 0; 9257ec681f3Smrg 9267ec681f3Smrg case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD: 9277ec681f3Smrg case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS: 9287ec681f3Smrg return 0; /* unsure */ 9297ec681f3Smrg 9307ec681f3Smrg case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED: 9317ec681f3Smrg case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS: 9327ec681f3Smrg case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS: 9337ec681f3Smrg case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: 9347ec681f3Smrg return 0; /* not implemented */ 9357ec681f3Smrg } 9367ec681f3Smrg 9377ec681f3Smrg /* should only get here on unhandled cases */ 9387ec681f3Smrg return 0; 9397ec681f3Smrg} 9407ec681f3Smrg 9417ec681f3Smrgstatic VkSampleCountFlagBits 9427ec681f3Smrgvk_sample_count_flags(uint32_t sample_count) 9437ec681f3Smrg{ 9447ec681f3Smrg switch (sample_count) { 9457ec681f3Smrg case 1: return VK_SAMPLE_COUNT_1_BIT; 9467ec681f3Smrg case 2: return VK_SAMPLE_COUNT_2_BIT; 9477ec681f3Smrg case 4: return VK_SAMPLE_COUNT_4_BIT; 9487ec681f3Smrg case 8: return VK_SAMPLE_COUNT_8_BIT; 9497ec681f3Smrg case 16: return VK_SAMPLE_COUNT_16_BIT; 9507ec681f3Smrg case 32: return VK_SAMPLE_COUNT_32_BIT; 9517ec681f3Smrg case 64: return VK_SAMPLE_COUNT_64_BIT; 9527ec681f3Smrg default: 9537ec681f3Smrg return 0; 9547ec681f3Smrg } 9557ec681f3Smrg} 9567ec681f3Smrg 9577ec681f3Smrgstatic bool 9587ec681f3Smrgzink_is_format_supported(struct pipe_screen *pscreen, 9597ec681f3Smrg enum pipe_format format, 9607ec681f3Smrg enum pipe_texture_target target, 9617ec681f3Smrg unsigned sample_count, 9627ec681f3Smrg unsigned storage_sample_count, 9637ec681f3Smrg unsigned bind) 9647ec681f3Smrg{ 9657ec681f3Smrg struct zink_screen *screen = zink_screen(pscreen); 9667ec681f3Smrg 9677ec681f3Smrg if (storage_sample_count && !screen->info.feats.features.shaderStorageImageMultisample && bind & PIPE_BIND_SHADER_IMAGE) 9687ec681f3Smrg return false; 9697ec681f3Smrg 9707ec681f3Smrg if (format == PIPE_FORMAT_NONE) 9717ec681f3Smrg return screen->info.props.limits.framebufferNoAttachmentsSampleCounts & 9727ec681f3Smrg vk_sample_count_flags(sample_count); 9737ec681f3Smrg 9747ec681f3Smrg if (bind & PIPE_BIND_INDEX_BUFFER) { 9757ec681f3Smrg if (format == PIPE_FORMAT_R8_UINT && 9767ec681f3Smrg !screen->info.have_EXT_index_type_uint8) 9777ec681f3Smrg return false; 9787ec681f3Smrg if (format != PIPE_FORMAT_R8_UINT && 9797ec681f3Smrg format != PIPE_FORMAT_R16_UINT && 9807ec681f3Smrg format != PIPE_FORMAT_R32_UINT) 9817ec681f3Smrg return false; 9827ec681f3Smrg } 9837ec681f3Smrg 9847ec681f3Smrg VkFormat vkformat = zink_get_format(screen, format); 9857ec681f3Smrg if (vkformat == VK_FORMAT_UNDEFINED) 9867ec681f3Smrg return false; 9877ec681f3Smrg 9887ec681f3Smrg if (sample_count >= 1) { 9897ec681f3Smrg VkSampleCountFlagBits sample_mask = vk_sample_count_flags(sample_count); 9907ec681f3Smrg if (!sample_mask) 9917ec681f3Smrg return false; 9927ec681f3Smrg const struct util_format_description *desc = util_format_description(format); 9937ec681f3Smrg if (util_format_is_depth_or_stencil(format)) { 9947ec681f3Smrg if (util_format_has_depth(desc)) { 9957ec681f3Smrg if (bind & PIPE_BIND_DEPTH_STENCIL && 9967ec681f3Smrg (screen->info.props.limits.framebufferDepthSampleCounts & sample_mask) != sample_mask) 9977ec681f3Smrg return false; 9987ec681f3Smrg if (bind & PIPE_BIND_SAMPLER_VIEW && 9997ec681f3Smrg (screen->info.props.limits.sampledImageDepthSampleCounts & sample_mask) != sample_mask) 10007ec681f3Smrg return false; 10017ec681f3Smrg } 10027ec681f3Smrg if (util_format_has_stencil(desc)) { 10037ec681f3Smrg if (bind & PIPE_BIND_DEPTH_STENCIL && 10047ec681f3Smrg (screen->info.props.limits.framebufferStencilSampleCounts & sample_mask) != sample_mask) 10057ec681f3Smrg return false; 10067ec681f3Smrg if (bind & PIPE_BIND_SAMPLER_VIEW && 10077ec681f3Smrg (screen->info.props.limits.sampledImageStencilSampleCounts & sample_mask) != sample_mask) 10087ec681f3Smrg return false; 10097ec681f3Smrg } 10107ec681f3Smrg } else if (util_format_is_pure_integer(format)) { 10117ec681f3Smrg if (bind & PIPE_BIND_RENDER_TARGET && 10127ec681f3Smrg !(screen->info.props.limits.framebufferColorSampleCounts & sample_mask)) 10137ec681f3Smrg return false; 10147ec681f3Smrg if (bind & PIPE_BIND_SAMPLER_VIEW && 10157ec681f3Smrg !(screen->info.props.limits.sampledImageIntegerSampleCounts & sample_mask)) 10167ec681f3Smrg return false; 10177ec681f3Smrg } else { 10187ec681f3Smrg if (bind & PIPE_BIND_RENDER_TARGET && 10197ec681f3Smrg !(screen->info.props.limits.framebufferColorSampleCounts & sample_mask)) 10207ec681f3Smrg return false; 10217ec681f3Smrg if (bind & PIPE_BIND_SAMPLER_VIEW && 10227ec681f3Smrg !(screen->info.props.limits.sampledImageColorSampleCounts & sample_mask)) 10237ec681f3Smrg return false; 10247ec681f3Smrg } 10257ec681f3Smrg if (bind & PIPE_BIND_SHADER_IMAGE) { 10267ec681f3Smrg if (!(screen->info.props.limits.storageImageSampleCounts & sample_mask)) 10277ec681f3Smrg return false; 10287ec681f3Smrg } 10297ec681f3Smrg } 10307ec681f3Smrg 10317ec681f3Smrg VkFormatProperties props = screen->format_props[format]; 10327ec681f3Smrg 10337ec681f3Smrg if (target == PIPE_BUFFER) { 10347ec681f3Smrg if (bind & PIPE_BIND_VERTEX_BUFFER) { 10357ec681f3Smrg if (!(props.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)) { 10367ec681f3Smrg enum pipe_format new_format = zink_decompose_vertex_format(format); 10377ec681f3Smrg if (!new_format) 10387ec681f3Smrg return false; 10397ec681f3Smrg if (!(screen->format_props[new_format].bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)) 10407ec681f3Smrg return false; 10417ec681f3Smrg } 10427ec681f3Smrg } 10437ec681f3Smrg 10447ec681f3Smrg if (bind & PIPE_BIND_SAMPLER_VIEW && 10457ec681f3Smrg !(props.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)) 10467ec681f3Smrg return false; 10477ec681f3Smrg 10487ec681f3Smrg if (bind & PIPE_BIND_SHADER_IMAGE && 10497ec681f3Smrg !(props.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT)) 10507ec681f3Smrg return false; 10517ec681f3Smrg } else { 10527ec681f3Smrg /* all other targets are texture-targets */ 10537ec681f3Smrg if (bind & PIPE_BIND_RENDER_TARGET && 10547ec681f3Smrg !(props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) 10557ec681f3Smrg return false; 10567ec681f3Smrg 10577ec681f3Smrg if (bind & PIPE_BIND_BLENDABLE && 10587ec681f3Smrg !(props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT)) 10597ec681f3Smrg return false; 10607ec681f3Smrg 10617ec681f3Smrg if (bind & PIPE_BIND_SAMPLER_VIEW && 10627ec681f3Smrg !(props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) 10637ec681f3Smrg return false; 10647ec681f3Smrg 10657ec681f3Smrg if (bind & PIPE_BIND_SAMPLER_REDUCTION_MINMAX && 10667ec681f3Smrg !(props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT)) 10677ec681f3Smrg return false; 10687ec681f3Smrg 10697ec681f3Smrg if ((bind & PIPE_BIND_SAMPLER_VIEW) || (bind & PIPE_BIND_RENDER_TARGET)) { 10707ec681f3Smrg /* if this is a 3-component texture, force gallium to give us 4 components by rejecting this one */ 10717ec681f3Smrg const struct util_format_description *desc = util_format_description(format); 10727ec681f3Smrg if (desc->nr_channels == 3 && 10737ec681f3Smrg (desc->block.bits == 24 || desc->block.bits == 48 || desc->block.bits == 96)) 10747ec681f3Smrg return false; 10757ec681f3Smrg } 10767ec681f3Smrg 10777ec681f3Smrg if (bind & PIPE_BIND_DEPTH_STENCIL && 10787ec681f3Smrg !(props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) 10797ec681f3Smrg return false; 10807ec681f3Smrg 10817ec681f3Smrg if (bind & PIPE_BIND_SHADER_IMAGE && 10827ec681f3Smrg !(props.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) 10837ec681f3Smrg return false; 10847ec681f3Smrg } 10857ec681f3Smrg 10867ec681f3Smrg if (util_format_is_compressed(format)) { 10877ec681f3Smrg const struct util_format_description *desc = util_format_description(format); 10887ec681f3Smrg if (desc->layout == UTIL_FORMAT_LAYOUT_BPTC && 10897ec681f3Smrg !screen->info.feats.features.textureCompressionBC) 10907ec681f3Smrg return false; 10917ec681f3Smrg } 10927ec681f3Smrg 10937ec681f3Smrg return true; 10947ec681f3Smrg} 10957ec681f3Smrg 10967ec681f3Smrgstatic void 10977ec681f3Smrgzink_destroy_screen(struct pipe_screen *pscreen) 10987ec681f3Smrg{ 10997ec681f3Smrg struct zink_screen *screen = zink_screen(pscreen); 11007ec681f3Smrg 11017ec681f3Smrg if (VK_NULL_HANDLE != screen->debugUtilsCallbackHandle) { 11027ec681f3Smrg VKSCR(DestroyDebugUtilsMessengerEXT)(screen->instance, screen->debugUtilsCallbackHandle, NULL); 11037ec681f3Smrg } 11047ec681f3Smrg 11057ec681f3Smrg if (!screen->info.have_KHR_imageless_framebuffer) { 11067ec681f3Smrg hash_table_foreach(&screen->framebuffer_cache, entry) { 11077ec681f3Smrg struct zink_framebuffer* fb = (struct zink_framebuffer*)entry->data; 11087ec681f3Smrg zink_destroy_framebuffer(screen, fb); 11097ec681f3Smrg } 11107ec681f3Smrg simple_mtx_destroy(&screen->framebuffer_mtx); 11117ec681f3Smrg } 11127ec681f3Smrg 11137ec681f3Smrg u_transfer_helper_destroy(pscreen->transfer_helper); 11147ec681f3Smrg#ifdef ENABLE_SHADER_CACHE 11157ec681f3Smrg if (screen->disk_cache) { 11167ec681f3Smrg util_queue_finish(&screen->cache_put_thread); 11177ec681f3Smrg util_queue_finish(&screen->cache_get_thread); 11187ec681f3Smrg disk_cache_wait_for_idle(screen->disk_cache); 11197ec681f3Smrg util_queue_destroy(&screen->cache_put_thread); 11207ec681f3Smrg util_queue_destroy(&screen->cache_get_thread); 11217ec681f3Smrg } 11227ec681f3Smrg#endif 11237ec681f3Smrg disk_cache_destroy(screen->disk_cache); 11247ec681f3Smrg zink_bo_deinit(screen); 11257ec681f3Smrg util_live_shader_cache_deinit(&screen->shaders); 11267ec681f3Smrg 11277ec681f3Smrg if (screen->sem) 11287ec681f3Smrg VKSCR(DestroySemaphore)(screen->dev, screen->sem, NULL); 11297ec681f3Smrg if (screen->prev_sem) 11307ec681f3Smrg VKSCR(DestroySemaphore)(screen->dev, screen->prev_sem, NULL); 11317ec681f3Smrg 11327ec681f3Smrg if (screen->threaded) 11337ec681f3Smrg util_queue_destroy(&screen->flush_queue); 11347ec681f3Smrg 11357ec681f3Smrg simple_mtx_destroy(&screen->queue_lock); 11367ec681f3Smrg VKSCR(DestroyDevice)(screen->dev, NULL); 11377ec681f3Smrg vkDestroyInstance(screen->instance, NULL); 11387ec681f3Smrg util_idalloc_mt_fini(&screen->buffer_ids); 11397ec681f3Smrg 11407ec681f3Smrg if (screen->drm_fd != -1) 11417ec681f3Smrg close(screen->drm_fd); 11427ec681f3Smrg 11437ec681f3Smrg slab_destroy_parent(&screen->transfer_pool); 11447ec681f3Smrg ralloc_free(screen); 11457ec681f3Smrg} 11467ec681f3Smrg 11477ec681f3Smrgstatic void 11487ec681f3Smrgchoose_pdev(struct zink_screen *screen) 11497ec681f3Smrg{ 11507ec681f3Smrg uint32_t i, pdev_count; 11517ec681f3Smrg VkPhysicalDevice *pdevs; 11527ec681f3Smrg VkResult result = vkEnumeratePhysicalDevices(screen->instance, &pdev_count, NULL); 11537ec681f3Smrg if (result != VK_SUCCESS) 11547ec681f3Smrg return; 11557ec681f3Smrg 11567ec681f3Smrg assert(pdev_count > 0); 11577ec681f3Smrg 11587ec681f3Smrg pdevs = malloc(sizeof(*pdevs) * pdev_count); 11597ec681f3Smrg result = vkEnumeratePhysicalDevices(screen->instance, &pdev_count, pdevs); 11607ec681f3Smrg assert(result == VK_SUCCESS); 11617ec681f3Smrg assert(pdev_count > 0); 11627ec681f3Smrg 11637ec681f3Smrg VkPhysicalDeviceProperties *props = &screen->info.props; 11647ec681f3Smrg for (i = 0; i < pdev_count; ++i) { 11657ec681f3Smrg vkGetPhysicalDeviceProperties(pdevs[i], props); 11667ec681f3Smrg 11677ec681f3Smrg#ifdef ZINK_WITH_SWRAST_VK 11687ec681f3Smrg char *use_lavapipe = getenv("ZINK_USE_LAVAPIPE"); 11697ec681f3Smrg if (use_lavapipe) { 11707ec681f3Smrg if (props->deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) { 11717ec681f3Smrg screen->pdev = pdevs[i]; 11727ec681f3Smrg screen->info.device_version = props->apiVersion; 11737ec681f3Smrg break; 11747ec681f3Smrg } 11757ec681f3Smrg continue; 11767ec681f3Smrg } 11777ec681f3Smrg#endif 11787ec681f3Smrg if (props->deviceType != VK_PHYSICAL_DEVICE_TYPE_CPU) { 11797ec681f3Smrg screen->pdev = pdevs[i]; 11807ec681f3Smrg screen->info.device_version = props->apiVersion; 11817ec681f3Smrg break; 11827ec681f3Smrg } 11837ec681f3Smrg } 11847ec681f3Smrg free(pdevs); 11857ec681f3Smrg 11867ec681f3Smrg /* runtime version is the lesser of the instance version and device version */ 11877ec681f3Smrg screen->vk_version = MIN2(screen->info.device_version, screen->instance_info.loader_version); 11887ec681f3Smrg 11897ec681f3Smrg /* calculate SPIR-V version based on VK version */ 11907ec681f3Smrg if (screen->vk_version >= VK_MAKE_VERSION(1, 2, 0)) 11917ec681f3Smrg screen->spirv_version = SPIRV_VERSION(1, 5); 11927ec681f3Smrg else if (screen->vk_version >= VK_MAKE_VERSION(1, 1, 0)) 11937ec681f3Smrg screen->spirv_version = SPIRV_VERSION(1, 3); 11947ec681f3Smrg else 11957ec681f3Smrg screen->spirv_version = SPIRV_VERSION(1, 0); 11967ec681f3Smrg} 11977ec681f3Smrg 11987ec681f3Smrgstatic void 11997ec681f3Smrgupdate_queue_props(struct zink_screen *screen) 12007ec681f3Smrg{ 12017ec681f3Smrg uint32_t num_queues; 12027ec681f3Smrg vkGetPhysicalDeviceQueueFamilyProperties(screen->pdev, &num_queues, NULL); 12037ec681f3Smrg assert(num_queues > 0); 12047ec681f3Smrg 12057ec681f3Smrg VkQueueFamilyProperties *props = malloc(sizeof(*props) * num_queues); 12067ec681f3Smrg vkGetPhysicalDeviceQueueFamilyProperties(screen->pdev, &num_queues, props); 12077ec681f3Smrg 12087ec681f3Smrg for (uint32_t i = 0; i < num_queues; i++) { 12097ec681f3Smrg if (props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { 12107ec681f3Smrg screen->gfx_queue = i; 12117ec681f3Smrg screen->max_queues = props[i].queueCount; 12127ec681f3Smrg screen->timestamp_valid_bits = props[i].timestampValidBits; 12137ec681f3Smrg break; 12147ec681f3Smrg } 12157ec681f3Smrg } 12167ec681f3Smrg free(props); 12177ec681f3Smrg} 12187ec681f3Smrg 12197ec681f3Smrgstatic void 12207ec681f3Smrginit_queue(struct zink_screen *screen) 12217ec681f3Smrg{ 12227ec681f3Smrg simple_mtx_init(&screen->queue_lock, mtx_plain); 12237ec681f3Smrg vkGetDeviceQueue(screen->dev, screen->gfx_queue, 0, &screen->queue); 12247ec681f3Smrg if (screen->threaded && screen->max_queues > 1) 12257ec681f3Smrg vkGetDeviceQueue(screen->dev, screen->gfx_queue, 1, &screen->thread_queue); 12267ec681f3Smrg else 12277ec681f3Smrg screen->thread_queue = screen->queue; 12287ec681f3Smrg} 12297ec681f3Smrg 12307ec681f3Smrgstatic void 12317ec681f3Smrgzink_flush_frontbuffer(struct pipe_screen *pscreen, 12327ec681f3Smrg struct pipe_context *pcontext, 12337ec681f3Smrg struct pipe_resource *pres, 12347ec681f3Smrg unsigned level, unsigned layer, 12357ec681f3Smrg void *winsys_drawable_handle, 12367ec681f3Smrg struct pipe_box *sub_box) 12377ec681f3Smrg{ 12387ec681f3Smrg struct zink_screen *screen = zink_screen(pscreen); 12397ec681f3Smrg struct sw_winsys *winsys = screen->winsys; 12407ec681f3Smrg struct zink_resource *res = zink_resource(pres); 12417ec681f3Smrg 12427ec681f3Smrg if (!winsys) 12437ec681f3Smrg return; 12447ec681f3Smrg void *map = winsys->displaytarget_map(winsys, res->dt, 0); 12457ec681f3Smrg 12467ec681f3Smrg if (map) { 12477ec681f3Smrg struct pipe_transfer *transfer = NULL; 12487ec681f3Smrg void *res_map = pipe_texture_map(pcontext, pres, level, layer, PIPE_MAP_READ, 0, 0, 12497ec681f3Smrg u_minify(pres->width0, level), 12507ec681f3Smrg u_minify(pres->height0, level), 12517ec681f3Smrg &transfer); 12527ec681f3Smrg if (res_map) { 12537ec681f3Smrg util_copy_rect((ubyte*)map, pres->format, res->dt_stride, 0, 0, 12547ec681f3Smrg transfer->box.width, transfer->box.height, 12557ec681f3Smrg (const ubyte*)res_map, transfer->stride, 0, 0); 12567ec681f3Smrg pipe_texture_unmap(pcontext, transfer); 12577ec681f3Smrg } 12587ec681f3Smrg winsys->displaytarget_unmap(winsys, res->dt); 12597ec681f3Smrg } 12607ec681f3Smrg 12617ec681f3Smrg winsys->displaytarget_display(winsys, res->dt, winsys_drawable_handle, sub_box); 12627ec681f3Smrg} 12637ec681f3Smrg 12647ec681f3Smrgbool 12657ec681f3Smrgzink_is_depth_format_supported(struct zink_screen *screen, VkFormat format) 12667ec681f3Smrg{ 12677ec681f3Smrg VkFormatProperties props; 12687ec681f3Smrg VKSCR(GetPhysicalDeviceFormatProperties)(screen->pdev, format, &props); 12697ec681f3Smrg return (props.linearTilingFeatures | props.optimalTilingFeatures) & 12707ec681f3Smrg VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; 12717ec681f3Smrg} 12727ec681f3Smrg 12737ec681f3Smrgstatic enum pipe_format 12747ec681f3Smrgemulate_x8(enum pipe_format format) 12757ec681f3Smrg{ 12767ec681f3Smrg /* convert missing X8 variants to A8 */ 12777ec681f3Smrg switch (format) { 12787ec681f3Smrg case PIPE_FORMAT_B8G8R8X8_UNORM: 12797ec681f3Smrg return PIPE_FORMAT_B8G8R8A8_UNORM; 12807ec681f3Smrg 12817ec681f3Smrg case PIPE_FORMAT_B8G8R8X8_SRGB: 12827ec681f3Smrg return PIPE_FORMAT_B8G8R8A8_SRGB; 12837ec681f3Smrg 12847ec681f3Smrg case PIPE_FORMAT_R8G8B8X8_SINT: 12857ec681f3Smrg return PIPE_FORMAT_R8G8B8A8_SINT; 12867ec681f3Smrg case PIPE_FORMAT_R8G8B8X8_SNORM: 12877ec681f3Smrg return PIPE_FORMAT_R8G8B8A8_SNORM; 12887ec681f3Smrg case PIPE_FORMAT_R8G8B8X8_UNORM: 12897ec681f3Smrg return PIPE_FORMAT_R8G8B8A8_UNORM; 12907ec681f3Smrg 12917ec681f3Smrg case PIPE_FORMAT_R16G16B16X16_FLOAT: 12927ec681f3Smrg return PIPE_FORMAT_R16G16B16A16_FLOAT; 12937ec681f3Smrg case PIPE_FORMAT_R16G16B16X16_SINT: 12947ec681f3Smrg return PIPE_FORMAT_R16G16B16A16_SINT; 12957ec681f3Smrg case PIPE_FORMAT_R16G16B16X16_SNORM: 12967ec681f3Smrg return PIPE_FORMAT_R16G16B16A16_SNORM; 12977ec681f3Smrg case PIPE_FORMAT_R16G16B16X16_UNORM: 12987ec681f3Smrg return PIPE_FORMAT_R16G16B16A16_UNORM; 12997ec681f3Smrg 13007ec681f3Smrg default: 13017ec681f3Smrg return format; 13027ec681f3Smrg } 13037ec681f3Smrg} 13047ec681f3Smrg 13057ec681f3SmrgVkFormat 13067ec681f3Smrgzink_get_format(struct zink_screen *screen, enum pipe_format format) 13077ec681f3Smrg{ 13087ec681f3Smrg VkFormat ret = zink_pipe_format_to_vk_format(emulate_x8(format)); 13097ec681f3Smrg 13107ec681f3Smrg if (format == PIPE_FORMAT_X32_S8X24_UINT) 13117ec681f3Smrg return VK_FORMAT_D32_SFLOAT_S8_UINT; 13127ec681f3Smrg 13137ec681f3Smrg if (format == PIPE_FORMAT_X24S8_UINT) 13147ec681f3Smrg /* valid when using aspects to extract stencil, 13157ec681f3Smrg * fails format test because it's emulated */ 13167ec681f3Smrg ret = VK_FORMAT_D24_UNORM_S8_UINT; 13177ec681f3Smrg 13187ec681f3Smrg if (ret == VK_FORMAT_X8_D24_UNORM_PACK32 && 13197ec681f3Smrg !screen->have_X8_D24_UNORM_PACK32) { 13207ec681f3Smrg assert(zink_is_depth_format_supported(screen, VK_FORMAT_D32_SFLOAT)); 13217ec681f3Smrg return VK_FORMAT_D32_SFLOAT; 13227ec681f3Smrg } 13237ec681f3Smrg 13247ec681f3Smrg if (ret == VK_FORMAT_D24_UNORM_S8_UINT && 13257ec681f3Smrg !screen->have_D24_UNORM_S8_UINT) { 13267ec681f3Smrg assert(zink_is_depth_format_supported(screen, 13277ec681f3Smrg VK_FORMAT_D32_SFLOAT_S8_UINT)); 13287ec681f3Smrg return VK_FORMAT_D32_SFLOAT_S8_UINT; 13297ec681f3Smrg } 13307ec681f3Smrg 13317ec681f3Smrg if ((ret == VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT && 13327ec681f3Smrg !screen->info.format_4444_feats.formatA4B4G4R4) || 13337ec681f3Smrg (ret == VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT && 13347ec681f3Smrg !screen->info.format_4444_feats.formatA4R4G4B4)) 13357ec681f3Smrg return VK_FORMAT_UNDEFINED; 13367ec681f3Smrg 13377ec681f3Smrg return ret; 13387ec681f3Smrg} 13397ec681f3Smrg 13407ec681f3Smrgvoid 13417ec681f3Smrgzink_screen_init_descriptor_funcs(struct zink_screen *screen, bool fallback) 13427ec681f3Smrg{ 13437ec681f3Smrg if (screen->info.have_KHR_descriptor_update_template && 13447ec681f3Smrg !fallback && 13457ec681f3Smrg screen->descriptor_mode == ZINK_DESCRIPTOR_MODE_LAZY) { 13467ec681f3Smrg#define LAZY(FUNC) screen->FUNC = zink_##FUNC##_lazy 13477ec681f3Smrg LAZY(descriptor_program_init); 13487ec681f3Smrg LAZY(descriptor_program_deinit); 13497ec681f3Smrg LAZY(context_invalidate_descriptor_state); 13507ec681f3Smrg LAZY(batch_descriptor_init); 13517ec681f3Smrg LAZY(batch_descriptor_reset); 13527ec681f3Smrg LAZY(batch_descriptor_deinit); 13537ec681f3Smrg LAZY(descriptors_init); 13547ec681f3Smrg LAZY(descriptors_deinit); 13557ec681f3Smrg LAZY(descriptors_update); 13567ec681f3Smrg#undef LAZY 13577ec681f3Smrg } else { 13587ec681f3Smrg#define DEFAULT(FUNC) screen->FUNC = zink_##FUNC 13597ec681f3Smrg DEFAULT(descriptor_program_init); 13607ec681f3Smrg DEFAULT(descriptor_program_deinit); 13617ec681f3Smrg DEFAULT(context_invalidate_descriptor_state); 13627ec681f3Smrg DEFAULT(batch_descriptor_init); 13637ec681f3Smrg DEFAULT(batch_descriptor_reset); 13647ec681f3Smrg DEFAULT(batch_descriptor_deinit); 13657ec681f3Smrg DEFAULT(descriptors_init); 13667ec681f3Smrg DEFAULT(descriptors_deinit); 13677ec681f3Smrg DEFAULT(descriptors_update); 13687ec681f3Smrg#undef DEFAULT 13697ec681f3Smrg } 13707ec681f3Smrg} 13717ec681f3Smrg 13727ec681f3Smrgstatic bool 13737ec681f3Smrgcheck_have_device_time(struct zink_screen *screen) 13747ec681f3Smrg{ 13757ec681f3Smrg uint32_t num_domains = 0; 13767ec681f3Smrg VkTimeDomainEXT domains[8]; //current max is 4 13777ec681f3Smrg VKSCR(GetPhysicalDeviceCalibrateableTimeDomainsEXT)(screen->pdev, &num_domains, NULL); 13787ec681f3Smrg assert(num_domains > 0); 13797ec681f3Smrg assert(num_domains < ARRAY_SIZE(domains)); 13807ec681f3Smrg 13817ec681f3Smrg VKSCR(GetPhysicalDeviceCalibrateableTimeDomainsEXT)(screen->pdev, &num_domains, domains); 13827ec681f3Smrg 13837ec681f3Smrg /* VK_TIME_DOMAIN_DEVICE_EXT is used for the ctx->get_timestamp hook and is the only one we really need */ 13847ec681f3Smrg for (unsigned i = 0; i < num_domains; i++) { 13857ec681f3Smrg if (domains[i] == VK_TIME_DOMAIN_DEVICE_EXT) { 13867ec681f3Smrg return true; 13877ec681f3Smrg } 13887ec681f3Smrg } 13897ec681f3Smrg 13907ec681f3Smrg return false; 13917ec681f3Smrg} 13927ec681f3Smrg 13937ec681f3Smrgstatic void 13947ec681f3Smrgzink_error(const char *msg) 13957ec681f3Smrg{ 13967ec681f3Smrg} 13977ec681f3Smrg 13987ec681f3Smrgstatic void 13997ec681f3Smrgzink_warn(const char *msg) 14007ec681f3Smrg{ 14017ec681f3Smrg} 14027ec681f3Smrg 14037ec681f3Smrgstatic void 14047ec681f3Smrgzink_info(const char *msg) 14057ec681f3Smrg{ 14067ec681f3Smrg} 14077ec681f3Smrg 14087ec681f3Smrgstatic void 14097ec681f3Smrgzink_msg(const char *msg) 14107ec681f3Smrg{ 14117ec681f3Smrg} 14127ec681f3Smrg 14137ec681f3Smrgstatic VKAPI_ATTR VkBool32 VKAPI_CALL 14147ec681f3Smrgzink_debug_util_callback( 14157ec681f3Smrg VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, 14167ec681f3Smrg VkDebugUtilsMessageTypeFlagsEXT messageType, 14177ec681f3Smrg const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, 14187ec681f3Smrg void *pUserData) 14197ec681f3Smrg{ 14207ec681f3Smrg // Pick message prefix and color to use. 14217ec681f3Smrg // Only MacOS and Linux have been tested for color support 14227ec681f3Smrg if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { 14237ec681f3Smrg zink_error(pCallbackData->pMessage); 14247ec681f3Smrg } else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { 14257ec681f3Smrg zink_warn(pCallbackData->pMessage); 14267ec681f3Smrg } else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) { 14277ec681f3Smrg zink_info(pCallbackData->pMessage); 14287ec681f3Smrg } else 14297ec681f3Smrg zink_msg(pCallbackData->pMessage); 14307ec681f3Smrg 14317ec681f3Smrg return VK_FALSE; 14327ec681f3Smrg} 14337ec681f3Smrg 14347ec681f3Smrgstatic bool 14357ec681f3Smrgcreate_debug(struct zink_screen *screen) 14367ec681f3Smrg{ 14377ec681f3Smrg VkDebugUtilsMessengerCreateInfoEXT vkDebugUtilsMessengerCreateInfoEXT = { 14387ec681f3Smrg VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, 14397ec681f3Smrg NULL, 14407ec681f3Smrg 0, // flags 14417ec681f3Smrg VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | 14427ec681f3Smrg VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | 14437ec681f3Smrg VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | 14447ec681f3Smrg VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 14457ec681f3Smrg VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | 14467ec681f3Smrg VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | 14477ec681f3Smrg VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, 14487ec681f3Smrg zink_debug_util_callback, 14497ec681f3Smrg NULL 14507ec681f3Smrg }; 14517ec681f3Smrg 14527ec681f3Smrg VkDebugUtilsMessengerEXT vkDebugUtilsCallbackEXT = VK_NULL_HANDLE; 14537ec681f3Smrg 14547ec681f3Smrg VKSCR(CreateDebugUtilsMessengerEXT)( 14557ec681f3Smrg screen->instance, 14567ec681f3Smrg &vkDebugUtilsMessengerCreateInfoEXT, 14577ec681f3Smrg NULL, 14587ec681f3Smrg &vkDebugUtilsCallbackEXT 14597ec681f3Smrg ); 14607ec681f3Smrg 14617ec681f3Smrg screen->debugUtilsCallbackHandle = vkDebugUtilsCallbackEXT; 14627ec681f3Smrg 14637ec681f3Smrg return true; 14647ec681f3Smrg} 14657ec681f3Smrg 14667ec681f3Smrgstatic bool 14677ec681f3Smrgzink_internal_setup_moltenvk(struct zink_screen *screen) 14687ec681f3Smrg{ 14697ec681f3Smrg#if defined(MVK_VERSION) 14707ec681f3Smrg if (!screen->instance_info.have_MVK_moltenvk) 14717ec681f3Smrg return true; 14727ec681f3Smrg 14737ec681f3Smrg GET_PROC_ADDR_INSTANCE_LOCAL(screen->instance, GetMoltenVKConfigurationMVK); 14747ec681f3Smrg GET_PROC_ADDR_INSTANCE_LOCAL(screen->instance, SetMoltenVKConfigurationMVK); 14757ec681f3Smrg GET_PROC_ADDR_INSTANCE_LOCAL(screen->instance, GetVersionStringsMVK); 14767ec681f3Smrg 14777ec681f3Smrg if (vk_GetVersionStringsMVK) { 14787ec681f3Smrg char molten_version[64] = {0}; 14797ec681f3Smrg char vulkan_version[64] = {0}; 14807ec681f3Smrg 14817ec681f3Smrg vk_GetVersionStringsMVK(molten_version, sizeof(molten_version) - 1, vulkan_version, sizeof(vulkan_version) - 1); 14827ec681f3Smrg 14837ec681f3Smrg printf("zink: MoltenVK %s Vulkan %s \n", molten_version, vulkan_version); 14847ec681f3Smrg } 14857ec681f3Smrg 14867ec681f3Smrg if (vk_GetMoltenVKConfigurationMVK && vk_SetMoltenVKConfigurationMVK) { 14877ec681f3Smrg MVKConfiguration molten_config = {0}; 14887ec681f3Smrg size_t molten_config_size = sizeof(molten_config); 14897ec681f3Smrg 14907ec681f3Smrg VkResult res = vk_GetMoltenVKConfigurationMVK(screen->instance, &molten_config, &molten_config_size); 14917ec681f3Smrg if (res == VK_SUCCESS || res == VK_INCOMPLETE) { 14927ec681f3Smrg // Needed to allow MoltenVK to accept VkImageView swizzles. 14937ec681f3Smrg // Encountered when using VK_FORMAT_R8G8_UNORM 14947ec681f3Smrg molten_config.fullImageViewSwizzle = VK_TRUE; 14957ec681f3Smrg vk_SetMoltenVKConfigurationMVK(screen->instance, &molten_config, &molten_config_size); 14967ec681f3Smrg } 14977ec681f3Smrg } 14987ec681f3Smrg#endif // MVK_VERSION 14997ec681f3Smrg 15007ec681f3Smrg return true; 15017ec681f3Smrg} 15027ec681f3Smrg 15037ec681f3Smrgstatic void 15047ec681f3Smrgcheck_device_needs_mesa_wsi(struct zink_screen *screen) 15057ec681f3Smrg{ 15067ec681f3Smrg if ( 15077ec681f3Smrg /* Raspberry Pi 4 V3DV driver */ 15087ec681f3Smrg (screen->info.props.vendorID == 0x14E4 && 15097ec681f3Smrg screen->info.props.deviceID == 42) || 15107ec681f3Smrg /* RADV */ 15117ec681f3Smrg screen->info.driver_props.driverID == VK_DRIVER_ID_MESA_RADV_KHR 15127ec681f3Smrg ) { 15137ec681f3Smrg screen->needs_mesa_wsi = true; 15147ec681f3Smrg } else if (screen->info.driver_props.driverID == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR) 15157ec681f3Smrg screen->needs_mesa_flush_wsi = true; 15167ec681f3Smrg 15177ec681f3Smrg} 15187ec681f3Smrg 15197ec681f3Smrgstatic void 15207ec681f3Smrgpopulate_format_props(struct zink_screen *screen) 15217ec681f3Smrg{ 15227ec681f3Smrg for (unsigned i = 0; i < PIPE_FORMAT_COUNT; i++) { 15237ec681f3Smrg VkFormat format = zink_get_format(screen, i); 15247ec681f3Smrg if (!format) 15257ec681f3Smrg continue; 15267ec681f3Smrg if (VKSCR(GetPhysicalDeviceFormatProperties2)) { 15277ec681f3Smrg VkFormatProperties2 props = {0}; 15287ec681f3Smrg props.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2; 15297ec681f3Smrg 15307ec681f3Smrg VkDrmFormatModifierPropertiesListEXT mod_props; 15317ec681f3Smrg VkDrmFormatModifierPropertiesEXT mods[128]; 15327ec681f3Smrg if (screen->info.have_EXT_image_drm_format_modifier) { 15337ec681f3Smrg mod_props.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT; 15347ec681f3Smrg mod_props.pNext = NULL; 15357ec681f3Smrg mod_props.drmFormatModifierCount = ARRAY_SIZE(mods); 15367ec681f3Smrg mod_props.pDrmFormatModifierProperties = mods; 15377ec681f3Smrg props.pNext = &mod_props; 15387ec681f3Smrg } 15397ec681f3Smrg VKSCR(GetPhysicalDeviceFormatProperties2)(screen->pdev, format, &props); 15407ec681f3Smrg screen->format_props[i] = props.formatProperties; 15417ec681f3Smrg if (screen->info.have_EXT_image_drm_format_modifier && mod_props.drmFormatModifierCount) { 15427ec681f3Smrg screen->modifier_props[i].drmFormatModifierCount = mod_props.drmFormatModifierCount; 15437ec681f3Smrg screen->modifier_props[i].pDrmFormatModifierProperties = ralloc_array(screen, VkDrmFormatModifierPropertiesEXT, mod_props.drmFormatModifierCount); 15447ec681f3Smrg if (mod_props.pDrmFormatModifierProperties) { 15457ec681f3Smrg for (unsigned j = 0; j < mod_props.drmFormatModifierCount; j++) 15467ec681f3Smrg screen->modifier_props[i].pDrmFormatModifierProperties[j] = mod_props.pDrmFormatModifierProperties[j]; 15477ec681f3Smrg } 15487ec681f3Smrg } 15497ec681f3Smrg } else 15507ec681f3Smrg VKSCR(GetPhysicalDeviceFormatProperties)(screen->pdev, format, &screen->format_props[i]); 15517ec681f3Smrg } 15527ec681f3Smrg} 15537ec681f3Smrg 15547ec681f3Smrgbool 15557ec681f3Smrgzink_screen_init_semaphore(struct zink_screen *screen) 15567ec681f3Smrg{ 15577ec681f3Smrg VkSemaphoreCreateInfo sci = {0}; 15587ec681f3Smrg VkSemaphoreTypeCreateInfo tci = {0}; 15597ec681f3Smrg VkSemaphore sem; 15607ec681f3Smrg sci.pNext = &tci; 15617ec681f3Smrg sci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 15627ec681f3Smrg tci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO; 15637ec681f3Smrg tci.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE; 15647ec681f3Smrg 15657ec681f3Smrg if (VKSCR(CreateSemaphore)(screen->dev, &sci, NULL, &sem) == VK_SUCCESS) { 15667ec681f3Smrg /* semaphore signal values can never decrease, 15677ec681f3Smrg * so we need a new semaphore anytime we overflow 15687ec681f3Smrg */ 15697ec681f3Smrg if (screen->prev_sem) 15707ec681f3Smrg VKSCR(DestroySemaphore)(screen->dev, screen->prev_sem, NULL); 15717ec681f3Smrg screen->prev_sem = screen->sem; 15727ec681f3Smrg screen->sem = sem; 15737ec681f3Smrg return true; 15747ec681f3Smrg } 15757ec681f3Smrg screen->info.have_KHR_timeline_semaphore = false; 15767ec681f3Smrg return false; 15777ec681f3Smrg} 15787ec681f3Smrg 15797ec681f3Smrgbool 15807ec681f3Smrgzink_screen_timeline_wait(struct zink_screen *screen, uint32_t batch_id, uint64_t timeout) 15817ec681f3Smrg{ 15827ec681f3Smrg VkSemaphoreWaitInfo wi = {0}; 15837ec681f3Smrg 15847ec681f3Smrg if (zink_screen_check_last_finished(screen, batch_id)) 15857ec681f3Smrg return true; 15867ec681f3Smrg 15877ec681f3Smrg wi.sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO; 15887ec681f3Smrg wi.semaphoreCount = 1; 15897ec681f3Smrg /* handle batch_id overflow */ 15907ec681f3Smrg wi.pSemaphores = batch_id > screen->curr_batch ? &screen->prev_sem : &screen->sem; 15917ec681f3Smrg uint64_t batch_id64 = batch_id; 15927ec681f3Smrg wi.pValues = &batch_id64; 15937ec681f3Smrg bool success = false; 15947ec681f3Smrg if (screen->device_lost) 15957ec681f3Smrg return true; 15967ec681f3Smrg VkResult ret = VKSCR(WaitSemaphores)(screen->dev, &wi, timeout); 15977ec681f3Smrg success = zink_screen_handle_vkresult(screen, ret); 15987ec681f3Smrg 15997ec681f3Smrg if (success) 16007ec681f3Smrg zink_screen_update_last_finished(screen, batch_id); 16017ec681f3Smrg 16027ec681f3Smrg return success; 16037ec681f3Smrg} 16047ec681f3Smrg 16057ec681f3Smrgstruct noop_submit_info { 16067ec681f3Smrg struct zink_screen *screen; 16077ec681f3Smrg VkFence fence; 16087ec681f3Smrg}; 16097ec681f3Smrg 16107ec681f3Smrgstatic void 16117ec681f3Smrgnoop_submit(void *data, void *gdata, int thread_index) 16127ec681f3Smrg{ 16137ec681f3Smrg struct noop_submit_info *n = data; 16147ec681f3Smrg VkSubmitInfo si = {0}; 16157ec681f3Smrg si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 16167ec681f3Smrg simple_mtx_lock(&n->screen->queue_lock); 16177ec681f3Smrg if (n->VKSCR(QueueSubmit)(n->screen->threaded ? n->screen->thread_queue : n->screen->queue, 16187ec681f3Smrg 1, &si, n->fence) != VK_SUCCESS) { 16197ec681f3Smrg debug_printf("ZINK: vkQueueSubmit() failed\n"); 16207ec681f3Smrg n->screen->device_lost = true; 16217ec681f3Smrg } 16227ec681f3Smrg simple_mtx_unlock(&n->screen->queue_lock); 16237ec681f3Smrg} 16247ec681f3Smrg 16257ec681f3Smrgbool 16267ec681f3Smrgzink_screen_batch_id_wait(struct zink_screen *screen, uint32_t batch_id, uint64_t timeout) 16277ec681f3Smrg{ 16287ec681f3Smrg if (zink_screen_check_last_finished(screen, batch_id)) 16297ec681f3Smrg return true; 16307ec681f3Smrg 16317ec681f3Smrg if (screen->info.have_KHR_timeline_semaphore) 16327ec681f3Smrg return zink_screen_timeline_wait(screen, batch_id, timeout); 16337ec681f3Smrg 16347ec681f3Smrg if (!timeout) 16357ec681f3Smrg return false; 16367ec681f3Smrg 16377ec681f3Smrg uint32_t new_id = 0; 16387ec681f3Smrg while (!new_id) 16397ec681f3Smrg new_id = p_atomic_inc_return(&screen->curr_batch); 16407ec681f3Smrg VkResult ret; 16417ec681f3Smrg struct noop_submit_info n; 16427ec681f3Smrg uint64_t abs_timeout = os_time_get_absolute_timeout(timeout); 16437ec681f3Smrg uint64_t remaining = PIPE_TIMEOUT_INFINITE; 16447ec681f3Smrg VkFenceCreateInfo fci = {0}; 16457ec681f3Smrg struct util_queue_fence fence; 16467ec681f3Smrg util_queue_fence_init(&fence); 16477ec681f3Smrg fci.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 16487ec681f3Smrg 16497ec681f3Smrg if (VKSCR(CreateFence)(screen->dev, &fci, NULL, &n.fence) != VK_SUCCESS) 16507ec681f3Smrg return false; 16517ec681f3Smrg 16527ec681f3Smrg n.screen = screen; 16537ec681f3Smrg if (screen->threaded) { 16547ec681f3Smrg /* must use thread dispatch for sanity */ 16557ec681f3Smrg util_queue_add_job(&screen->flush_queue, &n, &fence, noop_submit, NULL, 0); 16567ec681f3Smrg util_queue_fence_wait(&fence); 16577ec681f3Smrg } else { 16587ec681f3Smrg noop_submit(&n, NULL, 0); 16597ec681f3Smrg } 16607ec681f3Smrg if (timeout != PIPE_TIMEOUT_INFINITE) { 16617ec681f3Smrg int64_t time_ns = os_time_get_nano(); 16627ec681f3Smrg remaining = abs_timeout > time_ns ? abs_timeout - time_ns : 0; 16637ec681f3Smrg } 16647ec681f3Smrg 16657ec681f3Smrg if (remaining) 16667ec681f3Smrg ret = VKSCR(WaitForFences)(screen->dev, 1, &n.fence, VK_TRUE, remaining); 16677ec681f3Smrg else 16687ec681f3Smrg ret = VKSCR(GetFenceStatus)(screen->dev, n.fence); 16697ec681f3Smrg VKSCR(DestroyFence)(screen->dev, n.fence, NULL); 16707ec681f3Smrg bool success = zink_screen_handle_vkresult(screen, ret); 16717ec681f3Smrg 16727ec681f3Smrg if (success) 16737ec681f3Smrg zink_screen_update_last_finished(screen, new_id); 16747ec681f3Smrg 16757ec681f3Smrg return success; 16767ec681f3Smrg} 16777ec681f3Smrg 16787ec681f3Smrgstatic uint32_t 16797ec681f3Smrgzink_get_loader_version(void) 16807ec681f3Smrg{ 16817ec681f3Smrg 16827ec681f3Smrg uint32_t loader_version = VK_API_VERSION_1_0; 16837ec681f3Smrg 16847ec681f3Smrg // Get the Loader version 16857ec681f3Smrg GET_PROC_ADDR_INSTANCE_LOCAL(NULL, EnumerateInstanceVersion); 16867ec681f3Smrg if (vk_EnumerateInstanceVersion) { 16877ec681f3Smrg uint32_t loader_version_temp = VK_API_VERSION_1_0; 16887ec681f3Smrg if (VK_SUCCESS == (*vk_EnumerateInstanceVersion)(&loader_version_temp)) { 16897ec681f3Smrg loader_version = loader_version_temp; 16907ec681f3Smrg } 16917ec681f3Smrg } 16927ec681f3Smrg 16937ec681f3Smrg return loader_version; 16947ec681f3Smrg} 16957ec681f3Smrg 16967ec681f3Smrgstatic void 16977ec681f3Smrgzink_query_memory_info(struct pipe_screen *pscreen, struct pipe_memory_info *info) 16987ec681f3Smrg{ 16997ec681f3Smrg struct zink_screen *screen = zink_screen(pscreen); 17007ec681f3Smrg memset(info, 0, sizeof(struct pipe_memory_info)); 17017ec681f3Smrg if (screen->info.have_EXT_memory_budget && VKSCR(GetPhysicalDeviceMemoryProperties2)) { 17027ec681f3Smrg VkPhysicalDeviceMemoryProperties2 mem = {0}; 17037ec681f3Smrg mem.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; 17047ec681f3Smrg 17057ec681f3Smrg VkPhysicalDeviceMemoryBudgetPropertiesEXT budget = {0}; 17067ec681f3Smrg budget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT; 17077ec681f3Smrg mem.pNext = &budget; 17087ec681f3Smrg VKSCR(GetPhysicalDeviceMemoryProperties2)(screen->pdev, &mem); 17097ec681f3Smrg 17107ec681f3Smrg for (unsigned i = 0; i < mem.memoryProperties.memoryHeapCount; i++) { 17117ec681f3Smrg if (mem.memoryProperties.memoryHeaps[i].flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) { 17127ec681f3Smrg /* VRAM */ 17137ec681f3Smrg info->total_device_memory += mem.memoryProperties.memoryHeaps[i].size / 1024; 17147ec681f3Smrg info->avail_device_memory += (mem.memoryProperties.memoryHeaps[i].size - budget.heapUsage[i]) / 1024; 17157ec681f3Smrg } else { 17167ec681f3Smrg /* GART */ 17177ec681f3Smrg info->total_staging_memory += mem.memoryProperties.memoryHeaps[i].size / 1024; 17187ec681f3Smrg info->avail_staging_memory += (mem.memoryProperties.memoryHeaps[i].size - budget.heapUsage[i]) / 1024; 17197ec681f3Smrg } 17207ec681f3Smrg } 17217ec681f3Smrg /* evictions not yet supported in vulkan */ 17227ec681f3Smrg } else { 17237ec681f3Smrg for (unsigned i = 0; i < screen->info.mem_props.memoryHeapCount; i++) { 17247ec681f3Smrg if (screen->info.mem_props.memoryHeaps[i].flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) { 17257ec681f3Smrg /* VRAM */ 17267ec681f3Smrg info->total_device_memory += screen->info.mem_props.memoryHeaps[i].size / 1024; 17277ec681f3Smrg /* free real estate! */ 17287ec681f3Smrg info->avail_device_memory += info->total_device_memory; 17297ec681f3Smrg } else { 17307ec681f3Smrg /* GART */ 17317ec681f3Smrg info->total_staging_memory += screen->info.mem_props.memoryHeaps[i].size / 1024; 17327ec681f3Smrg /* free real estate! */ 17337ec681f3Smrg info->avail_staging_memory += info->total_staging_memory; 17347ec681f3Smrg } 17357ec681f3Smrg } 17367ec681f3Smrg } 17377ec681f3Smrg} 17387ec681f3Smrg 17397ec681f3Smrgstatic void 17407ec681f3Smrgzink_query_dmabuf_modifiers(struct pipe_screen *pscreen, enum pipe_format format, int max, uint64_t *modifiers, unsigned int *external_only, int *count) 17417ec681f3Smrg{ 17427ec681f3Smrg struct zink_screen *screen = zink_screen(pscreen); 17437ec681f3Smrg *count = screen->modifier_props[format].drmFormatModifierCount; 17447ec681f3Smrg for (int i = 0; i < MIN2(max, *count); i++) 17457ec681f3Smrg modifiers[i] = screen->modifier_props[format].pDrmFormatModifierProperties[i].drmFormatModifier; 17467ec681f3Smrg} 17477ec681f3Smrg 17487ec681f3Smrgstatic bool 17497ec681f3Smrgzink_is_dmabuf_modifier_supported(struct pipe_screen *pscreen, uint64_t modifier, enum pipe_format format, bool *external_only) 17507ec681f3Smrg{ 17517ec681f3Smrg struct zink_screen *screen = zink_screen(pscreen); 17527ec681f3Smrg for (unsigned i = 0; i < screen->modifier_props[format].drmFormatModifierCount; i++) 17537ec681f3Smrg if (screen->modifier_props[format].pDrmFormatModifierProperties[i].drmFormatModifier == modifier) 17547ec681f3Smrg return true; 17557ec681f3Smrg return false; 17567ec681f3Smrg} 17577ec681f3Smrg 17587ec681f3Smrgstatic unsigned 17597ec681f3Smrgzink_get_dmabuf_modifier_planes(struct pipe_screen *pscreen, uint64_t modifier, enum pipe_format format) 17607ec681f3Smrg{ 17617ec681f3Smrg struct zink_screen *screen = zink_screen(pscreen); 17627ec681f3Smrg for (unsigned i = 0; i < screen->modifier_props[format].drmFormatModifierCount; i++) 17637ec681f3Smrg if (screen->modifier_props[format].pDrmFormatModifierProperties[i].drmFormatModifier == modifier) 17647ec681f3Smrg return screen->modifier_props[format].pDrmFormatModifierProperties[i].drmFormatModifierPlaneCount; 17657ec681f3Smrg return 0; 17667ec681f3Smrg} 17677ec681f3Smrg 17687ec681f3Smrgstatic VkDevice 17697ec681f3Smrgzink_create_logical_device(struct zink_screen *screen) 17707ec681f3Smrg{ 17717ec681f3Smrg VkDevice dev = VK_NULL_HANDLE; 17727ec681f3Smrg 17737ec681f3Smrg VkDeviceQueueCreateInfo qci = {0}; 17747ec681f3Smrg float dummy = 0.0f; 17757ec681f3Smrg qci.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 17767ec681f3Smrg qci.queueFamilyIndex = screen->gfx_queue; 17777ec681f3Smrg qci.queueCount = screen->threaded && screen->max_queues > 1 ? 2 : 1; 17787ec681f3Smrg qci.pQueuePriorities = &dummy; 17797ec681f3Smrg 17807ec681f3Smrg VkDeviceCreateInfo dci = {0}; 17817ec681f3Smrg dci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 17827ec681f3Smrg dci.queueCreateInfoCount = 1; 17837ec681f3Smrg dci.pQueueCreateInfos = &qci; 17847ec681f3Smrg /* extensions don't have bool members in pEnabledFeatures. 17857ec681f3Smrg * this requires us to pass the whole VkPhysicalDeviceFeatures2 struct 17867ec681f3Smrg */ 17877ec681f3Smrg if (screen->info.feats.sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2) { 17887ec681f3Smrg dci.pNext = &screen->info.feats; 17897ec681f3Smrg } else { 17907ec681f3Smrg dci.pEnabledFeatures = &screen->info.feats.features; 17917ec681f3Smrg } 17927ec681f3Smrg 17937ec681f3Smrg dci.ppEnabledExtensionNames = screen->info.extensions; 17947ec681f3Smrg dci.enabledExtensionCount = screen->info.num_extensions; 17957ec681f3Smrg 17967ec681f3Smrg vkCreateDevice(screen->pdev, &dci, NULL, &dev); 17977ec681f3Smrg return dev; 17987ec681f3Smrg} 17997ec681f3Smrg 18007ec681f3Smrgstatic void 18017ec681f3Smrgpre_hash_descriptor_states(struct zink_screen *screen) 18027ec681f3Smrg{ 18037ec681f3Smrg VkImageViewCreateInfo null_info = {.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO}; 18047ec681f3Smrg VkBufferViewCreateInfo null_binfo = {.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; 18057ec681f3Smrg screen->null_descriptor_hashes.image_view = _mesa_hash_data(&null_info, sizeof(VkImageViewCreateInfo)); 18067ec681f3Smrg screen->null_descriptor_hashes.buffer_view = _mesa_hash_data(&null_binfo, sizeof(VkBufferViewCreateInfo)); 18077ec681f3Smrg} 18087ec681f3Smrg 18097ec681f3Smrgstatic void 18107ec681f3Smrgcheck_base_requirements(struct zink_screen *screen) 18117ec681f3Smrg{ 18127ec681f3Smrg if (!screen->info.feats.features.logicOp || 18137ec681f3Smrg !screen->info.feats.features.fillModeNonSolid || 18147ec681f3Smrg !screen->info.feats.features.wideLines || 18157ec681f3Smrg !screen->info.feats.features.largePoints || 18167ec681f3Smrg !screen->info.feats.features.shaderClipDistance || 18177ec681f3Smrg !(screen->info.feats12.scalarBlockLayout || 18187ec681f3Smrg screen->info.have_EXT_scalar_block_layout) || 18197ec681f3Smrg !screen->info.have_KHR_maintenance1 || 18207ec681f3Smrg !screen->info.have_EXT_custom_border_color || 18217ec681f3Smrg !screen->info.have_EXT_line_rasterization) { 18227ec681f3Smrg fprintf(stderr, "WARNING: Some incorrect rendering " 18237ec681f3Smrg "might occur because the selected Vulkan device (%s) doesn't support " 18247ec681f3Smrg "base Zink requirements: ", screen->info.props.deviceName); 18257ec681f3Smrg#define CHECK_OR_PRINT(X) \ 18267ec681f3Smrg if (!screen->info.X) \ 18277ec681f3Smrg fprintf(stderr, "%s ", #X) 18287ec681f3Smrg CHECK_OR_PRINT(feats.features.logicOp); 18297ec681f3Smrg CHECK_OR_PRINT(feats.features.fillModeNonSolid); 18307ec681f3Smrg CHECK_OR_PRINT(feats.features.wideLines); 18317ec681f3Smrg CHECK_OR_PRINT(feats.features.largePoints); 18327ec681f3Smrg CHECK_OR_PRINT(feats.features.shaderClipDistance); 18337ec681f3Smrg if (!screen->info.feats12.scalarBlockLayout && !screen->info.have_EXT_scalar_block_layout) 18347ec681f3Smrg printf("scalarBlockLayout OR EXT_scalar_block_layout "); 18357ec681f3Smrg CHECK_OR_PRINT(have_KHR_maintenance1); 18367ec681f3Smrg CHECK_OR_PRINT(have_EXT_custom_border_color); 18377ec681f3Smrg CHECK_OR_PRINT(have_EXT_line_rasterization); 18387ec681f3Smrg fprintf(stderr, "\n"); 18397ec681f3Smrg } 18407ec681f3Smrg} 18417ec681f3Smrg 18427ec681f3Smrgstatic void 18437ec681f3Smrgzink_get_sample_pixel_grid(struct pipe_screen *pscreen, unsigned sample_count, 18447ec681f3Smrg unsigned *width, unsigned *height) 18457ec681f3Smrg{ 18467ec681f3Smrg struct zink_screen *screen = zink_screen(pscreen); 18477ec681f3Smrg unsigned idx = util_logbase2_ceil(MAX2(sample_count, 1)); 18487ec681f3Smrg assert(idx < ARRAY_SIZE(screen->maxSampleLocationGridSize)); 18497ec681f3Smrg *width = screen->maxSampleLocationGridSize[idx].width; 18507ec681f3Smrg *height = screen->maxSampleLocationGridSize[idx].height; 18517ec681f3Smrg} 18527ec681f3Smrg 18537ec681f3Smrgstatic struct zink_screen * 18547ec681f3Smrgzink_internal_create_screen(const struct pipe_screen_config *config) 18557ec681f3Smrg{ 18567ec681f3Smrg struct zink_screen *screen = rzalloc(NULL, struct zink_screen); 18577ec681f3Smrg if (!screen) 18587ec681f3Smrg return NULL; 18597ec681f3Smrg 18607ec681f3Smrg util_cpu_detect(); 18617ec681f3Smrg screen->threaded = util_get_cpu_caps()->nr_cpus > 1 && debug_get_bool_option("GALLIUM_THREAD", util_get_cpu_caps()->nr_cpus > 1); 18627ec681f3Smrg if (screen->threaded) 18637ec681f3Smrg util_queue_init(&screen->flush_queue, "zfq", 8, 1, UTIL_QUEUE_INIT_RESIZE_IF_FULL, NULL); 18647ec681f3Smrg 18657ec681f3Smrg zink_debug = debug_get_option_zink_debug(); 18667ec681f3Smrg screen->descriptor_mode = debug_get_option_zink_descriptor_mode(); 18677ec681f3Smrg if (screen->descriptor_mode > ZINK_DESCRIPTOR_MODE_NOTEMPLATES) { 18687ec681f3Smrg printf("Specify exactly one descriptor mode.\n"); 18697ec681f3Smrg abort(); 18707ec681f3Smrg } 18717ec681f3Smrg 18727ec681f3Smrg screen->instance_info.loader_version = zink_get_loader_version(); 18737ec681f3Smrg screen->instance = zink_create_instance(&screen->instance_info); 18747ec681f3Smrg 18757ec681f3Smrg if (!screen->instance) 18767ec681f3Smrg goto fail; 18777ec681f3Smrg 18787ec681f3Smrg vk_instance_dispatch_table_load(&screen->vk.instance, &vkGetInstanceProcAddr, screen->instance); 18797ec681f3Smrg vk_physical_device_dispatch_table_load(&screen->vk.physical_device, &vkGetInstanceProcAddr, screen->instance); 18807ec681f3Smrg 18817ec681f3Smrg zink_verify_instance_extensions(screen); 18827ec681f3Smrg 18837ec681f3Smrg if (screen->instance_info.have_EXT_debug_utils && 18847ec681f3Smrg (zink_debug & ZINK_DEBUG_VALIDATION) && !create_debug(screen)) 18857ec681f3Smrg debug_printf("ZINK: failed to setup debug utils\n"); 18867ec681f3Smrg 18877ec681f3Smrg choose_pdev(screen); 18887ec681f3Smrg if (screen->pdev == VK_NULL_HANDLE) 18897ec681f3Smrg goto fail; 18907ec681f3Smrg 18917ec681f3Smrg update_queue_props(screen); 18927ec681f3Smrg 18937ec681f3Smrg screen->have_X8_D24_UNORM_PACK32 = zink_is_depth_format_supported(screen, 18947ec681f3Smrg VK_FORMAT_X8_D24_UNORM_PACK32); 18957ec681f3Smrg screen->have_D24_UNORM_S8_UINT = zink_is_depth_format_supported(screen, 18967ec681f3Smrg VK_FORMAT_D24_UNORM_S8_UINT); 18977ec681f3Smrg 18987ec681f3Smrg if (!zink_get_physical_device_info(screen)) { 18997ec681f3Smrg debug_printf("ZINK: failed to detect features\n"); 19007ec681f3Smrg goto fail; 19017ec681f3Smrg } 19027ec681f3Smrg 19037ec681f3Smrg /* Some Vulkan implementations have special requirements for WSI 19047ec681f3Smrg * allocations. 19057ec681f3Smrg */ 19067ec681f3Smrg check_device_needs_mesa_wsi(screen); 19077ec681f3Smrg 19087ec681f3Smrg zink_internal_setup_moltenvk(screen); 19097ec681f3Smrg 19107ec681f3Smrg screen->dev = zink_create_logical_device(screen); 19117ec681f3Smrg if (!screen->dev) 19127ec681f3Smrg goto fail; 19137ec681f3Smrg 19147ec681f3Smrg init_queue(screen); 19157ec681f3Smrg if (screen->info.driver_props.driverID == VK_DRIVER_ID_MESA_RADV || 19167ec681f3Smrg screen->info.driver_props.driverID == VK_DRIVER_ID_AMD_OPEN_SOURCE || 19177ec681f3Smrg screen->info.driver_props.driverID == VK_DRIVER_ID_AMD_PROPRIETARY) 19187ec681f3Smrg /* this has bad perf on AMD */ 19197ec681f3Smrg screen->info.have_KHR_push_descriptor = false; 19207ec681f3Smrg 19217ec681f3Smrg vk_device_dispatch_table_load(&screen->vk.device, &vkGetDeviceProcAddr, screen->dev); 19227ec681f3Smrg 19237ec681f3Smrg zink_verify_device_extensions(screen); 19247ec681f3Smrg 19257ec681f3Smrg if (screen->info.have_EXT_calibrated_timestamps && !check_have_device_time(screen)) 19267ec681f3Smrg goto fail; 19277ec681f3Smrg 19287ec681f3Smrg screen->have_triangle_fans = true; 19297ec681f3Smrg#if defined(VK_EXTX_PORTABILITY_SUBSET_EXTENSION_NAME) 19307ec681f3Smrg if (screen->info.have_EXTX_portability_subset) { 19317ec681f3Smrg screen->have_triangle_fans = (VK_TRUE == screen->info.portability_subset_extx_feats.triangleFans); 19327ec681f3Smrg } 19337ec681f3Smrg#endif // VK_EXTX_PORTABILITY_SUBSET_EXTENSION_NAME 19347ec681f3Smrg 19357ec681f3Smrg check_base_requirements(screen); 19367ec681f3Smrg util_live_shader_cache_init(&screen->shaders, zink_create_gfx_shader_state, zink_delete_shader_state); 19377ec681f3Smrg 19387ec681f3Smrg screen->base.get_name = zink_get_name; 19397ec681f3Smrg screen->base.get_vendor = zink_get_vendor; 19407ec681f3Smrg screen->base.get_device_vendor = zink_get_device_vendor; 19417ec681f3Smrg screen->base.get_compute_param = zink_get_compute_param; 19427ec681f3Smrg screen->base.query_memory_info = zink_query_memory_info; 19437ec681f3Smrg screen->base.get_param = zink_get_param; 19447ec681f3Smrg screen->base.get_paramf = zink_get_paramf; 19457ec681f3Smrg screen->base.get_shader_param = zink_get_shader_param; 19467ec681f3Smrg screen->base.get_compiler_options = zink_get_compiler_options; 19477ec681f3Smrg screen->base.get_sample_pixel_grid = zink_get_sample_pixel_grid; 19487ec681f3Smrg screen->base.is_format_supported = zink_is_format_supported; 19497ec681f3Smrg if (screen->info.have_EXT_image_drm_format_modifier && screen->info.have_EXT_external_memory_dma_buf) { 19507ec681f3Smrg screen->base.query_dmabuf_modifiers = zink_query_dmabuf_modifiers; 19517ec681f3Smrg screen->base.is_dmabuf_modifier_supported = zink_is_dmabuf_modifier_supported; 19527ec681f3Smrg screen->base.get_dmabuf_modifier_planes = zink_get_dmabuf_modifier_planes; 19537ec681f3Smrg } 19547ec681f3Smrg screen->base.context_create = zink_context_create; 19557ec681f3Smrg screen->base.flush_frontbuffer = zink_flush_frontbuffer; 19567ec681f3Smrg screen->base.destroy = zink_destroy_screen; 19577ec681f3Smrg screen->base.finalize_nir = zink_shader_finalize; 19587ec681f3Smrg 19597ec681f3Smrg if (screen->info.have_EXT_sample_locations) { 19607ec681f3Smrg VkMultisamplePropertiesEXT prop; 19617ec681f3Smrg prop.sType = VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT; 19627ec681f3Smrg prop.pNext = NULL; 19637ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(screen->maxSampleLocationGridSize); i++) { 19647ec681f3Smrg if (screen->info.sample_locations_props.sampleLocationSampleCounts & (1 << i)) { 19657ec681f3Smrg VKSCR(GetPhysicalDeviceMultisamplePropertiesEXT)(screen->pdev, 1 << i, &prop); 19667ec681f3Smrg screen->maxSampleLocationGridSize[i] = prop.maxSampleLocationGridSize; 19677ec681f3Smrg } 19687ec681f3Smrg } 19697ec681f3Smrg } 19707ec681f3Smrg 19717ec681f3Smrg if (!zink_screen_resource_init(&screen->base)) 19727ec681f3Smrg goto fail; 19737ec681f3Smrg zink_bo_init(screen); 19747ec681f3Smrg zink_screen_fence_init(&screen->base); 19757ec681f3Smrg 19767ec681f3Smrg zink_screen_init_compiler(screen); 19777ec681f3Smrg disk_cache_init(screen); 19787ec681f3Smrg populate_format_props(screen); 19797ec681f3Smrg pre_hash_descriptor_states(screen); 19807ec681f3Smrg 19817ec681f3Smrg slab_create_parent(&screen->transfer_pool, sizeof(struct zink_transfer), 16); 19827ec681f3Smrg 19837ec681f3Smrg#if WITH_XMLCONFIG 19847ec681f3Smrg if (config) { 19857ec681f3Smrg driParseConfigFiles(config->options, config->options_info, 0, "zink", 19867ec681f3Smrg NULL, NULL, NULL, 0, NULL, 0); 19877ec681f3Smrg screen->driconf.dual_color_blend_by_location = driQueryOptionb(config->options, "dual_color_blend_by_location"); 19887ec681f3Smrg //screen->driconf.inline_uniforms = driQueryOptionb(config->options, "radeonsi_inline_uniforms"); 19897ec681f3Smrg } 19907ec681f3Smrg#endif 19917ec681f3Smrg screen->driconf.inline_uniforms = debug_get_bool_option("ZINK_INLINE_UNIFORMS", false); 19927ec681f3Smrg 19937ec681f3Smrg screen->total_video_mem = get_video_mem(screen); 19947ec681f3Smrg screen->clamp_video_mem = screen->total_video_mem * 0.8; 19957ec681f3Smrg if (!os_get_total_physical_memory(&screen->total_mem)) 19967ec681f3Smrg goto fail; 19977ec681f3Smrg 19987ec681f3Smrg if (debug_get_bool_option("ZINK_NO_TIMELINES", false)) 19997ec681f3Smrg screen->info.have_KHR_timeline_semaphore = false; 20007ec681f3Smrg if (screen->info.have_KHR_timeline_semaphore) 20017ec681f3Smrg zink_screen_init_semaphore(screen); 20027ec681f3Smrg 20037ec681f3Smrg memset(&screen->heap_map, UINT8_MAX, sizeof(screen->heap_map)); 20047ec681f3Smrg for (enum zink_heap i = 0; i < ZINK_HEAP_MAX; i++) { 20057ec681f3Smrg for (unsigned j = 0; j < screen->info.mem_props.memoryTypeCount; j++) { 20067ec681f3Smrg VkMemoryPropertyFlags domains = vk_domain_from_heap(i); 20077ec681f3Smrg if ((screen->info.mem_props.memoryTypes[j].propertyFlags & domains) == domains) { 20087ec681f3Smrg assert(screen->heap_map[i] == UINT8_MAX); 20097ec681f3Smrg screen->heap_map[i] = j; 20107ec681f3Smrg break; 20117ec681f3Smrg } 20127ec681f3Smrg } 20137ec681f3Smrg 20147ec681f3Smrg /* not found: use compatible heap */ 20157ec681f3Smrg if (screen->heap_map[i] == UINT8_MAX) { 20167ec681f3Smrg /* only cached mem has a failure case for now */ 20177ec681f3Smrg assert(i == ZINK_HEAP_HOST_VISIBLE_CACHED || i == ZINK_HEAP_DEVICE_LOCAL_LAZY); 20187ec681f3Smrg if (i == ZINK_HEAP_HOST_VISIBLE_CACHED) 20197ec681f3Smrg screen->heap_map[i] = screen->heap_map[ZINK_HEAP_HOST_VISIBLE_COHERENT]; 20207ec681f3Smrg else 20217ec681f3Smrg screen->heap_map[i] = screen->heap_map[ZINK_HEAP_DEVICE_LOCAL]; 20227ec681f3Smrg } 20237ec681f3Smrg } 20247ec681f3Smrg { 20257ec681f3Smrg unsigned vis_vram = screen->heap_map[ZINK_HEAP_DEVICE_LOCAL_VISIBLE]; 20267ec681f3Smrg unsigned vram = screen->heap_map[ZINK_HEAP_DEVICE_LOCAL]; 20277ec681f3Smrg /* determine if vis vram is roughly equal to total vram */ 20287ec681f3Smrg if (screen->info.mem_props.memoryHeaps[screen->info.mem_props.memoryTypes[vis_vram].heapIndex].size > 20297ec681f3Smrg screen->info.mem_props.memoryHeaps[screen->info.mem_props.memoryTypes[vram].heapIndex].size * 0.9) 20307ec681f3Smrg screen->resizable_bar = true; 20317ec681f3Smrg } 20327ec681f3Smrg 20337ec681f3Smrg if (!screen->info.have_KHR_imageless_framebuffer) { 20347ec681f3Smrg simple_mtx_init(&screen->framebuffer_mtx, mtx_plain); 20357ec681f3Smrg _mesa_hash_table_init(&screen->framebuffer_cache, screen, hash_framebuffer_state, equals_framebuffer_state); 20367ec681f3Smrg } 20377ec681f3Smrg 20387ec681f3Smrg zink_screen_init_descriptor_funcs(screen, false); 20397ec681f3Smrg util_idalloc_mt_init_tc(&screen->buffer_ids); 20407ec681f3Smrg 20417ec681f3Smrg return screen; 20427ec681f3Smrg 20437ec681f3Smrgfail: 20447ec681f3Smrg ralloc_free(screen); 20457ec681f3Smrg return NULL; 20467ec681f3Smrg} 20477ec681f3Smrg 20487ec681f3Smrgstruct pipe_screen * 20497ec681f3Smrgzink_create_screen(struct sw_winsys *winsys) 20507ec681f3Smrg{ 20517ec681f3Smrg struct zink_screen *ret = zink_internal_create_screen(NULL); 20527ec681f3Smrg if (ret) { 20537ec681f3Smrg ret->winsys = winsys; 20547ec681f3Smrg ret->drm_fd = -1; 20557ec681f3Smrg } 20567ec681f3Smrg 20577ec681f3Smrg return &ret->base; 20587ec681f3Smrg} 20597ec681f3Smrg 20607ec681f3Smrgstruct pipe_screen * 20617ec681f3Smrgzink_drm_create_screen(int fd, const struct pipe_screen_config *config) 20627ec681f3Smrg{ 20637ec681f3Smrg struct zink_screen *ret = zink_internal_create_screen(config); 20647ec681f3Smrg 20657ec681f3Smrg if (ret) 20667ec681f3Smrg ret->drm_fd = os_dupfd_cloexec(fd); 20677ec681f3Smrg if (ret && !ret->info.have_KHR_external_memory_fd) { 20687ec681f3Smrg debug_printf("ZINK: KHR_external_memory_fd required!\n"); 20697ec681f3Smrg zink_destroy_screen(&ret->base); 20707ec681f3Smrg return NULL; 20717ec681f3Smrg } 20727ec681f3Smrg 20737ec681f3Smrg return &ret->base; 20747ec681f3Smrg} 20757ec681f3Smrg 20767ec681f3Smrgvoid zink_stub_function_not_loaded() 20777ec681f3Smrg{ 20787ec681f3Smrg /* this will be used by the zink_verify_*_extensions() functions on a 20797ec681f3Smrg * release build 20807ec681f3Smrg */ 20817ec681f3Smrg mesa_loge("ZINK: a Vulkan function was called without being loaded"); 20827ec681f3Smrg abort(); 20837ec681f3Smrg} 2084