Remove VDeleter garbage, and add working release target build config

This commit is contained in:
Darren VanBuren 2018-04-05 21:28:49 -07:00
parent 7c2ba102a3
commit 868c4a0975
3 changed files with 114 additions and 95 deletions

View file

@ -61,8 +61,12 @@
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>D:\Code\GLFW3\include;C:\VulkanSDK\1.0.46.0\Include;$(IncludePath)</IncludePath> <IncludePath>D:\Code\GLFW3\include;C:\VulkanSDK\1.1.70.1\Include;$(IncludePath)</IncludePath>
<LibraryPath>C:\VulkanSDK\1.0.46.0\Lib;D:\Code\GLFW3\win64\lib-vc2015;$(LibraryPath)</LibraryPath> <LibraryPath>C:\VulkanSDK\1.1.70.1\Lib;D:\Code\GLFW3\win64\lib-vc2015;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>D:\Code\GLFW3\include;C:\VulkanSDK\1.1.70.1\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
<LibraryPath>C:\VulkanSDK\1.1.70.1\Lib;D:\Code\GLFW3\win64\lib-vc2015;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64</LibraryPath>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup> <ItemDefinitionGroup>
</ItemDefinitionGroup> </ItemDefinitionGroup>

140
main.cpp
View file

@ -61,26 +61,26 @@ public:
private: private:
// Instance variables: // Instance variables:
GLFWwindow* window; GLFWwindow* window;
VDeleter<VkInstance> instance {vkDestroyInstance}; VkInstance instance;
VDeleter<VkDebugReportCallbackEXT> callback {instance, DestroyDebugReportCallbackEXT}; VkDebugReportCallbackEXT callback;
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
VkQueue graphicsQueue; VkQueue graphicsQueue;
VDeleter<VkDevice> device {vkDestroyDevice}; VkDevice device;
VDeleter<VkSurfaceKHR> surface {instance, vkDestroySurfaceKHR}; VkSurfaceKHR surface;
VkQueue presentQueue; VkQueue presentQueue;
VDeleter<VkSwapchainKHR> swapChain {device, vkDestroySwapchainKHR}; VkSwapchainKHR swapChain;
std::vector<VkImage> swapChainImages; std::vector<VkImage> swapChainImages;
VkFormat swapChainImageFormat; VkFormat swapChainImageFormat;
VkExtent2D swapChainExtent; VkExtent2D swapChainExtent;
std::vector<VDeleter<VkImageView>> swapChainImageViews; std::vector<VkImageView> swapChainImageViews;
VDeleter<VkRenderPass> renderPass {device, vkDestroyRenderPass}; VkRenderPass renderPass;
VDeleter<VkPipelineLayout> pipelineLayout {device, vkDestroyPipelineLayout}; VkPipelineLayout pipelineLayout;
VDeleter<VkPipeline> graphicsPipeline {device, vkDestroyPipeline}; VkPipeline graphicsPipeline;
std::vector<VDeleter<VkFramebuffer>> swapChainFramebuffers; std::vector<VkFramebuffer> swapChainFramebuffers;
VDeleter<VkCommandPool> commandPool {device, vkDestroyCommandPool}; VkCommandPool commandPool;
std::vector<VkCommandBuffer> commandBuffers; std::vector<VkCommandBuffer> commandBuffers;
VDeleter<VkSemaphore> imageAvailableSemaphore {device, vkDestroySemaphore}; VkSemaphore imageAvailableSemaphore;
VDeleter<VkSemaphore> renderFinishedSemaphore {device, vkDestroySemaphore}; VkSemaphore renderFinishedSemaphore;
// Initialize our GLFW window. // Initialize our GLFW window.
@ -175,7 +175,7 @@ private:
createInfo.enabledExtensionCount = reqExtensions.size(); createInfo.enabledExtensionCount = reqExtensions.size();
createInfo.ppEnabledExtensionNames = reqExtensions.data(); createInfo.ppEnabledExtensionNames = reqExtensions.data();
if(vkCreateInstance(&createInfo, nullptr, instance.replace()) != VK_SUCCESS) { if(vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
throw std::runtime_error("failed to create Vulkan instance!"); throw std::runtime_error("failed to create Vulkan instance!");
} }
@ -192,6 +192,10 @@ private:
} }
} }
void destroyInstance() {
vkDestroyInstance(instance, nullptr);
}
// Check if the validation layers are supported.s // Check if the validation layers are supported.s
bool checkValidationLayerSupport() { bool checkValidationLayerSupport() {
uint32_t layerCount; uint32_t layerCount;
@ -227,11 +231,17 @@ private:
createInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; createInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
createInfo.pfnCallback = debugCallback; createInfo.pfnCallback = debugCallback;
if(CreateDebugReportCallbackEXT(instance, &createInfo, nullptr, callback.replace()) != VK_SUCCESS) { if(CreateDebugReportCallbackEXT(instance, &createInfo, nullptr, &callback) != VK_SUCCESS) {
throw std::runtime_error("failed to setup debug callback!"); throw std::runtime_error("failed to setup debug callback!");
} }
} }
void cleanupDebugCallback() {
if (!enableValidationLayers) return;
DestroyDebugReportCallbackEXT(instance, callback, nullptr);
}
// Pick the first suitable physical device, using isDeviceSuitable(VkPhysicalDevice) // Pick the first suitable physical device, using isDeviceSuitable(VkPhysicalDevice)
void pickPhysicalDevice() { void pickPhysicalDevice() {
uint32_t deviceCount = 0; uint32_t deviceCount = 0;
@ -368,7 +378,7 @@ private:
createInfo.enabledLayerCount = 0; createInfo.enabledLayerCount = 0;
} }
if(vkCreateDevice(physicalDevice, &createInfo, nullptr, device.replace()) != VK_SUCCESS) { if(vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
throw std::runtime_error("failed to create logical device!"); throw std::runtime_error("failed to create logical device!");
} }
@ -376,14 +386,22 @@ private:
vkGetDeviceQueue(device, indices.presentFamily, 0, &presentQueue); vkGetDeviceQueue(device, indices.presentFamily, 0, &presentQueue);
} }
void destroyLogicalDevice() {
vkDestroyDevice(device, nullptr);
}
// Have GLFW create a surface for us, this lets us not be concerned with the platform-specifics // Have GLFW create a surface for us, this lets us not be concerned with the platform-specifics
// involved in surfaces. // involved in surfaces.
void createSurface() { void createSurface() {
if(glfwCreateWindowSurface(instance, window, nullptr, surface.replace()) != VK_SUCCESS) { if(glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) {
throw std::runtime_error("failed to create window surface!"); throw std::runtime_error("failed to create window surface!");
} }
} }
void destroySurface() {
vkDestroySurfaceKHR(instance, surface, nullptr);
}
// Find out what formats and present modes the physical device supports. // Find out what formats and present modes the physical device supports.
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device) { SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device) {
SwapChainSupportDetails details; SwapChainSupportDetails details;
@ -532,8 +550,12 @@ private:
swapChainExtent = extent; swapChainExtent = extent;
} }
void destroySwapChain() {
vkDestroySwapchainKHR(device, swapChain, nullptr);
}
void createImageViews() { void createImageViews() {
swapChainImageViews.resize(swapChainImages.size(), VDeleter<VkImageView>{device, vkDestroyImageView}); swapChainImageViews.resize(swapChainImages.size(), VkImageView{});
// For each image in the swap chain create a VkImageView // For each image in the swap chain create a VkImageView
for(uint32_t i = 0; i < swapChainImages.size(); i++) { for(uint32_t i = 0; i < swapChainImages.size(); i++) {
@ -556,22 +578,28 @@ private:
createInfo.subresourceRange.baseArrayLayer = 0; createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1; createInfo.subresourceRange.layerCount = 1;
if(vkCreateImageView(device, &createInfo, nullptr, swapChainImageViews[i].replace()) != VK_SUCCESS) { if(vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) {
throw std::runtime_error("failed to create image views!"); throw std::runtime_error("failed to create image views!");
} }
} }
} }
void destroyImageViews() {
for (uint32_t i = 0; i < swapChainImages.size(); i++) {
vkDestroyImageView(device, swapChainImageViews[i], nullptr);
}
}
void createGraphicsPipeline() { void createGraphicsPipeline() {
auto vertShaderCode = readFile("shaders/vert.spv"); auto vertShaderCode = readFile("shaders/vert.spv");
auto fragShaderCode = readFile("shaders/frag.spv"); auto fragShaderCode = readFile("shaders/frag.spv");
VDeleter<VkShaderModule> vertShaderModule{device, vkDestroyShaderModule}; VkShaderModule vertShaderModule;
VDeleter<VkShaderModule> fragShaderModule{device, vkDestroyShaderModule}; VkShaderModule fragShaderModule;
createShaderModule(vertShaderCode, vertShaderModule); createShaderModule(vertShaderCode, &vertShaderModule);
createShaderModule(fragShaderCode, fragShaderModule); createShaderModule(fragShaderCode, &fragShaderModule);
VkPipelineShaderStageCreateInfo vertShaderStageInfo = {}; VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
@ -670,7 +698,7 @@ private:
pipelineLayoutInfo.setLayoutCount = 0; pipelineLayoutInfo.setLayoutCount = 0;
pipelineLayoutInfo.pSetLayouts = nullptr; pipelineLayoutInfo.pSetLayouts = nullptr;
if(vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, pipelineLayout.replace()) != VK_SUCCESS) { if(vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
throw std::runtime_error("failed to create pipeline layout!"); throw std::runtime_error("failed to create pipeline layout!");
} }
@ -696,11 +724,16 @@ private:
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
pipelineInfo.basePipelineIndex = -1; pipelineInfo.basePipelineIndex = -1;
if(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, graphicsPipeline.replace()) != VK_SUCCESS) { if(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) {
throw std::runtime_error("failed to create graphics pipeline!"); throw std::runtime_error("failed to create graphics pipeline!");
} }
} }
void destroyGraphicsPipeline() {
vkDestroyPipeline(device, graphicsPipeline, nullptr);
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
}
static std::vector<char> readFile(const std::string& filename) { static std::vector<char> readFile(const std::string& filename) {
// Start reading at end of the file, as binary. // Start reading at end of the file, as binary.
std::ifstream file(filename, std::ios::ate | std::ios::binary); std::ifstream file(filename, std::ios::ate | std::ios::binary);
@ -718,13 +751,13 @@ private:
return buffer; return buffer;
} }
void createShaderModule(const std::vector<char>& code, VDeleter<VkShaderModule>& shaderModule) { void createShaderModule(const std::vector<char>& code, VkShaderModule* shaderModule) {
VkShaderModuleCreateInfo createInfo = {}; VkShaderModuleCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.codeSize = code.size(); createInfo.codeSize = code.size();
createInfo.pCode = (uint32_t*) code.data(); createInfo.pCode = (uint32_t*) code.data();
if(vkCreateShaderModule(device, &createInfo, nullptr, shaderModule.replace()) != VK_SUCCESS) { if(vkCreateShaderModule(device, &createInfo, nullptr, shaderModule) != VK_SUCCESS) {
throw std::runtime_error("failed to create shader module!"); throw std::runtime_error("failed to create shader module!");
} }
} }
@ -770,13 +803,17 @@ private:
renderPassInfo.dependencyCount = 1; renderPassInfo.dependencyCount = 1;
renderPassInfo.pDependencies = &dependency; renderPassInfo.pDependencies = &dependency;
if(vkCreateRenderPass(device, &renderPassInfo, nullptr, renderPass.replace()) != VK_SUCCESS) { if(vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {
throw std::runtime_error("failed to create render pass!"); throw std::runtime_error("failed to create render pass!");
} }
} }
void destroyRenderPass() {
vkDestroyRenderPass(device, renderPass, nullptr);
}
void createFramebuffers() { void createFramebuffers() {
swapChainFramebuffers.resize(swapChainImageViews.size(), VDeleter<VkFramebuffer> {device, vkDestroyFramebuffer}); swapChainFramebuffers.resize(swapChainImageViews.size(), VkFramebuffer{});
for(size_t i = 0; i < swapChainImageViews.size(); i++) { for(size_t i = 0; i < swapChainImageViews.size(); i++) {
VkImageView attachments[] = { swapChainImageViews[i] }; VkImageView attachments[] = { swapChainImageViews[i] };
@ -790,13 +827,19 @@ private:
framebufferInfo.height = swapChainExtent.height; framebufferInfo.height = swapChainExtent.height;
framebufferInfo.layers = 1; framebufferInfo.layers = 1;
if(vkCreateFramebuffer(device, &framebufferInfo, nullptr, swapChainFramebuffers[i].replace()) != VK_SUCCESS) { if(vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) {
throw std::runtime_error("failed to create framebuffer!"); throw std::runtime_error("failed to create framebuffer!");
} }
} }
} }
void destroyFramebuffers() {
for (size_t i = 0; i < swapChainImageViews.size(); i++) {
vkDestroyFramebuffer(device, swapChainFramebuffers[i], nullptr);
}
}
void createCommandPool() { void createCommandPool() {
QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice); QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice);
@ -805,11 +848,15 @@ private:
poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily; poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily;
poolInfo.flags = 0; poolInfo.flags = 0;
if(vkCreateCommandPool(device, &poolInfo, nullptr, commandPool.replace()) != VK_SUCCESS) { if(vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) {
throw std::runtime_error("failed to create command pool!"); throw std::runtime_error("failed to create command pool!");
} }
} }
void destroyCommandPool() {
vkDestroyCommandPool(device, commandPool, nullptr);
}
void createCommandBuffers() { void createCommandBuffers() {
if(commandBuffers.size() > 0) { if(commandBuffers.size() > 0) {
vkFreeCommandBuffers(device, commandPool, commandBuffers.size(), commandBuffers.data()); vkFreeCommandBuffers(device, commandPool, commandBuffers.size(), commandBuffers.data());
@ -860,16 +907,27 @@ private:
} }
} }
void destroyCommandBuffers() {
if (commandBuffers.size() > 0) {
vkFreeCommandBuffers(device, commandPool, commandBuffers.size(), commandBuffers.data());
}
}
void createSemaphores() { void createSemaphores() {
VkSemaphoreCreateInfo semaphoreInfo = {}; VkSemaphoreCreateInfo semaphoreInfo = {};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
if(vkCreateSemaphore(device, &semaphoreInfo, nullptr, imageAvailableSemaphore.replace()) != VK_SUCCESS || if(vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphore) != VK_SUCCESS ||
vkCreateSemaphore(device, &semaphoreInfo, nullptr, renderFinishedSemaphore.replace()) != VK_SUCCESS) { vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphore) != VK_SUCCESS) {
throw std::runtime_error("failed to create semaphores!"); throw std::runtime_error("failed to create semaphores!");
} }
} }
void destroySemaphores() {
vkDestroySemaphore(device, imageAvailableSemaphore, nullptr);
vkDestroySemaphore(device, renderFinishedSemaphore, nullptr);
}
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)) {
@ -878,6 +936,22 @@ private:
} }
vkDeviceWaitIdle(device); vkDeviceWaitIdle(device);
cleanup();
}
void cleanup() {
destroySemaphores();
destroyCommandBuffers();
destroyCommandPool();
destroyFramebuffers();
destroyGraphicsPipeline();
destroyRenderPass();
destroyImageViews();
destroySwapChain();
destroyLogicalDevice();
destroySurface();
cleanupDebugCallback();
destroyInstance();
} }
void drawFrame() { void drawFrame() {

59
main.h
View file

@ -16,65 +16,6 @@ void DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT
} }
} }
// VDeleter utility class that automatically destroys objects when they fall out of scope.
template <typename T>
class VDeleter {
public:
VDeleter() : VDeleter([](T, VkAllocationCallbacks*) {}) {}
VDeleter(std::function<void(T, VkAllocationCallbacks*)> deletef) {
this->deleter = [=](T obj) { deletef(obj, nullptr); };
}
VDeleter(const VDeleter<VkInstance>& instance, std::function<void(VkInstance, T, VkAllocationCallbacks*)> deletef) {
this->deleter = [&instance, deletef](T obj) { deletef(instance, obj, nullptr); };
}
VDeleter(const VDeleter<VkDevice>& device, std::function<void(VkDevice, T, VkAllocationCallbacks*)> deletef) {
this->deleter = [&device, deletef](T obj) { deletef(device, obj, nullptr); };
}
~VDeleter() {
cleanup();
}
const T* operator &() const {
return &object;
}
T* replace() {
cleanup();
return &object;
}
operator T() const {
return object;
}
void operator=(T rhs) {
if (rhs != object) {
cleanup();
object = rhs;
}
}
template<typename V>
bool operator==(V rhs) {
return object == T(rhs);
}
private:
T object{VK_NULL_HANDLE};
std::function<void(T)> deleter;
void cleanup() {
if (object != VK_NULL_HANDLE) {
deleter(object);
}
object = VK_NULL_HANDLE;
}
};
struct QueueFamilyIndices { struct QueueFamilyIndices {
int graphicsFamily = -1; int graphicsFamily = -1;
int presentFamily = -1; int presentFamily = -1;