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