VulkanDevice refactoring

This commit is contained in:
saschawillems 2016-07-22 20:45:48 +02:00
parent 109d3e718d
commit 2e6e9d5eb2
10 changed files with 83 additions and 60 deletions

View file

@ -289,7 +289,7 @@ public:
// Loads the mesh with some default flags
bool LoadMesh(const std::string& filename)
{
int flags = aiProcess_FlipWindingOrder | aiProcess_Triangulate | aiProcess_PreTransformVertices | aiProcess_CalcTangentSpace | aiProcess_GenSmoothNormals;
int flags = aiProcess_FlipWindingOrder | aiProcess_Triangulate/* | aiProcess_PreTransformVertices*/ | aiProcess_CalcTangentSpace | aiProcess_GenSmoothNormals;
return LoadMesh(filename, flags);
}
@ -615,10 +615,10 @@ public:
VK_CHECK_RESULT(vkQueueSubmit(copyQueue, 1, &submitInfo, VK_NULL_HANDLE));
VK_CHECK_RESULT(vkQueueWaitIdle(copyQueue));
vkDestroyBuffer(vulkanDevice->device, vertexStaging.buffer, nullptr);
vkFreeMemory(vulkanDevice->device, vertexStaging.memory, nullptr);
vkDestroyBuffer(vulkanDevice->device, indexStaging.buffer, nullptr);
vkFreeMemory(vulkanDevice->device, indexStaging.memory, nullptr);
vkDestroyBuffer(vulkanDevice->logicalDevice, vertexStaging.buffer, nullptr);
vkFreeMemory(vulkanDevice->logicalDevice, vertexStaging.memory, nullptr);
vkDestroyBuffer(vulkanDevice->logicalDevice, indexStaging.buffer, nullptr);
vkFreeMemory(vulkanDevice->logicalDevice, indexStaging.memory, nullptr);
}
else
{

View file

@ -22,7 +22,7 @@ namespace vk
/** @brief Physical device representation */
VkPhysicalDevice physicalDevice;
/** @brief Logical device representation (application's view of the device) */
VkDevice device;
VkDevice logicalDevice;
/** @brief Properties of the physical device including limits that the application can check against */
VkPhysicalDeviceProperties properties;
/** @brief Features of the physical device that an application can use to check if a feature is supported */
@ -34,7 +34,39 @@ namespace vk
bool enableDebugMarkers = false;
/**
* Return the index of a memory type that has all the requested property bits set
* Default constructor
*
* @param physicalDevice Phyiscal device that is to be used
*/
VulkanDevice(VkPhysicalDevice physicalDevice)
{
assert(physicalDevice);
this->physicalDevice = physicalDevice;
// Store Properties features, limits and properties of the physical device for later use
// Device properties also contain limits and sparse properties
vkGetPhysicalDeviceProperties(physicalDevice, &properties);
// Features should be checked by the examples before using them
vkGetPhysicalDeviceFeatures(physicalDevice, &features);
// Memory properties are used regularly for creating all kinds of buffer
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);
}
/**
* Default destructor
*
* @note Frees the logical device
*/
~VulkanDevice()
{
if (logicalDevice)
{
vkDestroyDevice(logicalDevice, nullptr);
}
}
/**
* Get the index of a memory type that has all the requested property bits set
*
* @param typeBits Bitmask with bits set for each memory type supported by the resource to request for (from VkMemoryRequirements)
* @param properties Bitmask of properties for the memory type to request
@ -61,32 +93,21 @@ namespace vk
//todo : Exceptions are disabled by default on Android (need to add LOCAL_CPP_FEATURES += exceptions to Android.mk), so for now just return zero
return 0;
#else
throw "Could not find a memory type for the passed properties";
throw std::runtime_error("Could not find a matching memory type");
#endif
}
/**
* Create the logical device based on the passed physical device
* Create the logical device based on the assigned physical device
*
* @param physicalDevice The physical device for which the logical reprenstation is to be created
* @param queueCreateInfos A vector containing queue create infos for all queues to be requested on the device
* @param enabledFeatures Can be used to enable certain features upon device creation
* @param useSwapChain Set to false for headless rendering to omit the swapchain device extensions
*
* @return VkResult of the device creation call
*/
VkResult create(VkPhysicalDevice physicalDevice, std::vector<VkDeviceQueueCreateInfo> &queueCreateInfos, VkPhysicalDeviceFeatures enabledFeatures, bool useSwapChain = true)
VkResult createLogicalDevice(std::vector<VkDeviceQueueCreateInfo> &queueCreateInfos, VkPhysicalDeviceFeatures enabledFeatures, bool useSwapChain = true)
{
this->physicalDevice = physicalDevice;
// Store Properties features, limits and properties of the physical device for later use
// Device properties also contain limits and sparse properties
vkGetPhysicalDeviceProperties(physicalDevice, &properties);
// Features should be checked by the examples before using them
vkGetPhysicalDeviceFeatures(physicalDevice, &features);
// Memory properties are used regularly for creating all kinds of buffer
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);
// Create the logical device representation
std::vector<const char*> deviceExtensions;
if (useSwapChain)
@ -115,7 +136,7 @@ namespace vk
deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data();
}
return vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device);
return vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &logicalDevice);
}
/**
@ -134,28 +155,28 @@ namespace vk
{
// Create the buffer handle
VkBufferCreateInfo bufferCreateInfo = vkTools::initializers::bufferCreateInfo(usageFlags, size);
VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, buffer));
VK_CHECK_RESULT(vkCreateBuffer(logicalDevice, &bufferCreateInfo, nullptr, buffer));
// Create the memory backing up the buffer handle
VkMemoryRequirements memReqs;
VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo();
vkGetBufferMemoryRequirements(device, *buffer, &memReqs);
vkGetBufferMemoryRequirements(logicalDevice, *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, memory));
VK_CHECK_RESULT(vkAllocateMemory(logicalDevice, &memAlloc, nullptr, memory));
// If a pointer to the buffer data has been passed, map the buffer and copy over the data
if (data != nullptr)
{
void *mapped;
VK_CHECK_RESULT(vkMapMemory(device, *memory, 0, size, 0, &mapped));
VK_CHECK_RESULT(vkMapMemory(logicalDevice, *memory, 0, size, 0, &mapped));
memcpy(mapped, data, size);
vkUnmapMemory(device, *memory);
vkUnmapMemory(logicalDevice, *memory);
}
// Attach the memory to the buffer object
VK_CHECK_RESULT(vkBindBufferMemory(device, *buffer, *memory, 0));
VK_CHECK_RESULT(vkBindBufferMemory(logicalDevice, *buffer, *memory, 0));
return VK_SUCCESS;
}
@ -173,20 +194,20 @@ namespace vk
*/
VkResult createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, vk::Buffer *buffer, VkDeviceSize size, void *data = nullptr)
{
buffer->device = device;
buffer->device = logicalDevice;
// Create the buffer handle
VkBufferCreateInfo bufferCreateInfo = vkTools::initializers::bufferCreateInfo(usageFlags, size);
VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &buffer->buffer));
VK_CHECK_RESULT(vkCreateBuffer(logicalDevice, &bufferCreateInfo, nullptr, &buffer->buffer));
// Create the memory backing up the buffer handle
VkMemoryRequirements memReqs;
VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo();
vkGetBufferMemoryRequirements(device, buffer->buffer, &memReqs);
vkGetBufferMemoryRequirements(logicalDevice, 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));
VK_CHECK_RESULT(vkAllocateMemory(logicalDevice, &memAlloc, nullptr, &buffer->memory));
buffer->alignment = memReqs.alignment;
buffer->size = memAlloc.allocationSize;

View file

@ -346,7 +346,7 @@ void VulkanExampleBase::loadMesh(std::string filename, vkMeshLoader::MeshBuffer
void VulkanExampleBase::loadMesh(std::string filename, vkMeshLoader::MeshBuffer * meshBuffer, std::vector<vkMeshLoader::VertexLayout> vertexLayout, vkMeshLoader::MeshCreateInfo *meshCreateInfo)
{
VulkanMeshLoader *mesh = new VulkanMeshLoader(&vulkanDevice);
VulkanMeshLoader *mesh = new VulkanMeshLoader(vulkanDevice);
#if defined(__ANDROID__)
mesh->assetManager = androidApp->activity->assetManager;
@ -759,7 +759,7 @@ VulkanExampleBase::~VulkanExampleBase()
delete textOverlay;
}
vkDestroyDevice(device, nullptr);
delete vulkanDevice;
if (enableValidation)
{
@ -812,6 +812,8 @@ void VulkanExampleBase::initVulkan(bool enableValidation)
// and want to use another one
physicalDevice = physicalDevices[0];
vulkanDevice = new vk::VulkanDevice(physicalDevice);
// Find a queue that supports graphics operations
uint32_t graphicsQueueIndex = 0;
uint32_t queueCount;
@ -841,10 +843,10 @@ void VulkanExampleBase::initVulkan(bool enableValidation)
queueCreateInfos[0].queueCount = 1;
queueCreateInfos[0].pQueuePriorities = queuePriorities.data();
VK_CHECK_RESULT(vulkanDevice.create(physicalDevice, queueCreateInfos, enabledFeatures));
VK_CHECK_RESULT(vulkanDevice->createLogicalDevice(queueCreateInfos, enabledFeatures));
// Assign device to base class context
device = vulkanDevice.device;
device = vulkanDevice->logicalDevice;
// Store properties (including limits) and features of the phyiscal device
// So examples can check against them and see if a feature is actually supported

View file

@ -97,7 +97,7 @@ protected:
// todo: getter? should always point to VulkanDevice->device
VkDevice device;
/** @brief Encapsulated physical and logical vulkan device */
vk::VulkanDevice vulkanDevice;
vk::VulkanDevice *vulkanDevice;
// Handle to the device graphics queue that command buffers are submitted to
VkQueue queue;
// Color buffer format

View file

@ -116,13 +116,13 @@ namespace vk
assert(vulkanDevice);
for (auto attachment : attachments)
{
vkDestroyImage(vulkanDevice->device, attachment.image, nullptr);
vkDestroyImageView(vulkanDevice->device, attachment.view, nullptr);
vkFreeMemory(vulkanDevice->device, attachment.memory, nullptr);
vkDestroyImage(vulkanDevice->logicalDevice, attachment.image, nullptr);
vkDestroyImageView(vulkanDevice->logicalDevice, attachment.view, nullptr);
vkFreeMemory(vulkanDevice->logicalDevice, attachment.memory, nullptr);
}
vkDestroySampler(vulkanDevice->device, sampler, nullptr);
vkDestroyRenderPass(vulkanDevice->device, renderPass, nullptr);
vkDestroyFramebuffer(vulkanDevice->device, framebuffer, nullptr);
vkDestroySampler(vulkanDevice->logicalDevice, sampler, nullptr);
vkDestroyRenderPass(vulkanDevice->logicalDevice, renderPass, nullptr);
vkDestroyFramebuffer(vulkanDevice->logicalDevice, framebuffer, nullptr);
}
/**
@ -185,12 +185,12 @@ namespace vk
VkMemoryRequirements memReqs;
// Create image for this attachment
VK_CHECK_RESULT(vkCreateImage(vulkanDevice->device, &image, nullptr, &attachment.image));
vkGetImageMemoryRequirements(vulkanDevice->device, attachment.image, &memReqs);
VK_CHECK_RESULT(vkCreateImage(vulkanDevice->logicalDevice, &image, nullptr, &attachment.image));
vkGetImageMemoryRequirements(vulkanDevice->logicalDevice, attachment.image, &memReqs);
memAlloc.allocationSize = memReqs.size;
memAlloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VK_CHECK_RESULT(vkAllocateMemory(vulkanDevice->device, &memAlloc, nullptr, &attachment.memory));
VK_CHECK_RESULT(vkBindImageMemory(vulkanDevice->device, attachment.image, attachment.memory, 0));
VK_CHECK_RESULT(vkAllocateMemory(vulkanDevice->logicalDevice, &memAlloc, nullptr, &attachment.memory));
VK_CHECK_RESULT(vkBindImageMemory(vulkanDevice->logicalDevice, attachment.image, attachment.memory, 0));
attachment.subresourceRange = {};
attachment.subresourceRange.aspectMask = aspectMask;
@ -214,7 +214,7 @@ namespace vk
//todo: workaround for depth+stencil attachments
imageView.subresourceRange.aspectMask = (attachment.hasDepth()) ? VK_IMAGE_ASPECT_DEPTH_BIT : aspectMask;
imageView.image = attachment.image;
VK_CHECK_RESULT(vkCreateImageView(vulkanDevice->device, &imageView, nullptr, &attachment.view));
VK_CHECK_RESULT(vkCreateImageView(vulkanDevice->logicalDevice, &imageView, nullptr, &attachment.view));
// Fill attachment description
attachment.description = {};
@ -264,7 +264,7 @@ namespace vk
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = 1.0f;
samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
return vkCreateSampler(vulkanDevice->device, &samplerInfo, nullptr, &sampler);
return vkCreateSampler(vulkanDevice->logicalDevice, &samplerInfo, nullptr, &sampler);
}
/**
@ -326,7 +326,7 @@ namespace vk
renderPassInfo.attachmentCount = static_cast<uint32_t>(attachmentDescriptions.size());
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
VK_CHECK_RESULT(vkCreateRenderPass(vulkanDevice->device, &renderPassInfo, nullptr, &renderPass));
VK_CHECK_RESULT(vkCreateRenderPass(vulkanDevice->logicalDevice, &renderPassInfo, nullptr, &renderPass));
std::vector<VkImageView> attachmentViews;
for (auto attachment : attachments)
@ -352,7 +352,7 @@ namespace vk
framebufferInfo.width = width;
framebufferInfo.height = height;
framebufferInfo.layers = maxLayers;
VK_CHECK_RESULT(vkCreateFramebuffer(vulkanDevice->device, &framebufferInfo, nullptr, &framebuffer));
VK_CHECK_RESULT(vkCreateFramebuffer(vulkanDevice->logicalDevice, &framebufferInfo, nullptr, &framebuffer));
return VK_SUCCESS;
}

View file

@ -585,7 +585,7 @@ public:
// Load a model file as separate meshes into a scene
void loadModel(std::string filename, Scene *scene)
{
VulkanMeshLoader *meshLoader = new VulkanMeshLoader(&vulkanDevice);
VulkanMeshLoader *meshLoader = new VulkanMeshLoader(vulkanDevice);
#if defined(__ANDROID__)
meshLoader->assetManager = androidApp->activity->assetManager;
#endif

View file

@ -247,7 +247,7 @@ public:
{
VkCommandBuffer layoutCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
frameBuffers.shadow = new vk::Framebuffer(&vulkanDevice);
frameBuffers.shadow = new vk::Framebuffer(vulkanDevice);
frameBuffers.shadow->width = SHADOWMAP_DIM;
frameBuffers.shadow->height = SHADOWMAP_DIM;
@ -279,7 +279,7 @@ public:
{
VkCommandBuffer layoutCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
frameBuffers.deferred = new vk::Framebuffer(&vulkanDevice);
frameBuffers.deferred = new vk::Framebuffer(vulkanDevice);
frameBuffers.deferred->width = FB_DIM;
frameBuffers.deferred->height = FB_DIM;

View file

@ -175,7 +175,7 @@ public:
// The other example will use the VulkanMesh loader which has some additional functionality for loading meshes
void loadMesh()
{
VulkanMeshLoader *meshLoader = new VulkanMeshLoader(&vulkanDevice);
VulkanMeshLoader *meshLoader = new VulkanMeshLoader(vulkanDevice);
#if defined(__ANDROID__)
meshLoader->assetManager = androidApp->activity->assetManager;
#endif

View file

@ -482,7 +482,7 @@ public:
void loadMesh()
{
skinnedMesh = new SkinnedMesh();
skinnedMesh->meshLoader = new VulkanMeshLoader(&vulkanDevice);
skinnedMesh->meshLoader = new VulkanMeshLoader(vulkanDevice);
#if defined(__ANDROID__)
skinnedMesh->meshLoader->assetManager = androidApp->activity->assetManager;
#endif

View file

@ -182,10 +182,10 @@ public:
};
// Load meshes for demos scene
demoMeshes.logos = new VulkanMeshLoader(&vulkanDevice);
demoMeshes.background = new VulkanMeshLoader(&vulkanDevice);
demoMeshes.models = new VulkanMeshLoader(&vulkanDevice);
demoMeshes.skybox = new VulkanMeshLoader(&vulkanDevice);
demoMeshes.logos = new VulkanMeshLoader(vulkanDevice);
demoMeshes.background = new VulkanMeshLoader(vulkanDevice);
demoMeshes.models = new VulkanMeshLoader(vulkanDevice);
demoMeshes.skybox = new VulkanMeshLoader(vulkanDevice);
#if defined(__ANDROID__)
demoMeshes.logos->assetManager = androidApp->activity->assetManager;