From 80ab6a2656b30660734f5ef8decd81b9563eb045 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jarkko=20P=C3=B6yry?= Date: Thu, 30 Jul 2015 15:15:58 -0700 Subject: [PATCH] Allow allocation of non-coherent memory if coherency is not required. 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 | 41 +++++++++++++++++++--- external/vulkancts/framework/vulkan/vkMemUtil.hpp | 33 +++++++++++++++-- .../vulkancts/modules/vulkan/api/vktApiTests.cpp | 6 ++-- 3 files changed, 71 insertions(+), 9 deletions(-) diff --git a/external/vulkancts/framework/vulkan/vkMemUtil.cpp b/external/vulkancts/framework/vulkan/vkMemUtil.cpp index b90eada..446953d 100644 --- a/external/vulkancts/framework/vulkan/vkMemUtil.cpp +++ b/external/vulkancts/framework/vulkan/vkMemUtil.cpp @@ -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 SimpleAllocator::allocate (const VkMemoryAllocInfo& allocInf return MovePtr(new SimpleAllocation(allocMemory(m_vk, m_device, &allocInfo))); } -MovePtr SimpleAllocator::allocate (const VkMemoryRequirements& memReqs, VkMemoryPropertyFlags allocProps) +MovePtr 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; diff --git a/external/vulkancts/framework/vulkan/vkMemUtil.hpp b/external/vulkancts/framework/vulkan/vkMemUtil.hpp index 66109e2..1d3f102 100644 --- a/external/vulkancts/framework/vulkan/vkMemUtil.hpp +++ b/external/vulkancts/framework/vulkan/vkMemUtil.hpp @@ -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 allocate (const VkMemoryAllocInfo& allocInfo, VkDeviceSize alignment) = 0; - virtual de::MovePtr allocate (const VkMemoryRequirements& memRequirements, VkMemoryPropertyFlags allocProps) = 0; + virtual de::MovePtr 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 allocate (const VkMemoryAllocInfo& allocInfo, VkDeviceSize alignment); - de::MovePtr allocate (const VkMemoryRequirements& memRequirements, VkMemoryPropertyFlags allocProps); + de::MovePtr allocate (const VkMemoryRequirements& memRequirements, MemoryRequirement requirement); private: const DeviceInterface& m_vk; diff --git a/external/vulkancts/modules/vulkan/api/vktApiTests.cpp b/external/vulkancts/modules/vulkan/api/vktApiTests.cpp index 0ec765a..2bd0aa7 100644 --- a/external/vulkancts/modules/vulkan/api/vktApiTests.cpp +++ b/external/vulkancts/modules/vulkan/api/vktApiTests.cpp @@ -154,7 +154,7 @@ tcu::TestStatus renderTriangleTest (Context& context) &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; }; const Unique vertexBuffer (createBuffer(vk, vkDevice, &vertexBufferParams)); - const UniquePtr vertexBufferMemory (memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); + const UniquePtr 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 readImageBuffer (createBuffer(vk, vkDevice, &readImageBufferParams)); - const UniquePtr readImageBufferMemory (memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); + const UniquePtr readImageBufferMemory (memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible)); const VkImageCreateInfo imageParams = { @@ -190,7 +190,7 @@ tcu::TestStatus renderTriangleTest (Context& context) }; const Unique image (createImage(vk, vkDevice, &imageParams)); - const UniquePtr imageMemory (memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *image), 0u)); + const UniquePtr imageMemory (memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any)); const VkAttachmentDescription colorAttDesc = { -- 2.7.4