diff --git a/Makefile b/Makefile index 7d7e7ef..bd30a5e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ ROOT_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) -all: build test +all: build reset: ifeq '$(OS)' 'Windows_NT' diff --git a/main.cpp b/main.cpp index 53e89a9..f958ea2 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,6 @@ #include -int main(int argc, char* argv[]) +int main() { VulkanEngine engine; diff --git a/meson.build b/meson.build index 7fa2479..52bc104 100644 --- a/meson.build +++ b/meson.build @@ -7,6 +7,8 @@ project('hellovulk', 'cpp', 'cpp_args=-D_GLIBCXX_DEBUG=1 -D_GLIBCXX_DEBUG_PEDANTIC=1', ]) +cmake = import('cmake') + # use this for common options only for our executables cpp_args=[] link_args=[] @@ -54,16 +56,20 @@ elif build_machine.system() == 'darwin' endif vma = subproject('vulkan-memory-allocator').get_variable('vma_allocator_dep') -vulkanheaders = subproject('vulkan-headers').get_variable('vulkan_headers_dep') - -vkbootstrap = subproject('vk-bootstrap').get_variable('vk_bootstrap_dep') glm = subproject('glm').get_variable('glm_dep') imgui = subproject('imgui').get_variable('imgui_dep') sdl2 = subproject('sdl2').get_variable('sdl2_dep') +opts = cmake.subproject_options() +opts.add_cmake_defines({ + 'VK_BOOTSTRAP_TEST': false, + 'VK_BOOTSTRAP_INSTALL': false, +}) +vkbootstrap_proj = cmake.subproject('vk-bootstrap', options: opts) +vkbootstrap = vkbootstrap_proj.get_variable('vk_bootstrap_dep') + dependencies += [ vma, - vulkanheaders, vkbootstrap, glm, imgui, @@ -73,6 +79,7 @@ dependencies += [ sources = [ 'vk_initializers.cpp', 'vk_engine.cpp', + 'vk_images.cpp', 'main.cpp', ] diff --git a/scripts/reset_build.sh b/scripts/reset_build.sh old mode 100644 new mode 100755 diff --git a/vk_engine.cpp b/vk_engine.cpp index 073aae3..fde9c6b 100644 --- a/vk_engine.cpp +++ b/vk_engine.cpp @@ -1,5 +1,9 @@ - +/* + * Stopped at https://vkguide.dev/docs/new_chapter_1/vulkan_mainloop_code/ + */ + #include "vk_engine.h" +#include "vk_images.h" #include #include @@ -7,54 +11,282 @@ #include #include +#include "VkBootstrap.h" + +#include +#include + +constexpr bool bUseValidationLayers = false; + +VulkanEngine* loadedEngine = nullptr; + +VulkanEngine& VulkanEngine::Get() { + return *loadedEngine; +} void VulkanEngine::init() { - // We initialize SDL and create a window with it. - SDL_Init(SDL_INIT_VIDEO); + assert(loadedEngine == nullptr); + loadedEngine = this; - SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN); - - _window = SDL_CreateWindow( - "Vulkan Engine", - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - int(_windowExtent.width), - int(_windowExtent.height), - window_flags - ); - - //everything went fine - _isInitialized = true; + // We initialize SDL and create a window with it. + SDL_Init(SDL_INIT_VIDEO); + + SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN); + + _window = SDL_CreateWindow( + "Vulkan Engine", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + int(_windowExtent.width), + int(_windowExtent.height), + window_flags); + + init_vulkan(); + init_swapchain(); + init_commands(); + init_sync_structures(); + + //everything went fine + _isInitialized = true; } + void VulkanEngine::cleanup() -{ - if (_isInitialized) { - SDL_DestroyWindow(_window); - } +{ + if (_isInitialized) { + vkDeviceWaitIdle(_device); + + for(int i = 0; i < FRAME_OVERLAP; i++) { + vkDestroyCommandPool(_device, _frames[i]._commandPool, nullptr); + + //destroy sync objects + vkDestroyFence(_device, _frames[i]._renderFence, nullptr); + vkDestroySemaphore(_device, _frames[i]._renderSemaphore, nullptr); + vkDestroySemaphore(_device ,_frames[i]._swapchainSemaphore, nullptr); + } + + destroy_swapchain(); + + vkDestroySurfaceKHR(_instance, _surface, nullptr); + vkDestroyDevice(_device, nullptr); + vkb::destroy_debug_utils_messenger(_instance, _debug_messenger); + vkDestroyInstance(_instance, nullptr); + SDL_DestroyWindow(_window); + } + + loadedEngine = nullptr; } void VulkanEngine::draw() { - //nothing yet + // wait until the gpu has finished rendering the last frame. Timeout of 1 second + VK_CHECK(vkWaitForFences(_device, 1, &get_current_frame()._renderFence, true, 1000000000)); + VK_CHECK(vkResetFences(_device, 1, &get_current_frame()._renderFence)); + + uint32_t swapchainImageIndex = 0; + VK_CHECK(vkAcquireNextImageKHR(_device, _swapchain, 1000000000, get_current_frame()._swapchainSemaphore, nullptr, &swapchainImageIndex)); + + VkCommandBuffer cmd = get_current_frame()._mainCommandBuffer; + VK_CHECK(vkResetCommandBuffer(cmd, 0)); + + VkCommandBufferBeginInfo cmdBeginInfo = vkinit::command_buffer_begin_info(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); + + VK_CHECK(vkBeginCommandBuffer(cmd, &cmdBeginInfo)); + + vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL); + + VkClearColorValue clearValue; + float flash = std::abs(std::sin(_frameNumber / 120.0f)); + clearValue = { { 0.0f, 0.0f, flash, 1.0f} }; + + VkImageSubresourceRange clearRange = vkinit::image_subresource_range(VK_IMAGE_ASPECT_COLOR_BIT); + + vkCmdClearColorImage(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_GENERAL, &clearValue, 1, &clearRange); + + vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + VK_CHECK(vkEndCommandBuffer(cmd)); + + //prepare the submission to the queue. + //we want to wait on the _presentSemaphore, as that semaphore is signaled when the swapchain is ready + //we will signal the _renderSemaphore, to signal that rendering has finished + + VkCommandBufferSubmitInfo cmdinfo = vkinit::command_buffer_submit_info(cmd); + + VkSemaphoreSubmitInfo waitInfo = vkinit::semaphore_submit_info(VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,get_current_frame()._swapchainSemaphore); + VkSemaphoreSubmitInfo signalInfo = vkinit::semaphore_submit_info(VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT, get_current_frame()._renderSemaphore); + + VkSubmitInfo2 submit = vkinit::submit_info(&cmdinfo,&signalInfo,&waitInfo); + + //submit command buffer to the queue and execute it. + // _renderFence will now block until the graphic commands finish execution + VK_CHECK(vkQueueSubmit2(_graphicsQueue, 1, &submit, get_current_frame()._renderFence)); + + //prepare present + // this will put the image we just rendered to into the visible window. + // we want to wait on the _renderSemaphore for that, + // as its necessary that drawing commands have finished before the image is displayed to the user + VkPresentInfoKHR presentInfo = {}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.pNext = nullptr; + presentInfo.pSwapchains = &_swapchain; + presentInfo.swapchainCount = 1; + + presentInfo.pWaitSemaphores = &get_current_frame()._renderSemaphore; + presentInfo.waitSemaphoreCount = 1; + + presentInfo.pImageIndices = &swapchainImageIndex; + + VK_CHECK(vkQueuePresentKHR(_graphicsQueue, &presentInfo)); + + //increase the number of frames drawn + _frameNumber++; } void VulkanEngine::run() { - SDL_Event e; - bool bQuit = false; + SDL_Event e; + bool bQuit = false; + bool stop_rendering = false; - //main loop - while (!bQuit) - { - //Handle events on queue - while (SDL_PollEvent(&e) != 0) - { - //close the window when user alt-f4s or clicks the X button - if (e.type == SDL_QUIT) bQuit = true; - } + //main loop + while(!bQuit) + { + //Handle events on queue + while(SDL_PollEvent(&e) != 0) + { + //close the window when user alt-f4s or clicks the X button + if(e.type == SDL_QUIT) { + bQuit = true; + } - draw(); + if(e.type == SDL_WINDOWEVENT) { + if(e.window.event == SDL_WINDOWEVENT_MINIMIZED) { + stop_rendering = true; + } + + if(e.window.event == SDL_WINDOWEVENT_RESTORED) { + stop_rendering = false; + } + } + } + + if(stop_rendering) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + continue; + } + + draw(); + } +} + +void VulkanEngine::init_vulkan() { + vkb::InstanceBuilder builder; + + // make the vulkan instance, with basic debug features + + auto inst_ret = builder.set_app_name("Example Vulkan Application") + .request_validation_layers(bUseValidationLayers) + .use_default_debug_messenger() + .require_api_version(1, 3, 0) + .build(); + + vkb::Instance vkb_inst = inst_ret.value(); + + // grab the instance + _instance = vkb_inst.instance; + _debug_messenger = vkb_inst.debug_messenger; + + SDL_Vulkan_CreateSurface(_window, _instance, &_surface); + + //vulkan 1.3 features + VkPhysicalDeviceVulkan13Features features{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES }; + features.dynamicRendering = true; + features.synchronization2 = true; + + //vulkan 1.2 features + VkPhysicalDeviceVulkan12Features features12{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES }; + features12.bufferDeviceAddress = true; + features12.descriptorIndexing = true; + + // use vkbootstrap to select a gpu + // We want a gpu that can write to the SDL surface + vkb::PhysicalDeviceSelector selector{ vkb_inst }; + vkb::PhysicalDevice physicalDevice = selector + .set_minimum_version(1, 4) + .set_required_features_13(features) + .set_required_features_12(features12) + .set_surface(_surface) + .select() + .value(); + + vkb::DeviceBuilder deviceBuilder{physicalDevice}; + vkb::Device vkbDevice = deviceBuilder.build().value(); + + _device = vkbDevice.device; + _chosenGPU = physicalDevice.physical_device; + + _graphicsQueue = vkbDevice.get_queue(vkb::QueueType::graphics).value(); + _graphicsQueueFamily = vkbDevice.get_queue_index(vkb::QueueType::graphics).value(); +} + +void VulkanEngine::create_swapchain(uint32_t width, uint32_t height) { + vkb::SwapchainBuilder swapchainBuilder{ _chosenGPU, _device, _surface}; + + _swapchainImageFormat = VK_FORMAT_B8G8R8A8_UNORM; + + vkb::Swapchain vkbSwapchain = swapchainBuilder + //.use_default_format_selection() + .set_desired_format(VkSurfaceFormatKHR{.format=_swapchainImageFormat}) + // use vsync present mode + .set_desired_present_mode(VK_PRESENT_MODE_FIFO_KHR) + .set_desired_extent(width, height) + .add_image_usage_flags(VK_IMAGE_USAGE_TRANSFER_DST_BIT) + .build() + .value(); + + _swapchainExtent = vkbSwapchain.extent; + _swapchain = vkbSwapchain.swapchain; + _swapchainImages = vkbSwapchain.get_images().value(); + _swapchainImageViews = vkbSwapchain.get_image_views().value(); +} + +void VulkanEngine::destroy_swapchain() { + vkDestroySwapchainKHR(_device, _swapchain, nullptr); + + for(auto& view : _swapchainImageViews) { + vkDestroyImageView(_device, view, nullptr); + } +} + +void VulkanEngine::init_swapchain() { + create_swapchain(_windowExtent.width, _windowExtent.height); +} + +void VulkanEngine::init_commands() { + //create a command pool for commands submitted to the graphics queue. + //we also want the pool to allow for resetting of individual command buffers + VkCommandPoolCreateInfo commandPoolInfo = vkinit::command_pool_create_info(_graphicsQueueFamily, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); + + for (int i = 0; i < FRAME_OVERLAP; i++) { + + VK_CHECK(vkCreateCommandPool(_device, &commandPoolInfo, nullptr, &_frames[i]._commandPool)); + + // allocate the default command buffer that we will use for rendering + VkCommandBufferAllocateInfo cmdAllocInfo = vkinit::command_buffer_allocate_info(_frames[i]._commandPool, 1); + + VK_CHECK(vkAllocateCommandBuffers(_device, &cmdAllocInfo, &_frames[i]._mainCommandBuffer)); } } +void VulkanEngine::init_sync_structures() { + VkFenceCreateInfo fenceCreateInfo = vkinit::fence_create_info(VK_FENCE_CREATE_SIGNALED_BIT); + VkSemaphoreCreateInfo semaphoreCreateInfo = vkinit::semaphore_create_info(); + + for (int i = 0; i < FRAME_OVERLAP; i++) { + VK_CHECK(vkCreateFence(_device, &fenceCreateInfo, nullptr, &_frames[i]._renderFence)); + + VK_CHECK(vkCreateSemaphore(_device, &semaphoreCreateInfo, nullptr, &_frames[i]._swapchainSemaphore)); + VK_CHECK(vkCreateSemaphore(_device, &semaphoreCreateInfo, nullptr, &_frames[i]._renderSemaphore)); + } +} + diff --git a/vk_engine.h b/vk_engine.h index 3453102..18861b1 100644 --- a/vk_engine.h +++ b/vk_engine.h @@ -5,25 +5,71 @@ #include +struct FrameData { + VkCommandPool _commandPool; + VkCommandBuffer _mainCommandBuffer; + VkSemaphore _swapchainSemaphore; + VkSemaphore _renderSemaphore; + VkFence _renderFence; +}; + +constexpr unsigned int FRAME_OVERLAP=2; + class VulkanEngine { public: + // device selection + VkInstance _instance; + VkDebugUtilsMessengerEXT _debug_messenger; + VkPhysicalDevice _chosenGPU; + VkDevice _device; + VkSurfaceKHR _surface; - bool _isInitialized{ false }; - int _frameNumber {0}; + // swapchain + VkSwapchainKHR _swapchain; + VkFormat _swapchainImageFormat; - VkExtent2D _windowExtent{ 1700 , 900 }; + std::vector _swapchainImages; + std::vector _swapchainImageViews; + VkExtent2D _swapchainExtent; - struct SDL_Window* _window{ nullptr }; + // frames/command buffer + int _frameNumber {0}; + FrameData _frames[FRAME_OVERLAP]; - //initializes everything in the engine - void init(); + FrameData& get_current_frame() { + return _frames[_frameNumber % FRAME_OVERLAP]; + } - //shuts down the engine - void cleanup(); + VkQueue _graphicsQueue; + uint32_t _graphicsQueueFamily; - //draw loop - void draw(); + // internal data + bool _isInitialized{ false }; - //run main loop - void run(); + VkExtent2D _windowExtent{ 1700 , 900 }; + + struct SDL_Window* _window{ nullptr }; + + static VulkanEngine& Get(); + + //initializes everything in the engine + void init(); + + //shuts down the engine + void cleanup(); + + //draw loop + void draw(); + + //run main loop + void run(); + +private: + void init_vulkan(); + void init_swapchain(); + void init_commands(); + void init_sync_structures(); + + void create_swapchain(uint32_t width, uint32_t height); + void destroy_swapchain(); }; diff --git a/vk_images.cpp b/vk_images.cpp new file mode 100644 index 0000000..cd9e87f --- /dev/null +++ b/vk_images.cpp @@ -0,0 +1,30 @@ +#include "vk_images.h" +#include "vk_initializers.h" + +void vkutil::transition_image(VkCommandBuffer cmd, VkImage image, VkImageLayout currentLayout, VkImageLayout newLayout) +{ + VkImageMemoryBarrier2 imageBarrier {.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2}; + imageBarrier.pNext = nullptr; + + imageBarrier.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT; + imageBarrier.srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT; + imageBarrier.dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT; + imageBarrier.dstAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT | VK_ACCESS_2_MEMORY_READ_BIT; + + + imageBarrier.oldLayout = currentLayout; + imageBarrier.newLayout = newLayout; + + VkImageAspectFlags aspectMask = (newLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; + imageBarrier.subresourceRange = vkinit::image_subresource_range(aspectMask); + imageBarrier.image = image; + + VkDependencyInfo depInfo{}; + depInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO; + depInfo.pNext = nullptr; + + depInfo.imageMemoryBarrierCount = 1; + depInfo.pImageMemoryBarriers = &imageBarrier; + + vkCmdPipelineBarrier2(cmd, &depInfo); +} diff --git a/vk_images.h b/vk_images.h new file mode 100644 index 0000000..a1de765 --- /dev/null +++ b/vk_images.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +namespace vkutil { + void transition_image(VkCommandBuffer cmd, VkImage image, VkImageLayout currentLayout, VkImageLayout newLayout); +} diff --git a/vk_initializers.cpp b/vk_initializers.cpp index 604ba70..bfa9806 100644 --- a/vk_initializers.cpp +++ b/vk_initializers.cpp @@ -1 +1,110 @@ #include + +VkCommandPoolCreateInfo vkinit::command_pool_create_info(uint32_t queueFamilyIndex, + VkCommandPoolCreateFlags flags /*= 0*/) +{ + VkCommandPoolCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + info.pNext = nullptr; + info.queueFamilyIndex = queueFamilyIndex; + info.flags = flags; + return info; +} + + +VkCommandBufferAllocateInfo vkinit::command_buffer_allocate_info( + VkCommandPool pool, uint32_t count /*= 1*/) +{ + VkCommandBufferAllocateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + info.pNext = nullptr; + + info.commandPool = pool; + info.commandBufferCount = count; + info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + return info; +} + +VkFenceCreateInfo vkinit::fence_create_info(VkFenceCreateFlags flags /*=0*/) +{ + VkFenceCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + info.pNext = nullptr; + info.flags = flags; + return info; +} + +VkSemaphoreCreateInfo vkinit::semaphore_create_info(VkSemaphoreCreateFlags flags/*=0*/) +{ + VkSemaphoreCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + info.pNext = nullptr; + info.flags = flags; + return info; +} + +VkCommandBufferBeginInfo vkinit::command_buffer_begin_info(VkCommandBufferUsageFlags flags /*= 0*/) +{ + VkCommandBufferBeginInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + info.pNext = nullptr; + + info.pInheritanceInfo = nullptr; + info.flags = flags; + return info; +} + +VkImageSubresourceRange vkinit::image_subresource_range(VkImageAspectFlags aspectMask) +{ + VkImageSubresourceRange subImage {}; + subImage.aspectMask = aspectMask; + subImage.baseMipLevel = 0; + subImage.levelCount = VK_REMAINING_MIP_LEVELS; + subImage.baseArrayLayer = 0; + subImage.layerCount = VK_REMAINING_ARRAY_LAYERS; + + return subImage; +} + +VkSemaphoreSubmitInfo vkinit::semaphore_submit_info(VkPipelineStageFlags2 stageMask, VkSemaphore semaphore) +{ + VkSemaphoreSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO; + submitInfo.pNext = nullptr; + submitInfo.semaphore = semaphore; + submitInfo.stageMask = stageMask; + submitInfo.deviceIndex = 0; + submitInfo.value = 1; + + return submitInfo; +} + +VkCommandBufferSubmitInfo vkinit::command_buffer_submit_info(VkCommandBuffer cmd) +{ + VkCommandBufferSubmitInfo info{}; + info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO; + info.pNext = nullptr; + info.commandBuffer = cmd; + info.deviceMask = 0; + + return info; +} + +VkSubmitInfo2 vkinit::submit_info(VkCommandBufferSubmitInfo* cmd, VkSemaphoreSubmitInfo* signalSemaphoreInfo, + VkSemaphoreSubmitInfo* waitSemaphoreInfo) +{ + VkSubmitInfo2 info = {}; + info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2; + info.pNext = nullptr; + + info.waitSemaphoreInfoCount = waitSemaphoreInfo == nullptr ? 0 : 1; + info.pWaitSemaphoreInfos = waitSemaphoreInfo; + + info.signalSemaphoreInfoCount = signalSemaphoreInfo == nullptr ? 0 : 1; + info.pSignalSemaphoreInfos = signalSemaphoreInfo; + + info.commandBufferInfoCount = 1; + info.pCommandBufferInfos = cmd; + + return info; +} diff --git a/vk_initializers.h b/vk_initializers.h index 54de59c..bf36032 100644 --- a/vk_initializers.h +++ b/vk_initializers.h @@ -7,6 +7,24 @@ namespace vkinit { - //vulkan init code goes here + VkCommandPoolCreateInfo command_pool_create_info(uint32_t queueFamilyIndex, + VkCommandPoolCreateFlags flags=0); + + VkCommandBufferAllocateInfo command_buffer_allocate_info( + VkCommandPool pool, uint32_t count=1); + + VkFenceCreateInfo fence_create_info(VkFenceCreateFlags flags=0); + + VkSemaphoreCreateInfo semaphore_create_info(VkSemaphoreCreateFlags flags=0); + + VkCommandBufferBeginInfo command_buffer_begin_info(VkCommandBufferUsageFlags flags=0); + + VkImageSubresourceRange image_subresource_range(VkImageAspectFlags aspectMask); + + VkSemaphoreSubmitInfo semaphore_submit_info(VkPipelineStageFlags2 stageMask, VkSemaphore semaphore); + + VkCommandBufferSubmitInfo command_buffer_submit_info(VkCommandBuffer cmd); + + VkSubmitInfo2 submit_info(VkCommandBufferSubmitInfo* cmd, VkSemaphoreSubmitInfo* signalSemaphoreInfo, VkSemaphoreSubmitInfo* waitSemaphoreInfo); } diff --git a/vk_types.h b/vk_types.h index aa0a73e..d4dfc65 100644 --- a/vk_types.h +++ b/vk_types.h @@ -1,8 +1,31 @@ -// vulkan_guide.h : Include file for standard system include files, -// or project specific include files. +// or project specific include files. +//we will add our main reusable types here #pragma once #include +#include +#include +#include +#include +#include +#include +#include +#include -//we will add our main reusable types here \ No newline at end of file +#include +// #include +#include + +#include + +#include +#include + +#define VK_CHECK(x)\ + do {\ + VkResult err = x;\ + if (err) {\ + std::println("Detected Vulkan error: {}", int(err));\ + }\ + } while (0)