Improve Vulkan null driver
authorPyry Haulos <phaulos@google.com>
Wed, 25 Nov 2015 17:48:14 +0000 (09:48 -0800)
committerPyry Haulos <phaulos@google.com>
Sat, 5 Dec 2015 20:31:06 +0000 (12:31 -0800)
 * Calling vkFreeDescriptorSet() on descriptor sets allocated from
pool without FREE_DESCRIPTOR_SET_BIT is a common mistake and thus
worth checking for in null driver.

 * Report sensible memory requirements for images in case test uses
linear-layout images to transfer pixel data.

Change-Id: Ief296977f83679b3b87601b1a08a2a96674d68ef

external/vulkancts/framework/vulkan/vkNullDriver.cpp
external/vulkancts/framework/vulkan/vkNullDriverImpl.inl
external/vulkancts/gen_framework.py

index 87f095c..9ca71df 100644 (file)
 
 #include "vkNullDriver.hpp"
 #include "vkPlatform.hpp"
+#include "vkImageUtil.hpp"
 #include "tcuFunctionLibrary.hpp"
 #include "deMemory.h"
 
 #include <stdexcept>
+#include <algorithm>
 
 namespace vk
 {
@@ -45,6 +47,8 @@ namespace vk
 namespace
 {
 
+using std::vector;
+
 #define VK_NULL_RETURN(STMT)                                   \
        do {                                                                            \
                try {                                                                   \
@@ -66,6 +70,21 @@ 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(RenderPass);
+VK_NULL_DEFINE_DEVICE_OBJ(DescriptorSetLayout);
+VK_NULL_DEFINE_DEVICE_OBJ(Sampler);
+VK_NULL_DEFINE_DEVICE_OBJ(Framebuffer);
+VK_NULL_DEFINE_DEVICE_OBJ(CommandPool);
+
 class Instance
 {
 public:
@@ -90,12 +109,6 @@ private:
        const tcu::StaticFunctionLibrary        m_functions;
 };
 
-class DescriptorSet
-{
-public:
-       DescriptorSet (VkDevice, VkDescriptorPool, VkDescriptorSetLayout) {}
-};
-
 class Pipeline
 {
 public:
@@ -103,18 +116,36 @@ public:
        Pipeline (VkDevice, const VkComputePipelineCreateInfo*) {}
 };
 
+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:
                                                DeviceMemory    (VkDevice, const VkMemoryAllocateInfo* pAllocInfo)
-                                                       : m_memory(deMalloc((size_t)pAllocInfo->allocationSize))
+                                                       : m_memory(allocateHeap(pAllocInfo))
                                                {
-                                                       if (!m_memory)
-                                                               throw std::bad_alloc();
                                                }
                                                ~DeviceMemory   (void)
                                                {
-                                                       deFree(m_memory);
+                                                       freeHeap(m_memory);
                                                }
 
        void*                           getPtr                  (void) const { return m_memory; }
@@ -136,6 +167,28 @@ private:
        const VkDeviceSize      m_size;
 };
 
+class Image
+{
+public:
+                                                               Image                   (VkDevice, const VkImageCreateInfo* pCreateInfo)
+                                                                       : m_imageType   (pCreateInfo->imageType)
+                                                                       , m_format              (pCreateInfo->format)
+                                                                       , m_extent              (pCreateInfo->extent)
+                                                                       , m_samples             (pCreateInfo->samples)
+                                                               {}
+
+       VkImageType                                     getImageType    (void) const { return m_imageType;      }
+       VkFormat                                        getFormat               (void) const { return m_format;         }
+       VkExtent3D                                      getExtent               (void) const { return m_extent;         }
+       VkSampleCountFlagBits           getSamples              (void) const { return m_samples;        }
+
+private:
+       const VkImageType                       m_imageType;
+       const VkFormat                          m_format;
+       const VkExtent3D                        m_extent;
+       const VkSampleCountFlagBits     m_samples;
+};
+
 class CommandBuffer
 {
 public:
@@ -143,22 +196,80 @@ public:
                                                {}
 };
 
-VK_NULL_DEFINE_DEVICE_OBJ(Fence);
-VK_NULL_DEFINE_DEVICE_OBJ(Image);
-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(RenderPass);
-VK_NULL_DEFINE_DEVICE_OBJ(DescriptorSetLayout);
-VK_NULL_DEFINE_DEVICE_OBJ(Sampler);
-VK_NULL_DEFINE_DEVICE_OBJ(Framebuffer);
-VK_NULL_DEFINE_DEVICE_OBJ(CommandPool);
-VK_NULL_DEFINE_DEVICE_OBJ(DescriptorPool);
+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<DescriptorSet*>                          m_managedSets;
+};
+
+VkDescriptorSet DescriptorPool::allocate (VkDescriptorSetLayout setLayout)
+{
+       DescriptorSet* const    impl    = new DescriptorSet(m_device, VkDescriptorPool(reinterpret_cast<deUintptr>(this)), setLayout);
+
+       try
+       {
+               m_managedSets.push_back(impl);
+       }
+       catch (...)
+       {
+               delete impl;
+               throw;
+       }
+
+       return VkDescriptorSet(reinterpret_cast<deUintptr>(impl));
+}
+
+void DescriptorPool::free (VkDescriptorSet set)
+{
+       DescriptorSet* const    impl    = reinterpret_cast<DescriptorSet*>((deUintptr)set.getInternal());
+
+       DE_ASSERT(m_flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT);
+
+       delete impl;
+
+       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();
+                       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();
+}
 
 extern "C"
 {
@@ -197,7 +308,7 @@ VkResult enumeratePhysicalDevices (VkInstance, deUint32* pPhysicalDeviceCount, V
        return VK_SUCCESS;
 }
 
-VkResult getPhysicalDeviceProperties (VkPhysicalDevice, VkPhysicalDeviceProperties* props)
+void getPhysicalDeviceProperties (VkPhysicalDevice, VkPhysicalDeviceProperties* props)
 {
        deMemset(props, 0, sizeof(VkPhysicalDeviceProperties));
 
@@ -208,11 +319,10 @@ VkResult getPhysicalDeviceProperties (VkPhysicalDevice, VkPhysicalDeviceProperti
        deMemcpy(props->deviceName, "null", 5);
 
        // \todo [2015-09-25 pyry] Fill in reasonable limits
-
-       return VK_SUCCESS;
+       props->limits.maxTexelBufferElements    = 8096;
 }
 
-VkResult getPhysicalDeviceQueueFamilyProperties (VkPhysicalDevice, deUint32* count, VkQueueFamilyProperties* props)
+void getPhysicalDeviceQueueFamilyProperties (VkPhysicalDevice, deUint32* count, VkQueueFamilyProperties* props)
 {
        if (props && *count >= 1u)
        {
@@ -224,11 +334,9 @@ VkResult getPhysicalDeviceQueueFamilyProperties (VkPhysicalDevice, deUint32* cou
        }
 
        *count = 1u;
-
-       return VK_SUCCESS;
 }
 
-VkResult getPhysicalDeviceMemoryProperties (VkPhysicalDevice, VkPhysicalDeviceMemoryProperties* props)
+void getPhysicalDeviceMemoryProperties (VkPhysicalDevice, VkPhysicalDeviceMemoryProperties* props)
 {
        deMemset(props, 0, sizeof(VkPhysicalDeviceMemoryProperties));
 
@@ -239,11 +347,9 @@ VkResult getPhysicalDeviceMemoryProperties (VkPhysicalDevice, VkPhysicalDeviceMe
        props->memoryHeapCount                          = 1u;
        props->memoryHeaps[0].size                      = 1ull << 31;
        props->memoryHeaps[0].flags                     = 0u;
-
-       return VK_SUCCESS;
 }
 
-VkResult getPhysicalDeviceFormatProperties (VkPhysicalDevice, VkFormat, VkFormatProperties* pFormatProperties)
+void getPhysicalDeviceFormatProperties (VkPhysicalDevice, VkFormat, VkFormatProperties* pFormatProperties)
 {
        const VkFormatFeatureFlags      allFeatures     = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
                                                                                        | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT
@@ -261,28 +367,33 @@ VkResult getPhysicalDeviceFormatProperties (VkPhysicalDevice, VkFormat, VkFormat
        pFormatProperties->linearTilingFeatures         = allFeatures;
        pFormatProperties->optimalTilingFeatures        = allFeatures;
        pFormatProperties->bufferFeatures                       = allFeatures;
-
-       return VK_SUCCESS;
 }
 
-VkResult getBufferMemoryRequirements (VkDevice, VkBuffer bufferHandle, VkMemoryRequirements* requirements)
+void getBufferMemoryRequirements (VkDevice, VkBuffer bufferHandle, VkMemoryRequirements* requirements)
 {
-       const Buffer*   buffer  = reinterpret_cast<Buffer*>(bufferHandle.getInternal());
+       const Buffer*   buffer  = reinterpret_cast<const Buffer*>(bufferHandle.getInternal());
 
        requirements->memoryTypeBits    = 1u;
        requirements->size                              = buffer->getSize();
        requirements->alignment                 = (VkDeviceSize)1u;
+}
 
-       return VK_SUCCESS;
+VkDeviceSize getPackedImageDataSize (VkFormat format, VkExtent3D extent, VkSampleCountFlagBits samples)
+{
+       return (VkDeviceSize)getPixelSize(mapVkFormat(format))
+                       * (VkDeviceSize)extent.width
+                       * (VkDeviceSize)extent.height
+                       * (VkDeviceSize)extent.depth
+                       * (VkDeviceSize)samples;
 }
 
-VkResult getImageMemoryRequirements (VkDevice, VkImage, VkMemoryRequirements* requirements)
+void getImageMemoryRequirements (VkDevice, VkImage imageHandle, VkMemoryRequirements* requirements)
 {
+       const Image*    image   = reinterpret_cast<const Image*>(imageHandle.getInternal());
+
        requirements->memoryTypeBits    = 1u;
-       requirements->size                              = 4u;
        requirements->alignment                 = 4u;
-
-       return VK_SUCCESS;
+       requirements->size                              = getPackedImageDataSize(image->getFormat(), image->getExtent(), image->getSamples());
 }
 
 VkResult mapMemory (VkDevice, VkDeviceMemory memHandle, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData)
@@ -297,13 +408,15 @@ VkResult mapMemory (VkDevice, VkDeviceMemory memHandle, VkDeviceSize offset, VkD
        return VK_SUCCESS;
 }
 
-VkResult allocateDescriptorSets (VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets)
+VkResult allocateDescriptorSets (VkDevice, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets)
 {
+       DescriptorPool* const   poolImpl        = reinterpret_cast<DescriptorPool*>((deUintptr)pAllocateInfo->descriptorPool.getInternal());
+
        for (deUint32 ndx = 0; ndx < pAllocateInfo->setLayoutCount; ++ndx)
        {
                try
                {
-                       pDescriptorSets[ndx] = VkDescriptorSet((deUint64)(deUintptr)new DescriptorSet(device, pAllocateInfo->descriptorPool, pAllocateInfo->pSetLayouts[ndx]));
+                       pDescriptorSets[ndx] = poolImpl->allocate(pAllocateInfo->pSetLayouts[ndx]);
                }
                catch (const std::bad_alloc&)
                {
@@ -324,13 +437,21 @@ VkResult allocateDescriptorSets (VkDevice device, const VkDescriptorSetAllocateI
        return VK_SUCCESS;
 }
 
-void freeDescriptorSets (VkDevice, VkDescriptorPool, deUint32 count, const VkDescriptorSet* pDescriptorSets)
+void freeDescriptorSets (VkDevice, VkDescriptorPool descriptorPool, deUint32 count, const VkDescriptorSet* pDescriptorSets)
 {
+       DescriptorPool* const   poolImpl        = reinterpret_cast<DescriptorPool*>((deUintptr)descriptorPool.getInternal());
+
        for (deUint32 ndx = 0; ndx < count; ++ndx)
-       {
-               // \note: delete cannot fail
-               delete reinterpret_cast<DescriptorSet*>((deUintptr)pDescriptorSets[ndx].getInternal());
-       }
+               poolImpl->free(pDescriptorSets[ndx]);
+}
+
+VkResult resetDescriptorPool (VkDevice, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags)
+{
+       DescriptorPool* const   poolImpl        = reinterpret_cast<DescriptorPool*>((deUintptr)descriptorPool.getInternal());
+
+       poolImpl->reset();
+
+       return VK_SUCCESS;
 }
 
 VkResult allocateCommandBuffers (VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers)
@@ -372,12 +493,12 @@ Device::Device (VkPhysicalDevice, const VkDeviceCreateInfo*)
 class NullDriverLibrary : public Library
 {
 public:
-                                                               NullDriverLibrary (void)
-                                                                       : m_library     (s_platformFunctions, DE_LENGTH_OF_ARRAY(s_platformFunctions))
-                                                                       , m_driver      (m_library)
-                                                               {}
+                                                                               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 PlatformInterface&                        getPlatformInterface    (void) const { return m_driver; }
 
 private:
        const tcu::StaticFunctionLibrary        m_library;
index 6a0db19..fa14c93 100644 (file)
@@ -506,14 +506,6 @@ VkResult mergePipelineCaches (VkDevice device, VkPipelineCache dstCache, deUint3
        return VK_SUCCESS;
 }
 
-VkResult resetDescriptorPool (VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags)
-{
-       DE_UNREF(device);
-       DE_UNREF(descriptorPool);
-       DE_UNREF(flags);
-       return VK_SUCCESS;
-}
-
 void updateDescriptorSets (VkDevice device, deUint32 descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, deUint32 descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies)
 {
        DE_UNREF(device);
index 0149502..ed72536 100644 (file)
@@ -657,6 +657,7 @@ def writeNullDriverImpl (api, filename):
                                "vkMapMemory",
                                "vkAllocateDescriptorSets",
                                "vkFreeDescriptorSets",
+                               "vkResetDescriptorPool",
                                "vkAllocateCommandBuffers",
                                "vkFreeCommandBuffers"
                        ]