vulkaninfo: Add video profiles support
[KhronosGroup/Vulkan-Tools.git] / scripts / mock_icd_generator.py
blobc788e7164c3a20fc2cc647d3dfd03ec569e56363
1 #!/usr/bin/python3 -i
3 # Copyright (c) 2015-2023 The Khronos Group Inc.
4 # Copyright (c) 2015-2023 Valve Corporation
5 # Copyright (c) 2015-2023 LunarG, Inc.
6 # Copyright (c) 2015-2023 Google Inc.
7 # Copyright (c) 2023-2023 RasterGrid Kft.
9 # Licensed under the Apache License, Version 2.0 (the "License");
10 # you may not use this file except in compliance with the License.
11 # You may obtain a copy of the License at
13 # http://www.apache.org/licenses/LICENSE-2.0
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS,
17 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 # See the License for the specific language governing permissions and
19 # limitations under the License.
21 # Author: Tobin Ehlis <tobine@google.com>
23 # This script generates a Mock ICD that intercepts almost all Vulkan
24 # functions. That layer is not intended to be useful or even compilable
25 # in its initial state. Rather it's intended to be a starting point that
26 # can be copied and customized to assist in creation of a new layer.
28 import os,re,sys
29 from generator import *
30 from common_codegen import *
32 CUSTOM_C_INTERCEPTS = {
33 'vkCreateInstance': '''
34 // TODO: If loader ver <=4 ICD must fail with VK_ERROR_INCOMPATIBLE_DRIVER for all vkCreateInstance calls with
35 // apiVersion set to > Vulkan 1.0 because the loader is still at interface version <= 4. Otherwise, the
36 // ICD should behave as normal.
37 if (loader_interface_version <= 4) {
38 return VK_ERROR_INCOMPATIBLE_DRIVER;
40 *pInstance = (VkInstance)CreateDispObjHandle();
41 for (auto& physical_device : physical_device_map[*pInstance])
42 physical_device = (VkPhysicalDevice)CreateDispObjHandle();
43 // TODO: If emulating specific device caps, will need to add intelligence here
44 return VK_SUCCESS;
45 ''',
46 'vkDestroyInstance': '''
47 if (instance) {
48 for (const auto physical_device : physical_device_map.at(instance)) {
49 display_map.erase(physical_device);
50 DestroyDispObjHandle((void*)physical_device);
52 physical_device_map.erase(instance);
53 DestroyDispObjHandle((void*)instance);
55 ''',
56 'vkAllocateCommandBuffers': '''
57 unique_lock_t lock(global_lock);
58 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; ++i) {
59 pCommandBuffers[i] = (VkCommandBuffer)CreateDispObjHandle();
60 command_pool_buffer_map[pAllocateInfo->commandPool].push_back(pCommandBuffers[i]);
62 return VK_SUCCESS;
63 ''',
64 'vkFreeCommandBuffers': '''
65 unique_lock_t lock(global_lock);
66 for (auto i = 0u; i < commandBufferCount; ++i) {
67 if (!pCommandBuffers[i]) {
68 continue;
71 for (auto& pair : command_pool_buffer_map) {
72 auto& cbs = pair.second;
73 auto it = std::find(cbs.begin(), cbs.end(), pCommandBuffers[i]);
74 if (it != cbs.end()) {
75 cbs.erase(it);
79 DestroyDispObjHandle((void*) pCommandBuffers[i]);
81 ''',
82 'vkCreateCommandPool': '''
83 unique_lock_t lock(global_lock);
84 *pCommandPool = (VkCommandPool)global_unique_handle++;
85 command_pool_map[device].insert(*pCommandPool);
86 return VK_SUCCESS;
87 ''',
88 'vkDestroyCommandPool': '''
89 // destroy command buffers for this pool
90 unique_lock_t lock(global_lock);
91 auto it = command_pool_buffer_map.find(commandPool);
92 if (it != command_pool_buffer_map.end()) {
93 for (auto& cb : it->second) {
94 DestroyDispObjHandle((void*) cb);
96 command_pool_buffer_map.erase(it);
98 command_pool_map[device].erase(commandPool);
99 ''',
100 'vkEnumeratePhysicalDevices': '''
101 VkResult result_code = VK_SUCCESS;
102 if (pPhysicalDevices) {
103 const auto return_count = (std::min)(*pPhysicalDeviceCount, icd_physical_device_count);
104 for (uint32_t i = 0; i < return_count; ++i) pPhysicalDevices[i] = physical_device_map.at(instance)[i];
105 if (return_count < icd_physical_device_count) result_code = VK_INCOMPLETE;
106 *pPhysicalDeviceCount = return_count;
107 } else {
108 *pPhysicalDeviceCount = icd_physical_device_count;
110 return result_code;
111 ''',
112 'vkCreateDevice': '''
113 *pDevice = (VkDevice)CreateDispObjHandle();
114 // TODO: If emulating specific device caps, will need to add intelligence here
115 return VK_SUCCESS;
116 ''',
117 'vkDestroyDevice': '''
118 unique_lock_t lock(global_lock);
119 // First destroy sub-device objects
120 // Destroy Queues
121 for (auto queue_family_map_pair : queue_map[device]) {
122 for (auto index_queue_pair : queue_map[device][queue_family_map_pair.first]) {
123 DestroyDispObjHandle((void*)index_queue_pair.second);
127 for (auto& cp : command_pool_map[device]) {
128 for (auto& cb : command_pool_buffer_map[cp]) {
129 DestroyDispObjHandle((void*) cb);
131 command_pool_buffer_map.erase(cp);
133 command_pool_map[device].clear();
135 queue_map.erase(device);
136 buffer_map.erase(device);
137 image_memory_size_map.erase(device);
138 // Now destroy device
139 DestroyDispObjHandle((void*)device);
140 // TODO: If emulating specific device caps, will need to add intelligence here
141 ''',
142 'vkGetDeviceQueue': '''
143 unique_lock_t lock(global_lock);
144 auto queue = queue_map[device][queueFamilyIndex][queueIndex];
145 if (queue) {
146 *pQueue = queue;
147 } else {
148 *pQueue = queue_map[device][queueFamilyIndex][queueIndex] = (VkQueue)CreateDispObjHandle();
150 // TODO: If emulating specific device caps, will need to add intelligence here
151 return;
152 ''',
153 'vkGetDeviceQueue2': '''
154 GetDeviceQueue(device, pQueueInfo->queueFamilyIndex, pQueueInfo->queueIndex, pQueue);
155 // TODO: Add further support for GetDeviceQueue2 features
156 ''',
157 'vkEnumerateInstanceLayerProperties': '''
158 return VK_SUCCESS;
159 ''',
160 'vkEnumerateInstanceVersion': '''
161 *pApiVersion = VK_HEADER_VERSION_COMPLETE;
162 return VK_SUCCESS;
163 ''',
164 'vkEnumerateDeviceLayerProperties': '''
165 return VK_SUCCESS;
166 ''',
167 'vkEnumerateInstanceExtensionProperties': '''
168 // If requesting number of extensions, return that
169 if (!pLayerName) {
170 if (!pProperties) {
171 *pPropertyCount = (uint32_t)instance_extension_map.size();
172 } else {
173 uint32_t i = 0;
174 for (const auto &name_ver_pair : instance_extension_map) {
175 if (i == *pPropertyCount) {
176 break;
178 std::strncpy(pProperties[i].extensionName, name_ver_pair.first.c_str(), sizeof(pProperties[i].extensionName));
179 pProperties[i].extensionName[sizeof(pProperties[i].extensionName) - 1] = 0;
180 pProperties[i].specVersion = name_ver_pair.second;
181 ++i;
183 if (i != instance_extension_map.size()) {
184 return VK_INCOMPLETE;
188 // If requesting extension properties, fill in data struct for number of extensions
189 return VK_SUCCESS;
190 ''',
191 'vkEnumerateDeviceExtensionProperties': '''
192 // If requesting number of extensions, return that
193 if (!pLayerName) {
194 if (!pProperties) {
195 *pPropertyCount = (uint32_t)device_extension_map.size();
196 } else {
197 uint32_t i = 0;
198 for (const auto &name_ver_pair : device_extension_map) {
199 if (i == *pPropertyCount) {
200 break;
202 std::strncpy(pProperties[i].extensionName, name_ver_pair.first.c_str(), sizeof(pProperties[i].extensionName));
203 pProperties[i].extensionName[sizeof(pProperties[i].extensionName) - 1] = 0;
204 pProperties[i].specVersion = name_ver_pair.second;
205 ++i;
207 if (i != device_extension_map.size()) {
208 return VK_INCOMPLETE;
212 // If requesting extension properties, fill in data struct for number of extensions
213 return VK_SUCCESS;
214 ''',
215 'vkGetPhysicalDeviceSurfacePresentModesKHR': '''
216 // Currently always say that all present modes are supported
217 if (!pPresentModes) {
218 *pPresentModeCount = 6;
219 } else {
220 if (*pPresentModeCount >= 6) pPresentModes[5] = VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR;
221 if (*pPresentModeCount >= 5) pPresentModes[4] = VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR;
222 if (*pPresentModeCount >= 4) pPresentModes[3] = VK_PRESENT_MODE_FIFO_RELAXED_KHR;
223 if (*pPresentModeCount >= 3) pPresentModes[2] = VK_PRESENT_MODE_FIFO_KHR;
224 if (*pPresentModeCount >= 2) pPresentModes[1] = VK_PRESENT_MODE_MAILBOX_KHR;
225 if (*pPresentModeCount >= 1) pPresentModes[0] = VK_PRESENT_MODE_IMMEDIATE_KHR;
227 return VK_SUCCESS;
228 ''',
229 'vkGetPhysicalDeviceSurfaceFormatsKHR': '''
230 // Currently always say that RGBA8 & BGRA8 are supported
231 if (!pSurfaceFormats) {
232 *pSurfaceFormatCount = 2;
233 } else {
234 if (*pSurfaceFormatCount >= 2) {
235 pSurfaceFormats[1].format = VK_FORMAT_R8G8B8A8_UNORM;
236 pSurfaceFormats[1].colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
238 if (*pSurfaceFormatCount >= 1) {
239 pSurfaceFormats[0].format = VK_FORMAT_B8G8R8A8_UNORM;
240 pSurfaceFormats[0].colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
243 return VK_SUCCESS;
244 ''',
245 'vkGetPhysicalDeviceSurfaceFormats2KHR': '''
246 // Currently always say that RGBA8 & BGRA8 are supported
247 if (!pSurfaceFormats) {
248 *pSurfaceFormatCount = 2;
249 } else {
250 if (*pSurfaceFormatCount >= 2) {
251 pSurfaceFormats[1].pNext = nullptr;
252 pSurfaceFormats[1].surfaceFormat.format = VK_FORMAT_R8G8B8A8_UNORM;
253 pSurfaceFormats[1].surfaceFormat.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
255 if (*pSurfaceFormatCount >= 1) {
256 pSurfaceFormats[1].pNext = nullptr;
257 pSurfaceFormats[0].surfaceFormat.format = VK_FORMAT_B8G8R8A8_UNORM;
258 pSurfaceFormats[0].surfaceFormat.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
261 return VK_SUCCESS;
262 ''',
263 'vkGetPhysicalDeviceSurfaceSupportKHR': '''
264 // Currently say that all surface/queue combos are supported
265 *pSupported = VK_TRUE;
266 return VK_SUCCESS;
267 ''',
268 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR': '''
269 // In general just say max supported is available for requested surface
270 pSurfaceCapabilities->minImageCount = 1;
271 pSurfaceCapabilities->maxImageCount = 0;
272 pSurfaceCapabilities->currentExtent.width = 0xFFFFFFFF;
273 pSurfaceCapabilities->currentExtent.height = 0xFFFFFFFF;
274 pSurfaceCapabilities->minImageExtent.width = 1;
275 pSurfaceCapabilities->minImageExtent.height = 1;
276 pSurfaceCapabilities->maxImageExtent.width = 0xFFFF;
277 pSurfaceCapabilities->maxImageExtent.height = 0xFFFF;
278 pSurfaceCapabilities->maxImageArrayLayers = 128;
279 pSurfaceCapabilities->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR |
280 VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR |
281 VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR |
282 VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR |
283 VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR |
284 VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR |
285 VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR |
286 VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR |
287 VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
288 pSurfaceCapabilities->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
289 pSurfaceCapabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR |
290 VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR |
291 VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR |
292 VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
293 pSurfaceCapabilities->supportedUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
294 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
295 VK_IMAGE_USAGE_SAMPLED_BIT |
296 VK_IMAGE_USAGE_STORAGE_BIT |
297 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
298 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
299 VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT |
300 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
301 return VK_SUCCESS;
302 ''',
303 'vkGetPhysicalDeviceSurfaceCapabilities2KHR': '''
304 GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, pSurfaceInfo->surface, &pSurfaceCapabilities->surfaceCapabilities);
306 auto *present_mode_compatibility = lvl_find_mod_in_chain<VkSurfacePresentModeCompatibilityEXT>(pSurfaceCapabilities->pNext);
307 if (present_mode_compatibility) {
308 if (!present_mode_compatibility->pPresentModes) {
309 present_mode_compatibility->presentModeCount = 3;
310 } else {
311 // arbitrary
312 present_mode_compatibility->pPresentModes[0] = VK_PRESENT_MODE_IMMEDIATE_KHR;
313 present_mode_compatibility->pPresentModes[1] = VK_PRESENT_MODE_FIFO_KHR;
314 present_mode_compatibility->pPresentModes[2] = VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR;
317 return VK_SUCCESS;
318 ''',
319 'vkGetInstanceProcAddr': '''
320 if (!negotiate_loader_icd_interface_called) {
321 loader_interface_version = 0;
323 const auto &item = name_to_funcptr_map.find(pName);
324 if (item != name_to_funcptr_map.end()) {
325 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
327 // Mock should intercept all functions so if we get here just return null
328 return nullptr;
329 ''',
330 'vkGetDeviceProcAddr': '''
331 return GetInstanceProcAddr(nullptr, pName);
332 ''',
333 'vkGetPhysicalDeviceMemoryProperties': '''
334 pMemoryProperties->memoryTypeCount = 6;
335 // Host visible Coherent
336 pMemoryProperties->memoryTypes[0].propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
337 pMemoryProperties->memoryTypes[0].heapIndex = 0;
338 // Host visible Cached
339 pMemoryProperties->memoryTypes[1].propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
340 pMemoryProperties->memoryTypes[1].heapIndex = 0;
341 // Device local and Host visible
342 pMemoryProperties->memoryTypes[2].propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
343 pMemoryProperties->memoryTypes[2].heapIndex = 1;
344 // Device local lazily
345 pMemoryProperties->memoryTypes[3].propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
346 pMemoryProperties->memoryTypes[3].heapIndex = 1;
347 // Device local protected
348 pMemoryProperties->memoryTypes[4].propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_PROTECTED_BIT;
349 pMemoryProperties->memoryTypes[4].heapIndex = 1;
350 // Device local only
351 pMemoryProperties->memoryTypes[5].propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
352 pMemoryProperties->memoryTypes[5].heapIndex = 1;
353 pMemoryProperties->memoryHeapCount = 2;
354 pMemoryProperties->memoryHeaps[0].flags = VK_MEMORY_HEAP_MULTI_INSTANCE_BIT;
355 pMemoryProperties->memoryHeaps[0].size = 8000000000;
356 pMemoryProperties->memoryHeaps[1].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
357 pMemoryProperties->memoryHeaps[1].size = 8000000000;
358 ''',
359 'vkGetPhysicalDeviceMemoryProperties2KHR': '''
360 GetPhysicalDeviceMemoryProperties(physicalDevice, &pMemoryProperties->memoryProperties);
361 ''',
362 'vkGetPhysicalDeviceQueueFamilyProperties': '''
363 if (pQueueFamilyProperties) {
364 std::vector<VkQueueFamilyProperties2KHR> props2(*pQueueFamilyPropertyCount, {
365 VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR});
366 GetPhysicalDeviceQueueFamilyProperties2KHR(physicalDevice, pQueueFamilyPropertyCount, props2.data());
367 for (uint32_t i = 0; i < *pQueueFamilyPropertyCount; ++i) {
368 pQueueFamilyProperties[i] = props2[i].queueFamilyProperties;
370 } else {
371 GetPhysicalDeviceQueueFamilyProperties2KHR(physicalDevice, pQueueFamilyPropertyCount, nullptr);
373 ''',
374 'vkGetPhysicalDeviceQueueFamilyProperties2KHR': '''
375 if (pQueueFamilyProperties) {
376 if (*pQueueFamilyPropertyCount >= 1) {
377 auto props = &pQueueFamilyProperties[0].queueFamilyProperties;
378 props->queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT
379 | VK_QUEUE_SPARSE_BINDING_BIT | VK_QUEUE_PROTECTED_BIT;
380 props->queueCount = 1;
381 props->timestampValidBits = 16;
382 props->minImageTransferGranularity = {1,1,1};
384 if (*pQueueFamilyPropertyCount >= 2) {
385 auto props = &pQueueFamilyProperties[1].queueFamilyProperties;
386 props->queueFlags = VK_QUEUE_TRANSFER_BIT | VK_QUEUE_PROTECTED_BIT | VK_QUEUE_VIDEO_DECODE_BIT_KHR;
387 props->queueCount = 1;
388 props->timestampValidBits = 16;
389 props->minImageTransferGranularity = {1,1,1};
391 auto status_query_props = lvl_find_mod_in_chain<VkQueueFamilyQueryResultStatusPropertiesKHR>(pQueueFamilyProperties[1].pNext);
392 if (status_query_props) {
393 status_query_props->queryResultStatusSupport = VK_TRUE;
395 auto video_props = lvl_find_mod_in_chain<VkQueueFamilyVideoPropertiesKHR>(pQueueFamilyProperties[1].pNext);
396 if (video_props) {
397 video_props->videoCodecOperations = VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR
398 | VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR
399 | VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR;
402 if (*pQueueFamilyPropertyCount >= 3) {
403 auto props = &pQueueFamilyProperties[2].queueFamilyProperties;
404 props->queueFlags = VK_QUEUE_TRANSFER_BIT | VK_QUEUE_PROTECTED_BIT | VK_QUEUE_VIDEO_ENCODE_BIT_KHR;
405 props->queueCount = 1;
406 props->timestampValidBits = 16;
407 props->minImageTransferGranularity = {1,1,1};
409 auto status_query_props = lvl_find_mod_in_chain<VkQueueFamilyQueryResultStatusPropertiesKHR>(pQueueFamilyProperties[2].pNext);
410 if (status_query_props) {
411 status_query_props->queryResultStatusSupport = VK_TRUE;
413 auto video_props = lvl_find_mod_in_chain<VkQueueFamilyVideoPropertiesKHR>(pQueueFamilyProperties[2].pNext);
414 if (video_props) {
415 video_props->videoCodecOperations = VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR
416 | VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR
417 | VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR;
420 if (*pQueueFamilyPropertyCount > 3) {
421 *pQueueFamilyPropertyCount = 3;
423 } else {
424 *pQueueFamilyPropertyCount = 3;
426 ''',
427 'vkGetPhysicalDeviceFeatures': '''
428 uint32_t num_bools = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
429 VkBool32 *bool_array = &pFeatures->robustBufferAccess;
430 SetBoolArrayTrue(bool_array, num_bools);
431 ''',
432 'vkGetPhysicalDeviceFeatures2KHR': '''
433 GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
434 uint32_t num_bools = 0; // Count number of VkBool32s in extension structs
435 VkBool32* feat_bools = nullptr;
436 auto vk_1_1_features = lvl_find_mod_in_chain<VkPhysicalDeviceVulkan11Features>(pFeatures->pNext);
437 if (vk_1_1_features) {
438 vk_1_1_features->protectedMemory = VK_TRUE;
440 auto vk_1_3_features = lvl_find_mod_in_chain<VkPhysicalDeviceVulkan13Features>(pFeatures->pNext);
441 if (vk_1_3_features) {
442 vk_1_3_features->synchronization2 = VK_TRUE;
444 auto prot_features = lvl_find_mod_in_chain<VkPhysicalDeviceProtectedMemoryFeatures>(pFeatures->pNext);
445 if (prot_features) {
446 prot_features->protectedMemory = VK_TRUE;
448 auto sync2_features = lvl_find_mod_in_chain<VkPhysicalDeviceSynchronization2FeaturesKHR>(pFeatures->pNext);
449 if (sync2_features) {
450 sync2_features->synchronization2 = VK_TRUE;
452 auto video_maintenance1_features = lvl_find_mod_in_chain<VkPhysicalDeviceVideoMaintenance1FeaturesKHR>(pFeatures->pNext);
453 if (video_maintenance1_features) {
454 video_maintenance1_features->videoMaintenance1 = VK_TRUE;
456 const auto *desc_idx_features = lvl_find_in_chain<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>(pFeatures->pNext);
457 if (desc_idx_features) {
458 const auto bool_size = sizeof(VkPhysicalDeviceDescriptorIndexingFeaturesEXT) - offsetof(VkPhysicalDeviceDescriptorIndexingFeaturesEXT, shaderInputAttachmentArrayDynamicIndexing);
459 num_bools = bool_size/sizeof(VkBool32);
460 feat_bools = (VkBool32*)&desc_idx_features->shaderInputAttachmentArrayDynamicIndexing;
461 SetBoolArrayTrue(feat_bools, num_bools);
463 const auto *blendop_features = lvl_find_in_chain<VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT>(pFeatures->pNext);
464 if (blendop_features) {
465 const auto bool_size = sizeof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT) - offsetof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT, advancedBlendCoherentOperations);
466 num_bools = bool_size/sizeof(VkBool32);
467 feat_bools = (VkBool32*)&blendop_features->advancedBlendCoherentOperations;
468 SetBoolArrayTrue(feat_bools, num_bools);
470 const auto *host_image_copy_features = lvl_find_in_chain<VkPhysicalDeviceHostImageCopyFeaturesEXT>(pFeatures->pNext);
471 if (host_image_copy_features) {
472 feat_bools = (VkBool32*)&host_image_copy_features->hostImageCopy;
473 SetBoolArrayTrue(feat_bools, 1);
475 ''',
476 'vkGetPhysicalDeviceFormatProperties': '''
477 if (VK_FORMAT_UNDEFINED == format) {
478 *pFormatProperties = { 0x0, 0x0, 0x0 };
479 } else {
480 // Default to a color format, skip DS bit
481 *pFormatProperties = { 0x00FFFDFF, 0x00FFFDFF, 0x00FFFDFF };
482 switch (format) {
483 case VK_FORMAT_D16_UNORM:
484 case VK_FORMAT_X8_D24_UNORM_PACK32:
485 case VK_FORMAT_D32_SFLOAT:
486 case VK_FORMAT_S8_UINT:
487 case VK_FORMAT_D16_UNORM_S8_UINT:
488 case VK_FORMAT_D24_UNORM_S8_UINT:
489 case VK_FORMAT_D32_SFLOAT_S8_UINT:
490 // Don't set color bits for DS formats
491 *pFormatProperties = { 0x00FFFE7F, 0x00FFFE7F, 0x00FFFE7F };
492 break;
493 case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
494 case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
495 case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
496 case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16:
497 case VK_FORMAT_G8_B8R8_2PLANE_444_UNORM:
498 // Set decode/encode bits for these formats
499 *pFormatProperties = { 0x1EFFFDFF, 0x1EFFFDFF, 0x00FFFDFF };
500 break;
501 default:
502 break;
505 ''',
506 'vkGetPhysicalDeviceFormatProperties2KHR': '''
507 GetPhysicalDeviceFormatProperties(physicalDevice, format, &pFormatProperties->formatProperties);
508 VkFormatProperties3KHR *props_3 = lvl_find_mod_in_chain<VkFormatProperties3KHR>(pFormatProperties->pNext);
509 if (props_3) {
510 props_3->linearTilingFeatures = pFormatProperties->formatProperties.linearTilingFeatures;
511 props_3->optimalTilingFeatures = pFormatProperties->formatProperties.optimalTilingFeatures;
512 props_3->bufferFeatures = pFormatProperties->formatProperties.bufferFeatures;
513 props_3->optimalTilingFeatures |= VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT;
515 ''',
516 'vkGetPhysicalDeviceImageFormatProperties': '''
517 // A hardcoded unsupported format
518 if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) {
519 return VK_ERROR_FORMAT_NOT_SUPPORTED;
522 // TODO: Just hard-coding some values for now
523 // TODO: If tiling is linear, limit the mips, levels, & sample count
524 if (VK_IMAGE_TILING_LINEAR == tiling) {
525 *pImageFormatProperties = { { 4096, 4096, 256 }, 1, 1, VK_SAMPLE_COUNT_1_BIT, 4294967296 };
526 } else {
527 // We hard-code support for all sample counts except 64 bits.
528 *pImageFormatProperties = { { 4096, 4096, 256 }, 12, 256, 0x7F & ~VK_SAMPLE_COUNT_64_BIT, 4294967296 };
530 return VK_SUCCESS;
531 ''',
532 'vkGetPhysicalDeviceImageFormatProperties2KHR': '''
533 auto *external_image_prop = lvl_find_mod_in_chain<VkExternalImageFormatProperties>(pImageFormatProperties->pNext);
534 auto *external_image_format = lvl_find_in_chain<VkPhysicalDeviceExternalImageFormatInfo>(pImageFormatInfo->pNext);
535 if (external_image_prop && external_image_format) {
536 external_image_prop->externalMemoryProperties.externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT;
537 external_image_prop->externalMemoryProperties.compatibleHandleTypes = external_image_format->handleType;
540 GetPhysicalDeviceImageFormatProperties(physicalDevice, pImageFormatInfo->format, pImageFormatInfo->type, pImageFormatInfo->tiling, pImageFormatInfo->usage, pImageFormatInfo->flags, &pImageFormatProperties->imageFormatProperties);
541 return VK_SUCCESS;
542 ''',
543 'vkGetPhysicalDeviceSparseImageFormatProperties': '''
544 if (!pProperties) {
545 *pPropertyCount = 1;
546 } else {
547 // arbitrary
548 pProperties->imageGranularity = {4, 4, 4};
549 pProperties->flags = VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT;
550 switch (format) {
551 case VK_FORMAT_D16_UNORM:
552 case VK_FORMAT_D32_SFLOAT:
553 pProperties->aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
554 break;
555 case VK_FORMAT_S8_UINT:
556 pProperties->aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
557 break;
558 case VK_FORMAT_X8_D24_UNORM_PACK32:
559 case VK_FORMAT_D16_UNORM_S8_UINT:
560 case VK_FORMAT_D24_UNORM_S8_UINT:
561 case VK_FORMAT_D32_SFLOAT_S8_UINT:
562 pProperties->aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
563 break;
564 default:
565 pProperties->aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
566 break;
569 ''',
570 'vkGetPhysicalDeviceSparseImageFormatProperties2KHR': '''
571 if (pPropertyCount && pProperties) {
572 GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, pFormatInfo->format, pFormatInfo->type, pFormatInfo->samples, pFormatInfo->usage, pFormatInfo->tiling, pPropertyCount, &pProperties->properties);
573 } else {
574 GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, pFormatInfo->format, pFormatInfo->type, pFormatInfo->samples, pFormatInfo->usage, pFormatInfo->tiling, pPropertyCount, nullptr);
576 ''',
577 'vkGetPhysicalDeviceProperties': '''
578 pProperties->apiVersion = VK_HEADER_VERSION_COMPLETE;
579 pProperties->driverVersion = 1;
580 pProperties->vendorID = 0xba5eba11;
581 pProperties->deviceID = 0xf005ba11;
582 pProperties->deviceType = VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU;
583 //std::string devName = "Vulkan Mock Device";
584 strcpy(pProperties->deviceName, "Vulkan Mock Device");
585 pProperties->pipelineCacheUUID[0] = 18;
586 pProperties->limits = SetLimits(&pProperties->limits);
587 pProperties->sparseProperties = { VK_TRUE, VK_TRUE, VK_TRUE, VK_TRUE, VK_TRUE };
588 ''',
589 'vkGetPhysicalDeviceProperties2KHR': '''
590 // The only value that need to be set are those the Profile layer can't set
591 // see https://github.com/KhronosGroup/Vulkan-Profiles/issues/352
592 // All values set are arbitrary
593 GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
595 auto *props_11 = lvl_find_mod_in_chain<VkPhysicalDeviceVulkan11Properties>(pProperties->pNext);
596 if (props_11) {
597 props_11->protectedNoFault = VK_FALSE;
600 auto *props_12 = lvl_find_mod_in_chain<VkPhysicalDeviceVulkan12Properties>(pProperties->pNext);
601 if (props_12) {
602 props_12->denormBehaviorIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL;
603 props_12->roundingModeIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL;
606 auto *props_13 = lvl_find_mod_in_chain<VkPhysicalDeviceVulkan13Properties>(pProperties->pNext);
607 if (props_13) {
608 props_13->storageTexelBufferOffsetSingleTexelAlignment = VK_TRUE;
609 props_13->uniformTexelBufferOffsetSingleTexelAlignment = VK_TRUE;
610 props_13->storageTexelBufferOffsetAlignmentBytes = 16;
611 props_13->uniformTexelBufferOffsetAlignmentBytes = 16;
614 auto *protected_memory_props = lvl_find_mod_in_chain<VkPhysicalDeviceProtectedMemoryProperties>(pProperties->pNext);
615 if (protected_memory_props) {
616 protected_memory_props->protectedNoFault = VK_FALSE;
619 auto *float_controls_props = lvl_find_mod_in_chain<VkPhysicalDeviceFloatControlsProperties>(pProperties->pNext);
620 if (float_controls_props) {
621 float_controls_props->denormBehaviorIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL;
622 float_controls_props->roundingModeIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL;
625 auto *conservative_raster_props = lvl_find_mod_in_chain<VkPhysicalDeviceConservativeRasterizationPropertiesEXT>(pProperties->pNext);
626 if (conservative_raster_props) {
627 conservative_raster_props->primitiveOverestimationSize = 0.00195313f;
628 conservative_raster_props->conservativePointAndLineRasterization = VK_TRUE;
629 conservative_raster_props->degenerateTrianglesRasterized = VK_TRUE;
630 conservative_raster_props->degenerateLinesRasterized = VK_TRUE;
633 auto *rt_pipeline_props = lvl_find_mod_in_chain<VkPhysicalDeviceRayTracingPipelinePropertiesKHR>(pProperties->pNext);
634 if (rt_pipeline_props) {
635 rt_pipeline_props->shaderGroupHandleSize = 32;
636 rt_pipeline_props->shaderGroupBaseAlignment = 64;
637 rt_pipeline_props->shaderGroupHandleCaptureReplaySize = 32;
640 auto *rt_pipeline_nv_props = lvl_find_mod_in_chain<VkPhysicalDeviceRayTracingPropertiesNV>(pProperties->pNext);
641 if (rt_pipeline_nv_props) {
642 rt_pipeline_nv_props->shaderGroupHandleSize = 32;
643 rt_pipeline_nv_props->shaderGroupBaseAlignment = 64;
646 auto *texel_buffer_props = lvl_find_mod_in_chain<VkPhysicalDeviceTexelBufferAlignmentProperties>(pProperties->pNext);
647 if (texel_buffer_props) {
648 texel_buffer_props->storageTexelBufferOffsetSingleTexelAlignment = VK_TRUE;
649 texel_buffer_props->uniformTexelBufferOffsetSingleTexelAlignment = VK_TRUE;
650 texel_buffer_props->storageTexelBufferOffsetAlignmentBytes = 16;
651 texel_buffer_props->uniformTexelBufferOffsetAlignmentBytes = 16;
654 auto *descriptor_buffer_props = lvl_find_mod_in_chain<VkPhysicalDeviceDescriptorBufferPropertiesEXT>(pProperties->pNext);
655 if (descriptor_buffer_props) {
656 descriptor_buffer_props->combinedImageSamplerDescriptorSingleArray = VK_TRUE;
657 descriptor_buffer_props->bufferlessPushDescriptors = VK_TRUE;
658 descriptor_buffer_props->allowSamplerImageViewPostSubmitCreation = VK_TRUE;
659 descriptor_buffer_props->descriptorBufferOffsetAlignment = 4;
662 auto *mesh_shader_props = lvl_find_mod_in_chain<VkPhysicalDeviceMeshShaderPropertiesEXT>(pProperties->pNext);
663 if (mesh_shader_props) {
664 mesh_shader_props->meshOutputPerVertexGranularity = 32;
665 mesh_shader_props->meshOutputPerPrimitiveGranularity = 32;
666 mesh_shader_props->prefersLocalInvocationVertexOutput = VK_TRUE;
667 mesh_shader_props->prefersLocalInvocationPrimitiveOutput = VK_TRUE;
668 mesh_shader_props->prefersCompactVertexOutput = VK_TRUE;
669 mesh_shader_props->prefersCompactPrimitiveOutput = VK_TRUE;
672 auto *fragment_density_map2_props = lvl_find_mod_in_chain<VkPhysicalDeviceFragmentDensityMap2PropertiesEXT>(pProperties->pNext);
673 if (fragment_density_map2_props) {
674 fragment_density_map2_props->subsampledLoads = VK_FALSE;
675 fragment_density_map2_props->subsampledCoarseReconstructionEarlyAccess = VK_FALSE;
676 fragment_density_map2_props->maxSubsampledArrayLayers = 2;
677 fragment_density_map2_props->maxDescriptorSetSubsampledSamplers = 1;
680 const uint32_t num_copy_layouts = 5;
681 const VkImageLayout HostCopyLayouts[]{
682 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
683 VK_IMAGE_LAYOUT_GENERAL,
684 VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
685 VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL,
686 VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
689 auto *host_image_copy_props = lvl_find_mod_in_chain<VkPhysicalDeviceHostImageCopyPropertiesEXT>(pProperties->pNext);
690 if (host_image_copy_props){
691 if (host_image_copy_props->pCopyDstLayouts == nullptr) host_image_copy_props->copyDstLayoutCount = num_copy_layouts;
692 else {
693 uint32_t num_layouts = (std::min)(host_image_copy_props->copyDstLayoutCount, num_copy_layouts);
694 for (uint32_t i = 0; i < num_layouts; i++) {
695 host_image_copy_props->pCopyDstLayouts[i] = HostCopyLayouts[i];
698 if (host_image_copy_props->pCopySrcLayouts == nullptr) host_image_copy_props->copySrcLayoutCount = num_copy_layouts;
699 else {
700 uint32_t num_layouts = (std::min)(host_image_copy_props->copySrcLayoutCount, num_copy_layouts);
701 for (uint32_t i = 0; i < num_layouts; i++) {
702 host_image_copy_props->pCopySrcLayouts[i] = HostCopyLayouts[i];
707 auto *driver_properties = lvl_find_mod_in_chain<VkPhysicalDeviceDriverProperties>(pProperties->pNext);
708 if (driver_properties) {
709 std::strncpy(driver_properties->driverName, "Vulkan Mock Device", VK_MAX_DRIVER_NAME_SIZE);
710 #if defined(GIT_BRANCH_NAME) && defined(GIT_TAG_INFO)
711 std::strncpy(driver_properties->driverInfo, "Branch: " GIT_BRANCH_NAME " Tag Info: " GIT_TAG_INFO, VK_MAX_DRIVER_INFO_SIZE);
712 #else
713 std::strncpy(driver_properties->driverInfo, "Branch: --unknown-- Tag Info: --unknown--", VK_MAX_DRIVER_INFO_SIZE);
714 #endif
716 ''',
717 'vkGetPhysicalDeviceExternalSemaphoreProperties':'''
718 // Hard code support for all handle types and features
719 pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0x1F;
720 pExternalSemaphoreProperties->compatibleHandleTypes = 0x1F;
721 pExternalSemaphoreProperties->externalSemaphoreFeatures = 0x3;
722 ''',
723 'vkGetPhysicalDeviceExternalSemaphorePropertiesKHR':'''
724 GetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, pExternalSemaphoreInfo, pExternalSemaphoreProperties);
725 ''',
726 'vkGetPhysicalDeviceExternalFenceProperties':'''
727 // Hard-code support for all handle types and features
728 pExternalFenceProperties->exportFromImportedHandleTypes = 0xF;
729 pExternalFenceProperties->compatibleHandleTypes = 0xF;
730 pExternalFenceProperties->externalFenceFeatures = 0x3;
731 ''',
732 'vkGetPhysicalDeviceExternalFencePropertiesKHR':'''
733 GetPhysicalDeviceExternalFenceProperties(physicalDevice, pExternalFenceInfo, pExternalFenceProperties);
734 ''',
735 'vkGetPhysicalDeviceExternalBufferProperties':'''
736 constexpr VkExternalMemoryHandleTypeFlags supported_flags = 0x1FF;
737 if (pExternalBufferInfo->handleType & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) {
738 // Can't have dedicated memory with AHB
739 pExternalBufferProperties->externalMemoryProperties.externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT;
740 pExternalBufferProperties->externalMemoryProperties.exportFromImportedHandleTypes = pExternalBufferInfo->handleType;
741 pExternalBufferProperties->externalMemoryProperties.compatibleHandleTypes = pExternalBufferInfo->handleType;
742 } else if (pExternalBufferInfo->handleType & supported_flags) {
743 pExternalBufferProperties->externalMemoryProperties.externalMemoryFeatures = 0x7;
744 pExternalBufferProperties->externalMemoryProperties.exportFromImportedHandleTypes = supported_flags;
745 pExternalBufferProperties->externalMemoryProperties.compatibleHandleTypes = supported_flags;
746 } else {
747 pExternalBufferProperties->externalMemoryProperties.externalMemoryFeatures = 0;
748 pExternalBufferProperties->externalMemoryProperties.exportFromImportedHandleTypes = 0;
749 // According to spec, handle type is always compatible with itself. Even if export/import
750 // not supported, it's important to properly implement self-compatibility property since
751 // application's control flow can rely on this.
752 pExternalBufferProperties->externalMemoryProperties.compatibleHandleTypes = pExternalBufferInfo->handleType;
754 ''',
755 'vkGetPhysicalDeviceExternalBufferPropertiesKHR':'''
756 GetPhysicalDeviceExternalBufferProperties(physicalDevice, pExternalBufferInfo, pExternalBufferProperties);
757 ''',
758 'vkGetBufferMemoryRequirements': '''
759 // TODO: Just hard-coding reqs for now
760 pMemoryRequirements->size = 4096;
761 pMemoryRequirements->alignment = 1;
762 pMemoryRequirements->memoryTypeBits = 0xFFFF;
763 // Return a better size based on the buffer size from the create info.
764 unique_lock_t lock(global_lock);
765 auto d_iter = buffer_map.find(device);
766 if (d_iter != buffer_map.end()) {
767 auto iter = d_iter->second.find(buffer);
768 if (iter != d_iter->second.end()) {
769 pMemoryRequirements->size = ((iter->second.size + 4095) / 4096) * 4096;
772 ''',
773 'vkGetBufferMemoryRequirements2KHR': '''
774 GetBufferMemoryRequirements(device, pInfo->buffer, &pMemoryRequirements->memoryRequirements);
775 ''',
776 'vkGetDeviceBufferMemoryRequirements': '''
777 // TODO: Just hard-coding reqs for now
778 pMemoryRequirements->memoryRequirements.alignment = 1;
779 pMemoryRequirements->memoryRequirements.memoryTypeBits = 0xFFFF;
781 // Return a size based on the buffer size from the create info.
782 pMemoryRequirements->memoryRequirements.size = ((pInfo->pCreateInfo->size + 4095) / 4096) * 4096;
783 ''',
784 'vkGetDeviceBufferMemoryRequirementsKHR': '''
785 GetDeviceBufferMemoryRequirements(device, pInfo, pMemoryRequirements);
786 ''',
787 'vkGetImageMemoryRequirements': '''
788 pMemoryRequirements->size = 0;
789 pMemoryRequirements->alignment = 1;
791 unique_lock_t lock(global_lock);
792 auto d_iter = image_memory_size_map.find(device);
793 if(d_iter != image_memory_size_map.end()){
794 auto iter = d_iter->second.find(image);
795 if (iter != d_iter->second.end()) {
796 pMemoryRequirements->size = iter->second;
799 // Here we hard-code that the memory type at index 3 doesn't support this image.
800 pMemoryRequirements->memoryTypeBits = 0xFFFF & ~(0x1 << 3);
801 ''',
802 'vkGetImageMemoryRequirements2KHR': '''
803 GetImageMemoryRequirements(device, pInfo->image, &pMemoryRequirements->memoryRequirements);
804 ''',
805 'vkGetDeviceImageMemoryRequirements': '''
806 pMemoryRequirements->memoryRequirements.size = GetImageSizeFromCreateInfo(pInfo->pCreateInfo);
807 pMemoryRequirements->memoryRequirements.alignment = 1;
808 // Here we hard-code that the memory type at index 3 doesn't support this image.
809 pMemoryRequirements->memoryRequirements.memoryTypeBits = 0xFFFF & ~(0x1 << 3);
810 ''',
811 'vkGetDeviceImageMemoryRequirementsKHR': '''
812 GetDeviceImageMemoryRequirements(device, pInfo, pMemoryRequirements);
813 ''',
814 'vkMapMemory': '''
815 unique_lock_t lock(global_lock);
816 if (VK_WHOLE_SIZE == size) {
817 if (allocated_memory_size_map.count(memory) != 0)
818 size = allocated_memory_size_map[memory] - offset;
819 else
820 size = 0x10000;
822 void* map_addr = malloc((size_t)size);
823 mapped_memory_map[memory].push_back(map_addr);
824 *ppData = map_addr;
825 return VK_SUCCESS;
826 ''',
827 'vkMapMemory2KHR': '''
828 return MapMemory(device, pMemoryMapInfo->memory, pMemoryMapInfo->offset, pMemoryMapInfo->size, pMemoryMapInfo->flags, ppData);
829 ''',
830 'vkUnmapMemory': '''
831 unique_lock_t lock(global_lock);
832 for (auto map_addr : mapped_memory_map[memory]) {
833 free(map_addr);
835 mapped_memory_map.erase(memory);
836 ''',
837 'vkUnmapMemory2KHR': '''
838 UnmapMemory(device, pMemoryUnmapInfo->memory);
839 return VK_SUCCESS;
840 ''',
841 'vkGetImageSubresourceLayout': '''
842 // Need safe values. Callers are computing memory offsets from pLayout, with no return code to flag failure.
843 *pLayout = VkSubresourceLayout(); // Default constructor zero values.
844 ''',
845 'vkCreateSwapchainKHR': '''
846 unique_lock_t lock(global_lock);
847 *pSwapchain = (VkSwapchainKHR)global_unique_handle++;
848 for(uint32_t i = 0; i < icd_swapchain_image_count; ++i){
849 swapchain_image_map[*pSwapchain][i] = (VkImage)global_unique_handle++;
851 return VK_SUCCESS;
852 ''',
853 'vkDestroySwapchainKHR': '''
854 unique_lock_t lock(global_lock);
855 swapchain_image_map.clear();
856 ''',
857 'vkGetSwapchainImagesKHR': '''
858 if (!pSwapchainImages) {
859 *pSwapchainImageCount = icd_swapchain_image_count;
860 } else {
861 unique_lock_t lock(global_lock);
862 for (uint32_t img_i = 0; img_i < (std::min)(*pSwapchainImageCount, icd_swapchain_image_count); ++img_i){
863 pSwapchainImages[img_i] = swapchain_image_map.at(swapchain)[img_i];
866 if (*pSwapchainImageCount < icd_swapchain_image_count) return VK_INCOMPLETE;
867 else if (*pSwapchainImageCount > icd_swapchain_image_count) *pSwapchainImageCount = icd_swapchain_image_count;
869 return VK_SUCCESS;
870 ''',
871 'vkAcquireNextImageKHR': '''
872 *pImageIndex = 0;
873 return VK_SUCCESS;
874 ''',
875 'vkAcquireNextImage2KHR': '''
876 *pImageIndex = 0;
877 return VK_SUCCESS;
878 ''',
879 'vkCreateBuffer': '''
880 unique_lock_t lock(global_lock);
881 *pBuffer = (VkBuffer)global_unique_handle++;
882 buffer_map[device][*pBuffer] = {
883 pCreateInfo->size,
884 current_available_address
886 current_available_address += pCreateInfo->size;
887 // Always align to next 64-bit pointer
888 const uint64_t alignment = current_available_address % 64;
889 if (alignment != 0) {
890 current_available_address += (64 - alignment);
892 return VK_SUCCESS;
893 ''',
894 'vkDestroyBuffer': '''
895 unique_lock_t lock(global_lock);
896 buffer_map[device].erase(buffer);
897 ''',
898 'vkCreateImage': '''
899 unique_lock_t lock(global_lock);
900 *pImage = (VkImage)global_unique_handle++;
901 image_memory_size_map[device][*pImage] = GetImageSizeFromCreateInfo(pCreateInfo);
902 return VK_SUCCESS;
903 ''',
904 'vkDestroyImage': '''
905 unique_lock_t lock(global_lock);
906 image_memory_size_map[device].erase(image);
907 ''',
908 'vkEnumeratePhysicalDeviceGroupsKHR': '''
909 if (!pPhysicalDeviceGroupProperties) {
910 *pPhysicalDeviceGroupCount = 1;
911 } else {
912 // arbitrary
913 pPhysicalDeviceGroupProperties->physicalDeviceCount = 1;
914 pPhysicalDeviceGroupProperties->physicalDevices[0] = physical_device_map.at(instance)[0];
915 pPhysicalDeviceGroupProperties->subsetAllocation = VK_FALSE;
917 return VK_SUCCESS;
918 ''',
919 'vkGetPhysicalDeviceMultisamplePropertiesEXT': '''
920 if (pMultisampleProperties) {
921 // arbitrary
922 pMultisampleProperties->maxSampleLocationGridSize = {32, 32};
924 ''',
925 'vkGetPhysicalDeviceFragmentShadingRatesKHR': '''
926 if (!pFragmentShadingRates) {
927 *pFragmentShadingRateCount = 1;
928 } else {
929 // arbitrary
930 pFragmentShadingRates->sampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT;
931 pFragmentShadingRates->fragmentSize = {8, 8};
933 return VK_SUCCESS;
934 ''',
935 'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT': '''
936 if (!pTimeDomains) {
937 *pTimeDomainCount = 1;
938 } else {
939 // arbitrary
940 *pTimeDomains = VK_TIME_DOMAIN_DEVICE_EXT;
942 return VK_SUCCESS;
943 ''',
944 'vkGetPhysicalDeviceCalibrateableTimeDomainsKHR': '''
945 if (!pTimeDomains) {
946 *pTimeDomainCount = 1;
947 } else {
948 // arbitrary
949 *pTimeDomains = VK_TIME_DOMAIN_DEVICE_KHR;
951 return VK_SUCCESS;
952 ''',
953 'vkGetFenceWin32HandleKHR': '''
954 *pHandle = (HANDLE)0x12345678;
955 return VK_SUCCESS;
956 ''',
957 'vkGetFenceFdKHR': '''
958 *pFd = 0x42;
959 return VK_SUCCESS;
960 ''',
961 'vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR': '''
962 if (!pCounters) {
963 *pCounterCount = 3;
964 } else {
965 if (*pCounterCount == 0){
966 return VK_INCOMPLETE;
968 // arbitrary
969 pCounters[0].unit = VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR;
970 pCounters[0].scope = VK_QUERY_SCOPE_COMMAND_BUFFER_KHR;
971 pCounters[0].storage = VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR;
972 pCounters[0].uuid[0] = 0x01;
973 if (*pCounterCount == 1){
974 return VK_INCOMPLETE;
976 pCounters[1].unit = VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR;
977 pCounters[1].scope = VK_QUERY_SCOPE_RENDER_PASS_KHR;
978 pCounters[1].storage = VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR;
979 pCounters[1].uuid[0] = 0x02;
980 if (*pCounterCount == 2){
981 return VK_INCOMPLETE;
983 pCounters[2].unit = VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR;
984 pCounters[2].scope = VK_QUERY_SCOPE_COMMAND_KHR;
985 pCounters[2].storage = VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR;
986 pCounters[2].uuid[0] = 0x03;
987 *pCounterCount = 3;
989 return VK_SUCCESS;
990 ''',
991 'vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR': '''
992 if (pNumPasses) {
993 // arbitrary
994 *pNumPasses = 1;
996 ''',
997 'vkGetShaderModuleIdentifierEXT': '''
998 if (pIdentifier) {
999 // arbitrary
1000 pIdentifier->identifierSize = 1;
1001 pIdentifier->identifier[0] = 0x01;
1003 ''',
1004 'vkGetImageSparseMemoryRequirements': '''
1005 if (!pSparseMemoryRequirements) {
1006 *pSparseMemoryRequirementCount = 1;
1007 } else {
1008 // arbitrary
1009 pSparseMemoryRequirements->imageMipTailFirstLod = 0;
1010 pSparseMemoryRequirements->imageMipTailSize = 8;
1011 pSparseMemoryRequirements->imageMipTailOffset = 0;
1012 pSparseMemoryRequirements->imageMipTailStride = 4;
1013 pSparseMemoryRequirements->formatProperties.imageGranularity = {4, 4, 4};
1014 pSparseMemoryRequirements->formatProperties.flags = VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT;
1015 // Would need to track the VkImage to know format for better value here
1016 pSparseMemoryRequirements->formatProperties.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_METADATA_BIT;
1019 ''',
1020 'vkGetImageSparseMemoryRequirements2KHR': '''
1021 if (pSparseMemoryRequirementCount && pSparseMemoryRequirements) {
1022 GetImageSparseMemoryRequirements(device, pInfo->image, pSparseMemoryRequirementCount, &pSparseMemoryRequirements->memoryRequirements);
1023 } else {
1024 GetImageSparseMemoryRequirements(device, pInfo->image, pSparseMemoryRequirementCount, nullptr);
1026 ''',
1027 'vkGetBufferDeviceAddress': '''
1028 VkDeviceAddress address = 0;
1029 auto d_iter = buffer_map.find(device);
1030 if (d_iter != buffer_map.end()) {
1031 auto iter = d_iter->second.find(pInfo->buffer);
1032 if (iter != d_iter->second.end()) {
1033 address = iter->second.address;
1036 return address;
1037 ''',
1038 'vkGetBufferDeviceAddressKHR': '''
1039 return GetBufferDeviceAddress(device, pInfo);
1040 ''',
1041 'vkGetBufferDeviceAddressEXT': '''
1042 return GetBufferDeviceAddress(device, pInfo);
1043 ''',
1044 'vkGetDescriptorSetLayoutSizeEXT': '''
1045 // Need to give something non-zero
1046 *pLayoutSizeInBytes = 4;
1047 ''',
1048 'vkGetAccelerationStructureBuildSizesKHR': '''
1049 // arbitrary
1050 pSizeInfo->accelerationStructureSize = 4;
1051 pSizeInfo->updateScratchSize = 4;
1052 pSizeInfo->buildScratchSize = 4;
1053 ''',
1054 'vkGetAccelerationStructureMemoryRequirementsNV': '''
1055 // arbitrary
1056 pMemoryRequirements->memoryRequirements.size = 4096;
1057 pMemoryRequirements->memoryRequirements.alignment = 1;
1058 pMemoryRequirements->memoryRequirements.memoryTypeBits = 0xFFFF;
1059 ''',
1060 'vkGetAccelerationStructureDeviceAddressKHR': '''
1061 // arbitrary - need to be aligned to 256 bytes
1062 return 0x262144;
1063 ''',
1064 'vkGetVideoSessionMemoryRequirementsKHR': '''
1065 if (!pMemoryRequirements) {
1066 *pMemoryRequirementsCount = 1;
1067 } else {
1068 // arbitrary
1069 pMemoryRequirements[0].memoryBindIndex = 0;
1070 pMemoryRequirements[0].memoryRequirements.size = 4096;
1071 pMemoryRequirements[0].memoryRequirements.alignment = 1;
1072 pMemoryRequirements[0].memoryRequirements.memoryTypeBits = 0xFFFF;
1074 return VK_SUCCESS;
1075 ''',
1076 'vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR': '''
1077 if (!pProperties) {
1078 *pPropertyCount = 2;
1079 } else {
1080 // arbitrary
1081 pProperties[0].MSize = 16;
1082 pProperties[0].NSize = 16;
1083 pProperties[0].KSize = 16;
1084 pProperties[0].AType = VK_COMPONENT_TYPE_UINT32_KHR;
1085 pProperties[0].BType = VK_COMPONENT_TYPE_UINT32_KHR;
1086 pProperties[0].CType = VK_COMPONENT_TYPE_UINT32_KHR;
1087 pProperties[0].ResultType = VK_COMPONENT_TYPE_UINT32_KHR;
1088 pProperties[0].saturatingAccumulation = VK_FALSE;
1089 pProperties[0].scope = VK_SCOPE_SUBGROUP_KHR;
1091 pProperties[1] = pProperties[0];
1092 pProperties[1].scope = VK_SCOPE_DEVICE_KHR;
1094 return VK_SUCCESS;
1095 ''',
1096 'vkGetPhysicalDeviceVideoCapabilitiesKHR': '''
1097 // We include some reasonable set of capability combinations to cover a wide range of use cases
1098 auto caps = pCapabilities;
1099 auto caps_decode = lvl_find_mod_in_chain<VkVideoDecodeCapabilitiesKHR>(pCapabilities->pNext);
1100 auto caps_decode_h264 = lvl_find_mod_in_chain<VkVideoDecodeH264CapabilitiesKHR>(pCapabilities->pNext);
1101 auto caps_decode_h265 = lvl_find_mod_in_chain<VkVideoDecodeH265CapabilitiesKHR>(pCapabilities->pNext);
1102 auto caps_decode_av1 = lvl_find_mod_in_chain<VkVideoDecodeAV1CapabilitiesKHR>(pCapabilities->pNext);
1103 auto caps_encode = lvl_find_mod_in_chain<VkVideoEncodeCapabilitiesKHR>(pCapabilities->pNext);
1104 auto caps_encode_quantization_map =
1105 lvl_find_mod_in_chain<VkVideoEncodeQuantizationMapCapabilitiesKHR>(pCapabilities->pNext);
1106 auto caps_encode_h264_quantization_map =
1107 lvl_find_mod_in_chain<VkVideoEncodeH264QuantizationMapCapabilitiesKHR>(pCapabilities->pNext);
1108 auto caps_encode_h265_quantization_map =
1109 lvl_find_mod_in_chain<VkVideoEncodeH265QuantizationMapCapabilitiesKHR>(pCapabilities->pNext);
1110 auto caps_encode_av1_quantization_map =
1111 lvl_find_mod_in_chain<VkVideoEncodeAV1QuantizationMapCapabilitiesKHR>(pCapabilities->pNext);
1112 auto caps_encode_h264 = lvl_find_mod_in_chain<VkVideoEncodeH264CapabilitiesKHR>(pCapabilities->pNext);
1113 auto caps_encode_h265 = lvl_find_mod_in_chain<VkVideoEncodeH265CapabilitiesKHR>(pCapabilities->pNext);
1114 auto caps_encode_av1 = lvl_find_mod_in_chain<VkVideoEncodeAV1CapabilitiesKHR>(pCapabilities->pNext);
1116 switch (pVideoProfile->videoCodecOperation) {
1117 case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR: {
1118 auto profile = lvl_find_in_chain<VkVideoDecodeH264ProfileInfoKHR>(pVideoProfile->pNext);
1119 if (profile->stdProfileIdc != STD_VIDEO_H264_PROFILE_IDC_BASELINE &&
1120 profile->stdProfileIdc != STD_VIDEO_H264_PROFILE_IDC_MAIN) {
1121 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1124 caps->flags = VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR;
1125 caps->minBitstreamBufferOffsetAlignment = 256;
1126 caps->minBitstreamBufferSizeAlignment = 256;
1127 caps->pictureAccessGranularity = {16,16};
1128 caps->minCodedExtent = {16,16};
1129 caps->maxCodedExtent = {1920,1080};
1130 caps->maxDpbSlots = 33;
1131 caps->maxActiveReferencePictures = 32;
1132 std::strncpy(caps->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME,
1133 sizeof(caps->stdHeaderVersion.extensionName));
1134 caps->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION;
1136 switch (pVideoProfile->chromaSubsampling) {
1137 case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR:
1138 if (profile->pictureLayout != VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR) {
1139 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1141 caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR;
1142 caps_decode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_6_2;
1143 caps_decode_h264->fieldOffsetGranularity = {0,0};
1144 break;
1145 case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR:
1146 if (profile->pictureLayout != VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR &&
1147 profile->pictureLayout != VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_KHR) {
1148 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1150 caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR;
1151 caps_decode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_5_0;
1152 caps_decode_h264->fieldOffsetGranularity = {0,16};
1153 break;
1154 case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR:
1155 if (profile->pictureLayout != VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR &&
1156 profile->pictureLayout != VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR) {
1157 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1159 caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR
1160 | VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR;
1161 caps_decode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_3_2;
1162 caps_decode_h264->fieldOffsetGranularity = {0,1};
1163 break;
1164 default:
1165 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1167 break;
1169 case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR: {
1170 auto profile = lvl_find_in_chain<VkVideoDecodeH265ProfileInfoKHR>(pVideoProfile->pNext);
1171 if (profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN) {
1172 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1175 caps->flags = VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR;
1176 caps->minBitstreamBufferOffsetAlignment = 64;
1177 caps->minBitstreamBufferSizeAlignment = 64;
1178 caps->pictureAccessGranularity = {32,32};
1179 caps->minCodedExtent = {48,48};
1180 caps->maxCodedExtent = {3840,2160};
1181 caps->maxDpbSlots = 16;
1182 caps->maxActiveReferencePictures = 15;
1183 std::strncpy(caps->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME,
1184 sizeof(caps->stdHeaderVersion.extensionName));
1185 caps->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION;
1187 switch (pVideoProfile->chromaSubsampling) {
1188 case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR:
1189 caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR;
1190 caps_decode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_6_0;
1191 break;
1192 case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR:
1193 caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR;
1194 caps_decode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_5_2;
1195 break;
1196 case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR:
1197 caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR
1198 | VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR;
1199 caps_decode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_4_1;
1200 break;
1201 default:
1202 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1204 break;
1206 case VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR: {
1207 auto profile = lvl_find_in_chain<VkVideoDecodeAV1ProfileInfoKHR>(pVideoProfile->pNext);
1208 if (profile->stdProfile != STD_VIDEO_AV1_PROFILE_MAIN) {
1209 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1212 caps->flags = VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR;
1213 caps->minBitstreamBufferOffsetAlignment = 256;
1214 caps->minBitstreamBufferSizeAlignment = 256;
1215 caps->pictureAccessGranularity = {16,16};
1216 caps->minCodedExtent = {16,16};
1217 caps->maxCodedExtent = {1920,1080};
1218 caps->maxDpbSlots = 8;
1219 caps->maxActiveReferencePictures = 7;
1220 std::strncpy(caps->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_EXTENSION_NAME,
1221 sizeof(caps->stdHeaderVersion.extensionName));
1222 caps->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_SPEC_VERSION;
1224 switch (pVideoProfile->chromaSubsampling) {
1225 case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR:
1226 caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR;
1227 caps_decode_av1->maxLevel = STD_VIDEO_AV1_LEVEL_6_2;
1228 break;
1229 case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR:
1230 if (profile->filmGrainSupport) {
1231 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1233 caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR;
1234 caps_decode_av1->maxLevel = STD_VIDEO_AV1_LEVEL_5_0;
1235 break;
1236 case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR:
1237 caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR
1238 | VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR;
1239 caps_decode_av1->maxLevel = STD_VIDEO_AV1_LEVEL_3_2;
1240 break;
1241 default:
1242 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1244 break;
1246 case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR: {
1247 auto profile = lvl_find_in_chain<VkVideoEncodeH264ProfileInfoKHR>(pVideoProfile->pNext);
1248 if (profile->stdProfileIdc != STD_VIDEO_H264_PROFILE_IDC_BASELINE) {
1249 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1252 caps->flags = VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR;
1253 caps->minBitstreamBufferOffsetAlignment = 4096;
1254 caps->minBitstreamBufferSizeAlignment = 4096;
1255 caps->pictureAccessGranularity = {16,16};
1256 caps->minCodedExtent = {160,128};
1257 caps->maxCodedExtent = {1920,1080};
1258 caps->maxDpbSlots = 10;
1259 caps->maxActiveReferencePictures = 4;
1260 std::strncpy(caps->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_EXTENSION_NAME,
1261 sizeof(caps->stdHeaderVersion.extensionName));
1262 caps->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION;
1264 switch (pVideoProfile->chromaSubsampling) {
1265 case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR:
1266 caps_encode->flags = VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR
1267 | VK_VIDEO_ENCODE_CAPABILITY_QUANTIZATION_DELTA_MAP_BIT_KHR
1268 | VK_VIDEO_ENCODE_CAPABILITY_EMPHASIS_MAP_BIT_KHR;
1269 caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR
1270 | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR
1271 | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR;
1272 caps_encode->maxRateControlLayers = 4;
1273 caps_encode->maxBitrate = 800000000;
1274 caps_encode->maxQualityLevels = 4;
1275 caps_encode->encodeInputPictureGranularity = {16,16};
1276 caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR
1277 | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR
1278 | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_HAS_OVERRIDES_BIT_KHR;
1279 caps_encode_h264->flags = VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_KHR
1280 | VK_VIDEO_ENCODE_H264_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_KHR
1281 | VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_KHR
1282 | VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_KHR
1283 | VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR
1284 | VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_KHR;
1285 caps_encode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_6_2;
1286 caps_encode_h264->maxSliceCount = 8;
1287 caps_encode_h264->maxPPictureL0ReferenceCount = 4;
1288 caps_encode_h264->maxBPictureL0ReferenceCount = 3;
1289 caps_encode_h264->maxL1ReferenceCount = 2;
1290 caps_encode_h264->maxTemporalLayerCount = 4;
1291 caps_encode_h264->expectDyadicTemporalLayerPattern = VK_FALSE;
1292 caps_encode_h264->minQp = 0;
1293 caps_encode_h264->maxQp = 51;
1294 caps_encode_h264->prefersGopRemainingFrames = VK_FALSE;
1295 caps_encode_h264->requiresGopRemainingFrames = VK_FALSE;
1297 if (caps_encode_quantization_map) {
1298 caps_encode_quantization_map->maxQuantizationMapExtent = {(caps->maxCodedExtent.width + 15) / 16,
1299 (caps->maxCodedExtent.height + 15) / 16};
1302 if (caps_encode_h264_quantization_map) {
1303 caps_encode_h264_quantization_map->minQpDelta = -26;
1304 caps_encode_h264_quantization_map->maxQpDelta = +25;
1306 break;
1307 case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR:
1308 caps_encode->flags = VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR
1309 | VK_VIDEO_ENCODE_CAPABILITY_EMPHASIS_MAP_BIT_KHR;
1310 caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR
1311 | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR;
1312 caps_encode->maxRateControlLayers = 1;
1313 caps_encode->maxBitrate = 480000000;
1314 caps_encode->maxQualityLevels = 3;
1315 caps_encode->encodeInputPictureGranularity = {32,32};
1316 caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR
1317 | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR;
1318 caps_encode_h264->flags = VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_KHR
1319 | VK_VIDEO_ENCODE_H264_CAPABILITY_PER_SLICE_CONSTANT_QP_BIT_KHR
1320 | VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_KHR;
1321 caps_encode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_6_1;
1322 caps_encode_h264->maxSliceCount = 4;
1323 caps_encode_h264->maxPPictureL0ReferenceCount = 4;
1324 caps_encode_h264->maxBPictureL0ReferenceCount = 0;
1325 caps_encode_h264->maxL1ReferenceCount = 0;
1326 caps_encode_h264->maxTemporalLayerCount = 4;
1327 caps_encode_h264->expectDyadicTemporalLayerPattern = VK_TRUE;
1328 caps_encode_h264->minQp = 0;
1329 caps_encode_h264->maxQp = 30;
1330 caps_encode_h264->prefersGopRemainingFrames = VK_TRUE;
1331 caps_encode_h264->requiresGopRemainingFrames = VK_FALSE;
1333 if (caps_encode_quantization_map) {
1334 caps_encode_quantization_map->maxQuantizationMapExtent = {(caps->maxCodedExtent.width + 15) / 16,
1335 (caps->maxCodedExtent.height + 15) / 16};
1338 if (caps_encode_h264_quantization_map) {
1339 caps_encode_h264_quantization_map->minQpDelta = 0;
1340 caps_encode_h264_quantization_map->maxQpDelta = 0;
1342 break;
1343 case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR:
1344 caps_encode->flags = 0;
1345 caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR;
1346 caps_encode->maxRateControlLayers = 1;
1347 caps_encode->maxBitrate = 240000000;
1348 caps_encode->maxQualityLevels = 1;
1349 caps_encode->encodeInputPictureGranularity = {1,1};
1350 caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR
1351 | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR;
1352 caps_encode_h264->flags = VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_KHR
1353 | VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_KHR
1354 | VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR;
1355 caps_encode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_5_1;
1356 caps_encode_h264->maxSliceCount = 1;
1357 caps_encode_h264->maxPPictureL0ReferenceCount = 0;
1358 caps_encode_h264->maxBPictureL0ReferenceCount = 2;
1359 caps_encode_h264->maxL1ReferenceCount = 2;
1360 caps_encode_h264->maxTemporalLayerCount = 1;
1361 caps_encode_h264->expectDyadicTemporalLayerPattern = VK_FALSE;
1362 caps_encode_h264->minQp = 5;
1363 caps_encode_h264->maxQp = 40;
1364 caps_encode_h264->prefersGopRemainingFrames = VK_TRUE;
1365 caps_encode_h264->requiresGopRemainingFrames = VK_TRUE;
1367 if (caps_encode_quantization_map) {
1368 caps_encode_quantization_map->maxQuantizationMapExtent = {0, 0};
1371 if (caps_encode_h264_quantization_map) {
1372 caps_encode_h264_quantization_map->minQpDelta = 0;
1373 caps_encode_h264_quantization_map->maxQpDelta = 0;
1375 break;
1376 default:
1377 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1379 break;
1381 case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR: {
1382 auto profile = lvl_find_in_chain<VkVideoEncodeH265ProfileInfoKHR>(pVideoProfile->pNext);
1383 if (profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN) {
1384 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1387 caps->flags = VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR;
1388 caps->minBitstreamBufferOffsetAlignment = 1;
1389 caps->minBitstreamBufferSizeAlignment = 1;
1390 caps->pictureAccessGranularity = {8,8};
1391 caps->minCodedExtent = {64,48};
1392 caps->maxCodedExtent = {4096,2560};
1393 caps->maxDpbSlots = 8;
1394 caps->maxActiveReferencePictures = 2;
1395 std::strncpy(caps->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME, sizeof(caps->stdHeaderVersion.extensionName));
1396 caps->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION;
1398 switch (pVideoProfile->chromaSubsampling) {
1399 case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR:
1400 caps_encode->flags = VK_VIDEO_ENCODE_CAPABILITY_EMPHASIS_MAP_BIT_KHR;
1401 caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR;
1402 caps_encode->maxRateControlLayers = 1;
1403 caps_encode->maxBitrate = 800000000;
1404 caps_encode->maxQualityLevels = 1;
1405 caps_encode->encodeInputPictureGranularity = {64,64};
1406 caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR
1407 | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR;
1408 caps_encode_h265->flags = VK_VIDEO_ENCODE_H265_CAPABILITY_HRD_COMPLIANCE_BIT_KHR
1409 | VK_VIDEO_ENCODE_H265_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_KHR
1410 | VK_VIDEO_ENCODE_H265_CAPABILITY_ROW_UNALIGNED_SLICE_SEGMENT_BIT_KHR
1411 | VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_KHR
1412 | VK_VIDEO_ENCODE_H265_CAPABILITY_PER_SLICE_SEGMENT_CONSTANT_QP_BIT_KHR
1413 | VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_SLICE_SEGMENTS_PER_TILE_BIT_KHR;
1414 caps_encode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_6_2;
1415 caps_encode_h265->maxSliceSegmentCount = 8;
1416 caps_encode_h265->maxTiles = {1,1};
1417 caps_encode_h265->ctbSizes = VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_KHR
1418 | VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR;
1419 caps_encode_h265->transformBlockSizes = VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_KHR
1420 | VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_KHR
1421 | VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR;
1422 caps_encode_h265->maxPPictureL0ReferenceCount = 4;
1423 caps_encode_h265->maxBPictureL0ReferenceCount = 3;
1424 caps_encode_h265->maxL1ReferenceCount = 2;
1425 caps_encode_h265->maxSubLayerCount = 1;
1426 caps_encode_h265->expectDyadicTemporalSubLayerPattern = VK_FALSE;
1427 caps_encode_h265->minQp = 16;
1428 caps_encode_h265->maxQp = 32;
1429 caps_encode_h265->prefersGopRemainingFrames = VK_FALSE;
1430 caps_encode_h265->requiresGopRemainingFrames = VK_FALSE;
1432 if (caps_encode_quantization_map) {
1433 caps_encode_quantization_map->maxQuantizationMapExtent = {(caps->maxCodedExtent.width + 3) / 4,
1434 (caps->maxCodedExtent.height + 3) / 4};
1437 if (caps_encode_h265_quantization_map) {
1438 caps_encode_h265_quantization_map->minQpDelta = -16;
1439 caps_encode_h265_quantization_map->maxQpDelta = +15;
1441 break;
1442 case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR:
1443 caps_encode->flags = VK_VIDEO_ENCODE_CAPABILITY_QUANTIZATION_DELTA_MAP_BIT_KHR;
1444 caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
1445 caps_encode->maxRateControlLayers = 0;
1446 caps_encode->maxBitrate = 480000000;
1447 caps_encode->maxQualityLevels = 2;
1448 caps_encode->encodeInputPictureGranularity = {32,32};
1449 caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR
1450 | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR;
1451 caps_encode_h265->flags = VK_VIDEO_ENCODE_H265_CAPABILITY_DIFFERENT_SLICE_SEGMENT_TYPE_BIT_KHR;
1452 caps_encode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_6_1;
1453 caps_encode_h265->maxSliceSegmentCount = 4;
1454 caps_encode_h265->maxTiles = {2,2};
1455 caps_encode_h265->ctbSizes = VK_VIDEO_ENCODE_H265_CTB_SIZE_16_BIT_KHR
1456 | VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR;
1457 caps_encode_h265->transformBlockSizes = VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_KHR
1458 | VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_KHR
1459 | VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR;
1460 caps_encode_h265->maxPPictureL0ReferenceCount = 4;
1461 caps_encode_h265->maxBPictureL0ReferenceCount = 0;
1462 caps_encode_h265->maxL1ReferenceCount = 0;
1463 caps_encode_h265->maxSubLayerCount = 1;
1464 caps_encode_h265->expectDyadicTemporalSubLayerPattern = VK_FALSE;
1465 caps_encode_h265->minQp = 0;
1466 caps_encode_h265->maxQp = 51;
1467 caps_encode_h265->prefersGopRemainingFrames = VK_TRUE;
1468 caps_encode_h265->requiresGopRemainingFrames = VK_FALSE;
1470 if (caps_encode_quantization_map) {
1471 caps_encode_quantization_map->maxQuantizationMapExtent = {(caps->maxCodedExtent.width + 31) / 32,
1472 (caps->maxCodedExtent.height + 31) / 32};
1475 if (caps_encode_h265_quantization_map) {
1476 caps_encode_h265_quantization_map->minQpDelta = 0;
1477 caps_encode_h265_quantization_map->maxQpDelta = 0;
1479 break;
1480 case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR:
1481 caps_encode->flags = VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR;
1482 caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR
1483 | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR
1484 | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR;
1485 caps_encode->maxRateControlLayers = 2;
1486 caps_encode->maxBitrate = 240000000;
1487 caps_encode->maxQualityLevels = 3;
1488 caps_encode->encodeInputPictureGranularity = {16,16};
1489 caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR
1490 | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR
1491 | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_HAS_OVERRIDES_BIT_KHR;
1492 caps_encode_h265->flags = VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_KHR
1493 | VK_VIDEO_ENCODE_H265_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR
1494 | VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILES_PER_SLICE_SEGMENT_BIT_KHR;
1495 caps_encode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_5_1;
1496 caps_encode_h265->maxSliceSegmentCount = 1;
1497 caps_encode_h265->maxTiles = {2,2};
1498 caps_encode_h265->ctbSizes = VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_KHR;
1499 caps_encode_h265->transformBlockSizes = VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR;
1500 caps_encode_h265->maxPPictureL0ReferenceCount = 0;
1501 caps_encode_h265->maxBPictureL0ReferenceCount = 2;
1502 caps_encode_h265->maxL1ReferenceCount = 2;
1503 caps_encode_h265->maxSubLayerCount = 4;
1504 caps_encode_h265->expectDyadicTemporalSubLayerPattern = VK_TRUE;
1505 caps_encode_h265->minQp = 16;
1506 caps_encode_h265->maxQp = 51;
1507 caps_encode_h265->prefersGopRemainingFrames = VK_TRUE;
1508 caps_encode_h265->requiresGopRemainingFrames = VK_TRUE;
1510 if (caps_encode_quantization_map) {
1511 caps_encode_quantization_map->maxQuantizationMapExtent = {0, 0};
1514 if (caps_encode_h265_quantization_map) {
1515 caps_encode_h265_quantization_map->minQpDelta = 0;
1516 caps_encode_h265_quantization_map->maxQpDelta = 0;
1518 break;
1519 default:
1520 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1522 break;
1524 case VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR: {
1525 auto profile = lvl_find_in_chain<VkVideoEncodeAV1ProfileInfoKHR>(pVideoProfile->pNext);
1526 if (profile->stdProfile != STD_VIDEO_AV1_PROFILE_MAIN) {
1527 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1530 caps->flags = VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR;
1531 caps->minBitstreamBufferOffsetAlignment = 1;
1532 caps->minBitstreamBufferSizeAlignment = 1;
1533 caps->pictureAccessGranularity = {8,8};
1534 caps->minCodedExtent = {192,128};
1535 caps->maxCodedExtent = {4096,2560};
1536 caps->maxDpbSlots = 8;
1537 caps->maxActiveReferencePictures = 2;
1538 std::strncpy(caps->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_EXTENSION_NAME, sizeof(caps->stdHeaderVersion.extensionName));
1539 caps->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_SPEC_VERSION;
1541 switch (pVideoProfile->chromaSubsampling) {
1542 case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR:
1543 caps_encode->flags = VK_VIDEO_ENCODE_CAPABILITY_QUANTIZATION_DELTA_MAP_BIT_KHR
1544 | VK_VIDEO_ENCODE_CAPABILITY_EMPHASIS_MAP_BIT_KHR;
1545 caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR;
1546 caps_encode->maxRateControlLayers = 1;
1547 caps_encode->maxBitrate = 800000000;
1548 caps_encode->maxQualityLevels = 1;
1549 caps_encode->encodeInputPictureGranularity = {64,64};
1550 caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR
1551 | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR;
1552 caps_encode_av1->flags = VK_VIDEO_ENCODE_AV1_CAPABILITY_PRIMARY_REFERENCE_CDF_ONLY_BIT_KHR;
1553 caps_encode_av1->maxLevel = STD_VIDEO_AV1_LEVEL_6_2;
1554 caps_encode_av1->maxTiles = {1,1};
1555 caps_encode_av1->minTileSize = {64,64};
1556 caps_encode_av1->maxTileSize = {4096,2560};
1557 caps_encode_av1->superblockSizes = VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_64_BIT_KHR;
1558 caps_encode_av1->maxSingleReferenceCount = 1;
1559 caps_encode_av1->singleReferenceNameMask = 0x7B;
1560 caps_encode_av1->maxUnidirectionalCompoundReferenceCount = 0;
1561 caps_encode_av1->maxUnidirectionalCompoundGroup1ReferenceCount = 0;
1562 caps_encode_av1->unidirectionalCompoundReferenceNameMask = 0x00;
1563 caps_encode_av1->maxBidirectionalCompoundReferenceCount = 0;
1564 caps_encode_av1->maxBidirectionalCompoundGroup1ReferenceCount = 0;
1565 caps_encode_av1->maxBidirectionalCompoundGroup2ReferenceCount = 0;
1566 caps_encode_av1->bidirectionalCompoundReferenceNameMask = 0x00;
1567 caps_encode_av1->maxTemporalLayerCount = 1;
1568 caps_encode_av1->maxSpatialLayerCount = 1;
1569 caps_encode_av1->maxOperatingPoints = 1;
1570 caps_encode_av1->minQIndex = 32;
1571 caps_encode_av1->maxQIndex = 128;
1572 caps_encode_av1->prefersGopRemainingFrames = VK_FALSE;
1573 caps_encode_av1->requiresGopRemainingFrames = VK_FALSE;
1575 if (caps_encode_quantization_map) {
1576 caps_encode_quantization_map->maxQuantizationMapExtent = {(caps->maxCodedExtent.width + 7) / 8,
1577 (caps->maxCodedExtent.height + 7) / 8};
1580 if (caps_encode_av1_quantization_map) {
1581 caps_encode_av1_quantization_map->minQIndexDelta = -64;
1582 caps_encode_av1_quantization_map->maxQIndexDelta = +64;
1584 break;
1585 case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR:
1586 caps_encode->flags = VK_VIDEO_ENCODE_CAPABILITY_QUANTIZATION_DELTA_MAP_BIT_KHR;
1587 caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
1588 caps_encode->maxRateControlLayers = 0;
1589 caps_encode->maxBitrate = 480000000;
1590 caps_encode->maxQualityLevels = 2;
1591 caps_encode->encodeInputPictureGranularity = {32,32};
1592 caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR
1593 | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR;
1594 caps_encode_av1->flags = VK_VIDEO_ENCODE_AV1_CAPABILITY_PRIMARY_REFERENCE_CDF_ONLY_BIT_KHR
1595 | VK_VIDEO_ENCODE_AV1_CAPABILITY_GENERATE_OBU_EXTENSION_HEADER_BIT_KHR
1596 | VK_VIDEO_ENCODE_AV1_CAPABILITY_FRAME_SIZE_OVERRIDE_BIT_KHR;
1597 caps_encode_av1->maxLevel = STD_VIDEO_AV1_LEVEL_6_1;
1598 caps_encode_av1->maxTiles = {2,2};
1599 caps_encode_av1->minTileSize = {128,128};
1600 caps_encode_av1->maxTileSize = {4096,2048};
1601 caps_encode_av1->superblockSizes = VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_64_BIT_KHR
1602 | VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_128_BIT_KHR;
1603 caps_encode_av1->maxSingleReferenceCount = 0;
1604 caps_encode_av1->singleReferenceNameMask = 0x00;
1605 caps_encode_av1->maxUnidirectionalCompoundReferenceCount = 2;
1606 caps_encode_av1->maxUnidirectionalCompoundGroup1ReferenceCount = 2;
1607 caps_encode_av1->unidirectionalCompoundReferenceNameMask = 0x5F;
1608 caps_encode_av1->maxBidirectionalCompoundReferenceCount = 2;
1609 caps_encode_av1->maxBidirectionalCompoundGroup1ReferenceCount = 2;
1610 caps_encode_av1->maxBidirectionalCompoundGroup2ReferenceCount = 2;
1611 caps_encode_av1->bidirectionalCompoundReferenceNameMask = 0x5F;
1612 caps_encode_av1->maxTemporalLayerCount = 4;
1613 caps_encode_av1->maxSpatialLayerCount = 1;
1614 caps_encode_av1->maxOperatingPoints = 4;
1615 caps_encode_av1->minQIndex = 0;
1616 caps_encode_av1->maxQIndex = 255;
1617 caps_encode_av1->prefersGopRemainingFrames = VK_TRUE;
1618 caps_encode_av1->requiresGopRemainingFrames = VK_FALSE;
1620 if (caps_encode_quantization_map) {
1621 caps_encode_quantization_map->maxQuantizationMapExtent = {(caps->maxCodedExtent.width + 63) / 64,
1622 (caps->maxCodedExtent.height + 63) / 64};
1625 if (caps_encode_av1_quantization_map) {
1626 caps_encode_av1_quantization_map->minQIndexDelta = -255;
1627 caps_encode_av1_quantization_map->maxQIndexDelta = +255;
1629 break;
1630 case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR:
1631 caps_encode->flags = VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR
1632 | VK_VIDEO_ENCODE_CAPABILITY_EMPHASIS_MAP_BIT_KHR;
1633 caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR
1634 | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR
1635 | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR;
1636 caps_encode->maxRateControlLayers = 2;
1637 caps_encode->maxBitrate = 240000000;
1638 caps_encode->maxQualityLevels = 3;
1639 caps_encode->encodeInputPictureGranularity = {16,16};
1640 caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR
1641 | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR
1642 | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_HAS_OVERRIDES_BIT_KHR;
1643 caps_encode_av1->flags = VK_VIDEO_ENCODE_AV1_CAPABILITY_PER_RATE_CONTROL_GROUP_MIN_MAX_Q_INDEX_BIT_KHR
1644 | VK_VIDEO_ENCODE_AV1_CAPABILITY_FRAME_SIZE_OVERRIDE_BIT_KHR
1645 | VK_VIDEO_ENCODE_AV1_CAPABILITY_MOTION_VECTOR_SCALING_BIT_KHR;
1646 caps_encode_av1->maxLevel = STD_VIDEO_AV1_LEVEL_5_1;
1647 caps_encode_av1->maxTiles = {4,4};
1648 caps_encode_av1->minTileSize = {128,128};
1649 caps_encode_av1->maxTileSize = {2048,2048};
1650 caps_encode_av1->superblockSizes = VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_128_BIT_KHR;
1651 caps_encode_av1->maxSingleReferenceCount = 1;
1652 caps_encode_av1->singleReferenceNameMask = 0x5F;
1653 caps_encode_av1->maxUnidirectionalCompoundReferenceCount = 4;
1654 caps_encode_av1->maxUnidirectionalCompoundGroup1ReferenceCount = 4;
1655 caps_encode_av1->unidirectionalCompoundReferenceNameMask = 0x5B;
1656 caps_encode_av1->maxBidirectionalCompoundReferenceCount = 0;
1657 caps_encode_av1->maxBidirectionalCompoundGroup1ReferenceCount = 0;
1658 caps_encode_av1->maxBidirectionalCompoundGroup2ReferenceCount = 0;
1659 caps_encode_av1->bidirectionalCompoundReferenceNameMask = 0x00;
1660 caps_encode_av1->maxTemporalLayerCount = 4;
1661 caps_encode_av1->maxSpatialLayerCount = 2;
1662 caps_encode_av1->maxOperatingPoints = 2;
1663 caps_encode_av1->minQIndex = 16;
1664 caps_encode_av1->maxQIndex = 96;
1665 caps_encode_av1->prefersGopRemainingFrames = VK_TRUE;
1666 caps_encode_av1->requiresGopRemainingFrames = VK_TRUE;
1668 if (caps_encode_quantization_map) {
1669 caps_encode_quantization_map->maxQuantizationMapExtent = {(caps->maxCodedExtent.width + 127) / 128,
1670 (caps->maxCodedExtent.height + 127) / 128};
1673 if (caps_encode_av1_quantization_map) {
1674 caps_encode_av1_quantization_map->minQIndexDelta = -64;
1675 caps_encode_av1_quantization_map->maxQIndexDelta = +63;
1677 break;
1678 default:
1679 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1681 break;
1683 default:
1684 break;
1686 return VK_SUCCESS;
1687 ''',
1688 'vkGetPhysicalDeviceVideoFormatPropertiesKHR': '''
1689 // We include some reasonable set of format combinations to cover a wide range of use cases
1690 auto profile_list = lvl_find_in_chain<VkVideoProfileListInfoKHR>(pVideoFormatInfo->pNext);
1691 if (profile_list->profileCount != 1) {
1692 return VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR;
1695 struct VideoFormatProperties {
1696 VkVideoFormatPropertiesKHR props;
1697 VkVideoFormatQuantizationMapPropertiesKHR props_quantization_map;
1698 VkVideoFormatH265QuantizationMapPropertiesKHR props_h265_quantization_map;
1699 VkVideoFormatAV1QuantizationMapPropertiesKHR props_av1_quantization_map;
1702 std::vector<VideoFormatProperties> format_props{};
1704 VideoFormatProperties fmt = {};
1705 fmt.props.sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR;
1706 fmt.props.imageCreateFlags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_ALIAS_BIT |
1707 VK_IMAGE_CREATE_EXTENDED_USAGE_BIT | VK_IMAGE_CREATE_PROTECTED_BIT | VK_IMAGE_CREATE_DISJOINT_BIT;
1708 fmt.props.imageType = VK_IMAGE_TYPE_2D;
1709 fmt.props.imageTiling = VK_IMAGE_TILING_OPTIMAL;
1710 fmt.props_quantization_map.sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_QUANTIZATION_MAP_PROPERTIES_KHR;
1711 fmt.props_h265_quantization_map.sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_H265_QUANTIZATION_MAP_PROPERTIES_KHR;
1712 fmt.props_av1_quantization_map.sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_AV1_QUANTIZATION_MAP_PROPERTIES_KHR;
1714 // Populate DPB and input/output formats
1715 switch (profile_list->pProfiles[0].videoCodecOperation) {
1716 case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
1717 case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
1718 case VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR:
1719 switch (profile_list->pProfiles[0].chromaSubsampling) {
1720 case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR:
1721 fmt.props.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
1722 fmt.props.imageUsageFlags =
1723 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR;
1724 format_props.push_back(fmt);
1725 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1726 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
1727 VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR |
1728 VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
1729 format_props.push_back(fmt);
1730 fmt.props.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
1731 format_props.push_back(fmt);
1732 break;
1733 case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR:
1734 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR;
1735 fmt.props.format = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM;
1736 format_props.push_back(fmt);
1737 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1738 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
1739 VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
1740 format_props.push_back(fmt);
1741 fmt.props.format = VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16;
1742 format_props.push_back(fmt);
1743 break;
1744 case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR:
1745 fmt.props.format = VK_FORMAT_G8_B8R8_2PLANE_444_UNORM;
1746 fmt.props.imageUsageFlags =
1747 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR;
1748 format_props.push_back(fmt);
1749 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1750 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
1751 VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR |
1752 VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
1753 format_props.push_back(fmt);
1754 break;
1755 default:
1756 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1758 break;
1759 case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR:
1760 case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR:
1761 case VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR:
1762 switch (profile_list->pProfiles[0].chromaSubsampling) {
1763 case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR:
1764 fmt.props.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
1765 fmt.props.imageUsageFlags =
1766 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR;
1767 format_props.push_back(fmt);
1768 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1769 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
1770 VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
1771 format_props.push_back(fmt);
1772 fmt.props.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
1773 format_props.push_back(fmt);
1774 break;
1775 case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR:
1776 fmt.props.format = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM;
1777 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR;
1778 format_props.push_back(fmt);
1779 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1780 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
1781 VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
1782 format_props.push_back(fmt);
1783 fmt.props.format = VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16;
1784 format_props.push_back(fmt);
1785 break;
1786 case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR:
1787 fmt.props.format = VK_FORMAT_G8_B8R8_2PLANE_444_UNORM;
1788 fmt.props.imageUsageFlags =
1789 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR;
1790 format_props.push_back(fmt);
1791 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1792 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
1793 VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
1794 format_props.push_back(fmt);
1795 break;
1796 default:
1797 return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
1799 break;
1801 default:
1802 break;
1805 // Populate quantization map formats
1806 fmt.props.imageCreateFlags = VK_IMAGE_CREATE_PROTECTED_BIT;
1807 fmt.props.imageTiling = VK_IMAGE_TILING_LINEAR;
1808 switch (profile_list->pProfiles[0].videoCodecOperation) {
1809 case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR:
1810 switch (profile_list->pProfiles[0].chromaSubsampling) {
1811 case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR:
1812 fmt.props.format = VK_FORMAT_R32_SINT;
1813 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1814 VK_IMAGE_USAGE_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR;
1815 fmt.props_quantization_map.quantizationMapTexelSize = {16, 16};
1816 format_props.push_back(fmt);
1817 fmt.props.format = VK_FORMAT_R8_UNORM;
1818 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1819 VK_IMAGE_USAGE_VIDEO_ENCODE_EMPHASIS_MAP_BIT_KHR;
1820 format_props.push_back(fmt);
1821 break;
1822 case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR:
1823 fmt.props.format = VK_FORMAT_R8_UNORM;
1824 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1825 VK_IMAGE_USAGE_VIDEO_ENCODE_EMPHASIS_MAP_BIT_KHR;
1826 fmt.props_quantization_map.quantizationMapTexelSize = {16, 16};
1827 format_props.push_back(fmt);
1828 break;
1829 case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR:
1830 break;
1831 default:
1832 break;
1834 break;
1835 case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR:
1836 switch (profile_list->pProfiles[0].chromaSubsampling) {
1837 case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR:
1838 fmt.props.format = VK_FORMAT_R8_UNORM;
1839 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1840 VK_IMAGE_USAGE_VIDEO_ENCODE_EMPHASIS_MAP_BIT_KHR;
1841 fmt.props_quantization_map.quantizationMapTexelSize = {4, 4};
1842 fmt.props_h265_quantization_map.compatibleCtbSizes =
1843 VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_KHR | VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR;
1844 format_props.push_back(fmt);
1845 fmt.props_quantization_map.quantizationMapTexelSize = {8, 8};
1846 format_props.push_back(fmt);
1847 fmt.props_quantization_map.quantizationMapTexelSize = {32, 32};
1848 format_props.push_back(fmt);
1849 fmt.props_quantization_map.quantizationMapTexelSize = {64, 64};
1850 fmt.props_h265_quantization_map.compatibleCtbSizes = VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR;
1851 format_props.push_back(fmt);
1852 break;
1853 case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR:
1854 fmt.props.format = VK_FORMAT_R32_SINT;
1855 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1856 VK_IMAGE_USAGE_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR;
1857 fmt.props_quantization_map.quantizationMapTexelSize = {32, 32};
1858 fmt.props_h265_quantization_map.compatibleCtbSizes =
1859 VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_KHR | VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR;
1860 format_props.push_back(fmt);
1861 fmt.props_quantization_map.quantizationMapTexelSize = {64, 64};
1862 fmt.props_h265_quantization_map.compatibleCtbSizes = VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR;
1863 format_props.push_back(fmt);
1864 break;
1865 case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR:
1866 break;
1867 default:
1868 break;
1870 break;
1871 case VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR:
1872 switch (profile_list->pProfiles[0].chromaSubsampling) {
1873 case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR:
1874 fmt.props.format = VK_FORMAT_R32_SINT;
1875 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1876 VK_IMAGE_USAGE_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR;
1877 fmt.props_quantization_map.quantizationMapTexelSize = {8, 8};
1878 fmt.props_av1_quantization_map.compatibleSuperblockSizes = VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_64_BIT_KHR;
1879 format_props.push_back(fmt);
1880 fmt.props.format = VK_FORMAT_R8_UNORM;
1881 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1882 VK_IMAGE_USAGE_VIDEO_ENCODE_EMPHASIS_MAP_BIT_KHR;
1883 fmt.props_quantization_map.quantizationMapTexelSize = {64, 64};
1884 fmt.props_av1_quantization_map.compatibleSuperblockSizes = VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_64_BIT_KHR;
1885 format_props.push_back(fmt);
1886 break;
1887 case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR:
1888 fmt.props.format = VK_FORMAT_R32_SINT;
1889 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1890 VK_IMAGE_USAGE_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR;
1891 fmt.props_quantization_map.quantizationMapTexelSize = {64, 64};
1892 fmt.props_av1_quantization_map.compatibleSuperblockSizes = VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_64_BIT_KHR;
1893 format_props.push_back(fmt);
1894 fmt.props_quantization_map.quantizationMapTexelSize = {128, 128};
1895 fmt.props_av1_quantization_map.compatibleSuperblockSizes = VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_128_BIT_KHR;
1896 format_props.push_back(fmt);
1897 break;
1898 case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR:
1899 fmt.props.format = VK_FORMAT_R8_UNORM;
1900 fmt.props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1901 VK_IMAGE_USAGE_VIDEO_ENCODE_EMPHASIS_MAP_BIT_KHR;
1902 fmt.props_quantization_map.quantizationMapTexelSize = {128, 128};
1903 fmt.props_av1_quantization_map.compatibleSuperblockSizes = VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_128_BIT_KHR;
1904 format_props.push_back(fmt);
1905 break;
1906 default:
1907 break;
1909 break;
1911 default:
1912 break;
1915 std::vector<VideoFormatProperties> filtered;
1916 for (const auto& format : format_props) {
1917 if ((pVideoFormatInfo->imageUsage & format.props.imageUsageFlags) == pVideoFormatInfo->imageUsage) {
1918 filtered.push_back(format);
1922 if (pVideoFormatProperties != nullptr) {
1923 for (uint32_t i = 0; i < (std::min)(*pVideoFormatPropertyCount, (uint32_t)filtered.size()); ++i) {
1924 void* saved_pNext = pVideoFormatProperties[i].pNext;
1925 pVideoFormatProperties[i] = filtered[i].props;
1926 pVideoFormatProperties[i].pNext = saved_pNext;
1928 auto* props_quantization_map = lvl_find_mod_in_chain<VkVideoFormatQuantizationMapPropertiesKHR>(saved_pNext);
1929 auto* props_h265_quantization_map = lvl_find_mod_in_chain<VkVideoFormatH265QuantizationMapPropertiesKHR>(saved_pNext);
1930 auto* props_av1_quantization_map = lvl_find_mod_in_chain<VkVideoFormatAV1QuantizationMapPropertiesKHR>(saved_pNext);
1932 if (props_quantization_map != nullptr) {
1933 saved_pNext = props_quantization_map->pNext;
1934 *props_quantization_map = filtered[i].props_quantization_map;
1935 props_quantization_map->pNext = saved_pNext;
1938 if (props_h265_quantization_map != nullptr) {
1939 saved_pNext = props_h265_quantization_map->pNext;
1940 *props_h265_quantization_map = filtered[i].props_h265_quantization_map;
1941 props_h265_quantization_map->pNext = saved_pNext;
1944 if (props_av1_quantization_map != nullptr) {
1945 saved_pNext = props_av1_quantization_map->pNext;
1946 *props_av1_quantization_map = filtered[i].props_av1_quantization_map;
1947 props_av1_quantization_map->pNext = saved_pNext;
1951 *pVideoFormatPropertyCount = (uint32_t)filtered.size();
1952 return VK_SUCCESS;
1953 ''',
1954 'vkGetDescriptorSetLayoutSupport':'''
1955 if (pSupport) {
1956 pSupport->supported = VK_TRUE;
1958 ''',
1959 'vkGetDescriptorSetLayoutSupportKHR':'''
1960 GetDescriptorSetLayoutSupport(device, pCreateInfo, pSupport);
1961 ''',
1962 'vkGetRenderAreaGranularity': '''
1963 pGranularity->width = 1;
1964 pGranularity->height = 1;
1965 ''',
1966 'vkGetMemoryFdKHR': '''
1967 *pFd = 1;
1968 return VK_SUCCESS;
1969 ''',
1970 'vkGetMemoryHostPointerPropertiesEXT': '''
1971 pMemoryHostPointerProperties->memoryTypeBits = 1 << 5; // DEVICE_LOCAL only type
1972 return VK_SUCCESS;
1973 ''',
1974 'vkGetAndroidHardwareBufferPropertiesANDROID': '''
1975 pProperties->allocationSize = 65536;
1976 pProperties->memoryTypeBits = 1 << 5; // DEVICE_LOCAL only type
1978 auto *format_prop = lvl_find_mod_in_chain<VkAndroidHardwareBufferFormatPropertiesANDROID>(pProperties->pNext);
1979 if (format_prop) {
1980 // Likley using this format
1981 format_prop->format = VK_FORMAT_R8G8B8A8_UNORM;
1982 format_prop->externalFormat = 37;
1985 auto *format_resolve_prop = lvl_find_mod_in_chain<VkAndroidHardwareBufferFormatResolvePropertiesANDROID>(pProperties->pNext);
1986 if (format_resolve_prop) {
1987 format_resolve_prop->colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM;
1989 return VK_SUCCESS;
1990 ''',
1991 'vkGetPhysicalDeviceDisplayPropertiesKHR': '''
1992 if (!pProperties) {
1993 *pPropertyCount = 1;
1994 } else {
1995 unique_lock_t lock(global_lock);
1996 pProperties[0].display = (VkDisplayKHR)global_unique_handle++;
1997 display_map[physicalDevice].insert(pProperties[0].display);
1999 return VK_SUCCESS;
2000 ''',
2001 'vkRegisterDisplayEventEXT': '''
2002 unique_lock_t lock(global_lock);
2003 *pFence = (VkFence)global_unique_handle++;
2004 return VK_SUCCESS;
2005 ''',
2006 'vkQueueSubmit': '''
2007 // Special way to cause DEVICE_LOST
2008 // Picked VkExportFenceCreateInfo because needed some struct that wouldn't get cleared by validation Safe Struct
2009 // ... TODO - It would be MUCH nicer to have a layer or other setting control when this occured
2010 // For now this is used to allow Validation Layers test reacting to device losts
2011 if (submitCount > 0 && pSubmits) {
2012 auto pNext = reinterpret_cast<const VkBaseInStructure *>(pSubmits[0].pNext);
2013 if (pNext && pNext->sType == VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO && pNext->pNext == nullptr) {
2014 return VK_ERROR_DEVICE_LOST;
2017 return VK_SUCCESS;
2018 ''',
2019 'vkGetMemoryWin32HandlePropertiesKHR': '''
2020 pMemoryWin32HandleProperties->memoryTypeBits = 0xFFFF;
2021 return VK_SUCCESS;
2022 ''',
2023 'vkCreatePipelineBinariesKHR': '''
2024 unique_lock_t lock(global_lock);
2025 for (uint32_t i = 0; i < pBinaries->pipelineBinaryCount; ++i) {
2026 pBinaries->pPipelineBinaries[i] = (VkPipelineBinaryKHR)global_unique_handle++;
2028 return VK_SUCCESS;
2032 # MockICDGeneratorOptions - subclass of GeneratorOptions.
2034 # Adds options used by MockICDOutputGenerator objects during Mock
2035 # ICD generation.
2037 # Additional members
2038 # prefixText - list of strings to prefix generated header with
2039 # (usually a copyright statement + calling convention macros).
2040 # protectFile - True if multiple inclusion protection should be
2041 # generated (based on the filename) around the entire header.
2042 # protectFeature - True if #ifndef..#endif protection should be
2043 # generated around a feature interface in the header file.
2044 # genFuncPointers - True if function pointer typedefs should be
2045 # generated
2046 # protectProto - If conditional protection should be generated
2047 # around prototype declarations, set to either '#ifdef'
2048 # to require opt-in (#ifdef protectProtoStr) or '#ifndef'
2049 # to require opt-out (#ifndef protectProtoStr). Otherwise
2050 # set to None.
2051 # protectProtoStr - #ifdef/#ifndef symbol to use around prototype
2052 # declarations, if protectProto is set
2053 # apicall - string to use for the function declaration prefix,
2054 # such as APICALL on Windows.
2055 # apientry - string to use for the calling convention macro,
2056 # in typedefs, such as APIENTRY.
2057 # apientryp - string to use for the calling convention macro
2058 # in function pointer typedefs, such as APIENTRYP.
2059 # indentFuncProto - True if prototype declarations should put each
2060 # parameter on a separate line
2061 # indentFuncPointer - True if typedefed function pointers should put each
2062 # parameter on a separate line
2063 # alignFuncParam - if nonzero and parameters are being put on a
2064 # separate line, align parameter names at the specified column
2065 class MockICDGeneratorOptions(GeneratorOptions):
2066 def __init__(self,
2067 conventions = None,
2068 filename = None,
2069 directory = '.',
2070 genpath = None,
2071 apiname = None,
2072 profile = None,
2073 versions = '.*',
2074 emitversions = '.*',
2075 defaultExtensions = None,
2076 addExtensions = None,
2077 removeExtensions = None,
2078 emitExtensions = None,
2079 sortProcedure = regSortFeatures,
2080 prefixText = "",
2081 genFuncPointers = True,
2082 protectFile = True,
2083 protectFeature = True,
2084 protectProto = None,
2085 protectProtoStr = None,
2086 apicall = '',
2087 apientry = '',
2088 apientryp = '',
2089 indentFuncProto = True,
2090 indentFuncPointer = False,
2091 alignFuncParam = 0,
2092 expandEnumerants = True,
2093 helper_file_type = ''):
2094 GeneratorOptions.__init__(self,
2095 conventions = conventions,
2096 filename = filename,
2097 directory = directory,
2098 genpath = genpath,
2099 apiname = apiname,
2100 profile = profile,
2101 versions = versions,
2102 emitversions = emitversions,
2103 defaultExtensions = defaultExtensions,
2104 addExtensions = addExtensions,
2105 removeExtensions = removeExtensions,
2106 emitExtensions = emitExtensions,
2107 sortProcedure = sortProcedure)
2108 self.prefixText = prefixText
2109 self.genFuncPointers = genFuncPointers
2110 self.protectFile = protectFile
2111 self.protectFeature = protectFeature
2112 self.protectProto = protectProto
2113 self.protectProtoStr = protectProtoStr
2114 self.apicall = apicall
2115 self.apientry = apientry
2116 self.apientryp = apientryp
2117 self.indentFuncProto = indentFuncProto
2118 self.indentFuncPointer = indentFuncPointer
2119 self.alignFuncParam = alignFuncParam
2121 # MockICDOutputGenerator - subclass of OutputGenerator.
2122 # Generates a mock vulkan ICD.
2123 # This is intended to be a minimal replacement for a vulkan device in order
2124 # to enable Vulkan Validation testing.
2126 # ---- methods ----
2127 # MockOutputGenerator(errFile, warnFile, diagFile) - args as for
2128 # OutputGenerator. Defines additional internal state.
2129 # ---- methods overriding base class ----
2130 # beginFile(genOpts)
2131 # endFile()
2132 # beginFeature(interface, emit)
2133 # endFeature()
2134 # genType(typeinfo,name)
2135 # genStruct(typeinfo,name)
2136 # genGroup(groupinfo,name)
2137 # genEnum(enuminfo, name)
2138 # genCmd(cmdinfo)
2139 class MockICDOutputGenerator(OutputGenerator):
2140 """Generate specified API interfaces in a specific style, such as a C header"""
2141 # This is an ordered list of sections in the header file.
2142 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
2143 'group', 'bitmask', 'funcpointer', 'struct']
2144 ALL_SECTIONS = TYPE_SECTIONS + ['command']
2145 def __init__(self,
2146 errFile = sys.stderr,
2147 warnFile = sys.stderr,
2148 diagFile = sys.stdout):
2149 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
2150 # Internal state - accumulators for different inner block text
2151 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
2152 self.intercepts = []
2153 self.function_declarations = False
2155 # Check if the parameter passed in is a pointer to an array
2156 def paramIsArray(self, param):
2157 return param.attrib.get('len') is not None
2159 # Check if the parameter passed in is a pointer
2160 def paramIsPointer(self, param):
2161 ispointer = False
2162 for elem in param:
2163 if ((elem.tag != 'type') and (elem.tail is not None)) and '*' in elem.tail:
2164 ispointer = True
2165 return ispointer
2167 # Check if an object is a non-dispatchable handle
2168 def isHandleTypeNonDispatchable(self, handletype):
2169 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
2170 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
2171 return True
2172 else:
2173 return False
2175 # Check if an object is a dispatchable handle
2176 def isHandleTypeDispatchable(self, handletype):
2177 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
2178 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
2179 return True
2180 else:
2181 return False
2183 # Check that the target API is in the supported list for the extension
2184 def checkExtensionAPISupport(self, supported):
2185 return self.genOpts.apiname in supported.split(',')
2187 def beginFile(self, genOpts):
2188 OutputGenerator.beginFile(self, genOpts)
2189 # C-specific
2191 # Multiple inclusion protection & C++ namespace.
2192 if (genOpts.protectFile and self.genOpts.filename == "function_declarations.h"):
2193 self.function_declarations = True
2195 # User-supplied prefix text, if any (list of strings)
2196 if (genOpts.prefixText):
2197 for s in genOpts.prefixText:
2198 write(s, file=self.outFile)
2200 if self.function_declarations:
2201 self.newline()
2202 # Include all of the extensions in ICD except specific ignored ones
2203 device_exts = []
2204 instance_exts = []
2205 # Ignore extensions that ICDs should not implement or are not safe to report
2206 ignore_exts = ['VK_EXT_validation_cache', 'VK_KHR_portability_subset']
2207 for ext in self.registry.tree.findall("extensions/extension"):
2208 if self.checkExtensionAPISupport(ext.attrib['supported']): # Only include API-relevant extensions
2209 if (ext.attrib['name'] not in ignore_exts):
2210 # Search for extension version enum
2211 for enum in ext.findall('require/enum'):
2212 if enum.get('name', '').endswith('_SPEC_VERSION'):
2213 ext_version = enum.get('value')
2214 if (ext.attrib.get('type') == 'instance'):
2215 instance_exts.append(' {"%s", %s},' % (ext.attrib['name'], ext_version))
2216 else:
2217 device_exts.append(' {"%s", %s},' % (ext.attrib['name'], ext_version))
2218 break
2219 write('#pragma once\n',file=self.outFile)
2220 write('#include <stdint.h>',file=self.outFile)
2221 write('#include <cstring>',file=self.outFile)
2222 write('#include <string>',file=self.outFile)
2223 write('#include <unordered_map>',file=self.outFile)
2224 write('#include <vulkan/vulkan.h>',file=self.outFile)
2225 self.newline()
2226 write('namespace vkmock {\n', file=self.outFile)
2227 write('// Map of instance extension name to version', file=self.outFile)
2228 write('static const std::unordered_map<std::string, uint32_t> instance_extension_map = {', file=self.outFile)
2229 write('\n'.join(instance_exts), file=self.outFile)
2230 write('};', file=self.outFile)
2231 write('// Map of device extension name to version', file=self.outFile)
2232 write('static const std::unordered_map<std::string, uint32_t> device_extension_map = {', file=self.outFile)
2233 write('\n'.join(device_exts), file=self.outFile)
2234 write('};', file=self.outFile)
2235 else:
2236 write('#pragma once\n',file=self.outFile)
2237 write('#include "mock_icd.h"',file=self.outFile)
2238 write('#include "function_declarations.h"\n',file=self.outFile)
2239 write('namespace vkmock {', file=self.outFile)
2242 def endFile(self):
2243 # C-specific
2244 # Finish C++ namespace
2245 self.newline()
2246 if self.function_declarations:
2247 # record intercepted procedures
2248 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
2249 write('static const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
2250 write('\n'.join(self.intercepts), file=self.outFile)
2251 write('};\n', file=self.outFile)
2252 write('} // namespace vkmock', file=self.outFile)
2253 self.newline()
2255 # Finish processing in superclass
2256 OutputGenerator.endFile(self)
2257 def beginFeature(self, interface, emit):
2258 #write('// starting beginFeature', file=self.outFile)
2259 # Start processing in superclass
2260 OutputGenerator.beginFeature(self, interface, emit)
2261 self.featureExtraProtect = GetFeatureProtect(interface)
2262 # C-specific
2263 # Accumulate includes, defines, types, enums, function pointer typedefs,
2264 # end function prototypes separately for this feature. They're only
2265 # printed in endFeature().
2266 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
2267 #write('// ending beginFeature', file=self.outFile)
2268 def endFeature(self):
2269 # C-specific
2270 # Actually write the interface to the output file.
2271 #write('// starting endFeature', file=self.outFile)
2272 if (self.emit):
2273 self.newline()
2274 if (self.genOpts.protectFeature):
2275 write('#ifndef', self.featureName, file=self.outFile)
2276 # If type declarations are needed by other features based on
2277 # this one, it may be necessary to suppress the ExtraProtect,
2278 # or move it below the 'for section...' loop.
2279 #write('// endFeature looking at self.featureExtraProtect', file=self.outFile)
2280 if (self.featureExtraProtect != None):
2281 write('#ifdef', self.featureExtraProtect, file=self.outFile)
2282 #write('#define', self.featureName, '1', file=self.outFile)
2283 for section in self.TYPE_SECTIONS:
2284 #write('// endFeature writing section'+section, file=self.outFile)
2285 contents = self.sections[section]
2286 if contents:
2287 write('\n'.join(contents), file=self.outFile)
2288 self.newline()
2289 #write('// endFeature looking at self.sections[command]', file=self.outFile)
2290 if (self.sections['command']):
2291 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
2292 self.newline()
2293 if (self.featureExtraProtect != None):
2294 write('#endif /*', self.featureExtraProtect, '*/', file=self.outFile)
2295 if (self.genOpts.protectFeature):
2296 write('#endif /*', self.featureName, '*/', file=self.outFile)
2297 # Finish processing in superclass
2298 OutputGenerator.endFeature(self)
2299 #write('// ending endFeature', file=self.outFile)
2301 # Append a definition to the specified section
2302 def appendSection(self, section, text):
2303 # self.sections[section].append('SECTION: ' + section + '\n')
2304 self.sections[section].append(text)
2306 # Type generation
2307 def genType(self, typeinfo, name, alias):
2308 pass
2310 # Struct (e.g. C "struct" type) generation.
2311 # This is a special case of the <type> tag where the contents are
2312 # interpreted as a set of <member> tags instead of freeform C
2313 # C type declarations. The <member> tags are just like <param>
2314 # tags - they are a declaration of a struct or union member.
2315 # Only simple member declarations are supported (no nested
2316 # structs etc.)
2317 def genStruct(self, typeinfo, typeName, alias):
2318 OutputGenerator.genStruct(self, typeinfo, typeName, alias)
2319 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
2320 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
2321 for member in typeinfo.elem.findall('.//member'):
2322 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
2323 body += ';\n'
2324 body += '} ' + typeName + ';\n'
2325 self.appendSection('struct', body)
2327 # Group (e.g. C "enum" type) generation.
2328 # These are concatenated together with other types.
2329 def genGroup(self, groupinfo, groupName, alias):
2330 pass
2331 # Enumerant generation
2332 # <enum> tags may specify their values in several ways, but are usually
2333 # just integers.
2334 def genEnum(self, enuminfo, name, alias):
2335 pass
2337 # Command generation
2338 def genCmd(self, cmdinfo, name, alias):
2339 decls = self.makeCDecls(cmdinfo.elem)
2340 if self.function_declarations: # In the header declare all intercepts
2341 self.appendSection('command', '')
2342 self.appendSection('command', 'static %s' % (decls[0]))
2343 if (self.featureExtraProtect != None):
2344 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
2345 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
2346 if (self.featureExtraProtect != None):
2347 self.intercepts += [ '#endif' ]
2348 return
2350 manual_functions = [
2351 # Include functions here to be intercepted w/ manually implemented function bodies
2352 'vkGetDeviceProcAddr',
2353 'vkGetInstanceProcAddr',
2354 'vkCreateDevice',
2355 'vkDestroyDevice',
2356 'vkCreateInstance',
2357 'vkDestroyInstance',
2358 'vkFreeCommandBuffers',
2359 'vkAllocateCommandBuffers',
2360 'vkDestroyCommandPool',
2361 #'vkCreateDebugReportCallbackEXT',
2362 #'vkDestroyDebugReportCallbackEXT',
2363 'vkEnumerateInstanceLayerProperties',
2364 'vkEnumerateInstanceVersion',
2365 'vkEnumerateInstanceExtensionProperties',
2366 'vkEnumerateDeviceLayerProperties',
2367 'vkEnumerateDeviceExtensionProperties',
2369 if name in manual_functions:
2370 self.appendSection('command', '')
2371 if name not in CUSTOM_C_INTERCEPTS:
2372 self.appendSection('command', '// declare only')
2373 self.appendSection('command', 'static %s' % (decls[0]))
2374 self.appendSection('command', '// TODO: Implement custom intercept body')
2375 else:
2376 self.appendSection('command', 'static %s' % (decls[0][:-1]))
2377 self.appendSection('command', '{\n%s}' % (CUSTOM_C_INTERCEPTS[name]))
2378 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
2379 return
2380 # record that the function will be intercepted
2381 if (self.featureExtraProtect != None):
2382 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
2383 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
2384 if (self.featureExtraProtect != None):
2385 self.intercepts += [ '#endif' ]
2387 OutputGenerator.genCmd(self, cmdinfo, name, alias)
2389 self.appendSection('command', '')
2390 self.appendSection('command', 'static %s' % (decls[0][:-1]))
2391 if name in CUSTOM_C_INTERCEPTS:
2392 self.appendSection('command', '{%s}' % (CUSTOM_C_INTERCEPTS[name]))
2393 return
2395 # Declare result variable, if any.
2396 resulttype = cmdinfo.elem.find('proto/type')
2397 if (resulttype != None and resulttype.text == 'void'):
2398 resulttype = None
2399 # if the name w/ KHR postfix is in the CUSTOM_C_INTERCEPTS
2400 # Call the KHR custom version instead of generating separate code
2401 khr_name = name + "KHR"
2402 if khr_name in CUSTOM_C_INTERCEPTS:
2403 return_string = ''
2404 if resulttype != None:
2405 return_string = 'return '
2406 params = cmdinfo.elem.findall('param/name')
2407 param_names = []
2408 for param in params:
2409 param_names.append(param.text)
2410 self.appendSection('command', '{\n %s%s(%s);\n}' % (return_string, khr_name[2:], ", ".join(param_names)))
2411 return
2412 self.appendSection('command', '{')
2414 api_function_name = cmdinfo.elem.attrib.get('name')
2415 # GET THE TYPE OF FUNCTION
2416 if any(api_function_name.startswith(ftxt) for ftxt in ('vkCreate', 'vkAllocate')):
2417 # Get last param
2418 last_param = cmdinfo.elem.findall('param')[-1]
2419 lp_txt = last_param.find('name').text
2420 lp_len = None
2421 if ('len' in last_param.attrib):
2422 lp_len = last_param.attrib['len']
2423 lp_len = lp_len.replace('::', '->')
2424 lp_type = last_param.find('type').text
2425 handle_type = 'dispatchable'
2426 allocator_txt = 'CreateDispObjHandle()';
2427 if (self.isHandleTypeNonDispatchable(lp_type)):
2428 handle_type = 'non-' + handle_type
2429 allocator_txt = 'global_unique_handle++';
2430 # Need to lock in both cases
2431 self.appendSection('command', ' unique_lock_t lock(global_lock);')
2432 if (lp_len != None):
2433 #print("%s last params (%s) has len %s" % (handle_type, lp_txt, lp_len))
2434 self.appendSection('command', ' for (uint32_t i = 0; i < %s; ++i) {' % (lp_len))
2435 self.appendSection('command', ' %s[i] = (%s)%s;' % (lp_txt, lp_type, allocator_txt))
2436 self.appendSection('command', ' }')
2437 else:
2438 #print("Single %s last param is '%s' w/ type '%s'" % (handle_type, lp_txt, lp_type))
2439 if 'AllocateMemory' in api_function_name:
2440 # Store allocation size in case it's mapped
2441 self.appendSection('command', ' allocated_memory_size_map[(VkDeviceMemory)global_unique_handle] = pAllocateInfo->allocationSize;')
2442 self.appendSection('command', ' *%s = (%s)%s;' % (lp_txt, lp_type, allocator_txt))
2443 elif True in [ftxt in api_function_name for ftxt in ['Destroy', 'Free']]:
2444 self.appendSection('command', '//Destroy object')
2445 if 'FreeMemory' in api_function_name:
2446 # If the memory is mapped, unmap it
2447 self.appendSection('command', ' UnmapMemory(device, memory);')
2448 # Remove from allocation map
2449 self.appendSection('command', ' unique_lock_t lock(global_lock);')
2450 self.appendSection('command', ' allocated_memory_size_map.erase(memory);')
2451 else:
2452 self.appendSection('command', '//Not a CREATE or DESTROY function')
2454 # Return result variable, if any.
2455 if (resulttype != None):
2456 if api_function_name == 'vkGetEventStatus':
2457 self.appendSection('command', ' return VK_EVENT_SET;')
2458 else:
2459 self.appendSection('command', ' return VK_SUCCESS;')
2460 self.appendSection('command', '}')
2462 # override makeProtoName to drop the "vk" prefix
2463 def makeProtoName(self, name, tail):
2464 return self.genOpts.apientry + name[2:] + tail