blob: 899a75b17f1618787430af89f123dcd90f267c9d [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
Tobin Ehlisf9821fe2017-10-27 12:40:32 -0600205extern "C" {
206
Tobin Ehlis45a0a802017-10-13 09:26:20 -0600207EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName) {
208 if (!vkmock::negotiate_loader_icd_interface_called) {
209 vkmock::loader_interface_version = 1;
210 }
211 return vkmock::GetInstanceProcAddr(instance, pName);
212}
213
214EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInstance instance, const char* pName) {
215 return vkmock::GetPhysicalDeviceProcAddr(instance, pName);
216}
217
218EXPORT VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) {
219 vkmock::negotiate_loader_icd_interface_called = true;
220 vkmock::loader_interface_version = *pSupportedVersion;
221 if (*pSupportedVersion > vkmock::SUPPORTED_LOADER_ICD_INTERFACE_VERSION) {
222 *pSupportedVersion = vkmock::SUPPORTED_LOADER_ICD_INTERFACE_VERSION;
223 }
224 return VK_SUCCESS;
225}
226
227
228EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(
229 VkInstance instance,
230 VkSurfaceKHR surface,
231 const VkAllocationCallbacks* pAllocator)
232{
233 vkmock::DestroySurfaceKHR(instance, surface, pAllocator);
234}
235
236EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(
237 VkPhysicalDevice physicalDevice,
238 uint32_t queueFamilyIndex,
239 VkSurfaceKHR surface,
240 VkBool32* pSupported)
241{
242 return vkmock::GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, pSupported);
243}
244
245EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
246 VkPhysicalDevice physicalDevice,
247 VkSurfaceKHR surface,
248 VkSurfaceCapabilitiesKHR* pSurfaceCapabilities)
249{
250 return vkmock::GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities);
251}
252
253EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR(
254 VkPhysicalDevice physicalDevice,
255 VkSurfaceKHR surface,
256 uint32_t* pSurfaceFormatCount,
257 VkSurfaceFormatKHR* pSurfaceFormats)
258{
259 return vkmock::GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);
260}
261
262EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR(
263 VkPhysicalDevice physicalDevice,
264 VkSurfaceKHR surface,
265 uint32_t* pPresentModeCount,
266 VkPresentModeKHR* pPresentModes)
267{
268 return vkmock::GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount, pPresentModes);
269}
270
271EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR(
272 VkInstance instance,
273 const VkDisplaySurfaceCreateInfoKHR* pCreateInfo,
274 const VkAllocationCallbacks* pAllocator,
275 VkSurfaceKHR* pSurface)
276{
277 return vkmock::CreateDisplayPlaneSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
278}
279
280#ifdef VK_USE_PLATFORM_XLIB_KHR
281
282EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(
283 VkInstance instance,
284 const VkXlibSurfaceCreateInfoKHR* pCreateInfo,
285 const VkAllocationCallbacks* pAllocator,
286 VkSurfaceKHR* pSurface)
287{
288 return vkmock::CreateXlibSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
289}
290#endif /* VK_USE_PLATFORM_XLIB_KHR */
291
292#ifdef VK_USE_PLATFORM_XCB_KHR
293
294EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(
295 VkInstance instance,
296 const VkXcbSurfaceCreateInfoKHR* pCreateInfo,
297 const VkAllocationCallbacks* pAllocator,
298 VkSurfaceKHR* pSurface)
299{
300 return vkmock::CreateXcbSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
301}
302#endif /* VK_USE_PLATFORM_XCB_KHR */
303
304#ifdef VK_USE_PLATFORM_WAYLAND_KHR
305
306EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR(
307 VkInstance instance,
308 const VkWaylandSurfaceCreateInfoKHR* pCreateInfo,
309 const VkAllocationCallbacks* pAllocator,
310 VkSurfaceKHR* pSurface)
311{
312 return vkmock::CreateWaylandSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
313}
314#endif /* VK_USE_PLATFORM_WAYLAND_KHR */
315
316#ifdef VK_USE_PLATFORM_MIR_KHR
317
318EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMirSurfaceKHR(
319 VkInstance instance,
320 const VkMirSurfaceCreateInfoKHR* pCreateInfo,
321 const VkAllocationCallbacks* pAllocator,
322 VkSurfaceKHR* pSurface)
323{
324 return vkmock::CreateMirSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
325}
326#endif /* VK_USE_PLATFORM_MIR_KHR */
327
328#ifdef VK_USE_PLATFORM_ANDROID_KHR
329
330EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR(
331 VkInstance instance,
332 const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
333 const VkAllocationCallbacks* pAllocator,
334 VkSurfaceKHR* pSurface)
335{
336 return vkmock::CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
337}
338#endif /* VK_USE_PLATFORM_ANDROID_KHR */
339
340#ifdef VK_USE_PLATFORM_WIN32_KHR
341
342EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(
343 VkInstance instance,
344 const VkWin32SurfaceCreateInfoKHR* pCreateInfo,
345 const VkAllocationCallbacks* pAllocator,
346 VkSurfaceKHR* pSurface)
347{
348 return vkmock::CreateWin32SurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
349}
350#endif /* VK_USE_PLATFORM_WIN32_KHR */
351
352EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHX(
353 VkDevice device,
354 VkSurfaceKHR surface,
355 VkDeviceGroupPresentModeFlagsKHX* pModes)
356{
357 return vkmock::GetDeviceGroupSurfacePresentModesKHX(device, surface, pModes);
358}
359
360EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHX(
361 VkPhysicalDevice physicalDevice,
362 VkSurfaceKHR surface,
363 uint32_t* pRectCount,
364 VkRect2D* pRects)
365{
366 return vkmock::GetPhysicalDevicePresentRectanglesKHX(physicalDevice, surface, pRectCount, pRects);
367}
368
369#ifdef VK_USE_PLATFORM_VI_NN
370
371EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateViSurfaceNN(
372 VkInstance instance,
373 const VkViSurfaceCreateInfoNN* pCreateInfo,
374 const VkAllocationCallbacks* pAllocator,
375 VkSurfaceKHR* pSurface)
376{
377 return vkmock::CreateViSurfaceNN(instance, pCreateInfo, pAllocator, pSurface);
378}
379#endif /* VK_USE_PLATFORM_VI_NN */
380
381EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2EXT(
382 VkPhysicalDevice physicalDevice,
383 VkSurfaceKHR surface,
384 VkSurfaceCapabilities2EXT* pSurfaceCapabilities)
385{
386 return vkmock::GetPhysicalDeviceSurfaceCapabilities2EXT(physicalDevice, surface, pSurfaceCapabilities);
387}
388
389#ifdef VK_USE_PLATFORM_IOS_MVK
390
391EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateIOSSurfaceMVK(
392 VkInstance instance,
393 const VkIOSSurfaceCreateInfoMVK* pCreateInfo,
394 const VkAllocationCallbacks* pAllocator,
395 VkSurfaceKHR* pSurface)
396{
397 return vkmock::CreateIOSSurfaceMVK(instance, pCreateInfo, pAllocator, pSurface);
398}
399#endif /* VK_USE_PLATFORM_IOS_MVK */
400
401#ifdef VK_USE_PLATFORM_MACOS_MVK
402
403EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMacOSSurfaceMVK(
404 VkInstance instance,
405 const VkMacOSSurfaceCreateInfoMVK* pCreateInfo,
406 const VkAllocationCallbacks* pAllocator,
407 VkSurfaceKHR* pSurface)
408{
409 return vkmock::CreateMacOSSurfaceMVK(instance, pCreateInfo, pAllocator, pSurface);
410}
411#endif /* VK_USE_PLATFORM_MACOS_MVK */
Tobin Ehlisf9821fe2017-10-27 12:40:32 -0600412
413} // end extern "C"
414
Tobin Ehlis45a0a802017-10-13 09:26:20 -0600415'''
416
417CUSTOM_C_INTERCEPTS = {
418'vkCreateInstance': '''
419 // TODO: If loader ver <=4 ICD must fail with VK_ERROR_INCOMPATIBLE_DRIVER for all vkCreateInstance calls with
420 // apiVersion set to > Vulkan 1.0 because the loader is still at interface version <= 4. Otherwise, the
421 // ICD should behave as normal.
422 if (loader_interface_version <= 4) {
423 return VK_ERROR_INCOMPATIBLE_DRIVER;
424 }
425 *pInstance = (VkInstance)CreateDispObjHandle();
426 // TODO: If emulating specific device caps, will need to add intelligence here
427 return VK_SUCCESS;
428''',
429'vkDestroyInstance': '''
430 // Destroy physical device
431 DestroyDispObjHandle((void*)physical_device);
432
433 DestroyDispObjHandle((void*)instance);
434''',
435'vkEnumeratePhysicalDevices': '''
436 if (pPhysicalDevices) {
437 if (!physical_device) {
438 physical_device = (VkPhysicalDevice)CreateDispObjHandle();
439 }
440 *pPhysicalDevices = physical_device;
441 } else {
442 *pPhysicalDeviceCount = 1;
443 }
444 return VK_SUCCESS;
445''',
446'vkCreateDevice': '''
447 *pDevice = (VkDevice)CreateDispObjHandle();
448 // TODO: If emulating specific device caps, will need to add intelligence here
449 return VK_SUCCESS;
450''',
451'vkDestroyDevice': '''
Mike Stroyanf215ee22017-11-02 10:39:34 -0600452 unique_lock_t lock(global_lock);
Tobin Ehlis45a0a802017-10-13 09:26:20 -0600453 // First destroy sub-device objects
454 // Destroy Queues
455 for (auto dev_queue_map_pair : queue_map) {
456 for (auto queue_family_map_pair : queue_map[dev_queue_map_pair.first]) {
457 for (auto index_queue_pair : queue_map[dev_queue_map_pair.first][queue_family_map_pair.first]) {
458 DestroyDispObjHandle((void*)index_queue_pair.second);
459 }
460 }
461 }
462 queue_map.clear();
463 // Now destroy device
464 DestroyDispObjHandle((void*)device);
465 // TODO: If emulating specific device caps, will need to add intelligence here
466''',
467'vkGetDeviceQueue': '''
Mike Stroyanf215ee22017-11-02 10:39:34 -0600468 unique_lock_t lock(global_lock);
Tobin Ehlis45a0a802017-10-13 09:26:20 -0600469 auto queue = queue_map[device][queueFamilyIndex][queueIndex];
470 if (queue) {
471 *pQueue = queue;
472 } else {
473 *pQueue = queue_map[device][queueFamilyIndex][queueIndex] = (VkQueue)CreateDispObjHandle();
474 }
475 // TODO: If emulating specific device caps, will need to add intelligence here
476 return;
477''',
478'vkEnumerateInstanceLayerProperties': '''
479 return VK_SUCCESS;
480''',
481'vkEnumerateDeviceLayerProperties': '''
482 return VK_SUCCESS;
483''',
484'vkEnumerateInstanceExtensionProperties': '''
485 // If requesting number of extensions, return that
486 if (!pLayerName) {
487 if (!pProperties) {
Tobin Ehlisf9821fe2017-10-27 12:40:32 -0600488 *pPropertyCount = (uint32_t)instance_extension_map.size();
Tobin Ehlis45a0a802017-10-13 09:26:20 -0600489 } else {
490 uint32_t i = 0;
491 for (const auto &name_ver_pair : instance_extension_map) {
492 if (i == *pPropertyCount) {
493 break;
494 }
495 std::strncpy(pProperties[i].extensionName, name_ver_pair.first.c_str(), sizeof(pProperties[i].extensionName));
496 pProperties[i].extensionName[sizeof(pProperties[i].extensionName) - 1] = 0;
497 pProperties[i].specVersion = name_ver_pair.second;
498 ++i;
499 }
500 if (i != instance_extension_map.size()) {
501 return VK_INCOMPLETE;
502 }
503 }
504 }
505 // If requesting extension properties, fill in data struct for number of extensions
506 return VK_SUCCESS;
507''',
508'vkEnumerateDeviceExtensionProperties': '''
509 // If requesting number of extensions, return that
510 if (!pLayerName) {
511 if (!pProperties) {
Tobin Ehlisf9821fe2017-10-27 12:40:32 -0600512 *pPropertyCount = (uint32_t)device_extension_map.size();
Tobin Ehlis45a0a802017-10-13 09:26:20 -0600513 } else {
514 uint32_t i = 0;
515 for (const auto &name_ver_pair : device_extension_map) {
516 if (i == *pPropertyCount) {
517 break;
518 }
519 std::strncpy(pProperties[i].extensionName, name_ver_pair.first.c_str(), sizeof(pProperties[i].extensionName));
520 pProperties[i].extensionName[sizeof(pProperties[i].extensionName) - 1] = 0;
521 pProperties[i].specVersion = name_ver_pair.second;
522 ++i;
523 }
524 if (i != device_extension_map.size()) {
525 return VK_INCOMPLETE;
526 }
527 }
528 }
529 // If requesting extension properties, fill in data struct for number of extensions
530 return VK_SUCCESS;
531''',
532'vkGetInstanceProcAddr': '''
533 if (!negotiate_loader_icd_interface_called) {
534 loader_interface_version = 0;
535 }
536 const auto &item = name_to_funcptr_map.find(pName);
537 if (item != name_to_funcptr_map.end()) {
538 return reinterpret_cast<PFN_vkVoidFunction>(item->second);
539 }
540 // Mock should intercept all functions so if we get here just return null
541 return nullptr;
542''',
543'vkGetDeviceProcAddr': '''
544 return GetInstanceProcAddr(nullptr, pName);
545''',
546'vkGetPhysicalDeviceMemoryProperties': '''
547 pMemoryProperties->memoryTypeCount = 2;
548 pMemoryProperties->memoryTypes[0].propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
549 pMemoryProperties->memoryTypes[0].heapIndex = 0;
550 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;
551 pMemoryProperties->memoryTypes[1].heapIndex = 1;
552 pMemoryProperties->memoryHeapCount = 2;
553 pMemoryProperties->memoryHeaps[0].flags = 0;
554 pMemoryProperties->memoryHeaps[0].size = 8000000000;
555 pMemoryProperties->memoryHeaps[1].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
556 pMemoryProperties->memoryHeaps[1].size = 8000000000;
557''',
558'vkGetPhysicalDeviceMemoryProperties2KHR': '''
559 GetPhysicalDeviceMemoryProperties(physicalDevice, &pMemoryProperties->memoryProperties);
560''',
561'vkGetPhysicalDeviceQueueFamilyProperties': '''
562 if (!pQueueFamilyProperties) {
563 *pQueueFamilyPropertyCount = 1;
564 } else {
565 if (*pQueueFamilyPropertyCount) {
566 pQueueFamilyProperties[0].queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT | VK_QUEUE_SPARSE_BINDING_BIT;
567 pQueueFamilyProperties[0].queueCount = 1;
568 pQueueFamilyProperties[0].timestampValidBits = 0;
Tobin Ehlisb2c98bf2017-10-26 17:25:05 -0600569 pQueueFamilyProperties[0].minImageTransferGranularity = {1,1,1};
Tobin Ehlis45a0a802017-10-13 09:26:20 -0600570 }
571 }
572''',
573'vkGetPhysicalDeviceQueueFamilyProperties2KHR': '''
574 if (pQueueFamilyPropertyCount && pQueueFamilyProperties) {
575 GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, &pQueueFamilyProperties->queueFamilyProperties);
576 } else {
577 GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, nullptr);
578 }
579''',
580'vkGetPhysicalDeviceFeatures': '''
581 uint32_t num_bools = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
582 VkBool32 *pBool = &pFeatures->robustBufferAccess;
583 for (uint32_t i = 0; i < num_bools; ++i) {
584 pBool[i] = VK_TRUE;
585 }
586''',
587'vkGetPhysicalDeviceFeatures2KHR': '''
588 GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
589''',
590'vkGetPhysicalDeviceFormatProperties': '''
Tobin Ehlis52a3afe2017-11-03 14:52:11 -0600591 if (VK_FORMAT_UNDEFINED == format) {
592 *pFormatProperties = { 0x0, 0x0, 0x0 };
593 } else {
594 // TODO: Just returning full support for everything initially
595 *pFormatProperties = { 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF };
596 }
Tobin Ehlis45a0a802017-10-13 09:26:20 -0600597''',
598'vkGetPhysicalDeviceFormatProperties2KHR': '''
599 GetPhysicalDeviceFormatProperties(physicalDevice, format, &pFormatProperties->formatProperties);
600''',
601'vkGetPhysicalDeviceImageFormatProperties': '''
602 // TODO: Just hard-coding some values for now
Tobin Ehlis85544112017-10-26 15:21:51 -0600603 // TODO: If tiling is linear, limit the mips, levels, & sample count
604 if (VK_IMAGE_TILING_LINEAR == tiling) {
605 *pImageFormatProperties = { { 4096, 4096, 256 }, 1, 1, VK_SAMPLE_COUNT_1_BIT, 4294967296 };
606 } else {
607 *pImageFormatProperties = { { 4096, 4096, 256 }, 12, 256, 0x7F, 4294967296 };
608 }
Tobin Ehlis45a0a802017-10-13 09:26:20 -0600609 return VK_SUCCESS;
610''',
611'vkGetPhysicalDeviceImageFormatProperties2KHR': '''
612 GetPhysicalDeviceImageFormatProperties(physicalDevice, pImageFormatInfo->format, pImageFormatInfo->type, pImageFormatInfo->tiling, pImageFormatInfo->usage, pImageFormatInfo->flags, &pImageFormatProperties->imageFormatProperties);
613 return VK_SUCCESS;
614''',
615'vkGetPhysicalDeviceProperties': '''
616 // TODO: Just hard-coding some values for now
617 pProperties->apiVersion = VK_API_VERSION_1_0;
618 pProperties->driverVersion = 1;
619 pProperties->vendorID = 0xba5eba11;
620 pProperties->deviceID = 0xf005ba11;
621 pProperties->deviceType = VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU;
622 //std::string devName = "Vulkan Mock Device";
623 strcpy(pProperties->deviceName, "Vulkan Mock Device");
624 pProperties->pipelineCacheUUID[0] = 18;
625 pProperties->limits = SetLimits(&pProperties->limits);
626 pProperties->sparseProperties = { VK_TRUE, VK_TRUE, VK_TRUE, VK_TRUE, VK_TRUE };
627''',
628'vkGetPhysicalDeviceProperties2KHR': '''
629 GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
630''',
631'vkGetBufferMemoryRequirements': '''
632 // TODO: Just hard-coding reqs for now
633 pMemoryRequirements->size = 4096;
634 pMemoryRequirements->alignment = 1;
635 pMemoryRequirements->memoryTypeBits = 0x1F;
636''',
637'vkGetBufferMemoryRequirements2KHR': '''
638 GetBufferMemoryRequirements(device, pInfo->buffer, &pMemoryRequirements->memoryRequirements);
639''',
640'vkGetImageMemoryRequirements': '''
641 // TODO: Just hard-coding reqs for now
642 pMemoryRequirements->size = 4096;
643 pMemoryRequirements->alignment = 1;
644 pMemoryRequirements->memoryTypeBits = 0x1F;
645''',
646'vkGetImageMemoryRequirements2KHR': '''
647 GetImageMemoryRequirements(device, pInfo->image, &pMemoryRequirements->memoryRequirements);
648''',
649'vkMapMemory': '''
Mike Stroyanf215ee22017-11-02 10:39:34 -0600650 unique_lock_t lock(global_lock);
Tobin Ehlis45a0a802017-10-13 09:26:20 -0600651 // TODO: Just hard-coding 4k whole size for now
652 if (VK_WHOLE_SIZE == size)
653 size = 4096;
Tobin Ehlisf9821fe2017-10-27 12:40:32 -0600654 void* map_addr = malloc((size_t)size);
Tobin Ehlis45a0a802017-10-13 09:26:20 -0600655 mapped_memory_map[memory].push_back(map_addr);
656 *ppData = map_addr;
657 return VK_SUCCESS;
658''',
659'vkUnmapMemory': '''
Mike Stroyanf215ee22017-11-02 10:39:34 -0600660 unique_lock_t lock(global_lock);
Tobin Ehlis45a0a802017-10-13 09:26:20 -0600661 for (auto map_addr : mapped_memory_map[memory]) {
662 free(map_addr);
663 }
664 mapped_memory_map.erase(memory);
665''',
666}
667
668# MockICDGeneratorOptions - subclass of GeneratorOptions.
669#
670# Adds options used by MockICDOutputGenerator objects during Mock
671# ICD generation.
672#
673# Additional members
674# prefixText - list of strings to prefix generated header with
675# (usually a copyright statement + calling convention macros).
676# protectFile - True if multiple inclusion protection should be
677# generated (based on the filename) around the entire header.
678# protectFeature - True if #ifndef..#endif protection should be
679# generated around a feature interface in the header file.
680# genFuncPointers - True if function pointer typedefs should be
681# generated
682# protectProto - If conditional protection should be generated
683# around prototype declarations, set to either '#ifdef'
684# to require opt-in (#ifdef protectProtoStr) or '#ifndef'
685# to require opt-out (#ifndef protectProtoStr). Otherwise
686# set to None.
687# protectProtoStr - #ifdef/#ifndef symbol to use around prototype
688# declarations, if protectProto is set
689# apicall - string to use for the function declaration prefix,
690# such as APICALL on Windows.
691# apientry - string to use for the calling convention macro,
692# in typedefs, such as APIENTRY.
693# apientryp - string to use for the calling convention macro
694# in function pointer typedefs, such as APIENTRYP.
695# indentFuncProto - True if prototype declarations should put each
696# parameter on a separate line
697# indentFuncPointer - True if typedefed function pointers should put each
698# parameter on a separate line
699# alignFuncParam - if nonzero and parameters are being put on a
700# separate line, align parameter names at the specified column
701class MockICDGeneratorOptions(GeneratorOptions):
702 def __init__(self,
703 filename = None,
704 directory = '.',
705 apiname = None,
706 profile = None,
707 versions = '.*',
708 emitversions = '.*',
709 defaultExtensions = None,
710 addExtensions = None,
711 removeExtensions = None,
712 sortProcedure = regSortFeatures,
713 prefixText = "",
714 genFuncPointers = True,
715 protectFile = True,
716 protectFeature = True,
717 protectProto = None,
718 protectProtoStr = None,
719 apicall = '',
720 apientry = '',
721 apientryp = '',
722 indentFuncProto = True,
723 indentFuncPointer = False,
724 alignFuncParam = 0,
725 helper_file_type = ''):
726 GeneratorOptions.__init__(self, filename, directory, apiname, profile,
727 versions, emitversions, defaultExtensions,
728 addExtensions, removeExtensions, sortProcedure)
729 self.prefixText = prefixText
730 self.genFuncPointers = genFuncPointers
731 self.protectFile = protectFile
732 self.protectFeature = protectFeature
733 self.protectProto = protectProto
734 self.protectProtoStr = protectProtoStr
735 self.apicall = apicall
736 self.apientry = apientry
737 self.apientryp = apientryp
738 self.indentFuncProto = indentFuncProto
739 self.indentFuncPointer = indentFuncPointer
740 self.alignFuncParam = alignFuncParam
741
742# MockICDOutputGenerator - subclass of OutputGenerator.
743# Generates a mock vulkan ICD.
744# This is intended to be a minimal replacement for a vulkan device in order
745# to enable Vulkan Validation testing.
746#
747# ---- methods ----
748# MockOutputGenerator(errFile, warnFile, diagFile) - args as for
749# OutputGenerator. Defines additional internal state.
750# ---- methods overriding base class ----
751# beginFile(genOpts)
752# endFile()
753# beginFeature(interface, emit)
754# endFeature()
755# genType(typeinfo,name)
756# genStruct(typeinfo,name)
757# genGroup(groupinfo,name)
758# genEnum(enuminfo, name)
759# genCmd(cmdinfo)
760class MockICDOutputGenerator(OutputGenerator):
761 """Generate specified API interfaces in a specific style, such as a C header"""
762 # This is an ordered list of sections in the header file.
763 TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
764 'group', 'bitmask', 'funcpointer', 'struct']
765 ALL_SECTIONS = TYPE_SECTIONS + ['command']
766 def __init__(self,
767 errFile = sys.stderr,
768 warnFile = sys.stderr,
769 diagFile = sys.stdout):
770 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
771 # Internal state - accumulators for different inner block text
772 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
773 self.intercepts = []
774
775 # Check if the parameter passed in is a pointer to an array
776 def paramIsArray(self, param):
777 return param.attrib.get('len') is not None
778
779 # Check if the parameter passed in is a pointer
780 def paramIsPointer(self, param):
781 ispointer = False
782 for elem in param:
783 if ((elem.tag is not 'type') and (elem.tail is not None)) and '*' in elem.tail:
784 ispointer = True
785 return ispointer
786
787 # Check if an object is a non-dispatchable handle
788 def isHandleTypeNonDispatchable(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_NON_DISPATCHABLE_HANDLE':
791 return True
792 else:
793 return False
794
795 # Check if an object is a dispatchable handle
796 def isHandleTypeDispatchable(self, handletype):
797 handle = self.registry.tree.find("types/type/[name='" + handletype + "'][@category='handle']")
798 if handle is not None and handle.find('type').text == 'VK_DEFINE_HANDLE':
799 return True
800 else:
801 return False
802
803 def beginFile(self, genOpts):
804 OutputGenerator.beginFile(self, genOpts)
805 # C-specific
806 #
807 # Multiple inclusion protection & C++ namespace.
808 self.header = False
809 if (genOpts.protectFile and self.genOpts.filename and 'h' == self.genOpts.filename[-1]):
810 self.header = True
811 headerSym = '__' + re.sub('\.h', '_h_', os.path.basename(self.genOpts.filename))
812 write('#ifndef', headerSym, file=self.outFile)
813 write('#define', headerSym, '1', file=self.outFile)
814 self.newline()
815 #
816 # User-supplied prefix text, if any (list of strings)
817 if (genOpts.prefixText):
818 for s in genOpts.prefixText:
819 write(s, file=self.outFile)
820 if self.header:
821 write('#include <unordered_map>', file=self.outFile)
822 write('#include <mutex>', file=self.outFile)
823 write('#include <cstring>', file=self.outFile)
824 write('#include "vulkan/vk_icd.h"', file=self.outFile)
825 else:
826 write('#include "mock_icd.h"', file=self.outFile)
827 write('#include <string.h>', file=self.outFile)
828 write('#include <stdlib.h>', file=self.outFile)
829 write('#include <vector>', file=self.outFile)
830
831 write('namespace vkmock {', file=self.outFile)
832 if self.header:
833 self.newline()
834 write(HEADER_C_CODE, file=self.outFile)
Tobin Ehlis0f3ce862017-10-31 08:50:48 -0600835 # Include all of the extensions in ICD except specific ignored ones
Tobin Ehlis45a0a802017-10-13 09:26:20 -0600836 device_exts = []
837 instance_exts = []
Tobin Ehlis479b7c82017-10-26 14:47:51 -0600838 # Ignore extensions that ICDs should not implement
839 ignore_exts = ['VK_EXT_validation_cache']
Tobin Ehlis45a0a802017-10-13 09:26:20 -0600840 for ext in self.registry.tree.findall("extensions/extension"):
841 if '0' != ext[0][0].attrib['value']: # Only include implemented extensions
Tobin Ehlis479b7c82017-10-26 14:47:51 -0600842 if (ext.attrib['name'] in ignore_exts):
843 pass
844 elif (ext.attrib.get('type') and 'instance' == ext.attrib['type']):
Tobin Ehlis45a0a802017-10-13 09:26:20 -0600845 instance_exts.append(' {"%s", %s},' % (ext.attrib['name'], ext[0][0].attrib['value']))
846 else:
847 device_exts.append(' {"%s", %s},' % (ext.attrib['name'], ext[0][0].attrib['value']))
848 write('// Map of instance extension name to version', file=self.outFile)
849 write('static const std::unordered_map<std::string, uint32_t> instance_extension_map = {', file=self.outFile)
850 write('\n'.join(instance_exts), file=self.outFile)
851 write('};', file=self.outFile)
852 write('// Map of device extension name to version', file=self.outFile)
853 write('static const std::unordered_map<std::string, uint32_t> device_extension_map = {', file=self.outFile)
854 write('\n'.join(device_exts), file=self.outFile)
855 write('};', file=self.outFile)
856
857 else:
858 self.newline()
859 write(SOURCE_CPP_PREFIX, file=self.outFile)
860
861 def endFile(self):
862 # C-specific
863 # Finish C++ namespace and multiple inclusion protection
864 self.newline()
865 if self.header:
866 # record intercepted procedures
867 write('// Map of all APIs to be intercepted by this layer', file=self.outFile)
868 write('static const std::unordered_map<std::string, void*> name_to_funcptr_map = {', file=self.outFile)
869 write('\n'.join(self.intercepts), file=self.outFile)
870 write('};\n', file=self.outFile)
871 self.newline()
872 write('} // namespace vkmock', file=self.outFile)
873 self.newline()
874 write('#endif', file=self.outFile)
875 else: # Loader-layer-interface, need to implement global interface functions
876 write(SOURCE_CPP_POSTFIX, file=self.outFile)
Tobin Ehlis45a0a802017-10-13 09:26:20 -0600877 # Finish processing in superclass
878 OutputGenerator.endFile(self)
879 def beginFeature(self, interface, emit):
880 #write('// starting beginFeature', file=self.outFile)
881 # Start processing in superclass
882 OutputGenerator.beginFeature(self, interface, emit)
883 # C-specific
884 # Accumulate includes, defines, types, enums, function pointer typedefs,
885 # end function prototypes separately for this feature. They're only
886 # printed in endFeature().
887 self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
888 #write('// ending beginFeature', file=self.outFile)
889 def endFeature(self):
890 # C-specific
891 # Actually write the interface to the output file.
892 #write('// starting endFeature', file=self.outFile)
893 if (self.emit):
894 self.newline()
895 if (self.genOpts.protectFeature):
896 write('#ifndef', self.featureName, file=self.outFile)
897 # If type declarations are needed by other features based on
898 # this one, it may be necessary to suppress the ExtraProtect,
899 # or move it below the 'for section...' loop.
900 #write('// endFeature looking at self.featureExtraProtect', file=self.outFile)
901 if (self.featureExtraProtect != None):
902 write('#ifdef', self.featureExtraProtect, file=self.outFile)
903 #write('#define', self.featureName, '1', file=self.outFile)
904 for section in self.TYPE_SECTIONS:
905 #write('// endFeature writing section'+section, file=self.outFile)
906 contents = self.sections[section]
907 if contents:
908 write('\n'.join(contents), file=self.outFile)
909 self.newline()
910 #write('// endFeature looking at self.sections[command]', file=self.outFile)
911 if (self.sections['command']):
912 write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
913 self.newline()
914 if (self.featureExtraProtect != None):
915 write('#endif /*', self.featureExtraProtect, '*/', file=self.outFile)
916 if (self.genOpts.protectFeature):
917 write('#endif /*', self.featureName, '*/', file=self.outFile)
918 # Finish processing in superclass
919 OutputGenerator.endFeature(self)
920 #write('// ending endFeature', file=self.outFile)
921 #
922 # Append a definition to the specified section
923 def appendSection(self, section, text):
924 # self.sections[section].append('SECTION: ' + section + '\n')
925 self.sections[section].append(text)
926 #
927 # Type generation
928 def genType(self, typeinfo, name):
929 pass
930 #
931 # Struct (e.g. C "struct" type) generation.
932 # This is a special case of the <type> tag where the contents are
933 # interpreted as a set of <member> tags instead of freeform C
934 # C type declarations. The <member> tags are just like <param>
935 # tags - they are a declaration of a struct or union member.
936 # Only simple member declarations are supported (no nested
937 # structs etc.)
938 def genStruct(self, typeinfo, typeName):
939 OutputGenerator.genStruct(self, typeinfo, typeName)
940 body = 'typedef ' + typeinfo.elem.get('category') + ' ' + typeName + ' {\n'
941 # paramdecl = self.makeCParamDecl(typeinfo.elem, self.genOpts.alignFuncParam)
942 for member in typeinfo.elem.findall('.//member'):
943 body += self.makeCParamDecl(member, self.genOpts.alignFuncParam)
944 body += ';\n'
945 body += '} ' + typeName + ';\n'
946 self.appendSection('struct', body)
947 #
948 # Group (e.g. C "enum" type) generation.
949 # These are concatenated together with other types.
950 def genGroup(self, groupinfo, groupName):
951 pass
952 # Enumerant generation
953 # <enum> tags may specify their values in several ways, but are usually
954 # just integers.
955 def genEnum(self, enuminfo, name):
956 pass
957 #
958 # Command generation
959 def genCmd(self, cmdinfo, name):
960 decls = self.makeCDecls(cmdinfo.elem)
961 if self.header: # In the header declare all intercepts
962 self.appendSection('command', '')
963 self.appendSection('command', 'static %s' % (decls[0]))
964 if (self.featureExtraProtect != None):
965 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
966 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
967 if (self.featureExtraProtect != None):
968 self.intercepts += [ '#endif' ]
969 return
970
971 manual_functions = [
972 # Include functions here to be interecpted w/ manually implemented function bodies
973 'vkGetDeviceProcAddr',
974 'vkGetInstanceProcAddr',
975 'vkCreateDevice',
976 'vkDestroyDevice',
977 'vkCreateInstance',
978 'vkDestroyInstance',
979 #'vkCreateDebugReportCallbackEXT',
980 #'vkDestroyDebugReportCallbackEXT',
981 'vkEnumerateInstanceLayerProperties',
982 'vkEnumerateInstanceExtensionProperties',
983 'vkEnumerateDeviceLayerProperties',
984 'vkEnumerateDeviceExtensionProperties',
985 ]
986 if name in manual_functions:
987 self.appendSection('command', '')
988 if name not in CUSTOM_C_INTERCEPTS:
989 self.appendSection('command', '// declare only')
990 self.appendSection('command', 'static %s' % (decls[0]))
991 self.appendSection('command', '// TODO: Implement custom intercept body')
992 else:
993 self.appendSection('command', 'static %s' % (decls[0][:-1]))
994 self.appendSection('command', '{\n%s}' % (CUSTOM_C_INTERCEPTS[name]))
995 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
996 return
997 # record that the function will be intercepted
998 if (self.featureExtraProtect != None):
999 self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
1000 self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
1001 if (self.featureExtraProtect != None):
1002 self.intercepts += [ '#endif' ]
1003
1004 OutputGenerator.genCmd(self, cmdinfo, name)
1005 #
1006 self.appendSection('command', '')
1007 self.appendSection('command', 'static %s' % (decls[0][:-1]))
1008 if name in CUSTOM_C_INTERCEPTS:
1009 self.appendSection('command', '{%s}' % (CUSTOM_C_INTERCEPTS[name]))
1010 return
1011 self.appendSection('command', '{')
Tobin Ehlis0f3ce862017-10-31 08:50:48 -06001012
Tobin Ehlis45a0a802017-10-13 09:26:20 -06001013 api_function_name = cmdinfo.elem.attrib.get('name')
Tobin Ehlis45a0a802017-10-13 09:26:20 -06001014 # GET THE TYPE OF FUNCTION
1015 if True in [ftxt in api_function_name for ftxt in ['Create', 'Allocate']]:
Tobin Ehlis45a0a802017-10-13 09:26:20 -06001016 # Get last param
1017 last_param = cmdinfo.elem.findall('param')[-1]
1018 lp_txt = last_param.find('name').text
1019 lp_len = None
1020 if ('len' in last_param.attrib):
1021 lp_len = last_param.attrib['len']
1022 lp_len = lp_len.replace('::', '->')
1023 lp_type = last_param.find('type').text
1024 handle_type = 'dispatchable'
1025 allocator_txt = 'CreateDispObjHandle()';
1026 if (self.isHandleTypeNonDispatchable(lp_type)):
1027 handle_type = 'non-' + handle_type
1028 allocator_txt = 'global_unique_handle++';
1029 # Need to lock in both cases
1030 self.appendSection('command', ' unique_lock_t lock(global_lock);')
1031 if (lp_len != None):
Tobin Ehlis0f3ce862017-10-31 08:50:48 -06001032 #print("%s last params (%s) has len %s" % (handle_type, lp_txt, lp_len))
Tobin Ehlis45a0a802017-10-13 09:26:20 -06001033 self.appendSection('command', ' for (uint32_t i = 0; i < %s; ++i) {' % (lp_len))
1034 self.appendSection('command', ' %s[i] = (%s)%s;' % (lp_txt, lp_type, allocator_txt))
1035 self.appendSection('command', ' }')
1036 else:
Tobin Ehlis0f3ce862017-10-31 08:50:48 -06001037 #print("Single %s last param is '%s' w/ type '%s'" % (handle_type, lp_txt, lp_type))
Tobin Ehlis45a0a802017-10-13 09:26:20 -06001038 self.appendSection('command', ' *%s = (%s)%s;' % (lp_txt, lp_type, allocator_txt))
Tobin Ehlis45a0a802017-10-13 09:26:20 -06001039 elif True in [ftxt in api_function_name for ftxt in ['Destroy', 'Free']]:
1040 self.appendSection('command', '//Destroy object')
1041 else:
1042 self.appendSection('command', '//Not a CREATE or DESTROY function')
Tobin Ehlis45a0a802017-10-13 09:26:20 -06001043 # Declare result variable, if any.
1044 resulttype = cmdinfo.elem.find('proto/type')
1045 if (resulttype != None and resulttype.text == 'void'):
1046 resulttype = None
Tobin Ehlis45a0a802017-10-13 09:26:20 -06001047
Tobin Ehlis45a0a802017-10-13 09:26:20 -06001048 # Return result variable, if any.
1049 if (resulttype != None):
1050 self.appendSection('command', ' return VK_SUCCESS;')
1051 self.appendSection('command', '}')
1052 #
1053 # override makeProtoName to drop the "vk" prefix
1054 def makeProtoName(self, name, tail):
1055 return self.genOpts.apientry + name[2:] + tail