• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 Collabora Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * on the rights to use, copy, modify, merge, publish, distribute, sub
8  * license, and/or sell copies of the Software, and to permit persons to whom
9  * the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21  * USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include "zink_screen.h"
25 
26 #include "zink_compiler.h"
27 #include "zink_context.h"
28 #include "zink_device_info.h"
29 #include "zink_fence.h"
30 #include "zink_public.h"
31 #include "zink_resource.h"
32 
33 #include "os/os_process.h"
34 #include "util/u_debug.h"
35 #include "util/format/u_format.h"
36 #include "util/u_math.h"
37 #include "util/u_memory.h"
38 #include "util/u_screen.h"
39 #include "util/u_string.h"
40 
41 #include "frontend/sw_winsys.h"
42 
43 static const struct debug_named_value
44 debug_options[] = {
45    { "nir", ZINK_DEBUG_NIR, "Dump NIR during program compile" },
46    { "spirv", ZINK_DEBUG_SPIRV, "Dump SPIR-V during program compile" },
47    { "tgsi", ZINK_DEBUG_TGSI, "Dump TGSI during program compile" },
48    { "validation", ZINK_DEBUG_VALIDATION, "Dump Validation layer output" },
49    DEBUG_NAMED_VALUE_END
50 };
51 
52 DEBUG_GET_ONCE_FLAGS_OPTION(zink_debug, "ZINK_DEBUG", debug_options, 0)
53 
54 uint32_t
55 zink_debug;
56 
57 static const char *
zink_get_vendor(struct pipe_screen * pscreen)58 zink_get_vendor(struct pipe_screen *pscreen)
59 {
60    return "Collabora Ltd";
61 }
62 
63 static const char *
zink_get_device_vendor(struct pipe_screen * pscreen)64 zink_get_device_vendor(struct pipe_screen *pscreen)
65 {
66    struct zink_screen *screen = zink_screen(pscreen);
67    static char buf[1000];
68    snprintf(buf, sizeof(buf), "Unknown (vendor-id: 0x%04x)", screen->info.props.vendorID);
69    return buf;
70 }
71 
72 static const char *
zink_get_name(struct pipe_screen * pscreen)73 zink_get_name(struct pipe_screen *pscreen)
74 {
75    struct zink_screen *screen = zink_screen(pscreen);
76    static char buf[1000];
77    snprintf(buf, sizeof(buf), "zink (%s)", screen->info.props.deviceName);
78    return buf;
79 }
80 
81 static int
get_video_mem(struct zink_screen * screen)82 get_video_mem(struct zink_screen *screen)
83 {
84    VkDeviceSize size = 0;
85    for (uint32_t i = 0; i < screen->info.mem_props.memoryHeapCount; ++i) {
86       if (screen->info.mem_props.memoryHeaps[i].flags &
87           VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
88          size += screen->info.mem_props.memoryHeaps[i].size;
89    }
90    return (int)(size >> 20);
91 }
92 
93 static int
zink_get_param(struct pipe_screen * pscreen,enum pipe_cap param)94 zink_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
95 {
96    struct zink_screen *screen = zink_screen(pscreen);
97 
98    switch (param) {
99    case PIPE_CAP_NPOT_TEXTURES:
100    case PIPE_CAP_TGSI_TEXCOORD:
101    case PIPE_CAP_DRAW_INDIRECT:
102    case PIPE_CAP_TEXTURE_QUERY_LOD:
103       return 1;
104 
105    case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
106       return screen->info.have_EXT_vertex_attribute_divisor;
107 
108    case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
109       if (!screen->info.feats.features.dualSrcBlend)
110          return 0;
111       return screen->info.props.limits.maxFragmentDualSrcAttachments;
112 
113    case PIPE_CAP_POINT_SPRITE:
114       return 1;
115 
116    case PIPE_CAP_MAX_RENDER_TARGETS:
117       return screen->info.props.limits.maxColorAttachments;
118 
119    case PIPE_CAP_OCCLUSION_QUERY:
120       return 1;
121 
122    case PIPE_CAP_QUERY_TIME_ELAPSED:
123       return screen->timestamp_valid_bits > 0;
124 
125    case PIPE_CAP_TEXTURE_MULTISAMPLE:
126       return 1;
127 
128    case PIPE_CAP_SAMPLE_SHADING:
129       return screen->info.feats.features.sampleRateShading;
130 
131    case PIPE_CAP_TEXTURE_SWIZZLE:
132       return 1;
133 
134    case PIPE_CAP_MAX_TEXTURE_2D_SIZE:
135       return screen->info.props.limits.maxImageDimension2D;
136    case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
137       return 1 + util_logbase2(screen->info.props.limits.maxImageDimension3D);
138    case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
139       return 1 + util_logbase2(screen->info.props.limits.maxImageDimensionCube);
140 
141    case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD:
142    case PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES:
143    case PIPE_CAP_VERTEX_SHADER_SATURATE:
144       return 1;
145 
146    case PIPE_CAP_BLEND_EQUATION_SEPARATE:
147    case PIPE_CAP_INDEP_BLEND_ENABLE:
148    case PIPE_CAP_INDEP_BLEND_FUNC:
149       return screen->info.feats.features.independentBlend;
150 
151    case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
152       return screen->info.have_EXT_transform_feedback ? screen->info.tf_props.maxTransformFeedbackBuffers : 0;
153    case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
154    case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS:
155       return screen->info.have_EXT_transform_feedback;
156 
157    case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
158       return screen->info.props.limits.maxImageArrayLayers;
159 
160    case PIPE_CAP_DEPTH_CLIP_DISABLE:
161       return screen->info.feats.features.depthClamp;
162 
163    case PIPE_CAP_TGSI_INSTANCEID:
164    case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
165    case PIPE_CAP_SEAMLESS_CUBE_MAP:
166       return 1;
167 
168    case PIPE_CAP_MIN_TEXEL_OFFSET:
169       return screen->info.props.limits.minTexelOffset;
170    case PIPE_CAP_MAX_TEXEL_OFFSET:
171       return screen->info.props.limits.maxTexelOffset;
172 
173    case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
174       return 1;
175 
176    case PIPE_CAP_CONDITIONAL_RENDER:
177      return screen->info.have_EXT_conditional_rendering;
178 
179    case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY:
180       return 130;
181    case PIPE_CAP_GLSL_FEATURE_LEVEL:
182       return 330;
183 
184 #if 0 /* TODO: Enable me */
185    case PIPE_CAP_COMPUTE:
186       return 1;
187 #endif
188 
189    case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
190       return screen->info.props.limits.minUniformBufferOffsetAlignment;
191 
192    case PIPE_CAP_QUERY_TIMESTAMP:
193       return screen->info.have_EXT_calibrated_timestamps &&
194              screen->timestamp_valid_bits > 0;
195 
196    case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
197       return screen->info.props.limits.minMemoryMapAlignment;
198 
199    case PIPE_CAP_CUBE_MAP_ARRAY:
200       return screen->info.feats.features.imageCubeArray;
201 
202    case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
203    case PIPE_CAP_PRIMITIVE_RESTART:
204       return 1;
205 
206    case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
207       return screen->info.props.limits.minTexelBufferOffsetAlignment;
208 
209    case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
210       return 0; /* unsure */
211 
212    case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
213       return screen->info.props.limits.maxTexelBufferElements;
214 
215    case PIPE_CAP_ENDIANNESS:
216       return PIPE_ENDIAN_NATIVE; /* unsure */
217 
218    case PIPE_CAP_MAX_VIEWPORTS:
219       return 1; /* TODO: When GS is supported, use screen->info.props.limits.maxViewports */
220 
221    case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
222       return 1;
223 
224    case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:
225       return screen->info.props.limits.maxGeometryOutputVertices;
226    case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
227       return screen->info.props.limits.maxGeometryTotalOutputComponents;
228 
229 #if 0 /* TODO: Enable me. Enables ARB_texture_gather */
230    case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
231       return 4;
232 #endif
233 
234    case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET:
235       return screen->info.props.limits.minTexelGatherOffset;
236    case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET:
237       return screen->info.props.limits.maxTexelGatherOffset;
238 
239    case PIPE_CAP_TGSI_FS_FINE_DERIVATIVE:
240       return 1;
241 
242    case PIPE_CAP_VENDOR_ID:
243       return screen->info.props.vendorID;
244    case PIPE_CAP_DEVICE_ID:
245       return screen->info.props.deviceID;
246 
247    case PIPE_CAP_ACCELERATED:
248       return 1;
249    case PIPE_CAP_VIDEO_MEMORY:
250       return get_video_mem(screen);
251    case PIPE_CAP_UMA:
252       return screen->info.props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
253 
254    case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE:
255       return screen->info.props.limits.maxVertexInputBindingStride;
256 
257 #if 0 /* TODO: Enable me */
258    case PIPE_CAP_SAMPLER_VIEW_TARGET:
259       return 1;
260 #endif
261 
262 #if 0 /* TODO: Enable me */
263    case PIPE_CAP_CLIP_HALFZ:
264       return 1;
265 #endif
266 
267 #if 0 /* TODO: Enable me */
268    case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
269    case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
270       return 1;
271 #endif
272 
273    case PIPE_CAP_SHAREABLE_SHADERS:
274       return 1;
275 
276 #if 0 /* TODO: Enable me. Enables GL_ARB_shader_storage_buffer_object */
277    case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
278       return screen->info.props.limits.minStorageBufferOffsetAlignment;
279 #endif
280 
281    case PIPE_CAP_PCI_GROUP:
282    case PIPE_CAP_PCI_BUS:
283    case PIPE_CAP_PCI_DEVICE:
284    case PIPE_CAP_PCI_FUNCTION:
285       return 0; /* TODO: figure these out */
286 
287    case PIPE_CAP_CULL_DISTANCE:
288       return screen->info.feats.features.shaderCullDistance;
289 
290    case PIPE_CAP_VIEWPORT_SUBPIXEL_BITS:
291       return screen->info.props.limits.viewportSubPixelBits;
292 
293    case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY:
294       return 0; /* not sure */
295 
296    case PIPE_CAP_MAX_GS_INVOCATIONS:
297       return screen->info.props.limits.maxGeometryShaderInvocations;
298 
299    case PIPE_CAP_MAX_COMBINED_SHADER_BUFFERS:
300       return screen->info.props.limits.maxDescriptorSetStorageBuffers;
301 
302    case PIPE_CAP_MAX_SHADER_BUFFER_SIZE:
303       return 65536;
304 
305    case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
306    case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
307       return 1;
308 
309    case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
310    case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
311       return 0;
312 
313    case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT:
314       return 0;
315 
316    case PIPE_CAP_NIR_COMPACT_ARRAYS:
317       return 1;
318 
319    case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL:
320       return 1;
321 
322    case PIPE_CAP_VIEWPORT_TRANSFORM_LOWERED:
323       return 1;
324 
325    case PIPE_CAP_FLATSHADE:
326    case PIPE_CAP_ALPHA_TEST:
327    case PIPE_CAP_CLIP_PLANES:
328    case PIPE_CAP_POINT_SIZE_FIXED:
329    case PIPE_CAP_TWO_SIDED_COLOR:
330       return 0;
331 
332    case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS:
333       return screen->info.props.limits.maxTessellationControlPerVertexOutputComponents / 4;
334    case PIPE_CAP_MAX_VARYINGS:
335       /* need to reserve up to 60 of our varying components and 16 slots for streamout */
336       return MIN2(screen->info.props.limits.maxVertexOutputComponents / 4 / 2, 16);
337 
338    case PIPE_CAP_DMABUF:
339       return screen->info.have_KHR_external_memory_fd;
340 
341    default:
342       return u_pipe_screen_get_param_defaults(pscreen, param);
343    }
344 }
345 
346 static float
zink_get_paramf(struct pipe_screen * pscreen,enum pipe_capf param)347 zink_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)
348 {
349    struct zink_screen *screen = zink_screen(pscreen);
350 
351    switch (param) {
352    case PIPE_CAPF_MAX_LINE_WIDTH:
353    case PIPE_CAPF_MAX_LINE_WIDTH_AA:
354       return screen->info.props.limits.lineWidthRange[1];
355 
356    case PIPE_CAPF_MAX_POINT_WIDTH:
357    case PIPE_CAPF_MAX_POINT_WIDTH_AA:
358       return screen->info.props.limits.pointSizeRange[1];
359 
360    case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
361       return screen->info.props.limits.maxSamplerAnisotropy;
362 
363    case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
364       return screen->info.props.limits.maxSamplerLodBias;
365 
366    case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE:
367    case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE:
368    case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY:
369       return 0.0f; /* not implemented */
370    }
371 
372    /* should only get here on unhandled cases */
373    return 0.0;
374 }
375 
376 static int
zink_get_shader_param(struct pipe_screen * pscreen,enum pipe_shader_type shader,enum pipe_shader_cap param)377 zink_get_shader_param(struct pipe_screen *pscreen,
378                        enum pipe_shader_type shader,
379                        enum pipe_shader_cap param)
380 {
381    struct zink_screen *screen = zink_screen(pscreen);
382 
383    switch (param) {
384    case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
385       switch (shader) {
386       case PIPE_SHADER_FRAGMENT:
387       case PIPE_SHADER_VERTEX:
388          return INT_MAX;
389 
390       case PIPE_SHADER_GEOMETRY:
391          if (screen->info.feats.features.geometryShader)
392             return INT_MAX;
393          break;
394 
395       default:
396          break;
397       }
398       return 0;
399    case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
400    case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
401    case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
402    case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
403       if (shader == PIPE_SHADER_VERTEX ||
404           shader == PIPE_SHADER_FRAGMENT)
405          return INT_MAX;
406       return 0;
407 
408    case PIPE_SHADER_CAP_MAX_INPUTS:
409       switch (shader) {
410       case PIPE_SHADER_VERTEX:
411          return MIN2(screen->info.props.limits.maxVertexInputAttributes,
412                      PIPE_MAX_SHADER_INPUTS);
413       case PIPE_SHADER_GEOMETRY:
414          return MIN2(screen->info.props.limits.maxGeometryInputComponents,
415                      PIPE_MAX_SHADER_INPUTS);
416       case PIPE_SHADER_FRAGMENT:
417          return MIN2(screen->info.props.limits.maxFragmentInputComponents / 4,
418                      PIPE_MAX_SHADER_INPUTS);
419       default:
420          return 0; /* unsupported stage */
421       }
422 
423    case PIPE_SHADER_CAP_MAX_OUTPUTS:
424       switch (shader) {
425       case PIPE_SHADER_VERTEX:
426          return MIN2(screen->info.props.limits.maxVertexOutputComponents / 4,
427                      PIPE_MAX_SHADER_OUTPUTS);
428       case PIPE_SHADER_GEOMETRY:
429          return MIN2(screen->info.props.limits.maxGeometryOutputComponents / 4,
430                      PIPE_MAX_SHADER_OUTPUTS);
431       case PIPE_SHADER_FRAGMENT:
432          return MIN2(screen->info.props.limits.maxColorAttachments,
433                 PIPE_MAX_SHADER_OUTPUTS);
434       default:
435          return 0; /* unsupported stage */
436       }
437 
438    case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
439       switch (shader) {
440       case PIPE_SHADER_VERTEX:
441       case PIPE_SHADER_FRAGMENT:
442       case PIPE_SHADER_GEOMETRY:
443          /* this might be a bit simplistic... */
444          return MIN2(screen->info.props.limits.maxPerStageDescriptorSamplers,
445                      PIPE_MAX_SAMPLERS);
446       default:
447          return 0; /* unsupported stage */
448       }
449 
450    case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:
451       return 65536;
452 
453    case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
454       return  MIN2(screen->info.props.limits.maxPerStageDescriptorUniformBuffers,
455                    PIPE_MAX_CONSTANT_BUFFERS);
456 
457    case PIPE_SHADER_CAP_MAX_TEMPS:
458       return INT_MAX;
459 
460    case PIPE_SHADER_CAP_INTEGERS:
461       return 1;
462 
463    case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
464       return 1;
465 
466    case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
467    case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
468    case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
469    case PIPE_SHADER_CAP_SUBROUTINES:
470    case PIPE_SHADER_CAP_INT64_ATOMICS:
471    case PIPE_SHADER_CAP_FP16:
472    case PIPE_SHADER_CAP_FP16_DERIVATIVES:
473    case PIPE_SHADER_CAP_INT16:
474    case PIPE_SHADER_CAP_GLSL_16BIT_CONSTS:
475       return 0; /* not implemented */
476 
477    case PIPE_SHADER_CAP_PREFERRED_IR:
478       return PIPE_SHADER_IR_NIR;
479 
480    case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
481       return 0; /* not implemented */
482 
483    case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
484       return MIN2(screen->info.props.limits.maxPerStageDescriptorSampledImages,
485                   PIPE_MAX_SHADER_SAMPLER_VIEWS);
486 
487    case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
488    case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED:
489    case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:
490       return 0; /* not implemented */
491 
492    case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:
493       return 0; /* no idea */
494 
495    case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT:
496       return 32; /* arbitrary */
497 
498    case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
499       return 0;
500 
501    case PIPE_SHADER_CAP_SUPPORTED_IRS:
502       return (1 << PIPE_SHADER_IR_NIR) | (1 << PIPE_SHADER_IR_TGSI);
503 
504    case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
505 #if 0 /* TODO: needs compiler support */
506       return MIN2(screen->info.props.limits.maxPerStageDescriptorStorageImages,
507                   PIPE_MAX_SHADER_IMAGES);
508 #else
509       return 0;
510 #endif
511 
512    case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD:
513    case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS:
514       return 0; /* unsure */
515 
516    case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED:
517    case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS:
518    case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS:
519    case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
520       return 0; /* not implemented */
521    }
522 
523    /* should only get here on unhandled cases */
524    return 0;
525 }
526 
527 static VkSampleCountFlagBits
vk_sample_count_flags(uint32_t sample_count)528 vk_sample_count_flags(uint32_t sample_count)
529 {
530    switch (sample_count) {
531    case 1: return VK_SAMPLE_COUNT_1_BIT;
532    case 2: return VK_SAMPLE_COUNT_2_BIT;
533    case 4: return VK_SAMPLE_COUNT_4_BIT;
534    case 8: return VK_SAMPLE_COUNT_8_BIT;
535    case 16: return VK_SAMPLE_COUNT_16_BIT;
536    case 32: return VK_SAMPLE_COUNT_32_BIT;
537    case 64: return VK_SAMPLE_COUNT_64_BIT;
538    default:
539       return 0;
540    }
541 }
542 
543 static bool
zink_is_format_supported(struct pipe_screen * pscreen,enum pipe_format format,enum pipe_texture_target target,unsigned sample_count,unsigned storage_sample_count,unsigned bind)544 zink_is_format_supported(struct pipe_screen *pscreen,
545                          enum pipe_format format,
546                          enum pipe_texture_target target,
547                          unsigned sample_count,
548                          unsigned storage_sample_count,
549                          unsigned bind)
550 {
551    struct zink_screen *screen = zink_screen(pscreen);
552 
553    if (format == PIPE_FORMAT_NONE)
554       return screen->info.props.limits.framebufferNoAttachmentsSampleCounts &
555              vk_sample_count_flags(sample_count);
556 
557    VkFormat vkformat = zink_get_format(screen, format);
558    if (vkformat == VK_FORMAT_UNDEFINED)
559       return false;
560 
561    if (sample_count >= 1) {
562       VkSampleCountFlagBits sample_mask = vk_sample_count_flags(sample_count);
563       if (!sample_mask)
564          return false;
565       const struct util_format_description *desc = util_format_description(format);
566       if (util_format_is_depth_or_stencil(format)) {
567          if (util_format_has_depth(desc)) {
568             if (bind & PIPE_BIND_DEPTH_STENCIL &&
569                 (screen->info.props.limits.framebufferDepthSampleCounts & sample_mask) != sample_mask)
570                return false;
571             if (bind & PIPE_BIND_SAMPLER_VIEW &&
572                 (screen->info.props.limits.sampledImageDepthSampleCounts & sample_mask) != sample_mask)
573                return false;
574          }
575          if (util_format_has_stencil(desc)) {
576             if (bind & PIPE_BIND_DEPTH_STENCIL &&
577                 (screen->info.props.limits.framebufferStencilSampleCounts & sample_mask) != sample_mask)
578                return false;
579             if (bind & PIPE_BIND_SAMPLER_VIEW &&
580                 (screen->info.props.limits.sampledImageStencilSampleCounts & sample_mask) != sample_mask)
581                return false;
582          }
583       } else if (util_format_is_pure_integer(format)) {
584          if (bind & PIPE_BIND_RENDER_TARGET &&
585              !(screen->info.props.limits.framebufferColorSampleCounts & sample_mask))
586             return false;
587          if (bind & PIPE_BIND_SAMPLER_VIEW &&
588              !(screen->info.props.limits.sampledImageIntegerSampleCounts & sample_mask))
589             return false;
590       } else {
591          if (bind & PIPE_BIND_RENDER_TARGET &&
592              !(screen->info.props.limits.framebufferColorSampleCounts & sample_mask))
593             return false;
594          if (bind & PIPE_BIND_SAMPLER_VIEW &&
595              !(screen->info.props.limits.sampledImageColorSampleCounts & sample_mask))
596             return false;
597       }
598    }
599 
600    VkFormatProperties props;
601    vkGetPhysicalDeviceFormatProperties(screen->pdev, vkformat, &props);
602 
603    if (target == PIPE_BUFFER) {
604       if (bind & PIPE_BIND_VERTEX_BUFFER &&
605           !(props.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))
606          return false;
607    } else {
608       /* all other targets are texture-targets */
609       if (bind & PIPE_BIND_RENDER_TARGET &&
610           !(props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
611          return false;
612 
613       if (bind & PIPE_BIND_BLENDABLE &&
614          !(props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT))
615         return false;
616 
617       if (bind & PIPE_BIND_SAMPLER_VIEW &&
618           !(props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
619          return false;
620 
621       if (bind & PIPE_BIND_DEPTH_STENCIL &&
622           !(props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
623          return false;
624    }
625 
626    if (util_format_is_compressed(format)) {
627       const struct util_format_description *desc = util_format_description(format);
628       if (desc->layout == UTIL_FORMAT_LAYOUT_BPTC &&
629           !screen->info.feats.features.textureCompressionBC)
630          return false;
631    }
632 
633    return true;
634 }
635 
636 static void
zink_destroy_screen(struct pipe_screen * pscreen)637 zink_destroy_screen(struct pipe_screen *pscreen)
638 {
639    struct zink_screen *screen = zink_screen(pscreen);
640 
641    if (VK_NULL_HANDLE != screen->debugUtilsCallbackHandle) {
642       screen->vk_DestroyDebugUtilsMessengerEXT(screen->instance, screen->debugUtilsCallbackHandle, NULL);
643    }
644 
645    slab_destroy_parent(&screen->transfer_pool);
646    FREE(screen);
647 }
648 
649 static VkInstance
create_instance(struct zink_screen * screen)650 create_instance(struct zink_screen *screen)
651 {
652    const char *layers[4] = { 0 };
653    uint32_t num_layers = 0;
654    const char *extensions[4] = { 0 };
655    uint32_t num_extensions = 0;
656 
657    bool have_debug_utils_ext = false;
658 #if defined(MVK_VERSION)
659    bool have_moltenvk_layer = false;
660    bool have_moltenvk_layer_ext = false;
661 #endif
662 
663    {
664       // Build up the extensions from the reported ones but only for the unnamed layer
665       uint32_t extension_count = 0;
666       VkResult err = vkEnumerateInstanceExtensionProperties(NULL, &extension_count, NULL);
667       if (err == VK_SUCCESS) {
668          VkExtensionProperties *extension_props = malloc(extension_count * sizeof(VkExtensionProperties));
669          if (extension_props) {
670             err = vkEnumerateInstanceExtensionProperties(NULL, &extension_count, extension_props);
671             if (err == VK_SUCCESS) {
672                for (uint32_t i = 0; i < extension_count; i++) {
673                   if (!strcmp(extension_props[i].extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
674                      have_debug_utils_ext = true;
675                   }
676                   if (!strcmp(extension_props[i].extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
677                      extensions[num_extensions++] = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME;
678                      screen->have_physical_device_prop2_ext = true;
679                   }
680                   if (!strcmp(extension_props[i].extensionName, VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME)) {
681                      extensions[num_extensions++] = VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME;
682                   }
683 #if defined(MVK_VERSION)
684                   if (!strcmp(extension_props[i].extensionName, VK_MVK_MOLTENVK_EXTENSION_NAME)) {
685                      have_moltenvk_layer_ext = true;
686                      extensions[num_extensions++] = VK_MVK_MOLTENVK_EXTENSION_NAME;
687                   }
688 #endif
689                }
690             }
691             free(extension_props);
692          }
693       }
694    }
695 
696    // Clear have_debug_utils_ext if we do not want debug info
697    if (!(zink_debug & ZINK_DEBUG_VALIDATION)) {
698       have_debug_utils_ext = false;
699    }
700 
701    {
702       // Build up the layers from the reported ones
703       uint32_t layer_count = 0;
704       // Init has_validation_layer so if we have debug_util allow a validation layer to be added.
705       // Once a validation layer has been found, do not add any more.
706       bool has_validation_layer = !have_debug_utils_ext;
707 
708       VkResult err = vkEnumerateInstanceLayerProperties(&layer_count, NULL);
709       if (err == VK_SUCCESS) {
710          VkLayerProperties *layer_props = malloc(layer_count * sizeof(VkLayerProperties));
711          if (layer_props) {
712             err = vkEnumerateInstanceLayerProperties(&layer_count, layer_props);
713             if (err == VK_SUCCESS) {
714                for (uint32_t i = 0; i < layer_count; i++) {
715                   if (!strcmp(layer_props[i].layerName, "VK_LAYER_KHRONOS_validation") && !has_validation_layer) {
716                      layers[num_layers++] = "VK_LAYER_KHRONOS_validation";
717                      has_validation_layer = true;
718                   }
719                   if (!strcmp(layer_props[i].layerName, "VK_LAYER_LUNARG_standard_validation") && !has_validation_layer) {
720                      layers[num_layers++] = "VK_LAYER_LUNARG_standard_validation";
721                      has_validation_layer = true;
722                   }
723 #if defined(MVK_VERSION)
724                   if (!strcmp(layer_props[i].layerName, "MoltenVK")) {
725                      have_moltenvk_layer = true;
726                      layers[num_layers++] = "MoltenVK";
727                   }
728 #endif
729                }
730             }
731             free(layer_props);
732          }
733       }
734    }
735 
736    if (have_debug_utils_ext) {
737       extensions[num_extensions++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
738       screen->have_debug_utils_ext = have_debug_utils_ext;
739    }
740 
741 #if defined(MVK_VERSION)
742    if (have_moltenvk_layer_ext && have_moltenvk_layer) {
743       screen->have_moltenvk = true;
744    }
745 #endif
746 
747    VkApplicationInfo ai = {};
748    ai.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
749 
750    char proc_name[128];
751    if (os_get_process_name(proc_name, ARRAY_SIZE(proc_name)))
752       ai.pApplicationName = proc_name;
753    else
754       ai.pApplicationName = "unknown";
755 
756    ai.pEngineName = "mesa zink";
757    ai.apiVersion = VK_API_VERSION_1_0;
758 
759    VkInstanceCreateInfo ici = {};
760    ici.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
761    ici.pApplicationInfo = &ai;
762    ici.ppEnabledExtensionNames = extensions;
763    ici.enabledExtensionCount = num_extensions;
764    ici.ppEnabledLayerNames = layers;
765    ici.enabledLayerCount = num_layers;
766 
767    VkInstance instance = VK_NULL_HANDLE;
768    VkResult err = vkCreateInstance(&ici, NULL, &instance);
769    if (err != VK_SUCCESS)
770       return VK_NULL_HANDLE;
771 
772    return instance;
773 }
774 
775 static VkPhysicalDevice
choose_pdev(const VkInstance instance)776 choose_pdev(const VkInstance instance)
777 {
778    uint32_t i, pdev_count;
779    VkPhysicalDevice *pdevs, pdev;
780    vkEnumeratePhysicalDevices(instance, &pdev_count, NULL);
781    assert(pdev_count > 0);
782 
783    pdevs = malloc(sizeof(*pdevs) * pdev_count);
784    vkEnumeratePhysicalDevices(instance, &pdev_count, pdevs);
785    assert(pdev_count > 0);
786 
787    pdev = pdevs[0];
788    for (i = 0; i < pdev_count; ++i) {
789       VkPhysicalDeviceProperties props;
790       vkGetPhysicalDeviceProperties(pdevs[i], &props);
791       if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
792          pdev = pdevs[i];
793          break;
794       }
795    }
796    free(pdevs);
797    return pdev;
798 }
799 
800 static void
update_queue_props(struct zink_screen * screen)801 update_queue_props(struct zink_screen *screen)
802 {
803    uint32_t num_queues;
804    vkGetPhysicalDeviceQueueFamilyProperties(screen->pdev, &num_queues, NULL);
805    assert(num_queues > 0);
806 
807    VkQueueFamilyProperties *props = malloc(sizeof(*props) * num_queues);
808    vkGetPhysicalDeviceQueueFamilyProperties(screen->pdev, &num_queues, props);
809 
810    for (uint32_t i = 0; i < num_queues; i++) {
811       if (props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
812          screen->gfx_queue = i;
813          screen->timestamp_valid_bits = props[i].timestampValidBits;
814          break;
815       }
816    }
817    free(props);
818 }
819 
820 static void
zink_flush_frontbuffer(struct pipe_screen * pscreen,struct pipe_resource * pres,unsigned level,unsigned layer,void * winsys_drawable_handle,struct pipe_box * sub_box)821 zink_flush_frontbuffer(struct pipe_screen *pscreen,
822                        struct pipe_resource *pres,
823                        unsigned level, unsigned layer,
824                        void *winsys_drawable_handle,
825                        struct pipe_box *sub_box)
826 {
827    struct zink_screen *screen = zink_screen(pscreen);
828    struct sw_winsys *winsys = screen->winsys;
829    struct zink_resource *res = zink_resource(pres);
830 
831    if (!winsys)
832      return;
833    void *map = winsys->displaytarget_map(winsys, res->dt, 0);
834 
835    if (map) {
836       VkImageSubresource isr = {};
837       isr.aspectMask = res->aspect;
838       isr.mipLevel = level;
839       isr.arrayLayer = layer;
840       VkSubresourceLayout layout;
841       vkGetImageSubresourceLayout(screen->dev, res->image, &isr, &layout);
842 
843       void *ptr;
844       VkResult result = vkMapMemory(screen->dev, res->mem, res->offset, res->size, 0, &ptr);
845       if (result != VK_SUCCESS) {
846          debug_printf("failed to map memory for display\n");
847          return;
848       }
849       for (int i = 0; i < pres->height0; ++i) {
850          uint8_t *src = (uint8_t *)ptr + i * layout.rowPitch;
851          uint8_t *dst = (uint8_t *)map + i * res->dt_stride;
852          memcpy(dst, src, res->dt_stride);
853       }
854       vkUnmapMemory(screen->dev, res->mem);
855    }
856 
857    winsys->displaytarget_unmap(winsys, res->dt);
858 
859    assert(res->dt);
860    if (res->dt)
861       winsys->displaytarget_display(winsys, res->dt, winsys_drawable_handle, sub_box);
862 }
863 
864 #define GET_PROC_ADDR(x) do {                                               \
865       screen->vk_##x = (PFN_vk##x)vkGetDeviceProcAddr(screen->dev, "vk"#x); \
866       if (!screen->vk_##x) {                                                \
867          debug_printf("vkGetDeviceProcAddr failed: vk"#x"\n");              \
868          return false;                                                      \
869       } \
870    } while (0)
871 
872 #define GET_PROC_ADDR_INSTANCE(x) do {                                          \
873       screen->vk_##x = (PFN_vk##x)vkGetInstanceProcAddr(screen->instance, "vk"#x); \
874       if (!screen->vk_##x) {                                                \
875          debug_printf("GetInstanceProcAddr failed: vk"#x"\n");        \
876          return false;                                                      \
877       } \
878    } while (0)
879 
880 #define GET_PROC_ADDR_INSTANCE_LOCAL(instance, x) PFN_vk##x vk_##x = (PFN_vk##x)vkGetInstanceProcAddr(instance, "vk"#x)
881 
882 static bool
load_instance_extensions(struct zink_screen * screen)883 load_instance_extensions(struct zink_screen *screen)
884 {
885    screen->loader_version = VK_API_VERSION_1_0;
886    {
887       // Get the Loader version
888       GET_PROC_ADDR_INSTANCE_LOCAL(NULL, EnumerateInstanceVersion);
889       if (vk_EnumerateInstanceVersion) {
890          uint32_t loader_version_temp = VK_API_VERSION_1_0;
891          if (VK_SUCCESS == (*vk_EnumerateInstanceVersion)( &loader_version_temp)) {
892             screen->loader_version = loader_version_temp;
893          }
894       }
895    }
896    if (zink_debug & ZINK_DEBUG_VALIDATION) {
897       printf("zink: Loader %d.%d.%d \n", VK_VERSION_MAJOR(screen->loader_version), VK_VERSION_MINOR(screen->loader_version), VK_VERSION_PATCH(screen->loader_version));
898    }
899 
900    if (VK_MAKE_VERSION(1,1,0) <= screen->loader_version) {
901       // Get Vk 1.1+ Instance functions
902       GET_PROC_ADDR_INSTANCE(GetPhysicalDeviceFeatures2);
903       GET_PROC_ADDR_INSTANCE(GetPhysicalDeviceProperties2);
904    } else
905    if (screen->have_physical_device_prop2_ext) {
906       // Not Vk 1.1+ so if VK_KHR_get_physical_device_properties2 the use it
907       GET_PROC_ADDR_INSTANCE_LOCAL(screen->instance, GetPhysicalDeviceFeatures2KHR);
908       GET_PROC_ADDR_INSTANCE_LOCAL(screen->instance, GetPhysicalDeviceProperties2KHR);
909       screen->vk_GetPhysicalDeviceFeatures2 = vk_GetPhysicalDeviceFeatures2KHR;
910       screen->vk_GetPhysicalDeviceProperties2 = vk_GetPhysicalDeviceProperties2KHR;
911    }
912 
913    return true;
914 }
915 
916 static bool
load_device_extensions(struct zink_screen * screen)917 load_device_extensions(struct zink_screen *screen)
918 {
919    if (screen->info.have_EXT_transform_feedback) {
920       GET_PROC_ADDR(CmdBindTransformFeedbackBuffersEXT);
921       GET_PROC_ADDR(CmdBeginTransformFeedbackEXT);
922       GET_PROC_ADDR(CmdEndTransformFeedbackEXT);
923       GET_PROC_ADDR(CmdBeginQueryIndexedEXT);
924       GET_PROC_ADDR(CmdEndQueryIndexedEXT);
925       GET_PROC_ADDR(CmdDrawIndirectByteCountEXT);
926    }
927    if (screen->info.have_KHR_external_memory_fd)
928       GET_PROC_ADDR(GetMemoryFdKHR);
929 
930    if (screen->info.have_EXT_conditional_rendering) {
931       GET_PROC_ADDR(CmdBeginConditionalRenderingEXT);
932       GET_PROC_ADDR(CmdEndConditionalRenderingEXT);
933    }
934 
935    if (screen->info.have_EXT_calibrated_timestamps) {
936       GET_PROC_ADDR_INSTANCE(GetPhysicalDeviceCalibrateableTimeDomainsEXT);
937       GET_PROC_ADDR(GetCalibratedTimestampsEXT);
938 
939       uint32_t num_domains = 0;
940       screen->vk_GetPhysicalDeviceCalibrateableTimeDomainsEXT(screen->pdev, &num_domains, NULL);
941       assert(num_domains > 0);
942 
943       VkTimeDomainEXT *domains = malloc(sizeof(VkTimeDomainEXT) * num_domains);
944       screen->vk_GetPhysicalDeviceCalibrateableTimeDomainsEXT(screen->pdev, &num_domains, domains);
945 
946       /* VK_TIME_DOMAIN_DEVICE_EXT is used for the ctx->get_timestamp hook and is the only one we really need */
947       ASSERTED bool have_device_time = false;
948       for (unsigned i = 0; i < num_domains; i++) {
949          if (domains[i] == VK_TIME_DOMAIN_DEVICE_EXT) {
950             have_device_time = true;
951             break;
952          }
953       }
954       assert(have_device_time);
955       free(domains);
956    }
957    if (screen->info.have_EXT_extended_dynamic_state) {
958       GET_PROC_ADDR(CmdSetViewportWithCountEXT);
959       GET_PROC_ADDR(CmdSetScissorWithCountEXT);
960    }
961 
962    screen->have_triangle_fans = true;
963 #if defined(VK_EXTX_PORTABILITY_SUBSET_EXTENSION_NAME)
964    if (screen->info.have_EXTX_portability_subset) {
965       screen->have_triangle_fans = (VK_TRUE == screen->info.portability_subset_extx_feats.triangleFans);
966    }
967 #endif // VK_EXTX_PORTABILITY_SUBSET_EXTENSION_NAME
968 
969    return true;
970 }
971 
972 static VkBool32 VKAPI_CALL
zink_debug_util_callback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,VkDebugUtilsMessageTypeFlagsEXT messageType,const VkDebugUtilsMessengerCallbackDataEXT * pCallbackData,void * pUserData)973 zink_debug_util_callback(
974     VkDebugUtilsMessageSeverityFlagBitsEXT           messageSeverity,
975     VkDebugUtilsMessageTypeFlagsEXT                  messageType,
976     const VkDebugUtilsMessengerCallbackDataEXT      *pCallbackData,
977     void                                            *pUserData)
978 {
979    const char *severity = "MSG";
980 
981    // Pick message prefix and color to use.
982    // Only MacOS and Linux have been tested for color support
983    if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
984       severity = "ERR";
985    } else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
986       severity = "WRN";
987    } else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
988       severity = "NFO";
989    }
990 
991    fprintf(stderr, "zink DEBUG: %s: '%s'\n", severity, pCallbackData->pMessage);
992    return VK_FALSE;
993 }
994 
995 static bool
create_debug(struct zink_screen * screen)996 create_debug(struct zink_screen *screen)
997 {
998    GET_PROC_ADDR_INSTANCE(CreateDebugUtilsMessengerEXT);
999    GET_PROC_ADDR_INSTANCE(DestroyDebugUtilsMessengerEXT);
1000 
1001    if (!screen->vk_CreateDebugUtilsMessengerEXT || !screen->vk_DestroyDebugUtilsMessengerEXT)
1002       return false;
1003 
1004    VkDebugUtilsMessengerCreateInfoEXT vkDebugUtilsMessengerCreateInfoEXT = {
1005        VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
1006        NULL,
1007        0,  // flags
1008        VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
1009        VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
1010        VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
1011        VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
1012        VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
1013        VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
1014        VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
1015        zink_debug_util_callback,
1016        NULL
1017    };
1018 
1019    VkDebugUtilsMessengerEXT vkDebugUtilsCallbackEXT = VK_NULL_HANDLE;
1020 
1021    screen->vk_CreateDebugUtilsMessengerEXT(
1022        screen->instance,
1023        &vkDebugUtilsMessengerCreateInfoEXT,
1024        NULL,
1025        &vkDebugUtilsCallbackEXT
1026    );
1027 
1028    screen->debugUtilsCallbackHandle = vkDebugUtilsCallbackEXT;
1029 
1030    return true;
1031 }
1032 
1033 #if defined(MVK_VERSION)
1034 static bool
zink_internal_setup_moltenvk(struct zink_screen * screen)1035 zink_internal_setup_moltenvk(struct zink_screen *screen)
1036 {
1037    if (!screen->have_moltenvk)
1038       return true;
1039 
1040    GET_PROC_ADDR_INSTANCE(GetMoltenVKConfigurationMVK);
1041    GET_PROC_ADDR_INSTANCE(SetMoltenVKConfigurationMVK);
1042 
1043    GET_PROC_ADDR_INSTANCE(GetPhysicalDeviceMetalFeaturesMVK);
1044    GET_PROC_ADDR_INSTANCE(GetVersionStringsMVK);
1045    GET_PROC_ADDR_INSTANCE(UseIOSurfaceMVK);
1046    GET_PROC_ADDR_INSTANCE(GetIOSurfaceMVK);
1047 
1048    if (screen->vk_GetVersionStringsMVK) {
1049       char molten_version[64] = {0};
1050       char vulkan_version[64] = {0};
1051 
1052       (*screen->vk_GetVersionStringsMVK)(molten_version, sizeof(molten_version) - 1, vulkan_version, sizeof(vulkan_version) - 1);
1053 
1054       printf("zink: MoltenVK %s Vulkan %s \n", molten_version, vulkan_version);
1055    }
1056 
1057    if (screen->vk_GetMoltenVKConfigurationMVK && screen->vk_SetMoltenVKConfigurationMVK) {
1058       MVKConfiguration molten_config = {0};
1059       size_t molten_config_size = sizeof(molten_config);
1060 
1061       VkResult res = (*screen->vk_GetMoltenVKConfigurationMVK)(screen->instance, &molten_config, &molten_config_size);
1062       if (res == VK_SUCCESS || res == VK_INCOMPLETE) {
1063          // Needed to allow MoltenVK to accept VkImageView swizzles.
1064          // Encounted when using VK_FORMAT_R8G8_UNORM
1065          molten_config.fullImageViewSwizzle = VK_TRUE;
1066          (*screen->vk_SetMoltenVKConfigurationMVK)(screen->instance, &molten_config, &molten_config_size);
1067       }
1068    }
1069 
1070    return true;
1071 }
1072 #endif // MVK_VERSION
1073 
1074 static struct pipe_screen *
zink_internal_create_screen(struct sw_winsys * winsys,int fd,const struct pipe_screen_config * config)1075 zink_internal_create_screen(struct sw_winsys *winsys, int fd, const struct pipe_screen_config *config)
1076 {
1077    struct zink_screen *screen = CALLOC_STRUCT(zink_screen);
1078    if (!screen)
1079       return NULL;
1080 
1081    zink_debug = debug_get_option_zink_debug();
1082 
1083    screen->instance = create_instance(screen);
1084    if (!screen->instance)
1085       goto fail;
1086 
1087    if (!load_instance_extensions(screen))
1088       goto fail;
1089 
1090    if (screen->have_debug_utils_ext && !create_debug(screen))
1091       debug_printf("ZINK: failed to setup debug utils\n");
1092 
1093    screen->pdev = choose_pdev(screen->instance);
1094    update_queue_props(screen);
1095 
1096    screen->have_X8_D24_UNORM_PACK32 = zink_is_depth_format_supported(screen,
1097                                               VK_FORMAT_X8_D24_UNORM_PACK32);
1098    screen->have_D24_UNORM_S8_UINT = zink_is_depth_format_supported(screen,
1099                                               VK_FORMAT_D24_UNORM_S8_UINT);
1100 
1101    if (!zink_get_physical_device_info(screen)) {
1102       debug_printf("ZINK: failed to detect features\n");
1103       goto fail;
1104    }
1105 
1106 #if defined(MVK_VERSION)
1107    zink_internal_setup_moltenvk(screen);
1108 #endif
1109 
1110    if (fd >= 0 && !screen->info.have_KHR_external_memory_fd) {
1111       debug_printf("ZINK: KHR_external_memory_fd required!\n");
1112       goto fail;
1113    }
1114 
1115    VkDeviceQueueCreateInfo qci = {};
1116    float dummy = 0.0f;
1117    qci.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
1118    qci.queueFamilyIndex = screen->gfx_queue;
1119    qci.queueCount = 1;
1120    qci.pQueuePriorities = &dummy;
1121 
1122    /* TODO: we can probably support non-premul here with some work? */
1123    screen->info.have_EXT_blend_operation_advanced = screen->info.have_EXT_blend_operation_advanced &&
1124                                                     screen->info.blend_props.advancedBlendNonPremultipliedSrcColor &&
1125                                                     screen->info.blend_props.advancedBlendNonPremultipliedDstColor;
1126 
1127    VkDeviceCreateInfo dci = {};
1128    dci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
1129    dci.queueCreateInfoCount = 1;
1130    dci.pQueueCreateInfos = &qci;
1131    /* extensions don't have bool members in pEnabledFeatures.
1132     * this requires us to pass the whole VkPhysicalDeviceFeatures2 struct
1133     */
1134    if (screen->info.feats.sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2) {
1135       dci.pNext = &screen->info.feats;
1136    } else {
1137       dci.pEnabledFeatures = &screen->info.feats.features;
1138    }
1139 
1140    dci.ppEnabledExtensionNames = screen->info.extensions;
1141    dci.enabledExtensionCount = screen->info.num_extensions;
1142 
1143    if (vkCreateDevice(screen->pdev, &dci, NULL, &screen->dev) != VK_SUCCESS)
1144       goto fail;
1145 
1146    if (!load_device_extensions(screen))
1147       goto fail;
1148 
1149    screen->winsys = winsys;
1150 
1151    screen->base.get_name = zink_get_name;
1152    screen->base.get_vendor = zink_get_vendor;
1153    screen->base.get_device_vendor = zink_get_device_vendor;
1154    screen->base.get_param = zink_get_param;
1155    screen->base.get_paramf = zink_get_paramf;
1156    screen->base.get_shader_param = zink_get_shader_param;
1157    screen->base.get_compiler_options = zink_get_compiler_options;
1158    screen->base.is_format_supported = zink_is_format_supported;
1159    screen->base.context_create = zink_context_create;
1160    screen->base.flush_frontbuffer = zink_flush_frontbuffer;
1161    screen->base.destroy = zink_destroy_screen;
1162 
1163    zink_screen_resource_init(&screen->base);
1164    zink_screen_fence_init(&screen->base);
1165 
1166    slab_create_parent(&screen->transfer_pool, sizeof(struct zink_transfer), 16);
1167 
1168    return &screen->base;
1169 
1170 fail:
1171    FREE(screen);
1172    return NULL;
1173 }
1174 
1175 struct pipe_screen *
zink_create_screen(struct sw_winsys * winsys)1176 zink_create_screen(struct sw_winsys *winsys)
1177 {
1178    return zink_internal_create_screen(winsys, -1, NULL);
1179 }
1180 
1181 struct pipe_screen *
zink_drm_create_screen(int fd,const struct pipe_screen_config * config)1182 zink_drm_create_screen(int fd, const struct pipe_screen_config *config)
1183 {
1184    return zink_internal_create_screen(NULL, fd, config);
1185 }
1186