Path: blob/21.2-virgl/src/gallium/drivers/zink/zink_screen.c
4570 views
/*1* Copyright 2018 Collabora Ltd.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* on the rights to use, copy, modify, merge, publish, distribute, sub7* license, and/or sell copies of the Software, and to permit persons to whom8* the Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,18* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR19* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE20* USE OR OTHER DEALINGS IN THE SOFTWARE.21*/2223#include "zink_screen.h"2425#include "zink_compiler.h"26#include "zink_context.h"27#include "zink_device_info.h"28#include "zink_descriptors.h"29#include "zink_fence.h"30#include "zink_format.h"31#include "zink_framebuffer.h"32#include "zink_instance.h"33#include "zink_program.h"34#include "zink_public.h"35#include "zink_resource.h"36#include "nir_to_spirv/nir_to_spirv.h" // for SPIRV_VERSION3738#include "os/os_process.h"39#include "util/u_debug.h"40#include "util/format/u_format.h"41#include "util/hash_table.h"42#include "util/u_math.h"43#include "util/u_memory.h"44#include "util/u_screen.h"45#include "util/u_string.h"46#include "util/u_transfer_helper.h"47#include "util/xmlconfig.h"4849#include "util/u_cpu_detect.h"5051#include "frontend/sw_winsys.h"5253#if defined(__APPLE__)54// Source of MVK_VERSION55#include "MoltenVK/vk_mvk_moltenvk.h"56#endif5758static const struct debug_named_value59zink_debug_options[] = {60{ "nir", ZINK_DEBUG_NIR, "Dump NIR during program compile" },61{ "spirv", ZINK_DEBUG_SPIRV, "Dump SPIR-V during program compile" },62{ "tgsi", ZINK_DEBUG_TGSI, "Dump TGSI during program compile" },63{ "validation", ZINK_DEBUG_VALIDATION, "Dump Validation layer output" },64DEBUG_NAMED_VALUE_END65};6667DEBUG_GET_ONCE_FLAGS_OPTION(zink_debug, "ZINK_DEBUG", zink_debug_options, 0)6869uint32_t70zink_debug;717273static const struct debug_named_value74zink_descriptor_options[] = {75{ "auto", ZINK_DESCRIPTOR_MODE_AUTO, "Automatically detect best mode" },76{ "lazy", ZINK_DESCRIPTOR_MODE_LAZY, "Don't cache, do least amount of updates" },77{ "notemplates", ZINK_DESCRIPTOR_MODE_NOTEMPLATES, "Cache, but disable templated updates" },78DEBUG_NAMED_VALUE_END79};8081DEBUG_GET_ONCE_FLAGS_OPTION(zink_descriptor_mode, "ZINK_DESCRIPTORS", zink_descriptor_options, ZINK_DESCRIPTOR_MODE_AUTO)8283static const char *84zink_get_vendor(struct pipe_screen *pscreen)85{86return "Collabora Ltd";87}8889static const char *90zink_get_device_vendor(struct pipe_screen *pscreen)91{92struct zink_screen *screen = zink_screen(pscreen);93static char buf[1000];94snprintf(buf, sizeof(buf), "Unknown (vendor-id: 0x%04x)", screen->info.props.vendorID);95return buf;96}9798static const char *99zink_get_name(struct pipe_screen *pscreen)100{101struct zink_screen *screen = zink_screen(pscreen);102static char buf[1000];103snprintf(buf, sizeof(buf), "zink (%s)", screen->info.props.deviceName);104return buf;105}106107static bool108equals_ivci(const void *a, const void *b)109{110return memcmp(a, b, sizeof(VkImageViewCreateInfo)) == 0;111}112113static bool114equals_bvci(const void *a, const void *b)115{116return memcmp(a, b, sizeof(VkBufferViewCreateInfo)) == 0;117}118119static uint32_t120hash_framebuffer_state(const void *key)121{122struct zink_framebuffer_state* s = (struct zink_framebuffer_state*)key;123return _mesa_hash_data(key, offsetof(struct zink_framebuffer_state, attachments) + sizeof(s->attachments[0]) * s->num_attachments);124}125126static bool127equals_framebuffer_state(const void *a, const void *b)128{129struct zink_framebuffer_state *s = (struct zink_framebuffer_state*)a;130return memcmp(a, b, offsetof(struct zink_framebuffer_state, attachments) + sizeof(s->attachments[0]) * s->num_attachments) == 0;131}132133static VkDeviceSize134get_video_mem(struct zink_screen *screen)135{136VkDeviceSize size = 0;137for (uint32_t i = 0; i < screen->info.mem_props.memoryHeapCount; ++i) {138if (screen->info.mem_props.memoryHeaps[i].flags &139VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)140size += screen->info.mem_props.memoryHeaps[i].size;141}142return size;143}144145static void146disk_cache_init(struct zink_screen *screen)147{148#ifdef ENABLE_SHADER_CACHE149static char buf[1000];150snprintf(buf, sizeof(buf), "zink_%x04x", screen->info.props.vendorID);151152screen->disk_cache = disk_cache_create(buf, screen->info.props.deviceName, 0);153if (screen->disk_cache) {154util_queue_init(&screen->cache_put_thread, "zcq", 8, 1, UTIL_QUEUE_INIT_RESIZE_IF_FULL, screen);155util_queue_init(&screen->cache_get_thread, "zcfq", 8, 4, UTIL_QUEUE_INIT_RESIZE_IF_FULL, screen);156}157#endif158}159160161static void162cache_put_job(void *data, void *gdata, int thread_index)163{164struct zink_program *pg = data;165struct zink_screen *screen = gdata;166size_t size = 0;167if (vkGetPipelineCacheData(screen->dev, pg->pipeline_cache, &size, NULL) != VK_SUCCESS)168return;169if (pg->pipeline_cache_size == size)170return;171void *pipeline_data = malloc(size);172if (!pipeline_data)173return;174if (vkGetPipelineCacheData(screen->dev, pg->pipeline_cache, &size, pipeline_data) == VK_SUCCESS) {175pg->pipeline_cache_size = size;176177cache_key key;178disk_cache_compute_key(screen->disk_cache, pg->sha1, sizeof(pg->sha1), key);179disk_cache_put_nocopy(screen->disk_cache, key, pipeline_data, size, NULL);180}181}182183void184zink_screen_update_pipeline_cache(struct zink_screen *screen, struct zink_program *pg)185{186util_queue_fence_init(&pg->cache_fence);187if (!screen->disk_cache)188return;189190util_queue_add_job(&screen->cache_put_thread, pg, NULL, cache_put_job, NULL, 0);191}192193static void194cache_get_job(void *data, void *gdata, int thread_index)195{196struct zink_program *pg = data;197struct zink_screen *screen = gdata;198199VkPipelineCacheCreateInfo pcci;200pcci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;201pcci.pNext = NULL;202pcci.flags = screen->info.have_EXT_pipeline_creation_cache_control ? VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT : 0;203pcci.initialDataSize = 0;204pcci.pInitialData = NULL;205206cache_key key;207disk_cache_compute_key(screen->disk_cache, pg->sha1, sizeof(pg->sha1), key);208pcci.pInitialData = disk_cache_get(screen->disk_cache, key, &pg->pipeline_cache_size);209pcci.initialDataSize = pg->pipeline_cache_size;210vkCreatePipelineCache(screen->dev, &pcci, NULL, &pg->pipeline_cache);211free((void*)pcci.pInitialData);212}213214void215zink_screen_get_pipeline_cache(struct zink_screen *screen, struct zink_program *pg)216{217util_queue_fence_init(&pg->cache_fence);218if (!screen->disk_cache)219return;220221util_queue_add_job(&screen->cache_get_thread, pg, &pg->cache_fence, cache_get_job, NULL, 0);222}223224static int225zink_get_compute_param(struct pipe_screen *pscreen, enum pipe_shader_ir ir_type,226enum pipe_compute_cap param, void *ret)227{228struct zink_screen *screen = zink_screen(pscreen);229#define RET(x) do { \230if (ret) \231memcpy(ret, x, sizeof(x)); \232return sizeof(x); \233} while (0)234235switch (param) {236case PIPE_COMPUTE_CAP_ADDRESS_BITS:237RET((uint32_t []){ 32 });238239case PIPE_COMPUTE_CAP_IR_TARGET:240if (ret)241strcpy(ret, "nir");242return 4;243244case PIPE_COMPUTE_CAP_GRID_DIMENSION:245RET((uint64_t []) { 3 });246247case PIPE_COMPUTE_CAP_MAX_GRID_SIZE:248RET(((uint64_t []) { screen->info.props.limits.maxComputeWorkGroupCount[0],249screen->info.props.limits.maxComputeWorkGroupCount[1],250screen->info.props.limits.maxComputeWorkGroupCount[2] }));251252case PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE:253/* MaxComputeWorkGroupSize[0..2] */254RET(((uint64_t []) {screen->info.props.limits.maxComputeWorkGroupSize[0],255screen->info.props.limits.maxComputeWorkGroupSize[1],256screen->info.props.limits.maxComputeWorkGroupSize[2]}));257258case PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK:259case PIPE_COMPUTE_CAP_MAX_VARIABLE_THREADS_PER_BLOCK:260RET((uint64_t []) { screen->info.props.limits.maxComputeWorkGroupInvocations });261262case PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE:263RET((uint64_t []) { screen->info.props.limits.maxComputeSharedMemorySize });264265case PIPE_COMPUTE_CAP_IMAGES_SUPPORTED:266RET((uint32_t []) { 1 });267268case PIPE_COMPUTE_CAP_SUBGROUP_SIZE:269RET((uint32_t []) { screen->info.props11.subgroupSize });270271case PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE:272case PIPE_COMPUTE_CAP_MAX_CLOCK_FREQUENCY:273case PIPE_COMPUTE_CAP_MAX_COMPUTE_UNITS:274case PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE:275case PIPE_COMPUTE_CAP_MAX_PRIVATE_SIZE:276case PIPE_COMPUTE_CAP_MAX_INPUT_SIZE:277// XXX: I think these are for Clover...278return 0;279280default:281unreachable("unknown compute param");282}283}284285static int286zink_get_param(struct pipe_screen *pscreen, enum pipe_cap param)287{288struct zink_screen *screen = zink_screen(pscreen);289290switch (param) {291case PIPE_CAP_ANISOTROPIC_FILTER:292return screen->info.feats.features.samplerAnisotropy;293case PIPE_CAP_EMULATE_NONFIXED_PRIMITIVE_RESTART:294return 1;295case PIPE_CAP_SUPPORTED_PRIM_MODES_WITH_RESTART: {296uint32_t modes = BITFIELD_BIT(PIPE_PRIM_LINE_STRIP) |297BITFIELD_BIT(PIPE_PRIM_TRIANGLE_STRIP) |298BITFIELD_BIT(PIPE_PRIM_LINE_STRIP_ADJACENCY) |299BITFIELD_BIT(PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY) |300BITFIELD_BIT(PIPE_PRIM_PATCHES);301if (screen->have_triangle_fans)302modes |= BITFIELD_BIT(PIPE_PRIM_TRIANGLE_FAN);303return modes;304}305case PIPE_CAP_SUPPORTED_PRIM_MODES: {306uint32_t modes = BITFIELD_MASK(PIPE_PRIM_MAX);307modes &= ~BITFIELD_BIT(PIPE_PRIM_QUADS);308modes &= ~BITFIELD_BIT(PIPE_PRIM_QUAD_STRIP);309modes &= ~BITFIELD_BIT(PIPE_PRIM_POLYGON);310modes &= ~BITFIELD_BIT(PIPE_PRIM_LINE_LOOP);311if (!screen->have_triangle_fans)312modes &= ~BITFIELD_BIT(PIPE_PRIM_TRIANGLE_FAN);313return modes;314}315316case PIPE_CAP_QUERY_MEMORY_INFO:317case PIPE_CAP_NPOT_TEXTURES:318case PIPE_CAP_TGSI_TEXCOORD:319case PIPE_CAP_DRAW_INDIRECT:320case PIPE_CAP_TEXTURE_QUERY_LOD:321case PIPE_CAP_GLSL_TESS_LEVELS_AS_INPUTS:322case PIPE_CAP_CLEAR_TEXTURE:323case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS:324case PIPE_CAP_FORCE_PERSAMPLE_INTERP:325case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT:326case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT:327case PIPE_CAP_TGSI_ARRAY_COMPONENTS:328case PIPE_CAP_QUERY_BUFFER_OBJECT:329case PIPE_CAP_CONDITIONAL_RENDER_INVERTED:330case PIPE_CAP_CLIP_HALFZ:331case PIPE_CAP_TGSI_TXQS:332case PIPE_CAP_TEXTURE_BARRIER:333case PIPE_CAP_DRAW_PARAMETERS:334case PIPE_CAP_QUERY_SO_OVERFLOW:335case PIPE_CAP_GL_SPIRV:336case PIPE_CAP_CLEAR_SCISSORED:337case PIPE_CAP_INVALIDATE_BUFFER:338case PIPE_CAP_PREFER_REAL_BUFFER_IN_CONSTBUF0:339case PIPE_CAP_PACKED_UNIFORMS:340case PIPE_CAP_TGSI_PACK_HALF_FLOAT:341return 1;342343case PIPE_CAP_TGSI_VOTE:344return screen->spirv_version >= SPIRV_VERSION(1, 3);345346case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:347return screen->info.have_EXT_provoking_vertex;348349case PIPE_CAP_TEXTURE_MIRROR_CLAMP_TO_EDGE:350return screen->info.have_KHR_sampler_mirror_clamp_to_edge;351352case PIPE_CAP_POLYGON_OFFSET_CLAMP:353return screen->info.feats.features.depthBiasClamp;354355case PIPE_CAP_QUERY_PIPELINE_STATISTICS_SINGLE:356return screen->info.feats.features.pipelineStatisticsQuery;357358case PIPE_CAP_ROBUST_BUFFER_ACCESS_BEHAVIOR:359return screen->info.feats.features.robustBufferAccess;360361case PIPE_CAP_MULTI_DRAW_INDIRECT:362return screen->info.feats.features.multiDrawIndirect;363364case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS:365return screen->info.have_KHR_draw_indirect_count;366367case PIPE_CAP_START_INSTANCE:368return (screen->info.have_vulkan12 && screen->info.feats11.shaderDrawParameters) ||369screen->info.have_KHR_shader_draw_parameters;370371case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:372return screen->info.have_EXT_vertex_attribute_divisor;373374case PIPE_CAP_MAX_VERTEX_STREAMS:375return screen->info.tf_props.maxTransformFeedbackStreams;376377case PIPE_CAP_INT64:378case PIPE_CAP_INT64_DIVMOD:379case PIPE_CAP_DOUBLES:380return 1;381382case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:383if (!screen->info.feats.features.dualSrcBlend)384return 0;385return screen->info.props.limits.maxFragmentDualSrcAttachments;386387case PIPE_CAP_MAX_RENDER_TARGETS:388return screen->info.props.limits.maxColorAttachments;389390case PIPE_CAP_OCCLUSION_QUERY:391return 1;392393case PIPE_CAP_PROGRAMMABLE_SAMPLE_LOCATIONS:394return screen->info.have_EXT_sample_locations && screen->info.have_EXT_extended_dynamic_state;395396case PIPE_CAP_QUERY_TIME_ELAPSED:397return screen->timestamp_valid_bits > 0;398399case PIPE_CAP_TEXTURE_MULTISAMPLE:400return 1;401402case PIPE_CAP_FRAGMENT_SHADER_INTERLOCK:403return screen->info.have_EXT_fragment_shader_interlock;404405case PIPE_CAP_TGSI_CLOCK:406return screen->info.have_KHR_shader_clock;407408case PIPE_CAP_POINT_SPRITE:409return 1;410411case PIPE_CAP_SAMPLE_SHADING:412return screen->info.feats.features.sampleRateShading;413414case PIPE_CAP_TEXTURE_SWIZZLE:415return 1;416417case PIPE_CAP_GL_CLAMP:418return 0;419420case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:421/* This is also broken on the other AMD drivers for old HW, but422* there's no obvious way to test for that.423*/424if (screen->info.driver_props.driverID == VK_DRIVER_ID_MESA_RADV ||425screen->info.driver_props.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY)426return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50;427return 0;428429case PIPE_CAP_MAX_TEXTURE_2D_SIZE:430return screen->info.props.limits.maxImageDimension2D;431case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:432return 1 + util_logbase2(screen->info.props.limits.maxImageDimension3D);433case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:434return 1 + util_logbase2(screen->info.props.limits.maxImageDimensionCube);435436case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD:437case PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES:438case PIPE_CAP_VERTEX_SHADER_SATURATE:439return 1;440441case PIPE_CAP_BLEND_EQUATION_SEPARATE:442case PIPE_CAP_INDEP_BLEND_ENABLE:443case PIPE_CAP_INDEP_BLEND_FUNC:444return screen->info.feats.features.independentBlend;445446case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:447return screen->info.have_EXT_transform_feedback ? screen->info.tf_props.maxTransformFeedbackBuffers : 0;448case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:449case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS:450return screen->info.have_EXT_transform_feedback;451452case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:453return screen->info.props.limits.maxImageArrayLayers;454455case PIPE_CAP_DEPTH_CLIP_DISABLE:456return screen->info.feats.features.depthClamp;457458case PIPE_CAP_SHADER_STENCIL_EXPORT:459return screen->info.have_EXT_shader_stencil_export;460461case PIPE_CAP_TGSI_INSTANCEID:462case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:463case PIPE_CAP_SEAMLESS_CUBE_MAP:464return 1;465466case PIPE_CAP_MIN_TEXEL_OFFSET:467return screen->info.props.limits.minTexelOffset;468case PIPE_CAP_MAX_TEXEL_OFFSET:469return screen->info.props.limits.maxTexelOffset;470471case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:472return 1;473474case PIPE_CAP_CONDITIONAL_RENDER:475return screen->info.have_EXT_conditional_rendering;476477case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY:478return 130;479case PIPE_CAP_GLSL_FEATURE_LEVEL:480return 460;481482case PIPE_CAP_COMPUTE:483return 1;484485case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:486return screen->info.props.limits.minUniformBufferOffsetAlignment;487488case PIPE_CAP_QUERY_TIMESTAMP:489return screen->info.have_EXT_calibrated_timestamps &&490screen->timestamp_valid_bits > 0;491492case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:493return screen->info.props.limits.minMemoryMapAlignment;494495case PIPE_CAP_CUBE_MAP_ARRAY:496return screen->info.feats.features.imageCubeArray;497498case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:499case PIPE_CAP_PRIMITIVE_RESTART:500return 1;501502case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:503return screen->info.props.limits.minTexelBufferOffsetAlignment;504505case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:506return 1;507508case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:509return screen->info.props.limits.maxTexelBufferElements;510511case PIPE_CAP_ENDIANNESS:512return PIPE_ENDIAN_NATIVE; /* unsure */513514case PIPE_CAP_MAX_VIEWPORTS:515return MIN2(screen->info.props.limits.maxViewports, PIPE_MAX_VIEWPORTS);516517case PIPE_CAP_IMAGE_LOAD_FORMATTED:518return screen->info.feats.features.shaderStorageImageReadWithoutFormat;519520case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:521return 1;522523case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:524return screen->info.props.limits.maxGeometryOutputVertices;525case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:526return screen->info.props.limits.maxGeometryTotalOutputComponents;527528case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:529return 4;530531case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET:532return screen->info.props.limits.minTexelGatherOffset;533case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET:534return screen->info.props.limits.maxTexelGatherOffset;535536case PIPE_CAP_SAMPLER_REDUCTION_MINMAX_ARB:537return screen->vk_version >= VK_MAKE_VERSION(1,2,0) || screen->info.have_EXT_sampler_filter_minmax;538539case PIPE_CAP_TGSI_FS_FINE_DERIVATIVE:540return 1;541542case PIPE_CAP_VENDOR_ID:543return screen->info.props.vendorID;544case PIPE_CAP_DEVICE_ID:545return screen->info.props.deviceID;546547case PIPE_CAP_ACCELERATED:548return 1;549case PIPE_CAP_VIDEO_MEMORY:550return get_video_mem(screen) >> 20;551case PIPE_CAP_UMA:552return screen->info.props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;553554case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE:555return screen->info.props.limits.maxVertexInputBindingStride;556557case PIPE_CAP_SAMPLER_VIEW_TARGET:558return 1;559560case PIPE_CAP_TGSI_VS_LAYER_VIEWPORT:561case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT:562return screen->info.have_EXT_shader_viewport_index_layer ||563(screen->spirv_version >= SPIRV_VERSION(1, 5) &&564screen->info.feats12.shaderOutputLayer &&565screen->info.feats12.shaderOutputViewportIndex);566567case PIPE_CAP_TEXTURE_FLOAT_LINEAR:568case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:569return 1;570571case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:572return screen->info.props.limits.minStorageBufferOffsetAlignment;573574case PIPE_CAP_PCI_GROUP:575case PIPE_CAP_PCI_BUS:576case PIPE_CAP_PCI_DEVICE:577case PIPE_CAP_PCI_FUNCTION:578return 0; /* TODO: figure these out */579580case PIPE_CAP_CULL_DISTANCE:581return screen->info.feats.features.shaderCullDistance;582583case PIPE_CAP_SPARSE_BUFFER_PAGE_SIZE:584/* this is the spec minimum */585return screen->info.feats.features.sparseBinding ? 64 * 1024 : 0;586587case PIPE_CAP_VIEWPORT_SUBPIXEL_BITS:588return screen->info.props.limits.viewportSubPixelBits;589590case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY:591return 0; /* not sure */592593case PIPE_CAP_MAX_GS_INVOCATIONS:594return screen->info.props.limits.maxGeometryShaderInvocations;595596case PIPE_CAP_MAX_COMBINED_SHADER_BUFFERS:597/* gallium handles this automatically */598return 0;599600case PIPE_CAP_MAX_SHADER_BUFFER_SIZE:601/* 1<<27 is required by VK spec */602assert(screen->info.props.limits.maxStorageBufferRange >= 1 << 27);603/* but Gallium can't handle values that are too big, so clamp to VK spec minimum */604return 1 << 27;605606case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:607case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:608return 1;609610case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:611case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:612return 0;613614case PIPE_CAP_NIR_COMPACT_ARRAYS:615return 1;616617case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL:618return 1;619620case PIPE_CAP_VIEWPORT_TRANSFORM_LOWERED:621return 1;622623case PIPE_CAP_FLATSHADE:624case PIPE_CAP_ALPHA_TEST:625case PIPE_CAP_CLIP_PLANES:626case PIPE_CAP_POINT_SIZE_FIXED:627case PIPE_CAP_TWO_SIDED_COLOR:628return 0;629630case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS:631return screen->info.props.limits.maxTessellationControlPerVertexOutputComponents / 4;632case PIPE_CAP_MAX_VARYINGS:633/* need to reserve up to 60 of our varying components and 16 slots for streamout */634return MIN2(screen->info.props.limits.maxVertexOutputComponents / 4 / 2, 16);635636case PIPE_CAP_DMABUF:637return screen->info.have_KHR_external_memory_fd;638639case PIPE_CAP_DEPTH_BOUNDS_TEST:640return screen->info.feats.features.depthBounds;641642case PIPE_CAP_POST_DEPTH_COVERAGE:643return screen->info.have_EXT_post_depth_coverage;644645case PIPE_CAP_STRING_MARKER:646return screen->instance_info.have_EXT_debug_utils;647648default:649return u_pipe_screen_get_param_defaults(pscreen, param);650}651}652653static float654zink_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)655{656struct zink_screen *screen = zink_screen(pscreen);657658switch (param) {659case PIPE_CAPF_MAX_LINE_WIDTH:660case PIPE_CAPF_MAX_LINE_WIDTH_AA:661if (!screen->info.feats.features.wideLines)662return 1.0f;663return screen->info.props.limits.lineWidthRange[1];664665case PIPE_CAPF_MAX_POINT_WIDTH:666case PIPE_CAPF_MAX_POINT_WIDTH_AA:667if (!screen->info.feats.features.largePoints)668return 1.0f;669return screen->info.props.limits.pointSizeRange[1];670671case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:672if (!screen->info.feats.features.samplerAnisotropy)673return 1.0f;674return screen->info.props.limits.maxSamplerAnisotropy;675676case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:677return screen->info.props.limits.maxSamplerLodBias;678679case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE:680case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE:681case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY:682return 0.0f; /* not implemented */683}684685/* should only get here on unhandled cases */686return 0.0f;687}688689static int690zink_get_shader_param(struct pipe_screen *pscreen,691enum pipe_shader_type shader,692enum pipe_shader_cap param)693{694struct zink_screen *screen = zink_screen(pscreen);695696switch (param) {697case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:698switch (shader) {699case PIPE_SHADER_FRAGMENT:700case PIPE_SHADER_VERTEX:701return INT_MAX;702case PIPE_SHADER_TESS_CTRL:703case PIPE_SHADER_TESS_EVAL:704if (screen->info.feats.features.tessellationShader &&705screen->info.have_KHR_maintenance2)706return INT_MAX;707break;708709case PIPE_SHADER_GEOMETRY:710if (screen->info.feats.features.geometryShader)711return INT_MAX;712break;713714case PIPE_SHADER_COMPUTE:715return INT_MAX;716default:717break;718}719return 0;720case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:721case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:722case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:723case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:724if (shader == PIPE_SHADER_VERTEX ||725shader == PIPE_SHADER_FRAGMENT)726return INT_MAX;727return 0;728729case PIPE_SHADER_CAP_MAX_INPUTS: {730uint32_t max = 0;731switch (shader) {732case PIPE_SHADER_VERTEX:733max = MIN2(screen->info.props.limits.maxVertexInputAttributes, PIPE_MAX_ATTRIBS);734break;735case PIPE_SHADER_TESS_CTRL:736max = screen->info.props.limits.maxTessellationControlPerVertexInputComponents / 4;737break;738case PIPE_SHADER_TESS_EVAL:739max = screen->info.props.limits.maxTessellationEvaluationInputComponents / 4;740break;741case PIPE_SHADER_GEOMETRY:742max = screen->info.props.limits.maxGeometryInputComponents;743break;744case PIPE_SHADER_FRAGMENT:745/* intel drivers report fewer components, but it's a value that's compatible746* with what we need for GL, so we can still force a conformant value here747*/748if (screen->info.driver_props.driverID == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR ||749screen->info.driver_props.driverID == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR)750return 32;751max = screen->info.props.limits.maxFragmentInputComponents / 4;752break;753default:754return 0; /* unsupported stage */755}756return MIN2(max, 64); // prevent overflowing struct shader_info::inputs_read757}758759case PIPE_SHADER_CAP_MAX_OUTPUTS: {760uint32_t max = 0;761switch (shader) {762case PIPE_SHADER_VERTEX:763max = screen->info.props.limits.maxVertexOutputComponents / 4;764break;765case PIPE_SHADER_TESS_CTRL:766max = screen->info.props.limits.maxTessellationControlPerVertexOutputComponents / 4;767break;768case PIPE_SHADER_TESS_EVAL:769max = screen->info.props.limits.maxTessellationEvaluationOutputComponents / 4;770break;771case PIPE_SHADER_GEOMETRY:772max = screen->info.props.limits.maxGeometryOutputComponents / 4;773break;774case PIPE_SHADER_FRAGMENT:775max = screen->info.props.limits.maxColorAttachments;776break;777default:778return 0; /* unsupported stage */779}780return MIN2(max, 64); // prevent overflowing struct shader_info::outputs_read/written781}782783case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:784/* At least 16384 is guaranteed by VK spec */785assert(screen->info.props.limits.maxUniformBufferRange >= 16384);786/* but Gallium can't handle values that are too big */787return MIN2(screen->info.props.limits.maxUniformBufferRange, 1 << 31);788789case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:790return MIN2(screen->info.props.limits.maxPerStageDescriptorUniformBuffers,791PIPE_MAX_CONSTANT_BUFFERS);792793case PIPE_SHADER_CAP_MAX_TEMPS:794return INT_MAX;795796case PIPE_SHADER_CAP_INTEGERS:797return 1;798799case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:800return 1;801802case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:803case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:804case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:805case PIPE_SHADER_CAP_SUBROUTINES:806case PIPE_SHADER_CAP_INT64_ATOMICS:807case PIPE_SHADER_CAP_FP16_CONST_BUFFERS:808case PIPE_SHADER_CAP_GLSL_16BIT_CONSTS:809return 0; /* not implemented */810811case PIPE_SHADER_CAP_FP16:812case PIPE_SHADER_CAP_FP16_DERIVATIVES:813return screen->info.feats12.shaderFloat16 ||814(screen->info.have_KHR_shader_float16_int8 &&815screen->info.shader_float16_int8_feats.shaderFloat16);816817case PIPE_SHADER_CAP_INT16:818return screen->info.feats.features.shaderInt16;819820case PIPE_SHADER_CAP_PREFERRED_IR:821return PIPE_SHADER_IR_NIR;822823case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:824return 0; /* not implemented */825826case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:827case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:828return MIN2(MIN2(screen->info.props.limits.maxPerStageDescriptorSamplers,829screen->info.props.limits.maxPerStageDescriptorSampledImages),830PIPE_MAX_SAMPLERS);831832case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:833case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED:834case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:835return 0; /* not implemented */836837case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:838return 0; /* no idea */839840case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT:841return 0;842843case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:844switch (shader) {845case PIPE_SHADER_VERTEX:846case PIPE_SHADER_TESS_CTRL:847case PIPE_SHADER_TESS_EVAL:848case PIPE_SHADER_GEOMETRY:849if (!screen->info.feats.features.vertexPipelineStoresAndAtomics)850return 0;851break;852853case PIPE_SHADER_FRAGMENT:854if (!screen->info.feats.features.fragmentStoresAndAtomics)855return 0;856break;857858default:859break;860}861862/* TODO: this limitation is dumb, and will need some fixes in mesa */863return MIN2(screen->info.props.limits.maxPerStageDescriptorStorageBuffers, PIPE_MAX_SHADER_BUFFERS);864865case PIPE_SHADER_CAP_SUPPORTED_IRS:866return (1 << PIPE_SHADER_IR_NIR) | (1 << PIPE_SHADER_IR_TGSI);867868case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:869if (screen->info.feats.features.shaderStorageImageExtendedFormats &&870screen->info.feats.features.shaderStorageImageWriteWithoutFormat)871return MIN2(screen->info.props.limits.maxPerStageDescriptorStorageImages,872PIPE_MAX_SHADER_IMAGES);873return 0;874875case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD:876case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS:877return 0; /* unsure */878879case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED:880case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS:881case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS:882case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:883return 0; /* not implemented */884}885886/* should only get here on unhandled cases */887return 0;888}889890static VkSampleCountFlagBits891vk_sample_count_flags(uint32_t sample_count)892{893switch (sample_count) {894case 1: return VK_SAMPLE_COUNT_1_BIT;895case 2: return VK_SAMPLE_COUNT_2_BIT;896case 4: return VK_SAMPLE_COUNT_4_BIT;897case 8: return VK_SAMPLE_COUNT_8_BIT;898case 16: return VK_SAMPLE_COUNT_16_BIT;899case 32: return VK_SAMPLE_COUNT_32_BIT;900case 64: return VK_SAMPLE_COUNT_64_BIT;901default:902return 0;903}904}905906static bool907zink_is_format_supported(struct pipe_screen *pscreen,908enum pipe_format format,909enum pipe_texture_target target,910unsigned sample_count,911unsigned storage_sample_count,912unsigned bind)913{914struct zink_screen *screen = zink_screen(pscreen);915916if (format == PIPE_FORMAT_NONE)917return screen->info.props.limits.framebufferNoAttachmentsSampleCounts &918vk_sample_count_flags(sample_count);919920if (bind & PIPE_BIND_INDEX_BUFFER) {921if (format == PIPE_FORMAT_R8_UINT &&922!screen->info.have_EXT_index_type_uint8)923return false;924if (format != PIPE_FORMAT_R8_UINT &&925format != PIPE_FORMAT_R16_UINT &&926format != PIPE_FORMAT_R32_UINT)927return false;928}929930VkFormat vkformat = zink_get_format(screen, format);931if (vkformat == VK_FORMAT_UNDEFINED)932return false;933934if (sample_count >= 1) {935VkSampleCountFlagBits sample_mask = vk_sample_count_flags(sample_count);936if (!sample_mask)937return false;938const struct util_format_description *desc = util_format_description(format);939if (util_format_is_depth_or_stencil(format)) {940if (util_format_has_depth(desc)) {941if (bind & PIPE_BIND_DEPTH_STENCIL &&942(screen->info.props.limits.framebufferDepthSampleCounts & sample_mask) != sample_mask)943return false;944if (bind & PIPE_BIND_SAMPLER_VIEW &&945(screen->info.props.limits.sampledImageDepthSampleCounts & sample_mask) != sample_mask)946return false;947}948if (util_format_has_stencil(desc)) {949if (bind & PIPE_BIND_DEPTH_STENCIL &&950(screen->info.props.limits.framebufferStencilSampleCounts & sample_mask) != sample_mask)951return false;952if (bind & PIPE_BIND_SAMPLER_VIEW &&953(screen->info.props.limits.sampledImageStencilSampleCounts & sample_mask) != sample_mask)954return false;955}956} else if (util_format_is_pure_integer(format)) {957if (bind & PIPE_BIND_RENDER_TARGET &&958!(screen->info.props.limits.framebufferColorSampleCounts & sample_mask))959return false;960if (bind & PIPE_BIND_SAMPLER_VIEW &&961!(screen->info.props.limits.sampledImageIntegerSampleCounts & sample_mask))962return false;963} else {964if (bind & PIPE_BIND_RENDER_TARGET &&965!(screen->info.props.limits.framebufferColorSampleCounts & sample_mask))966return false;967if (bind & PIPE_BIND_SAMPLER_VIEW &&968!(screen->info.props.limits.sampledImageColorSampleCounts & sample_mask))969return false;970}971if (bind & PIPE_BIND_SHADER_IMAGE) {972if (!(screen->info.props.limits.storageImageSampleCounts & sample_mask))973return false;974}975}976977VkFormatProperties props = screen->format_props[format];978979if (target == PIPE_BUFFER) {980if (bind & PIPE_BIND_VERTEX_BUFFER &&981!(props.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))982return false;983984if (bind & PIPE_BIND_SAMPLER_VIEW &&985!(props.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))986return false;987988if (bind & PIPE_BIND_SHADER_IMAGE &&989!(props.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))990return false;991} else {992/* all other targets are texture-targets */993if (bind & PIPE_BIND_RENDER_TARGET &&994!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))995return false;996997if (bind & PIPE_BIND_BLENDABLE &&998!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT))999return false;10001001if (bind & PIPE_BIND_SAMPLER_VIEW &&1002!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))1003return false;10041005if (bind & PIPE_BIND_SAMPLER_REDUCTION_MINMAX &&1006!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT))1007return false;10081009if ((bind & PIPE_BIND_SAMPLER_VIEW) || (bind & PIPE_BIND_RENDER_TARGET)) {1010/* if this is a 3-component texture, force gallium to give us 4 components by rejecting this one */1011const struct util_format_description *desc = util_format_description(format);1012if (desc->nr_channels == 3 &&1013(desc->block.bits == 24 || desc->block.bits == 48 || desc->block.bits == 96))1014return false;1015}10161017if (bind & PIPE_BIND_DEPTH_STENCIL &&1018!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))1019return false;10201021if (bind & PIPE_BIND_SHADER_IMAGE &&1022!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))1023return false;1024}10251026if (util_format_is_compressed(format)) {1027const struct util_format_description *desc = util_format_description(format);1028if (desc->layout == UTIL_FORMAT_LAYOUT_BPTC &&1029!screen->info.feats.features.textureCompressionBC)1030return false;1031}10321033return true;1034}10351036static void1037resource_cache_entry_destroy(struct zink_screen *screen, struct hash_entry *he)1038{1039struct util_dynarray *array = (void*)he->data;1040util_dynarray_foreach(array, struct mem_cache_entry, mc) {1041vkFreeMemory(screen->dev, mc->mem, NULL);1042}1043util_dynarray_fini(array);1044}10451046static void1047zink_destroy_screen(struct pipe_screen *pscreen)1048{1049struct zink_screen *screen = zink_screen(pscreen);10501051if (VK_NULL_HANDLE != screen->debugUtilsCallbackHandle) {1052screen->vk.DestroyDebugUtilsMessengerEXT(screen->instance, screen->debugUtilsCallbackHandle, NULL);1053}10541055hash_table_foreach(&screen->surface_cache, entry) {1056struct pipe_surface *psurf = (struct pipe_surface*)entry->data;1057/* context is already destroyed, so this has to be destroyed directly */1058zink_destroy_surface(screen, psurf);1059}10601061hash_table_foreach(&screen->bufferview_cache, entry) {1062struct zink_buffer_view *bv = (struct zink_buffer_view*)entry->data;1063zink_buffer_view_reference(screen, &bv, NULL);1064}10651066hash_table_foreach(&screen->framebuffer_cache, entry) {1067struct zink_framebuffer* fb = (struct zink_framebuffer*)entry->data;1068zink_destroy_framebuffer(screen, fb);1069}10701071simple_mtx_destroy(&screen->surface_mtx);1072simple_mtx_destroy(&screen->bufferview_mtx);1073simple_mtx_destroy(&screen->framebuffer_mtx);10741075u_transfer_helper_destroy(pscreen->transfer_helper);1076#ifdef ENABLE_SHADER_CACHE1077if (screen->disk_cache) {1078util_queue_finish(&screen->cache_put_thread);1079util_queue_finish(&screen->cache_get_thread);1080disk_cache_wait_for_idle(screen->disk_cache);1081util_queue_destroy(&screen->cache_put_thread);1082util_queue_destroy(&screen->cache_get_thread);1083}1084#endif1085disk_cache_destroy(screen->disk_cache);1086simple_mtx_lock(&screen->mem_cache_mtx);1087hash_table_foreach(screen->resource_mem_cache, he)1088resource_cache_entry_destroy(screen, he);1089_mesa_hash_table_destroy(screen->resource_mem_cache, NULL);1090simple_mtx_unlock(&screen->mem_cache_mtx);1091simple_mtx_destroy(&screen->mem_cache_mtx);10921093util_live_shader_cache_deinit(&screen->shaders);10941095if (screen->sem)1096vkDestroySemaphore(screen->dev, screen->sem, NULL);1097if (screen->prev_sem)1098vkDestroySemaphore(screen->dev, screen->prev_sem, NULL);10991100if (screen->threaded)1101util_queue_destroy(&screen->flush_queue);11021103vkDestroyDevice(screen->dev, NULL);1104vkDestroyInstance(screen->instance, NULL);1105util_idalloc_mt_fini(&screen->buffer_ids);11061107slab_destroy_parent(&screen->transfer_pool);1108ralloc_free(screen);1109}11101111static void1112choose_pdev(struct zink_screen *screen)1113{1114uint32_t i, pdev_count;1115VkPhysicalDevice *pdevs;1116VkResult result = vkEnumeratePhysicalDevices(screen->instance, &pdev_count, NULL);1117if (result != VK_SUCCESS)1118return;11191120assert(pdev_count > 0);11211122pdevs = malloc(sizeof(*pdevs) * pdev_count);1123result = vkEnumeratePhysicalDevices(screen->instance, &pdev_count, pdevs);1124assert(result == VK_SUCCESS);1125assert(pdev_count > 0);11261127VkPhysicalDeviceProperties *props = &screen->info.props;1128for (i = 0; i < pdev_count; ++i) {1129vkGetPhysicalDeviceProperties(pdevs[i], props);11301131#ifdef ZINK_WITH_SWRAST_VK1132char *use_lavapipe = getenv("ZINK_USE_LAVAPIPE");1133if (use_lavapipe) {1134if (props->deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) {1135screen->pdev = pdevs[i];1136screen->info.device_version = props->apiVersion;1137break;1138}1139continue;1140}1141#endif1142if (props->deviceType != VK_PHYSICAL_DEVICE_TYPE_CPU) {1143screen->pdev = pdevs[i];1144screen->info.device_version = props->apiVersion;1145break;1146}1147}1148free(pdevs);11491150/* runtime version is the lesser of the instance version and device version */1151screen->vk_version = MIN2(screen->info.device_version, screen->instance_info.loader_version);11521153/* calculate SPIR-V version based on VK version */1154if (screen->vk_version >= VK_MAKE_VERSION(1, 2, 0))1155screen->spirv_version = SPIRV_VERSION(1, 5);1156else if (screen->vk_version >= VK_MAKE_VERSION(1, 1, 0))1157screen->spirv_version = SPIRV_VERSION(1, 3);1158else1159screen->spirv_version = SPIRV_VERSION(1, 0);1160}11611162static void1163update_queue_props(struct zink_screen *screen)1164{1165uint32_t num_queues;1166vkGetPhysicalDeviceQueueFamilyProperties(screen->pdev, &num_queues, NULL);1167assert(num_queues > 0);11681169VkQueueFamilyProperties *props = malloc(sizeof(*props) * num_queues);1170vkGetPhysicalDeviceQueueFamilyProperties(screen->pdev, &num_queues, props);11711172for (uint32_t i = 0; i < num_queues; i++) {1173if (props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {1174screen->gfx_queue = i;1175screen->max_queues = props[i].queueCount;1176screen->timestamp_valid_bits = props[i].timestampValidBits;1177break;1178}1179}1180free(props);1181}11821183static void1184init_queue(struct zink_screen *screen)1185{1186vkGetDeviceQueue(screen->dev, screen->gfx_queue, 0, &screen->queue);1187if (screen->threaded && screen->max_queues > 1)1188vkGetDeviceQueue(screen->dev, screen->gfx_queue, 1, &screen->thread_queue);1189else1190screen->thread_queue = screen->queue;1191}11921193static void1194zink_flush_frontbuffer(struct pipe_screen *pscreen,1195struct pipe_context *pcontext,1196struct pipe_resource *pres,1197unsigned level, unsigned layer,1198void *winsys_drawable_handle,1199struct pipe_box *sub_box)1200{1201struct zink_screen *screen = zink_screen(pscreen);1202struct sw_winsys *winsys = screen->winsys;1203struct zink_resource *res = zink_resource(pres);12041205if (!winsys)1206return;1207void *map = winsys->displaytarget_map(winsys, res->dt, 0);12081209if (map) {1210struct pipe_transfer *transfer = NULL;1211void *res_map = pipe_texture_map(pcontext, pres, level, layer, PIPE_MAP_READ, 0, 0,1212u_minify(pres->width0, level),1213u_minify(pres->height0, level),1214&transfer);1215if (res_map) {1216util_copy_rect((ubyte*)map, pres->format, res->dt_stride, 0, 0,1217transfer->box.width, transfer->box.height,1218(const ubyte*)res_map, transfer->stride, 0, 0);1219pipe_texture_unmap(pcontext, transfer);1220}1221winsys->displaytarget_unmap(winsys, res->dt);1222}12231224winsys->displaytarget_display(winsys, res->dt, winsys_drawable_handle, sub_box);1225}12261227bool1228zink_is_depth_format_supported(struct zink_screen *screen, VkFormat format)1229{1230VkFormatProperties props;1231vkGetPhysicalDeviceFormatProperties(screen->pdev, format, &props);1232return (props.linearTilingFeatures | props.optimalTilingFeatures) &1233VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;1234}12351236static enum pipe_format1237emulate_x8(enum pipe_format format)1238{1239/* convert missing X8 variants to A8 */1240switch (format) {1241case PIPE_FORMAT_B8G8R8X8_UNORM:1242return PIPE_FORMAT_B8G8R8A8_UNORM;12431244case PIPE_FORMAT_B8G8R8X8_SRGB:1245return PIPE_FORMAT_B8G8R8A8_SRGB;12461247case PIPE_FORMAT_R8G8B8X8_SINT:1248return PIPE_FORMAT_R8G8B8A8_SINT;1249case PIPE_FORMAT_R8G8B8X8_SNORM:1250return PIPE_FORMAT_R8G8B8A8_SNORM;1251case PIPE_FORMAT_R8G8B8X8_UNORM:1252return PIPE_FORMAT_R8G8B8A8_UNORM;12531254default:1255return format;1256}1257}12581259VkFormat1260zink_get_format(struct zink_screen *screen, enum pipe_format format)1261{1262VkFormat ret = zink_pipe_format_to_vk_format(emulate_x8(format));12631264if (format == PIPE_FORMAT_X32_S8X24_UINT)1265return VK_FORMAT_D32_SFLOAT_S8_UINT;12661267if (format == PIPE_FORMAT_X24S8_UINT)1268/* valid when using aspects to extract stencil,1269* fails format test because it's emulated */1270ret = VK_FORMAT_D24_UNORM_S8_UINT;12711272if (ret == VK_FORMAT_X8_D24_UNORM_PACK32 &&1273!screen->have_X8_D24_UNORM_PACK32) {1274assert(zink_is_depth_format_supported(screen, VK_FORMAT_D32_SFLOAT));1275return VK_FORMAT_D32_SFLOAT;1276}12771278if (ret == VK_FORMAT_D24_UNORM_S8_UINT &&1279!screen->have_D24_UNORM_S8_UINT) {1280assert(zink_is_depth_format_supported(screen,1281VK_FORMAT_D32_SFLOAT_S8_UINT));1282return VK_FORMAT_D32_SFLOAT_S8_UINT;1283}12841285if ((ret == VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT &&1286!screen->info.format_4444_feats.formatA4B4G4R4) ||1287(ret == VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT &&1288!screen->info.format_4444_feats.formatA4R4G4B4))1289return VK_FORMAT_UNDEFINED;12901291return ret;1292}12931294void1295zink_screen_init_descriptor_funcs(struct zink_screen *screen, bool fallback)1296{1297if (screen->info.have_KHR_descriptor_update_template &&1298!fallback &&1299screen->descriptor_mode == ZINK_DESCRIPTOR_MODE_LAZY) {1300#define LAZY(FUNC) screen->FUNC = zink_##FUNC##_lazy1301LAZY(descriptor_program_init);1302LAZY(descriptor_program_deinit);1303LAZY(context_invalidate_descriptor_state);1304LAZY(batch_descriptor_init);1305LAZY(batch_descriptor_reset);1306LAZY(batch_descriptor_deinit);1307LAZY(descriptors_init);1308LAZY(descriptors_deinit);1309LAZY(descriptors_update);1310#undef LAZY1311} else {1312#define DEFAULT(FUNC) screen->FUNC = zink_##FUNC1313DEFAULT(descriptor_program_init);1314DEFAULT(descriptor_program_deinit);1315DEFAULT(context_invalidate_descriptor_state);1316DEFAULT(batch_descriptor_init);1317DEFAULT(batch_descriptor_reset);1318DEFAULT(batch_descriptor_deinit);1319DEFAULT(descriptors_init);1320DEFAULT(descriptors_deinit);1321DEFAULT(descriptors_update);1322#undef DEFAULT1323}1324}13251326static bool1327check_have_device_time(struct zink_screen *screen)1328{1329uint32_t num_domains = 0;1330screen->vk.GetPhysicalDeviceCalibrateableTimeDomainsEXT(screen->pdev, &num_domains, NULL);1331assert(num_domains > 0);13321333VkTimeDomainEXT *domains = malloc(sizeof(VkTimeDomainEXT) * num_domains);1334screen->vk.GetPhysicalDeviceCalibrateableTimeDomainsEXT(screen->pdev, &num_domains, domains);13351336/* VK_TIME_DOMAIN_DEVICE_EXT is used for the ctx->get_timestamp hook and is the only one we really need */1337for (unsigned i = 0; i < num_domains; i++) {1338if (domains[i] == VK_TIME_DOMAIN_DEVICE_EXT) {1339return true;1340}1341}13421343free(domains);1344return false;1345}13461347static VKAPI_ATTR VkBool32 VKAPI_CALL1348zink_debug_util_callback(1349VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,1350VkDebugUtilsMessageTypeFlagsEXT messageType,1351const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,1352void *pUserData)1353{1354const char *severity = "MSG";13551356// Pick message prefix and color to use.1357// Only MacOS and Linux have been tested for color support1358if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {1359severity = "ERR";1360} else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {1361severity = "WRN";1362} else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {1363severity = "NFO";1364}13651366fprintf(stderr, "zink DEBUG: %s: '%s'\n", severity, pCallbackData->pMessage);1367return VK_FALSE;1368}13691370static bool1371create_debug(struct zink_screen *screen)1372{1373VkDebugUtilsMessengerCreateInfoEXT vkDebugUtilsMessengerCreateInfoEXT = {1374VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,1375NULL,13760, // flags1377VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |1378VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |1379VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |1380VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,1381VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |1382VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |1383VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,1384zink_debug_util_callback,1385NULL1386};13871388VkDebugUtilsMessengerEXT vkDebugUtilsCallbackEXT = VK_NULL_HANDLE;13891390screen->vk.CreateDebugUtilsMessengerEXT(1391screen->instance,1392&vkDebugUtilsMessengerCreateInfoEXT,1393NULL,1394&vkDebugUtilsCallbackEXT1395);13961397screen->debugUtilsCallbackHandle = vkDebugUtilsCallbackEXT;13981399return true;1400}14011402static bool1403zink_internal_setup_moltenvk(struct zink_screen *screen)1404{1405#if defined(MVK_VERSION)1406if (!screen->instance_info.have_MVK_moltenvk)1407return true;14081409GET_PROC_ADDR_INSTANCE_LOCAL(screen->instance, GetMoltenVKConfigurationMVK);1410GET_PROC_ADDR_INSTANCE_LOCAL(screen->instance, SetMoltenVKConfigurationMVK);1411GET_PROC_ADDR_INSTANCE_LOCAL(screen->instance, GetVersionStringsMVK);14121413if (vk_GetVersionStringsMVK) {1414char molten_version[64] = {0};1415char vulkan_version[64] = {0};14161417vk_GetVersionStringsMVK(molten_version, sizeof(molten_version) - 1, vulkan_version, sizeof(vulkan_version) - 1);14181419printf("zink: MoltenVK %s Vulkan %s \n", molten_version, vulkan_version);1420}14211422if (vk_GetMoltenVKConfigurationMVK && vk_SetMoltenVKConfigurationMVK) {1423MVKConfiguration molten_config = {0};1424size_t molten_config_size = sizeof(molten_config);14251426VkResult res = vk_GetMoltenVKConfigurationMVK(screen->instance, &molten_config, &molten_config_size);1427if (res == VK_SUCCESS || res == VK_INCOMPLETE) {1428// Needed to allow MoltenVK to accept VkImageView swizzles.1429// Encountered when using VK_FORMAT_R8G8_UNORM1430molten_config.fullImageViewSwizzle = VK_TRUE;1431vk_SetMoltenVKConfigurationMVK(screen->instance, &molten_config, &molten_config_size);1432}1433}1434#endif // MVK_VERSION14351436return true;1437}14381439static void1440check_device_needs_mesa_wsi(struct zink_screen *screen)1441{1442if (1443/* Raspberry Pi 4 V3DV driver */1444(screen->info.props.vendorID == 0x14E4 &&1445screen->info.props.deviceID == 42) ||1446/* RADV */1447screen->info.driver_props.driverID == VK_DRIVER_ID_MESA_RADV_KHR1448) {1449screen->needs_mesa_wsi = true;1450} else if (screen->info.driver_props.driverID == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR)1451screen->needs_mesa_flush_wsi = true;14521453}14541455static void1456populate_format_props(struct zink_screen *screen)1457{1458for (unsigned i = 0; i < PIPE_FORMAT_COUNT; i++) {1459VkFormat format = zink_get_format(screen, i);1460if (!format)1461continue;1462if (screen->vk.GetPhysicalDeviceFormatProperties2) {1463VkFormatProperties2 props = {0};1464props.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;14651466VkDrmFormatModifierPropertiesListEXT mod_props;1467VkDrmFormatModifierPropertiesEXT mods[128];1468if (screen->info.have_EXT_image_drm_format_modifier) {1469mod_props.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT;1470mod_props.pNext = NULL;1471mod_props.drmFormatModifierCount = ARRAY_SIZE(mods);1472mod_props.pDrmFormatModifierProperties = mods;1473props.pNext = &mod_props;1474}1475screen->vk.GetPhysicalDeviceFormatProperties2(screen->pdev, format, &props);1476screen->format_props[i] = props.formatProperties;1477if (screen->info.have_EXT_image_drm_format_modifier && mod_props.drmFormatModifierCount) {1478screen->modifier_props[i].drmFormatModifierCount = mod_props.drmFormatModifierCount;1479screen->modifier_props[i].pDrmFormatModifierProperties = ralloc_array(screen, VkDrmFormatModifierPropertiesEXT, mod_props.drmFormatModifierCount);1480if (mod_props.pDrmFormatModifierProperties) {1481for (unsigned j = 0; j < mod_props.drmFormatModifierCount; j++)1482screen->modifier_props[i].pDrmFormatModifierProperties[j] = mod_props.pDrmFormatModifierProperties[j];1483}1484}1485} else1486vkGetPhysicalDeviceFormatProperties(screen->pdev, format, &screen->format_props[i]);1487}1488}14891490bool1491zink_screen_init_semaphore(struct zink_screen *screen)1492{1493VkSemaphoreCreateInfo sci = {0};1494VkSemaphoreTypeCreateInfo tci = {0};1495VkSemaphore sem;1496sci.pNext = &tci;1497sci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;1498tci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO;1499tci.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;15001501if (vkCreateSemaphore(screen->dev, &sci, NULL, &sem) == VK_SUCCESS) {1502/* semaphore signal values can never decrease,1503* so we need a new semaphore anytime we overflow1504*/1505if (screen->prev_sem)1506vkDestroySemaphore(screen->dev, screen->prev_sem, NULL);1507screen->prev_sem = screen->sem;1508screen->sem = sem;1509return true;1510}1511screen->info.have_KHR_timeline_semaphore = false;1512return false;1513}15141515bool1516zink_screen_timeline_wait(struct zink_screen *screen, uint32_t batch_id, uint64_t timeout)1517{1518VkSemaphoreWaitInfo wi = {0};15191520if (zink_screen_check_last_finished(screen, batch_id))1521return true;15221523wi.sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO;1524wi.semaphoreCount = 1;1525/* handle batch_id overflow */1526wi.pSemaphores = batch_id > screen->curr_batch ? &screen->prev_sem : &screen->sem;1527uint64_t batch_id64 = batch_id;1528wi.pValues = &batch_id64;1529bool success = false;1530if (screen->device_lost)1531return true;1532VkResult ret = screen->vk.WaitSemaphores(screen->dev, &wi, timeout);1533success = zink_screen_handle_vkresult(screen, ret);15341535if (success)1536zink_screen_update_last_finished(screen, batch_id);15371538return success;1539}15401541struct noop_submit_info {1542struct zink_screen *screen;1543VkFence fence;1544};15451546static void1547noop_submit(void *data, void *gdata, int thread_index)1548{1549struct noop_submit_info *n = data;1550VkSubmitInfo si = {0};1551si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;1552if (vkQueueSubmit(n->screen->threaded ? n->screen->thread_queue : n->screen->queue,15531, &si, n->fence) != VK_SUCCESS) {1554debug_printf("ZINK: vkQueueSubmit() failed\n");1555n->screen->device_lost = true;1556}1557}15581559bool1560zink_screen_batch_id_wait(struct zink_screen *screen, uint32_t batch_id, uint64_t timeout)1561{1562if (zink_screen_check_last_finished(screen, batch_id))1563return true;15641565if (screen->info.have_KHR_timeline_semaphore)1566return zink_screen_timeline_wait(screen, batch_id, timeout);15671568if (!timeout)1569return false;15701571uint32_t new_id = 0;1572while (!new_id)1573new_id = p_atomic_inc_return(&screen->curr_batch);1574VkResult ret;1575struct noop_submit_info n;1576uint64_t abs_timeout = os_time_get_absolute_timeout(timeout);1577uint64_t remaining = PIPE_TIMEOUT_INFINITE;1578VkFenceCreateInfo fci = {0};1579struct util_queue_fence fence;1580util_queue_fence_init(&fence);1581fci.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;15821583if (vkCreateFence(screen->dev, &fci, NULL, &n.fence) != VK_SUCCESS)1584return false;15851586n.screen = screen;1587if (screen->threaded) {1588/* must use thread dispatch for sanity */1589util_queue_add_job(&screen->flush_queue, &n, &fence, noop_submit, NULL, 0);1590util_queue_fence_wait(&fence);1591} else {1592noop_submit(&n, NULL, 0);1593}1594if (timeout != PIPE_TIMEOUT_INFINITE) {1595int64_t time_ns = os_time_get_nano();1596remaining = abs_timeout > time_ns ? abs_timeout - time_ns : 0;1597}15981599if (remaining)1600ret = vkWaitForFences(screen->dev, 1, &n.fence, VK_TRUE, remaining);1601else1602ret = vkGetFenceStatus(screen->dev, n.fence);1603vkDestroyFence(screen->dev, n.fence, NULL);1604bool success = zink_screen_handle_vkresult(screen, ret);16051606if (success)1607zink_screen_update_last_finished(screen, new_id);16081609return success;1610}16111612static uint32_t1613zink_get_loader_version(void)1614{16151616uint32_t loader_version = VK_API_VERSION_1_0;16171618// Get the Loader version1619GET_PROC_ADDR_INSTANCE_LOCAL(NULL, EnumerateInstanceVersion);1620if (vk_EnumerateInstanceVersion) {1621uint32_t loader_version_temp = VK_API_VERSION_1_0;1622if (VK_SUCCESS == (*vk_EnumerateInstanceVersion)(&loader_version_temp)) {1623loader_version = loader_version_temp;1624}1625}16261627return loader_version;1628}16291630static void1631zink_query_memory_info(struct pipe_screen *pscreen, struct pipe_memory_info *info)1632{1633struct zink_screen *screen = zink_screen(pscreen);1634memset(info, 0, sizeof(struct pipe_memory_info));1635if (screen->info.have_EXT_memory_budget && screen->vk.GetPhysicalDeviceMemoryProperties2) {1636VkPhysicalDeviceMemoryProperties2 mem = {0};1637mem.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;16381639VkPhysicalDeviceMemoryBudgetPropertiesEXT budget = {0};1640budget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT;1641mem.pNext = &budget;1642screen->vk.GetPhysicalDeviceMemoryProperties2(screen->pdev, &mem);16431644for (unsigned i = 0; i < mem.memoryProperties.memoryHeapCount; i++) {1645if (mem.memoryProperties.memoryHeaps[i].flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {1646/* VRAM */1647info->total_device_memory += mem.memoryProperties.memoryHeaps[i].size / 1024;1648info->avail_device_memory += (budget.heapBudget[i] - budget.heapUsage[i]) / 1024;1649} else {1650/* GART */1651info->total_staging_memory += mem.memoryProperties.memoryHeaps[i].size / 1024;1652info->avail_staging_memory += (budget.heapBudget[i] - budget.heapUsage[i]) / 1024;1653}1654}1655/* evictions not yet supported in vulkan */1656} else {1657for (unsigned i = 0; i < screen->info.mem_props.memoryHeapCount; i++) {1658if (screen->info.mem_props.memoryHeaps[i].flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {1659/* VRAM */1660info->total_device_memory += screen->info.mem_props.memoryHeaps[i].size / 1024;1661/* free real estate! */1662info->avail_device_memory += info->total_device_memory;1663} else {1664/* GART */1665info->total_staging_memory += screen->info.mem_props.memoryHeaps[i].size / 1024;1666/* free real estate! */1667info->avail_staging_memory += info->total_staging_memory;1668}1669}1670}1671}16721673static VkDevice1674zink_create_logical_device(struct zink_screen *screen)1675{1676VkDevice dev = VK_NULL_HANDLE;16771678VkDeviceQueueCreateInfo qci = {0};1679float dummy = 0.0f;1680qci.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;1681qci.queueFamilyIndex = screen->gfx_queue;1682qci.queueCount = screen->threaded && screen->max_queues > 1 ? 2 : 1;1683qci.pQueuePriorities = &dummy;16841685VkDeviceCreateInfo dci = {0};1686dci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;1687dci.queueCreateInfoCount = 1;1688dci.pQueueCreateInfos = &qci;1689/* extensions don't have bool members in pEnabledFeatures.1690* this requires us to pass the whole VkPhysicalDeviceFeatures2 struct1691*/1692if (screen->info.feats.sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2) {1693dci.pNext = &screen->info.feats;1694} else {1695dci.pEnabledFeatures = &screen->info.feats.features;1696}16971698dci.ppEnabledExtensionNames = screen->info.extensions;1699dci.enabledExtensionCount = screen->info.num_extensions;17001701vkCreateDevice(screen->pdev, &dci, NULL, &dev);1702return dev;1703}17041705static void1706pre_hash_descriptor_states(struct zink_screen *screen)1707{1708VkImageViewCreateInfo null_info = {.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};1709VkBufferViewCreateInfo null_binfo = {.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO};1710screen->null_descriptor_hashes.image_view = _mesa_hash_data(&null_info, sizeof(VkImageViewCreateInfo));1711screen->null_descriptor_hashes.buffer_view = _mesa_hash_data(&null_binfo, sizeof(VkBufferViewCreateInfo));1712}17131714static void1715check_base_requirements(struct zink_screen *screen)1716{1717if (!screen->info.feats.features.logicOp ||1718!screen->info.feats.features.fillModeNonSolid ||1719!screen->info.feats.features.wideLines ||1720!screen->info.feats.features.largePoints ||1721!screen->info.feats.features.alphaToOne ||1722!screen->info.feats.features.shaderClipDistance ||1723!(screen->info.feats12.scalarBlockLayout ||1724screen->info.have_EXT_scalar_block_layout) ||1725!screen->info.have_KHR_maintenance1 ||1726!screen->info.have_EXT_custom_border_color ||1727!screen->info.have_EXT_line_rasterization ||1728!screen->info.line_rast_feats.rectangularLines ||1729!screen->info.line_rast_feats.bresenhamLines ||1730!screen->info.line_rast_feats.smoothLines ||1731!screen->info.line_rast_feats.stippledRectangularLines ||1732!screen->info.line_rast_feats.stippledBresenhamLines ||1733!screen->info.line_rast_feats.stippledSmoothLines) {1734fprintf(stderr, "WARNING: Some incorrect rendering "1735"might occur because the selected Vulkan device (%s) doesn't support "1736"base Zink requirements: ", screen->info.props.deviceName);1737#define CHECK_OR_PRINT(X) \1738if (!screen->info.X) \1739fprintf(stderr, "%s ", #X)1740CHECK_OR_PRINT(feats.features.logicOp);1741CHECK_OR_PRINT(feats.features.fillModeNonSolid);1742CHECK_OR_PRINT(feats.features.wideLines);1743CHECK_OR_PRINT(feats.features.largePoints);1744CHECK_OR_PRINT(feats.features.alphaToOne);1745CHECK_OR_PRINT(feats.features.shaderClipDistance);1746if (!screen->info.feats12.scalarBlockLayout && !screen->info.have_EXT_scalar_block_layout)1747printf("scalarBlockLayout OR EXT_scalar_block_layout ");1748CHECK_OR_PRINT(have_KHR_maintenance1);1749CHECK_OR_PRINT(have_EXT_custom_border_color);1750CHECK_OR_PRINT(have_EXT_line_rasterization);1751if (screen->info.have_EXT_line_rasterization) {1752CHECK_OR_PRINT(line_rast_feats.rectangularLines);1753CHECK_OR_PRINT(line_rast_feats.bresenhamLines);1754CHECK_OR_PRINT(line_rast_feats.smoothLines);1755CHECK_OR_PRINT(line_rast_feats.stippledRectangularLines);1756CHECK_OR_PRINT(line_rast_feats.stippledBresenhamLines);1757CHECK_OR_PRINT(line_rast_feats.stippledSmoothLines);1758}1759fprintf(stderr, "\n");1760}1761}17621763static void1764zink_get_sample_pixel_grid(struct pipe_screen *pscreen, unsigned sample_count,1765unsigned *width, unsigned *height)1766{1767struct zink_screen *screen = zink_screen(pscreen);1768unsigned idx = util_logbase2_ceil(MAX2(sample_count, 1));1769assert(idx < ARRAY_SIZE(screen->maxSampleLocationGridSize));1770*width = screen->maxSampleLocationGridSize[idx].width;1771*height = screen->maxSampleLocationGridSize[idx].height;1772}17731774static struct zink_screen *1775zink_internal_create_screen(const struct pipe_screen_config *config)1776{1777struct zink_screen *screen = rzalloc(NULL, struct zink_screen);1778if (!screen)1779return NULL;17801781util_cpu_detect();1782screen->threaded = util_get_cpu_caps()->nr_cpus > 1 && debug_get_bool_option("GALLIUM_THREAD", util_get_cpu_caps()->nr_cpus > 1);1783if (screen->threaded)1784util_queue_init(&screen->flush_queue, "zfq", 8, 1, UTIL_QUEUE_INIT_RESIZE_IF_FULL, NULL);17851786zink_debug = debug_get_option_zink_debug();1787screen->descriptor_mode = debug_get_option_zink_descriptor_mode();1788if (util_bitcount(screen->descriptor_mode) > 1) {1789printf("Specify exactly one descriptor mode.\n");1790abort();1791}17921793screen->instance_info.loader_version = zink_get_loader_version();1794screen->instance = zink_create_instance(&screen->instance_info);17951796if (!screen->instance)1797goto fail;17981799vk_instance_dispatch_table_load(&screen->vk.instance, &vkGetInstanceProcAddr, screen->instance);1800vk_physical_device_dispatch_table_load(&screen->vk.physical_device, &vkGetInstanceProcAddr, screen->instance);18011802zink_verify_instance_extensions(screen);18031804if (screen->instance_info.have_EXT_debug_utils &&1805(zink_debug & ZINK_DEBUG_VALIDATION) && !create_debug(screen))1806debug_printf("ZINK: failed to setup debug utils\n");18071808choose_pdev(screen);1809if (screen->pdev == VK_NULL_HANDLE)1810goto fail;18111812update_queue_props(screen);18131814screen->have_X8_D24_UNORM_PACK32 = zink_is_depth_format_supported(screen,1815VK_FORMAT_X8_D24_UNORM_PACK32);1816screen->have_D24_UNORM_S8_UINT = zink_is_depth_format_supported(screen,1817VK_FORMAT_D24_UNORM_S8_UINT);18181819if (!zink_get_physical_device_info(screen)) {1820debug_printf("ZINK: failed to detect features\n");1821goto fail;1822}18231824/* Some Vulkan implementations have special requirements for WSI1825* allocations.1826*/1827check_device_needs_mesa_wsi(screen);18281829zink_internal_setup_moltenvk(screen);18301831screen->dev = zink_create_logical_device(screen);1832if (!screen->dev) {1833debug_printf("ZINK: failed to init: no logical device\n");1834goto fail;1835}18361837init_queue(screen);1838if (screen->info.driver_props.driverID == VK_DRIVER_ID_MESA_RADV ||1839screen->info.driver_props.driverID == VK_DRIVER_ID_AMD_OPEN_SOURCE ||1840screen->info.driver_props.driverID == VK_DRIVER_ID_AMD_PROPRIETARY)1841/* this has bad perf on AMD */1842screen->info.have_KHR_push_descriptor = false;18431844vk_device_dispatch_table_load(&screen->vk.device, &vkGetDeviceProcAddr, screen->dev);18451846zink_verify_device_extensions(screen);18471848if (screen->info.have_EXT_calibrated_timestamps && !check_have_device_time(screen))1849goto fail;18501851screen->have_triangle_fans = true;1852#if defined(VK_EXTX_PORTABILITY_SUBSET_EXTENSION_NAME)1853if (screen->info.have_EXTX_portability_subset) {1854screen->have_triangle_fans = (VK_TRUE == screen->info.portability_subset_extx_feats.triangleFans);1855}1856#endif // VK_EXTX_PORTABILITY_SUBSET_EXTENSION_NAME18571858check_base_requirements(screen);1859util_live_shader_cache_init(&screen->shaders, zink_create_gfx_shader_state, zink_delete_shader_state);18601861screen->base.get_name = zink_get_name;1862screen->base.get_vendor = zink_get_vendor;1863screen->base.get_device_vendor = zink_get_device_vendor;1864screen->base.get_compute_param = zink_get_compute_param;1865screen->base.query_memory_info = zink_query_memory_info;1866screen->base.get_param = zink_get_param;1867screen->base.get_paramf = zink_get_paramf;1868screen->base.get_shader_param = zink_get_shader_param;1869screen->base.get_compiler_options = zink_get_compiler_options;1870screen->base.get_sample_pixel_grid = zink_get_sample_pixel_grid;1871screen->base.is_format_supported = zink_is_format_supported;1872screen->base.context_create = zink_context_create;1873screen->base.flush_frontbuffer = zink_flush_frontbuffer;1874screen->base.destroy = zink_destroy_screen;1875screen->base.finalize_nir = zink_shader_finalize;18761877if (screen->info.have_EXT_sample_locations) {1878VkMultisamplePropertiesEXT prop;1879prop.sType = VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT;1880prop.pNext = NULL;1881for (unsigned i = 0; i < ARRAY_SIZE(screen->maxSampleLocationGridSize); i++) {1882if (screen->info.sample_locations_props.sampleLocationSampleCounts & (1 << i)) {1883screen->vk.GetPhysicalDeviceMultisamplePropertiesEXT(screen->pdev, 1 << i, &prop);1884screen->maxSampleLocationGridSize[i] = prop.maxSampleLocationGridSize;1885}1886}1887}18881889if (!zink_screen_resource_init(&screen->base))1890goto fail;1891zink_screen_fence_init(&screen->base);18921893zink_screen_init_compiler(screen);1894disk_cache_init(screen);1895populate_format_props(screen);1896pre_hash_descriptor_states(screen);18971898slab_create_parent(&screen->transfer_pool, sizeof(struct zink_transfer), 16);18991900#if WITH_XMLCONFIG1901if (config)1902screen->driconf.dual_color_blend_by_location = driQueryOptionb(config->options, "dual_color_blend_by_location");1903//screen->driconf.inline_uniforms = driQueryOptionb(config->options, "radeonsi_inline_uniforms");1904#endif1905screen->driconf.inline_uniforms = debug_get_bool_option("ZINK_INLINE_UNIFORMS", false);19061907screen->total_video_mem = get_video_mem(screen);1908if (!os_get_total_physical_memory(&screen->total_mem))1909goto fail;1910if (screen->info.have_KHR_timeline_semaphore)1911zink_screen_init_semaphore(screen);19121913simple_mtx_init(&screen->surface_mtx, mtx_plain);1914simple_mtx_init(&screen->bufferview_mtx, mtx_plain);1915simple_mtx_init(&screen->framebuffer_mtx, mtx_plain);19161917_mesa_hash_table_init(&screen->framebuffer_cache, screen, hash_framebuffer_state, equals_framebuffer_state);1918_mesa_hash_table_init(&screen->surface_cache, screen, NULL, equals_ivci);1919_mesa_hash_table_init(&screen->bufferview_cache, screen, NULL, equals_bvci);19201921zink_screen_init_descriptor_funcs(screen, false);1922util_idalloc_mt_init_tc(&screen->buffer_ids);19231924return screen;19251926fail:1927ralloc_free(screen);1928return NULL;1929}19301931struct pipe_screen *1932zink_create_screen(struct sw_winsys *winsys)1933{1934struct zink_screen *ret = zink_internal_create_screen(NULL);1935if (ret)1936ret->winsys = winsys;19371938return &ret->base;1939}19401941struct pipe_screen *1942zink_drm_create_screen(int fd, const struct pipe_screen_config *config)1943{1944struct zink_screen *ret = zink_internal_create_screen(config);19451946if (ret && !ret->info.have_KHR_external_memory_fd) {1947debug_printf("ZINK: KHR_external_memory_fd required!\n");1948zink_destroy_screen(&ret->base);1949return NULL;1950}19511952return &ret->base;1953}19541955void zink_stub_function_not_loaded()1956{1957/* this will be used by the zink_verify_*_extensions() functions on a1958* release build1959*/1960mesa_loge("ZINK: a Vulkan function was called without being loaded");1961abort();1962}196319641965