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
|
||||
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
|
||||
g++ $(CFLAGS) -g -o VulkanTest main.cpp $(LDFLAGS)
|
||||
|
||||
|
|
164
main.cpp
164
main.cpp
|
@ -46,6 +46,13 @@ public:
|
|||
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:
|
||||
// Instance variables:
|
||||
GLFWwindow* window;
|
||||
|
@ -66,13 +73,21 @@ private:
|
|||
VDeleter<VkPipeline> graphicsPipeline {device, vkDestroyPipeline};
|
||||
std::vector<VDeleter<VkFramebuffer>> swapChainFramebuffers;
|
||||
VDeleter<VkCommandPool> commandPool {device, vkDestroyCommandPool};
|
||||
std::vector<VkCommandBuffer> commandBuffers;
|
||||
VDeleter<VkSemaphore> imageAvailableSemaphore {device, vkDestroySemaphore};
|
||||
VDeleter<VkSemaphore> renderFinishedSemaphore {device, vkDestroySemaphore};
|
||||
|
||||
|
||||
// Initialize our GLFW window.
|
||||
void initWindow() {
|
||||
glfwInit();
|
||||
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||
|
||||
window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
|
||||
|
||||
glfwSetWindowUserPointer(window, this);
|
||||
glfwSetWindowSizeCallback(window, HelloTriangleApplication::onWindowResized);
|
||||
}
|
||||
|
||||
void initVulkan() {
|
||||
|
@ -86,6 +101,20 @@ private:
|
|||
createRenderPass();
|
||||
createGraphicsPipeline();
|
||||
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.
|
||||
|
@ -478,10 +507,16 @@ private:
|
|||
// and we want to create a new swap chain to match the new window size.
|
||||
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!");
|
||||
}
|
||||
|
||||
swapChain = newSwapChain;
|
||||
|
||||
// Get the swapchain images.
|
||||
vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);
|
||||
swapChainImages.resize(imageCount);
|
||||
|
@ -719,6 +754,17 @@ private:
|
|||
renderPassInfo.subpassCount = 1;
|
||||
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) {
|
||||
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() {
|
||||
// While we shouldn't close, have glfw poll for events
|
||||
while(!glfwWindowShouldClose(window)) {
|
||||
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