null_driver.cpp revision 03c64b0b525a2f259456a220c51bbc8438ae2c03
1/*
2 * Copyright 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <hardware/hwvulkan.h>
18
19#include <array>
20#include <algorithm>
21#include <inttypes.h>
22#include <string.h>
23
24// #define LOG_NDEBUG 0
25#include <log/log.h>
26#include <utils/Errors.h>
27
28#include "null_driver.h"
29
30using namespace null_driver;
31
32struct VkPhysicalDevice_T {
33    hwvulkan_dispatch_t dispatch;
34};
35
36struct VkInstance_T {
37    hwvulkan_dispatch_t dispatch;
38    const VkAllocCallbacks* alloc;
39    VkPhysicalDevice_T physical_device;
40};
41
42struct VkQueue_T {
43    hwvulkan_dispatch_t dispatch;
44};
45
46struct VkCmdBuffer_T {
47    hwvulkan_dispatch_t dispatch;
48};
49
50namespace {
51// Handles for non-dispatchable objects are either pointers, or arbitrary
52// 64-bit non-zero values. We only use pointers when we need to keep state for
53// the object even in a null driver. For the rest, we form a handle as:
54//   [63:63] = 1 to distinguish from pointer handles*
55//   [62:56] = non-zero handle type enum value
56//   [55: 0] = per-handle-type incrementing counter
57// * This works because virtual addresses with the high bit set are reserved
58// for kernel data in all ABIs we run on.
59//
60// We never reclaim handles on vkDestroy*. It's not even necessary for us to
61// have distinct handles for live objects, and practically speaking we won't
62// ever create 2^56 objects of the same type from a single VkDevice in a null
63// driver.
64//
65// Using a namespace here instead of 'enum class' since we want scoped
66// constants but also want implicit conversions to integral types.
67namespace HandleType {
68enum Enum {
69    kAttachmentView,
70    kBufferView,
71    kCmdPool,
72    kDescriptorPool,
73    kDescriptorSet,
74    kDescriptorSetLayout,
75    kDynamicColorBlendState,
76    kDynamicDepthStencilState,
77    kDynamicRasterState,
78    kDynamicViewportState,
79    kEvent,
80    kFence,
81    kFramebuffer,
82    kImageView,
83    kPipeline,
84    kPipelineCache,
85    kPipelineLayout,
86    kQueryPool,
87    kRenderPass,
88    kSampler,
89    kSemaphore,
90    kShader,
91    kShaderModule,
92
93    kNumTypes
94};
95}  // namespace HandleType
96uint64_t AllocHandle(VkDevice device, HandleType::Enum type);
97
98const VkDeviceSize kMaxDeviceMemory = VkDeviceSize(INTPTR_MAX) + 1;
99
100}  // anonymous namespace
101
102struct VkDevice_T {
103    hwvulkan_dispatch_t dispatch;
104    VkInstance_T* instance;
105    VkQueue_T queue;
106    std::array<uint64_t, HandleType::kNumTypes> next_handle;
107};
108
109// -----------------------------------------------------------------------------
110// Declare HAL_MODULE_INFO_SYM early so it can be referenced by nulldrv_device
111// later.
112
113namespace {
114int OpenDevice(const hw_module_t* module, const char* id, hw_device_t** device);
115hw_module_methods_t nulldrv_module_methods = {.open = OpenDevice};
116}  // namespace
117
118#pragma clang diagnostic push
119#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
120__attribute__((visibility("default"))) hwvulkan_module_t HAL_MODULE_INFO_SYM = {
121    .common =
122        {
123            .tag = HARDWARE_MODULE_TAG,
124            .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
125            .hal_api_version = HARDWARE_HAL_API_VERSION,
126            .id = HWVULKAN_HARDWARE_MODULE_ID,
127            .name = "Null Vulkan Driver",
128            .author = "The Android Open Source Project",
129            .methods = &nulldrv_module_methods,
130        },
131};
132#pragma clang diagnostic pop
133
134// -----------------------------------------------------------------------------
135
136namespace {
137
138VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
139                        VkInstance* out_instance) {
140    // Assume the loader provided alloc callbacks even if the app didn't.
141    ALOG_ASSERT(
142        create_info->pAllocCb,
143        "Missing alloc callbacks, loader or app should have provided them");
144
145    VkInstance_T* instance =
146        static_cast<VkInstance_T*>(create_info->pAllocCb->pfnAlloc(
147            create_info->pAllocCb->pUserData, sizeof(VkInstance_T),
148            alignof(VkInstance_T), VK_SYSTEM_ALLOC_TYPE_API_OBJECT));
149    if (!instance)
150        return VK_ERROR_OUT_OF_HOST_MEMORY;
151
152    instance->dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
153    instance->alloc = create_info->pAllocCb;
154    instance->physical_device.dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
155
156    *out_instance = instance;
157    return VK_SUCCESS;
158}
159
160int CloseDevice(struct hw_device_t* /*device*/) {
161    // nothing to do - opening a device doesn't allocate any resources
162    return 0;
163}
164
165hwvulkan_device_t nulldrv_device = {
166    .common =
167        {
168            .tag = HARDWARE_DEVICE_TAG,
169            .version = HWVULKAN_DEVICE_API_VERSION_0_1,
170            .module = &HAL_MODULE_INFO_SYM.common,
171            .close = CloseDevice,
172        },
173    .GetGlobalExtensionProperties = GetGlobalExtensionProperties,
174    .CreateInstance = CreateInstance,
175    .GetInstanceProcAddr = GetInstanceProcAddr};
176
177int OpenDevice(const hw_module_t* /*module*/,
178               const char* id,
179               hw_device_t** device) {
180    if (strcmp(id, HWVULKAN_DEVICE_0) == 0) {
181        *device = &nulldrv_device.common;
182        return 0;
183    }
184    return -ENOENT;
185}
186
187VkInstance_T* GetInstanceFromPhysicalDevice(
188    VkPhysicalDevice_T* physical_device) {
189    return reinterpret_cast<VkInstance_T*>(
190        reinterpret_cast<uintptr_t>(physical_device) -
191        offsetof(VkInstance_T, physical_device));
192}
193
194uint64_t AllocHandle(VkDevice device, HandleType::Enum type) {
195    const uint64_t kHandleMask = (UINT64_C(1) << 56) - 1;
196    ALOGE_IF(device->next_handle[type] == kHandleMask,
197             "non-dispatchable handles of type=%u are about to overflow", type);
198    return (UINT64_C(1) << 63) | ((uint64_t(type) & 0x7) << 56) |
199           (device->next_handle[type]++ & kHandleMask);
200}
201
202}  // namespace
203
204namespace null_driver {
205
206template <typename HandleT>
207struct HandleTraits {};
208
209template <typename HandleT>
210typename HandleTraits<HandleT>::PointerType GetObjectFromHandle(
211    const HandleT& h) {
212    return reinterpret_cast<typename HandleTraits<HandleT>::PointerType>(
213        uintptr_t(h.handle));
214}
215
216template <typename T>
217typename T::HandleType GetHandleToObject(const T* obj) {
218    return typename T::HandleType(reinterpret_cast<uintptr_t>(obj));
219}
220
221// -----------------------------------------------------------------------------
222// Global
223
224VkResult GetGlobalExtensionProperties(const char*,
225                                      uint32_t* count,
226                                      VkExtensionProperties*) {
227    *count = 0;
228    return VK_SUCCESS;
229}
230
231PFN_vkVoidFunction GetInstanceProcAddr(VkInstance, const char* name) {
232    PFN_vkVoidFunction proc = LookupInstanceProcAddr(name);
233    if (!proc && strcmp(name, "vkGetDeviceProcAddr") == 0)
234        proc = reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr);
235    return proc;
236}
237
238PFN_vkVoidFunction GetDeviceProcAddr(VkDevice, const char* name) {
239    PFN_vkVoidFunction proc = LookupDeviceProcAddr(name);
240    if (proc)
241        return proc;
242    if (strcmp(name, "vkImportNativeFenceANDROID") == 0)
243        return reinterpret_cast<PFN_vkVoidFunction>(ImportNativeFenceANDROID);
244    if (strcmp(name, "vkQueueSignalNativeFenceANDROID") == 0)
245        return reinterpret_cast<PFN_vkVoidFunction>(
246            QueueSignalNativeFenceANDROID);
247    return nullptr;
248}
249
250// -----------------------------------------------------------------------------
251// Instance
252
253VkResult DestroyInstance(VkInstance instance) {
254    instance->alloc->pfnFree(instance->alloc->pUserData, instance);
255    return VK_SUCCESS;
256}
257
258// -----------------------------------------------------------------------------
259// PhysicalDevice
260
261VkResult EnumeratePhysicalDevices(VkInstance instance,
262                                  uint32_t* physical_device_count,
263                                  VkPhysicalDevice* physical_devices) {
264    if (physical_devices && *physical_device_count >= 1)
265        physical_devices[0] = &instance->physical_device;
266    *physical_device_count = 1;
267    return VK_SUCCESS;
268}
269
270VkResult GetPhysicalDeviceProperties(VkPhysicalDevice,
271                                     VkPhysicalDeviceProperties* properties) {
272    properties->apiVersion = VK_API_VERSION;
273    properties->driverVersion = VK_MAKE_VERSION(0, 0, 1);
274    properties->vendorId = 0xC0DE;
275    properties->deviceId = 0xCAFE;
276    properties->deviceType = VK_PHYSICAL_DEVICE_TYPE_OTHER;
277    strcpy(properties->deviceName, "Android Vulkan Null Driver");
278    memset(properties->pipelineCacheUUID, 0,
279           sizeof(properties->pipelineCacheUUID));
280    return VK_SUCCESS;
281}
282
283VkResult GetPhysicalDeviceMemoryProperties(
284    VkPhysicalDevice,
285    VkPhysicalDeviceMemoryProperties* properties) {
286    properties->memoryTypeCount = 1;
287    properties->memoryTypes[0].propertyFlags =
288        VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
289    properties->memoryTypes[0].heapIndex = 0;
290    properties->memoryHeapCount = 1;
291    properties->memoryHeaps[0].size = kMaxDeviceMemory;
292    properties->memoryHeaps[0].flags = VK_MEMORY_HEAP_HOST_LOCAL;
293    return VK_SUCCESS;
294}
295
296// -----------------------------------------------------------------------------
297// Device
298
299VkResult CreateDevice(VkPhysicalDevice physical_device,
300                      const VkDeviceCreateInfo*,
301                      VkDevice* out_device) {
302    VkInstance_T* instance = GetInstanceFromPhysicalDevice(physical_device);
303    VkDevice_T* device = static_cast<VkDevice_T*>(instance->alloc->pfnAlloc(
304        instance->alloc->pUserData, sizeof(VkDevice_T), alignof(VkDevice_T),
305        VK_SYSTEM_ALLOC_TYPE_API_OBJECT));
306    if (!device)
307        return VK_ERROR_OUT_OF_HOST_MEMORY;
308
309    device->dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
310    device->instance = instance;
311    device->queue.dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
312    std::fill(device->next_handle.begin(), device->next_handle.end(),
313              UINT64_C(0));
314
315    *out_device = device;
316    return VK_SUCCESS;
317}
318
319VkResult DestroyDevice(VkDevice device) {
320    if (!device)
321        return VK_SUCCESS;
322    const VkAllocCallbacks* alloc = device->instance->alloc;
323    alloc->pfnFree(alloc->pUserData, device);
324    return VK_SUCCESS;
325}
326
327VkResult GetDeviceQueue(VkDevice device, uint32_t, uint32_t, VkQueue* queue) {
328    *queue = &device->queue;
329    return VK_SUCCESS;
330}
331
332// -----------------------------------------------------------------------------
333// CmdBuffer
334
335VkResult CreateCommandBuffer(VkDevice device,
336                             const VkCmdBufferCreateInfo*,
337                             VkCmdBuffer* out_cmdbuf) {
338    const VkAllocCallbacks* alloc = device->instance->alloc;
339    VkCmdBuffer_T* cmdbuf = static_cast<VkCmdBuffer_T*>(alloc->pfnAlloc(
340        alloc->pUserData, sizeof(VkCmdBuffer_T), alignof(VkCmdBuffer_T),
341        VK_SYSTEM_ALLOC_TYPE_API_OBJECT));
342    if (!cmdbuf)
343        return VK_ERROR_OUT_OF_HOST_MEMORY;
344    cmdbuf->dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
345    *out_cmdbuf = cmdbuf;
346    return VK_SUCCESS;
347}
348
349VkResult DestroyCommandBuffer(VkDevice device, VkCmdBuffer cmdbuf) {
350    const VkAllocCallbacks* alloc = device->instance->alloc;
351    alloc->pfnFree(alloc->pUserData, cmdbuf);
352    return VK_SUCCESS;
353}
354
355// -----------------------------------------------------------------------------
356// DeviceMemory
357
358struct DeviceMemory {
359    typedef VkDeviceMemory HandleType;
360    VkDeviceSize size;
361    alignas(16) uint8_t data[0];
362};
363template <>
364struct HandleTraits<VkDeviceMemory> {
365    typedef DeviceMemory* PointerType;
366};
367
368VkResult AllocMemory(VkDevice device,
369                     const VkMemoryAllocInfo* alloc_info,
370                     VkDeviceMemory* mem_handle) {
371    if (SIZE_MAX - sizeof(DeviceMemory) <= alloc_info->allocationSize)
372        return VK_ERROR_OUT_OF_HOST_MEMORY;
373
374    const VkAllocCallbacks* alloc = device->instance->alloc;
375    size_t size = sizeof(DeviceMemory) + size_t(alloc_info->allocationSize);
376    DeviceMemory* mem = static_cast<DeviceMemory*>(
377        alloc->pfnAlloc(alloc->pUserData, size, alignof(DeviceMemory),
378                        VK_SYSTEM_ALLOC_TYPE_API_OBJECT));
379    if (!mem)
380        return VK_ERROR_OUT_OF_HOST_MEMORY;
381    mem->size = size;
382    *mem_handle = GetHandleToObject(mem);
383    return VK_SUCCESS;
384}
385
386VkResult FreeMemory(VkDevice device, VkDeviceMemory mem_handle) {
387    const VkAllocCallbacks* alloc = device->instance->alloc;
388    DeviceMemory* mem = GetObjectFromHandle(mem_handle);
389    alloc->pfnFree(alloc->pUserData, mem);
390    return VK_SUCCESS;
391}
392
393VkResult MapMemory(VkDevice,
394                   VkDeviceMemory mem_handle,
395                   VkDeviceSize offset,
396                   VkDeviceSize,
397                   VkMemoryMapFlags,
398                   void** out_ptr) {
399    DeviceMemory* mem = GetObjectFromHandle(mem_handle);
400    *out_ptr = &mem->data[0] + offset;
401    return VK_SUCCESS;
402}
403
404// -----------------------------------------------------------------------------
405// Buffer
406
407struct Buffer {
408    typedef VkBuffer HandleType;
409    VkDeviceSize size;
410};
411template <>
412struct HandleTraits<VkBuffer> {
413    typedef Buffer* PointerType;
414};
415
416VkResult CreateBuffer(VkDevice device,
417                      const VkBufferCreateInfo* create_info,
418                      VkBuffer* buffer_handle) {
419    ALOGW_IF(create_info->size > kMaxDeviceMemory,
420             "CreateBuffer: requested size 0x%" PRIx64
421             " exceeds max device memory size 0x%" PRIx64,
422             create_info->size, kMaxDeviceMemory);
423
424    const VkAllocCallbacks* alloc = device->instance->alloc;
425    Buffer* buffer = static_cast<Buffer*>(
426        alloc->pfnAlloc(alloc->pUserData, sizeof(Buffer), alignof(Buffer),
427                        VK_SYSTEM_ALLOC_TYPE_API_OBJECT));
428    if (!buffer)
429        return VK_ERROR_OUT_OF_HOST_MEMORY;
430    buffer->size = create_info->size;
431    *buffer_handle = GetHandleToObject(buffer);
432    return VK_SUCCESS;
433}
434
435VkResult GetBufferMemoryRequirements(VkDevice,
436                                     VkBuffer buffer_handle,
437                                     VkMemoryRequirements* requirements) {
438    Buffer* buffer = GetObjectFromHandle(buffer_handle);
439    requirements->size = buffer->size;
440    requirements->alignment = 16;  // allow fast Neon/SSE memcpy
441    requirements->memoryTypeBits = 0x1;
442    return VK_SUCCESS;
443}
444
445VkResult DestroyBuffer(VkDevice device, VkBuffer buffer_handle) {
446    const VkAllocCallbacks* alloc = device->instance->alloc;
447    Buffer* buffer = GetObjectFromHandle(buffer_handle);
448    alloc->pfnFree(alloc->pUserData, buffer);
449    return VK_SUCCESS;
450}
451
452// -----------------------------------------------------------------------------
453// Image
454
455struct Image {
456    typedef VkImage HandleType;
457    VkDeviceSize size;
458};
459template <>
460struct HandleTraits<VkImage> {
461    typedef Image* PointerType;
462};
463
464VkResult CreateImage(VkDevice device,
465                     const VkImageCreateInfo* create_info,
466                     VkImage* image_handle) {
467    if (create_info->imageType != VK_IMAGE_TYPE_2D ||
468        create_info->format != VK_FORMAT_R8G8B8A8_UNORM ||
469        create_info->mipLevels != 1) {
470        ALOGE("CreateImage: not yet implemented: type=%d format=%d mips=%u",
471              create_info->imageType, create_info->format,
472              create_info->mipLevels);
473        return VK_ERROR_UNAVAILABLE;
474    }
475
476    VkDeviceSize size =
477        VkDeviceSize(create_info->extent.width * create_info->extent.height) *
478        create_info->arraySize * create_info->samples * 4u;
479    ALOGW_IF(size > kMaxDeviceMemory,
480             "CreateImage: image size 0x%" PRIx64
481             " exceeds max device memory size 0x%" PRIx64,
482             size, kMaxDeviceMemory);
483
484    const VkAllocCallbacks* alloc = device->instance->alloc;
485    Image* image = static_cast<Image*>(
486        alloc->pfnAlloc(alloc->pUserData, sizeof(Image), alignof(Image),
487                        VK_SYSTEM_ALLOC_TYPE_API_OBJECT));
488    if (!image)
489        return VK_ERROR_OUT_OF_HOST_MEMORY;
490    image->size = size;
491    *image_handle = GetHandleToObject(image);
492    return VK_SUCCESS;
493}
494
495VkResult GetImageMemoryRequirements(VkDevice,
496                                    VkImage image_handle,
497                                    VkMemoryRequirements* requirements) {
498    Image* image = GetObjectFromHandle(image_handle);
499    requirements->size = image->size;
500    requirements->alignment = 16;  // allow fast Neon/SSE memcpy
501    requirements->memoryTypeBits = 0x1;
502    return VK_SUCCESS;
503}
504
505VkResult DestroyImage(VkDevice device, VkImage image_handle) {
506    const VkAllocCallbacks* alloc = device->instance->alloc;
507    Image* image = GetObjectFromHandle(image_handle);
508    alloc->pfnFree(alloc->pUserData, image);
509    return VK_SUCCESS;
510}
511
512// -----------------------------------------------------------------------------
513// No-op types
514
515VkResult CreateAttachmentView(VkDevice device,
516                              const VkAttachmentViewCreateInfo*,
517                              VkAttachmentView* view) {
518    *view = AllocHandle(device, HandleType::kAttachmentView);
519    return VK_SUCCESS;
520}
521
522VkResult CreateBufferView(VkDevice device,
523                          const VkBufferViewCreateInfo*,
524                          VkBufferView* view) {
525    *view = AllocHandle(device, HandleType::kBufferView);
526    return VK_SUCCESS;
527}
528
529VkResult CreateCommandPool(VkDevice device,
530                           const VkCmdPoolCreateInfo*,
531                           VkCmdPool* pool) {
532    *pool = AllocHandle(device, HandleType::kCmdPool);
533    return VK_SUCCESS;
534}
535
536VkResult CreateDescriptorPool(VkDevice device,
537                              VkDescriptorPoolUsage,
538                              uint32_t,
539                              const VkDescriptorPoolCreateInfo*,
540                              VkDescriptorPool* pool) {
541    *pool = AllocHandle(device, HandleType::kDescriptorPool);
542    return VK_SUCCESS;
543}
544
545VkResult AllocDescriptorSets(VkDevice device,
546                             VkDescriptorPool,
547                             VkDescriptorSetUsage,
548                             uint32_t count,
549                             const VkDescriptorSetLayout*,
550                             VkDescriptorSet* sets,
551                             uint32_t* out_count) {
552    for (uint32_t i = 0; i < count; i++)
553        sets[i] = AllocHandle(device, HandleType::kDescriptorSet);
554    *out_count = count;
555    return VK_SUCCESS;
556}
557
558VkResult CreateDescriptorSetLayout(VkDevice device,
559                                   const VkDescriptorSetLayoutCreateInfo*,
560                                   VkDescriptorSetLayout* layout) {
561    *layout = AllocHandle(device, HandleType::kDescriptorSetLayout);
562    return VK_SUCCESS;
563}
564
565VkResult CreateDynamicColorBlendState(VkDevice device,
566                                      const VkDynamicColorBlendStateCreateInfo*,
567                                      VkDynamicColorBlendState* state) {
568    *state = AllocHandle(device, HandleType::kDynamicColorBlendState);
569    return VK_SUCCESS;
570}
571
572VkResult CreateDynamicDepthStencilState(
573    VkDevice device,
574    const VkDynamicDepthStencilStateCreateInfo*,
575    VkDynamicDepthStencilState* state) {
576    *state = AllocHandle(device, HandleType::kDynamicDepthStencilState);
577    return VK_SUCCESS;
578}
579
580VkResult CreateDynamicRasterState(VkDevice device,
581                                  const VkDynamicRasterStateCreateInfo*,
582                                  VkDynamicRasterState* state) {
583    *state = AllocHandle(device, HandleType::kDynamicRasterState);
584    return VK_SUCCESS;
585}
586
587VkResult CreateDynamicViewportState(VkDevice device,
588                                    const VkDynamicViewportStateCreateInfo*,
589                                    VkDynamicViewportState* state) {
590    *state = AllocHandle(device, HandleType::kDynamicViewportState);
591    return VK_SUCCESS;
592}
593
594VkResult CreateEvent(VkDevice device,
595                     const VkEventCreateInfo*,
596                     VkEvent* event) {
597    *event = AllocHandle(device, HandleType::kEvent);
598    return VK_SUCCESS;
599}
600
601VkResult CreateFence(VkDevice device,
602                     const VkFenceCreateInfo*,
603                     VkFence* fence) {
604    *fence = AllocHandle(device, HandleType::kFence);
605    return VK_SUCCESS;
606}
607
608VkResult CreateFramebuffer(VkDevice device,
609                           const VkFramebufferCreateInfo*,
610                           VkFramebuffer* framebuffer) {
611    *framebuffer = AllocHandle(device, HandleType::kFramebuffer);
612    return VK_SUCCESS;
613}
614
615VkResult CreateImageView(VkDevice device,
616                         const VkImageViewCreateInfo*,
617                         VkImageView* view) {
618    *view = AllocHandle(device, HandleType::kImageView);
619    return VK_SUCCESS;
620}
621
622VkResult CreateGraphicsPipelines(VkDevice device,
623                                 VkPipelineCache,
624                                 uint32_t count,
625                                 const VkGraphicsPipelineCreateInfo*,
626                                 VkPipeline* pipelines) {
627    for (uint32_t i = 0; i < count; i++)
628        pipelines[i] = AllocHandle(device, HandleType::kPipeline);
629    return VK_SUCCESS;
630}
631
632VkResult CreateComputePipelines(VkDevice device,
633                                VkPipelineCache,
634                                uint32_t count,
635                                const VkComputePipelineCreateInfo*,
636                                VkPipeline* pipelines) {
637    for (uint32_t i = 0; i < count; i++)
638        pipelines[i] = AllocHandle(device, HandleType::kPipeline);
639    return VK_SUCCESS;
640}
641
642VkResult CreatePipelineCache(VkDevice device,
643                             const VkPipelineCacheCreateInfo*,
644                             VkPipelineCache* cache) {
645    *cache = AllocHandle(device, HandleType::kPipelineCache);
646    return VK_SUCCESS;
647}
648
649VkResult CreatePipelineLayout(VkDevice device,
650                              const VkPipelineLayoutCreateInfo*,
651                              VkPipelineLayout* layout) {
652    *layout = AllocHandle(device, HandleType::kPipelineLayout);
653    return VK_SUCCESS;
654}
655
656VkResult CreateQueryPool(VkDevice device,
657                         const VkQueryPoolCreateInfo*,
658                         VkQueryPool* pool) {
659    *pool = AllocHandle(device, HandleType::kQueryPool);
660    return VK_SUCCESS;
661}
662
663VkResult CreateRenderPass(VkDevice device,
664                          const VkRenderPassCreateInfo*,
665                          VkRenderPass* renderpass) {
666    *renderpass = AllocHandle(device, HandleType::kRenderPass);
667    return VK_SUCCESS;
668}
669
670VkResult CreateSampler(VkDevice device,
671                       const VkSamplerCreateInfo*,
672                       VkSampler* sampler) {
673    *sampler = AllocHandle(device, HandleType::kSampler);
674    return VK_SUCCESS;
675}
676
677VkResult CreateSemaphore(VkDevice device,
678                         const VkSemaphoreCreateInfo*,
679                         VkSemaphore* semaphore) {
680    *semaphore = AllocHandle(device, HandleType::kSemaphore);
681    return VK_SUCCESS;
682}
683
684VkResult CreateShader(VkDevice device,
685                      const VkShaderCreateInfo*,
686                      VkShader* shader) {
687    *shader = AllocHandle(device, HandleType::kShader);
688    return VK_SUCCESS;
689}
690
691VkResult CreateShaderModule(VkDevice device,
692                            const VkShaderModuleCreateInfo*,
693                            VkShaderModule* module) {
694    *module = AllocHandle(device, HandleType::kShaderModule);
695    return VK_SUCCESS;
696}
697
698VkResult ImportNativeFenceANDROID(VkDevice, VkSemaphore, int fence) {
699    close(fence);
700    return VK_SUCCESS;
701}
702
703VkResult QueueSignalNativeFenceANDROID(VkQueue, int* fence) {
704    *fence = -1;
705    return VK_SUCCESS;
706}
707
708// -----------------------------------------------------------------------------
709// No-op entrypoints
710
711// clang-format off
712#pragma clang diagnostic push
713#pragma clang diagnostic ignored "-Wunused-parameter"
714
715VkResult GetPhysicalDeviceQueueCount(VkPhysicalDevice physicalDevice, uint32_t* pCount) {
716    ALOGV("TODO: vk%s", __FUNCTION__);
717    return VK_SUCCESS;
718}
719
720VkResult GetPhysicalDeviceQueueProperties(VkPhysicalDevice physicalDevice, uint32_t count, VkPhysicalDeviceQueueProperties* pQueueProperties) {
721    ALOGV("TODO: vk%s", __FUNCTION__);
722    return VK_SUCCESS;
723}
724
725VkResult GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures) {
726    ALOGV("TODO: vk%s", __FUNCTION__);
727    return VK_SUCCESS;
728}
729
730VkResult GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties) {
731    ALOGV("TODO: vk%s", __FUNCTION__);
732    return VK_SUCCESS;
733}
734
735VkResult GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageFormatProperties* pImageFormatProperties) {
736    ALOGV("TODO: vk%s", __FUNCTION__);
737    return VK_SUCCESS;
738}
739
740VkResult GetPhysicalDeviceLimits(VkPhysicalDevice physicalDevice, VkPhysicalDeviceLimits* pLimits) {
741    ALOGV("TODO: vk%s", __FUNCTION__);
742    return VK_SUCCESS;
743}
744
745VkResult GetGlobalLayerProperties(uint32_t* pCount, VkLayerProperties* pProperties) {
746    ALOGV("TODO: vk%s", __FUNCTION__);
747    return VK_SUCCESS;
748}
749
750VkResult GetPhysicalDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pCount, VkLayerProperties* pProperties) {
751    ALOGV("TODO: vk%s", __FUNCTION__);
752    return VK_SUCCESS;
753}
754
755VkResult GetPhysicalDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pCount, VkExtensionProperties* pProperties) {
756    ALOGV("TODO: vk%s", __FUNCTION__);
757    return VK_SUCCESS;
758}
759
760VkResult QueueSubmit(VkQueue queue, uint32_t cmdBufferCount, const VkCmdBuffer* pCmdBuffers, VkFence fence) {
761    return VK_SUCCESS;
762}
763
764VkResult QueueWaitIdle(VkQueue queue) {
765    ALOGV("TODO: vk%s", __FUNCTION__);
766    return VK_SUCCESS;
767}
768
769VkResult DeviceWaitIdle(VkDevice device) {
770    ALOGV("TODO: vk%s", __FUNCTION__);
771    return VK_SUCCESS;
772}
773
774VkResult UnmapMemory(VkDevice device, VkDeviceMemory mem) {
775    return VK_SUCCESS;
776}
777
778VkResult FlushMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, const VkMappedMemoryRange* pMemRanges) {
779    ALOGV("TODO: vk%s", __FUNCTION__);
780    return VK_SUCCESS;
781}
782
783VkResult InvalidateMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, const VkMappedMemoryRange* pMemRanges) {
784    ALOGV("TODO: vk%s", __FUNCTION__);
785    return VK_SUCCESS;
786}
787
788VkResult GetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes) {
789    ALOGV("TODO: vk%s", __FUNCTION__);
790    return VK_SUCCESS;
791}
792
793VkResult BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset) {
794    return VK_SUCCESS;
795}
796
797VkResult BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset) {
798    return VK_SUCCESS;
799}
800
801VkResult GetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t* pNumRequirements, VkSparseImageMemoryRequirements* pSparseMemoryRequirements) {
802    ALOGV("TODO: vk%s", __FUNCTION__);
803    return VK_SUCCESS;
804}
805
806VkResult GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, uint32_t samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pNumProperties, VkSparseImageFormatProperties* pProperties) {
807    ALOGV("TODO: vk%s", __FUNCTION__);
808    return VK_SUCCESS;
809}
810
811VkResult QueueBindSparseBufferMemory(VkQueue queue, VkBuffer buffer, uint32_t numBindings, const VkSparseMemoryBindInfo* pBindInfo) {
812    ALOGV("TODO: vk%s", __FUNCTION__);
813    return VK_SUCCESS;
814}
815
816VkResult QueueBindSparseImageOpaqueMemory(VkQueue queue, VkImage image, uint32_t numBindings, const VkSparseMemoryBindInfo* pBindInfo) {
817    ALOGV("TODO: vk%s", __FUNCTION__);
818    return VK_SUCCESS;
819}
820
821VkResult QueueBindSparseImageMemory(VkQueue queue, VkImage image, uint32_t numBindings, const VkSparseImageMemoryBindInfo* pBindInfo) {
822    ALOGV("TODO: vk%s", __FUNCTION__);
823    return VK_SUCCESS;
824}
825
826VkResult DestroyFence(VkDevice device, VkFence fence) {
827    return VK_SUCCESS;
828}
829
830VkResult ResetFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences) {
831    return VK_SUCCESS;
832}
833
834VkResult GetFenceStatus(VkDevice device, VkFence fence) {
835    ALOGV("TODO: vk%s", __FUNCTION__);
836    return VK_SUCCESS;
837}
838
839VkResult WaitForFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout) {
840    return VK_SUCCESS;
841}
842
843VkResult DestroySemaphore(VkDevice device, VkSemaphore semaphore) {
844    return VK_SUCCESS;
845}
846
847VkResult QueueSignalSemaphore(VkQueue queue, VkSemaphore semaphore) {
848    ALOGV("TODO: vk%s", __FUNCTION__);
849    return VK_SUCCESS;
850}
851
852VkResult QueueWaitSemaphore(VkQueue queue, VkSemaphore semaphore) {
853    return VK_SUCCESS;
854}
855
856VkResult DestroyEvent(VkDevice device, VkEvent event) {
857    return VK_SUCCESS;
858}
859
860VkResult GetEventStatus(VkDevice device, VkEvent event) {
861    ALOGV("TODO: vk%s", __FUNCTION__);
862    return VK_SUCCESS;
863}
864
865VkResult SetEvent(VkDevice device, VkEvent event) {
866    ALOGV("TODO: vk%s", __FUNCTION__);
867    return VK_SUCCESS;
868}
869
870VkResult ResetEvent(VkDevice device, VkEvent event) {
871    ALOGV("TODO: vk%s", __FUNCTION__);
872    return VK_SUCCESS;
873}
874
875VkResult DestroyQueryPool(VkDevice device, VkQueryPool queryPool) {
876    return VK_SUCCESS;
877}
878
879VkResult GetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount, size_t* pDataSize, void* pData, VkQueryResultFlags flags) {
880    ALOGV("TODO: vk%s", __FUNCTION__);
881    return VK_SUCCESS;
882}
883
884VkResult DestroyBufferView(VkDevice device, VkBufferView bufferView) {
885    return VK_SUCCESS;
886}
887
888VkResult GetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) {
889    ALOGV("TODO: vk%s", __FUNCTION__);
890    return VK_SUCCESS;
891}
892
893VkResult DestroyImageView(VkDevice device, VkImageView imageView) {
894    return VK_SUCCESS;
895}
896
897VkResult DestroyAttachmentView(VkDevice device, VkAttachmentView attachmentView) {
898    return VK_SUCCESS;
899}
900
901VkResult DestroyShaderModule(VkDevice device, VkShaderModule shaderModule) {
902    return VK_SUCCESS;
903}
904
905VkResult DestroyShader(VkDevice device, VkShader shader) {
906    return VK_SUCCESS;
907}
908
909VkResult DestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache) {
910    return VK_SUCCESS;
911}
912
913size_t GetPipelineCacheSize(VkDevice device, VkPipelineCache pipelineCache) {
914    ALOGV("TODO: vk%s", __FUNCTION__);
915    return VK_SUCCESS;
916}
917
918VkResult GetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, void* pData) {
919    ALOGV("TODO: vk%s", __FUNCTION__);
920    return VK_SUCCESS;
921}
922
923VkResult MergePipelineCaches(VkDevice device, VkPipelineCache destCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches) {
924    ALOGV("TODO: vk%s", __FUNCTION__);
925    return VK_SUCCESS;
926}
927
928VkResult DestroyPipeline(VkDevice device, VkPipeline pipeline) {
929    return VK_SUCCESS;
930}
931
932VkResult DestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout) {
933    return VK_SUCCESS;
934}
935
936VkResult DestroySampler(VkDevice device, VkSampler sampler) {
937    return VK_SUCCESS;
938}
939
940VkResult DestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout) {
941    return VK_SUCCESS;
942}
943
944VkResult DestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool) {
945    return VK_SUCCESS;
946}
947
948VkResult ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool) {
949    ALOGV("TODO: vk%s", __FUNCTION__);
950    return VK_SUCCESS;
951}
952
953VkResult UpdateDescriptorSets(VkDevice device, uint32_t writeCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t copyCount, const VkCopyDescriptorSet* pDescriptorCopies) {
954    ALOGV("TODO: vk%s", __FUNCTION__);
955    return VK_SUCCESS;
956}
957
958VkResult FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, const VkDescriptorSet* pDescriptorSets) {
959    ALOGV("TODO: vk%s", __FUNCTION__);
960    return VK_SUCCESS;
961}
962
963VkResult DestroyDynamicViewportState(VkDevice device, VkDynamicViewportState dynamicViewportState) {
964    return VK_SUCCESS;
965}
966
967VkResult DestroyDynamicRasterState(VkDevice device, VkDynamicRasterState dynamicRasterState) {
968    return VK_SUCCESS;
969}
970
971VkResult DestroyDynamicColorBlendState(VkDevice device, VkDynamicColorBlendState dynamicColorBlendState) {
972    return VK_SUCCESS;
973}
974
975VkResult DestroyDynamicDepthStencilState(VkDevice device, VkDynamicDepthStencilState dynamicDepthStencilState) {
976    return VK_SUCCESS;
977}
978
979VkResult DestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer) {
980    return VK_SUCCESS;
981}
982
983VkResult DestroyRenderPass(VkDevice device, VkRenderPass renderPass) {
984    return VK_SUCCESS;
985}
986
987VkResult GetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity) {
988    ALOGV("TODO: vk%s", __FUNCTION__);
989    return VK_SUCCESS;
990}
991
992VkResult DestroyCommandPool(VkDevice device, VkCmdPool cmdPool) {
993    return VK_SUCCESS;
994}
995
996VkResult ResetCommandPool(VkDevice device, VkCmdPool cmdPool, VkCmdPoolResetFlags flags) {
997    ALOGV("TODO: vk%s", __FUNCTION__);
998    return VK_SUCCESS;
999}
1000
1001VkResult BeginCommandBuffer(VkCmdBuffer cmdBuffer, const VkCmdBufferBeginInfo* pBeginInfo) {
1002    return VK_SUCCESS;
1003}
1004
1005VkResult EndCommandBuffer(VkCmdBuffer cmdBuffer) {
1006    return VK_SUCCESS;
1007}
1008
1009VkResult ResetCommandBuffer(VkCmdBuffer cmdBuffer, VkCmdBufferResetFlags flags) {
1010    ALOGV("TODO: vk%s", __FUNCTION__);
1011    return VK_SUCCESS;
1012}
1013
1014void CmdBindPipeline(VkCmdBuffer cmdBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) {
1015}
1016
1017void CmdBindDynamicViewportState(VkCmdBuffer cmdBuffer, VkDynamicViewportState dynamicViewportState) {
1018}
1019
1020void CmdBindDynamicRasterState(VkCmdBuffer cmdBuffer, VkDynamicRasterState dynamicRasterState) {
1021}
1022
1023void CmdBindDynamicColorBlendState(VkCmdBuffer cmdBuffer, VkDynamicColorBlendState dynamicColorBlendState) {
1024}
1025
1026void CmdBindDynamicDepthStencilState(VkCmdBuffer cmdBuffer, VkDynamicDepthStencilState dynamicDepthStencilState) {
1027}
1028
1029void CmdBindDescriptorSets(VkCmdBuffer cmdBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets) {
1030}
1031
1032void CmdBindIndexBuffer(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) {
1033}
1034
1035void CmdBindVertexBuffers(VkCmdBuffer cmdBuffer, uint32_t startBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets) {
1036}
1037
1038void CmdDraw(VkCmdBuffer cmdBuffer, uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount) {
1039}
1040
1041void CmdDrawIndexed(VkCmdBuffer cmdBuffer, uint32_t firstIndex, uint32_t indexCount, int32_t vertexOffset, uint32_t firstInstance, uint32_t instanceCount) {
1042}
1043
1044void CmdDrawIndirect(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
1045}
1046
1047void CmdDrawIndexedIndirect(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
1048}
1049
1050void CmdDispatch(VkCmdBuffer cmdBuffer, uint32_t x, uint32_t y, uint32_t z) {
1051}
1052
1053void CmdDispatchIndirect(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset) {
1054}
1055
1056void CmdCopyBuffer(VkCmdBuffer cmdBuffer, VkBuffer srcBuffer, VkBuffer destBuffer, uint32_t regionCount, const VkBufferCopy* pRegions) {
1057}
1058
1059void CmdCopyImage(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageCopy* pRegions) {
1060}
1061
1062void CmdBlitImage(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkTexFilter filter) {
1063}
1064
1065void CmdCopyBufferToImage(VkCmdBuffer cmdBuffer, VkBuffer srcBuffer, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions) {
1066}
1067
1068void CmdCopyImageToBuffer(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer destBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions) {
1069}
1070
1071void CmdUpdateBuffer(VkCmdBuffer cmdBuffer, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize dataSize, const uint32_t* pData) {
1072}
1073
1074void CmdFillBuffer(VkCmdBuffer cmdBuffer, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize fillSize, uint32_t data) {
1075}
1076
1077void CmdClearColorImage(VkCmdBuffer cmdBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges) {
1078}
1079
1080void CmdClearDepthStencilImage(VkCmdBuffer cmdBuffer, VkImage image, VkImageLayout imageLayout, float depth, uint32_t stencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges) {
1081}
1082
1083void CmdClearColorAttachment(VkCmdBuffer cmdBuffer, uint32_t colorAttachment, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rectCount, const VkRect3D* pRects) {
1084}
1085
1086void CmdClearDepthStencilAttachment(VkCmdBuffer cmdBuffer, VkImageAspectFlags imageAspectMask, VkImageLayout imageLayout, float depth, uint32_t stencil, uint32_t rectCount, const VkRect3D* pRects) {
1087}
1088
1089void CmdResolveImage(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageResolve* pRegions) {
1090}
1091
1092void CmdSetEvent(VkCmdBuffer cmdBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
1093}
1094
1095void CmdResetEvent(VkCmdBuffer cmdBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
1096}
1097
1098void CmdWaitEvents(VkCmdBuffer cmdBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags destStageMask, uint32_t memBarrierCount, const void* const* ppMemBarriers) {
1099}
1100
1101void CmdPipelineBarrier(VkCmdBuffer cmdBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags destStageMask, VkBool32 byRegion, uint32_t memBarrierCount, const void* const* ppMemBarriers) {
1102}
1103
1104void CmdBeginQuery(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t slot, VkQueryControlFlags flags) {
1105}
1106
1107void CmdEndQuery(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t slot) {
1108}
1109
1110void CmdResetQueryPool(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount) {
1111}
1112
1113void CmdWriteTimestamp(VkCmdBuffer cmdBuffer, VkTimestampType timestampType, VkBuffer destBuffer, VkDeviceSize destOffset) {
1114}
1115
1116void CmdCopyQueryPoolResults(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize destStride, VkQueryResultFlags flags) {
1117}
1118
1119void CmdPushConstants(VkCmdBuffer cmdBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t start, uint32_t length, const void* values) {
1120}
1121
1122void CmdBeginRenderPass(VkCmdBuffer cmdBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkRenderPassContents contents) {
1123}
1124
1125void CmdNextSubpass(VkCmdBuffer cmdBuffer, VkRenderPassContents contents) {
1126}
1127
1128void CmdEndRenderPass(VkCmdBuffer cmdBuffer) {
1129}
1130
1131void CmdExecuteCommands(VkCmdBuffer cmdBuffer, uint32_t cmdBuffersCount, const VkCmdBuffer* pCmdBuffers) {
1132}
1133
1134#pragma clang diagnostic pop
1135// clang-format on
1136
1137}  // namespace null_driver
1138