Added a dedicated buffer object class
This commit is contained in:
parent
16d78af7fe
commit
dafc4da14a
2 changed files with 197 additions and 0 deletions
148
base/vulkanbuffer.hpp
Normal file
148
base/vulkanbuffer.hpp
Normal file
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
* Vulkan buffer class
|
||||||
|
*
|
||||||
|
* Encapsulates a Vulkan buffer
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
|
||||||
|
*
|
||||||
|
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "vulkan/vulkan.h"
|
||||||
|
#include "vulkantools.h"
|
||||||
|
|
||||||
|
namespace vk
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Encapsulates access to a Vulkan buffer backed up by device memory
|
||||||
|
* @note To be filled by an external source like the VulkanDevice
|
||||||
|
*/
|
||||||
|
struct Buffer
|
||||||
|
{
|
||||||
|
VkBuffer buffer;
|
||||||
|
VkDevice device;
|
||||||
|
VkDeviceMemory memory;
|
||||||
|
VkDescriptorBufferInfo descriptor;
|
||||||
|
VkDeviceSize size = 0;
|
||||||
|
VkDeviceSize alignment = 0;
|
||||||
|
void* mapped = nullptr;
|
||||||
|
|
||||||
|
/** @brief Usage flags to be filled by external source at buffer creation (to query at some later point) */
|
||||||
|
VkBufferUsageFlags usageFlags;
|
||||||
|
/** @brief Memory propertys flags to be filled by external source at buffer creation (to query at some later point) */
|
||||||
|
VkMemoryPropertyFlags memoryPropertyFlags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map a memory range of this buffer. If successful, mapped points to the specified buffer range.
|
||||||
|
*
|
||||||
|
* @param size (Optional) Size of the memory range to map. Pass VK_WHOLE_SIZE to map the complete buffer range.
|
||||||
|
* @param offset (Optional) Byte offset from beginning
|
||||||
|
*
|
||||||
|
* @return VkResult of the buffer mapping call
|
||||||
|
*/
|
||||||
|
VkResult map(VkDeviceSize size = VK_WHOLE_SIZE, VkDeviceSize offset = 0)
|
||||||
|
{
|
||||||
|
return vkMapMemory(device, memory, offset, size, 0, &mapped);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unmap a mapped memory range
|
||||||
|
*
|
||||||
|
* @note Does not return a result as vkUnmapMemory can't fail
|
||||||
|
*/
|
||||||
|
void unmap()
|
||||||
|
{
|
||||||
|
if (mapped)
|
||||||
|
{
|
||||||
|
vkUnmapMemory(device, memory);
|
||||||
|
mapped = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach the allocated memory block to the buffer
|
||||||
|
*
|
||||||
|
* @param offset (Optional) Byte offset (from the beginning) for the memory region to bind
|
||||||
|
*
|
||||||
|
* @return VkResult of the bindBufferMemory call
|
||||||
|
*/
|
||||||
|
VkResult bind(VkDeviceSize offset = 0)
|
||||||
|
{
|
||||||
|
return vkBindBufferMemory(device, buffer, memory, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup the default descriptor for this buffer
|
||||||
|
*
|
||||||
|
* @param size (Optional) Size of the memory range of the descriptor
|
||||||
|
* @param offset (Optional) Byte offset from beginning
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void setupDescriptor(VkDeviceSize size = VK_WHOLE_SIZE, VkDeviceSize offset = 0)
|
||||||
|
{
|
||||||
|
descriptor.offset = offset;
|
||||||
|
descriptor.buffer = buffer;
|
||||||
|
descriptor.range = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush a memory range of the buffer to make it visible to the device
|
||||||
|
*
|
||||||
|
* @note Only required for non-coherent memory
|
||||||
|
*
|
||||||
|
* @param size (Optional) Size of the memory range to flush. Pass VK_WHOLE_SIZE to flush the complete buffer range.
|
||||||
|
* @param offset (Optional) Byte offset from beginning
|
||||||
|
*
|
||||||
|
* @return VkResult of the flush call
|
||||||
|
*/
|
||||||
|
VkResult flush(VkDeviceSize size = VK_WHOLE_SIZE, VkDeviceSize offset = 0)
|
||||||
|
{
|
||||||
|
VkMappedMemoryRange mappedRange = {};
|
||||||
|
mappedRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
|
||||||
|
mappedRange.memory = memory;
|
||||||
|
mappedRange.offset = offset;
|
||||||
|
mappedRange.size = size;
|
||||||
|
return vkFlushMappedMemoryRanges(device, 1, &mappedRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate a memory range of the buffer to make it visible to the host
|
||||||
|
*
|
||||||
|
* @note Only required for non-coherent memory
|
||||||
|
*
|
||||||
|
* @param size (Optional) Size of the memory range to invalidate. Pass VK_WHOLE_SIZE to invalidate the complete buffer range.
|
||||||
|
* @param offset (Optional) Byte offset from beginning
|
||||||
|
*
|
||||||
|
* @return VkResult of the invalidate call
|
||||||
|
*/
|
||||||
|
VkResult invalidate(VkDeviceSize size = VK_WHOLE_SIZE, VkDeviceSize offset = 0)
|
||||||
|
{
|
||||||
|
VkMappedMemoryRange mappedRange = {};
|
||||||
|
mappedRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
|
||||||
|
mappedRange.memory = memory;
|
||||||
|
mappedRange.offset = offset;
|
||||||
|
mappedRange.size = size;
|
||||||
|
return vkInvalidateMappedMemoryRanges(device, 1, &mappedRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release all Vulkan resources held by this buffer
|
||||||
|
*/
|
||||||
|
void destroy()
|
||||||
|
{
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
vkDestroyBuffer(device, buffer, nullptr);
|
||||||
|
}
|
||||||
|
if (memory)
|
||||||
|
{
|
||||||
|
vkFreeMemory(device, memory, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include "vulkan/vulkan.h"
|
#include "vulkan/vulkan.h"
|
||||||
#include "vulkantools.h"
|
#include "vulkantools.h"
|
||||||
|
#include "vulkanbuffer.hpp"
|
||||||
|
|
||||||
namespace vk
|
namespace vk
|
||||||
{
|
{
|
||||||
|
|
@ -158,5 +159,53 @@ namespace vk
|
||||||
|
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a buffer on the device
|
||||||
|
*
|
||||||
|
* @param usageFlags Usage flag bitmask for the buffer (i.e. index, vertex, uniform buffer)
|
||||||
|
* @param memoryPropertyFlags Memory properties for this buffer (i.e. device local, host visible, coherent)
|
||||||
|
* @param buffer Pointer to a vk::Vulkan buffer object
|
||||||
|
* @param size Size of the buffer in byes
|
||||||
|
* @param data Pointer to the data that should be copied to the buffer after creation (optional, if not set, no data is copied over)
|
||||||
|
*
|
||||||
|
* @return VK_SUCCESS if buffer handle and memory have been created and (optionally passed) data has been copied
|
||||||
|
*/
|
||||||
|
VkResult createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, vk::Buffer *buffer, VkDeviceSize size, void *data = nullptr)
|
||||||
|
{
|
||||||
|
buffer->device = device;
|
||||||
|
|
||||||
|
// Create the buffer handle
|
||||||
|
VkBufferCreateInfo bufferCreateInfo = vkTools::initializers::bufferCreateInfo(usageFlags, size);
|
||||||
|
VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &buffer->buffer));
|
||||||
|
|
||||||
|
// Create the memory backing up the buffer handle
|
||||||
|
VkMemoryRequirements memReqs;
|
||||||
|
VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo();
|
||||||
|
vkGetBufferMemoryRequirements(device, buffer->buffer, &memReqs);
|
||||||
|
memAlloc.allocationSize = memReqs.size;
|
||||||
|
// Find a memory type index that fits the properties of the buffer
|
||||||
|
memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags);
|
||||||
|
VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &buffer->memory));
|
||||||
|
|
||||||
|
buffer->alignment = memReqs.alignment;
|
||||||
|
buffer->size = memAlloc.allocationSize;
|
||||||
|
buffer->usageFlags = usageFlags;
|
||||||
|
buffer->memoryPropertyFlags = memoryPropertyFlags;
|
||||||
|
|
||||||
|
// If a pointer to the buffer data has been passed, map the buffer and copy over the data
|
||||||
|
if (data != nullptr)
|
||||||
|
{
|
||||||
|
VK_CHECK_RESULT(buffer->map());
|
||||||
|
memcpy(buffer->mapped, data, size);
|
||||||
|
buffer->unmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize a default descriptor that covers the whole buffer size
|
||||||
|
buffer->setupDescriptor();
|
||||||
|
|
||||||
|
// Attach the memory to the buffer object
|
||||||
|
return buffer->bind();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue