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;
}
{
}
+// 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
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;
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
{
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
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;
&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 =
&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 =
{
};
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 =
{