finish up command buffers, and actually draws now
This commit is contained in:
parent
b1720560a6
commit
7a299629a9
2 changed files with 164 additions and 2 deletions
2
Makefile
2
Makefile
|
@ -2,6 +2,8 @@ VULKAN_SDK_PATH = /mnt/storage/Downloads/VulkanSDK/1.0.30.0/x86_64
|
||||||
CFLAGS = -std=c++11 -I$(VULKAN_SDK_PATH)/include
|
CFLAGS = -std=c++11 -I$(VULKAN_SDK_PATH)/include
|
||||||
LDFLAGS = -L$(VULKAN_SDK_PATH)/lib -L/usr/local/lib -lglfw3 -lrt -lm -ldl -lXrandr -lXinerama -lXxf86vm -lXext -lXcursor -lXrender -lXfixes -lX11 -lpthread -lxcb -lXau -lvulkan
|
LDFLAGS = -L$(VULKAN_SDK_PATH)/lib -L/usr/local/lib -lglfw3 -lrt -lm -ldl -lXrandr -lXinerama -lXxf86vm -lXext -lXcursor -lXrender -lXfixes -lX11 -lpthread -lxcb -lXau -lvulkan
|
||||||
|
|
||||||
|
all: VulkanTest
|
||||||
|
|
||||||
VulkanTest: main.cpp
|
VulkanTest: main.cpp
|
||||||
g++ $(CFLAGS) -g -o VulkanTest main.cpp $(LDFLAGS)
|
g++ $(CFLAGS) -g -o VulkanTest main.cpp $(LDFLAGS)
|
||||||
|
|
||||||
|
|
164
main.cpp
164
main.cpp
|
@ -46,6 +46,13 @@ public:
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void onWindowResized(GLFWwindow* window, int width, int height) {
|
||||||
|
if(width == 0 || height == 0) return;
|
||||||
|
|
||||||
|
HelloTriangleApplication* app = reinterpret_cast<HelloTriangleApplication*>(glfwGetWindowUserPointer(window));
|
||||||
|
app->recreateSwapChain();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Instance variables:
|
// Instance variables:
|
||||||
GLFWwindow* window;
|
GLFWwindow* window;
|
||||||
|
@ -66,13 +73,21 @@ private:
|
||||||
VDeleter<VkPipeline> graphicsPipeline {device, vkDestroyPipeline};
|
VDeleter<VkPipeline> graphicsPipeline {device, vkDestroyPipeline};
|
||||||
std::vector<VDeleter<VkFramebuffer>> swapChainFramebuffers;
|
std::vector<VDeleter<VkFramebuffer>> swapChainFramebuffers;
|
||||||
VDeleter<VkCommandPool> commandPool {device, vkDestroyCommandPool};
|
VDeleter<VkCommandPool> commandPool {device, vkDestroyCommandPool};
|
||||||
|
std::vector<VkCommandBuffer> commandBuffers;
|
||||||
|
VDeleter<VkSemaphore> imageAvailableSemaphore {device, vkDestroySemaphore};
|
||||||
|
VDeleter<VkSemaphore> renderFinishedSemaphore {device, vkDestroySemaphore};
|
||||||
|
|
||||||
|
|
||||||
// Initialize our GLFW window.
|
// Initialize our GLFW window.
|
||||||
void initWindow() {
|
void initWindow() {
|
||||||
glfwInit();
|
glfwInit();
|
||||||
|
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
|
||||||
window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
|
window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
|
||||||
|
|
||||||
|
glfwSetWindowUserPointer(window, this);
|
||||||
|
glfwSetWindowSizeCallback(window, HelloTriangleApplication::onWindowResized);
|
||||||
}
|
}
|
||||||
|
|
||||||
void initVulkan() {
|
void initVulkan() {
|
||||||
|
@ -86,6 +101,20 @@ private:
|
||||||
createRenderPass();
|
createRenderPass();
|
||||||
createGraphicsPipeline();
|
createGraphicsPipeline();
|
||||||
createFramebuffers();
|
createFramebuffers();
|
||||||
|
createCommandPool();
|
||||||
|
createCommandBuffers();
|
||||||
|
createSemaphores();
|
||||||
|
}
|
||||||
|
|
||||||
|
void recreateSwapChain() {
|
||||||
|
vkDeviceWaitIdle(device);
|
||||||
|
|
||||||
|
createSwapChain();
|
||||||
|
createImageViews();
|
||||||
|
createRenderPass();
|
||||||
|
createGraphicsPipeline();
|
||||||
|
createFramebuffers();
|
||||||
|
createCommandBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Figure out what extensions GLFW requires to make a Vulkan surface.
|
// Figure out what extensions GLFW requires to make a Vulkan surface.
|
||||||
|
@ -478,10 +507,16 @@ private:
|
||||||
// and we want to create a new swap chain to match the new window size.
|
// and we want to create a new swap chain to match the new window size.
|
||||||
createInfo.oldSwapchain = VK_NULL_HANDLE;
|
createInfo.oldSwapchain = VK_NULL_HANDLE;
|
||||||
|
|
||||||
if(vkCreateSwapchainKHR(device, &createInfo, nullptr, swapChain.replace()) != VK_SUCCESS) {
|
VkSwapchainKHR oldSwapChain = swapChain;
|
||||||
|
createInfo.oldSwapchain = oldSwapChain;
|
||||||
|
|
||||||
|
VkSwapchainKHR newSwapChain;
|
||||||
|
if(vkCreateSwapchainKHR(device, &createInfo, nullptr, &newSwapChain) != VK_SUCCESS) {
|
||||||
throw std::runtime_error("failed to create swap chain!");
|
throw std::runtime_error("failed to create swap chain!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
swapChain = newSwapChain;
|
||||||
|
|
||||||
// Get the swapchain images.
|
// Get the swapchain images.
|
||||||
vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);
|
vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);
|
||||||
swapChainImages.resize(imageCount);
|
swapChainImages.resize(imageCount);
|
||||||
|
@ -719,6 +754,17 @@ private:
|
||||||
renderPassInfo.subpassCount = 1;
|
renderPassInfo.subpassCount = 1;
|
||||||
renderPassInfo.pSubpasses = &subPass;
|
renderPassInfo.pSubpasses = &subPass;
|
||||||
|
|
||||||
|
VkSubpassDependency dependency = {};
|
||||||
|
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||||
|
dependency.dstSubpass = 0;
|
||||||
|
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
dependency.srcAccessMask = 0;
|
||||||
|
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
|
|
||||||
|
renderPassInfo.dependencyCount = 1;
|
||||||
|
renderPassInfo.pDependencies = &dependency;
|
||||||
|
|
||||||
if(vkCreateRenderPass(device, &renderPassInfo, nullptr, renderPass.replace()) != VK_SUCCESS) {
|
if(vkCreateRenderPass(device, &renderPassInfo, nullptr, renderPass.replace()) != VK_SUCCESS) {
|
||||||
throw std::runtime_error("failed to create render pass!");
|
throw std::runtime_error("failed to create render pass!");
|
||||||
}
|
}
|
||||||
|
@ -746,11 +792,125 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void createCommandPool() {
|
||||||
|
QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice);
|
||||||
|
|
||||||
|
VkCommandPoolCreateInfo poolInfo = {};
|
||||||
|
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||||
|
poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily;
|
||||||
|
poolInfo.flags = 0;
|
||||||
|
|
||||||
|
if(vkCreateCommandPool(device, &poolInfo, nullptr, commandPool.replace()) != VK_SUCCESS) {
|
||||||
|
throw std::runtime_error("failed to create command pool!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void createCommandBuffers() {
|
||||||
|
if(commandBuffers.size() > 0) {
|
||||||
|
vkFreeCommandBuffers(device, commandPool, commandBuffers.size(), commandBuffers.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
commandBuffers.resize(swapChainFramebuffers.size());
|
||||||
|
|
||||||
|
VkCommandBufferAllocateInfo allocInfo = {};
|
||||||
|
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
|
allocInfo.commandPool = commandPool;
|
||||||
|
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||||
|
allocInfo.commandBufferCount = (uint32_t) commandBuffers.size();
|
||||||
|
|
||||||
|
if(vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) {
|
||||||
|
throw std::runtime_error("failed to allocate command buffers!");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < commandBuffers.size(); i++) {
|
||||||
|
VkCommandBufferBeginInfo beginInfo = {};
|
||||||
|
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
|
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
|
||||||
|
beginInfo.pInheritanceInfo = nullptr;
|
||||||
|
|
||||||
|
vkBeginCommandBuffer(commandBuffers[i], &beginInfo);
|
||||||
|
|
||||||
|
VkRenderPassBeginInfo renderPassInfo = {};
|
||||||
|
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||||
|
renderPassInfo.renderPass = renderPass;
|
||||||
|
renderPassInfo.framebuffer = swapChainFramebuffers[i];
|
||||||
|
renderPassInfo.renderArea.offset = {0, 0};
|
||||||
|
renderPassInfo.renderArea.extent = swapChainExtent;
|
||||||
|
|
||||||
|
VkClearValue clearColor = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
|
renderPassInfo.clearValueCount = 1;
|
||||||
|
renderPassInfo.pClearValues = &clearColor;
|
||||||
|
|
||||||
|
vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
|
vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
|
||||||
|
|
||||||
|
vkCmdDraw(commandBuffers[i], 3, 1, 0, 0);
|
||||||
|
|
||||||
|
vkCmdEndRenderPass(commandBuffers[i]);
|
||||||
|
|
||||||
|
if(vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS) {
|
||||||
|
throw std::runtime_error("failed to record command buffer!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void createSemaphores() {
|
||||||
|
VkSemaphoreCreateInfo semaphoreInfo = {};
|
||||||
|
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||||
|
|
||||||
|
if(vkCreateSemaphore(device, &semaphoreInfo, nullptr, imageAvailableSemaphore.replace()) != VK_SUCCESS ||
|
||||||
|
vkCreateSemaphore(device, &semaphoreInfo, nullptr, renderFinishedSemaphore.replace()) != VK_SUCCESS) {
|
||||||
|
throw std::runtime_error("failed to create semaphores!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void mainLoop() {
|
void mainLoop() {
|
||||||
// While we shouldn't close, have glfw poll for events
|
// While we shouldn't close, have glfw poll for events
|
||||||
while(!glfwWindowShouldClose(window)) {
|
while(!glfwWindowShouldClose(window)) {
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
drawFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vkDeviceWaitIdle(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawFrame() {
|
||||||
|
uint32_t imageIndex;
|
||||||
|
vkAcquireNextImageKHR(device, swapChain, std::numeric_limits<uint64_t>::max(), imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
|
||||||
|
|
||||||
|
VkSubmitInfo submitInfo = {};
|
||||||
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
|
||||||
|
VkSemaphore waitSemaphores[] = {imageAvailableSemaphore};
|
||||||
|
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
||||||
|
submitInfo.waitSemaphoreCount = 1;
|
||||||
|
submitInfo.pWaitSemaphores = waitSemaphores;
|
||||||
|
submitInfo.pWaitDstStageMask = waitStages;
|
||||||
|
submitInfo.commandBufferCount = 1;
|
||||||
|
submitInfo.pCommandBuffers = &commandBuffers[imageIndex];
|
||||||
|
|
||||||
|
VkSemaphore signalSemaphores[] = {renderFinishedSemaphore};
|
||||||
|
submitInfo.signalSemaphoreCount = 1;
|
||||||
|
submitInfo.pSignalSemaphores = signalSemaphores;
|
||||||
|
|
||||||
|
if(vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE) != VK_SUCCESS) {
|
||||||
|
throw std::runtime_error("failed to submit draw command buffer!");
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPresentInfoKHR presentInfo = {};
|
||||||
|
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
|
|
||||||
|
presentInfo.waitSemaphoreCount = 1;
|
||||||
|
presentInfo.pWaitSemaphores = signalSemaphores;
|
||||||
|
|
||||||
|
VkSwapchainKHR swapChains[] = {swapChain};
|
||||||
|
presentInfo.swapchainCount = 1;
|
||||||
|
presentInfo.pSwapchains = swapChains;
|
||||||
|
presentInfo.pImageIndices = &imageIndex;
|
||||||
|
presentInfo.pResults = nullptr;
|
||||||
|
|
||||||
|
vkQueuePresentKHR(presentQueue, &presentInfo);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue