Complete "Hello Triangle" program with resizing and minimization handled
This commit is contained in:
parent
54e69982eb
commit
75e9921d45
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,3 @@
|
|||||||
.cache/
|
.cache/
|
||||||
|
.vscode/
|
||||||
build/
|
build/
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,13 @@ add_executable(${EXE_NAME} ${CMAKE_SOURCE_DIR}/src/main.cc ${PROGRAM_SOURCES} ${
|
|||||||
target_include_directories(${EXE_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include)
|
target_include_directories(${EXE_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include)
|
||||||
add_dependencies(${EXE_NAME} shaders)
|
add_dependencies(${EXE_NAME} shaders)
|
||||||
|
|
||||||
|
if ( CMAKE_COMPILER_IS_GNUCC )
|
||||||
|
target_compile_options(${EXE_NAME} PRIVATE -Wall -Wextra)
|
||||||
|
endif()
|
||||||
|
if ( MSVC )
|
||||||
|
target_compile_options(${EXE_NAME} PRIVATE /W4)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Linking
|
# Linking
|
||||||
target_link_libraries(${EXE_NAME} PRIVATE SDL2::SDL2)
|
target_link_libraries(${EXE_NAME} PRIVATE SDL2::SDL2)
|
||||||
target_link_libraries(${EXE_NAME} PRIVATE Vulkan::Vulkan)
|
target_link_libraries(${EXE_NAME} PRIVATE Vulkan::Vulkan)
|
||||||
@ -17,6 +17,8 @@ const std::vector<const char*> deviceExtensions = {
|
|||||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const int MAX_FRAMES_IN_FLIGHT = 2;
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
const bool enableValidationLayers = false;
|
const bool enableValidationLayers = false;
|
||||||
#else
|
#else
|
||||||
@ -44,7 +46,7 @@ struct SwapChainSupportDetails {
|
|||||||
class VulkanApp {
|
class VulkanApp {
|
||||||
public:
|
public:
|
||||||
VulkanApp(const uint32_t& _w, const uint32_t& _h) :
|
VulkanApp(const uint32_t& _w, const uint32_t& _h) :
|
||||||
mWidth(_w), mHeight(_h), mWin(nullptr), mActive(false) {}
|
mWin(nullptr), mWidth(_w), mHeight(_h) {}
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void loop();
|
void loop();
|
||||||
@ -55,9 +57,11 @@ private:
|
|||||||
SDL_Event mEvent;
|
SDL_Event mEvent;
|
||||||
|
|
||||||
// Not tied to library
|
// Not tied to library
|
||||||
const uint32_t mWidth;
|
uint32_t mWidth;
|
||||||
const uint32_t mHeight;
|
uint32_t mHeight;
|
||||||
bool mActive;
|
bool mActive = false;
|
||||||
|
bool mResized = false;
|
||||||
|
bool mMinimized = false;
|
||||||
|
|
||||||
// Vulkan
|
// Vulkan
|
||||||
VkInstance mInstance;
|
VkInstance mInstance;
|
||||||
@ -77,14 +81,14 @@ private:
|
|||||||
VkPipeline mGraphicsPipeline;
|
VkPipeline mGraphicsPipeline;
|
||||||
|
|
||||||
VkCommandPool mCommandPool;
|
VkCommandPool mCommandPool;
|
||||||
VkCommandBuffer mCommandBuffer;
|
std::vector<VkCommandBuffer> mCommandBuffers;
|
||||||
|
|
||||||
VkQueue mGraphicsQueue;
|
VkQueue mGraphicsQueue;
|
||||||
VkQueue mPresentQueue;
|
VkQueue mPresentQueue;
|
||||||
|
|
||||||
VkSemaphore mImageAvailableSemaphore;
|
std::vector<VkSemaphore> mImageAvailableSemaphores;
|
||||||
VkSemaphore mRenderFinishedSemaphore;
|
std::vector<VkSemaphore> mRenderFinishedSemaphores;
|
||||||
VkFence mInFlightFence;
|
std::vector<VkFence> mInFlightFences;
|
||||||
|
|
||||||
|
|
||||||
VkDebugUtilsMessengerEXT mDebugMessenger;
|
VkDebugUtilsMessengerEXT mDebugMessenger;
|
||||||
@ -92,7 +96,11 @@ private:
|
|||||||
void createInstance();
|
void createInstance();
|
||||||
void selectPhysicalDevice();
|
void selectPhysicalDevice();
|
||||||
void createLogicalDevice();
|
void createLogicalDevice();
|
||||||
|
|
||||||
void createSwapChain();
|
void createSwapChain();
|
||||||
|
void recreateSwapChain();
|
||||||
|
void cleanupSwapChain();
|
||||||
|
|
||||||
void createImageViews();
|
void createImageViews();
|
||||||
void createRenderPass();
|
void createRenderPass();
|
||||||
void createGraphicsPipeline();
|
void createGraphicsPipeline();
|
||||||
@ -118,7 +126,15 @@ private:
|
|||||||
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
||||||
VkDebugUtilsMessageTypeFlagsEXT messageType,
|
VkDebugUtilsMessageTypeFlagsEXT messageType,
|
||||||
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) {
|
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) {
|
||||||
fprintf(stderr, "Validation Layer: %s \n", pCallbackData->pMessage);
|
(void)pUserData;
|
||||||
|
|
||||||
|
if(messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
|
||||||
|
fprintf(stderr, "Validation Layer [Error/Warning]: %s \n", pCallbackData->pMessage);
|
||||||
|
} else if(messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) {
|
||||||
|
fprintf(stderr, "Validation Layer [General]: %s \n", pCallbackData->pMessage);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Validation Layer: %s \n", pCallbackData->pMessage);
|
||||||
|
}
|
||||||
|
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
layout(location = 0) out vec3 fragColor;
|
layout(location = 0) out vec3 fragColor;
|
||||||
|
|
||||||
vec2 positions[3] = vec2[](
|
const vec2 positions[3] = vec2[](
|
||||||
vec2(0.0, -0.5),
|
vec2(0.0, -0.5),
|
||||||
vec2(0.5, 0.5),
|
vec2(0.5, 0.5),
|
||||||
vec2(-0.5, 0.5)
|
vec2(-0.5, 0.5)
|
||||||
);
|
);
|
||||||
|
|
||||||
vec3 colors[3] = vec3[](
|
const vec3 colors[3] = vec3[](
|
||||||
vec3(1.0, 0.0, 0.0),
|
vec3(1.0, 0.0, 0.0),
|
||||||
vec3(0.0, 1.0, 0.0),
|
vec3(0.0, 1.0, 0.0),
|
||||||
vec3(0.0, 0.0, 1.0)
|
vec3(0.0, 0.0, 1.0)
|
||||||
|
|||||||
181
src/vulkanapp.cc
181
src/vulkanapp.cc
@ -83,7 +83,7 @@ QueueFamilyIndices VulkanApp::findQueueFamilies(VkPhysicalDevice device) {
|
|||||||
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
|
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
|
||||||
|
|
||||||
// Get queue families and check them
|
// Get queue families and check them
|
||||||
for(int i=0;i<queueFamilies.size();i++) {
|
for(size_t i=0;i<queueFamilies.size();i++) {
|
||||||
const VkQueueFamilyProperties& queueFamily = queueFamilies[i];
|
const VkQueueFamilyProperties& queueFamily = queueFamilies[i];
|
||||||
|
|
||||||
VkBool32 presentSupport = false;
|
VkBool32 presentSupport = false;
|
||||||
@ -197,7 +197,7 @@ void VulkanApp::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imag
|
|||||||
renderPassInfo.renderArea.offset = {0, 0};
|
renderPassInfo.renderArea.offset = {0, 0};
|
||||||
renderPassInfo.renderArea.extent = mSwapChainExtent;
|
renderPassInfo.renderArea.extent = mSwapChainExtent;
|
||||||
|
|
||||||
VkClearValue clearColor = {{{0.5f, 0.0f, 0.5f, 1.0f}}};
|
VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
|
||||||
renderPassInfo.clearValueCount = 1;
|
renderPassInfo.clearValueCount = 1;
|
||||||
renderPassInfo.pClearValues = &clearColor;
|
renderPassInfo.pClearValues = &clearColor;
|
||||||
|
|
||||||
@ -218,6 +218,7 @@ void VulkanApp::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imag
|
|||||||
scissor.extent = mSwapChainExtent;
|
scissor.extent = mSwapChainExtent;
|
||||||
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
||||||
|
|
||||||
|
// Actually draw the vertices
|
||||||
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
|
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
|
||||||
vkCmdEndRenderPass(commandBuffer);
|
vkCmdEndRenderPass(commandBuffer);
|
||||||
|
|
||||||
@ -227,32 +228,48 @@ void VulkanApp::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imag
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VulkanApp::drawFrame() {
|
void VulkanApp::drawFrame() {
|
||||||
vkWaitForFences(mLogicalDevice, 1, &mInFlightFence, VK_TRUE, UINT64_MAX);
|
uint32_t currentFrame = 0;
|
||||||
vkResetFences(mLogicalDevice, 1, &mInFlightFence);
|
VkResult result = VK_SUCCESS;
|
||||||
|
uint32_t imageIndex = 0;
|
||||||
|
|
||||||
uint32_t imageIndex;
|
vkWaitForFences(mLogicalDevice, 1, &mInFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
|
||||||
vkAcquireNextImageKHR(mLogicalDevice, mSwapChain, UINT64_MAX, mImageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
|
vkResetFences(mLogicalDevice, 1, &mInFlightFences[currentFrame]);
|
||||||
|
|
||||||
vkResetCommandBuffer(mCommandBuffer, /*VkCommandBufferResetFlagBits*/ 0);
|
|
||||||
recordCommandBuffer(mCommandBuffer, imageIndex);
|
result = vkAcquireNextImageKHR(mLogicalDevice,
|
||||||
|
mSwapChain,
|
||||||
|
UINT64_MAX,
|
||||||
|
mImageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
|
||||||
|
|
||||||
|
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||||
|
recreateSwapChain();
|
||||||
|
return;
|
||||||
|
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
|
||||||
|
throw std::runtime_error("Could not get Vulkan swap chain image!");
|
||||||
|
}
|
||||||
|
|
||||||
|
vkResetFences(mLogicalDevice, 1, &mInFlightFences[currentFrame]);
|
||||||
|
|
||||||
|
vkResetCommandBuffer(mCommandBuffers[currentFrame], /*VkCommandBufferResetFlagBits*/ 0);
|
||||||
|
recordCommandBuffer(mCommandBuffers[currentFrame], imageIndex);
|
||||||
|
|
||||||
VkSubmitInfo submitInfo{};
|
VkSubmitInfo submitInfo{};
|
||||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
|
||||||
VkSemaphore waitSemaphores[] = {mImageAvailableSemaphore};
|
VkSemaphore waitSemaphores[] = {mImageAvailableSemaphores[currentFrame]};
|
||||||
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
||||||
submitInfo.waitSemaphoreCount = 1;
|
submitInfo.waitSemaphoreCount = 1;
|
||||||
submitInfo.pWaitSemaphores = waitSemaphores;
|
submitInfo.pWaitSemaphores = waitSemaphores;
|
||||||
submitInfo.pWaitDstStageMask = waitStages;
|
submitInfo.pWaitDstStageMask = waitStages;
|
||||||
|
|
||||||
submitInfo.commandBufferCount = 1;
|
submitInfo.commandBufferCount = 1;
|
||||||
submitInfo.pCommandBuffers = &mCommandBuffer;
|
submitInfo.pCommandBuffers = &mCommandBuffers[currentFrame];
|
||||||
|
|
||||||
VkSemaphore signalSemaphores[] = {mRenderFinishedSemaphore};
|
VkSemaphore signalSemaphores[] = {mRenderFinishedSemaphores[currentFrame]};
|
||||||
submitInfo.signalSemaphoreCount = 1;
|
submitInfo.signalSemaphoreCount = 1;
|
||||||
submitInfo.pSignalSemaphores = signalSemaphores;
|
submitInfo.pSignalSemaphores = signalSemaphores;
|
||||||
|
|
||||||
if (vkQueueSubmit(mGraphicsQueue, 1, &submitInfo, mInFlightFence) != VK_SUCCESS) {
|
if (vkQueueSubmit(mGraphicsQueue, 1, &submitInfo, mInFlightFences[currentFrame]) != VK_SUCCESS) {
|
||||||
throw std::runtime_error("Could not submit Vulkan command buffer!");
|
throw std::runtime_error("Could not submit Vulkan command buffer!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,7 +285,17 @@ void VulkanApp::drawFrame() {
|
|||||||
|
|
||||||
presentInfo.pImageIndices = &imageIndex;
|
presentInfo.pImageIndices = &imageIndex;
|
||||||
|
|
||||||
vkQueuePresentKHR(mPresentQueue, &presentInfo);
|
result = vkQueuePresentKHR(mPresentQueue, &presentInfo);
|
||||||
|
|
||||||
|
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || mResized) {
|
||||||
|
mResized = false;
|
||||||
|
recreateSwapChain();
|
||||||
|
return;
|
||||||
|
} else if (result != VK_SUCCESS) {
|
||||||
|
throw std::runtime_error("Could not present Vulkan swap chain image!");
|
||||||
|
}
|
||||||
|
|
||||||
|
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanApp::init() {
|
void VulkanApp::init() {
|
||||||
@ -276,18 +303,13 @@ void VulkanApp::init() {
|
|||||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
|
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
|
||||||
//SDL_Vulkan_LoadLibrary(nullptr);
|
//SDL_Vulkan_LoadLibrary(nullptr);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
// I really hate GNOME
|
|
||||||
SDL_VideoInit("x11");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Create the window
|
// Create the window
|
||||||
mWin = SDL_CreateWindow("Vulkan+SDL2 Application",
|
mWin = SDL_CreateWindow("Vulkan+SDL2 Application",
|
||||||
SDL_WINDOWPOS_CENTERED,
|
SDL_WINDOWPOS_CENTERED,
|
||||||
SDL_WINDOWPOS_CENTERED,
|
SDL_WINDOWPOS_CENTERED,
|
||||||
mWidth,
|
mWidth,
|
||||||
mHeight,
|
mHeight,
|
||||||
SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN
|
SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE
|
||||||
);
|
);
|
||||||
|
|
||||||
if(mWin == nullptr) {
|
if(mWin == nullptr) {
|
||||||
@ -355,8 +377,12 @@ void VulkanApp::createInstance() {
|
|||||||
|
|
||||||
debugCreateInfo = {};
|
debugCreateInfo = {};
|
||||||
debugCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
debugCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
||||||
debugCreateInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
debugCreateInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
|
||||||
debugCreateInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
|
||||||
|
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
||||||
|
debugCreateInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
|
||||||
|
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
|
||||||
|
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
||||||
debugCreateInfo.pfnUserCallback = debugCallback;
|
debugCreateInfo.pfnUserCallback = debugCallback;
|
||||||
|
|
||||||
createInfo.pNext = reinterpret_cast<VkDebugUtilsMessengerCreateInfoEXT*>(&debugCreateInfo);
|
createInfo.pNext = reinterpret_cast<VkDebugUtilsMessengerCreateInfoEXT*>(&debugCreateInfo);
|
||||||
@ -415,12 +441,17 @@ void VulkanApp::createLogicalDevice() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VkPhysicalDeviceFeatures deviceFeatures{};
|
VkPhysicalDeviceFeatures deviceFeatures{};
|
||||||
|
|
||||||
|
vkGetPhysicalDeviceFeatures(mPhysicalDevice, &deviceFeatures);
|
||||||
|
|
||||||
VkDeviceCreateInfo createInfo{};
|
VkDeviceCreateInfo createInfo{};
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||||
|
|
||||||
createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
|
createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
|
||||||
createInfo.pQueueCreateInfos = queueCreateInfos.data();
|
createInfo.pQueueCreateInfos = queueCreateInfos.data();
|
||||||
|
|
||||||
|
createInfo.pEnabledFeatures = &deviceFeatures;
|
||||||
|
|
||||||
createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
|
createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
|
||||||
createInfo.ppEnabledExtensionNames = deviceExtensions.data();
|
createInfo.ppEnabledExtensionNames = deviceExtensions.data();
|
||||||
|
|
||||||
@ -493,6 +524,28 @@ void VulkanApp::createSwapChain() {
|
|||||||
mSwapChainExtent = extent;
|
mSwapChainExtent = extent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VulkanApp::recreateSwapChain() {
|
||||||
|
vkDeviceWaitIdle(mLogicalDevice);
|
||||||
|
|
||||||
|
cleanupSwapChain();
|
||||||
|
|
||||||
|
createSwapChain();
|
||||||
|
createImageViews();
|
||||||
|
createFramebuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanApp::cleanupSwapChain() {
|
||||||
|
for (VkFramebuffer framebuffer : mSwapChainFramebuffers) {
|
||||||
|
vkDestroyFramebuffer(mLogicalDevice, framebuffer, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (VkImageView imageView : mSwapChainImageViews) {
|
||||||
|
vkDestroyImageView(mLogicalDevice, imageView, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
vkDestroySwapchainKHR(mLogicalDevice, mSwapChain, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
void VulkanApp::createImageViews() {
|
void VulkanApp::createImageViews() {
|
||||||
mSwapChainImageViews.resize(mSwapChainImages.size());
|
mSwapChainImageViews.resize(mSwapChainImages.size());
|
||||||
|
|
||||||
@ -652,7 +705,12 @@ void VulkanApp::createGraphicsPipeline() {
|
|||||||
pipelineInfo.subpass = 0;
|
pipelineInfo.subpass = 0;
|
||||||
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
|
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
|
||||||
|
|
||||||
if (vkCreateGraphicsPipelines(mLogicalDevice, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &mGraphicsPipeline) != VK_SUCCESS) {
|
if (vkCreateGraphicsPipelines(mLogicalDevice,
|
||||||
|
VK_NULL_HANDLE,
|
||||||
|
1,
|
||||||
|
&pipelineInfo,
|
||||||
|
nullptr,
|
||||||
|
&mGraphicsPipeline) != VK_SUCCESS) {
|
||||||
throw std::runtime_error("Could not create Vulkan graphics pipeline!");
|
throw std::runtime_error("Could not create Vulkan graphics pipeline!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,18 +757,24 @@ void VulkanApp::createCommandPool() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VulkanApp::createCommandBuffer() {
|
void VulkanApp::createCommandBuffer() {
|
||||||
|
mCommandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
|
||||||
|
|
||||||
VkCommandBufferAllocateInfo allocInfo{};
|
VkCommandBufferAllocateInfo allocInfo{};
|
||||||
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
allocInfo.commandPool = mCommandPool;
|
allocInfo.commandPool = mCommandPool;
|
||||||
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||||
allocInfo.commandBufferCount = 1;
|
allocInfo.commandBufferCount = static_cast<uint32_t>(mCommandBuffers.size());
|
||||||
|
|
||||||
if (vkAllocateCommandBuffers(mLogicalDevice, &allocInfo, &mCommandBuffer) != VK_SUCCESS) {
|
if (vkAllocateCommandBuffers(mLogicalDevice, &allocInfo, mCommandBuffers.data()) != VK_SUCCESS) {
|
||||||
throw std::runtime_error("Could not allocate Vulkan command buffers!");
|
throw std::runtime_error("Could not allocate Vulkan command buffers!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanApp::createSyncObjects() {
|
void VulkanApp::createSyncObjects() {
|
||||||
|
mImageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
|
||||||
|
mRenderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
|
||||||
|
mInFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
|
||||||
|
|
||||||
VkSemaphoreCreateInfo semaphoreInfo{};
|
VkSemaphoreCreateInfo semaphoreInfo{};
|
||||||
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||||
|
|
||||||
@ -718,14 +782,15 @@ void VulkanApp::createSyncObjects() {
|
|||||||
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||||
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||||
|
|
||||||
VkResult imageAvailableResult = vkCreateSemaphore(mLogicalDevice, &semaphoreInfo, nullptr, &mImageAvailableSemaphore);
|
for(size_t i = 0;i<MAX_FRAMES_IN_FLIGHT;i++) {
|
||||||
VkResult renderFinishedResult = vkCreateSemaphore(mLogicalDevice, &semaphoreInfo, nullptr, &mRenderFinishedSemaphore);
|
VkResult imageAvailableResult = vkCreateSemaphore(mLogicalDevice, &semaphoreInfo, nullptr, &mImageAvailableSemaphores[i]);
|
||||||
VkResult inFlightResult = vkCreateFence(mLogicalDevice, &fenceInfo, nullptr, &mInFlightFence);
|
VkResult renderFinishedResult = vkCreateSemaphore(mLogicalDevice, &semaphoreInfo, nullptr, &mRenderFinishedSemaphores[i]);
|
||||||
|
VkResult inFlightResult = vkCreateFence(mLogicalDevice, &fenceInfo, nullptr, &mInFlightFences[i]);
|
||||||
|
|
||||||
if(imageAvailableResult != VK_SUCCESS || renderFinishedResult != VK_SUCCESS || inFlightResult != VK_SUCCESS) {
|
if(imageAvailableResult != VK_SUCCESS || renderFinishedResult != VK_SUCCESS || inFlightResult != VK_SUCCESS) {
|
||||||
throw std::runtime_error("Could not create needed semaphores or other memory handling objects for Vulkan!");
|
throw std::runtime_error("Could not create needed semaphores or other memory handling objects for Vulkan!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VulkanApp::checkDeviceExtensionSupport(VkPhysicalDevice device) {
|
bool VulkanApp::checkDeviceExtensionSupport(VkPhysicalDevice device) {
|
||||||
@ -775,8 +840,12 @@ void VulkanApp::setupDebugMessenger() {
|
|||||||
VkDebugUtilsMessengerCreateInfoEXT createInfo;
|
VkDebugUtilsMessengerCreateInfoEXT createInfo;
|
||||||
createInfo = {};
|
createInfo = {};
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
||||||
createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
|
||||||
createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
|
||||||
|
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
||||||
|
createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
|
||||||
|
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
|
||||||
|
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
||||||
createInfo.pfnUserCallback = debugCallback;
|
createInfo.pfnUserCallback = debugCallback;
|
||||||
|
|
||||||
if (CreateDebugUtilsMessengerEXT(mInstance, &createInfo, nullptr, &mDebugMessenger) != VK_SUCCESS) {
|
if (CreateDebugUtilsMessengerEXT(mInstance, &createInfo, nullptr, &mDebugMessenger) != VK_SUCCESS) {
|
||||||
@ -796,18 +865,37 @@ void VulkanApp::loop() {
|
|||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
while(mActive) {
|
while(mActive) {
|
||||||
while(SDL_PollEvent(&mEvent))
|
while(SDL_PollEvent(&mEvent)) {
|
||||||
if(mEvent.type == SDL_QUIT) {
|
switch (mEvent.type) {
|
||||||
|
case SDL_QUIT:
|
||||||
mActive = false;
|
mActive = false;
|
||||||
break;
|
break;
|
||||||
|
case SDL_WINDOWEVENT:
|
||||||
|
switch(mEvent.window.event) {
|
||||||
|
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||||
|
mResized = true;
|
||||||
|
break;
|
||||||
|
case SDL_WINDOWEVENT_MINIMIZED:
|
||||||
|
mMinimized = true;
|
||||||
|
break;
|
||||||
|
case SDL_WINDOWEVENT_RESTORED:
|
||||||
|
mMinimized = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//SDL_SetRenderDrawColor(rend, 255, 0, 0, 255);
|
//SDL_SetRenderDrawColor(rend, 255, 0, 0, 255);
|
||||||
//SDL_RenderClear(rend);
|
//SDL_RenderClear(rend);
|
||||||
|
|
||||||
//SDL_RenderPresent(rend);
|
//SDL_RenderPresent(rend);
|
||||||
drawFrame();
|
|
||||||
SDL_ShowWindow(mWin);
|
if(!mMinimized) drawFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
vkDeviceWaitIdle(mLogicalDevice);
|
vkDeviceWaitIdle(mLogicalDevice);
|
||||||
@ -815,30 +903,27 @@ void VulkanApp::loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VulkanApp::cleanup() {
|
void VulkanApp::cleanup() {
|
||||||
vkDestroySemaphore(mLogicalDevice, mImageAvailableSemaphore, nullptr);
|
cleanupSwapChain();
|
||||||
vkDestroySemaphore(mLogicalDevice, mRenderFinishedSemaphore, nullptr);
|
|
||||||
vkDestroyFence(mLogicalDevice, mInFlightFence, nullptr);
|
|
||||||
|
|
||||||
vkDestroyCommandPool(mLogicalDevice, mCommandPool, nullptr);
|
|
||||||
|
|
||||||
for (VkFramebuffer framebuffer : mSwapChainFramebuffers) {
|
|
||||||
vkDestroyFramebuffer(mLogicalDevice, framebuffer, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
vkDestroyPipeline(mLogicalDevice, mGraphicsPipeline, nullptr);
|
vkDestroyPipeline(mLogicalDevice, mGraphicsPipeline, nullptr);
|
||||||
vkDestroyPipelineLayout(mLogicalDevice, mPipelineLayout, nullptr);
|
vkDestroyPipelineLayout(mLogicalDevice, mPipelineLayout, nullptr);
|
||||||
|
|
||||||
vkDestroyRenderPass(mLogicalDevice, mRenderPass, nullptr);
|
vkDestroyRenderPass(mLogicalDevice, mRenderPass, nullptr);
|
||||||
|
|
||||||
for (VkImageView imageView : mSwapChainImageViews) {
|
for(size_t i=0;i<MAX_FRAMES_IN_FLIGHT;i++) {
|
||||||
vkDestroyImageView(mLogicalDevice, imageView, nullptr);
|
vkDestroySemaphore(mLogicalDevice, mImageAvailableSemaphores[i], nullptr);
|
||||||
|
vkDestroySemaphore(mLogicalDevice, mRenderFinishedSemaphores[i], nullptr);
|
||||||
|
vkDestroyFence(mLogicalDevice, mInFlightFences[i], nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
vkDestroySwapchainKHR(mLogicalDevice, mSwapChain, nullptr);
|
vkDestroyCommandPool(mLogicalDevice, mCommandPool, nullptr);
|
||||||
|
|
||||||
vkDestroyDevice(mLogicalDevice, nullptr);
|
vkDestroyDevice(mLogicalDevice, nullptr);
|
||||||
|
|
||||||
if (enableValidationLayers) {
|
if (enableValidationLayers) {
|
||||||
DestroyDebugUtilsMessengerEXT(mInstance, mDebugMessenger, nullptr);
|
DestroyDebugUtilsMessengerEXT(mInstance, mDebugMessenger, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
vkDestroySurfaceKHR(mInstance, mSurface, nullptr);
|
vkDestroySurfaceKHR(mInstance, mSurface, nullptr);
|
||||||
vkDestroyInstance(mInstance, nullptr);
|
vkDestroyInstance(mInstance, nullptr);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user