blob: e351d70e5ed81b2c97e5dd252248a8b6c09b6fd0 [file] [log] [blame]
Tobin Ehlis45a0a802017-10-13 09:26:20 -06001#!/usr/bin/python3 -i
2#
3# Copyright (c) 2015-2017 The Khronos Group Inc.
4# Copyright (c) 2015-2017 Valve Corporation
5# Copyright (c) 2015-2017 LunarG, Inc.
6# Copyright (c) 2015-2017 Google Inc.
7#
8# Licensed under the Apache License, Version 2.0 (the "License");
9# you may not use this file except in compliance with the License.
10# You may obtain a copy of the License at
11#
12# http://www.apache.org/licenses/LICENSE-2.0
13#
14# Unless required by applicable law or agreed to in writing, software
15# distributed under the License is distributed on an "AS IS" BASIS,
16# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17# See the License for the specific language governing permissions and
18# limitations under the License.
19#
20# Author: Tobin Ehlis <tobine@google.com>
21#
22# This script generates a Mock ICD that intercepts almost all Vulkan
23# functions. That layer is not intended to be useful or even compilable
24# in its initial state. Rather it's intended to be a starting point that
25# can be copied and customized to assist in creation of a new layer.
26
27import os,re,sys
28from generator import *
29
30# Mock header code
31HEADER_C_CODE = '''
32using mutex_t = std::mutex;
33using lock_guard_t = std::lock_guard<mutex_t>;
34using unique_lock_t = std::unique_lock<mutex_t>;
35
36static mutex_t global_lock;
37static uint64_t global_unique_handle = 1;
38static const uint32_t SUPPORTED_LOADER_ICD_INTERFACE_VERSION = 5;
39static uint32_t loader_interface_version = 0;
40static bool negotiate_loader_icd_interface_called = false;
41static void* CreateDispObjHandle() {
42 auto handle = new VK_LOADER_DATA;
43 set_loader_magic_value(handle);
44 return handle;
45}
46static void DestroyDispObjHandle(void* handle) {
47 delete reinterpret_cast<VK_LOADER_DATA*>(handle);
48}
49'''
50
51# Manual code at the top of the cpp source file
52SOURCE_CPP_PREFIX = '''
53using std::unordered_map;
54
55// Map device memory handle to any mapped allocations that we'll need to free on unmap
56static unordered_map<VkDeviceMemory, std::vector<void*>> mapped_memory_map;
57
58static VkPhysicalDevice physical_device = nullptr;
59static unordered_map<VkDevice, unordered_map<uint32_t, unordered_map<uint32_t, VkQueue>>> queue_map;
60
61// TODO: Would like to codegen this but limits aren't in XML
62static VkPhysicalDeviceLimits SetLimits(VkPhysicalDeviceLimits *limits) {
63 limits->maxImageDimension1D = 4096;
64 limits->maxImageDimension2D = 4096;
65 limits->maxImageDimension3D = 256;
66 limits->maxImageDimensionCube = 4096;
67 limits->maxImageArrayLayers = 256;
68 limits->maxTexelBufferElements = 65536;
69 limits->maxUniformBufferRange = 16384;
70 limits->maxStorageBufferRange = 134217728;
71 limits->maxPushConstantsSize = 128;
72 limits->maxMemoryAllocationCount = 4096;
73 limits->maxSamplerAllocationCount = 4000;
74 limits->bufferImageGranularity = 1;
75 limits->sparseAddressSpaceSize = 2147483648;
76 limits->maxBoundDescriptorSets = 4;
77 limits->maxPerStageDescriptorSamplers = 16;
78 limits->maxPerStageDescriptorUniformBuffers = 12;
79 limits->maxPerStageDescriptorStorageBuffers = 4;
80 limits->maxPerStageDescriptorSampledImages = 16;
81 limits->maxPerStageDescriptorStorageImages = 4;
82 limits->maxPerStageDescriptorInputAttachments = 4;
83 limits->maxPerStageResources = 128^2;
84 limits->maxDescriptorSetSamplers = 96^8;
85 limits->maxDescriptorSetUniformBuffers = 72^8;
86 limits->maxDescriptorSetUniformBuffersDynamic = 8;
87 limits->maxDescriptorSetStorageBuffers = 24^8;
88 limits->maxDescriptorSetStorageBuffersDynamic = 4;
89 limits->maxDescriptorSetSampledImages = 96^8;
90 limits->maxDescriptorSetStorageImages = 24^8;
91 limits->maxDescriptorSetInputAttachments = 4;
92 limits->maxVertexInputAttributes = 16;
93 limits->maxVertexInputBindings = 16;
94 limits->maxVertexInputAttributeOffset = 2047;
95 limits->maxVertexInputBindingStride = 2048;
96 limits->maxVertexOutputComponents = 64;
97 limits->maxTessellationGenerationLevel = 64;
98 limits->maxTessellationPatchSize = 32;
99 limits->maxTessellationControlPerVertexInputComponents = 64;
100 limits->maxTessellationControlPerVertexOutputComponents = 64;
101 limits->maxTessellationControlPerPatchOutputComponents = 120;
102 limits->maxTessellationControlTotalOutputComponents = 2048;
103 limits->maxTessellationEvaluationInputComponents = 64;
104 limits->maxTessellationEvaluationOutputComponents = 64;
105 limits->maxGeometryShaderInvocations = 32;
106 limits->maxGeometryInputComponents = 64;
107 limits->maxGeometryOutputComponents = 64;
108 limits->maxGeometryOutputVertices = 256;
109 limits->maxGeometryTotalOutputComponents = 1024;
110 limits->maxFragmentInputComponents = 64;
111 limits->maxFragmentOutputAttachments = 4;
112 limits->maxFragmentDualSrcAttachments = 1;
113 limits->maxFragmentCombinedOutputResources = 4;
114 limits->maxComputeSharedMemorySize = 16384;
115 limits->maxComputeWorkGroupCount[0] = 65535;
116 limits->maxComputeWorkGroupCount[1] = 65535;
117 limits->maxComputeWorkGroupCount[2] = 65535;
118 limits->maxComputeWorkGroupInvocations = 128;
119 limits->maxComputeWorkGroupSize[0] = 128;
120 limits->maxComputeWorkGroupSize[1] = 128;
121 limits->maxComputeWorkGroupSize[2] = 64;
122 limits->subPixelPrecisionBits = 4;
123 limits->subTexelPrecisionBits = 4;
124 limits->mipmapPrecisionBits = 4;
125 limits->maxDrawIndexedIndexValue = (2^32) - 1;
126 limits->maxDrawIndirectCount = (2^16) - 1;
127 limits->maxSamplerLodBias = 2.0f;
128 limits->maxSamplerAnisotropy = 16;
129 limits->maxViewports = 16;
130 limits->maxViewportDimensions[0] = 4096;
131 limits->maxViewportDimensions[1] = 4096;
132 limits->viewportBoundsRange[0] = -8192;
133 limits->viewportBoundsRange[1] = 8191;
134 limits->viewportSubPixelBits = 0;
135 limits->minMemoryMapAlignment = 64;
136 limits->minTexelBufferOffsetAlignment = 256;
137 limits->minUniformBufferOffsetAlignment = 256;
138 limits->minStorageBufferOffsetAlignment = 256;
139 limits->minTexelOffset = -8;
140 limits->maxTexelOffset = 7;
141 limits->minTexelGatherOffset = -8;
142 limits->maxTexelGatherOffset = 7;
143 limits->minInterpolationOffset = 0.0f;
144 limits->maxInterpolationOffset = 0.5f;
145 limits->subPixelInterpolationOffsetBits = 4;
146 limits->maxFramebufferWidth = 4096;
147 limits->maxFramebufferHeight = 4096;
148 limits->maxFramebufferLayers = 256;
149 limits->framebufferColorSampleCounts = 0x7F;
150 limits->framebufferDepthSampleCounts = 0x7F;
151 limits->framebufferStencilSampleCounts = 0x7F;
152 limits->framebufferNoAttachmentsSampleCounts = 0x7F;
153 limits->maxColorAttachments = 4;
154 limits->sampledImageColorSampleCounts = 0x7F;
155 limits->sampledImageIntegerSampleCounts = 0x7F;
156 limits->sampledImageDepthSampleCounts = 0x7F;
157 limits->sampledImageStencilSampleCounts = 0x7F;
158 limits->storageImageSampleCounts = 0x7F;
159 limits->maxSampleMaskWords = 1;
160 limits->timestampComputeAndGraphics = VK_TRUE;
161 limits->timestampPeriod = 1;
162 limits->maxClipDistances = 8;
163 limits->maxCullDistances = 8;
164 limits->maxCombinedClipAndCullDistances = 8;
165 limits->discreteQueuePriorities = 2;
166 limits->pointSizeRange[0] = 1.0f;
167 limits->pointSizeRange[1] = 64.0f;
168 limits->lineWidthRange[0] = 1.0f;
169 limits->lineWidthRange[1] = 8.0f;
170 limits->pointSizeGranularity = 1.0f;
171 limits->lineWidthGranularity = 1.0f;
172 limits->strictLines = VK_TRUE;
173 limits->standardSampleLocations = VK_TRUE;
174 limits->optimalBufferCopyOffsetAlignment = 1;
175 limits->optimalBufferCopyRowPitchAlignment = 1;
176 limits->nonCoherentAtomSize = 256;
177
178 return *limits;
179}
180'''
181
182# Manual code at the end of the cpp source file
183SOURCE_CPP_POSTFIX = '''
184
185static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
186 // TODO: This function should only care about physical device functions and return nullptr for other functions
187 const auto &item = name_to_funcptr_map.find(funcName);
188 if (item != name_to_funcptr_map.end()) {
189 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
190 }
191 // Mock should intercept all functions so if we get here just return null
192 return nullptr;
193}
194
195} // namespace vkmock
196
197#if defined(__GNUC__) && __GNUC__ >= 4
198#define EXPORT __attribute__((visibility("default")))
199#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
200#define EXPORT __attribute__((visibility("default")))
201#else
202#define EXPORT
203#endif
204
205#ifdef WIN32
206 extern "C" __declspec(dllexport) {
207#else
208 extern "C" {
209#endif
210EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName) {
211 if (!vkmock::negotiate_loader_icd_interface_called) {
212 vkmock::loader_interface_version = 1;
213 }
214 return vkmock::GetInstanceProcAddr(instance, pName);
215}
216
217EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInstance instance, const char* pName) {
218 return vkmock::GetPhysicalDeviceProcAddr(instance, pName);
219}
220
221EXPORT VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) {
222 vkmock::negotiate_loader_icd_interface_called = true;
223 vkmock::loader_interface_version = *pSupportedVersion;
224 if (*pSupportedVersion > vkmock::SUPPORTED_LOADER_ICD_INTERFACE_VERSION) {
225 *pSupportedVersion = vkmock::SUPPORTED_LOADER_ICD_INTERFACE_VERSION;
226 }
227 return VK_SUCCESS;
228}
229
230
231EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(
232 VkInstance instance,
233 VkSurfaceKHR surface,
234 const VkAllocationCallbacks* pAllocator)
235{
236 vkmock::DestroySurfaceKHR(instance, surface, pAllocator);
237}
238
239EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(
240 VkPhysicalDevice physicalDevice,
241 uint32_t queueFamilyIndex,
242 VkSurfaceKHR surface,
243 VkBool32* pSupported)
244{
245 return vkmock::GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, pSupported);
246}
247
248EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
249 VkPhysicalDevice physicalDevice,
250 VkSurfaceKHR surface,
251 VkSurfaceCapabilitiesKHR* pSurfaceCapabilities)
252{
253 return vkmock::GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities);
254}
255
256EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR(
257 VkPhysicalDevice physicalDevice,
258 VkSurfaceKHR surface,
259 uint32_t* pSurfaceFormatCount,
260 VkSurfaceFormatKHR* pSurfaceFormats)
261{
262 return vkmock::GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);
263}
264
265EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR(
266 VkPhysicalDevice physicalDevice,
267 VkSurfaceKHR surface,
268 uint32_t* pPresentModeCount,
269 VkPresentModeKHR* pPresentModes)
270{
271 return vkmock::GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount, pPresentModes);
272}
273
274EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR(
275 VkInstance instance,
276 const VkDisplaySurfaceCreateInfoKHR* pCreateInfo,
277 const VkAllocationCallbacks* pAllocator,
278 VkSurfaceKHR* pSurface)
279{
280 return vkmock::CreateDisplayPlaneSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
281}
282
283#ifdef VK_USE_PLATFORM_XLIB_KHR
284
285EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(
286 VkInstance instance,
287 const VkXlibSurfaceCreateInfoKHR* pCreateInfo,
288 const VkAllocationCallbacks* pAllocator,
289 VkSurfaceKHR* pSurface)
290{
291 return vkmock::CreateXlibSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
292}
293#endif /* VK_USE_PLATFORM_XLIB_KHR */
294
295#ifdef VK_USE_PLATFORM_XCB_KHR
296
297EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(
298 VkInstance instance,
299 const VkXcbSurfaceCreateInfoKHR* pCreateInfo,
300 const VkAllocationCallbacks* pAllocator,
301 VkSurfaceKHR* pSurface)
302{
303 return vkmock::CreateXcbSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
304}
305#endif /* VK_USE_PLATFORM_XCB_KHR */
306
307#ifdef VK_USE_PLATFORM_WAYLAND_KHR
308
309EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR(
310 VkInstance instance,
311 const VkWaylandSurfaceCreateInfoKHR* pCreateInfo,
312 const VkAllocationCallbacks* pAllocator,
313 VkSurfaceKHR* pSurface)
314{
315 return vkmock::CreateWaylandSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
316}
317#endif /* VK_USE_PLATFORM_WAYLAND_KHR */
318
319#ifdef VK_USE_PLATFORM_MIR_KHR
320
321EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMirSurfaceKHR(
322 VkInstance instance,
323 const VkMirSurfaceCreateInfoKHR* pCreateInfo,
324 const VkAllocationCallbacks* pAllocator,
325 VkSurfaceKHR* pSurface)
326{
327 return vkmock::CreateMirSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
328}
329#endif /* VK_USE_PLATFORM_MIR_KHR */
330
331#ifdef VK_USE_PLATFORM_ANDROID_KHR
332
333EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR(
334 VkInstance instance,
335 const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
336 const VkAllocationCallbacks* pAllocator,
337 VkSurfaceKHR* pSurface)
338{
339 return vkmock::CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
340}
341#endif /* VK_USE_PLATFORM_ANDROID_KHR */
342
343#ifdef VK_USE_PLATFORM_WIN32_KHR
344
345EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(
346 VkInstance instance,
347 const VkWin32SurfaceCreateInfoKHR* pCreateInfo,
348 const VkAllocationCallbacks* pAllocator,
349 VkSurfaceKHR* pSurface)
350{
351 return vkmock::CreateWin32SurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
352}
353#endif /* VK_USE_PLATFORM_WIN32_KHR */
354
355EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHX(
356 VkDevice device,
357 VkSurfaceKHR surface,
358 VkDeviceGroupPresentModeFlagsKHX* pModes)
359{
360 return vkmock::GetDeviceGroupSurfacePresentModesKHX(device, surface, pModes);
361}
362
363EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHX(
364 VkPhysicalDevice physicalDevice,
365 VkSurfaceKHR surface,
366 uint32_t* pRectCount,
367 VkRect2D* pRects)
368{
369 return vkmock::GetPhysicalDevicePresentRectanglesKHX(physicalDevice, surface, pRectCount, pRects);
370}
371
372#ifdef VK_USE_PLATFORM_VI_NN
373
374EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateViSurfaceNN(
375 VkInstance instance,
376 const VkViSurfaceCreateInfoNN* pCreateInfo,
377 const VkAllocationCallbacks* pAllocator,
378 VkSurfaceKHR* pSurface)
379{
380 return vkmock::CreateViSurfaceNN(instance, pCreateInfo, pAllocator, pSurface);
381}
382#endif /* VK_USE_PLATFORM_VI_NN */
383
384EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2EXT(
385 VkPhysicalDevice physicalDevice,
386 VkSurfaceKHR surface,
387 VkSurfaceCapabilities2EXT* pSurfaceCapabilities)
388{
389 return vkmock::GetPhysicalDeviceSurfaceCapabilities2EXT(physicalDevice, surface, pSurfaceCapabilities);
390}
391
392#ifdef VK_USE_PLATFORM_IOS_MVK
393
394EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateIOSSurfaceMVK(
395 VkInstance instance,
396 const VkIOSSurfaceCreateInfoMVK* pCreateInfo,
397 const VkAllocationCallbacks* pAllocator,
398 VkSurfaceKHR* pSurface)
399{
400 return vkmock::CreateIOSSurfaceMVK(instance, pCreateInfo, pAllocator, pSurface);
401}
402#endif /* VK_USE_PLATFORM_IOS_MVK */
403
404#ifdef VK_USE_PLATFORM_MACOS_MVK
405
406EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMacOSSurfaceMVK(
407 VkInstance instance,
408 const VkMacOSSurfaceCreateInfoMVK* pCreateInfo,
409 const VkAllocationCallbacks* pAllocator,
410 VkSurfaceKHR* pSurface)
411{
412 return vkmock::CreateMacOSSurfaceMVK(instance, pCreateInfo, pAllocator, pSurface);
413}
414#endif /* VK_USE_PLATFORM_MACOS_MVK */
415#ifdef WIN32
416 } // end extern "C"
417#else
418 } // end extern "C"
419#endif
420'''
421
422CUSTOM_C_INTERCEPTS = {
423'vkCreateInstance': '''
424 // TODO: If loader ver <=4 ICD must fail with VK_ERROR_INCOMPATIBLE_DRIVER for all vkCreateInstance calls with
425 // apiVersion set to > Vulkan 1.0 because the loader is still at interface version <= 4. Otherwise, the
426 // ICD should behave as normal.
427 if (loader_interface_version <= 4) {
428 return VK_ERROR_INCOMPATIBLE_DRIVER;
429 }
430 *pInstance = (VkInstance)CreateDispObjHandle();
431 // TODO: If emulating specific device caps, will need to add intelligence here
432 return VK_SUCCESS;
433''',
434'vkDestroyInstance': '''
435 // Destroy physical device
436 DestroyDispObjHandle((void*)physical_device);
437
438 DestroyDispObjHandle((void*)instance);
439''',
440'vkEnumeratePhysicalDevices': '''
441 if (pPhysicalDevices) {
442 if (!physical_device) {
443 physical_device = (VkPhysicalDevice)CreateDispObjHandle();
444 }
445 *pPhysicalDevices = physical_device;
446 } else {
447 *pPhysicalDeviceCount = 1;
448 }
449 return VK_SUCCESS;
450''',
451'vkCreateDevice': '''
452 *pDevice = (VkDevice)CreateDispObjHandle();
453 // TODO: If emulating specific device caps, will need to add intelligence here
454 return VK_SUCCESS;
455''',
456'vkDestroyDevice': '''
457 // First destroy sub-device objects
458 // Destroy Queues
459 for (auto dev_queue_map_pair : queue_map) {
460 for (auto queue_family_map_pair : queue_map[dev_queue_map_pair.first]) {
461 for (auto index_queue_pair : queue_map[dev_queue_map_pair.first][queue_family_map_pair.first]) {
462 DestroyDispObjHandle((void*)index_queue_pair.second);
463 }
464 }
465 }
466 queue_map.clear();
467 // Now destroy device
468 DestroyDispObjHandle((void*)device);
469 // TODO: If emulating specific device caps, will need to add intelligence here
470''',
471'vkGetDeviceQueue': '''
472 auto queue = queue_map[device][queueFamilyIndex][queueIndex];
473 if (queue) {
474 *pQueue = queue;
475 } else {
476 *pQueue = queue_map[device][queueFamilyIndex][queueIndex] = (VkQueue)CreateDispObjHandle();
477 }
478 // TODO: If emulating specific device caps, will need to add intelligence here
479 return;
480''',
481'vkEnumerateInstanceLayerProperties': '''
482 return VK_SUCCESS;
483''',
484'vkEnumerateDeviceLayerProperties': '''
485 return VK_SUCCESS;
486''',
487'vkEnumerateInstanceExtensionProperties': '''
488 // If requesting number of extensions, return that
489 if (!pLayerName) {
490 if (!pProperties) {
491 *pPropertyCount = instance_extension_map.size();
492 } else {
493 uint32_t i = 0;
494 for (const auto &name_ver_pair : instance_extension_map) {
495 if (i == *pPropertyCount) {
496 break;
497 }
498 std::strncpy(pProperties[i].extensionName, name_ver_pair.first.c_str(), sizeof(pProperties[i].extensionName));
499 pProperties[i].extensionName[sizeof(pProperties[i].extensionName) - 1] = 0;
500 pProperties[i].specVersion = name_ver_pair.second;
501 ++i;
502 }
503 if (i != instance_extension_map.size()) {
504 return VK_INCOMPLETE;
505 }
506 }
507 }
508 // If requesting extension properties, fill in data struct for number of extensions
509 return VK_SUCCESS;
510''',
511'vkEnumerateDeviceExtensionProperties': '''
512 // If requesting number of extensions, return that
513 if (!pLayerName) {
514 if (!pProperties) {
515 *pPropertyCount = device_extension_map.size();
516 } else {
517 uint32_t i = 0;
518 for (const auto &name_ver_pair : device_extension_map) {
519 if (i == *pPropertyCount) {
520 break;
521 }
522 std::strncpy(pProperties[i].extensionName, name_ver_pair.first.c_str(), sizeof(pProperties[i].extensionName));
523 pProperties[i].extensionName[sizeof(pProperties[i].extensionName) - 1] = 0;
524 pProperties[i].specVersion = name_ver_pair.second;
525 ++i;
526 }
527 if (i != device_extension_map.size()) {
528 return VK_INCOMPLETE;
529 }
530 }
531 }
532 // If requesting extension properties, fill in data struct for number of extensions
533 return VK_SUCCESS;
534''',
535'vkGetInstanceProcAddr': '''
536 if (!negotiate_loader_icd_interface_called) {
537 loader_interface_version = 0;
538 }
539 const auto &item = name_to_funcptr_map.find(pName);
540 if (item != name_to_funcptr_map.end()) {
541 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
542 }
543 // Mock should intercept all functions so if we get here just return null
544 return nullptr;
545''',
546'vkGetDeviceProcAddr': '''
547 return GetInstanceProcAddr(nullptr, pName);
548''',
549'vkGetPhysicalDeviceMemoryProperties': '''
550 pMemoryProperties->memoryTypeCount = 2;
551 pMemoryProperties->memoryTypes[0].propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
552 pMemoryProperties->memoryTypes[0].heapIndex = 0;
553 pMemoryProperties->memoryTypes[1].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;
554 pMemoryProperties->memoryTypes[1].heapIndex = 1;
555 pMemoryProperties->memoryHeapCount = 2;
556 pMemoryProperties->memoryHeaps[0].flags = 0;
557 pMemoryProperties->memoryHeaps[0].size = 8000000000;
558 pMemoryProperties->memoryHeaps[1].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
559 pMemoryProperties->memoryHeaps[1].size = 8000000000;
560''',
561'vkGetPhysicalDeviceMemoryProperties2KHR': '''
562 GetPhysicalDeviceMemoryProperties(physicalDevice, &pMemoryProperties->memoryProperties);
563''',
564'vkGetPhysicalDeviceQueueFamilyProperties': '''
565 if (!pQueueFamilyProperties) {
566 *pQueueFamilyPropertyCount = 1;
567 } else {
568 if (*pQueueFamilyPropertyCount) {
569 pQueueFamilyProperties[0].queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT | VK_QUEUE_SPARSE_BINDING_BIT;
570 pQueueFamilyProperties[0].queueCount = 1;
571 pQueueFamilyProperties[0].timestampValidBits = 0;
572 pQueueFamilyProperties[0].minImageTransferGranularity = {0,0,0};
573 }
574 }
575''',
576'vkGetPhysicalDeviceQueueFamilyProperties2KHR': '''
577 if (pQueueFamilyPropertyCount && pQueueFamilyProperties) {
578 GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, &pQueueFamilyProperties->queueFamilyProperties);
579 } else {
580 GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, nullptr);
581 }
582''',
583'vkGetPhysicalDeviceFeatures': '''
584 uint32_t num_bools = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
585 VkBool32 *pBool = &pFeatures->robustBufferAccess;
586 for (uint32_t i = 0; i < num_bools; ++i) {
587 pBool[i] = VK_TRUE;
588 }
589''',
590'vkGetPhysicalDeviceFeatures2KHR': '''
591 GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
592''',
593'vkGetPhysicalDeviceFormatProperties': '''
594 // TODO: Just returning full support for everything initially
595 *pFormatProperties = { 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF };
596''',
597'vkGetPhysicalDeviceFormatProperties2KHR': '''
598 GetPhysicalDeviceFormatProperties(physicalDevice, format, &pFormatProperties->formatProperties);
599''',
600'vkGetPhysicalDeviceImageFormatProperties': '''
601 // TODO: Just hard-coding some values for now
602 *pImageFormatProperties = { { 4096, 4096, 256 }, 12, 256, 0x7F, 4294967296 };
603 return VK_SUCCESS;
604''',
605'vkGetPhysicalDeviceImageFormatProperties2KHR': '''
606 GetPhysicalDeviceImageFormatProperties(physicalDevice, pImageFormatInfo->format, pImageFormatInfo->type, pImageFormatInfo->tiling, pImageFormatInfo->usage, pImageFormatInfo->flags, &pImageFormatProperties->imageFormatProperties);
607 return VK_SUCCESS;
608''',
609'vkGetPhysicalDeviceProperties': '''
610 // TODO: Just hard-coding some values for now
611 pProperties->apiVersion = VK_API_VERSION_1_0;
612 pProperties->driverVersion = 1;
613 pProperties->vendorID = 0xba5eba11;
614 pProperties->deviceID = 0xf005ba11;
615 pProperties->deviceType = VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU;
616 //std::string devName = "Vulkan Mock Device";
617 strcpy(pProperties->deviceName, "Vulkan Mock Device");
618 pProperties->pipelineCacheUUID[0] = 18;
619 pProperties->limits = SetLimits(&pProperties->limits);
620 pProperties->sparseProperties = { VK_TRUE, VK_TRUE, VK_TRUE, VK_TRUE, VK_TRUE };
621''',
622'vkGetPhysicalDeviceProperties2KHR': '''
623 GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
624''',
625'vkGetBufferMemoryRequirements': '''
626 // TODO: Just hard-coding reqs for now
627 pMemoryRequirements->size = 4096;
628 pMemoryRequirements->alignment = 1;
629 pMemoryRequirements->memoryTypeBits = 0x1F;
630''',
631'vkGetBufferMemoryRequirements2KHR': '''
632 GetBufferMemoryRequirements(device, pInfo->buffer, &pMemoryRequirements->memoryRequirements);
633''',
634'vkGetImageMemoryRequirements': '''
635 // TODO: Just hard-coding reqs for now
636 pMemoryRequirements->size = 4096;
637 pMemoryRequirements->alignment = 1;
638 pMemoryRequirements->memoryTypeBits = 0x1F;
639''',
640'vkGetImageMemoryRequirements2KHR': '''
641 GetImageMemoryRequirements(device, pInfo->image, &pMemoryRequirements->memoryRequirements);
642''',
643'vkMapMemory': '''
644 // TODO: Just hard-coding 4k whole size for now
645 if (VK_WHOLE_SIZE == size)
646 size = 4096;
647 void* map_addr = malloc(size);
648 mapped_memory_map[memory].push_back(map_addr);
649 *ppData = map_addr;
650 return VK_SUCCESS;
651''',
652'vkUnmapMemory': '''
653 for (auto map_addr : mapped_memory_map[memory]) {
654 free(map_addr);
655 }
656 mapped_memory_map.erase(memory);
657''',
658}
659
660# MockICDGeneratorOptions - subclass of GeneratorOptions.
661#
662# Adds options used by MockICDOutputGenerator objects during Mock
663# ICD generation.
664#
665# Additional members
666# prefixText - list of strings to prefix generated header with
667# (usually a copyright statement + calling convention macros).
668# protectFile - True if multiple inclusion protection should be
669# generated (based on the filename) around the entire header.
670# protectFeature - True if #ifndef..#endif protection should be
671# generated around a feature interface in the header file.
672# genFuncPointers - True if function pointer typedefs should be
673# generated
674# protectProto - If conditional protection should be generated
675# around prototype declarations, set to either '#ifdef'
676# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
677# to require opt-out (#ifndef protectProtoStr). Otherwise
678# set to None.
679# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
680# declarations, if protectProto is set
681# apicall - string to use for the function declaration prefix,
682# such as APICALL on Windows.
683# apientry - string to use for the calling convention macro,
684# in typedefs, such as APIENTRY.
685# apientryp - string to use for the calling convention macro
686# in function pointer typedefs, such as APIENTRYP.
687# indentFuncProto - True if prototype declarations should put each
688# parameter on a separate line
689# indentFuncPointer - True if typedefed function pointers should put each
690# parameter on a separate line
691# alignFuncParam - if nonzero and parameters are being put on a
692# separate line, align parameter names at the specified column
693class MockICDGeneratorOptions(GeneratorOptions):
694 def __init__(self,
695 filename = None,
696 directory = '.',
697 apiname = None,
698 profile = None,
699 versions = '.*',
700 emitversions = '.*',
701 defaultExtensions = None,
702 addExtensions = None,
703 removeExtensions = None,
704 sortProcedure = regSortFeatures,
705 prefixText = "",
706 genFuncPointers = True,
707 protectFile = True,
708 protectFeature = True,
709 protectProto = None,
710 protectProtoStr = None,
711 apicall = '',
712 apientry = '',
713 apientryp = '',
714 indentFuncProto = True,
715 indentFuncPointer = False,
716 alignFuncParam = 0,
717 helper_file_type = ''):
718 GeneratorOptions.__init__(self, filename, directory, apiname, profile,
719 versions, emitversions, defaultExtensions,
720 addExtensions, removeExtensions, sortProcedure)
721 self.prefixText = prefixText
722 self.genFuncPointers = genFuncPointers
723 self.protectFile = protectFile
724 self.protectFeature = protectFeature
725 self.protectProto = protectProto
726 self.protectProtoStr = protectProtoStr
727 self.apicall = apicall
728 self.apientry = apientry
729 self.apientryp = apientryp
730 self.indentFuncProto = indentFuncProto
731 self.indentFuncPointer = indentFuncPointer
732 self.alignFuncParam = alignFuncParam
733
734# MockICDOutputGenerator - subclass of OutputGenerator.
735# Generates a mock vulkan ICD.
736# This is intended to be a minimal replacement for a vulkan device in order
737# to enable Vulkan Validation testing.
738#
739# ---- methods ----
740# MockOutputGenerator(errFile, warnFile, diagFile) - args as for
741# OutputGenerator. Defines additional internal state.
742# ---- methods overriding base class ----
743# beginFile(genOpts)
744# endFile()
745# beginFeature(interface, emit)
746# endFeature()
747# genType(typeinfo,name)
748# genStruct(typeinfo,name)
749# genGroup(groupinfo,name)
750# genEnum(enuminfo, name)
751# genCmd(cmdinfo)
752class MockICDOutputGenerator(OutputGenerator):
753 """Generate specified API interfaces in a specific style, such as a C header"""
754 # This is an ordered list of sections in the header file.
755 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
756 'group', 'bitmask', 'funcpointer', 'struct']
757 ALL_SECTIONS = TYPE_SECTIONS + ['command']
758 def __init__(self,
759 errFile = sys.stderr,
760 warnFile = sys.stderr,
761 diagFile = sys.stdout):
762 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
763 # Internal state - accumulators for different inner block text
764 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
765 self.intercepts = []
766
767 # Check if the parameter passed in is a pointer to an array
768 def paramIsArray(self, param):
769 return param.attrib.get('len') is not None
770
771 # Check if the parameter passed in is a pointer
772 def paramIsPointer(self, param):
773 ispointer = False
774 for elem in param:
775 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
776 ispointer = True
777 return ispointer
778
779 # Check if an object is a non-dispatchable handle
780 def isHandleTypeNonDispatchable(self, handletype):
781 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
782 if handle is not None and handle.find('type').text == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
783 return True
784 else:
785 return False
786
787 # Check if an object is a dispatchable handle
788 def isHandleTypeDispatchable(self, handletype):
789 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
790 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
791 return True
792 else:
793 return False
794
795 def beginFile(self, genOpts):
796 OutputGenerator.beginFile(self, genOpts)
797 # C-specific
798 #
799 # Multiple inclusion protection & C++ namespace.
800 self.header = False
801 if (genOpts.protectFile and self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
802 self.header = True
803 headerSym = '__' + re.sub('\.h', '_h_', os.path.basename(self.genOpts.filename))
804 write('#ifndef', headerSym, file=self.outFile)
805 write('#define', headerSym, '1', file=self.outFile)
806 self.newline()
807 #
808 # User-supplied prefix text, if any (list of strings)
809 if (genOpts.prefixText):
810 for s in genOpts.prefixText:
811 write(s, file=self.outFile)
812 if self.header:
813 write('#include <unordered_map>', file=self.outFile)
814 write('#include <mutex>', file=self.outFile)
815 write('#include <cstring>', file=self.outFile)
816 write('#include "vulkan/vk_icd.h"', file=self.outFile)
817 else:
818 write('#include "mock_icd.h"', file=self.outFile)
819 write('#include <string.h>', file=self.outFile)
820 write('#include <stdlib.h>', file=self.outFile)
821 write('#include <vector>', file=self.outFile)
822
823 write('namespace vkmock {', file=self.outFile)
824 if self.header:
825 self.newline()
826 write(HEADER_C_CODE, file=self.outFile)
827 # Include all of the extensions
828 # static unordered_map<void *, device_layer_data *> device_layer_data_map;
829 # typedef struct VkExtensionProperties {
830 # char extensionName[VK_MAX_EXTENSION_NAME_SIZE];
831 # uint32_t specVersion;
832 # } VkExtensionProperties;
833 device_exts = []
834 instance_exts = []
835 for ext in self.registry.tree.findall("extensions/extension"):
836 if '0' != ext[0][0].attrib['value']: # Only include implemented extensions
837 if (ext.attrib.get('type') and 'instance' == ext.attrib['type']):
838 instance_exts.append(' {"%s", %s},' % (ext.attrib['name'], ext[0][0].attrib['value']))
839 else:
840 device_exts.append(' {"%s", %s},' % (ext.attrib['name'], ext[0][0].attrib['value']))
841 write('// Map of instance extension name to version', file=self.outFile)
842 write('static const std::unordered_map<std::string, uint32_t> instance_extension_map = {', file=self.outFile)
843 write('\n'.join(instance_exts), file=self.outFile)
844 write('};', file=self.outFile)
845 write('// Map of device extension name to version', file=self.outFile)
846 write('static const std::unordered_map<std::string, uint32_t> device_extension_map = {', file=self.outFile)
847 write('\n'.join(device_exts), file=self.outFile)
848 write('};', file=self.outFile)
849
850 else:
851 self.newline()
852 write(SOURCE_CPP_PREFIX, file=self.outFile)
853
854 def endFile(self):
855 # C-specific
856 # Finish C++ namespace and multiple inclusion protection
857 self.newline()
858 if self.header:
859 # record intercepted procedures
860 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
861 write('static const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
862 write('\n'.join(self.intercepts), file=self.outFile)
863 write('};\n', file=self.outFile)
864 self.newline()
865 write('} // namespace vkmock', file=self.outFile)
866 self.newline()
867 write('#endif', file=self.outFile)
868 else: # Loader-layer-interface, need to implement global interface functions
869 write(SOURCE_CPP_POSTFIX, file=self.outFile)
870 #init_commands = self.registry.tree.find("feature/require/[@comment='Device initialization']")
871 #for cmd in init_commands:
872 # cmd_name = cmd.attrib['name']
873 # write('// Found init function: %s' % (cmd_name), file=self.outFile)
874 # cmdinfo = self.registry.tree.find("commands/command/[name='%s']" % (cmd_name))
875 # write('VK_LAYER_EXPORT %s {' % (self.makeCDecls(cmdinfo.elem)[0][:-1]))
876 # Finish processing in superclass
877 OutputGenerator.endFile(self)
878 def beginFeature(self, interface, emit):
879 #write('// starting beginFeature', file=self.outFile)
880 # Start processing in superclass
881 OutputGenerator.beginFeature(self, interface, emit)
882 # C-specific
883 # Accumulate includes, defines, types, enums, function pointer typedefs,
884 # end function prototypes separately for this feature. They're only
885 # printed in endFeature().
886 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
887 #write('// ending beginFeature', file=self.outFile)
888 def endFeature(self):
889 # C-specific
890 # Actually write the interface to the output file.
891 #write('// starting endFeature', file=self.outFile)
892 if (self.emit):
893 self.newline()
894 if (self.genOpts.protectFeature):
895 write('#ifndef', self.featureName, file=self.outFile)
896 # If type declarations are needed by other features based on
897 # this one, it may be necessary to suppress the ExtraProtect,
898 # or move it below the 'for section...' loop.
899 #write('// endFeature looking at self.featureExtraProtect', file=self.outFile)
900 if (self.featureExtraProtect != None):
901 write('#ifdef', self.featureExtraProtect, file=self.outFile)
902 #write('#define', self.featureName, '1', file=self.outFile)
903 for section in self.TYPE_SECTIONS:
904 #write('// endFeature writing section'+section, file=self.outFile)
905 contents = self.sections[section]
906 if contents:
907 write('\n'.join(contents), file=self.outFile)
908 self.newline()
909 #write('// endFeature looking at self.sections[command]', file=self.outFile)
910 if (self.sections['command']):
911 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
912 self.newline()
913 if (self.featureExtraProtect != None):
914 write('#endif /*', self.featureExtraProtect, '*/', file=self.outFile)
915 if (self.genOpts.protectFeature):
916 write('#endif /*', self.featureName, '*/', file=self.outFile)
917 # Finish processing in superclass
918 OutputGenerator.endFeature(self)
919 #write('// ending endFeature', file=self.outFile)
920 #
921 # Append a definition to the specified section
922 def appendSection(self, section, text):
923 # self.sections[section].append('SECTION: ' + section + '\n')
924 self.sections[section].append(text)
925 #
926 # Type generation
927 def genType(self, typeinfo, name):
928 pass
929 #
930 # Struct (e.g. C "struct" type) generation.
931 # This is a special case of the <type> tag where the contents are
932 # interpreted as a set of <member> tags instead of freeform C
933 # C type declarations. The <member> tags are just like <param>
934 # tags - they are a declaration of a struct or union member.
935 # Only simple member declarations are supported (no nested
936 # structs etc.)
937 def genStruct(self, typeinfo, typeName):
938 OutputGenerator.genStruct(self, typeinfo, typeName)
939 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
940 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
941 for member in typeinfo.elem.findall('.//member'):
942 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
943 body += ';\n'
944 body += '} ' + typeName + ';\n'
945 self.appendSection('struct', body)
946 #
947 # Group (e.g. C "enum" type) generation.
948 # These are concatenated together with other types.
949 def genGroup(self, groupinfo, groupName):
950 pass
951 # Enumerant generation
952 # <enum> tags may specify their values in several ways, but are usually
953 # just integers.
954 def genEnum(self, enuminfo, name):
955 pass
956 #
957 # Command generation
958 def genCmd(self, cmdinfo, name):
959 decls = self.makeCDecls(cmdinfo.elem)
960 if self.header: # In the header declare all intercepts
961 self.appendSection('command', '')
962 self.appendSection('command', 'static %s' % (decls[0]))
963 if (self.featureExtraProtect != None):
964 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
965 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
966 if (self.featureExtraProtect != None):
967 self.intercepts += [ '#endif' ]
968 return
969
970 manual_functions = [
971 # Include functions here to be interecpted w/ manually implemented function bodies
972 'vkGetDeviceProcAddr',
973 'vkGetInstanceProcAddr',
974 'vkCreateDevice',
975 'vkDestroyDevice',
976 'vkCreateInstance',
977 'vkDestroyInstance',
978 #'vkCreateDebugReportCallbackEXT',
979 #'vkDestroyDebugReportCallbackEXT',
980 'vkEnumerateInstanceLayerProperties',
981 'vkEnumerateInstanceExtensionProperties',
982 'vkEnumerateDeviceLayerProperties',
983 'vkEnumerateDeviceExtensionProperties',
984 ]
985 if name in manual_functions:
986 self.appendSection('command', '')
987 if name not in CUSTOM_C_INTERCEPTS:
988 self.appendSection('command', '// declare only')
989 self.appendSection('command', 'static %s' % (decls[0]))
990 self.appendSection('command', '// TODO: Implement custom intercept body')
991 else:
992 self.appendSection('command', 'static %s' % (decls[0][:-1]))
993 self.appendSection('command', '{\n%s}' % (CUSTOM_C_INTERCEPTS[name]))
994 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
995 return
996 # record that the function will be intercepted
997 if (self.featureExtraProtect != None):
998 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
999 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1000 if (self.featureExtraProtect != None):
1001 self.intercepts += [ '#endif' ]
1002
1003 OutputGenerator.genCmd(self, cmdinfo, name)
1004 #
1005 self.appendSection('command', '')
1006 self.appendSection('command', 'static %s' % (decls[0][:-1]))
1007 if name in CUSTOM_C_INTERCEPTS:
1008 self.appendSection('command', '{%s}' % (CUSTOM_C_INTERCEPTS[name]))
1009 return
1010 self.appendSection('command', '{')
1011 # setup common to call wrappers
1012 # first parameter is always dispatchable
1013 dispatchable_type = cmdinfo.elem.find('param/type').text
1014 #dispatchable_name = cmdinfo.elem.find('param/name').text
1015 # Default to device
1016 device_or_instance = 'device'
1017 #dispatch_table_name = 'VkLayerDispatchTable'
1018 # Set to instance as necessary
1019 #if dispatchable_type in ["VkPhysicalDevice", "VkInstance"]:
1020 #device_or_instance = 'instance'
1021 #dispatch_table_name = 'VkLayerInstanceDispatchTable'
1022 #self.appendSection('command', ' %s_layer_data *%s_data = GetLayerDataPtr(get_dispatch_key(%s), %s_layer_data_map);' % (device_or_instance, device_or_instance, dispatchable_name, device_or_instance))
1023 api_function_name = cmdinfo.elem.attrib.get('name')
1024 params = cmdinfo.elem.findall('param/name')
1025 paramstext = ', '.join([str(param.text) for param in params])
1026 # GET THE TYPE OF FUNCTION
1027 if True in [ftxt in api_function_name for ftxt in ['Create', 'Allocate']]:
1028 #self.appendSection('command', ' //Add object generation here for last param')
1029 # Get last param
1030 last_param = cmdinfo.elem.findall('param')[-1]
1031 lp_txt = last_param.find('name').text
1032 lp_len = None
1033 if ('len' in last_param.attrib):
1034 lp_len = last_param.attrib['len']
1035 lp_len = lp_len.replace('::', '->')
1036 lp_type = last_param.find('type').text
1037 handle_type = 'dispatchable'
1038 allocator_txt = 'CreateDispObjHandle()';
1039 if (self.isHandleTypeNonDispatchable(lp_type)):
1040 handle_type = 'non-' + handle_type
1041 allocator_txt = 'global_unique_handle++';
1042 # Need to lock in both cases
1043 self.appendSection('command', ' unique_lock_t lock(global_lock);')
1044 if (lp_len != None):
1045 print("%s last params (%s) has len %s" % (handle_type, lp_txt, lp_len))
1046 self.appendSection('command', ' for (uint32_t i = 0; i < %s; ++i) {' % (lp_len))
1047 self.appendSection('command', ' %s[i] = (%s)%s;' % (lp_txt, lp_type, allocator_txt))
1048 self.appendSection('command', ' }')
1049 else:
1050 print("Single %s last param is '%s' w/ type '%s'" % (handle_type, lp_txt, lp_type))
1051 self.appendSection('command', ' *%s = (%s)%s;' % (lp_txt, lp_type, allocator_txt))
1052 # If las param has a len, then we need to loop over that len
1053 # Add unique ID to return value and increment
1054
1055 elif True in [ftxt in api_function_name for ftxt in ['Destroy', 'Free']]:
1056 self.appendSection('command', '//Destroy object')
1057 else:
1058 self.appendSection('command', '//Not a CREATE or DESTROY function')
1059 # GENERATE BODY CODE APPROPRIATELY
1060 #API = api_function_name.replace('vk','%s_data->dispatch_table.' % (device_or_instance),1)
1061 #self.appendSection('command', ' PreCall%s(%s_data, %s);' % (api_function_name[2:], device_or_instance, paramstext))
1062 # Declare result variable, if any.
1063 resulttype = cmdinfo.elem.find('proto/type')
1064 if (resulttype != None and resulttype.text == 'void'):
1065 resulttype = None
1066 if (resulttype != None):
1067 assignresult = resulttype.text + ' result = '
1068 else:
1069 assignresult = ''
1070
1071 #self.appendSection('command', ' ' + assignresult + API + '(' + paramstext + ');')
1072 #self.appendSection('command', ' PostCall%s(%s_data, %s);' % (api_function_name[2:], device_or_instance, paramstext))
1073 # Return result variable, if any.
1074 if (resulttype != None):
1075 self.appendSection('command', ' return VK_SUCCESS;')
1076 self.appendSection('command', '}')
1077 #
1078 # override makeProtoName to drop the "vk" prefix
1079 def makeProtoName(self, name, tail):
1080 return self.genOpts.apientry + name[2:] + tail