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