Allow allocation of non-coherent memory if coherency is not required.
authorJarkko Pöyry <jpoyry@google.com>
Thu, 30 Jul 2015 22:15:58 +0000 (15:15 -0700)
committerJarkko Pöyry <jpoyry@google.com>
Thu, 30 Jul 2015 23:52:25 +0000 (16:52 -0700)
Use MemoryRequirement instead of VkMemoryProperty flags as allocation
requirement. This allows specifying memory that is allowed to be
coherent but it is not required. This is not possible with the vk mask
since in vulkan non-coherence (instead of coherence) is a feature
of the memory.

Change-Id: Iab50a6264599c8c50f4c5008e95b9c9429d264db

external/vulkancts/framework/vulkan/vkMemUtil.cpp
external/vulkancts/framework/vulkan/vkMemUtil.hpp
external/vulkancts/modules/vulkan/api/vktApiTests.cpp

index b90eada..446953d 100644 (file)
@@ -49,12 +49,12 @@ using de::MovePtr;
 namespace
 {
 
-deUint32 selectMemoryTypeWithProperties (const VkPhysicalDeviceMemoryProperties& deviceMemProps, deUint32 allowedMemTypeBits, VkMemoryPropertyFlags allocProps)
+deUint32 selectMatchingMemoryType (const VkPhysicalDeviceMemoryProperties& deviceMemProps, deUint32 allowedMemTypeBits, MemoryRequirement requirement)
 {
        for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < deviceMemProps.memoryTypeCount; memoryTypeNdx++)
        {
                if ((allowedMemTypeBits & (1u << memoryTypeNdx)) != 0 &&
-                       (deviceMemProps.memoryTypes[memoryTypeNdx].propertyFlags & allocProps) == allocProps)
+                       requirement.matchesHeap(deviceMemProps.memoryTypes[memoryTypeNdx].propertyFlags))
                        return memoryTypeNdx;
        }
 
@@ -75,6 +75,39 @@ Allocation::~Allocation (void)
 {
 }
 
+// MemoryRequirement
+
+const MemoryRequirement MemoryRequirement::Any                         = MemoryRequirement(0x0u);
+const MemoryRequirement MemoryRequirement::HostVisible         = MemoryRequirement(MemoryRequirement::FLAG_HOST_VISIBLE);
+const MemoryRequirement MemoryRequirement::Coherent                    = MemoryRequirement(MemoryRequirement::FLAG_COHERENT);
+const MemoryRequirement MemoryRequirement::LazilyAllocated     = MemoryRequirement(MemoryRequirement::FLAG_LAZY_ALLOCATION);
+
+bool MemoryRequirement::matchesHeap (VkMemoryPropertyFlags heapFlags) const
+{
+       // host-visible
+       if ((m_flags & FLAG_HOST_VISIBLE) && !(heapFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
+               return false;
+
+       // coherent
+       if ((m_flags & FLAG_COHERENT) && (heapFlags & VK_MEMORY_PROPERTY_HOST_NON_COHERENT_BIT))
+               return false;
+
+       // lazy
+       if ((m_flags & FLAG_LAZY_ALLOCATION) && !(heapFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT))
+               return false;
+
+       return true;
+}
+
+MemoryRequirement::MemoryRequirement (deUint32 flags)
+       : m_flags(flags)
+{
+       if ((flags & FLAG_COHERENT) && !(flags & FLAG_HOST_VISIBLE))
+               DE_FATAL("Coherent memory must be host-visible");
+       if ((flags & FLAG_HOST_VISIBLE) && (flags & FLAG_LAZY_ALLOCATION))
+               DE_FATAL("Lazily allocated memory cannot be mappable");
+}
+
 // SimpleAllocator
 
 class SimpleAllocation : public Allocation
@@ -110,9 +143,9 @@ MovePtr<Allocation> SimpleAllocator::allocate (const VkMemoryAllocInfo& allocInf
        return MovePtr<Allocation>(new SimpleAllocation(allocMemory(m_vk, m_device, &allocInfo)));
 }
 
-MovePtr<Allocation> SimpleAllocator::allocate (const VkMemoryRequirements& memReqs, VkMemoryPropertyFlags allocProps)
+MovePtr<Allocation> SimpleAllocator::allocate (const VkMemoryRequirements& memReqs, MemoryRequirement requirement)
 {
-       const deUint32                  memoryTypeNdx   = selectMemoryTypeWithProperties(m_memProps, memReqs.memoryTypeBits, allocProps);
+       const deUint32                  memoryTypeNdx   = selectMatchingMemoryType(m_memProps, memReqs.memoryTypeBits, requirement);
        const VkMemoryAllocInfo allocInfo       =
        {
                VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO,    //      VkStructureType                 sType;
index 66109e2..1d3f102 100644 (file)
@@ -57,6 +57,35 @@ private:
        const VkDeviceSize              m_offset;
 };
 
+//! Memory allocation requirements
+class MemoryRequirement
+{
+public:
+       static const MemoryRequirement  Any;
+       static const MemoryRequirement  HostVisible;
+       static const MemoryRequirement  Coherent;
+       static const MemoryRequirement  LazilyAllocated;
+
+       inline MemoryRequirement                operator|                       (MemoryRequirement requirement) const
+       {
+               return MemoryRequirement(m_flags | requirement.m_flags);
+       }
+
+       bool                                                    matchesHeap                     (VkMemoryPropertyFlags heapFlags) const;
+
+private:
+       explicit                                                MemoryRequirement       (deUint32 flags);
+
+       const deUint32                                  m_flags;
+
+       enum Flags
+       {
+               FLAG_HOST_VISIBLE               = 1u << 0u,
+               FLAG_COHERENT                   = 1u << 1u,
+               FLAG_LAZY_ALLOCATION    = 1u << 2u,
+       };
+};
+
 //! Memory allocator interface
 class Allocator
 {
@@ -65,7 +94,7 @@ public:
        virtual                                                 ~Allocator      (void) {}
 
        virtual de::MovePtr<Allocation> allocate        (const VkMemoryAllocInfo& allocInfo, VkDeviceSize alignment) = 0;
-       virtual de::MovePtr<Allocation> allocate        (const VkMemoryRequirements& memRequirements, VkMemoryPropertyFlags allocProps) = 0;
+       virtual de::MovePtr<Allocation> allocate        (const VkMemoryRequirements& memRequirements, MemoryRequirement requirement) = 0;
 };
 
 //! Allocator that backs every allocation with its own VkDeviceMemory
@@ -75,7 +104,7 @@ public:
                                                                                        SimpleAllocator (const DeviceInterface& vk, VkDevice device, const VkPhysicalDeviceMemoryProperties& deviceMemProps);
 
        de::MovePtr<Allocation>                                 allocate                (const VkMemoryAllocInfo& allocInfo, VkDeviceSize alignment);
-       de::MovePtr<Allocation>                                 allocate                (const VkMemoryRequirements& memRequirements, VkMemoryPropertyFlags allocProps);
+       de::MovePtr<Allocation>                                 allocate                (const VkMemoryRequirements& memRequirements, MemoryRequirement requirement);
 
 private:
        const DeviceInterface&                                  m_vk;
index 0ec765a..2bd0aa7 100644 (file)
@@ -154,7 +154,7 @@ tcu::TestStatus renderTriangleTest (Context& context)
                &queueFamilyIndex,                                              //      const deUint32*         pQueueFamilyIndices;
        };
        const Unique<VkBuffer>                                  vertexBuffer                    (createBuffer(vk, vkDevice, &vertexBufferParams));
-       const UniquePtr<Allocation>                             vertexBufferMemory              (memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
+       const UniquePtr<Allocation>                             vertexBufferMemory              (memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible));
 
        const VkDeviceSize                                              imageSizeBytes                  = (VkDeviceSize)(sizeof(deUint32)*renderSize.x()*renderSize.y());
        const VkBufferCreateInfo                                readImageBufferParams   =
@@ -169,7 +169,7 @@ tcu::TestStatus renderTriangleTest (Context& context)
                &queueFamilyIndex,                                                      //      const deUint32*         pQueueFamilyIndices;
        };
        const Unique<VkBuffer>                                  readImageBuffer                 (createBuffer(vk, vkDevice, &readImageBufferParams));
-       const UniquePtr<Allocation>                             readImageBufferMemory   (memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
+       const UniquePtr<Allocation>                             readImageBufferMemory   (memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
 
        const VkImageCreateInfo                                 imageParams                             =
        {
@@ -190,7 +190,7 @@ tcu::TestStatus renderTriangleTest (Context& context)
        };
 
        const Unique<VkImage>                                   image                                   (createImage(vk, vkDevice, &imageParams));
-       const UniquePtr<Allocation>                             imageMemory                             (memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *image), 0u));
+       const UniquePtr<Allocation>                             imageMemory                             (memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any));
 
        const VkAttachmentDescription                   colorAttDesc                    =
        {