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 // Loads the mesh with some default flags
bool LoadMesh(const std::string& filename) 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); return LoadMesh(filename, flags);
} }
@ -615,10 +615,10 @@ public:
VK_CHECK_RESULT(vkQueueSubmit(copyQueue, 1, &submitInfo, VK_NULL_HANDLE)); VK_CHECK_RESULT(vkQueueSubmit(copyQueue, 1, &submitInfo, VK_NULL_HANDLE));
VK_CHECK_RESULT(vkQueueWaitIdle(copyQueue)); VK_CHECK_RESULT(vkQueueWaitIdle(copyQueue));
vkDestroyBuffer(vulkanDevice->device, vertexStaging.buffer, nullptr); vkDestroyBuffer(vulkanDevice->logicalDevice, vertexStaging.buffer, nullptr);
vkFreeMemory(vulkanDevice->device, vertexStaging.memory, nullptr); vkFreeMemory(vulkanDevice->logicalDevice, vertexStaging.memory, nullptr);
vkDestroyBuffer(vulkanDevice->device, indexStaging.buffer, nullptr); vkDestroyBuffer(vulkanDevice->logicalDevice, indexStaging.buffer, nullptr);
vkFreeMemory(vulkanDevice->device, indexStaging.memory, nullptr); vkFreeMemory(vulkanDevice->logicalDevice, indexStaging.memory, nullptr);
} }
else else
{ {

View file

@ -22,7 +22,7 @@ namespace vk
/** @brief Physical device representation */ /** @brief Physical device representation */
VkPhysicalDevice physicalDevice; VkPhysicalDevice physicalDevice;
/** @brief Logical device representation (application's view of the device) */ /** @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 */ /** @brief Properties of the physical device including limits that the application can check against */
VkPhysicalDeviceProperties properties; VkPhysicalDeviceProperties properties;
/** @brief Features of the physical device that an application can use to check if a feature is supported */ /** @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; 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 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 * @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 //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; return 0;
#else #else
throw "Could not find a memory type for the passed properties"; throw std::runtime_error("Could not find a matching memory type");
#endif #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 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 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 * @param useSwapChain Set to false for headless rendering to omit the swapchain device extensions
* *
* @return VkResult of the device creation call * @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 // Create the logical device representation
std::vector<const char*> deviceExtensions; std::vector<const char*> deviceExtensions;
if (useSwapChain) if (useSwapChain)
@ -115,7 +136,7 @@ namespace vk
deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data(); 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 // Create the buffer handle
VkBufferCreateInfo bufferCreateInfo = vkTools::initializers::bufferCreateInfo(usageFlags, size); 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 // Create the memory backing up the buffer handle
VkMemoryRequirements memReqs; VkMemoryRequirements memReqs;
VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo(); VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo();
vkGetBufferMemoryRequirements(device, *buffer, &memReqs); vkGetBufferMemoryRequirements(logicalDevice, *buffer, &memReqs);
memAlloc.allocationSize = memReqs.size; memAlloc.allocationSize = memReqs.size;
// Find a memory type index that fits the properties of the buffer // Find a memory type index that fits the properties of the buffer
memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags); 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 a pointer to the buffer data has been passed, map the buffer and copy over the data
if (data != nullptr) if (data != nullptr)
{ {
void *mapped; 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); memcpy(mapped, data, size);
vkUnmapMemory(device, *memory); vkUnmapMemory(logicalDevice, *memory);
} }
// Attach the memory to the buffer object // 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; return VK_SUCCESS;
} }
@ -173,20 +194,20 @@ namespace vk
*/ */
VkResult createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, vk::Buffer *buffer, VkDeviceSize size, void *data = nullptr) VkResult createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, vk::Buffer *buffer, VkDeviceSize size, void *data = nullptr)
{ {
buffer->device = device; buffer->device = logicalDevice;
// Create the buffer handle // Create the buffer handle
VkBufferCreateInfo bufferCreateInfo = vkTools::initializers::bufferCreateInfo(usageFlags, size); 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 // Create the memory backing up the buffer handle
VkMemoryRequirements memReqs; VkMemoryRequirements memReqs;
VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo(); VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo();
vkGetBufferMemoryRequirements(device, buffer->buffer, &memReqs); vkGetBufferMemoryRequirements(logicalDevice, buffer->buffer, &memReqs);
memAlloc.allocationSize = memReqs.size; memAlloc.allocationSize = memReqs.size;
// Find a memory type index that fits the properties of the buffer // Find a memory type index that fits the properties of the buffer
memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags); 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->alignment = memReqs.alignment;
buffer->size = memAlloc.allocationSize; 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) 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__) #if defined(__ANDROID__)
mesh->assetManager = androidApp->activity->assetManager; mesh->assetManager = androidApp->activity->assetManager;
@ -759,7 +759,7 @@ VulkanExampleBase::~VulkanExampleBase()
delete textOverlay; delete textOverlay;
} }
vkDestroyDevice(device, nullptr); delete vulkanDevice;
if (enableValidation) if (enableValidation)
{ {
@ -812,6 +812,8 @@ void VulkanExampleBase::initVulkan(bool enableValidation)
// and want to use another one // and want to use another one
physicalDevice = physicalDevices[0]; physicalDevice = physicalDevices[0];
vulkanDevice = new vk::VulkanDevice(physicalDevice);
// Find a queue that supports graphics operations // Find a queue that supports graphics operations
uint32_t graphicsQueueIndex = 0; uint32_t graphicsQueueIndex = 0;
uint32_t queueCount; uint32_t queueCount;
@ -841,10 +843,10 @@ void VulkanExampleBase::initVulkan(bool enableValidation)
queueCreateInfos[0].queueCount = 1; queueCreateInfos[0].queueCount = 1;
queueCreateInfos[0].pQueuePriorities = queuePriorities.data(); 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 // Assign device to base class context
device = vulkanDevice.device; device = vulkanDevice->logicalDevice;
// Store properties (including limits) and features of the phyiscal device // Store properties (including limits) and features of the phyiscal device
// So examples can check against them and see if a feature is actually supported // 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 // todo: getter? should always point to VulkanDevice->device
VkDevice device; VkDevice device;
/** @brief Encapsulated physical and logical vulkan 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 // Handle to the device graphics queue that command buffers are submitted to
VkQueue queue; VkQueue queue;
// Color buffer format // Color buffer format

View file

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

View file

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

View file

@ -247,7 +247,7 @@ public:
{ {
VkCommandBuffer layoutCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); 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->width = SHADOWMAP_DIM;
frameBuffers.shadow->height = SHADOWMAP_DIM; frameBuffers.shadow->height = SHADOWMAP_DIM;
@ -279,7 +279,7 @@ public:
{ {
VkCommandBuffer layoutCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); 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->width = FB_DIM;
frameBuffers.deferred->height = 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 // The other example will use the VulkanMesh loader which has some additional functionality for loading meshes
void loadMesh() void loadMesh()
{ {
VulkanMeshLoader *meshLoader = new VulkanMeshLoader(&vulkanDevice); VulkanMeshLoader *meshLoader = new VulkanMeshLoader(vulkanDevice);
#if defined(__ANDROID__) #if defined(__ANDROID__)
meshLoader->assetManager = androidApp->activity->assetManager; meshLoader->assetManager = androidApp->activity->assetManager;
#endif #endif

View file

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

View file

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