/*------------------------------------------------------------------------- * Vulkan CTS Framework * -------------------- * * Copyright (c) 2015 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Null (dummy) Vulkan implementation. *//*--------------------------------------------------------------------*/ #include "vkNullDriver.hpp" #include "vkPlatform.hpp" #include "vkImageUtil.hpp" #include "vkQueryUtil.hpp" #include "tcuFunctionLibrary.hpp" #include "deMemory.h" #if (DE_OS == DE_OS_ANDROID) && defined(__ANDROID_API_O__) && (DE_ANDROID_API >= __ANDROID_API_O__ /* __ANDROID_API_O__ */) # define USE_ANDROID_O_HARDWARE_BUFFER #endif #if defined(USE_ANDROID_O_HARDWARE_BUFFER) # include #endif #include #include namespace vk { namespace { using std::vector; // Memory management template void* allocateSystemMem (const VkAllocationCallbacks* pAllocator, VkSystemAllocationScope scope) { void* ptr = pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(T), sizeof(void*), scope); if (!ptr) throw std::bad_alloc(); return ptr; } void freeSystemMem (const VkAllocationCallbacks* pAllocator, void* mem) { pAllocator->pfnFree(pAllocator->pUserData, mem); } template Handle allocateHandle (Parent parent, const CreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator) { Object* obj = DE_NULL; if (pAllocator) { void* mem = allocateSystemMem(pAllocator, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); try { obj = new (mem) Object(parent, pCreateInfo); DE_ASSERT(obj == mem); } catch (...) { pAllocator->pfnFree(pAllocator->pUserData, mem); throw; } } else obj = new Object(parent, pCreateInfo); return reinterpret_cast(obj); } template Handle allocateHandle (const CreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator) { Object* obj = DE_NULL; if (pAllocator) { void* mem = allocateSystemMem(pAllocator, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); try { obj = new (mem) Object(pCreateInfo); DE_ASSERT(obj == mem); } catch (...) { pAllocator->pfnFree(pAllocator->pUserData, mem); throw; } } else obj = new Object(pCreateInfo); return reinterpret_cast(obj); } template void freeHandle (Handle handle, const VkAllocationCallbacks* pAllocator) { Object* obj = reinterpret_cast(handle); if (pAllocator) { obj->~Object(); freeSystemMem(pAllocator, reinterpret_cast(obj)); } else delete obj; } template Handle allocateNonDispHandle (Parent parent, const CreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator) { Object* const obj = allocateHandle(parent, pCreateInfo, pAllocator); return Handle((deUint64)(deUintptr)static_cast(obj)); } template Handle allocateNonDispHandle (Parent parent, const CreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator) { return allocateNonDispHandle(parent, pCreateInfo, pAllocator); } template void freeNonDispHandle (Handle handle, const VkAllocationCallbacks* pAllocator) { freeHandle(reinterpret_cast((deUintptr)handle.getInternal()), pAllocator); } // Object definitions #define VK_NULL_RETURN(STMT) \ do { \ try { \ STMT; \ return VK_SUCCESS; \ } catch (const std::bad_alloc&) { \ return VK_ERROR_OUT_OF_HOST_MEMORY; \ } catch (VkResult res) { \ return res; \ } \ } while (deGetFalse()) // \todo [2015-07-14 pyry] Check FUNC type by checkedCastToPtr() or similar #define VK_NULL_FUNC_ENTRY(NAME, FUNC) { #NAME, (deFunctionPtr)FUNC } // NOLINT(FUNC) #define VK_NULL_DEFINE_DEVICE_OBJ(NAME) \ struct NAME \ { \ NAME (VkDevice, const Vk##NAME##CreateInfo*) {} \ } VK_NULL_DEFINE_DEVICE_OBJ(Fence); VK_NULL_DEFINE_DEVICE_OBJ(Semaphore); VK_NULL_DEFINE_DEVICE_OBJ(Event); VK_NULL_DEFINE_DEVICE_OBJ(QueryPool); VK_NULL_DEFINE_DEVICE_OBJ(BufferView); VK_NULL_DEFINE_DEVICE_OBJ(ImageView); VK_NULL_DEFINE_DEVICE_OBJ(ShaderModule); VK_NULL_DEFINE_DEVICE_OBJ(PipelineCache); VK_NULL_DEFINE_DEVICE_OBJ(PipelineLayout); VK_NULL_DEFINE_DEVICE_OBJ(DescriptorSetLayout); VK_NULL_DEFINE_DEVICE_OBJ(Sampler); VK_NULL_DEFINE_DEVICE_OBJ(Framebuffer); class Instance { public: Instance (const VkInstanceCreateInfo* instanceInfo); ~Instance (void) {} PFN_vkVoidFunction getProcAddr (const char* name) const { return (PFN_vkVoidFunction)m_functions.getFunction(name); } private: const tcu::StaticFunctionLibrary m_functions; }; class SurfaceKHR { public: SurfaceKHR (VkInstance, const VkXlibSurfaceCreateInfoKHR*) {} SurfaceKHR (VkInstance, const VkXcbSurfaceCreateInfoKHR*) {} SurfaceKHR (VkInstance, const VkWaylandSurfaceCreateInfoKHR*) {} SurfaceKHR (VkInstance, const VkMirSurfaceCreateInfoKHR*) {} SurfaceKHR (VkInstance, const VkAndroidSurfaceCreateInfoKHR*) {} SurfaceKHR (VkInstance, const VkWin32SurfaceCreateInfoKHR*) {} SurfaceKHR (VkInstance, const VkDisplaySurfaceCreateInfoKHR*) {} SurfaceKHR (VkInstance, const VkViSurfaceCreateInfoNN*) {} SurfaceKHR (VkInstance, const VkIOSSurfaceCreateInfoMVK*) {} SurfaceKHR (VkInstance, const VkMacOSSurfaceCreateInfoMVK*) {} ~SurfaceKHR (void) {} }; class DisplayModeKHR { public: DisplayModeKHR (VkDisplayKHR, const VkDisplayModeCreateInfoKHR*) {} ~DisplayModeKHR (void) {} }; class DebugReportCallbackEXT { public: DebugReportCallbackEXT (VkInstance, const VkDebugReportCallbackCreateInfoEXT*) {} ~DebugReportCallbackEXT (void) {} }; class Device { public: Device (VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* deviceInfo); ~Device (void) {} PFN_vkVoidFunction getProcAddr (const char* name) const { return (PFN_vkVoidFunction)m_functions.getFunction(name); } private: const tcu::StaticFunctionLibrary m_functions; }; class Pipeline { public: Pipeline (VkDevice, const VkGraphicsPipelineCreateInfo*) {} Pipeline (VkDevice, const VkComputePipelineCreateInfo*) {} }; class RenderPass { public: RenderPass (VkDevice, const VkRenderPassCreateInfo*) {} RenderPass (VkDevice, const VkRenderPassCreateInfo2KHR*) {} }; class SwapchainKHR { public: SwapchainKHR (VkDevice, const VkSwapchainCreateInfoKHR*) {} ~SwapchainKHR (void) {} }; class SamplerYcbcrConversion { public: SamplerYcbcrConversion (VkDevice, const VkSamplerYcbcrConversionCreateInfo*) {} }; class Buffer { public: Buffer (VkDevice, const VkBufferCreateInfo* pCreateInfo) : m_size (pCreateInfo->size) { } VkDeviceSize getSize (void) const { return m_size; } private: const VkDeviceSize m_size; }; VkExternalMemoryHandleTypeFlags getExternalTypesHandle (const VkImageCreateInfo* pCreateInfo) { const VkExternalMemoryImageCreateInfo* const externalInfo = findStructure (pCreateInfo->pNext); return externalInfo ? externalInfo->handleTypes : 0u; } class Image { public: Image (VkDevice, const VkImageCreateInfo* pCreateInfo) : m_imageType (pCreateInfo->imageType) , m_format (pCreateInfo->format) , m_extent (pCreateInfo->extent) , m_arrayLayers (pCreateInfo->arrayLayers) , m_samples (pCreateInfo->samples) , m_usage (pCreateInfo->usage) , m_flags (pCreateInfo->flags) , m_externalHandleTypes (getExternalTypesHandle(pCreateInfo)) { } VkImageType getImageType (void) const { return m_imageType; } VkFormat getFormat (void) const { return m_format; } VkExtent3D getExtent (void) const { return m_extent; } deUint32 getArrayLayers (void) const { return m_arrayLayers; } VkSampleCountFlagBits getSamples (void) const { return m_samples; } VkImageUsageFlags getUsage (void) const { return m_usage; } VkImageCreateFlags getFlags (void) const { return m_flags; } VkExternalMemoryHandleTypeFlags getExternalHandleTypes (void) const { return m_externalHandleTypes; } private: const VkImageType m_imageType; const VkFormat m_format; const VkExtent3D m_extent; const deUint32 m_arrayLayers; const VkSampleCountFlagBits m_samples; const VkImageUsageFlags m_usage; const VkImageCreateFlags m_flags; const VkExternalMemoryHandleTypeFlags m_externalHandleTypes; }; void* allocateHeap (const VkMemoryAllocateInfo* pAllocInfo) { // \todo [2015-12-03 pyry] Alignment requirements? // \todo [2015-12-03 pyry] Empty allocations okay? if (pAllocInfo->allocationSize > 0) { void* const heapPtr = deMalloc((size_t)pAllocInfo->allocationSize); if (!heapPtr) throw std::bad_alloc(); return heapPtr; } else return DE_NULL; } void freeHeap (void* ptr) { deFree(ptr); } class DeviceMemory { public: virtual ~DeviceMemory (void) {} virtual void* map (void) = 0; virtual void unmap (void) = 0; }; class PrivateDeviceMemory : public DeviceMemory { public: PrivateDeviceMemory (VkDevice, const VkMemoryAllocateInfo* pAllocInfo) : m_memory(allocateHeap(pAllocInfo)) { // \todo [2016-08-03 pyry] In some cases leaving data unintialized would help valgrind analysis, // but currently it mostly hinders it. if (m_memory) deMemset(m_memory, 0xcd, (size_t)pAllocInfo->allocationSize); } virtual ~PrivateDeviceMemory (void) { freeHeap(m_memory); } virtual void* map (void) /*override*/ { return m_memory; } virtual void unmap (void) /*override*/ {} private: void* const m_memory; }; #if defined(USE_ANDROID_O_HARDWARE_BUFFER) AHardwareBuffer* findOrCreateHwBuffer (const VkMemoryAllocateInfo* pAllocInfo) { const VkExportMemoryAllocateInfo* const exportInfo = findStructure(pAllocInfo->pNext); const VkImportAndroidHardwareBufferInfoANDROID* const importInfo = findStructure(pAllocInfo->pNext); const VkMemoryDedicatedAllocateInfo* const dedicatedInfo = findStructure(pAllocInfo->pNext); const Image* const image = dedicatedInfo && !!dedicatedInfo->image ? reinterpret_cast(dedicatedInfo->image.getInternal()) : DE_NULL; AHardwareBuffer* hwbuffer = DE_NULL; // Import and export aren't mutually exclusive; we can have both simultaneously. DE_ASSERT((importInfo && importInfo->buffer.internal) || (exportInfo && (exportInfo->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) != 0)); if (importInfo && importInfo->buffer.internal) { hwbuffer = (AHardwareBuffer*)importInfo->buffer.internal; AHardwareBuffer_acquire(hwbuffer); } else if (exportInfo && (exportInfo->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) != 0) { AHardwareBuffer_Desc hwbufferDesc; deMemset(&hwbufferDesc, 0, sizeof(hwbufferDesc)); if (image) { hwbufferDesc.width = image->getExtent().width; hwbufferDesc.height = image->getExtent().height; hwbufferDesc.layers = image->getArrayLayers(); switch (image->getFormat()) { case VK_FORMAT_R8G8B8A8_UNORM: hwbufferDesc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; break; case VK_FORMAT_R8G8B8_UNORM: hwbufferDesc.format = AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM; break; case VK_FORMAT_R5G6B5_UNORM_PACK16: hwbufferDesc.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM; break; case VK_FORMAT_R16G16B16A16_SFLOAT: hwbufferDesc.format = AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT; break; case VK_FORMAT_A2R10G10B10_UNORM_PACK32: hwbufferDesc.format = AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM; break; default: DE_FATAL("Unsupported image format for Android hardware buffer export"); break; } if ((image->getUsage() & VK_IMAGE_USAGE_SAMPLED_BIT) != 0) hwbufferDesc.usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; if ((image->getUsage() & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0) hwbufferDesc.usage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT; // if ((image->getFlags() & VK_IMAGE_CREATE_PROTECTED_BIT) != 0) // hwbufferDesc.usage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT; // Make sure we have at least one AHB GPU usage, even if the image doesn't have any // Vulkan usages with corresponding to AHB GPU usages. if ((image->getUsage() & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) == 0) hwbufferDesc.usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; } else { hwbufferDesc.width = static_cast(pAllocInfo->allocationSize); hwbufferDesc.height = 1, hwbufferDesc.layers = 1, hwbufferDesc.format = AHARDWAREBUFFER_FORMAT_BLOB, hwbufferDesc.usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER; } AHardwareBuffer_allocate(&hwbufferDesc, &hwbuffer); } return hwbuffer; } class ExternalDeviceMemoryAndroid : public DeviceMemory { public: ExternalDeviceMemoryAndroid (VkDevice, const VkMemoryAllocateInfo* pAllocInfo) : m_hwbuffer(findOrCreateHwBuffer(pAllocInfo)) {} virtual ~ExternalDeviceMemoryAndroid (void) { if (m_hwbuffer) AHardwareBuffer_release(m_hwbuffer); } virtual void* map (void) /*override*/ { void* p; AHardwareBuffer_lock(m_hwbuffer, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, NULL, &p); return p; } virtual void unmap (void) /*override*/ { AHardwareBuffer_unlock(m_hwbuffer, NULL); } AHardwareBuffer* getHwBuffer (void) { return m_hwbuffer; } private: AHardwareBuffer* const m_hwbuffer; }; #endif // defined(USE_ANDROID_O_HARDWARE_BUFFER) class IndirectCommandsLayoutNVX { public: IndirectCommandsLayoutNVX (VkDevice, const VkIndirectCommandsLayoutCreateInfoNVX*) {} }; class ObjectTableNVX { public: ObjectTableNVX (VkDevice, const VkObjectTableCreateInfoNVX*) {} }; class ValidationCacheEXT { public: ValidationCacheEXT (VkDevice, const VkValidationCacheCreateInfoEXT*) {} }; class CommandBuffer { public: CommandBuffer (VkDevice, VkCommandPool, VkCommandBufferLevel) {} }; class DescriptorUpdateTemplate { public: DescriptorUpdateTemplate (VkDevice, const VkDescriptorUpdateTemplateCreateInfo*) {} }; class CommandPool { public: CommandPool (VkDevice device, const VkCommandPoolCreateInfo*) : m_device(device) {} ~CommandPool (void); VkCommandBuffer allocate (VkCommandBufferLevel level); void free (VkCommandBuffer buffer); private: const VkDevice m_device; vector m_buffers; }; CommandPool::~CommandPool (void) { for (size_t ndx = 0; ndx < m_buffers.size(); ++ndx) delete m_buffers[ndx]; } VkCommandBuffer CommandPool::allocate (VkCommandBufferLevel level) { CommandBuffer* const impl = new CommandBuffer(m_device, VkCommandPool(reinterpret_cast(this)), level); try { m_buffers.push_back(impl); } catch (...) { delete impl; throw; } return reinterpret_cast(impl); } void CommandPool::free (VkCommandBuffer buffer) { CommandBuffer* const impl = reinterpret_cast(buffer); for (size_t ndx = 0; ndx < m_buffers.size(); ++ndx) { if (m_buffers[ndx] == impl) { std::swap(m_buffers[ndx], m_buffers.back()); m_buffers.pop_back(); delete impl; return; } } DE_FATAL("VkCommandBuffer not owned by VkCommandPool"); } class DescriptorSet { public: DescriptorSet (VkDevice, VkDescriptorPool, VkDescriptorSetLayout) {} }; class DescriptorPool { public: DescriptorPool (VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo) : m_device (device) , m_flags (pCreateInfo->flags) {} ~DescriptorPool (void) { reset(); } VkDescriptorSet allocate (VkDescriptorSetLayout setLayout); void free (VkDescriptorSet set); void reset (void); private: const VkDevice m_device; const VkDescriptorPoolCreateFlags m_flags; vector m_managedSets; }; VkDescriptorSet DescriptorPool::allocate (VkDescriptorSetLayout setLayout) { DescriptorSet* const impl = new DescriptorSet(m_device, VkDescriptorPool(reinterpret_cast(this)), setLayout); try { m_managedSets.push_back(impl); } catch (...) { delete impl; throw; } return VkDescriptorSet(reinterpret_cast(impl)); } void DescriptorPool::free (VkDescriptorSet set) { DescriptorSet* const impl = reinterpret_cast((deUintptr)set.getInternal()); DE_ASSERT(m_flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT); DE_UNREF(m_flags); for (size_t ndx = 0; ndx < m_managedSets.size(); ++ndx) { if (m_managedSets[ndx] == impl) { std::swap(m_managedSets[ndx], m_managedSets.back()); m_managedSets.pop_back(); delete impl; return; } } DE_FATAL("VkDescriptorSet not owned by VkDescriptorPool"); } void DescriptorPool::reset (void) { for (size_t ndx = 0; ndx < m_managedSets.size(); ++ndx) delete m_managedSets[ndx]; m_managedSets.clear(); } // API implementation extern "C" { VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL getDeviceProcAddr (VkDevice device, const char* pName) { return reinterpret_cast(device)->getProcAddr(pName); } VKAPI_ATTR VkResult VKAPI_CALL createGraphicsPipelines (VkDevice device, VkPipelineCache, deUint32 count, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) { deUint32 allocNdx; try { for (allocNdx = 0; allocNdx < count; allocNdx++) pPipelines[allocNdx] = allocateNonDispHandle(device, pCreateInfos+allocNdx, pAllocator); return VK_SUCCESS; } catch (const std::bad_alloc&) { for (deUint32 freeNdx = 0; freeNdx < allocNdx; freeNdx++) freeNonDispHandle(pPipelines[freeNdx], pAllocator); return VK_ERROR_OUT_OF_HOST_MEMORY; } catch (VkResult err) { for (deUint32 freeNdx = 0; freeNdx < allocNdx; freeNdx++) freeNonDispHandle(pPipelines[freeNdx], pAllocator); return err; } } VKAPI_ATTR VkResult VKAPI_CALL createComputePipelines (VkDevice device, VkPipelineCache, deUint32 count, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) { deUint32 allocNdx; try { for (allocNdx = 0; allocNdx < count; allocNdx++) pPipelines[allocNdx] = allocateNonDispHandle(device, pCreateInfos+allocNdx, pAllocator); return VK_SUCCESS; } catch (const std::bad_alloc&) { for (deUint32 freeNdx = 0; freeNdx < allocNdx; freeNdx++) freeNonDispHandle(pPipelines[freeNdx], pAllocator); return VK_ERROR_OUT_OF_HOST_MEMORY; } catch (VkResult err) { for (deUint32 freeNdx = 0; freeNdx < allocNdx; freeNdx++) freeNonDispHandle(pPipelines[freeNdx], pAllocator); return err; } } VKAPI_ATTR VkResult VKAPI_CALL enumeratePhysicalDevices (VkInstance, deUint32* pPhysicalDeviceCount, VkPhysicalDevice* pDevices) { if (pDevices && *pPhysicalDeviceCount >= 1u) *pDevices = reinterpret_cast((void*)(deUintptr)1u); *pPhysicalDeviceCount = 1; return VK_SUCCESS; } VkResult enumerateExtensions (deUint32 numExtensions, const VkExtensionProperties* extensions, deUint32* pPropertyCount, VkExtensionProperties* pProperties) { const deUint32 dstSize = pPropertyCount ? *pPropertyCount : 0; if (pPropertyCount) *pPropertyCount = numExtensions; if (pProperties) { for (deUint32 ndx = 0; ndx < de::min(numExtensions, dstSize); ++ndx) pProperties[ndx] = extensions[ndx]; if (dstSize < numExtensions) return VK_INCOMPLETE; } return VK_SUCCESS; } VKAPI_ATTR VkResult VKAPI_CALL enumerateInstanceExtensionProperties (const char* pLayerName, deUint32* pPropertyCount, VkExtensionProperties* pProperties) { static const VkExtensionProperties s_extensions[] = { { "VK_KHR_get_physical_device_properties2", 1u }, { "VK_KHR_external_memory_capabilities", 1u }, }; if (!pLayerName) return enumerateExtensions((deUint32)DE_LENGTH_OF_ARRAY(s_extensions), s_extensions, pPropertyCount, pProperties); else return enumerateExtensions(0, DE_NULL, pPropertyCount, pProperties); } VKAPI_ATTR VkResult VKAPI_CALL enumerateDeviceExtensionProperties (VkPhysicalDevice physicalDevice, const char* pLayerName, deUint32* pPropertyCount, VkExtensionProperties* pProperties) { DE_UNREF(physicalDevice); static const VkExtensionProperties s_extensions[] = { { "VK_KHR_bind_memory2", 1u }, { "VK_KHR_external_memory", 1u }, { "VK_KHR_get_memory_requirements2", 1u }, { "VK_KHR_maintenance1", 1u }, { "VK_KHR_sampler_ycbcr_conversion", 1u }, #if defined(USE_ANDROID_O_HARDWARE_BUFFER) { "VK_ANDROID_external_memory_android_hardware_buffer", 1u }, #endif }; if (!pLayerName) return enumerateExtensions((deUint32)DE_LENGTH_OF_ARRAY(s_extensions), s_extensions, pPropertyCount, pProperties); else return enumerateExtensions(0, DE_NULL, pPropertyCount, pProperties); } VKAPI_ATTR void VKAPI_CALL getPhysicalDeviceFeatures (VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures) { DE_UNREF(physicalDevice); // Enable all features allow as many tests to run as possible pFeatures->robustBufferAccess = VK_TRUE; pFeatures->fullDrawIndexUint32 = VK_TRUE; pFeatures->imageCubeArray = VK_TRUE; pFeatures->independentBlend = VK_TRUE; pFeatures->geometryShader = VK_TRUE; pFeatures->tessellationShader = VK_TRUE; pFeatures->sampleRateShading = VK_TRUE; pFeatures->dualSrcBlend = VK_TRUE; pFeatures->logicOp = VK_TRUE; pFeatures->multiDrawIndirect = VK_TRUE; pFeatures->drawIndirectFirstInstance = VK_TRUE; pFeatures->depthClamp = VK_TRUE; pFeatures->depthBiasClamp = VK_TRUE; pFeatures->fillModeNonSolid = VK_TRUE; pFeatures->depthBounds = VK_TRUE; pFeatures->wideLines = VK_TRUE; pFeatures->largePoints = VK_TRUE; pFeatures->alphaToOne = VK_TRUE; pFeatures->multiViewport = VK_TRUE; pFeatures->samplerAnisotropy = VK_TRUE; pFeatures->textureCompressionETC2 = VK_TRUE; pFeatures->textureCompressionASTC_LDR = VK_TRUE; pFeatures->textureCompressionBC = VK_TRUE; pFeatures->occlusionQueryPrecise = VK_TRUE; pFeatures->pipelineStatisticsQuery = VK_TRUE; pFeatures->vertexPipelineStoresAndAtomics = VK_TRUE; pFeatures->fragmentStoresAndAtomics = VK_TRUE; pFeatures->shaderTessellationAndGeometryPointSize = VK_TRUE; pFeatures->shaderImageGatherExtended = VK_TRUE; pFeatures->shaderStorageImageExtendedFormats = VK_TRUE; pFeatures->shaderStorageImageMultisample = VK_TRUE; pFeatures->shaderStorageImageReadWithoutFormat = VK_TRUE; pFeatures->shaderStorageImageWriteWithoutFormat = VK_TRUE; pFeatures->shaderUniformBufferArrayDynamicIndexing = VK_TRUE; pFeatures->shaderSampledImageArrayDynamicIndexing = VK_TRUE; pFeatures->shaderStorageBufferArrayDynamicIndexing = VK_TRUE; pFeatures->shaderStorageImageArrayDynamicIndexing = VK_TRUE; pFeatures->shaderClipDistance = VK_TRUE; pFeatures->shaderCullDistance = VK_TRUE; pFeatures->shaderFloat64 = VK_TRUE; pFeatures->shaderInt64 = VK_TRUE; pFeatures->shaderInt16 = VK_TRUE; pFeatures->shaderResourceResidency = VK_TRUE; pFeatures->shaderResourceMinLod = VK_TRUE; pFeatures->sparseBinding = VK_TRUE; pFeatures->sparseResidencyBuffer = VK_TRUE; pFeatures->sparseResidencyImage2D = VK_TRUE; pFeatures->sparseResidencyImage3D = VK_TRUE; pFeatures->sparseResidency2Samples = VK_TRUE; pFeatures->sparseResidency4Samples = VK_TRUE; pFeatures->sparseResidency8Samples = VK_TRUE; pFeatures->sparseResidency16Samples = VK_TRUE; pFeatures->sparseResidencyAliased = VK_TRUE; pFeatures->variableMultisampleRate = VK_TRUE; pFeatures->inheritedQueries = VK_TRUE; } VKAPI_ATTR void VKAPI_CALL getPhysicalDeviceProperties (VkPhysicalDevice, VkPhysicalDeviceProperties* props) { deMemset(props, 0, sizeof(VkPhysicalDeviceProperties)); props->apiVersion = VK_API_VERSION_1_1; props->driverVersion = 1u; props->deviceType = VK_PHYSICAL_DEVICE_TYPE_OTHER; deMemcpy(props->deviceName, "null", 5); // Spec minmax props->limits.maxImageDimension1D = 4096; props->limits.maxImageDimension2D = 4096; props->limits.maxImageDimension3D = 256; props->limits.maxImageDimensionCube = 4096; props->limits.maxImageArrayLayers = 256; props->limits.maxTexelBufferElements = 65536; props->limits.maxUniformBufferRange = 16384; props->limits.maxStorageBufferRange = 1u<<27; props->limits.maxPushConstantsSize = 128; props->limits.maxMemoryAllocationCount = 4096; props->limits.maxSamplerAllocationCount = 4000; props->limits.bufferImageGranularity = 131072; props->limits.sparseAddressSpaceSize = 1u<<31; props->limits.maxBoundDescriptorSets = 4; props->limits.maxPerStageDescriptorSamplers = 16; props->limits.maxPerStageDescriptorUniformBuffers = 12; props->limits.maxPerStageDescriptorStorageBuffers = 4; props->limits.maxPerStageDescriptorSampledImages = 16; props->limits.maxPerStageDescriptorStorageImages = 4; props->limits.maxPerStageDescriptorInputAttachments = 4; props->limits.maxPerStageResources = 128; props->limits.maxDescriptorSetSamplers = 96; props->limits.maxDescriptorSetUniformBuffers = 72; props->limits.maxDescriptorSetUniformBuffersDynamic = 8; props->limits.maxDescriptorSetStorageBuffers = 24; props->limits.maxDescriptorSetStorageBuffersDynamic = 4; props->limits.maxDescriptorSetSampledImages = 96; props->limits.maxDescriptorSetStorageImages = 24; props->limits.maxDescriptorSetInputAttachments = 4; props->limits.maxVertexInputAttributes = 16; props->limits.maxVertexInputBindings = 16; props->limits.maxVertexInputAttributeOffset = 2047; props->limits.maxVertexInputBindingStride = 2048; props->limits.maxVertexOutputComponents = 64; props->limits.maxTessellationGenerationLevel = 64; props->limits.maxTessellationPatchSize = 32; props->limits.maxTessellationControlPerVertexInputComponents = 64; props->limits.maxTessellationControlPerVertexOutputComponents = 64; props->limits.maxTessellationControlPerPatchOutputComponents = 120; props->limits.maxTessellationControlTotalOutputComponents = 2048; props->limits.maxTessellationEvaluationInputComponents = 64; props->limits.maxTessellationEvaluationOutputComponents = 64; props->limits.maxGeometryShaderInvocations = 32; props->limits.maxGeometryInputComponents = 64; props->limits.maxGeometryOutputComponents = 64; props->limits.maxGeometryOutputVertices = 256; props->limits.maxGeometryTotalOutputComponents = 1024; props->limits.maxFragmentInputComponents = 64; props->limits.maxFragmentOutputAttachments = 4; props->limits.maxFragmentDualSrcAttachments = 1; props->limits.maxFragmentCombinedOutputResources = 4; props->limits.maxComputeSharedMemorySize = 16384; props->limits.maxComputeWorkGroupCount[0] = 65535; props->limits.maxComputeWorkGroupCount[1] = 65535; props->limits.maxComputeWorkGroupCount[2] = 65535; props->limits.maxComputeWorkGroupInvocations = 128; props->limits.maxComputeWorkGroupSize[0] = 128; props->limits.maxComputeWorkGroupSize[1] = 128; props->limits.maxComputeWorkGroupSize[2] = 128; props->limits.subPixelPrecisionBits = 4; props->limits.subTexelPrecisionBits = 4; props->limits.mipmapPrecisionBits = 4; props->limits.maxDrawIndexedIndexValue = 0xffffffffu; props->limits.maxDrawIndirectCount = (1u<<16) - 1u; props->limits.maxSamplerLodBias = 2.0f; props->limits.maxSamplerAnisotropy = 16.0f; props->limits.maxViewports = 16; props->limits.maxViewportDimensions[0] = 4096; props->limits.maxViewportDimensions[1] = 4096; props->limits.viewportBoundsRange[0] = -8192.f; props->limits.viewportBoundsRange[1] = 8191.f; props->limits.viewportSubPixelBits = 0; props->limits.minMemoryMapAlignment = 64; props->limits.minTexelBufferOffsetAlignment = 256; props->limits.minUniformBufferOffsetAlignment = 256; props->limits.minStorageBufferOffsetAlignment = 256; props->limits.minTexelOffset = -8; props->limits.maxTexelOffset = 7; props->limits.minTexelGatherOffset = -8; props->limits.maxTexelGatherOffset = 7; props->limits.minInterpolationOffset = -0.5f; props->limits.maxInterpolationOffset = 0.5f; // -1ulp props->limits.subPixelInterpolationOffsetBits = 4; props->limits.maxFramebufferWidth = 4096; props->limits.maxFramebufferHeight = 4096; props->limits.maxFramebufferLayers = 256; props->limits.framebufferColorSampleCounts = VK_SAMPLE_COUNT_1_BIT|VK_SAMPLE_COUNT_4_BIT; props->limits.framebufferDepthSampleCounts = VK_SAMPLE_COUNT_1_BIT|VK_SAMPLE_COUNT_4_BIT; props->limits.framebufferStencilSampleCounts = VK_SAMPLE_COUNT_1_BIT|VK_SAMPLE_COUNT_4_BIT; props->limits.framebufferNoAttachmentsSampleCounts = VK_SAMPLE_COUNT_1_BIT|VK_SAMPLE_COUNT_4_BIT; props->limits.maxColorAttachments = 4; props->limits.sampledImageColorSampleCounts = VK_SAMPLE_COUNT_1_BIT|VK_SAMPLE_COUNT_4_BIT; props->limits.sampledImageIntegerSampleCounts = VK_SAMPLE_COUNT_1_BIT; props->limits.sampledImageDepthSampleCounts = VK_SAMPLE_COUNT_1_BIT|VK_SAMPLE_COUNT_4_BIT; props->limits.sampledImageStencilSampleCounts = VK_SAMPLE_COUNT_1_BIT|VK_SAMPLE_COUNT_4_BIT; props->limits.storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT|VK_SAMPLE_COUNT_4_BIT; props->limits.maxSampleMaskWords = 1; props->limits.timestampComputeAndGraphics = VK_TRUE; props->limits.timestampPeriod = 1.0f; props->limits.maxClipDistances = 8; props->limits.maxCullDistances = 8; props->limits.maxCombinedClipAndCullDistances = 8; props->limits.discreteQueuePriorities = 2; props->limits.pointSizeRange[0] = 1.0f; props->limits.pointSizeRange[1] = 64.0f; // -1ulp props->limits.lineWidthRange[0] = 1.0f; props->limits.lineWidthRange[1] = 8.0f; // -1ulp props->limits.pointSizeGranularity = 1.0f; props->limits.lineWidthGranularity = 1.0f; props->limits.strictLines = 0; props->limits.standardSampleLocations = VK_TRUE; props->limits.optimalBufferCopyOffsetAlignment = 256; props->limits.optimalBufferCopyRowPitchAlignment = 256; props->limits.nonCoherentAtomSize = 128; } VKAPI_ATTR void VKAPI_CALL getPhysicalDeviceQueueFamilyProperties (VkPhysicalDevice, deUint32* count, VkQueueFamilyProperties* props) { if (props && *count >= 1u) { deMemset(props, 0, sizeof(VkQueueFamilyProperties)); props->queueCount = 4u; props->queueFlags = VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT; props->timestampValidBits = 64; } *count = 1u; } VKAPI_ATTR void VKAPI_CALL getPhysicalDeviceMemoryProperties (VkPhysicalDevice, VkPhysicalDeviceMemoryProperties* props) { deMemset(props, 0, sizeof(VkPhysicalDeviceMemoryProperties)); props->memoryTypeCount = 1u; props->memoryTypes[0].heapIndex = 0u; props->memoryTypes[0].propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; props->memoryHeapCount = 1u; props->memoryHeaps[0].size = 1ull << 31; props->memoryHeaps[0].flags = 0u; } VKAPI_ATTR void VKAPI_CALL getPhysicalDeviceFormatProperties (VkPhysicalDevice, VkFormat format, VkFormatProperties* pFormatProperties) { const VkFormatFeatureFlags allFeatures = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT | VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT; pFormatProperties->linearTilingFeatures = allFeatures; pFormatProperties->optimalTilingFeatures = allFeatures; pFormatProperties->bufferFeatures = allFeatures; if (isYCbCrFormat(format) && getPlaneCount(format) > 1) pFormatProperties->optimalTilingFeatures |= VK_FORMAT_FEATURE_DISJOINT_BIT; } VKAPI_ATTR VkResult VKAPI_CALL getPhysicalDeviceImageFormatProperties (VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties) { DE_UNREF(physicalDevice); DE_UNREF(format); DE_UNREF(type); DE_UNREF(tiling); DE_UNREF(usage); DE_UNREF(flags); pImageFormatProperties->maxArrayLayers = 8; pImageFormatProperties->maxExtent.width = 4096; pImageFormatProperties->maxExtent.height = 4096; pImageFormatProperties->maxExtent.depth = 4096; pImageFormatProperties->maxMipLevels = deLog2Ceil32(4096) + 1; pImageFormatProperties->maxResourceSize = 64u * 1024u * 1024u; pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT|VK_SAMPLE_COUNT_4_BIT; return VK_SUCCESS; } VKAPI_ATTR void VKAPI_CALL getDeviceQueue (VkDevice device, deUint32 queueFamilyIndex, deUint32 queueIndex, VkQueue* pQueue) { DE_UNREF(device); DE_UNREF(queueFamilyIndex); if (pQueue) *pQueue = reinterpret_cast((deUint64)queueIndex + 1); } VKAPI_ATTR void VKAPI_CALL getBufferMemoryRequirements (VkDevice, VkBuffer bufferHandle, VkMemoryRequirements* requirements) { const Buffer* buffer = reinterpret_cast(bufferHandle.getInternal()); requirements->memoryTypeBits = 1u; requirements->size = buffer->getSize(); requirements->alignment = (VkDeviceSize)1u; } VkDeviceSize getPackedImageDataSize (VkFormat format, VkExtent3D extent, VkSampleCountFlagBits samples) { return (VkDeviceSize)getPixelSize(mapVkFormat(format)) * (VkDeviceSize)extent.width * (VkDeviceSize)extent.height * (VkDeviceSize)extent.depth * (VkDeviceSize)samples; } VkDeviceSize getCompressedImageDataSize (VkFormat format, VkExtent3D extent) { try { const tcu::CompressedTexFormat tcuFormat = mapVkCompressedFormat(format); const size_t blockSize = tcu::getBlockSize(tcuFormat); const tcu::IVec3 blockPixelSize = tcu::getBlockPixelSize(tcuFormat); const int numBlocksX = deDivRoundUp32((int)extent.width, blockPixelSize.x()); const int numBlocksY = deDivRoundUp32((int)extent.height, blockPixelSize.y()); const int numBlocksZ = deDivRoundUp32((int)extent.depth, blockPixelSize.z()); return blockSize*numBlocksX*numBlocksY*numBlocksZ; } catch (...) { return 0; // Unsupported compressed format } } VkDeviceSize getYCbCrImageDataSize (VkFormat format, VkExtent3D extent) { const PlanarFormatDescription desc = getPlanarFormatDescription(format); VkDeviceSize totalSize = 0; DE_ASSERT(extent.depth == 1); for (deUint32 planeNdx = 0; planeNdx < desc.numPlanes; ++planeNdx) { const deUint32 planeW = extent.width / desc.planes[planeNdx].widthDivisor; const deUint32 planeH = extent.height / desc.planes[planeNdx].heightDivisor; const deUint32 elementSize = desc.planes[planeNdx].elementSizeBytes; totalSize = (VkDeviceSize)deAlign64((deInt64)totalSize, elementSize); totalSize += planeW * planeH * elementSize; } return totalSize; } VKAPI_ATTR void VKAPI_CALL getImageMemoryRequirements (VkDevice, VkImage imageHandle, VkMemoryRequirements* requirements) { const Image* image = reinterpret_cast(imageHandle.getInternal()); requirements->memoryTypeBits = 1u; requirements->alignment = 16u; if (isCompressedFormat(image->getFormat())) requirements->size = getCompressedImageDataSize(image->getFormat(), image->getExtent()); else if (isYCbCrFormat(image->getFormat())) requirements->size = getYCbCrImageDataSize(image->getFormat(), image->getExtent()); else requirements->size = getPackedImageDataSize(image->getFormat(), image->getExtent(), image->getSamples()); } VKAPI_ATTR VkResult VKAPI_CALL allocateMemory (VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory) { const VkExportMemoryAllocateInfo* const exportInfo = findStructure(pAllocateInfo->pNext); const VkImportAndroidHardwareBufferInfoANDROID* const importInfo = findStructure(pAllocateInfo->pNext); if ((exportInfo && (exportInfo->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) != 0) || (importInfo && importInfo->buffer.internal)) { #if defined(USE_ANDROID_O_HARDWARE_BUFFER) VK_NULL_RETURN((*pMemory = allocateNonDispHandle(device, pAllocateInfo, pAllocator))); #else return VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR; #endif } else { VK_NULL_RETURN((*pMemory = allocateNonDispHandle(device, pAllocateInfo, pAllocator))); } } VKAPI_ATTR VkResult VKAPI_CALL mapMemory (VkDevice, VkDeviceMemory memHandle, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) { DeviceMemory* const memory = reinterpret_cast(memHandle.getInternal()); DE_UNREF(size); DE_UNREF(flags); *ppData = (deUint8*)memory->map() + offset; return VK_SUCCESS; } VKAPI_ATTR void VKAPI_CALL unmapMemory (VkDevice device, VkDeviceMemory memHandle) { DeviceMemory* const memory = reinterpret_cast(memHandle.getInternal()); DE_UNREF(device); memory->unmap(); } VKAPI_ATTR VkResult VKAPI_CALL getMemoryAndroidHardwareBufferANDROID (VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, pt::AndroidHardwareBufferPtr* pBuffer) { DE_UNREF(device); #if defined(USE_ANDROID_O_HARDWARE_BUFFER) DeviceMemory* const memory = reinterpret_cast(pInfo->memory.getInternal()); ExternalDeviceMemoryAndroid* const androidMemory = static_cast(memory); AHardwareBuffer* hwbuffer = androidMemory->getHwBuffer(); AHardwareBuffer_acquire(hwbuffer); pBuffer->internal = hwbuffer; #else DE_UNREF(pInfo); DE_UNREF(pBuffer); #endif return VK_SUCCESS; } VKAPI_ATTR VkResult VKAPI_CALL allocateDescriptorSets (VkDevice, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets) { DescriptorPool* const poolImpl = reinterpret_cast((deUintptr)pAllocateInfo->descriptorPool.getInternal()); for (deUint32 ndx = 0; ndx < pAllocateInfo->descriptorSetCount; ++ndx) { try { pDescriptorSets[ndx] = poolImpl->allocate(pAllocateInfo->pSetLayouts[ndx]); } catch (const std::bad_alloc&) { for (deUint32 freeNdx = 0; freeNdx < ndx; freeNdx++) delete reinterpret_cast((deUintptr)pDescriptorSets[freeNdx].getInternal()); return VK_ERROR_OUT_OF_HOST_MEMORY; } catch (VkResult res) { for (deUint32 freeNdx = 0; freeNdx < ndx; freeNdx++) delete reinterpret_cast((deUintptr)pDescriptorSets[freeNdx].getInternal()); return res; } } return VK_SUCCESS; } VKAPI_ATTR void VKAPI_CALL freeDescriptorSets (VkDevice, VkDescriptorPool descriptorPool, deUint32 count, const VkDescriptorSet* pDescriptorSets) { DescriptorPool* const poolImpl = reinterpret_cast((deUintptr)descriptorPool.getInternal()); for (deUint32 ndx = 0; ndx < count; ++ndx) poolImpl->free(pDescriptorSets[ndx]); } VKAPI_ATTR VkResult VKAPI_CALL resetDescriptorPool (VkDevice, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags) { DescriptorPool* const poolImpl = reinterpret_cast((deUintptr)descriptorPool.getInternal()); poolImpl->reset(); return VK_SUCCESS; } VKAPI_ATTR VkResult VKAPI_CALL allocateCommandBuffers (VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers) { DE_UNREF(device); if (pAllocateInfo && pCommandBuffers) { CommandPool* const poolImpl = reinterpret_cast((deUintptr)pAllocateInfo->commandPool.getInternal()); for (deUint32 ndx = 0; ndx < pAllocateInfo->commandBufferCount; ++ndx) pCommandBuffers[ndx] = poolImpl->allocate(pAllocateInfo->level); } return VK_SUCCESS; } VKAPI_ATTR void VKAPI_CALL freeCommandBuffers (VkDevice device, VkCommandPool commandPool, deUint32 commandBufferCount, const VkCommandBuffer* pCommandBuffers) { CommandPool* const poolImpl = reinterpret_cast((deUintptr)commandPool.getInternal()); DE_UNREF(device); for (deUint32 ndx = 0; ndx < commandBufferCount; ++ndx) poolImpl->free(pCommandBuffers[ndx]); } VKAPI_ATTR VkResult VKAPI_CALL createDisplayModeKHR (VkPhysicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode) { DE_UNREF(pAllocator); VK_NULL_RETURN((*pMode = allocateNonDispHandle(display, pCreateInfo, pAllocator))); } VKAPI_ATTR VkResult VKAPI_CALL createSharedSwapchainsKHR (VkDevice device, deUint32 swapchainCount, const VkSwapchainCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains) { for (deUint32 ndx = 0; ndx < swapchainCount; ++ndx) { pSwapchains[ndx] = allocateNonDispHandle(device, pCreateInfos+ndx, pAllocator); } return VK_SUCCESS; } VKAPI_ATTR void VKAPI_CALL getPhysicalDeviceExternalBufferPropertiesKHR (VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties) { DE_UNREF(physicalDevice); DE_UNREF(pExternalBufferInfo); pExternalBufferProperties->externalMemoryProperties.externalMemoryFeatures = 0; pExternalBufferProperties->externalMemoryProperties.exportFromImportedHandleTypes = 0; pExternalBufferProperties->externalMemoryProperties.compatibleHandleTypes = 0; if (pExternalBufferInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) { pExternalBufferProperties->externalMemoryProperties.externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR; pExternalBufferProperties->externalMemoryProperties.exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; pExternalBufferProperties->externalMemoryProperties.compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; } } VKAPI_ATTR VkResult VKAPI_CALL getPhysicalDeviceImageFormatProperties2KHR (VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties) { const VkPhysicalDeviceExternalImageFormatInfo* const externalInfo = findStructure(pImageFormatInfo->pNext); VkExternalImageFormatProperties* const externalProperties = findStructure(pImageFormatProperties->pNext); VkResult result; result = getPhysicalDeviceImageFormatProperties(physicalDevice, pImageFormatInfo->format, pImageFormatInfo->type, pImageFormatInfo->tiling, pImageFormatInfo->usage, pImageFormatInfo->flags, &pImageFormatProperties->imageFormatProperties); if (result != VK_SUCCESS) return result; if (externalInfo && externalInfo->handleType != 0) { if (externalInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) return VK_ERROR_FORMAT_NOT_SUPPORTED; if (!(pImageFormatInfo->format == VK_FORMAT_R8G8B8A8_UNORM || pImageFormatInfo->format == VK_FORMAT_R8G8B8_UNORM || pImageFormatInfo->format == VK_FORMAT_R5G6B5_UNORM_PACK16 || pImageFormatInfo->format == VK_FORMAT_R16G16B16A16_SFLOAT || pImageFormatInfo->format == VK_FORMAT_A2R10G10B10_UNORM_PACK32)) { return VK_ERROR_FORMAT_NOT_SUPPORTED; } if (pImageFormatInfo->type != VK_IMAGE_TYPE_2D) return VK_ERROR_FORMAT_NOT_SUPPORTED; if ((pImageFormatInfo->usage & ~(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) != 0) { return VK_ERROR_FORMAT_NOT_SUPPORTED; } if ((pImageFormatInfo->flags & ~(VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT /*| VK_IMAGE_CREATE_PROTECTED_BIT_KHR*/ /*| VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR*/)) != 0) { return VK_ERROR_FORMAT_NOT_SUPPORTED; } if (externalProperties) { externalProperties->externalMemoryProperties.externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR; externalProperties->externalMemoryProperties.exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; externalProperties->externalMemoryProperties.compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; } } return VK_SUCCESS; } // \note getInstanceProcAddr is a little bit special: // vkNullDriverImpl.inl needs it to define s_platformFunctions but // getInstanceProcAddr() implementation needs other entry points from // vkNullDriverImpl.inl. VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL getInstanceProcAddr (VkInstance instance, const char* pName); #include "vkNullDriverImpl.inl" VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL getInstanceProcAddr (VkInstance instance, const char* pName) { if (instance) { return reinterpret_cast(instance)->getProcAddr(pName); } else { const std::string name = pName; if (name == "vkCreateInstance") return (PFN_vkVoidFunction)createInstance; else if (name == "vkEnumerateInstanceExtensionProperties") return (PFN_vkVoidFunction)enumerateInstanceExtensionProperties; else if (name == "vkEnumerateInstanceLayerProperties") return (PFN_vkVoidFunction)enumerateInstanceLayerProperties; else return (PFN_vkVoidFunction)DE_NULL; } } } // extern "C" Instance::Instance (const VkInstanceCreateInfo*) : m_functions(s_instanceFunctions, DE_LENGTH_OF_ARRAY(s_instanceFunctions)) { } Device::Device (VkPhysicalDevice, const VkDeviceCreateInfo*) : m_functions(s_deviceFunctions, DE_LENGTH_OF_ARRAY(s_deviceFunctions)) { } class NullDriverLibrary : public Library { public: NullDriverLibrary (void) : m_library (s_platformFunctions, DE_LENGTH_OF_ARRAY(s_platformFunctions)) , m_driver (m_library) {} const PlatformInterface& getPlatformInterface (void) const { return m_driver; } const tcu::FunctionLibrary& getFunctionLibrary (void) const { return m_library; } private: const tcu::StaticFunctionLibrary m_library; const PlatformDriver m_driver; }; } // anonymous Library* createNullDriver (void) { return new NullDriverLibrary(); } } // vk