1 /*
2  * Copyright © 2019 Red Hat.
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  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "lvp_private.h"
25 
26 #include "pipe-loader/pipe_loader.h"
27 #include "git_sha1.h"
28 #include "vk_util.h"
29 #include "pipe/p_config.h"
30 #include "pipe/p_defines.h"
31 #include "pipe/p_state.h"
32 #include "pipe/p_context.h"
33 #include "frontend/drisw_api.h"
34 
35 #include "util/u_inlines.h"
36 #include "util/os_memory.h"
37 #include "util/u_thread.h"
38 #include "util/u_atomic.h"
39 #include "util/timespec.h"
40 #include "os_time.h"
41 
42 #if defined(VK_USE_PLATFORM_WAYLAND_KHR) || \
43     defined(VK_USE_PLATFORM_WIN32_KHR) || \
44     defined(VK_USE_PLATFORM_XCB_KHR) || \
45     defined(VK_USE_PLATFORM_XLIB_KHR)
46 #define LVP_USE_WSI_PLATFORM
47 #endif
48 #define LVP_API_VERSION VK_MAKE_VERSION(1, 2, VK_HEADER_VERSION)
49 
lvp_EnumerateInstanceVersion(uint32_t * pApiVersion)50 VKAPI_ATTR VkResult VKAPI_CALL lvp_EnumerateInstanceVersion(uint32_t* pApiVersion)
51 {
52    *pApiVersion = LVP_API_VERSION;
53    return VK_SUCCESS;
54 }
55 
56 static const struct vk_instance_extension_table lvp_instance_extensions_supported = {
57    .KHR_device_group_creation                = true,
58    .KHR_external_fence_capabilities          = true,
59    .KHR_external_memory_capabilities         = true,
60    .KHR_external_semaphore_capabilities      = true,
61    .KHR_get_physical_device_properties2      = true,
62    .EXT_debug_report                         = true,
63 #ifdef LVP_USE_WSI_PLATFORM
64    .KHR_get_surface_capabilities2            = true,
65    .KHR_surface                              = true,
66    .KHR_surface_protected_capabilities       = true,
67 #endif
68 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
69    .KHR_wayland_surface                      = true,
70 #endif
71 #ifdef VK_USE_PLATFORM_WIN32_KHR
72    .KHR_win32_surface                        = true,
73 #endif
74 #ifdef VK_USE_PLATFORM_XCB_KHR
75    .KHR_xcb_surface                          = true,
76 #endif
77 #ifdef VK_USE_PLATFORM_XLIB_KHR
78    .KHR_xlib_surface                         = true,
79 #endif
80 };
81 
82 static const struct vk_device_extension_table lvp_device_extensions_supported = {
83    .KHR_8bit_storage                      = true,
84    .KHR_16bit_storage                     = true,
85    .KHR_bind_memory2                      = true,
86    .KHR_buffer_device_address             = true,
87    .KHR_create_renderpass2                = true,
88    .KHR_copy_commands2                    = true,
89    .KHR_dedicated_allocation              = true,
90    .KHR_depth_stencil_resolve             = true,
91    .KHR_descriptor_update_template        = true,
92    .KHR_device_group                      = true,
93    .KHR_draw_indirect_count               = true,
94    .KHR_driver_properties                 = true,
95    .KHR_external_fence                    = true,
96    .KHR_external_memory                   = true,
97 #ifdef PIPE_MEMORY_FD
98    .KHR_external_memory_fd                = true,
99 #endif
100    .KHR_external_semaphore                = true,
101    .KHR_shader_float_controls             = true,
102    .KHR_get_memory_requirements2          = true,
103 #ifdef LVP_USE_WSI_PLATFORM
104    .KHR_incremental_present               = true,
105 #endif
106    .KHR_image_format_list                 = true,
107    .KHR_imageless_framebuffer             = true,
108    .KHR_maintenance1                      = true,
109    .KHR_maintenance2                      = true,
110    .KHR_maintenance3                      = true,
111    .KHR_multiview                         = true,
112    .KHR_push_descriptor                   = true,
113    .KHR_relaxed_block_layout              = true,
114    .KHR_sampler_mirror_clamp_to_edge      = true,
115    .KHR_separate_depth_stencil_layouts    = true,
116    .KHR_shader_atomic_int64               = true,
117    .KHR_shader_draw_parameters            = true,
118    .KHR_shader_float16_int8               = true,
119    .KHR_shader_subgroup_extended_types    = true,
120    .KHR_spirv_1_4                         = true,
121    .KHR_storage_buffer_storage_class      = true,
122 #ifdef LVP_USE_WSI_PLATFORM
123    .KHR_swapchain                         = true,
124 #endif
125    .KHR_timeline_semaphore                = true,
126    .KHR_uniform_buffer_standard_layout    = true,
127    .KHR_variable_pointers                 = true,
128    .EXT_4444_formats                      = true,
129    .EXT_calibrated_timestamps             = true,
130    .EXT_color_write_enable                = true,
131    .EXT_conditional_rendering             = true,
132    .EXT_depth_clip_enable                 = true,
133    .EXT_extended_dynamic_state            = true,
134    .EXT_extended_dynamic_state2           = true,
135    .EXT_external_memory_host              = true,
136    .EXT_host_query_reset                  = true,
137    .EXT_index_type_uint8                  = true,
138    .EXT_multi_draw                        = true,
139    .EXT_post_depth_coverage               = true,
140    .EXT_private_data                      = true,
141    .EXT_primitive_topology_list_restart   = true,
142    .EXT_sampler_filter_minmax             = true,
143    .EXT_scalar_block_layout               = true,
144    .EXT_separate_stencil_usage            = true,
145    .EXT_shader_stencil_export             = true,
146    .EXT_shader_viewport_index_layer       = true,
147    .EXT_transform_feedback                = true,
148    .EXT_vertex_attribute_divisor          = true,
149    .EXT_vertex_input_dynamic_state        = true,
150    .EXT_custom_border_color               = true,
151    .EXT_provoking_vertex                  = true,
152    .EXT_line_rasterization                = true,
153    .GOOGLE_decorate_string                = true,
154    .GOOGLE_hlsl_functionality1            = true,
155 };
156 
157 static VkResult VKAPI_CALL
lvp_physical_device_init(struct lvp_physical_device * device,struct lvp_instance * instance,struct pipe_loader_device * pld)158 lvp_physical_device_init(struct lvp_physical_device *device,
159                          struct lvp_instance *instance,
160                          struct pipe_loader_device *pld)
161 {
162    VkResult result;
163 
164    struct vk_physical_device_dispatch_table dispatch_table;
165    vk_physical_device_dispatch_table_from_entrypoints(
166       &dispatch_table, &lvp_physical_device_entrypoints, true);
167    vk_physical_device_dispatch_table_from_entrypoints(
168       &dispatch_table, &wsi_physical_device_entrypoints, false);
169    result = vk_physical_device_init(&device->vk, &instance->vk,
170                                     NULL, &dispatch_table);
171    if (result != VK_SUCCESS) {
172       vk_error(instance, result);
173       goto fail;
174    }
175    device->pld = pld;
176 
177    device->pscreen = pipe_loader_create_screen_vk(device->pld, true);
178    if (!device->pscreen)
179       return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
180 
181    device->max_images = device->pscreen->get_shader_param(device->pscreen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_MAX_SHADER_IMAGES);
182    device->vk.supported_extensions = lvp_device_extensions_supported;
183    result = lvp_init_wsi(device);
184    if (result != VK_SUCCESS) {
185       vk_physical_device_finish(&device->vk);
186       vk_error(instance, result);
187       goto fail;
188    }
189 
190    return VK_SUCCESS;
191  fail:
192    return result;
193 }
194 
195 static void VKAPI_CALL
lvp_physical_device_finish(struct lvp_physical_device * device)196 lvp_physical_device_finish(struct lvp_physical_device *device)
197 {
198    lvp_finish_wsi(device);
199    device->pscreen->destroy(device->pscreen);
200    vk_physical_device_finish(&device->vk);
201 }
202 
lvp_CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)203 VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateInstance(
204    const VkInstanceCreateInfo*                 pCreateInfo,
205    const VkAllocationCallbacks*                pAllocator,
206    VkInstance*                                 pInstance)
207 {
208    struct lvp_instance *instance;
209    VkResult result;
210 
211    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
212 
213    if (pAllocator == NULL)
214       pAllocator = vk_default_allocator();
215 
216    instance = vk_zalloc(pAllocator, sizeof(*instance), 8,
217                         VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
218    if (!instance)
219       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
220 
221    struct vk_instance_dispatch_table dispatch_table;
222    vk_instance_dispatch_table_from_entrypoints(
223       &dispatch_table, &lvp_instance_entrypoints, true);
224    vk_instance_dispatch_table_from_entrypoints(
225       &dispatch_table, &wsi_instance_entrypoints, false);
226 
227    result = vk_instance_init(&instance->vk,
228                              &lvp_instance_extensions_supported,
229                              &dispatch_table,
230                              pCreateInfo,
231                              pAllocator);
232    if (result != VK_SUCCESS) {
233       vk_free(pAllocator, instance);
234       return vk_error(instance, result);
235    }
236 
237    instance->apiVersion = LVP_API_VERSION;
238    instance->physicalDeviceCount = -1;
239 
240    //   _mesa_locale_init();
241    //   VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
242 
243    *pInstance = lvp_instance_to_handle(instance);
244 
245    return VK_SUCCESS;
246 }
247 
lvp_DestroyInstance(VkInstance _instance,const VkAllocationCallbacks * pAllocator)248 VKAPI_ATTR void VKAPI_CALL lvp_DestroyInstance(
249    VkInstance                                  _instance,
250    const VkAllocationCallbacks*                pAllocator)
251 {
252    LVP_FROM_HANDLE(lvp_instance, instance, _instance);
253 
254    if (!instance)
255       return;
256    if (instance->physicalDeviceCount > 0)
257       lvp_physical_device_finish(&instance->physicalDevice);
258    //   _mesa_locale_fini();
259 
260    pipe_loader_release(&instance->devs, instance->num_devices);
261 
262    vk_instance_finish(&instance->vk);
263    vk_free(&instance->vk.alloc, instance);
264 }
265 
266 #if defined(HAVE_PIPE_LOADER_DRI)
lvp_get_image(struct dri_drawable * dri_drawable,int x,int y,unsigned width,unsigned height,unsigned stride,void * data)267 static void lvp_get_image(struct dri_drawable *dri_drawable,
268                           int x, int y, unsigned width, unsigned height, unsigned stride,
269                           void *data)
270 {
271 
272 }
273 
lvp_put_image(struct dri_drawable * dri_drawable,void * data,unsigned width,unsigned height)274 static void lvp_put_image(struct dri_drawable *dri_drawable,
275                           void *data, unsigned width, unsigned height)
276 {
277    fprintf(stderr, "put image %dx%d\n", width, height);
278 }
279 
lvp_put_image2(struct dri_drawable * dri_drawable,void * data,int x,int y,unsigned width,unsigned height,unsigned stride)280 static void lvp_put_image2(struct dri_drawable *dri_drawable,
281                            void *data, int x, int y, unsigned width, unsigned height,
282                            unsigned stride)
283 {
284    fprintf(stderr, "put image 2 %d,%d %dx%d\n", x, y, width, height);
285 }
286 
287 static struct drisw_loader_funcs lvp_sw_lf = {
288    .get_image = lvp_get_image,
289    .put_image = lvp_put_image,
290    .put_image2 = lvp_put_image2,
291 };
292 #endif
293 
294 static VkResult
lvp_enumerate_physical_devices(struct lvp_instance * instance)295 lvp_enumerate_physical_devices(struct lvp_instance *instance)
296 {
297    VkResult result;
298 
299    if (instance->physicalDeviceCount != -1)
300       return VK_SUCCESS;
301 
302    /* sw only for now */
303    instance->num_devices = pipe_loader_sw_probe(NULL, 0);
304 
305    assert(instance->num_devices == 1);
306 
307 #if defined(HAVE_PIPE_LOADER_DRI)
308    pipe_loader_sw_probe_dri(&instance->devs, &lvp_sw_lf);
309 #else
310    pipe_loader_sw_probe_null(&instance->devs);
311 #endif
312 
313    result = lvp_physical_device_init(&instance->physicalDevice,
314                                      instance, &instance->devs[0]);
315    if (result == VK_ERROR_INCOMPATIBLE_DRIVER) {
316       instance->physicalDeviceCount = 0;
317    } else if (result == VK_SUCCESS) {
318       instance->physicalDeviceCount = 1;
319    }
320 
321    return result;
322 }
323 
lvp_EnumeratePhysicalDevices(VkInstance _instance,uint32_t * pPhysicalDeviceCount,VkPhysicalDevice * pPhysicalDevices)324 VKAPI_ATTR VkResult VKAPI_CALL lvp_EnumeratePhysicalDevices(
325    VkInstance                                  _instance,
326    uint32_t*                                   pPhysicalDeviceCount,
327    VkPhysicalDevice*                           pPhysicalDevices)
328 {
329    LVP_FROM_HANDLE(lvp_instance, instance, _instance);
330    VkResult result;
331 
332    result = lvp_enumerate_physical_devices(instance);
333    if (result != VK_SUCCESS)
334       return result;
335 
336    if (!pPhysicalDevices) {
337       *pPhysicalDeviceCount = instance->physicalDeviceCount;
338    } else if (*pPhysicalDeviceCount >= 1) {
339       pPhysicalDevices[0] = lvp_physical_device_to_handle(&instance->physicalDevice);
340       *pPhysicalDeviceCount = 1;
341    } else {
342       *pPhysicalDeviceCount = 0;
343    }
344 
345    return VK_SUCCESS;
346 }
347 
lvp_EnumeratePhysicalDeviceGroups(VkInstance _instance,uint32_t * pPhysicalDeviceGroupCount,VkPhysicalDeviceGroupProperties * pPhysicalDeviceGroupProperties)348 VKAPI_ATTR VkResult VKAPI_CALL lvp_EnumeratePhysicalDeviceGroups(
349    VkInstance                                 _instance,
350    uint32_t*                                   pPhysicalDeviceGroupCount,
351    VkPhysicalDeviceGroupProperties*            pPhysicalDeviceGroupProperties)
352 {
353    LVP_FROM_HANDLE(lvp_instance, instance, _instance);
354    VK_OUTARRAY_MAKE_TYPED(VkPhysicalDeviceGroupProperties, out,
355                           pPhysicalDeviceGroupProperties,
356                           pPhysicalDeviceGroupCount);
357 
358    VkResult result = lvp_enumerate_physical_devices(instance);
359    if (result != VK_SUCCESS)
360       return result;
361 
362    vk_outarray_append_typed(VkPhysicalDeviceGroupProperties, &out, p) {
363       p->physicalDeviceCount = 1;
364       memset(p->physicalDevices, 0, sizeof(p->physicalDevices));
365       p->physicalDevices[0] = lvp_physical_device_to_handle(&instance->physicalDevice);
366       p->subsetAllocation = false;
367    }
368 
369    return vk_outarray_status(&out);
370 }
371 
372 static int
min_vertex_pipeline_param(struct pipe_screen * pscreen,enum pipe_shader_cap param)373 min_vertex_pipeline_param(struct pipe_screen *pscreen, enum pipe_shader_cap param)
374 {
375    int val = INT_MAX;
376    for (int i = 0; i < PIPE_SHADER_COMPUTE; ++i) {
377       if (i == PIPE_SHADER_FRAGMENT ||
378           !pscreen->get_shader_param(pscreen, i,
379                                      PIPE_SHADER_CAP_MAX_INSTRUCTIONS))
380          continue;
381 
382       val = MAX2(val, pscreen->get_shader_param(pscreen, i, param));
383    }
384    return val;
385 }
386 
387 static int
min_shader_param(struct pipe_screen * pscreen,enum pipe_shader_cap param)388 min_shader_param(struct pipe_screen *pscreen, enum pipe_shader_cap param)
389 {
390    return MIN3(min_vertex_pipeline_param(pscreen, param),
391                pscreen->get_shader_param(pscreen, PIPE_SHADER_FRAGMENT, param),
392                pscreen->get_shader_param(pscreen, PIPE_SHADER_COMPUTE, param));
393 }
394 
lvp_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,VkPhysicalDeviceFeatures * pFeatures)395 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceFeatures(
396    VkPhysicalDevice                            physicalDevice,
397    VkPhysicalDeviceFeatures*                   pFeatures)
398 {
399    LVP_FROM_HANDLE(lvp_physical_device, pdevice, physicalDevice);
400    bool indirect = false;//pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_GLSL_FEATURE_LEVEL) >= 400;
401    memset(pFeatures, 0, sizeof(*pFeatures));
402    *pFeatures = (VkPhysicalDeviceFeatures) {
403       .robustBufferAccess                       = true,
404       .fullDrawIndexUint32                      = true,
405       .imageCubeArray                           = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_CUBE_MAP_ARRAY) != 0),
406       .independentBlend                         = true,
407       .geometryShader                           = (pdevice->pscreen->get_shader_param(pdevice->pscreen, PIPE_SHADER_GEOMETRY, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) != 0),
408       .tessellationShader                       = (pdevice->pscreen->get_shader_param(pdevice->pscreen, PIPE_SHADER_TESS_EVAL, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) != 0),
409       .sampleRateShading                        = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_SAMPLE_SHADING) != 0),
410       .dualSrcBlend                             = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS) != 0),
411       .logicOp                                  = true,
412       .multiDrawIndirect                        = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MULTI_DRAW_INDIRECT) != 0),
413       .drawIndirectFirstInstance                = true,
414       .depthClamp                               = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_DEPTH_CLIP_DISABLE) != 0),
415       .depthBiasClamp                           = true,
416       .fillModeNonSolid                         = true,
417       .depthBounds                              = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_DEPTH_BOUNDS_TEST) != 0),
418       .wideLines                                = true,
419       .largePoints                              = true,
420       .alphaToOne                               = true,
421       .multiViewport                            = true,
422       .samplerAnisotropy                        = true,
423       .textureCompressionETC2                   = false,
424       .textureCompressionASTC_LDR               = false,
425       .textureCompressionBC                     = true,
426       .occlusionQueryPrecise                    = true,
427       .pipelineStatisticsQuery                  = true,
428       .vertexPipelineStoresAndAtomics           = (min_vertex_pipeline_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_SHADER_BUFFERS) != 0),
429       .fragmentStoresAndAtomics                 = (pdevice->pscreen->get_shader_param(pdevice->pscreen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_MAX_SHADER_BUFFERS) != 0),
430       .shaderTessellationAndGeometryPointSize   = true,
431       .shaderImageGatherExtended                = true,
432       .shaderStorageImageExtendedFormats        = (min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_SHADER_IMAGES) != 0),
433       .shaderStorageImageMultisample            = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_TEXTURE_MULTISAMPLE) != 0),
434       .shaderUniformBufferArrayDynamicIndexing  = true,
435       .shaderSampledImageArrayDynamicIndexing   = indirect,
436       .shaderStorageBufferArrayDynamicIndexing  = true,
437       .shaderStorageImageArrayDynamicIndexing   = indirect,
438       .shaderStorageImageReadWithoutFormat      = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_IMAGE_LOAD_FORMATTED) != 0),
439       .shaderStorageImageWriteWithoutFormat     = (min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_SHADER_IMAGES) != 0),
440       .shaderClipDistance                       = true,
441       .shaderCullDistance                       = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_CULL_DISTANCE) == 1),
442       .shaderFloat64                            = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_DOUBLES) == 1),
443       .shaderInt64                              = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_INT64) == 1),
444       .shaderInt16                              = (min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_INT16) == 1),
445       .variableMultisampleRate                  = false,
446       .inheritedQueries                         = false,
447    };
448 }
449 
450 static void
lvp_get_physical_device_features_1_1(struct lvp_physical_device * pdevice,VkPhysicalDeviceVulkan11Features * f)451 lvp_get_physical_device_features_1_1(struct lvp_physical_device *pdevice,
452                                      VkPhysicalDeviceVulkan11Features *f)
453 {
454    assert(f->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES);
455 
456    f->storageBuffer16BitAccess            = true;
457    f->uniformAndStorageBuffer16BitAccess  = true;
458    f->storagePushConstant16               = true;
459    f->storageInputOutput16                = false;
460    f->multiview                           = true;
461    f->multiviewGeometryShader             = true;
462    f->multiviewTessellationShader         = true;
463    f->variablePointersStorageBuffer       = true;
464    f->variablePointers                    = false;
465    f->protectedMemory                     = false;
466    f->samplerYcbcrConversion              = false;
467    f->shaderDrawParameters                = true;
468 }
469 
470 static void
lvp_get_physical_device_features_1_2(struct lvp_physical_device * pdevice,VkPhysicalDeviceVulkan12Features * f)471 lvp_get_physical_device_features_1_2(struct lvp_physical_device *pdevice,
472                                      VkPhysicalDeviceVulkan12Features *f)
473 {
474    assert(f->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES);
475 
476    f->samplerMirrorClampToEdge = true;
477    f->drawIndirectCount = true;
478    f->storageBuffer8BitAccess = true;
479    f->uniformAndStorageBuffer8BitAccess = true;
480    f->storagePushConstant8 = true;
481    f->shaderBufferInt64Atomics = true;
482    f->shaderSharedInt64Atomics = true;
483    f->shaderFloat16 = pdevice->pscreen->get_shader_param(pdevice->pscreen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_FP16) != 0;
484    f->shaderInt8 = true;
485 
486    f->descriptorIndexing = false;
487    f->shaderInputAttachmentArrayDynamicIndexing = false;
488    f->shaderUniformTexelBufferArrayDynamicIndexing = false;
489    f->shaderStorageTexelBufferArrayDynamicIndexing = false;
490    f->shaderUniformBufferArrayNonUniformIndexing = false;
491    f->shaderSampledImageArrayNonUniformIndexing = false;
492    f->shaderStorageBufferArrayNonUniformIndexing = false;
493    f->shaderStorageImageArrayNonUniformIndexing = false;
494    f->shaderInputAttachmentArrayNonUniformIndexing = false;
495    f->shaderUniformTexelBufferArrayNonUniformIndexing = false;
496    f->shaderStorageTexelBufferArrayNonUniformIndexing = false;
497    f->descriptorBindingUniformBufferUpdateAfterBind = false;
498    f->descriptorBindingSampledImageUpdateAfterBind = false;
499    f->descriptorBindingStorageImageUpdateAfterBind = false;
500    f->descriptorBindingStorageBufferUpdateAfterBind = false;
501    f->descriptorBindingUniformTexelBufferUpdateAfterBind = false;
502    f->descriptorBindingStorageTexelBufferUpdateAfterBind = false;
503    f->descriptorBindingUpdateUnusedWhilePending = false;
504    f->descriptorBindingPartiallyBound = false;
505    f->descriptorBindingVariableDescriptorCount = false;
506    f->runtimeDescriptorArray = false;
507 
508    f->samplerFilterMinmax = true;
509    f->scalarBlockLayout = true;
510    f->imagelessFramebuffer = true;
511    f->uniformBufferStandardLayout = true;
512    f->shaderSubgroupExtendedTypes = true;
513    f->separateDepthStencilLayouts = true;
514    f->hostQueryReset = true;
515    f->timelineSemaphore = true;
516    f->bufferDeviceAddress = true;
517    f->bufferDeviceAddressCaptureReplay = false;
518    f->bufferDeviceAddressMultiDevice = false;
519    f->vulkanMemoryModel = false;
520    f->vulkanMemoryModelDeviceScope = false;
521    f->vulkanMemoryModelAvailabilityVisibilityChains = false;
522    f->shaderOutputViewportIndex = true;
523    f->shaderOutputLayer = true;
524    f->subgroupBroadcastDynamicId = true;
525 }
526 
lvp_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,VkPhysicalDeviceFeatures2 * pFeatures)527 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceFeatures2(
528    VkPhysicalDevice                            physicalDevice,
529    VkPhysicalDeviceFeatures2                  *pFeatures)
530 {
531    LVP_FROM_HANDLE(lvp_physical_device, pdevice, physicalDevice);
532    lvp_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
533 
534    VkPhysicalDeviceVulkan11Features core_1_1 = {
535       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES,
536    };
537    lvp_get_physical_device_features_1_1(pdevice, &core_1_1);
538 
539    VkPhysicalDeviceVulkan12Features core_1_2 = {
540       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
541    };
542    lvp_get_physical_device_features_1_2(pdevice, &core_1_2);
543 
544    vk_foreach_struct(ext, pFeatures->pNext) {
545 
546       if (vk_get_physical_device_core_1_1_feature_ext(ext, &core_1_1))
547          continue;
548       if (vk_get_physical_device_core_1_2_feature_ext(ext, &core_1_2))
549          continue;
550 
551       switch (ext->sType) {
552       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT: {
553          VkPhysicalDevicePrivateDataFeaturesEXT *features =
554             (VkPhysicalDevicePrivateDataFeaturesEXT *)ext;
555          features->privateData = true;
556          break;
557       }
558       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: {
559          VkPhysicalDeviceLineRasterizationFeaturesEXT *features =
560             (VkPhysicalDeviceLineRasterizationFeaturesEXT *)ext;
561          features->rectangularLines = true;
562          features->bresenhamLines = true;
563          features->smoothLines = true;
564          features->stippledRectangularLines = true;
565          features->stippledBresenhamLines = true;
566          features->stippledSmoothLines = true;
567          break;
568       }
569       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
570          VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features =
571             (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *)ext;
572          features->vertexAttributeInstanceRateZeroDivisor = false;
573          if (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR) != 0) {
574             features->vertexAttributeInstanceRateDivisor = true;
575          } else {
576             features->vertexAttributeInstanceRateDivisor = false;
577          }
578          break;
579       }
580 
581       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: {
582          VkPhysicalDeviceIndexTypeUint8FeaturesEXT *features =
583             (VkPhysicalDeviceIndexTypeUint8FeaturesEXT *)ext;
584          features->indexTypeUint8 = true;
585          break;
586       }
587 
588       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT: {
589          VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT *features =
590             (VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT *)ext;
591          features->vertexInputDynamicState = true;
592          break;
593       }
594       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: {
595          VkPhysicalDeviceTransformFeedbackFeaturesEXT *features =
596             (VkPhysicalDeviceTransformFeedbackFeaturesEXT*)ext;
597 
598          features->transformFeedback = true;
599          features->geometryStreams = true;
600          break;
601       }
602       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: {
603          VkPhysicalDeviceConditionalRenderingFeaturesEXT *features =
604             (VkPhysicalDeviceConditionalRenderingFeaturesEXT*)ext;
605          features->conditionalRendering = true;
606          features->inheritedConditionalRendering = false;
607          break;
608       }
609       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT: {
610          VkPhysicalDeviceExtendedDynamicStateFeaturesEXT *features =
611             (VkPhysicalDeviceExtendedDynamicStateFeaturesEXT*)ext;
612          features->extendedDynamicState = true;
613          break;
614       }
615       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: {
616          VkPhysicalDevice4444FormatsFeaturesEXT *features =
617             (VkPhysicalDevice4444FormatsFeaturesEXT*)ext;
618          features->formatA4R4G4B4 = true;
619          features->formatA4B4G4R4 = true;
620          break;
621       }
622       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: {
623          VkPhysicalDeviceCustomBorderColorFeaturesEXT *features =
624             (VkPhysicalDeviceCustomBorderColorFeaturesEXT *)ext;
625          features->customBorderColors = true;
626          features->customBorderColorWithoutFormat = true;
627          break;
628       }
629       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT: {
630          VkPhysicalDeviceColorWriteEnableFeaturesEXT *features =
631             (VkPhysicalDeviceColorWriteEnableFeaturesEXT *)ext;
632          features->colorWriteEnable = true;
633          break;
634       }
635       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT: {
636          VkPhysicalDeviceProvokingVertexFeaturesEXT *features =
637             (VkPhysicalDeviceProvokingVertexFeaturesEXT*)ext;
638          features->provokingVertexLast = true;
639          features->transformFeedbackPreservesProvokingVertex = true;
640          break;
641       }
642       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT: {
643          VkPhysicalDeviceMultiDrawFeaturesEXT *features = (VkPhysicalDeviceMultiDrawFeaturesEXT *)ext;
644          features->multiDraw = true;
645          break;
646       }
647       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: {
648          VkPhysicalDeviceDepthClipEnableFeaturesEXT *features =
649             (VkPhysicalDeviceDepthClipEnableFeaturesEXT *)ext;
650          if (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_DEPTH_CLAMP_ENABLE) != 0)
651             features->depthClipEnable = true;
652          else
653             features->depthClipEnable = false;
654          break;
655       }
656       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT: {
657          VkPhysicalDeviceExtendedDynamicState2FeaturesEXT *features = (VkPhysicalDeviceExtendedDynamicState2FeaturesEXT *)ext;
658          features->extendedDynamicState2 = true;
659          features->extendedDynamicState2LogicOp = true;
660          features->extendedDynamicState2PatchControlPoints = true;
661          break;
662       }
663       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT: {
664          VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT *features = (VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT *)ext;
665          features->primitiveTopologyListRestart = true;
666          features->primitiveTopologyPatchListRestart = true;
667          break;
668       }
669       default:
670          break;
671       }
672    }
673 }
674 
675 void
lvp_device_get_cache_uuid(void * uuid)676 lvp_device_get_cache_uuid(void *uuid)
677 {
678    memset(uuid, 0, VK_UUID_SIZE);
679    snprintf(uuid, VK_UUID_SIZE, "val-%s", MESA_GIT_SHA1 + 4);
680 }
681 
lvp_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,VkPhysicalDeviceProperties * pProperties)682 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
683                                      VkPhysicalDeviceProperties *pProperties)
684 {
685    LVP_FROM_HANDLE(lvp_physical_device, pdevice, physicalDevice);
686 
687    VkSampleCountFlags sample_counts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT;
688 
689    uint64_t grid_size[3], block_size[3];
690    uint64_t max_threads_per_block, max_local_size;
691 
692    pdevice->pscreen->get_compute_param(pdevice->pscreen, PIPE_SHADER_IR_NIR,
693                                        PIPE_COMPUTE_CAP_MAX_GRID_SIZE, grid_size);
694    pdevice->pscreen->get_compute_param(pdevice->pscreen, PIPE_SHADER_IR_NIR,
695                                        PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE, block_size);
696    pdevice->pscreen->get_compute_param(pdevice->pscreen, PIPE_SHADER_IR_NIR,
697                                        PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK,
698                                        &max_threads_per_block);
699    pdevice->pscreen->get_compute_param(pdevice->pscreen, PIPE_SHADER_IR_NIR,
700                                        PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE,
701                                        &max_local_size);
702 
703    VkPhysicalDeviceLimits limits = {
704       .maxImageDimension1D                      = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE),
705       .maxImageDimension2D                      = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE),
706       .maxImageDimension3D                      = (1 << pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_3D_LEVELS)),
707       .maxImageDimensionCube                    = (1 << pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS)),
708       .maxImageArrayLayers                      = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS),
709       .maxTexelBufferElements                   = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE),
710       .maxUniformBufferRange                    = min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE),
711       .maxStorageBufferRange                    = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_SHADER_BUFFER_SIZE),
712       .maxPushConstantsSize                     = MAX_PUSH_CONSTANTS_SIZE,
713       .maxMemoryAllocationCount                 = UINT32_MAX,
714       .maxSamplerAllocationCount                = 32 * 1024,
715       .bufferImageGranularity                   = 64, /* A cache line */
716       .sparseAddressSpaceSize                   = 0,
717       .maxBoundDescriptorSets                   = MAX_SETS,
718       .maxPerStageDescriptorSamplers            = min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS),
719       .maxPerStageDescriptorUniformBuffers      = min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_CONST_BUFFERS) - 1,
720       .maxPerStageDescriptorStorageBuffers      = min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_SHADER_BUFFERS),
721       .maxPerStageDescriptorSampledImages       = min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS),
722       .maxPerStageDescriptorStorageImages       = min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_SHADER_IMAGES),
723       .maxPerStageDescriptorInputAttachments    = 8,
724       .maxPerStageResources                     = 128,
725       .maxDescriptorSetSamplers                 = 32 * 1024,
726       .maxDescriptorSetUniformBuffers           = 256,
727       .maxDescriptorSetUniformBuffersDynamic    = 256,
728       .maxDescriptorSetStorageBuffers           = 256,
729       .maxDescriptorSetStorageBuffersDynamic    = 256,
730       .maxDescriptorSetSampledImages            = 256,
731       .maxDescriptorSetStorageImages            = 256,
732       .maxDescriptorSetInputAttachments         = 256,
733       .maxVertexInputAttributes                 = 32,
734       .maxVertexInputBindings                   = 32,
735       .maxVertexInputAttributeOffset            = 2047,
736       .maxVertexInputBindingStride              = 2048,
737       .maxVertexOutputComponents                = 128,
738       .maxTessellationGenerationLevel           = 64,
739       .maxTessellationPatchSize                 = 32,
740       .maxTessellationControlPerVertexInputComponents = 128,
741       .maxTessellationControlPerVertexOutputComponents = 128,
742       .maxTessellationControlPerPatchOutputComponents = 128,
743       .maxTessellationControlTotalOutputComponents = 4096,
744       .maxTessellationEvaluationInputComponents = 128,
745       .maxTessellationEvaluationOutputComponents = 128,
746       .maxGeometryShaderInvocations             = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_GS_INVOCATIONS),
747       .maxGeometryInputComponents               = 64,
748       .maxGeometryOutputComponents              = 128,
749       .maxGeometryOutputVertices                = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES),
750       .maxGeometryTotalOutputComponents         = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS),
751       .maxFragmentInputComponents               = 128,
752       .maxFragmentOutputAttachments             = 8,
753       .maxFragmentDualSrcAttachments            = 2,
754       .maxFragmentCombinedOutputResources       = 8,
755       .maxComputeSharedMemorySize               = max_local_size,
756       .maxComputeWorkGroupCount                 = { grid_size[0], grid_size[1], grid_size[2] },
757       .maxComputeWorkGroupInvocations           = max_threads_per_block,
758       .maxComputeWorkGroupSize = { block_size[0], block_size[1], block_size[2] },
759       .subPixelPrecisionBits                    = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_RASTERIZER_SUBPIXEL_BITS),
760       .subTexelPrecisionBits                    = 8,
761       .mipmapPrecisionBits                      = 4,
762       .maxDrawIndexedIndexValue                 = UINT32_MAX,
763       .maxDrawIndirectCount                     = UINT32_MAX,
764       .maxSamplerLodBias                        = 16,
765       .maxSamplerAnisotropy                     = 16,
766       .maxViewports                             = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_VIEWPORTS),
767       .maxViewportDimensions                    = { (1 << 14), (1 << 14) },
768       .viewportBoundsRange                      = { -32768.0, 32768.0 },
769       .viewportSubPixelBits                     = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_VIEWPORT_SUBPIXEL_BITS),
770       .minMemoryMapAlignment                    = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT),
771       .minTexelBufferOffsetAlignment            = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT),
772       .minUniformBufferOffsetAlignment          = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT),
773       .minStorageBufferOffsetAlignment          = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT),
774       .minTexelOffset                           = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MIN_TEXEL_OFFSET),
775       .maxTexelOffset                           = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXEL_OFFSET),
776       .minTexelGatherOffset                     = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET),
777       .maxTexelGatherOffset                     = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET),
778       .minInterpolationOffset                   = -2, /* FIXME */
779       .maxInterpolationOffset                   = 2, /* FIXME */
780       .subPixelInterpolationOffsetBits          = 8, /* FIXME */
781       .maxFramebufferWidth                      = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE),
782       .maxFramebufferHeight                     = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE),
783       .maxFramebufferLayers                     = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS),
784       .framebufferColorSampleCounts             = sample_counts,
785       .framebufferDepthSampleCounts             = sample_counts,
786       .framebufferStencilSampleCounts           = sample_counts,
787       .framebufferNoAttachmentsSampleCounts     = sample_counts,
788       .maxColorAttachments                      = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_RENDER_TARGETS),
789       .sampledImageColorSampleCounts            = sample_counts,
790       .sampledImageIntegerSampleCounts          = sample_counts,
791       .sampledImageDepthSampleCounts            = sample_counts,
792       .sampledImageStencilSampleCounts          = sample_counts,
793       .storageImageSampleCounts                 = sample_counts,
794       .maxSampleMaskWords                       = 1,
795       .timestampComputeAndGraphics              = true,
796       .timestampPeriod                          = 1,
797       .maxClipDistances                         = 8,
798       .maxCullDistances                         = 8,
799       .maxCombinedClipAndCullDistances          = 8,
800       .discreteQueuePriorities                  = 2,
801       .pointSizeRange                           = { 0.0, pdevice->pscreen->get_paramf(pdevice->pscreen, PIPE_CAPF_MAX_POINT_WIDTH) },
802       .lineWidthRange                           = { 1.0, pdevice->pscreen->get_paramf(pdevice->pscreen, PIPE_CAPF_MAX_LINE_WIDTH) },
803       .pointSizeGranularity                     = (1.0 / 8.0),
804       .lineWidthGranularity                     = 1.0 / 128.0,
805       .strictLines                              = true,
806       .standardSampleLocations                  = true,
807       .optimalBufferCopyOffsetAlignment         = 128,
808       .optimalBufferCopyRowPitchAlignment       = 128,
809       .nonCoherentAtomSize                      = 64,
810    };
811 
812    *pProperties = (VkPhysicalDeviceProperties) {
813       .apiVersion = LVP_API_VERSION,
814       .driverVersion = 1,
815       .vendorID = VK_VENDOR_ID_MESA,
816       .deviceID = 0,
817       .deviceType = VK_PHYSICAL_DEVICE_TYPE_CPU,
818       .limits = limits,
819       .sparseProperties = {0},
820    };
821 
822    strcpy(pProperties->deviceName, pdevice->pscreen->get_name(pdevice->pscreen));
823    lvp_device_get_cache_uuid(pProperties->pipelineCacheUUID);
824 
825 }
826 
827 extern unsigned lp_native_vector_width;
828 static void
lvp_get_physical_device_properties_1_1(struct lvp_physical_device * pdevice,VkPhysicalDeviceVulkan11Properties * p)829 lvp_get_physical_device_properties_1_1(struct lvp_physical_device *pdevice,
830                                        VkPhysicalDeviceVulkan11Properties *p)
831 {
832    assert(p->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES);
833 
834    memset(p->deviceUUID, 0, VK_UUID_SIZE);
835    memset(p->driverUUID, 0, VK_UUID_SIZE);
836    memset(p->deviceLUID, 0, VK_LUID_SIZE);
837    /* The LUID is for Windows. */
838    p->deviceLUIDValid = false;
839    p->deviceNodeMask = 0;
840 
841    p->subgroupSize = lp_native_vector_width / 32;
842    p->subgroupSupportedStages = VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
843    p->subgroupSupportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT | VK_SUBGROUP_FEATURE_VOTE_BIT | VK_SUBGROUP_FEATURE_ARITHMETIC_BIT | VK_SUBGROUP_FEATURE_BALLOT_BIT;
844    p->subgroupQuadOperationsInAllStages = false;
845 
846    p->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
847    p->maxMultiviewViewCount = 6;
848    p->maxMultiviewInstanceIndex = INT_MAX;
849    p->protectedNoFault = false;
850    p->maxPerSetDescriptors = 1024;
851    p->maxMemoryAllocationSize = (1u << 31);
852 }
853 
854 static void
lvp_get_physical_device_properties_1_2(struct lvp_physical_device * pdevice,VkPhysicalDeviceVulkan12Properties * p)855 lvp_get_physical_device_properties_1_2(struct lvp_physical_device *pdevice,
856                                        VkPhysicalDeviceVulkan12Properties *p)
857 {
858    p->driverID = VK_DRIVER_ID_MESA_LLVMPIPE;
859    snprintf(p->driverName, VK_MAX_DRIVER_NAME_SIZE, "llvmpipe");
860    snprintf(p->driverInfo, VK_MAX_DRIVER_INFO_SIZE, "Mesa " PACKAGE_VERSION MESA_GIT_SHA1
861 #ifdef MESA_LLVM_VERSION_STRING
862                   " (LLVM " MESA_LLVM_VERSION_STRING ")"
863 #endif
864             );
865 
866    p->conformanceVersion = (VkConformanceVersion){
867       .major = 0,
868       .minor = 0,
869       .subminor = 0,
870       .patch = 0,
871    };
872 
873    p->denormBehaviorIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL_KHR;
874    p->roundingModeIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL_KHR;
875    p->shaderDenormFlushToZeroFloat16 = false;
876    p->shaderDenormPreserveFloat16 = false;
877    p->shaderRoundingModeRTEFloat16 = true;
878    p->shaderRoundingModeRTZFloat16 = false;
879    p->shaderSignedZeroInfNanPreserveFloat16 = true;
880 
881    p->shaderDenormFlushToZeroFloat32 = false;
882    p->shaderDenormPreserveFloat32 = false;
883    p->shaderRoundingModeRTEFloat32 = true;
884    p->shaderRoundingModeRTZFloat32 = false;
885    p->shaderSignedZeroInfNanPreserveFloat32 = true;
886 
887    p->shaderDenormFlushToZeroFloat64 = false;
888    p->shaderDenormPreserveFloat64 = false;
889    p->shaderRoundingModeRTEFloat64 = true;
890    p->shaderRoundingModeRTZFloat64 = false;
891    p->shaderSignedZeroInfNanPreserveFloat64 = true;
892 
893    p->maxUpdateAfterBindDescriptorsInAllPools = UINT32_MAX / 64;
894    p->shaderUniformBufferArrayNonUniformIndexingNative = false;
895    p->shaderSampledImageArrayNonUniformIndexingNative = false;
896    p->shaderStorageBufferArrayNonUniformIndexingNative = false;
897    p->shaderStorageImageArrayNonUniformIndexingNative = false;
898    p->shaderInputAttachmentArrayNonUniformIndexingNative = false;
899    p->robustBufferAccessUpdateAfterBind = true;
900    p->quadDivergentImplicitLod = false;
901 
902    size_t max_descriptor_set_size = 65536; //TODO
903    p->maxPerStageDescriptorUpdateAfterBindSamplers = max_descriptor_set_size;
904    p->maxPerStageDescriptorUpdateAfterBindUniformBuffers = max_descriptor_set_size;
905    p->maxPerStageDescriptorUpdateAfterBindStorageBuffers = max_descriptor_set_size;
906    p->maxPerStageDescriptorUpdateAfterBindSampledImages = max_descriptor_set_size;
907    p->maxPerStageDescriptorUpdateAfterBindStorageImages = max_descriptor_set_size;
908    p->maxPerStageDescriptorUpdateAfterBindInputAttachments = max_descriptor_set_size;
909    p->maxPerStageUpdateAfterBindResources = max_descriptor_set_size;
910    p->maxDescriptorSetUpdateAfterBindSamplers = max_descriptor_set_size;
911    p->maxDescriptorSetUpdateAfterBindUniformBuffers = max_descriptor_set_size;
912    p->maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = 16;
913    p->maxDescriptorSetUpdateAfterBindStorageBuffers = max_descriptor_set_size;
914    p->maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = 16;
915    p->maxDescriptorSetUpdateAfterBindSampledImages = max_descriptor_set_size;
916    p->maxDescriptorSetUpdateAfterBindStorageImages = max_descriptor_set_size;
917    p->maxDescriptorSetUpdateAfterBindInputAttachments = max_descriptor_set_size;
918 
919    p->supportedDepthResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT | VK_RESOLVE_MODE_AVERAGE_BIT;
920    p->supportedStencilResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
921    p->independentResolveNone = false;
922    p->independentResolve = false;
923 
924    p->filterMinmaxImageComponentMapping = true;
925    p->filterMinmaxSingleComponentFormats = true;
926 
927    p->maxTimelineSemaphoreValueDifference = UINT64_MAX;
928    p->framebufferIntegerColorSampleCounts = VK_SAMPLE_COUNT_1_BIT;
929 }
930 
lvp_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,VkPhysicalDeviceProperties2 * pProperties)931 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceProperties2(
932    VkPhysicalDevice                            physicalDevice,
933    VkPhysicalDeviceProperties2                *pProperties)
934 {
935    LVP_FROM_HANDLE(lvp_physical_device, pdevice, physicalDevice);
936    lvp_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
937 
938    VkPhysicalDeviceVulkan11Properties core_1_1 = {
939       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES,
940    };
941    lvp_get_physical_device_properties_1_1(pdevice, &core_1_1);
942 
943    VkPhysicalDeviceVulkan12Properties core_1_2 = {
944       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES,
945    };
946    lvp_get_physical_device_properties_1_2(pdevice, &core_1_2);
947 
948    vk_foreach_struct(ext, pProperties->pNext) {
949 
950       if (vk_get_physical_device_core_1_1_property_ext(ext, &core_1_1))
951          continue;
952       if (vk_get_physical_device_core_1_2_property_ext(ext, &core_1_2))
953          continue;
954       switch (ext->sType) {
955       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
956          VkPhysicalDevicePushDescriptorPropertiesKHR *properties =
957             (VkPhysicalDevicePushDescriptorPropertiesKHR *) ext;
958          properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;
959          break;
960       }
961       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: {
962          VkPhysicalDevicePointClippingProperties *properties =
963             (VkPhysicalDevicePointClippingProperties*)ext;
964          properties->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
965          break;
966       }
967       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {
968          VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *props =
969             (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *)ext;
970          if (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR) != 0)
971             props->maxVertexAttribDivisor = UINT32_MAX;
972          else
973             props->maxVertexAttribDivisor = 1;
974          break;
975       }
976       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT: {
977          VkPhysicalDeviceTransformFeedbackPropertiesEXT *properties =
978             (VkPhysicalDeviceTransformFeedbackPropertiesEXT*)ext;
979          properties->maxTransformFeedbackStreams = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_VERTEX_STREAMS);
980          properties->maxTransformFeedbackBuffers = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS);
981          properties->maxTransformFeedbackBufferSize = UINT32_MAX;
982          properties->maxTransformFeedbackStreamDataSize = 512;
983          properties->maxTransformFeedbackBufferDataSize = 512;
984          properties->maxTransformFeedbackBufferDataStride = 512;
985          properties->transformFeedbackQueries = true;
986          properties->transformFeedbackStreamsLinesTriangles = false;
987          properties->transformFeedbackRasterizationStreamSelect = false;
988          properties->transformFeedbackDraw = true;
989          break;
990       }
991       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT: {
992          VkPhysicalDeviceLineRasterizationPropertiesEXT *properties =
993             (VkPhysicalDeviceLineRasterizationPropertiesEXT *)ext;
994          properties->lineSubPixelPrecisionBits =
995             pdevice->pscreen->get_param(pdevice->pscreen,
996                                         PIPE_CAP_RASTERIZER_SUBPIXEL_BITS);
997          break;
998       }
999       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT: {
1000          VkPhysicalDeviceExternalMemoryHostPropertiesEXT *properties =
1001             (VkPhysicalDeviceExternalMemoryHostPropertiesEXT *)ext;
1002          properties->minImportedHostPointerAlignment = 4096;
1003          break;
1004       }
1005       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT: {
1006          VkPhysicalDeviceCustomBorderColorPropertiesEXT *properties =
1007             (VkPhysicalDeviceCustomBorderColorPropertiesEXT *)ext;
1008          properties->maxCustomBorderColorSamplers = 32 * 1024;
1009          break;
1010       }
1011       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT: {
1012          VkPhysicalDeviceProvokingVertexPropertiesEXT *properties =
1013             (VkPhysicalDeviceProvokingVertexPropertiesEXT*)ext;
1014          properties->provokingVertexModePerPipeline = true;
1015          properties->transformFeedbackPreservesTriangleFanProvokingVertex = true;
1016          break;
1017       }
1018       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT: {
1019          VkPhysicalDeviceMultiDrawPropertiesEXT *props = (VkPhysicalDeviceMultiDrawPropertiesEXT *)ext;
1020          props->maxMultiDrawCount = 2048;
1021          break;
1022       }
1023       default:
1024          break;
1025       }
1026    }
1027 }
1028 
lvp_get_physical_device_queue_family_properties(VkQueueFamilyProperties * pQueueFamilyProperties)1029 static void lvp_get_physical_device_queue_family_properties(
1030    VkQueueFamilyProperties*                    pQueueFamilyProperties)
1031 {
1032    *pQueueFamilyProperties = (VkQueueFamilyProperties) {
1033       .queueFlags = VK_QUEUE_GRAPHICS_BIT |
1034       VK_QUEUE_COMPUTE_BIT |
1035       VK_QUEUE_TRANSFER_BIT,
1036       .queueCount = 1,
1037       .timestampValidBits = 64,
1038       .minImageTransferGranularity = (VkExtent3D) { 1, 1, 1 },
1039    };
1040 }
1041 
lvp_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,uint32_t * pCount,VkQueueFamilyProperties * pQueueFamilyProperties)1042 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceQueueFamilyProperties(
1043    VkPhysicalDevice                            physicalDevice,
1044    uint32_t*                                   pCount,
1045    VkQueueFamilyProperties*                    pQueueFamilyProperties)
1046 {
1047    if (pQueueFamilyProperties == NULL) {
1048       *pCount = 1;
1049       return;
1050    }
1051 
1052    assert(*pCount >= 1);
1053    lvp_get_physical_device_queue_family_properties(pQueueFamilyProperties);
1054 }
1055 
lvp_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,uint32_t * pCount,VkQueueFamilyProperties2 * pQueueFamilyProperties)1056 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceQueueFamilyProperties2(
1057    VkPhysicalDevice                            physicalDevice,
1058    uint32_t*                                   pCount,
1059    VkQueueFamilyProperties2                   *pQueueFamilyProperties)
1060 {
1061    if (pQueueFamilyProperties == NULL) {
1062       *pCount = 1;
1063       return;
1064    }
1065 
1066    assert(*pCount >= 1);
1067    lvp_get_physical_device_queue_family_properties(&pQueueFamilyProperties->queueFamilyProperties);
1068 }
1069 
lvp_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,VkPhysicalDeviceMemoryProperties * pMemoryProperties)1070 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceMemoryProperties(
1071    VkPhysicalDevice                            physicalDevice,
1072    VkPhysicalDeviceMemoryProperties*           pMemoryProperties)
1073 {
1074    pMemoryProperties->memoryTypeCount = 1;
1075    pMemoryProperties->memoryTypes[0] = (VkMemoryType) {
1076       .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
1077       VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
1078       VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
1079       VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
1080       .heapIndex = 0,
1081    };
1082 
1083    pMemoryProperties->memoryHeapCount = 1;
1084    pMemoryProperties->memoryHeaps[0] = (VkMemoryHeap) {
1085       .size = 2ULL*1024*1024*1024,
1086       .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
1087    };
1088 }
1089 
lvp_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice,VkPhysicalDeviceMemoryProperties2 * pMemoryProperties)1090 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceMemoryProperties2(
1091    VkPhysicalDevice                            physicalDevice,
1092    VkPhysicalDeviceMemoryProperties2          *pMemoryProperties)
1093 {
1094    lvp_GetPhysicalDeviceMemoryProperties(physicalDevice,
1095                                          &pMemoryProperties->memoryProperties);
1096 }
1097 
1098 VKAPI_ATTR VkResult VKAPI_CALL
lvp_GetMemoryHostPointerPropertiesEXT(VkDevice _device,VkExternalMemoryHandleTypeFlagBits handleType,const void * pHostPointer,VkMemoryHostPointerPropertiesEXT * pMemoryHostPointerProperties)1099 lvp_GetMemoryHostPointerPropertiesEXT(
1100    VkDevice _device,
1101    VkExternalMemoryHandleTypeFlagBits handleType,
1102    const void *pHostPointer,
1103    VkMemoryHostPointerPropertiesEXT *pMemoryHostPointerProperties)
1104 {
1105    switch (handleType) {
1106    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: {
1107       pMemoryHostPointerProperties->memoryTypeBits = 1;
1108       return VK_SUCCESS;
1109    }
1110    default:
1111       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
1112    }
1113 }
1114 
lvp_GetInstanceProcAddr(VkInstance _instance,const char * pName)1115 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL lvp_GetInstanceProcAddr(
1116    VkInstance                                  _instance,
1117    const char*                                 pName)
1118 {
1119    LVP_FROM_HANDLE(lvp_instance, instance, _instance);
1120    return vk_instance_get_proc_addr(&instance->vk,
1121                                     &lvp_instance_entrypoints,
1122                                     pName);
1123 }
1124 
1125 /* Windows will use a dll definition file to avoid build errors. */
1126 #ifdef _WIN32
1127 #undef PUBLIC
1128 #define PUBLIC
1129 #endif
1130 
1131 /* The loader wants us to expose a second GetInstanceProcAddr function
1132  * to work around certain LD_PRELOAD issues seen in apps.
1133  */
1134 PUBLIC
1135 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(
1136    VkInstance                                  instance,
1137    const char*                                 pName);
1138 
1139 PUBLIC
vk_icdGetInstanceProcAddr(VkInstance instance,const char * pName)1140 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(
1141    VkInstance                                  instance,
1142    const char*                                 pName)
1143 {
1144    return lvp_GetInstanceProcAddr(instance, pName);
1145 }
1146 
1147 PUBLIC
1148 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(
1149    VkInstance                                  _instance,
1150    const char*                                 pName);
1151 
1152 PUBLIC
vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance,const char * pName)1153 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(
1154    VkInstance                                  _instance,
1155    const char*                                 pName)
1156 {
1157    LVP_FROM_HANDLE(lvp_instance, instance, _instance);
1158    return vk_instance_get_physical_device_proc_addr(&instance->vk, pName);
1159 }
1160 
1161 static void
set_last_fence(struct lvp_device * device,struct pipe_fence_handle * handle,uint64_t timeline)1162 set_last_fence(struct lvp_device *device, struct pipe_fence_handle *handle, uint64_t timeline)
1163 {
1164    simple_mtx_lock(&device->queue.last_lock);
1165    device->queue.last_fence_timeline = timeline;
1166    device->pscreen->fence_reference(device->pscreen, &device->queue.last_fence, handle);
1167    simple_mtx_unlock(&device->queue.last_lock);
1168 }
1169 
1170 static void
thread_flush(struct lvp_device * device,struct lvp_fence * fence,uint64_t timeline,unsigned num_timelines,struct lvp_semaphore_timeline ** timelines)1171 thread_flush(struct lvp_device *device, struct lvp_fence *fence, uint64_t timeline,
1172              unsigned num_timelines, struct lvp_semaphore_timeline **timelines)
1173 {
1174    struct pipe_fence_handle *handle = NULL;
1175    device->queue.ctx->flush(device->queue.ctx, &handle, 0);
1176    if (fence)
1177       fence->handle = handle;
1178    set_last_fence(device, handle, timeline);
1179    /* this is the array of signaling timeline semaphore links */
1180    for (unsigned i = 0; i < num_timelines; i++)
1181       timelines[i]->fence = handle;
1182 }
1183 
1184 /* get a new timeline link for creating a new signal event
1185  * sema->lock MUST be locked before calling
1186  */
1187 static struct lvp_semaphore_timeline *
get_semaphore_link(struct lvp_semaphore * sema)1188 get_semaphore_link(struct lvp_semaphore *sema)
1189 {
1190    if (!util_dynarray_num_elements(&sema->links, struct lvp_semaphore_timeline*)) {
1191 #define NUM_LINKS 50
1192       /* bucket allocate using the ralloc ctx because I like buckets */
1193       struct lvp_semaphore_timeline *link = ralloc_array(sema->mem, struct lvp_semaphore_timeline, NUM_LINKS);
1194       for (unsigned i = 0; i < NUM_LINKS; i++) {
1195          link[i].next = NULL;
1196          link[i].fence = NULL;
1197          util_dynarray_append(&sema->links, struct lvp_semaphore_timeline*, &link[i]);
1198       }
1199    }
1200    struct lvp_semaphore_timeline *tl = util_dynarray_pop(&sema->links, struct lvp_semaphore_timeline*);
1201    if (sema->timeline)
1202       sema->latest->next = tl;
1203    else
1204       sema->timeline = tl;
1205    sema->latest = tl;
1206    return tl;
1207 }
1208 
1209 /* prune any timeline links which are older than the current device timeline id
1210  * sema->lock MUST be locked before calling
1211  */
1212 static void
prune_semaphore_links(struct lvp_semaphore * sema,uint64_t timeline)1213 prune_semaphore_links(struct lvp_semaphore *sema, uint64_t timeline)
1214 {
1215    if (!timeline)
1216       /* zero isn't a valid id to prune with */
1217       return;
1218    struct lvp_semaphore_timeline *tl = sema->timeline;
1219    /* walk the timeline links and pop all the ones that are old */
1220    while (tl && ((tl->timeline <= timeline) || (tl->signal <= sema->current))) {
1221       struct lvp_semaphore_timeline *cur = tl;
1222       /* only update current timeline id if the update is monotonic */
1223       if (sema->current < tl->signal)
1224          sema->current = tl->signal;
1225       util_dynarray_append(&sema->links, struct lvp_semaphore_timeline*, tl);
1226       tl = tl->next;
1227       cur->next = NULL;
1228       cur->fence = NULL;
1229    }
1230    /* this is now the current timeline link */
1231    sema->timeline = tl;
1232 }
1233 
1234 /* find a timeline id that can be waited on to satisfy the signal condition
1235  * sema->lock MUST be locked before calling
1236  */
1237 static struct lvp_semaphore_timeline *
find_semaphore_timeline(struct lvp_semaphore * sema,uint64_t signal)1238 find_semaphore_timeline(struct lvp_semaphore *sema, uint64_t signal)
1239 {
1240    for (struct lvp_semaphore_timeline *tl = sema->timeline; tl; tl = tl->next) {
1241       if (tl->signal >= signal)
1242          return tl;
1243    }
1244    /* never submitted or is completed */
1245    return NULL;
1246 }
1247 
1248 struct timeline_wait {
1249    bool done;
1250    struct lvp_semaphore_timeline *tl;
1251 };
1252 
wait_semaphores(struct lvp_device * device,const VkSemaphoreWaitInfo * pWaitInfo,uint64_t timeout)1253 static VkResult wait_semaphores(struct lvp_device *device,
1254     const VkSemaphoreWaitInfo*                  pWaitInfo,
1255     uint64_t                                    timeout)
1256 {
1257    /* build array of timeline links to poll */
1258    VkResult ret = VK_TIMEOUT;
1259    bool any = (pWaitInfo->flags & VK_SEMAPHORE_WAIT_ANY_BIT) == VK_SEMAPHORE_WAIT_ANY_BIT;
1260    unsigned num_remaining = any ? 1 : pWaitInfo->semaphoreCount;
1261    /* just allocate an array for simplicity */
1262    struct timeline_wait *tl_array = calloc(pWaitInfo->semaphoreCount, sizeof(struct timeline_wait));
1263 
1264    int64_t abs_timeout = os_time_get_absolute_timeout(timeout);
1265    /* UINT64_MAX will always overflow, so special case it
1266     * otherwise, calculate ((timeout / num_semaphores) / 10) to allow waiting 10 times on every semaphore
1267     */
1268    uint64_t wait_interval = timeout == UINT64_MAX ? 5000 : timeout / pWaitInfo->semaphoreCount / 10;
1269    while (num_remaining) {
1270       for (unsigned i = 0; num_remaining && i < pWaitInfo->semaphoreCount; i++) {
1271          if (tl_array[i].done) //completed
1272             continue;
1273          if (timeout && timeout != UINT64_MAX) {
1274             /* update remaining timeout on every loop */
1275             int64_t time_ns = os_time_get_nano();
1276             if (abs_timeout <= time_ns)
1277                goto end;
1278             timeout = abs_timeout > time_ns ? abs_timeout - time_ns : 0;
1279          }
1280          const uint64_t waitval = pWaitInfo->pValues[i];
1281          LVP_FROM_HANDLE(lvp_semaphore, sema, pWaitInfo->pSemaphores[i]);
1282          if (sema->current >= waitval) {
1283             tl_array[i].done = true;
1284             num_remaining--;
1285             continue;
1286          }
1287          if (!tl_array[i].tl) {
1288             /* no timeline link was available yet: try to find one */
1289             simple_mtx_lock(&sema->lock);
1290             /* always prune first to update current timeline id */
1291             prune_semaphore_links(sema, device->queue.last_finished);
1292             tl_array[i].tl = find_semaphore_timeline(sema, waitval);
1293             if (timeout && !tl_array[i].tl) {
1294                /* still no timeline link available:
1295                 * try waiting on the conditional for a broadcast instead of melting the cpu
1296                 */
1297                mtx_lock(&sema->submit_lock);
1298                struct timespec t;
1299                t.tv_nsec = wait_interval % 1000000000u;
1300                t.tv_sec = (wait_interval - t.tv_nsec) / 1000000000u;
1301                cnd_timedwait(&sema->submit, &sema->submit_lock, &t);
1302                mtx_unlock(&sema->submit_lock);
1303                tl_array[i].tl = find_semaphore_timeline(sema, waitval);
1304             }
1305             simple_mtx_unlock(&sema->lock);
1306          }
1307          /* mark semaphore as done if:
1308           * - timeline id comparison passes
1309           * - fence for timeline id exists and completes
1310           */
1311          if (sema->current >= waitval ||
1312              (tl_array[i].tl &&
1313               tl_array[i].tl->fence &&
1314               device->pscreen->fence_finish(device->pscreen, NULL, tl_array[i].tl->fence, wait_interval))) {
1315             tl_array[i].done = true;
1316             num_remaining--;
1317          }
1318       }
1319       if (!timeout)
1320          break;
1321    }
1322    if (!num_remaining)
1323       ret = VK_SUCCESS;
1324 
1325 end:
1326    free(tl_array);
1327    return ret;
1328 }
1329 
1330 void
queue_thread_noop(void * data,void * gdata,int thread_index)1331 queue_thread_noop(void *data, void *gdata, int thread_index)
1332 {
1333    struct lvp_device *device = gdata;
1334    struct lvp_fence *fence = data;
1335    thread_flush(device, fence, fence->timeline, 0, NULL);
1336 }
1337 
1338 static void
queue_thread(void * data,void * gdata,int thread_index)1339 queue_thread(void *data, void *gdata, int thread_index)
1340 {
1341    struct lvp_queue_work *task = data;
1342    struct lvp_device *device = gdata;
1343    struct lvp_queue *queue = &device->queue;
1344 
1345    if (task->wait_count) {
1346       /* identical to WaitSemaphores */
1347       VkSemaphoreWaitInfo wait;
1348       wait.flags = 0; //wait on all semaphores
1349       wait.semaphoreCount = task->wait_count;
1350       wait.pSemaphores = task->waits;
1351       wait.pValues = task->wait_vals;
1352       //wait
1353       wait_semaphores(device, &wait, UINT64_MAX);
1354    }
1355 
1356    //execute
1357    for (unsigned i = 0; i < task->cmd_buffer_count; i++) {
1358       lvp_execute_cmds(queue->device, queue, task->cmd_buffers[i]);
1359    }
1360 
1361    thread_flush(device, task->fence, task->timeline, task->timeline_count, task->timelines);
1362    free(task);
1363 }
1364 
1365 static VkResult
lvp_queue_init(struct lvp_device * device,struct lvp_queue * queue,const VkDeviceQueueCreateInfo * create_info,uint32_t index_in_family)1366 lvp_queue_init(struct lvp_device *device, struct lvp_queue *queue,
1367                const VkDeviceQueueCreateInfo *create_info,
1368                uint32_t index_in_family)
1369 {
1370    VkResult result = vk_queue_init(&queue->vk, &device->vk, create_info,
1371                                    index_in_family);
1372    if (result != VK_SUCCESS)
1373       return result;
1374 
1375    queue->device = device;
1376 
1377    simple_mtx_init(&queue->last_lock, mtx_plain);
1378    queue->timeline = 0;
1379    queue->ctx = device->pscreen->context_create(device->pscreen, NULL, PIPE_CONTEXT_ROBUST_BUFFER_ACCESS);
1380    queue->cso = cso_create_context(queue->ctx, CSO_NO_VBUF);
1381    util_queue_init(&queue->queue, "lavapipe", 8, 1, UTIL_QUEUE_INIT_RESIZE_IF_FULL, device);
1382    p_atomic_set(&queue->count, 0);
1383 
1384    return VK_SUCCESS;
1385 }
1386 
1387 static void
lvp_queue_finish(struct lvp_queue * queue)1388 lvp_queue_finish(struct lvp_queue *queue)
1389 {
1390    util_queue_finish(&queue->queue);
1391    util_queue_destroy(&queue->queue);
1392 
1393    cso_destroy_context(queue->cso);
1394    queue->ctx->destroy(queue->ctx);
1395    simple_mtx_destroy(&queue->last_lock);
1396 
1397    vk_queue_finish(&queue->vk);
1398 }
1399 
lvp_CreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)1400 VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateDevice(
1401    VkPhysicalDevice                            physicalDevice,
1402    const VkDeviceCreateInfo*                   pCreateInfo,
1403    const VkAllocationCallbacks*                pAllocator,
1404    VkDevice*                                   pDevice)
1405 {
1406    fprintf(stderr, "WARNING: lavapipe is not a conformant vulkan implementation, testing use only.\n");
1407 
1408    LVP_FROM_HANDLE(lvp_physical_device, physical_device, physicalDevice);
1409    struct lvp_device *device;
1410    struct lvp_instance *instance = (struct lvp_instance *)physical_device->vk.instance;
1411 
1412    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO);
1413 
1414    device = vk_zalloc2(&physical_device->vk.instance->alloc, pAllocator,
1415                        sizeof(*device), 8,
1416                        VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1417    if (!device)
1418       return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1419 
1420    struct vk_device_dispatch_table dispatch_table;
1421    vk_device_dispatch_table_from_entrypoints(&dispatch_table,
1422       &lvp_device_entrypoints, true);
1423    vk_device_dispatch_table_from_entrypoints(&dispatch_table,
1424       &wsi_device_entrypoints, false);
1425    VkResult result = vk_device_init(&device->vk,
1426                                     &physical_device->vk,
1427                                     &dispatch_table, pCreateInfo,
1428                                     pAllocator);
1429    if (result != VK_SUCCESS) {
1430       vk_free(&device->vk.alloc, device);
1431       return result;
1432    }
1433 
1434    device->instance = (struct lvp_instance *)physical_device->vk.instance;
1435    device->physical_device = physical_device;
1436 
1437    device->pscreen = physical_device->pscreen;
1438 
1439    assert(pCreateInfo->queueCreateInfoCount == 1);
1440    assert(pCreateInfo->pQueueCreateInfos[0].queueFamilyIndex == 0);
1441    assert(pCreateInfo->pQueueCreateInfos[0].queueCount == 1);
1442    lvp_queue_init(device, &device->queue, pCreateInfo->pQueueCreateInfos, 0);
1443 
1444    *pDevice = lvp_device_to_handle(device);
1445 
1446    return VK_SUCCESS;
1447 
1448 }
1449 
lvp_DestroyDevice(VkDevice _device,const VkAllocationCallbacks * pAllocator)1450 VKAPI_ATTR void VKAPI_CALL lvp_DestroyDevice(
1451    VkDevice                                    _device,
1452    const VkAllocationCallbacks*                pAllocator)
1453 {
1454    LVP_FROM_HANDLE(lvp_device, device, _device);
1455 
1456    if (device->queue.last_fence)
1457       device->pscreen->fence_reference(device->pscreen, &device->queue.last_fence, NULL);
1458    lvp_queue_finish(&device->queue);
1459    vk_device_finish(&device->vk);
1460    vk_free(&device->vk.alloc, device);
1461 }
1462 
lvp_EnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)1463 VKAPI_ATTR VkResult VKAPI_CALL lvp_EnumerateInstanceExtensionProperties(
1464    const char*                                 pLayerName,
1465    uint32_t*                                   pPropertyCount,
1466    VkExtensionProperties*                      pProperties)
1467 {
1468    if (pLayerName)
1469       return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
1470 
1471    return vk_enumerate_instance_extension_properties(
1472       &lvp_instance_extensions_supported, pPropertyCount, pProperties);
1473 }
1474 
lvp_EnumerateInstanceLayerProperties(uint32_t * pPropertyCount,VkLayerProperties * pProperties)1475 VKAPI_ATTR VkResult VKAPI_CALL lvp_EnumerateInstanceLayerProperties(
1476    uint32_t*                                   pPropertyCount,
1477    VkLayerProperties*                          pProperties)
1478 {
1479    if (pProperties == NULL) {
1480       *pPropertyCount = 0;
1481       return VK_SUCCESS;
1482    }
1483 
1484    /* None supported at this time */
1485    return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
1486 }
1487 
lvp_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkLayerProperties * pProperties)1488 VKAPI_ATTR VkResult VKAPI_CALL lvp_EnumerateDeviceLayerProperties(
1489    VkPhysicalDevice                            physicalDevice,
1490    uint32_t*                                   pPropertyCount,
1491    VkLayerProperties*                          pProperties)
1492 {
1493    if (pProperties == NULL) {
1494       *pPropertyCount = 0;
1495       return VK_SUCCESS;
1496    }
1497 
1498    /* None supported at this time */
1499    return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
1500 }
1501 
lvp_QueueSubmit(VkQueue _queue,uint32_t submitCount,const VkSubmitInfo * pSubmits,VkFence _fence)1502 VKAPI_ATTR VkResult VKAPI_CALL lvp_QueueSubmit(
1503    VkQueue                                     _queue,
1504    uint32_t                                    submitCount,
1505    const VkSubmitInfo*                         pSubmits,
1506    VkFence                                     _fence)
1507 {
1508    LVP_FROM_HANDLE(lvp_queue, queue, _queue);
1509    LVP_FROM_HANDLE(lvp_fence, fence, _fence);
1510 
1511    /* each submit is a separate job to simplify/streamline semaphore waits */
1512    for (uint32_t i = 0; i < submitCount; i++) {
1513       uint64_t timeline = ++queue->timeline;
1514       struct lvp_queue_work *task = malloc(sizeof(struct lvp_queue_work) +
1515                                            pSubmits[i].commandBufferCount * sizeof(struct lvp_cmd_buffer *) +
1516                                            pSubmits[i].signalSemaphoreCount * sizeof(struct lvp_semaphore_timeline*) +
1517                                            pSubmits[i].waitSemaphoreCount * (sizeof(VkSemaphore) + sizeof(uint64_t)));
1518       task->cmd_buffer_count = pSubmits[i].commandBufferCount;
1519       task->timeline_count = pSubmits[i].signalSemaphoreCount;
1520       task->wait_count = pSubmits[i].waitSemaphoreCount;
1521       task->fence = fence;
1522       task->timeline = timeline;
1523       task->cmd_buffers = (struct lvp_cmd_buffer **)(task + 1);
1524       task->timelines = (struct lvp_semaphore_timeline**)((uint8_t*)task->cmd_buffers + pSubmits[i].commandBufferCount * sizeof(struct lvp_cmd_buffer *));
1525       task->waits = (VkSemaphore*)((uint8_t*)task->timelines + pSubmits[i].signalSemaphoreCount * sizeof(struct lvp_semaphore_timeline *));
1526       task->wait_vals = (uint64_t*)((uint8_t*)task->waits + pSubmits[i].waitSemaphoreCount * sizeof(VkSemaphore));
1527 
1528       unsigned c = 0;
1529       for (uint32_t j = 0; j < pSubmits[i].commandBufferCount; j++) {
1530          task->cmd_buffers[c++] = lvp_cmd_buffer_from_handle(pSubmits[i].pCommandBuffers[j]);
1531       }
1532       const VkTimelineSemaphoreSubmitInfo *info = vk_find_struct_const(pSubmits[i].pNext, TIMELINE_SEMAPHORE_SUBMIT_INFO);
1533       unsigned s = 0;
1534       for (unsigned j = 0; j < pSubmits[i].signalSemaphoreCount; j++) {
1535          LVP_FROM_HANDLE(lvp_semaphore, sema, pSubmits[i].pSignalSemaphores[j]);
1536          if (!sema->is_timeline) {
1537             /* non-timeline semaphores never matter to lavapipe */
1538             task->timeline_count--;
1539             continue;
1540          }
1541          simple_mtx_lock(&sema->lock);
1542          /* always prune first to make links available and update timeline id */
1543          prune_semaphore_links(sema, queue->last_finished);
1544          if (sema->current < info->pSignalSemaphoreValues[j]) {
1545             /* only signal semaphores if the new id is >= the current one */
1546             struct lvp_semaphore_timeline *tl = get_semaphore_link(sema);
1547             tl->signal = info->pSignalSemaphoreValues[j];
1548             tl->timeline = timeline;
1549             task->timelines[s] = tl;
1550             s++;
1551          } else
1552             task->timeline_count--;
1553          simple_mtx_unlock(&sema->lock);
1554       }
1555       unsigned w = 0;
1556       for (unsigned j = 0; j < pSubmits[i].waitSemaphoreCount; j++) {
1557          LVP_FROM_HANDLE(lvp_semaphore, sema, pSubmits[i].pWaitSemaphores[j]);
1558          if (!sema->is_timeline) {
1559             /* non-timeline semaphores never matter to lavapipe */
1560             task->wait_count--;
1561             continue;
1562          }
1563          simple_mtx_lock(&sema->lock);
1564          /* always prune first to update timeline id */
1565          prune_semaphore_links(sema, queue->last_finished);
1566          if (info->pWaitSemaphoreValues[j] &&
1567              pSubmits[i].pWaitDstStageMask && pSubmits[i].pWaitDstStageMask[j] &&
1568              sema->current < info->pWaitSemaphoreValues[j]) {
1569             /* only wait on semaphores if the new id is > the current one and a wait mask is set
1570              *
1571              * technically the mask could be used to check whether there's gfx/compute ops on a cmdbuf and no-op,
1572              * but probably that's not worth the complexity
1573              */
1574             task->waits[w] = pSubmits[i].pWaitSemaphores[j];
1575             task->wait_vals[w] = info->pWaitSemaphoreValues[j];
1576             w++;
1577          } else
1578             task->wait_count--;
1579          simple_mtx_unlock(&sema->lock);
1580       }
1581       if (fence && i == submitCount - 1) {
1582          /* u_queue fences should only be signaled for the last submit, as this is the one that
1583           * the vk fence represents
1584           */
1585          fence->timeline = timeline;
1586          util_queue_add_job(&queue->queue, task, &fence->fence, queue_thread, NULL, 0);
1587       } else
1588          util_queue_add_job(&queue->queue, task, NULL, queue_thread, NULL, 0);
1589    }
1590    if (!submitCount && fence) {
1591       /* special case where a fence is created to use as a synchronization point */
1592       fence->timeline = p_atomic_inc_return(&queue->timeline);
1593       util_queue_add_job(&queue->queue, fence, &fence->fence, queue_thread_noop, NULL, 0);
1594    }
1595 
1596    return VK_SUCCESS;
1597 }
1598 
lvp_QueueWaitIdle(VkQueue _queue)1599 VKAPI_ATTR VkResult VKAPI_CALL lvp_QueueWaitIdle(
1600    VkQueue                                     _queue)
1601 {
1602    LVP_FROM_HANDLE(lvp_queue, queue, _queue);
1603 
1604    util_queue_finish(&queue->queue);
1605    simple_mtx_lock(&queue->last_lock);
1606    uint64_t timeline = queue->last_fence_timeline;
1607    if (queue->last_fence) {
1608       queue->device->pscreen->fence_finish(queue->device->pscreen, NULL, queue->last_fence, PIPE_TIMEOUT_INFINITE);
1609       queue->device->pscreen->fence_reference(queue->device->pscreen, &queue->device->queue.last_fence, NULL);
1610       queue->last_finished = timeline;
1611    }
1612    simple_mtx_unlock(&queue->last_lock);
1613    return VK_SUCCESS;
1614 }
1615 
lvp_DeviceWaitIdle(VkDevice _device)1616 VKAPI_ATTR VkResult VKAPI_CALL lvp_DeviceWaitIdle(
1617    VkDevice                                    _device)
1618 {
1619    LVP_FROM_HANDLE(lvp_device, device, _device);
1620 
1621    lvp_QueueWaitIdle(lvp_queue_to_handle(&device->queue));
1622 
1623    return VK_SUCCESS;
1624 }
1625 
lvp_AllocateMemory(VkDevice _device,const VkMemoryAllocateInfo * pAllocateInfo,const VkAllocationCallbacks * pAllocator,VkDeviceMemory * pMem)1626 VKAPI_ATTR VkResult VKAPI_CALL lvp_AllocateMemory(
1627    VkDevice                                    _device,
1628    const VkMemoryAllocateInfo*                 pAllocateInfo,
1629    const VkAllocationCallbacks*                pAllocator,
1630    VkDeviceMemory*                             pMem)
1631 {
1632    LVP_FROM_HANDLE(lvp_device, device, _device);
1633    struct lvp_device_memory *mem;
1634    const VkExportMemoryAllocateInfo *export_info = NULL;
1635    const VkImportMemoryFdInfoKHR *import_info = NULL;
1636    const VkImportMemoryHostPointerInfoEXT *host_ptr_info = NULL;
1637    VkResult error = VK_ERROR_OUT_OF_DEVICE_MEMORY;
1638    assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
1639 
1640    if (pAllocateInfo->allocationSize == 0) {
1641       /* Apparently, this is allowed */
1642       *pMem = VK_NULL_HANDLE;
1643       return VK_SUCCESS;
1644    }
1645 
1646    vk_foreach_struct_const(ext, pAllocateInfo->pNext) {
1647       switch ((unsigned)ext->sType) {
1648       case VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT:
1649          host_ptr_info = (VkImportMemoryHostPointerInfoEXT*)ext;
1650          assert(host_ptr_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT);
1651          break;
1652       case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO:
1653          export_info = (VkExportMemoryAllocateInfo*)ext;
1654          assert(export_info->handleTypes == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT);
1655          break;
1656       case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR:
1657          import_info = (VkImportMemoryFdInfoKHR*)ext;
1658          assert(import_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT);
1659          break;
1660       default:
1661          break;
1662       }
1663    }
1664 
1665 #ifdef PIPE_MEMORY_FD
1666    if (import_info != NULL && import_info->fd < 0) {
1667       return vk_error(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
1668    }
1669 #endif
1670 
1671    mem = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*mem), 8,
1672                    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1673    if (mem == NULL)
1674       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1675 
1676    vk_object_base_init(&device->vk, &mem->base,
1677                        VK_OBJECT_TYPE_DEVICE_MEMORY);
1678 
1679    mem->memory_type = LVP_DEVICE_MEMORY_TYPE_DEFAULT;
1680    mem->backed_fd = -1;
1681 
1682    if (host_ptr_info) {
1683       mem->pmem = host_ptr_info->pHostPointer;
1684       mem->memory_type = LVP_DEVICE_MEMORY_TYPE_USER_PTR;
1685    }
1686 #ifdef PIPE_MEMORY_FD
1687    else if(import_info) {
1688       uint64_t size;
1689       if(!device->pscreen->import_memory_fd(device->pscreen, import_info->fd, &mem->pmem, &size)) {
1690          close(import_info->fd);
1691          error = VK_ERROR_INVALID_EXTERNAL_HANDLE;
1692          goto fail;
1693       }
1694       if(size < pAllocateInfo->allocationSize) {
1695          device->pscreen->free_memory_fd(device->pscreen, mem->pmem);
1696          close(import_info->fd);
1697          goto fail;
1698       }
1699       if (export_info) {
1700          mem->backed_fd = import_info->fd;
1701       }
1702       else {
1703          close(import_info->fd);
1704       }
1705       mem->memory_type = LVP_DEVICE_MEMORY_TYPE_OPAQUE_FD;
1706    }
1707    else if (export_info) {
1708       mem->pmem = device->pscreen->allocate_memory_fd(device->pscreen, pAllocateInfo->allocationSize, &mem->backed_fd);
1709       if (!mem->pmem || mem->backed_fd < 0) {
1710          goto fail;
1711       }
1712       mem->memory_type = LVP_DEVICE_MEMORY_TYPE_OPAQUE_FD;
1713    }
1714 #endif
1715    else {
1716       mem->pmem = device->pscreen->allocate_memory(device->pscreen, pAllocateInfo->allocationSize);
1717       if (!mem->pmem) {
1718          goto fail;
1719       }
1720    }
1721 
1722    mem->type_index = pAllocateInfo->memoryTypeIndex;
1723 
1724    *pMem = lvp_device_memory_to_handle(mem);
1725 
1726    return VK_SUCCESS;
1727 
1728 fail:
1729    vk_free2(&device->vk.alloc, pAllocator, mem);
1730    return vk_error(device, error);
1731 }
1732 
lvp_FreeMemory(VkDevice _device,VkDeviceMemory _mem,const VkAllocationCallbacks * pAllocator)1733 VKAPI_ATTR void VKAPI_CALL lvp_FreeMemory(
1734    VkDevice                                    _device,
1735    VkDeviceMemory                              _mem,
1736    const VkAllocationCallbacks*                pAllocator)
1737 {
1738    LVP_FROM_HANDLE(lvp_device, device, _device);
1739    LVP_FROM_HANDLE(lvp_device_memory, mem, _mem);
1740 
1741    if (mem == NULL)
1742       return;
1743 
1744    switch(mem->memory_type) {
1745    case LVP_DEVICE_MEMORY_TYPE_DEFAULT:
1746       device->pscreen->free_memory(device->pscreen, mem->pmem);
1747       break;
1748 #ifdef PIPE_MEMORY_FD
1749    case LVP_DEVICE_MEMORY_TYPE_OPAQUE_FD:
1750       device->pscreen->free_memory_fd(device->pscreen, mem->pmem);
1751       if(mem->backed_fd >= 0)
1752          close(mem->backed_fd);
1753       break;
1754 #endif
1755    case LVP_DEVICE_MEMORY_TYPE_USER_PTR:
1756    default:
1757       break;
1758    }
1759    vk_object_base_finish(&mem->base);
1760    vk_free2(&device->vk.alloc, pAllocator, mem);
1761 
1762 }
1763 
lvp_MapMemory(VkDevice _device,VkDeviceMemory _memory,VkDeviceSize offset,VkDeviceSize size,VkMemoryMapFlags flags,void ** ppData)1764 VKAPI_ATTR VkResult VKAPI_CALL lvp_MapMemory(
1765    VkDevice                                    _device,
1766    VkDeviceMemory                              _memory,
1767    VkDeviceSize                                offset,
1768    VkDeviceSize                                size,
1769    VkMemoryMapFlags                            flags,
1770    void**                                      ppData)
1771 {
1772    LVP_FROM_HANDLE(lvp_device, device, _device);
1773    LVP_FROM_HANDLE(lvp_device_memory, mem, _memory);
1774    void *map;
1775    if (mem == NULL) {
1776       *ppData = NULL;
1777       return VK_SUCCESS;
1778    }
1779 
1780    map = device->pscreen->map_memory(device->pscreen, mem->pmem);
1781 
1782    *ppData = (char *)map + offset;
1783    return VK_SUCCESS;
1784 }
1785 
lvp_UnmapMemory(VkDevice _device,VkDeviceMemory _memory)1786 VKAPI_ATTR void VKAPI_CALL lvp_UnmapMemory(
1787    VkDevice                                    _device,
1788    VkDeviceMemory                              _memory)
1789 {
1790    LVP_FROM_HANDLE(lvp_device, device, _device);
1791    LVP_FROM_HANDLE(lvp_device_memory, mem, _memory);
1792 
1793    if (mem == NULL)
1794       return;
1795 
1796    device->pscreen->unmap_memory(device->pscreen, mem->pmem);
1797 }
1798 
lvp_FlushMappedMemoryRanges(VkDevice _device,uint32_t memoryRangeCount,const VkMappedMemoryRange * pMemoryRanges)1799 VKAPI_ATTR VkResult VKAPI_CALL lvp_FlushMappedMemoryRanges(
1800    VkDevice                                    _device,
1801    uint32_t                                    memoryRangeCount,
1802    const VkMappedMemoryRange*                  pMemoryRanges)
1803 {
1804    return VK_SUCCESS;
1805 }
1806 
lvp_InvalidateMappedMemoryRanges(VkDevice _device,uint32_t memoryRangeCount,const VkMappedMemoryRange * pMemoryRanges)1807 VKAPI_ATTR VkResult VKAPI_CALL lvp_InvalidateMappedMemoryRanges(
1808    VkDevice                                    _device,
1809    uint32_t                                    memoryRangeCount,
1810    const VkMappedMemoryRange*                  pMemoryRanges)
1811 {
1812    return VK_SUCCESS;
1813 }
1814 
lvp_GetBufferMemoryRequirements(VkDevice device,VkBuffer _buffer,VkMemoryRequirements * pMemoryRequirements)1815 VKAPI_ATTR void VKAPI_CALL lvp_GetBufferMemoryRequirements(
1816    VkDevice                                    device,
1817    VkBuffer                                    _buffer,
1818    VkMemoryRequirements*                       pMemoryRequirements)
1819 {
1820    LVP_FROM_HANDLE(lvp_buffer, buffer, _buffer);
1821 
1822    /* The Vulkan spec (git aaed022) says:
1823     *
1824     *    memoryTypeBits is a bitfield and contains one bit set for every
1825     *    supported memory type for the resource. The bit `1<<i` is set if and
1826     *    only if the memory type `i` in the VkPhysicalDeviceMemoryProperties
1827     *    structure for the physical device is supported.
1828     *
1829     * We support exactly one memory type.
1830     */
1831    pMemoryRequirements->memoryTypeBits = 1;
1832 
1833    pMemoryRequirements->size = buffer->total_size;
1834    pMemoryRequirements->alignment = 64;
1835 }
1836 
lvp_GetBufferMemoryRequirements2(VkDevice device,const VkBufferMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)1837 VKAPI_ATTR void VKAPI_CALL lvp_GetBufferMemoryRequirements2(
1838    VkDevice                                     device,
1839    const VkBufferMemoryRequirementsInfo2       *pInfo,
1840    VkMemoryRequirements2                       *pMemoryRequirements)
1841 {
1842    lvp_GetBufferMemoryRequirements(device, pInfo->buffer,
1843                                    &pMemoryRequirements->memoryRequirements);
1844    vk_foreach_struct(ext, pMemoryRequirements->pNext) {
1845       switch (ext->sType) {
1846       case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
1847          VkMemoryDedicatedRequirements *req =
1848             (VkMemoryDedicatedRequirements *) ext;
1849          req->requiresDedicatedAllocation = false;
1850          req->prefersDedicatedAllocation = req->requiresDedicatedAllocation;
1851          break;
1852       }
1853       default:
1854          break;
1855       }
1856    }
1857 }
1858 
lvp_GetImageMemoryRequirements(VkDevice device,VkImage _image,VkMemoryRequirements * pMemoryRequirements)1859 VKAPI_ATTR void VKAPI_CALL lvp_GetImageMemoryRequirements(
1860    VkDevice                                    device,
1861    VkImage                                     _image,
1862    VkMemoryRequirements*                       pMemoryRequirements)
1863 {
1864    LVP_FROM_HANDLE(lvp_image, image, _image);
1865    pMemoryRequirements->memoryTypeBits = 1;
1866 
1867    pMemoryRequirements->size = image->size;
1868    pMemoryRequirements->alignment = image->alignment;
1869 }
1870 
lvp_GetImageMemoryRequirements2(VkDevice device,const VkImageMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)1871 VKAPI_ATTR void VKAPI_CALL lvp_GetImageMemoryRequirements2(
1872    VkDevice                                    device,
1873    const VkImageMemoryRequirementsInfo2       *pInfo,
1874    VkMemoryRequirements2                      *pMemoryRequirements)
1875 {
1876    lvp_GetImageMemoryRequirements(device, pInfo->image,
1877                                   &pMemoryRequirements->memoryRequirements);
1878 
1879    vk_foreach_struct(ext, pMemoryRequirements->pNext) {
1880       switch (ext->sType) {
1881       case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
1882          VkMemoryDedicatedRequirements *req =
1883             (VkMemoryDedicatedRequirements *) ext;
1884          req->requiresDedicatedAllocation = false;
1885          req->prefersDedicatedAllocation = req->requiresDedicatedAllocation;
1886          break;
1887       }
1888       default:
1889          break;
1890       }
1891    }
1892 }
1893 
lvp_GetImageSparseMemoryRequirements(VkDevice device,VkImage image,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements * pSparseMemoryRequirements)1894 VKAPI_ATTR void VKAPI_CALL lvp_GetImageSparseMemoryRequirements(
1895    VkDevice                                    device,
1896    VkImage                                     image,
1897    uint32_t*                                   pSparseMemoryRequirementCount,
1898    VkSparseImageMemoryRequirements*            pSparseMemoryRequirements)
1899 {
1900    stub();
1901 }
1902 
lvp_GetImageSparseMemoryRequirements2(VkDevice device,const VkImageSparseMemoryRequirementsInfo2 * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)1903 VKAPI_ATTR void VKAPI_CALL lvp_GetImageSparseMemoryRequirements2(
1904    VkDevice                                    device,
1905    const VkImageSparseMemoryRequirementsInfo2* pInfo,
1906    uint32_t* pSparseMemoryRequirementCount,
1907    VkSparseImageMemoryRequirements2* pSparseMemoryRequirements)
1908 {
1909    stub();
1910 }
1911 
lvp_GetDeviceMemoryCommitment(VkDevice device,VkDeviceMemory memory,VkDeviceSize * pCommittedMemoryInBytes)1912 VKAPI_ATTR void VKAPI_CALL lvp_GetDeviceMemoryCommitment(
1913    VkDevice                                    device,
1914    VkDeviceMemory                              memory,
1915    VkDeviceSize*                               pCommittedMemoryInBytes)
1916 {
1917    *pCommittedMemoryInBytes = 0;
1918 }
1919 
lvp_BindBufferMemory2(VkDevice _device,uint32_t bindInfoCount,const VkBindBufferMemoryInfo * pBindInfos)1920 VKAPI_ATTR VkResult VKAPI_CALL lvp_BindBufferMemory2(VkDevice _device,
1921                                uint32_t bindInfoCount,
1922                                const VkBindBufferMemoryInfo *pBindInfos)
1923 {
1924    LVP_FROM_HANDLE(lvp_device, device, _device);
1925    for (uint32_t i = 0; i < bindInfoCount; ++i) {
1926       LVP_FROM_HANDLE(lvp_device_memory, mem, pBindInfos[i].memory);
1927       LVP_FROM_HANDLE(lvp_buffer, buffer, pBindInfos[i].buffer);
1928 
1929       buffer->pmem = mem->pmem;
1930       device->pscreen->resource_bind_backing(device->pscreen,
1931                                              buffer->bo,
1932                                              mem->pmem,
1933                                              pBindInfos[i].memoryOffset);
1934    }
1935    return VK_SUCCESS;
1936 }
1937 
lvp_BindImageMemory2(VkDevice _device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)1938 VKAPI_ATTR VkResult VKAPI_CALL lvp_BindImageMemory2(VkDevice _device,
1939                               uint32_t bindInfoCount,
1940                               const VkBindImageMemoryInfo *pBindInfos)
1941 {
1942    LVP_FROM_HANDLE(lvp_device, device, _device);
1943    for (uint32_t i = 0; i < bindInfoCount; ++i) {
1944       const VkBindImageMemoryInfo *bind_info = &pBindInfos[i];
1945       LVP_FROM_HANDLE(lvp_device_memory, mem, bind_info->memory);
1946       LVP_FROM_HANDLE(lvp_image, image, bind_info->image);
1947       bool did_bind = false;
1948 
1949       vk_foreach_struct_const(s, bind_info->pNext) {
1950          switch (s->sType) {
1951          case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR: {
1952             const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
1953                (const VkBindImageMemorySwapchainInfoKHR *) s;
1954             struct lvp_image *swapchain_image =
1955                lvp_swapchain_get_image(swapchain_info->swapchain,
1956                                        swapchain_info->imageIndex);
1957 
1958             image->pmem = swapchain_image->pmem;
1959             image->memory_offset = swapchain_image->memory_offset;
1960             device->pscreen->resource_bind_backing(device->pscreen,
1961                                                    image->bo,
1962                                                    image->pmem,
1963                                                    image->memory_offset);
1964             did_bind = true;
1965          }
1966          default:
1967             break;
1968          }
1969       }
1970 
1971       if (!did_bind) {
1972          if (!device->pscreen->resource_bind_backing(device->pscreen,
1973                                                      image->bo,
1974                                                      mem->pmem,
1975                                                      bind_info->memoryOffset)) {
1976             /* This is probably caused by the texture being too large, so let's
1977              * report this as the *closest* allowed error-code. It's not ideal,
1978              * but it's unlikely that anyone will care too much.
1979              */
1980             return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
1981          }
1982          image->pmem = mem->pmem;
1983          image->memory_offset = bind_info->memoryOffset;
1984       }
1985    }
1986    return VK_SUCCESS;
1987 }
1988 
1989 #ifdef PIPE_MEMORY_FD
1990 
1991 VkResult
lvp_GetMemoryFdKHR(VkDevice _device,const VkMemoryGetFdInfoKHR * pGetFdInfo,int * pFD)1992 lvp_GetMemoryFdKHR(VkDevice _device, const VkMemoryGetFdInfoKHR *pGetFdInfo, int *pFD)
1993 {
1994    LVP_FROM_HANDLE(lvp_device_memory, memory, pGetFdInfo->memory);
1995 
1996    assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);
1997    assert(pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT);
1998 
1999    *pFD = dup(memory->backed_fd);
2000    assert(*pFD >= 0);
2001    return VK_SUCCESS;
2002 }
2003 
2004 VkResult
lvp_GetMemoryFdPropertiesKHR(VkDevice _device,VkExternalMemoryHandleTypeFlagBits handleType,int fd,VkMemoryFdPropertiesKHR * pMemoryFdProperties)2005 lvp_GetMemoryFdPropertiesKHR(VkDevice _device,
2006                              VkExternalMemoryHandleTypeFlagBits handleType,
2007                              int fd,
2008                              VkMemoryFdPropertiesKHR *pMemoryFdProperties)
2009 {
2010    LVP_FROM_HANDLE(lvp_device, device, _device);
2011 
2012    assert(pMemoryFdProperties->sType == VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR);
2013 
2014    if(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) {
2015       // There is only one memoryType so select this one
2016       pMemoryFdProperties->memoryTypeBits = 1;
2017    }
2018    else
2019       return vk_error(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
2020    return VK_SUCCESS;
2021 }
2022 
2023 #endif
2024 
lvp_QueueBindSparse(VkQueue queue,uint32_t bindInfoCount,const VkBindSparseInfo * pBindInfo,VkFence fence)2025 VKAPI_ATTR VkResult VKAPI_CALL lvp_QueueBindSparse(
2026    VkQueue                                     queue,
2027    uint32_t                                    bindInfoCount,
2028    const VkBindSparseInfo*                     pBindInfo,
2029    VkFence                                     fence)
2030 {
2031    stub_return(VK_ERROR_INCOMPATIBLE_DRIVER);
2032 }
2033 
2034 
lvp_CreateFence(VkDevice _device,const VkFenceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkFence * pFence)2035 VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateFence(
2036    VkDevice                                    _device,
2037    const VkFenceCreateInfo*                    pCreateInfo,
2038    const VkAllocationCallbacks*                pAllocator,
2039    VkFence*                                    pFence)
2040 {
2041    LVP_FROM_HANDLE(lvp_device, device, _device);
2042    struct lvp_fence *fence;
2043 
2044    fence = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*fence), 8,
2045                      VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2046    if (fence == NULL)
2047       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2048    vk_object_base_init(&device->vk, &fence->base, VK_OBJECT_TYPE_FENCE);
2049    util_queue_fence_init(&fence->fence);
2050    fence->signalled = (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) == VK_FENCE_CREATE_SIGNALED_BIT;
2051 
2052    fence->handle = NULL;
2053    fence->timeline = 0;
2054    *pFence = lvp_fence_to_handle(fence);
2055 
2056    return VK_SUCCESS;
2057 }
2058 
lvp_DestroyFence(VkDevice _device,VkFence _fence,const VkAllocationCallbacks * pAllocator)2059 VKAPI_ATTR void VKAPI_CALL lvp_DestroyFence(
2060    VkDevice                                    _device,
2061    VkFence                                     _fence,
2062    const VkAllocationCallbacks*                pAllocator)
2063 {
2064    LVP_FROM_HANDLE(lvp_device, device, _device);
2065    LVP_FROM_HANDLE(lvp_fence, fence, _fence);
2066 
2067    if (!_fence)
2068       return;
2069    /* evade annoying destroy assert */
2070    util_queue_fence_init(&fence->fence);
2071    util_queue_fence_destroy(&fence->fence);
2072    if (fence->handle)
2073       device->pscreen->fence_reference(device->pscreen, &fence->handle, NULL);
2074 
2075    vk_object_base_finish(&fence->base);
2076    vk_free2(&device->vk.alloc, pAllocator, fence);
2077 }
2078 
lvp_ResetFences(VkDevice _device,uint32_t fenceCount,const VkFence * pFences)2079 VKAPI_ATTR VkResult VKAPI_CALL lvp_ResetFences(
2080    VkDevice                                    _device,
2081    uint32_t                                    fenceCount,
2082    const VkFence*                              pFences)
2083 {
2084    LVP_FROM_HANDLE(lvp_device, device, _device);
2085    for (unsigned i = 0; i < fenceCount; i++) {
2086       struct lvp_fence *fence = lvp_fence_from_handle(pFences[i]);
2087       /* ensure u_queue doesn't explode when submitting a completed lvp_fence
2088        * which has not yet signalled its u_queue fence
2089        */
2090       util_queue_fence_wait(&fence->fence);
2091 
2092       if (fence->handle) {
2093          simple_mtx_lock(&device->queue.last_lock);
2094          if (fence->handle == device->queue.last_fence)
2095             device->pscreen->fence_reference(device->pscreen, &device->queue.last_fence, NULL);
2096          simple_mtx_unlock(&device->queue.last_lock);
2097          device->pscreen->fence_reference(device->pscreen, &fence->handle, NULL);
2098       }
2099       fence->signalled = false;
2100    }
2101    return VK_SUCCESS;
2102 }
2103 
lvp_GetFenceStatus(VkDevice _device,VkFence _fence)2104 VKAPI_ATTR VkResult VKAPI_CALL lvp_GetFenceStatus(
2105    VkDevice                                    _device,
2106    VkFence                                     _fence)
2107 {
2108    LVP_FROM_HANDLE(lvp_device, device, _device);
2109    LVP_FROM_HANDLE(lvp_fence, fence, _fence);
2110 
2111    if (fence->signalled)
2112       return VK_SUCCESS;
2113 
2114    if (!util_queue_fence_is_signalled(&fence->fence) ||
2115        !fence->handle ||
2116        !device->pscreen->fence_finish(device->pscreen, NULL, fence->handle, 0))
2117       return VK_NOT_READY;
2118 
2119    fence->signalled = true;
2120    simple_mtx_lock(&device->queue.last_lock);
2121    if (fence->handle == device->queue.last_fence) {
2122       device->pscreen->fence_reference(device->pscreen, &device->queue.last_fence, NULL);
2123       device->queue.last_finished = fence->timeline;
2124    }
2125    simple_mtx_unlock(&device->queue.last_lock);
2126    return VK_SUCCESS;
2127 }
2128 
lvp_CreateFramebuffer(VkDevice _device,const VkFramebufferCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkFramebuffer * pFramebuffer)2129 VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateFramebuffer(
2130    VkDevice                                    _device,
2131    const VkFramebufferCreateInfo*              pCreateInfo,
2132    const VkAllocationCallbacks*                pAllocator,
2133    VkFramebuffer*                              pFramebuffer)
2134 {
2135    LVP_FROM_HANDLE(lvp_device, device, _device);
2136    struct lvp_framebuffer *framebuffer;
2137    const VkFramebufferAttachmentsCreateInfo *imageless_create_info =
2138       vk_find_struct_const(pCreateInfo->pNext,
2139                            FRAMEBUFFER_ATTACHMENTS_CREATE_INFO);
2140 
2141    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
2142 
2143    size_t size = sizeof(*framebuffer);
2144 
2145    if (!imageless_create_info)
2146       size += sizeof(struct lvp_image_view *) * pCreateInfo->attachmentCount;
2147    framebuffer = vk_alloc2(&device->vk.alloc, pAllocator, size, 8,
2148                            VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2149    if (framebuffer == NULL)
2150       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2151 
2152    vk_object_base_init(&device->vk, &framebuffer->base,
2153                        VK_OBJECT_TYPE_FRAMEBUFFER);
2154 
2155    if (!imageless_create_info) {
2156       framebuffer->attachment_count = pCreateInfo->attachmentCount;
2157       for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
2158          VkImageView _iview = pCreateInfo->pAttachments[i];
2159          framebuffer->attachments[i] = lvp_image_view_from_handle(_iview);
2160       }
2161    }
2162 
2163    framebuffer->width = pCreateInfo->width;
2164    framebuffer->height = pCreateInfo->height;
2165    framebuffer->layers = pCreateInfo->layers;
2166    framebuffer->imageless = !!imageless_create_info;
2167 
2168    *pFramebuffer = lvp_framebuffer_to_handle(framebuffer);
2169 
2170    return VK_SUCCESS;
2171 }
2172 
lvp_DestroyFramebuffer(VkDevice _device,VkFramebuffer _fb,const VkAllocationCallbacks * pAllocator)2173 VKAPI_ATTR void VKAPI_CALL lvp_DestroyFramebuffer(
2174    VkDevice                                    _device,
2175    VkFramebuffer                               _fb,
2176    const VkAllocationCallbacks*                pAllocator)
2177 {
2178    LVP_FROM_HANDLE(lvp_device, device, _device);
2179    LVP_FROM_HANDLE(lvp_framebuffer, fb, _fb);
2180 
2181    if (!fb)
2182       return;
2183    vk_object_base_finish(&fb->base);
2184    vk_free2(&device->vk.alloc, pAllocator, fb);
2185 }
2186 
lvp_WaitForFences(VkDevice _device,uint32_t fenceCount,const VkFence * pFences,VkBool32 waitAll,uint64_t timeout)2187 VKAPI_ATTR VkResult VKAPI_CALL lvp_WaitForFences(
2188    VkDevice                                    _device,
2189    uint32_t                                    fenceCount,
2190    const VkFence*                              pFences,
2191    VkBool32                                    waitAll,
2192    uint64_t                                    timeout)
2193 {
2194    LVP_FROM_HANDLE(lvp_device, device, _device);
2195    struct lvp_fence *fence = NULL;
2196 
2197    /* lavapipe is completely synchronous, so only one fence needs to be waited on */
2198    if (waitAll) {
2199       /* find highest timeline id */
2200       for (unsigned i = 0; i < fenceCount; i++) {
2201          struct lvp_fence *f = lvp_fence_from_handle(pFences[i]);
2202 
2203          /* this is an unsubmitted fence: immediately bail out */
2204          if (!f->timeline && !f->signalled)
2205             return VK_TIMEOUT;
2206          if (!fence || f->timeline > fence->timeline)
2207             fence = f;
2208       }
2209    } else {
2210       /* find lowest timeline id */
2211       for (unsigned i = 0; i < fenceCount; i++) {
2212          struct lvp_fence *f = lvp_fence_from_handle(pFences[i]);
2213          if (f->signalled)
2214             return VK_SUCCESS;
2215          if (f->timeline && (!fence || f->timeline < fence->timeline))
2216             fence = f;
2217       }
2218    }
2219    if (!fence)
2220       return VK_TIMEOUT;
2221    if (fence->signalled)
2222       return VK_SUCCESS;
2223 
2224    if (!util_queue_fence_is_signalled(&fence->fence)) {
2225       int64_t abs_timeout = os_time_get_absolute_timeout(timeout);
2226       if (!util_queue_fence_wait_timeout(&fence->fence, abs_timeout))
2227          return VK_TIMEOUT;
2228 
2229       int64_t time_ns = os_time_get_nano();
2230       timeout = abs_timeout > time_ns ? abs_timeout - time_ns : 0;
2231    }
2232 
2233    if (!fence->handle ||
2234        !device->pscreen->fence_finish(device->pscreen, NULL, fence->handle, timeout))
2235       return VK_TIMEOUT;
2236    simple_mtx_lock(&device->queue.last_lock);
2237    if (fence->handle == device->queue.last_fence) {
2238       device->pscreen->fence_reference(device->pscreen, &device->queue.last_fence, NULL);
2239       device->queue.last_finished = fence->timeline;
2240    }
2241    simple_mtx_unlock(&device->queue.last_lock);
2242    fence->signalled = true;
2243    return VK_SUCCESS;
2244 }
2245 
lvp_CreateSemaphore(VkDevice _device,const VkSemaphoreCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSemaphore * pSemaphore)2246 VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateSemaphore(
2247    VkDevice                                    _device,
2248    const VkSemaphoreCreateInfo*                pCreateInfo,
2249    const VkAllocationCallbacks*                pAllocator,
2250    VkSemaphore*                                pSemaphore)
2251 {
2252    LVP_FROM_HANDLE(lvp_device, device, _device);
2253 
2254    struct lvp_semaphore *sema = vk_alloc2(&device->vk.alloc, pAllocator,
2255                                           sizeof(*sema), 8,
2256                                           VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2257 
2258    if (!sema)
2259       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2260    vk_object_base_init(&device->vk, &sema->base,
2261                        VK_OBJECT_TYPE_SEMAPHORE);
2262 
2263    const VkSemaphoreTypeCreateInfo *info = vk_find_struct_const(pCreateInfo->pNext, SEMAPHORE_TYPE_CREATE_INFO);
2264    sema->is_timeline = info && info->semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE;
2265    if (sema->is_timeline) {
2266       sema->is_timeline = true;
2267       sema->timeline = NULL;
2268       sema->current = info->initialValue;
2269       sema->mem = ralloc_context(NULL);
2270       util_dynarray_init(&sema->links, sema->mem);
2271       simple_mtx_init(&sema->lock, mtx_plain);
2272       mtx_init(&sema->submit_lock, mtx_plain);
2273       cnd_init(&sema->submit);
2274    }
2275 
2276    *pSemaphore = lvp_semaphore_to_handle(sema);
2277 
2278    return VK_SUCCESS;
2279 }
2280 
lvp_DestroySemaphore(VkDevice _device,VkSemaphore _semaphore,const VkAllocationCallbacks * pAllocator)2281 VKAPI_ATTR void VKAPI_CALL lvp_DestroySemaphore(
2282    VkDevice                                    _device,
2283    VkSemaphore                                 _semaphore,
2284    const VkAllocationCallbacks*                pAllocator)
2285 {
2286    LVP_FROM_HANDLE(lvp_device, device, _device);
2287    LVP_FROM_HANDLE(lvp_semaphore, sema, _semaphore);
2288 
2289    if (!_semaphore)
2290       return;
2291    if (sema->is_timeline) {
2292       ralloc_free(sema->mem);
2293       simple_mtx_destroy(&sema->lock);
2294       mtx_destroy(&sema->submit_lock);
2295       cnd_destroy(&sema->submit);
2296    }
2297    vk_object_base_finish(&sema->base);
2298    vk_free2(&device->vk.alloc, pAllocator, sema);
2299 }
2300 
lvp_WaitSemaphores(VkDevice _device,const VkSemaphoreWaitInfo * pWaitInfo,uint64_t timeout)2301 VKAPI_ATTR VkResult VKAPI_CALL lvp_WaitSemaphores(
2302     VkDevice                                    _device,
2303     const VkSemaphoreWaitInfo*                  pWaitInfo,
2304     uint64_t                                    timeout)
2305 {
2306    LVP_FROM_HANDLE(lvp_device, device, _device);
2307    /* same mechanism as used by queue submit */
2308    return wait_semaphores(device, pWaitInfo, timeout);
2309 }
2310 
lvp_GetSemaphoreCounterValue(VkDevice _device,VkSemaphore _semaphore,uint64_t * pValue)2311 VKAPI_ATTR VkResult VKAPI_CALL lvp_GetSemaphoreCounterValue(
2312     VkDevice                                    _device,
2313     VkSemaphore                                 _semaphore,
2314     uint64_t*                                   pValue)
2315 {
2316    LVP_FROM_HANDLE(lvp_device, device, _device);
2317    LVP_FROM_HANDLE(lvp_semaphore, sema, _semaphore);
2318    simple_mtx_lock(&sema->lock);
2319    prune_semaphore_links(sema, device->queue.last_finished);
2320    *pValue = sema->current;
2321    simple_mtx_unlock(&sema->lock);
2322    return VK_SUCCESS;
2323 }
2324 
lvp_SignalSemaphore(VkDevice _device,const VkSemaphoreSignalInfo * pSignalInfo)2325 VKAPI_ATTR VkResult VKAPI_CALL lvp_SignalSemaphore(
2326     VkDevice                                    _device,
2327     const VkSemaphoreSignalInfo*                pSignalInfo)
2328 {
2329    LVP_FROM_HANDLE(lvp_device, device, _device);
2330    LVP_FROM_HANDLE(lvp_semaphore, sema, pSignalInfo->semaphore);
2331 
2332    /* try to remain monotonic */
2333    if (sema->current < pSignalInfo->value)
2334       sema->current = pSignalInfo->value;
2335    cnd_broadcast(&sema->submit);
2336    simple_mtx_lock(&sema->lock);
2337    prune_semaphore_links(sema, device->queue.last_finished);
2338    simple_mtx_unlock(&sema->lock);
2339    return VK_SUCCESS;
2340 }
2341 
lvp_CreateEvent(VkDevice _device,const VkEventCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkEvent * pEvent)2342 VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateEvent(
2343    VkDevice                                    _device,
2344    const VkEventCreateInfo*                    pCreateInfo,
2345    const VkAllocationCallbacks*                pAllocator,
2346    VkEvent*                                    pEvent)
2347 {
2348    LVP_FROM_HANDLE(lvp_device, device, _device);
2349    struct lvp_event *event = vk_alloc2(&device->vk.alloc, pAllocator,
2350                                        sizeof(*event), 8,
2351                                        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2352 
2353    if (!event)
2354       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2355 
2356    vk_object_base_init(&device->vk, &event->base, VK_OBJECT_TYPE_EVENT);
2357    *pEvent = lvp_event_to_handle(event);
2358    event->event_storage = 0;
2359 
2360    return VK_SUCCESS;
2361 }
2362 
lvp_DestroyEvent(VkDevice _device,VkEvent _event,const VkAllocationCallbacks * pAllocator)2363 VKAPI_ATTR void VKAPI_CALL lvp_DestroyEvent(
2364    VkDevice                                    _device,
2365    VkEvent                                     _event,
2366    const VkAllocationCallbacks*                pAllocator)
2367 {
2368    LVP_FROM_HANDLE(lvp_device, device, _device);
2369    LVP_FROM_HANDLE(lvp_event, event, _event);
2370 
2371    if (!event)
2372       return;
2373 
2374    vk_object_base_finish(&event->base);
2375    vk_free2(&device->vk.alloc, pAllocator, event);
2376 }
2377 
lvp_GetEventStatus(VkDevice _device,VkEvent _event)2378 VKAPI_ATTR VkResult VKAPI_CALL lvp_GetEventStatus(
2379    VkDevice                                    _device,
2380    VkEvent                                     _event)
2381 {
2382    LVP_FROM_HANDLE(lvp_event, event, _event);
2383    if (event->event_storage == 1)
2384       return VK_EVENT_SET;
2385    return VK_EVENT_RESET;
2386 }
2387 
lvp_SetEvent(VkDevice _device,VkEvent _event)2388 VKAPI_ATTR VkResult VKAPI_CALL lvp_SetEvent(
2389    VkDevice                                    _device,
2390    VkEvent                                     _event)
2391 {
2392    LVP_FROM_HANDLE(lvp_event, event, _event);
2393    event->event_storage = 1;
2394 
2395    return VK_SUCCESS;
2396 }
2397 
lvp_ResetEvent(VkDevice _device,VkEvent _event)2398 VKAPI_ATTR VkResult VKAPI_CALL lvp_ResetEvent(
2399    VkDevice                                    _device,
2400    VkEvent                                     _event)
2401 {
2402    LVP_FROM_HANDLE(lvp_event, event, _event);
2403    event->event_storage = 0;
2404 
2405    return VK_SUCCESS;
2406 }
2407 
lvp_CreateSampler(VkDevice _device,const VkSamplerCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSampler * pSampler)2408 VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateSampler(
2409    VkDevice                                    _device,
2410    const VkSamplerCreateInfo*                  pCreateInfo,
2411    const VkAllocationCallbacks*                pAllocator,
2412    VkSampler*                                  pSampler)
2413 {
2414    LVP_FROM_HANDLE(lvp_device, device, _device);
2415    struct lvp_sampler *sampler;
2416    const VkSamplerReductionModeCreateInfo *reduction_mode_create_info =
2417       vk_find_struct_const(pCreateInfo->pNext,
2418                            SAMPLER_REDUCTION_MODE_CREATE_INFO);
2419    const VkSamplerCustomBorderColorCreateInfoEXT *custom_border_color_create_info =
2420       vk_find_struct_const(pCreateInfo->pNext,
2421                            SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT);
2422 
2423    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
2424 
2425    sampler = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*sampler), 8,
2426                        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2427    if (!sampler)
2428       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2429 
2430    vk_object_base_init(&device->vk, &sampler->base,
2431                        VK_OBJECT_TYPE_SAMPLER);
2432    sampler->create_info = *pCreateInfo;
2433 
2434    switch (pCreateInfo->borderColor) {
2435    case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
2436    case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK:
2437    default:
2438       memset(&sampler->border_color, 0, sizeof(union pipe_color_union));
2439       break;
2440    case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
2441       sampler->border_color.f[0] = sampler->border_color.f[1] =
2442       sampler->border_color.f[2] = 0.0f;
2443       sampler->border_color.f[3] = 1.0f;
2444       break;
2445    case VK_BORDER_COLOR_INT_OPAQUE_BLACK:
2446       sampler->border_color.i[0] = sampler->border_color.i[1] =
2447       sampler->border_color.i[2] = 0;
2448       sampler->border_color.i[3] = 1;
2449       break;
2450    case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
2451       sampler->border_color.f[0] = sampler->border_color.f[1] =
2452       sampler->border_color.f[2] = 1.0f;
2453       sampler->border_color.f[3] = 1.0f;
2454       break;
2455    case VK_BORDER_COLOR_INT_OPAQUE_WHITE:
2456       sampler->border_color.i[0] = sampler->border_color.i[1] =
2457       sampler->border_color.i[2] = 1;
2458       sampler->border_color.i[3] = 1;
2459       break;
2460    case VK_BORDER_COLOR_FLOAT_CUSTOM_EXT:
2461    case VK_BORDER_COLOR_INT_CUSTOM_EXT:
2462       assert(custom_border_color_create_info != NULL);
2463       memcpy(&sampler->border_color,
2464              &custom_border_color_create_info->customBorderColor,
2465              sizeof(union pipe_color_union));
2466       break;
2467    }
2468 
2469    sampler->reduction_mode = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE;
2470    if (reduction_mode_create_info)
2471       sampler->reduction_mode = reduction_mode_create_info->reductionMode;
2472 
2473    *pSampler = lvp_sampler_to_handle(sampler);
2474 
2475    return VK_SUCCESS;
2476 }
2477 
lvp_DestroySampler(VkDevice _device,VkSampler _sampler,const VkAllocationCallbacks * pAllocator)2478 VKAPI_ATTR void VKAPI_CALL lvp_DestroySampler(
2479    VkDevice                                    _device,
2480    VkSampler                                   _sampler,
2481    const VkAllocationCallbacks*                pAllocator)
2482 {
2483    LVP_FROM_HANDLE(lvp_device, device, _device);
2484    LVP_FROM_HANDLE(lvp_sampler, sampler, _sampler);
2485 
2486    if (!_sampler)
2487       return;
2488    vk_object_base_finish(&sampler->base);
2489    vk_free2(&device->vk.alloc, pAllocator, sampler);
2490 }
2491 
lvp_CreateSamplerYcbcrConversionKHR(VkDevice device,const VkSamplerYcbcrConversionCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSamplerYcbcrConversion * pYcbcrConversion)2492 VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateSamplerYcbcrConversionKHR(
2493     VkDevice                                    device,
2494     const VkSamplerYcbcrConversionCreateInfo*   pCreateInfo,
2495     const VkAllocationCallbacks*                pAllocator,
2496     VkSamplerYcbcrConversion*                   pYcbcrConversion)
2497 {
2498    return VK_ERROR_OUT_OF_HOST_MEMORY;
2499 }
2500 
lvp_DestroySamplerYcbcrConversionKHR(VkDevice device,VkSamplerYcbcrConversion ycbcrConversion,const VkAllocationCallbacks * pAllocator)2501 VKAPI_ATTR void VKAPI_CALL lvp_DestroySamplerYcbcrConversionKHR(
2502     VkDevice                                    device,
2503     VkSamplerYcbcrConversion                    ycbcrConversion,
2504     const VkAllocationCallbacks*                pAllocator)
2505 {
2506 }
2507 
2508 /* vk_icd.h does not declare this function, so we declare it here to
2509  * suppress Wmissing-prototypes.
2510  */
2511 PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
2512 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion);
2513 
2514 PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t * pSupportedVersion)2515 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion)
2516 {
2517    /* For the full details on loader interface versioning, see
2518     * <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.
2519     * What follows is a condensed summary, to help you navigate the large and
2520     * confusing official doc.
2521     *
2522     *   - Loader interface v0 is incompatible with later versions. We don't
2523     *     support it.
2524     *
2525     *   - In loader interface v1:
2526     *       - The first ICD entrypoint called by the loader is
2527     *         vk_icdGetInstanceProcAddr(). The ICD must statically expose this
2528     *         entrypoint.
2529     *       - The ICD must statically expose no other Vulkan symbol unless it is
2530     *         linked with -Bsymbolic.
2531     *       - Each dispatchable Vulkan handle created by the ICD must be
2532     *         a pointer to a struct whose first member is VK_LOADER_DATA. The
2533     *         ICD must initialize VK_LOADER_DATA.loadMagic to ICD_LOADER_MAGIC.
2534     *       - The loader implements vkCreate{PLATFORM}SurfaceKHR() and
2535     *         vkDestroySurfaceKHR(). The ICD must be capable of working with
2536     *         such loader-managed surfaces.
2537     *
2538     *    - Loader interface v2 differs from v1 in:
2539     *       - The first ICD entrypoint called by the loader is
2540     *         vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must
2541     *         statically expose this entrypoint.
2542     *
2543     *    - Loader interface v3 differs from v2 in:
2544     *        - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),
2545     *          vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,
2546     *          because the loader no longer does so.
2547     *
2548     *    - Loader interface v4 differs from v3 in:
2549     *        - The ICD must implement vk_icdGetPhysicalDeviceProcAddr().
2550     */
2551    *pSupportedVersion = MIN2(*pSupportedVersion, 4u);
2552    return VK_SUCCESS;
2553 }
2554 
lvp_CreatePrivateDataSlotEXT(VkDevice _device,const VkPrivateDataSlotCreateInfoEXT * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkPrivateDataSlotEXT * pPrivateDataSlot)2555 VKAPI_ATTR VkResult VKAPI_CALL lvp_CreatePrivateDataSlotEXT(
2556    VkDevice                                    _device,
2557    const VkPrivateDataSlotCreateInfoEXT*       pCreateInfo,
2558    const VkAllocationCallbacks*                pAllocator,
2559    VkPrivateDataSlotEXT*                       pPrivateDataSlot)
2560 {
2561    LVP_FROM_HANDLE(lvp_device, device, _device);
2562    return vk_private_data_slot_create(&device->vk, pCreateInfo, pAllocator,
2563                                       pPrivateDataSlot);
2564 }
2565 
lvp_DestroyPrivateDataSlotEXT(VkDevice _device,VkPrivateDataSlotEXT privateDataSlot,const VkAllocationCallbacks * pAllocator)2566 VKAPI_ATTR void VKAPI_CALL lvp_DestroyPrivateDataSlotEXT(
2567    VkDevice                                    _device,
2568    VkPrivateDataSlotEXT                        privateDataSlot,
2569    const VkAllocationCallbacks*                pAllocator)
2570 {
2571    LVP_FROM_HANDLE(lvp_device, device, _device);
2572    vk_private_data_slot_destroy(&device->vk, privateDataSlot, pAllocator);
2573 }
2574 
lvp_SetPrivateDataEXT(VkDevice _device,VkObjectType objectType,uint64_t objectHandle,VkPrivateDataSlotEXT privateDataSlot,uint64_t data)2575 VKAPI_ATTR VkResult VKAPI_CALL lvp_SetPrivateDataEXT(
2576    VkDevice                                    _device,
2577    VkObjectType                                objectType,
2578    uint64_t                                    objectHandle,
2579    VkPrivateDataSlotEXT                        privateDataSlot,
2580    uint64_t                                    data)
2581 {
2582    LVP_FROM_HANDLE(lvp_device, device, _device);
2583    return vk_object_base_set_private_data(&device->vk, objectType,
2584                                           objectHandle, privateDataSlot,
2585                                           data);
2586 }
2587 
lvp_GetPrivateDataEXT(VkDevice _device,VkObjectType objectType,uint64_t objectHandle,VkPrivateDataSlotEXT privateDataSlot,uint64_t * pData)2588 VKAPI_ATTR void VKAPI_CALL lvp_GetPrivateDataEXT(
2589    VkDevice                                    _device,
2590    VkObjectType                                objectType,
2591    uint64_t                                    objectHandle,
2592    VkPrivateDataSlotEXT                        privateDataSlot,
2593    uint64_t*                                   pData)
2594 {
2595    LVP_FROM_HANDLE(lvp_device, device, _device);
2596    vk_object_base_get_private_data(&device->vk, objectType, objectHandle,
2597                                    privateDataSlot, pData);
2598 }
2599 
lvp_GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalFenceInfo * pExternalFenceInfo,VkExternalFenceProperties * pExternalFenceProperties)2600 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceExternalFenceProperties(
2601    VkPhysicalDevice                           physicalDevice,
2602    const VkPhysicalDeviceExternalFenceInfo    *pExternalFenceInfo,
2603    VkExternalFenceProperties                  *pExternalFenceProperties)
2604 {
2605    pExternalFenceProperties->exportFromImportedHandleTypes = 0;
2606    pExternalFenceProperties->compatibleHandleTypes = 0;
2607    pExternalFenceProperties->externalFenceFeatures = 0;
2608 }
2609 
lvp_GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalSemaphoreInfo * pExternalSemaphoreInfo,VkExternalSemaphoreProperties * pExternalSemaphoreProperties)2610 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceExternalSemaphoreProperties(
2611    VkPhysicalDevice                            physicalDevice,
2612    const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo,
2613    VkExternalSemaphoreProperties               *pExternalSemaphoreProperties)
2614 {
2615    pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
2616    pExternalSemaphoreProperties->compatibleHandleTypes = 0;
2617    pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
2618 }
2619 
2620 static const VkTimeDomainEXT lvp_time_domains[] = {
2621         VK_TIME_DOMAIN_DEVICE_EXT,
2622         VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT,
2623 };
2624 
lvp_GetPhysicalDeviceCalibrateableTimeDomainsEXT(VkPhysicalDevice physicalDevice,uint32_t * pTimeDomainCount,VkTimeDomainEXT * pTimeDomains)2625 VKAPI_ATTR VkResult VKAPI_CALL lvp_GetPhysicalDeviceCalibrateableTimeDomainsEXT(
2626    VkPhysicalDevice physicalDevice,
2627    uint32_t *pTimeDomainCount,
2628    VkTimeDomainEXT *pTimeDomains)
2629 {
2630    int d;
2631    VK_OUTARRAY_MAKE_TYPED(VkTimeDomainEXT, out, pTimeDomains,
2632                           pTimeDomainCount);
2633 
2634    for (d = 0; d < ARRAY_SIZE(lvp_time_domains); d++) {
2635       vk_outarray_append_typed(VkTimeDomainEXT, &out, i) {
2636          *i = lvp_time_domains[d];
2637       }
2638     }
2639 
2640     return vk_outarray_status(&out);
2641 }
2642 
lvp_GetCalibratedTimestampsEXT(VkDevice device,uint32_t timestampCount,const VkCalibratedTimestampInfoEXT * pTimestampInfos,uint64_t * pTimestamps,uint64_t * pMaxDeviation)2643 VKAPI_ATTR VkResult VKAPI_CALL lvp_GetCalibratedTimestampsEXT(
2644    VkDevice device,
2645    uint32_t timestampCount,
2646    const VkCalibratedTimestampInfoEXT *pTimestampInfos,
2647    uint64_t *pTimestamps,
2648    uint64_t *pMaxDeviation)
2649 {
2650    *pMaxDeviation = 1;
2651 
2652    uint64_t now = os_time_get_nano();
2653    for (unsigned i = 0; i < timestampCount; i++) {
2654       pTimestamps[i] = now;
2655    }
2656    return VK_SUCCESS;
2657 }
2658 
lvp_GetDeviceGroupPeerMemoryFeaturesKHR(VkDevice device,uint32_t heapIndex,uint32_t localDeviceIndex,uint32_t remoteDeviceIndex,VkPeerMemoryFeatureFlags * pPeerMemoryFeatures)2659 VKAPI_ATTR void VKAPI_CALL lvp_GetDeviceGroupPeerMemoryFeaturesKHR(
2660     VkDevice device,
2661     uint32_t heapIndex,
2662     uint32_t localDeviceIndex,
2663     uint32_t remoteDeviceIndex,
2664     VkPeerMemoryFeatureFlags *pPeerMemoryFeatures)
2665 {
2666    *pPeerMemoryFeatures = 0;
2667 }
2668