Added vertex buffer and staging buffers
This commit is contained in:
+110
-12
@@ -13,17 +13,12 @@ namespace vapp{
|
||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
||||
};
|
||||
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
||||
VkDebugUtilsMessageTypeFlagsEXT messageType,
|
||||
const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
|
||||
void *pUserData){
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData){
|
||||
std::cerr << "Validation Layer: " << pCallbackData->pMessage << std::endl;
|
||||
return VK_FALSE;
|
||||
}
|
||||
|
||||
VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkDebugUtilsMessengerEXT *pDebugMessenger){
|
||||
VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pDebugMessenger){
|
||||
auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
|
||||
instance, "vkCreateDebugUtilsMessengerEXT");
|
||||
if(func == nullptr) return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
@@ -31,8 +26,7 @@ namespace vapp{
|
||||
return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
|
||||
}
|
||||
|
||||
void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger,
|
||||
const VkAllocationCallbacks *pAllocator){
|
||||
void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks *pAllocator){
|
||||
if(auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
|
||||
instance, "vkDestroyDebugUtilsMessengerEXT"); func != nullptr){
|
||||
func(instance, debugMessenger, pAllocator);
|
||||
@@ -481,10 +475,15 @@ namespace vapp{
|
||||
dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
|
||||
dynamicState.pDynamicStates = dynamicStates.data();
|
||||
|
||||
auto bindingDescription = Vertex::getBindingDescription();
|
||||
auto attributeDescription = Vertex::getAttributeDescriptions();
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
|
||||
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||
vertexInputInfo.vertexBindingDescriptionCount = 0;
|
||||
vertexInputInfo.vertexAttributeDescriptionCount = 0;
|
||||
vertexInputInfo.vertexBindingDescriptionCount = 1;
|
||||
vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescription.size());
|
||||
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
|
||||
vertexInputInfo.pVertexAttributeDescriptions = attributeDescription.data();
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
|
||||
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||
@@ -675,6 +674,97 @@ namespace vapp{
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Vulkan::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties){
|
||||
VkPhysicalDeviceMemoryProperties memProperties;
|
||||
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);
|
||||
for(uint32_t i = 0; i < memProperties.memoryTypeCount; i++){
|
||||
if(typeFilter & (1 << i) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) return i;
|
||||
}
|
||||
|
||||
throw std::runtime_error("Func: findMemoryType\nError: Failed to find suitable memory type!\n");
|
||||
}
|
||||
|
||||
void Vulkan::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer &buffer, VkDeviceMemory &bufferMemory){
|
||||
VkBufferCreateInfo bufferInfo{};
|
||||
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
bufferInfo.size = size;
|
||||
bufferInfo.usage = usage;
|
||||
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
|
||||
if(vkCreateBuffer(device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS){
|
||||
throw std::runtime_error("Func: createBuffer\nError: Failed to create buffer!\n");
|
||||
}
|
||||
|
||||
VkMemoryRequirements memRequirements;
|
||||
vkGetBufferMemoryRequirements(device, buffer, &memRequirements);
|
||||
|
||||
VkMemoryAllocateInfo allocInfo{};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
allocInfo.allocationSize = memRequirements.size;
|
||||
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);
|
||||
|
||||
if(vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS){
|
||||
throw std::runtime_error("Func: createBuffer\nError: Failed to allocate memory for buffer!\n");
|
||||
}
|
||||
|
||||
vkBindBufferMemory(device, buffer, bufferMemory, 0);
|
||||
}
|
||||
|
||||
void Vulkan::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size){
|
||||
VkCommandBufferAllocateInfo allocInfo{};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
allocInfo.commandPool = commandPool;
|
||||
allocInfo.commandBufferCount = 1;
|
||||
|
||||
VkCommandBuffer commandBuffer;
|
||||
vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer);
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo{};
|
||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
|
||||
vkBeginCommandBuffer(commandBuffer, &beginInfo);
|
||||
|
||||
VkBufferCopy copyRegion{};
|
||||
copyRegion.size = size;
|
||||
|
||||
vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region);
|
||||
|
||||
vkEndCommandBuffer(commandBuffer);
|
||||
|
||||
VkSubmitInfo submitInfo{};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &commandBuffer;
|
||||
|
||||
vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||
vkQueueWaitIdle(graphicsQueue);
|
||||
|
||||
vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
|
||||
}
|
||||
|
||||
void Vulkan::createVertexBuffer(){
|
||||
VkDeviceSize bufferSize = sizeof(vertices[0]) * vertices.size();
|
||||
|
||||
VkBuffer stagingBuffer;
|
||||
VkDeviceMemory stagingBufferMemory;
|
||||
|
||||
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
|
||||
|
||||
void *data;
|
||||
vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data);
|
||||
memcpy(data, vertices.data(), (size_t)bufferSize);
|
||||
vkUnmapMemory(device, stagingBufferMemory);
|
||||
|
||||
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer, vertexBufferMemory);
|
||||
|
||||
copyBuffer(stagingBuffer, vertexBuffer, bufferSize);
|
||||
|
||||
vkDestroyBuffer(device, stagingBuffer, nullptr);
|
||||
vkFreeMemory(device, stagingBufferMemory, nullptr);
|
||||
}
|
||||
|
||||
void Vulkan::createCommandBuffers(){
|
||||
commandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
|
||||
|
||||
@@ -711,6 +801,10 @@ namespace vapp{
|
||||
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
|
||||
|
||||
VkBuffer vertexBuffers[] = { vertexBuffer };
|
||||
VkDeviceSize offsets[] = { 0 };
|
||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
|
||||
|
||||
VkViewport viewport{};
|
||||
viewport.x = 0.0f;
|
||||
viewport.y = 0.0f;
|
||||
@@ -725,7 +819,7 @@ namespace vapp{
|
||||
scissor.extent = swapChainExtent;
|
||||
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
||||
|
||||
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
|
||||
vkCmdDraw(commandBuffer, static_cast<uint32_t>(vertices.size()), 1, 0, 0);
|
||||
|
||||
vkCmdEndRenderPass(commandBuffer);
|
||||
if(vkEndCommandBuffer(commandBuffer) != VK_SUCCESS){
|
||||
@@ -862,6 +956,7 @@ namespace vapp{
|
||||
createGraphicsPipeline();
|
||||
createFrameBuffers();
|
||||
createCommandPool();
|
||||
createVertexBuffer();
|
||||
createCommandBuffers();
|
||||
createSyncObjects();
|
||||
}
|
||||
@@ -879,6 +974,9 @@ namespace vapp{
|
||||
// Vulkan
|
||||
cleanupSwapChain();
|
||||
|
||||
vkDestroyBuffer(device, vertexBuffer, nullptr);
|
||||
vkFreeMemory(device, vertexBufferMemory, nullptr);
|
||||
|
||||
vkDestroyPipeline(device, graphicsPipeline, nullptr);
|
||||
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
|
||||
|
||||
|
||||
+51
-5
@@ -19,28 +19,67 @@
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <glm/glm.hpp>
|
||||
#include <array>
|
||||
|
||||
namespace vapp{
|
||||
|
||||
// Change here for other presentMode
|
||||
const VkPresentModeKHR WISHED_PRESENT_MODE = VK_PRESENT_MODE_MAILBOX_KHR;
|
||||
|
||||
typedef struct _QueueFamilyIndices{
|
||||
struct Vertex{
|
||||
glm::vec2 pos;
|
||||
glm::vec3 color;
|
||||
|
||||
static VkVertexInputBindingDescription getBindingDescription(){
|
||||
VkVertexInputBindingDescription bindingDescription{};
|
||||
bindingDescription.binding = 0;
|
||||
bindingDescription.stride = sizeof(Vertex);
|
||||
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
return bindingDescription;
|
||||
}
|
||||
|
||||
static std::array<VkVertexInputAttributeDescription, 2> getAttributeDescriptions(){
|
||||
std::array<VkVertexInputAttributeDescription, 2> attributeDescriptions{};
|
||||
|
||||
attributeDescriptions[0].binding = 0;
|
||||
attributeDescriptions[0].location = 0;
|
||||
attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT;
|
||||
attributeDescriptions[0].offset = offsetof(Vertex, pos);
|
||||
|
||||
attributeDescriptions[1].binding = 0;
|
||||
attributeDescriptions[1].location = 1;
|
||||
attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
|
||||
attributeDescriptions[1].offset = offsetof(Vertex, color);
|
||||
|
||||
return attributeDescriptions;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Remove
|
||||
const std::vector<Vertex> vertices = {
|
||||
{{0.0f, -0.5f}, {0.0f, 1.0f, 0.0f}},
|
||||
{{0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}},
|
||||
{{-0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}}
|
||||
};
|
||||
|
||||
struct QueueFamilyIndices{
|
||||
std::optional<uint32_t> graphicsFamily;
|
||||
std::optional<uint32_t> presentFamily;
|
||||
|
||||
bool isComplete(){
|
||||
return graphicsFamily.has_value();
|
||||
}
|
||||
} QueueFamilyIndices;
|
||||
};
|
||||
|
||||
typedef struct{
|
||||
struct SwapChainSupportDetails{
|
||||
VkSurfaceCapabilitiesKHR capabilities;
|
||||
std::vector<VkSurfaceFormatKHR> formats;
|
||||
std::vector<VkPresentModeKHR> presentModes;
|
||||
} SwapChainSupportDetails;
|
||||
};
|
||||
|
||||
static std::vector<char> readFile(const std::string& filename);
|
||||
static std::array<VkVertexInputAttributeDescription, 2> getAttributeDescription();
|
||||
|
||||
|
||||
class Vulkan{
|
||||
private:
|
||||
@@ -81,6 +120,9 @@ private:
|
||||
|
||||
const int MAX_FRAMES_IN_FLIGHT = 2;
|
||||
uint32_t currentFrame = 0;
|
||||
|
||||
VkBuffer vertexBuffer;
|
||||
VkDeviceMemory vertexBufferMemory;
|
||||
#pragma endregion
|
||||
|
||||
bool checkValidationLayerSupport();
|
||||
@@ -105,6 +147,10 @@ private:
|
||||
void createRenderPass();
|
||||
void createFrameBuffers();
|
||||
void createCommandPool();
|
||||
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
|
||||
void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer &buffer, VkDeviceMemory &bufferMemory);
|
||||
void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
|
||||
void createVertexBuffer();
|
||||
void createCommandBuffers();
|
||||
void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex);
|
||||
void createSyncObjects();
|
||||
|
||||
Reference in New Issue
Block a user