1 /*-------------------------------------------------------------------------
5 * Copyright (c) 2015 Google Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief Null (dummy) Vulkan implementation.
22 *//*--------------------------------------------------------------------*/
24 #include "vkNullDriver.hpp"
25 #include "vkPlatform.hpp"
26 #include "vkImageUtil.hpp"
27 #include "tcuFunctionLibrary.hpp"
44 void* allocateSystemMem (const VkAllocationCallbacks* pAllocator, VkSystemAllocationScope scope)
46 void* ptr = pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(T), sizeof(void*), scope);
48 throw std::bad_alloc();
52 void freeSystemMem (const VkAllocationCallbacks* pAllocator, void* mem)
54 pAllocator->pfnFree(pAllocator->pUserData, mem);
57 template<typename Object, typename Handle, typename Parent, typename CreateInfo>
58 Handle allocateHandle (Parent parent, const CreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator)
60 Object* obj = DE_NULL;
64 void* mem = allocateSystemMem<Object>(pAllocator, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
67 obj = new (mem) Object(parent, pCreateInfo);
68 DE_ASSERT(obj == mem);
72 pAllocator->pfnFree(pAllocator->pUserData, mem);
77 obj = new Object(parent, pCreateInfo);
79 return reinterpret_cast<Handle>(obj);
82 template<typename Object, typename Handle, typename CreateInfo>
83 Handle allocateHandle (const CreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator)
85 Object* obj = DE_NULL;
89 void* mem = allocateSystemMem<Object>(pAllocator, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
92 obj = new (mem) Object(pCreateInfo);
93 DE_ASSERT(obj == mem);
97 pAllocator->pfnFree(pAllocator->pUserData, mem);
102 obj = new Object(pCreateInfo);
104 return reinterpret_cast<Handle>(obj);
107 template<typename Object, typename Handle>
108 void freeHandle (Handle handle, const VkAllocationCallbacks* pAllocator)
110 Object* obj = reinterpret_cast<Object*>(handle);
115 freeSystemMem(pAllocator, reinterpret_cast<void*>(obj));
121 template<typename Object, typename Handle, typename Parent, typename CreateInfo>
122 Handle allocateNonDispHandle (Parent parent, const CreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator)
124 Object* const obj = allocateHandle<Object, Object*>(parent, pCreateInfo, pAllocator);
125 return Handle((deUint64)(deUintptr)obj);
128 template<typename Object, typename Handle>
129 void freeNonDispHandle (Handle handle, const VkAllocationCallbacks* pAllocator)
131 freeHandle<Object>(reinterpret_cast<Object*>((deUintptr)handle.getInternal()), pAllocator);
134 // Object definitions
136 #define VK_NULL_RETURN(STMT) \
141 } catch (const std::bad_alloc&) { \
142 return VK_ERROR_OUT_OF_HOST_MEMORY; \
143 } catch (VkResult res) { \
146 } while (deGetFalse())
148 // \todo [2015-07-14 pyry] Check FUNC type by checkedCastToPtr<T>() or similar
149 #define VK_NULL_FUNC_ENTRY(NAME, FUNC) { #NAME, (deFunctionPtr)FUNC }
151 #define VK_NULL_DEFINE_DEVICE_OBJ(NAME) \
154 NAME (VkDevice, const Vk##NAME##CreateInfo*) {} \
157 VK_NULL_DEFINE_DEVICE_OBJ(Fence);
158 VK_NULL_DEFINE_DEVICE_OBJ(Semaphore);
159 VK_NULL_DEFINE_DEVICE_OBJ(Event);
160 VK_NULL_DEFINE_DEVICE_OBJ(QueryPool);
161 VK_NULL_DEFINE_DEVICE_OBJ(BufferView);
162 VK_NULL_DEFINE_DEVICE_OBJ(ImageView);
163 VK_NULL_DEFINE_DEVICE_OBJ(ShaderModule);
164 VK_NULL_DEFINE_DEVICE_OBJ(PipelineCache);
165 VK_NULL_DEFINE_DEVICE_OBJ(PipelineLayout);
166 VK_NULL_DEFINE_DEVICE_OBJ(RenderPass);
167 VK_NULL_DEFINE_DEVICE_OBJ(DescriptorSetLayout);
168 VK_NULL_DEFINE_DEVICE_OBJ(Sampler);
169 VK_NULL_DEFINE_DEVICE_OBJ(Framebuffer);
170 VK_NULL_DEFINE_DEVICE_OBJ(CommandPool);
175 Instance (const VkInstanceCreateInfo* instanceInfo);
178 PFN_vkVoidFunction getProcAddr (const char* name) const { return (PFN_vkVoidFunction)m_functions.getFunction(name); }
181 const tcu::StaticFunctionLibrary m_functions;
184 class DebugReportCallbackEXT
187 DebugReportCallbackEXT (VkInstance, const VkDebugReportCallbackCreateInfoEXT*) {}
188 ~DebugReportCallbackEXT (void) {}
194 Device (VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* deviceInfo);
197 PFN_vkVoidFunction getProcAddr (const char* name) const { return (PFN_vkVoidFunction)m_functions.getFunction(name); }
200 const tcu::StaticFunctionLibrary m_functions;
206 Pipeline (VkDevice, const VkGraphicsPipelineCreateInfo*) {}
207 Pipeline (VkDevice, const VkComputePipelineCreateInfo*) {}
210 void* allocateHeap (const VkMemoryAllocateInfo* pAllocInfo)
212 // \todo [2015-12-03 pyry] Alignment requirements?
213 // \todo [2015-12-03 pyry] Empty allocations okay?
214 if (pAllocInfo->allocationSize > 0)
216 void* const heapPtr = deMalloc((size_t)pAllocInfo->allocationSize);
218 throw std::bad_alloc();
225 void freeHeap (void* ptr)
233 DeviceMemory (VkDevice, const VkMemoryAllocateInfo* pAllocInfo)
234 : m_memory(allocateHeap(pAllocInfo))
242 void* getPtr (void) const { return m_memory; }
245 void* const m_memory;
251 Buffer (VkDevice, const VkBufferCreateInfo* pCreateInfo)
252 : m_size(pCreateInfo->size)
255 VkDeviceSize getSize (void) const { return m_size; }
258 const VkDeviceSize m_size;
264 Image (VkDevice, const VkImageCreateInfo* pCreateInfo)
265 : m_imageType (pCreateInfo->imageType)
266 , m_format (pCreateInfo->format)
267 , m_extent (pCreateInfo->extent)
268 , m_samples (pCreateInfo->samples)
271 VkImageType getImageType (void) const { return m_imageType; }
272 VkFormat getFormat (void) const { return m_format; }
273 VkExtent3D getExtent (void) const { return m_extent; }
274 VkSampleCountFlagBits getSamples (void) const { return m_samples; }
277 const VkImageType m_imageType;
278 const VkFormat m_format;
279 const VkExtent3D m_extent;
280 const VkSampleCountFlagBits m_samples;
286 CommandBuffer(VkDevice, VkCommandPool, VkCommandBufferLevel)
293 DescriptorSet (VkDevice, VkDescriptorPool, VkDescriptorSetLayout) {}
299 DescriptorPool (VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo)
301 , m_flags (pCreateInfo->flags)
303 ~DescriptorPool (void)
308 VkDescriptorSet allocate (VkDescriptorSetLayout setLayout);
309 void free (VkDescriptorSet set);
314 const VkDevice m_device;
315 const VkDescriptorPoolCreateFlags m_flags;
317 vector<DescriptorSet*> m_managedSets;
320 VkDescriptorSet DescriptorPool::allocate (VkDescriptorSetLayout setLayout)
322 DescriptorSet* const impl = new DescriptorSet(m_device, VkDescriptorPool(reinterpret_cast<deUintptr>(this)), setLayout);
326 m_managedSets.push_back(impl);
334 return VkDescriptorSet(reinterpret_cast<deUintptr>(impl));
337 void DescriptorPool::free (VkDescriptorSet set)
339 DescriptorSet* const impl = reinterpret_cast<DescriptorSet*>((deUintptr)set.getInternal());
341 DE_ASSERT(m_flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT);
345 for (size_t ndx = 0; ndx < m_managedSets.size(); ++ndx)
347 if (m_managedSets[ndx] == impl)
349 std::swap(m_managedSets[ndx], m_managedSets.back());
350 m_managedSets.pop_back();
355 DE_FATAL("VkDescriptorSet not owned by VkDescriptorPool");
358 void DescriptorPool::reset (void)
360 for (size_t ndx = 0; ndx < m_managedSets.size(); ++ndx)
361 delete m_managedSets[ndx];
362 m_managedSets.clear();
365 // API implementation
370 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL getInstanceProcAddr (VkInstance instance, const char* pName)
372 return reinterpret_cast<Instance*>(instance)->getProcAddr(pName);
375 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL getDeviceProcAddr (VkDevice device, const char* pName)
377 return reinterpret_cast<Device*>(device)->getProcAddr(pName);
380 VKAPI_ATTR VkResult VKAPI_CALL createGraphicsPipelines (VkDevice device, VkPipelineCache, deUint32 count, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines)
385 for (allocNdx = 0; allocNdx < count; allocNdx++)
386 pPipelines[allocNdx] = allocateNonDispHandle<Pipeline, VkPipeline>(device, pCreateInfos+allocNdx, pAllocator);
390 catch (const std::bad_alloc&)
392 for (deUint32 freeNdx = 0; freeNdx < allocNdx; freeNdx++)
393 freeNonDispHandle<Pipeline, VkPipeline>(pPipelines[freeNdx], pAllocator);
395 return VK_ERROR_OUT_OF_HOST_MEMORY;
399 for (deUint32 freeNdx = 0; freeNdx < allocNdx; freeNdx++)
400 freeNonDispHandle<Pipeline, VkPipeline>(pPipelines[freeNdx], pAllocator);
406 VKAPI_ATTR VkResult VKAPI_CALL createComputePipelines (VkDevice device, VkPipelineCache, deUint32 count, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines)
411 for (allocNdx = 0; allocNdx < count; allocNdx++)
412 pPipelines[allocNdx] = allocateNonDispHandle<Pipeline, VkPipeline>(device, pCreateInfos+allocNdx, pAllocator);
416 catch (const std::bad_alloc&)
418 for (deUint32 freeNdx = 0; freeNdx < allocNdx; freeNdx++)
419 freeNonDispHandle<Pipeline, VkPipeline>(pPipelines[freeNdx], pAllocator);
421 return VK_ERROR_OUT_OF_HOST_MEMORY;
425 for (deUint32 freeNdx = 0; freeNdx < allocNdx; freeNdx++)
426 freeNonDispHandle<Pipeline, VkPipeline>(pPipelines[freeNdx], pAllocator);
432 VKAPI_ATTR VkResult VKAPI_CALL enumeratePhysicalDevices (VkInstance, deUint32* pPhysicalDeviceCount, VkPhysicalDevice* pDevices)
434 if (pDevices && *pPhysicalDeviceCount >= 1u)
435 *pDevices = reinterpret_cast<VkPhysicalDevice>((void*)(deUintptr)1u);
437 *pPhysicalDeviceCount = 1;
442 VKAPI_ATTR void VKAPI_CALL getPhysicalDeviceProperties (VkPhysicalDevice, VkPhysicalDeviceProperties* props)
444 deMemset(props, 0, sizeof(VkPhysicalDeviceProperties));
446 props->apiVersion = VK_API_VERSION;
447 props->driverVersion = 1u;
448 props->deviceType = VK_PHYSICAL_DEVICE_TYPE_OTHER;
450 deMemcpy(props->deviceName, "null", 5);
452 // \todo [2015-09-25 pyry] Fill in reasonable limits
453 props->limits.maxTexelBufferElements = 8096;
456 VKAPI_ATTR void VKAPI_CALL getPhysicalDeviceQueueFamilyProperties (VkPhysicalDevice, deUint32* count, VkQueueFamilyProperties* props)
458 if (props && *count >= 1u)
460 deMemset(props, 0, sizeof(VkQueueFamilyProperties));
462 props->queueCount = 1u;
463 props->queueFlags = VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT;
464 props->timestampValidBits = 64;
470 VKAPI_ATTR void VKAPI_CALL getPhysicalDeviceMemoryProperties (VkPhysicalDevice, VkPhysicalDeviceMemoryProperties* props)
472 deMemset(props, 0, sizeof(VkPhysicalDeviceMemoryProperties));
474 props->memoryTypeCount = 1u;
475 props->memoryTypes[0].heapIndex = 0u;
476 props->memoryTypes[0].propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
478 props->memoryHeapCount = 1u;
479 props->memoryHeaps[0].size = 1ull << 31;
480 props->memoryHeaps[0].flags = 0u;
483 VKAPI_ATTR void VKAPI_CALL getPhysicalDeviceFormatProperties (VkPhysicalDevice, VkFormat, VkFormatProperties* pFormatProperties)
485 const VkFormatFeatureFlags allFeatures = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
486 | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT
487 | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT
488 | VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT
489 | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT
490 | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT
491 | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT
492 | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
493 | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT
494 | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
495 | VK_FORMAT_FEATURE_BLIT_SRC_BIT
496 | VK_FORMAT_FEATURE_BLIT_DST_BIT;
498 pFormatProperties->linearTilingFeatures = allFeatures;
499 pFormatProperties->optimalTilingFeatures = allFeatures;
500 pFormatProperties->bufferFeatures = allFeatures;
503 VKAPI_ATTR void VKAPI_CALL getBufferMemoryRequirements (VkDevice, VkBuffer bufferHandle, VkMemoryRequirements* requirements)
505 const Buffer* buffer = reinterpret_cast<const Buffer*>(bufferHandle.getInternal());
507 requirements->memoryTypeBits = 1u;
508 requirements->size = buffer->getSize();
509 requirements->alignment = (VkDeviceSize)1u;
512 VkDeviceSize getPackedImageDataSize (VkFormat format, VkExtent3D extent, VkSampleCountFlagBits samples)
514 return (VkDeviceSize)getPixelSize(mapVkFormat(format))
515 * (VkDeviceSize)extent.width
516 * (VkDeviceSize)extent.height
517 * (VkDeviceSize)extent.depth
518 * (VkDeviceSize)samples;
521 VkDeviceSize getCompressedImageDataSize (VkFormat format, VkExtent3D extent)
525 const tcu::CompressedTexFormat tcuFormat = mapVkCompressedFormat(format);
526 const size_t blockSize = tcu::getBlockSize(tcuFormat);
527 const tcu::IVec3 blockPixelSize = tcu::getBlockPixelSize(tcuFormat);
528 const int numBlocksX = deDivRoundUp32((int)extent.width, blockPixelSize.x());
529 const int numBlocksY = deDivRoundUp32((int)extent.height, blockPixelSize.y());
530 const int numBlocksZ = deDivRoundUp32((int)extent.depth, blockPixelSize.z());
532 return blockSize*numBlocksX*numBlocksY*numBlocksZ;
536 return 0; // Unsupported compressed format
540 VKAPI_ATTR void VKAPI_CALL getImageMemoryRequirements (VkDevice, VkImage imageHandle, VkMemoryRequirements* requirements)
542 const Image* image = reinterpret_cast<const Image*>(imageHandle.getInternal());
544 requirements->memoryTypeBits = 1u;
545 requirements->alignment = 16u;
547 if (isCompressedFormat(image->getFormat()))
548 requirements->size = getCompressedImageDataSize(image->getFormat(), image->getExtent());
550 requirements->size = getPackedImageDataSize(image->getFormat(), image->getExtent(), image->getSamples());
553 VKAPI_ATTR VkResult VKAPI_CALL mapMemory (VkDevice, VkDeviceMemory memHandle, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData)
555 const DeviceMemory* memory = reinterpret_cast<DeviceMemory*>(memHandle.getInternal());
560 *ppData = (deUint8*)memory->getPtr() + offset;
565 VKAPI_ATTR VkResult VKAPI_CALL allocateDescriptorSets (VkDevice, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets)
567 DescriptorPool* const poolImpl = reinterpret_cast<DescriptorPool*>((deUintptr)pAllocateInfo->descriptorPool.getInternal());
569 for (deUint32 ndx = 0; ndx < pAllocateInfo->descriptorSetCount; ++ndx)
573 pDescriptorSets[ndx] = poolImpl->allocate(pAllocateInfo->pSetLayouts[ndx]);
575 catch (const std::bad_alloc&)
577 for (deUint32 freeNdx = 0; freeNdx < ndx; freeNdx++)
578 delete reinterpret_cast<DescriptorSet*>((deUintptr)pDescriptorSets[freeNdx].getInternal());
580 return VK_ERROR_OUT_OF_HOST_MEMORY;
584 for (deUint32 freeNdx = 0; freeNdx < ndx; freeNdx++)
585 delete reinterpret_cast<DescriptorSet*>((deUintptr)pDescriptorSets[freeNdx].getInternal());
594 VKAPI_ATTR void VKAPI_CALL freeDescriptorSets (VkDevice, VkDescriptorPool descriptorPool, deUint32 count, const VkDescriptorSet* pDescriptorSets)
596 DescriptorPool* const poolImpl = reinterpret_cast<DescriptorPool*>((deUintptr)descriptorPool.getInternal());
598 for (deUint32 ndx = 0; ndx < count; ++ndx)
599 poolImpl->free(pDescriptorSets[ndx]);
602 VKAPI_ATTR VkResult VKAPI_CALL resetDescriptorPool (VkDevice, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags)
604 DescriptorPool* const poolImpl = reinterpret_cast<DescriptorPool*>((deUintptr)descriptorPool.getInternal());
611 VKAPI_ATTR VkResult VKAPI_CALL allocateCommandBuffers (VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers)
613 if (pAllocateInfo && pCommandBuffers)
615 for (deUint32 ndx = 0; ndx < pAllocateInfo->commandBufferCount; ++ndx)
617 pCommandBuffers[ndx] = reinterpret_cast<VkCommandBuffer>(new CommandBuffer(device, pAllocateInfo->commandPool, pAllocateInfo->level));
624 VKAPI_ATTR void VKAPI_CALL freeCommandBuffers (VkDevice device, VkCommandPool commandPool, deUint32 commandBufferCount, const VkCommandBuffer* pCommandBuffers)
627 DE_UNREF(commandPool);
629 for (deUint32 ndx = 0; ndx < commandBufferCount; ++ndx)
630 delete reinterpret_cast<CommandBuffer*>(pCommandBuffers[ndx]);
633 #include "vkNullDriverImpl.inl"
637 Instance::Instance (const VkInstanceCreateInfo*)
638 : m_functions(s_instanceFunctions, DE_LENGTH_OF_ARRAY(s_instanceFunctions))
642 Device::Device (VkPhysicalDevice, const VkDeviceCreateInfo*)
643 : m_functions(s_deviceFunctions, DE_LENGTH_OF_ARRAY(s_deviceFunctions))
647 class NullDriverLibrary : public Library
650 NullDriverLibrary (void)
651 : m_library (s_platformFunctions, DE_LENGTH_OF_ARRAY(s_platformFunctions))
652 , m_driver (m_library)
655 const PlatformInterface& getPlatformInterface (void) const { return m_driver; }
658 const tcu::StaticFunctionLibrary m_library;
659 const PlatformDriver m_driver;
664 Library* createNullDriver (void)
666 return new NullDriverLibrary();