Add uniform buffers

This commit is contained in:
Piotr Krygier committed 2023-03-08 14:36:30 +01:00
1 parent a94e7a95f5
commit cce4875329
3 files changed
+188 -19

No files matched your search

+9
View File
@@ -43,6 +43,9 @@ enum Errors
VULKAN_SHADER_UNABLE_TO_CREATE_SHADER, VULKAN_SHADER_UNABLE_TO_CREATE_SHADER,
VULKAN_PIPELAYOUT_CREATION_FAILED, VULKAN_PIPELAYOUT_CREATION_FAILED,
VULKAN_RENDERPASS_CREATION_FAILED, VULKAN_RENDERPASS_CREATION_FAILED,
VULKAN_DESCRIPTOR_POOL_CREATION_FAILED,
VULKAN_DESCRIPTOR_SETS_ALLOCATION_FAILED,
VULKAN_DESCRIPTORSETLAYOUT_CREATION_FAILED,
VULKAN_GRAPHICSPIPELINE_CREATION_FAILED, VULKAN_GRAPHICSPIPELINE_CREATION_FAILED,
VULKAN_FRAMEBUFFERS_CREATION_FAILED, VULKAN_FRAMEBUFFERS_CREATION_FAILED,
VULKAN_RECORD_COMMAND_BUFFER_FAILED, VULKAN_RECORD_COMMAND_BUFFER_FAILED,
@@ -90,6 +93,12 @@ std::array<std::array<const char*, LAST_MESSAGE>, LAST_LANGUAGE> vulkanErrorMess
"Failed to create pipeline layout", "Failed to create pipeline layout",
/* VULKAN_RENDERPASS_CREATION_FAILED */ /* VULKAN_RENDERPASS_CREATION_FAILED */
"Failed to create render pass", "Failed to create render pass",
/* VULKAN_DESCRIPTOR_POOL_CREATION_FAILED */
"Failed to create descriptor pool",
/* VULKAN_DESCRIPTOR_SETS_ALLOCATION_FAILED */
"Failed to allocate descriptor sets",
/* VULKAN_DESCRIPTORSETLAYOUT_CREATION_FAILED */
"Failed to create descriptor set layout",
/* VULKAN_GRAPHICSPIPELINE_CREATION_FAILED */ /* VULKAN_GRAPHICSPIPELINE_CREATION_FAILED */
"Failed to create graphics pipeline", "Failed to create graphics pipeline",
/* VULKAN_FRAMEBUFFERS_CREATION_FAILED */ /* VULKAN_FRAMEBUFFERS_CREATION_FAILED */
+7 -1
View File
@@ -1,11 +1,17 @@
#version 450 #version 450
layout(binding = 0) uniform UniformBufferObject {
mat4 model;
mat4 view;
mat4 proj;
} ubo;
layout(location = 0) in vec2 inPosition; layout(location = 0) in vec2 inPosition;
layout(location = 1) in vec3 inColor; layout(location = 1) in vec3 inColor;
layout(location = 0) out vec3 fragColor; layout(location = 0) out vec3 fragColor;
void main() { void main() {
gl_Position = vec4(inPosition, 0.0, 1.0); gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0);
fragColor = inColor; fragColor = inColor;
} }
+172 -18
View File
@@ -34,7 +34,9 @@
#include "logger.hpp" #include "logger.hpp"
#include "window.hpp" #include "window.hpp"
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vector> #include <vector>
#include <string> #include <string>
@@ -82,6 +84,9 @@ enum VULKAN_ERROR
VULKAN_ERROR_SHADER_CREATION_FAILED, VULKAN_ERROR_SHADER_CREATION_FAILED,
VULKAN_ERROR_PIPELINE_LAYOUT_CREATION_FAILED, VULKAN_ERROR_PIPELINE_LAYOUT_CREATION_FAILED,
VULKAN_ERROR_RENDERPASS_CREATION_FAILED, VULKAN_ERROR_RENDERPASS_CREATION_FAILED,
VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED,
VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED,
VULKAN_ERROR_DESCRIPTORSETLAYOUT_CREATION_FAILED,
VULKAN_ERROR_GRAPHICSPIPELINE_CREATION_FAILED, VULKAN_ERROR_GRAPHICSPIPELINE_CREATION_FAILED,
VULKAN_ERROR_FRAMEBUFFERS_CREATION_FAILED, VULKAN_ERROR_FRAMEBUFFERS_CREATION_FAILED,
VULKAN_ERROR_RECORD_COMMAND_BUFFER_FAILED, VULKAN_ERROR_RECORD_COMMAND_BUFFER_FAILED,
@@ -131,6 +136,12 @@ struct Vertex
}; };
struct UniformBufferObject {
alignas(16) glm::mat4 model;
alignas(16) glm::mat4 view;
alignas(16) glm::mat4 proj;
};
/** /**
* @brief Wrapper for Vulan buffer. Holds allocation data; * @brief Wrapper for Vulan buffer. Holds allocation data;
* *
@@ -207,7 +218,10 @@ VkExtent2D gSwapchainExtent;
std::vector<VkShaderModule> gShaderModules; std::vector<VkShaderModule> gShaderModules;
VkRenderPass gRenderPass = VK_NULL_HANDLE; VkRenderPass gRenderPass = VK_NULL_HANDLE;
VkPipelineLayout gPipelineLayout = VK_NULL_HANDLE; VkPipelineLayout gPipelineLayout = VK_NULL_HANDLE;
VkDescriptorSetLayout gDescriptorSetLayout = VK_NULL_HANDLE;
VkPipeline gGraphicsPipeline = VK_NULL_HANDLE; VkPipeline gGraphicsPipeline = VK_NULL_HANDLE;
VkDescriptorPool gDescriptorPool = {};
std::vector<VkDescriptorSet> gDescriptorSets = {};
std::vector<VkFramebuffer> gSwapchainFramebuffers = {}; std::vector<VkFramebuffer> gSwapchainFramebuffers = {};
std::vector<VkSemaphore> gImageAvailableSemaphores = {}; std::vector<VkSemaphore> gImageAvailableSemaphores = {};
std::vector<VkSemaphore> gRenderFinishedSemaphores = {}; std::vector<VkSemaphore> gRenderFinishedSemaphores = {};
@@ -218,6 +232,9 @@ Buffer gVertexBuffer = {};
Buffer gVertexStagingBuffer = {}; Buffer gVertexStagingBuffer = {};
Buffer gIndexBuffer = {}; Buffer gIndexBuffer = {};
Buffer gIndexStagingBuffer = {}; Buffer gIndexStagingBuffer = {};
std::vector<Buffer> gUniformBuffers = {};
std::vector<void*> gUniformBuffersMappedMemory = {};
/** /**
* @brief Helper function. Creates a buffer object * @brief Helper function. Creates a buffer object
@@ -316,6 +333,13 @@ static uint8_t createVertexBuffer();
*/ */
static uint8_t createIndexBuffer(); static uint8_t createIndexBuffer();
/**
* @brief Create a Uniform Buffers
*
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
*/
static uint8_t createUniformBuffers();
/** /**
* @brief Allocate Command Buffers * @brief Allocate Command Buffers
* *
@@ -339,14 +363,6 @@ static uint8_t createSwapchain();
*/ */
static uint8_t createSwapchainImageViews(); static uint8_t createSwapchainImageViews();
/**
* @brief Creates shader stages from hardcoded shader paths. Changes input
*
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_SHADER_FILE_OPEN_FAILED
* VULKAN_ERROR_SHADER_CREATION_FAILED
*/
/** /**
* @brief Creates shader stages from hardcoded shader paths. Changes input * @brief Creates shader stages from hardcoded shader paths. Changes input
* *
@@ -426,6 +442,13 @@ static uint8_t createRenderPass();
*/ */
static uint8_t createPipelineLayout(); static uint8_t createPipelineLayout();
/**
* @brief Create a Descriptor Set Layout
*
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
*/
static uint8_t createDescriptorSetLayout();
/** /**
* @brief Create Graphics Pipeline * @brief Create Graphics Pipeline
* *
@@ -630,7 +653,7 @@ static uint8_t createInstance()
/* Check if selected layers are supported*/ /* Check if selected layers are supported*/
for (auto &layer : gEnabledInstanceLayersNames) { for (auto &layer : gEnabledInstanceLayersNames) {
if(std::find_if(layerProperties.begin(), layerProperties.end(), [&layer](const VkLayerProperties& lp) { if(std::find_if(layerProperties.begin(), layerProperties.end(), [&layer](const VkLayerProperties& lp) {
return strcmp(lp.layerName, layer); return strcmp(lp.layerName, layer) == 0;
}) == std::end(layerProperties)) { }) == std::end(layerProperties)) {
LOGF << vulkanErrorMesssages[VULKAN_LAYER_NOT_SUPPORTED] << layer; LOGF << vulkanErrorMesssages[VULKAN_LAYER_NOT_SUPPORTED] << layer;
return VULKAN_ERROR_LAYER_NOT_SUPPORTED; return VULKAN_ERROR_LAYER_NOT_SUPPORTED;
@@ -640,7 +663,7 @@ static uint8_t createInstance()
/* Check if selected extensions are supported*/ /* Check if selected extensions are supported*/
for (auto &extension : gEnabledInstanceExtensionsNames) { for (auto &extension : gEnabledInstanceExtensionsNames) {
if(std::find_if(extensionsProperties.begin(), extensionsProperties.end(), [&extension](const VkExtensionProperties& ep) { if(std::find_if(extensionsProperties.begin(), extensionsProperties.end(), [&extension](const VkExtensionProperties& ep) {
return strcmp(ep.extensionName, extension); return strcmp(ep.extensionName, extension) == 0;
}) == std::end(extensionsProperties)) { }) == std::end(extensionsProperties)) {
LOGF << vulkanErrorMesssages[VULKAN_EXTENSION_NOT_SUPPORTED] << extension; LOGF << vulkanErrorMesssages[VULKAN_EXTENSION_NOT_SUPPORTED] << extension;
return VULKAN_ERROR_EXTENSION_NOT_SUPPORTED; return VULKAN_ERROR_EXTENSION_NOT_SUPPORTED;
@@ -711,7 +734,8 @@ static uint8_t pickPhysicalDevice()
vkGetPhysicalDeviceFeatures(pPhysicalDevices[physicalDeviceIdx], &deviceFeatures); vkGetPhysicalDeviceFeatures(pPhysicalDevices[physicalDeviceIdx], &deviceFeatures);
/* Expect discrete graphics device type */ /* Expect discrete graphics device type */
if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
|| deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
/* Application MUST have geometry shader */ /* Application MUST have geometry shader */
if (deviceFeatures.geometryShader) { if (deviceFeatures.geometryShader) {
gPhysicalDevice = pPhysicalDevices[physicalDeviceIdx]; gPhysicalDevice = pPhysicalDevices[physicalDeviceIdx];
@@ -948,6 +972,84 @@ static uint8_t createIndexBuffer()
return VULKAN_ERROR_NO_ERROR; return VULKAN_ERROR_NO_ERROR;
} }
static uint8_t createUniformBuffers()
{
VkDeviceSize bufferSize = sizeof(UniformBufferObject);
gUniformBuffers.resize(SWAP_BUFFER_COUNT);
gUniformBuffersMappedMemory.resize(SWAP_BUFFER_COUNT);
for (size_t i = 0; i < SWAP_BUFFER_COUNT; i++) {
createBuffer(bufferSize,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
gUniformBuffers[i]);
VmaAllocationInfo allocInfo;
vmaGetAllocationInfo(gAllocator, gUniformBuffers[i].allocation, &allocInfo);
gUniformBuffersMappedMemory[i] = allocInfo.pMappedData;
}
return VULKAN_ERROR_NO_ERROR;
}
static uint8_t createDescriptorPool()
{
VkDescriptorPoolSize poolSize{};
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSize.descriptorCount = static_cast<uint32_t>(SWAP_BUFFER_COUNT);
VkDescriptorPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.poolSizeCount = 1;
poolInfo.pPoolSizes = &poolSize;
poolInfo.maxSets = static_cast<uint32_t>(SWAP_BUFFER_COUNT);
if (vkCreateDescriptorPool(gDevice, &poolInfo, nullptr, &gDescriptorPool) != VK_SUCCESS) {
LOGF << vulkanErrorMesssages[VULKAN_DESCRIPTOR_POOL_CREATION_FAILED];
return VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED;
}
return VULKAN_ERROR_NO_ERROR;
}
static uint8_t createDescriptorSets()
{
std::vector<VkDescriptorSetLayout> layouts(SWAP_BUFFER_COUNT, gDescriptorSetLayout);
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = gDescriptorPool;
allocInfo.descriptorSetCount = static_cast<uint32_t>(SWAP_BUFFER_COUNT);
allocInfo.pSetLayouts = layouts.data();
gDescriptorSets.resize(SWAP_BUFFER_COUNT);
if (vkAllocateDescriptorSets(gDevice, &allocInfo, gDescriptorSets.data()) != VK_SUCCESS) {
LOGF << vulkanErrorMesssages[VULKAN_DESCRIPTOR_SETS_ALLOCATION_FAILED];
return VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED;
}
for (size_t i = 0; i < SWAP_BUFFER_COUNT; i++) {
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = gUniformBuffers[i].buffer;
bufferInfo.offset = 0;
bufferInfo.range = sizeof(UniformBufferObject);
VkWriteDescriptorSet descriptorWrite{};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = gDescriptorSets[i];
descriptorWrite.dstBinding = 0;
descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrite.descriptorCount = 1;
descriptorWrite.pBufferInfo = &bufferInfo;
vkUpdateDescriptorSets(gDevice, 1, &descriptorWrite, 0, nullptr);
}
return VULKAN_ERROR_NO_ERROR;
}
static uint8_t allocateCommandBuffers() static uint8_t allocateCommandBuffers()
{ {
VkCommandBufferAllocateInfo allocateInfo; VkCommandBufferAllocateInfo allocateInfo;
@@ -1236,7 +1338,7 @@ static void fillRasterizationInfo(VkPipelineRasterizationStateCreateInfo* raster
rasterizer->rasterizerDiscardEnable = VK_FALSE; /* Disable/Enable output to framebuffer*/ rasterizer->rasterizerDiscardEnable = VK_FALSE; /* Disable/Enable output to framebuffer*/
rasterizer->polygonMode = VK_POLYGON_MODE_FILL; rasterizer->polygonMode = VK_POLYGON_MODE_FILL;
rasterizer->cullMode = VK_CULL_MODE_BACK_BIT; rasterizer->cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer->frontFace = VK_FRONT_FACE_CLOCKWISE; rasterizer->frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterizer->depthBiasEnable = VK_FALSE; rasterizer->depthBiasEnable = VK_FALSE;
rasterizer->depthBiasConstantFactor = 0.0f; rasterizer->depthBiasConstantFactor = 0.0f;
rasterizer->depthBiasClamp = 0.0f; rasterizer->depthBiasClamp = 0.0f;
@@ -1334,8 +1436,8 @@ static uint8_t createPipelineLayout()
createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
createInfo.pNext = nullptr; createInfo.pNext = nullptr;
createInfo.flags = 0U; createInfo.flags = 0U;
createInfo.setLayoutCount = 0; createInfo.setLayoutCount = 1U;
createInfo.pSetLayouts = nullptr; createInfo.pSetLayouts = &gDescriptorSetLayout;
createInfo.pushConstantRangeCount = 0U; createInfo.pushConstantRangeCount = 0U;
createInfo.pPushConstantRanges = nullptr; createInfo.pPushConstantRanges = nullptr;
@@ -1349,6 +1451,31 @@ static uint8_t createPipelineLayout()
return VULKAN_ERROR_NO_ERROR; return VULKAN_ERROR_NO_ERROR;
} }
static uint8_t createDescriptorSetLayout()
{
VkDescriptorSetLayoutCreateInfo layoutInfo;
VkDescriptorSetLayoutBinding uboLayoutBinding;
uboLayoutBinding.binding = 0;
uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding.descriptorCount = 1;
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
uboLayoutBinding.pImmutableSamplers = nullptr;
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.pNext = nullptr;
layoutInfo.flags = 0U;
layoutInfo.bindingCount = 1U;
layoutInfo.pBindings = &uboLayoutBinding;
if (vkCreateDescriptorSetLayout(gDevice, &layoutInfo, nullptr, &gDescriptorSetLayout) != VK_SUCCESS) {
LOGF << vulkanErrorMesssages[VULKAN_DESCRIPTORSETLAYOUT_CREATION_FAILED];
return VULKAN_ERROR_DESCRIPTORSETLAYOUT_CREATION_FAILED;
}
return VULKAN_ERROR_NO_ERROR;
}
static uint8_t createGraphicsPipeline() static uint8_t createGraphicsPipeline()
{ {
uint8_t status = VULKAN_ERROR_NO_ERROR; uint8_t status = VULKAN_ERROR_NO_ERROR;
@@ -1477,6 +1604,7 @@ static uint8_t recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t image
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
vkCmdBindIndexBuffer(commandBuffer, gIndexBuffer.buffer, 0, VK_INDEX_TYPE_UINT16); vkCmdBindIndexBuffer(commandBuffer, gIndexBuffer.buffer, 0, VK_INDEX_TYPE_UINT16);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, gPipelineLayout, 0, 1, &gDescriptorSets[gCurrentFrame], 0, nullptr);
vkCmdDrawIndexed(commandBuffer, static_cast<uint32_t>(indices.size()), 1, 0, 0, 0); vkCmdDrawIndexed(commandBuffer, static_cast<uint32_t>(indices.size()), 1, 0, 0, 0);
@@ -1516,6 +1644,21 @@ static uint8_t createSyncObjects()
return VULKAN_ERROR_NO_ERROR; return VULKAN_ERROR_NO_ERROR;
} }
static void updateUniformBuffer(uint32_t currentImage)
{
static auto startTime = std::chrono::high_resolution_clock::now();
auto currentTime = std::chrono::high_resolution_clock::now();
float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();
UniformBufferObject ubo{};
ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
ubo.proj = glm::perspective(glm::radians(45.0f), gSwapchainExtent.width / (float) gSwapchainExtent.height, 0.1f, 10.0f);
ubo.proj[1][1] *= -1;
memcpy(gUniformBuffersMappedMemory[currentImage], &ubo, sizeof(ubo));
}
static void cleanupSwapchain() static void cleanupSwapchain()
{ {
vkDeviceWaitIdle(gDevice); vkDeviceWaitIdle(gDevice);
@@ -1550,16 +1693,20 @@ uint8_t initVulkan()
STATUS_CHECK(pickPhysicalDevice()); STATUS_CHECK(pickPhysicalDevice());
STATUS_CHECK(createDevice()); STATUS_CHECK(createDevice());
STATUS_CHECK(createMemoryAllocator()); STATUS_CHECK(createMemoryAllocator());
STATUS_CHECK(createCommandPools());
STATUS_CHECK(createVertexBuffer());
STATUS_CHECK(createIndexBuffer());
STATUS_CHECK(allocateCommandBuffers());
STATUS_CHECK(createSwapchain()); STATUS_CHECK(createSwapchain());
STATUS_CHECK(createSwapchainImageViews()); STATUS_CHECK(createSwapchainImageViews());
STATUS_CHECK(createRenderPass()); STATUS_CHECK(createRenderPass());
STATUS_CHECK(createDescriptorSetLayout());
STATUS_CHECK(createPipelineLayout()); STATUS_CHECK(createPipelineLayout());
STATUS_CHECK(createGraphicsPipeline()); STATUS_CHECK(createGraphicsPipeline());
STATUS_CHECK(createFrambuffers()); STATUS_CHECK(createFrambuffers());
STATUS_CHECK(createCommandPools());
STATUS_CHECK(createVertexBuffer());
STATUS_CHECK(createIndexBuffer());
STATUS_CHECK(createUniformBuffers());
STATUS_CHECK(createDescriptorPool());
STATUS_CHECK(createDescriptorSets());
STATUS_CHECK(allocateCommandBuffers());
STATUS_CHECK(createSyncObjects()); STATUS_CHECK(createSyncObjects());
return status; return status;
} }
@@ -1580,6 +1727,8 @@ void drawFrame()
return; return;
} }
updateUniformBuffer(gCurrentFrame);
/* Only reset the fence if we are submitting work */ /* Only reset the fence if we are submitting work */
vkResetFences(gDevice, 1, &gInFlightFences[gCurrentFrame]); vkResetFences(gDevice, 1, &gInFlightFences[gCurrentFrame]);
@@ -1626,7 +1775,12 @@ void drawFrame()
void deinitVulkan() void deinitVulkan()
{ {
cleanupSwapchain(); cleanupSwapchain();
for (size_t i = 0; i < SWAP_BUFFER_COUNT; ++i) {
vmaDestroyBuffer(gAllocator, gUniformBuffers[i].buffer, gUniformBuffers[i].allocation);
}
vkDestroyDescriptorPool(gDevice, gDescriptorPool, nullptr);
vkDestroyDescriptorSetLayout(gDevice, gDescriptorSetLayout, nullptr);
vmaDestroyBuffer(gAllocator, gVertexBuffer.buffer, gVertexBuffer.allocation); vmaDestroyBuffer(gAllocator, gVertexBuffer.buffer, gVertexBuffer.allocation);
vmaDestroyBuffer(gAllocator, gVertexStagingBuffer.buffer, gVertexStagingBuffer.allocation); vmaDestroyBuffer(gAllocator, gVertexStagingBuffer.buffer, gVertexStagingBuffer.allocation);
vmaDestroyBuffer(gAllocator, gIndexBuffer.buffer, gIndexBuffer.allocation); vmaDestroyBuffer(gAllocator, gIndexBuffer.buffer, gIndexBuffer.allocation);