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