diff --git a/.gitignore b/.gitignore index ae5f6c81..80afaa56 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,6 @@ ads.txt build_ebook.log temp_ebook.md ebook/*.pdf -ebook/*.epub \ No newline at end of file +ebook/*.epub +/code/build +/build diff --git a/code/09_shader_base.frag b/code/08_shader_base.frag similarity index 94% rename from code/09_shader_base.frag rename to code/08_shader_base.frag index 36176035..7c5b0e74 100644 --- a/code/09_shader_base.frag +++ b/code/08_shader_base.frag @@ -1,9 +1,9 @@ -#version 450 - -layout(location = 0) in vec3 fragColor; - -layout(location = 0) out vec4 outColor; - -void main() { - outColor = vec4(fragColor, 1.0); -} +#version 450 + +layout(location = 0) in vec3 fragColor; + +layout(location = 0) out vec4 outColor; + +void main() { + outColor = vec4(fragColor, 1.0); +} diff --git a/code/09_shader_base.vert b/code/08_shader_base.vert similarity index 94% rename from code/09_shader_base.vert rename to code/08_shader_base.vert index 9bd71d4d..f5b2f8dc 100644 --- a/code/09_shader_base.vert +++ b/code/08_shader_base.vert @@ -1,20 +1,20 @@ -#version 450 - -layout(location = 0) out vec3 fragColor; - -vec2 positions[3] = vec2[]( - vec2(0.0, -0.5), - vec2(0.5, 0.5), - vec2(-0.5, 0.5) -); - -vec3 colors[3] = vec3[]( - vec3(1.0, 0.0, 0.0), - vec3(0.0, 1.0, 0.0), - vec3(0.0, 0.0, 1.0) -); - -void main() { - gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); - fragColor = colors[gl_VertexIndex]; -} +#version 450 + +layout(location = 0) out vec3 fragColor; + +vec2 positions[3] = vec2[]( + vec2(0.0, -0.5), + vec2(0.5, 0.5), + vec2(-0.5, 0.5) +); + +vec3 colors[3] = vec3[]( + vec3(1.0, 0.0, 0.0), + vec3(0.0, 1.0, 0.0), + vec3(0.0, 0.0, 1.0) +); + +void main() { + gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); + fragColor = colors[gl_VertexIndex]; +} diff --git a/code/08_graphics_pipeline.cpp b/code/08_shader_objects.cpp similarity index 85% rename from code/08_graphics_pipeline.cpp rename to code/08_shader_objects.cpp index 4c337f75..3707f82d 100644 --- a/code/08_graphics_pipeline.cpp +++ b/code/08_shader_objects.cpp @@ -1,7 +1,9 @@ +#include "volk.h" #define GLFW_INCLUDE_VULKAN #include #include +#include #include #include #include @@ -20,7 +22,8 @@ const std::vector validationLayers = { }; const std::vector deviceExtensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + VK_EXT_SHADER_OBJECT_EXTENSION_NAME }; #ifdef NDEBUG @@ -30,16 +33,17 @@ const bool enableValidationLayers = true; #endif VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) { - auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); + auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); if (func != nullptr) { return func(instance, pCreateInfo, pAllocator, pDebugMessenger); - } else { + } + else { return VK_ERROR_EXTENSION_NOT_PRESENT; } } void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) { - auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); + auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); if (func != nullptr) { func(instance, debugMessenger, pAllocator); } @@ -63,6 +67,7 @@ struct SwapChainSupportDetails { class HelloTriangleApplication { public: void run() { + volkInitialize(); initWindow(); initVulkan(); mainLoop(); @@ -88,6 +93,9 @@ class HelloTriangleApplication { VkExtent2D swapChainExtent; std::vector swapChainImageViews; + VkShaderEXT vertShader; + VkShaderEXT fragShader; + void initWindow() { glfwInit(); @@ -119,6 +127,9 @@ class HelloTriangleApplication { vkDestroyImageView(device, imageView, nullptr); } + vkDestroyShaderEXT(device, fragShader, nullptr); + vkDestroyShaderEXT(device, vertShader, nullptr); + vkDestroySwapchainKHR(device, swapChain, nullptr); vkDestroyDevice(device, nullptr); @@ -145,7 +156,7 @@ class HelloTriangleApplication { appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.pEngineName = "No Engine"; appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.apiVersion = VK_API_VERSION_1_0; + appInfo.apiVersion = VK_API_VERSION_1_3; VkInstanceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; @@ -161,8 +172,9 @@ class HelloTriangleApplication { createInfo.ppEnabledLayerNames = validationLayers.data(); populateDebugMessengerCreateInfo(debugCreateInfo); - createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo; - } else { + createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*)&debugCreateInfo; + } + else { createInfo.enabledLayerCount = 0; createInfo.pNext = nullptr; @@ -171,6 +183,8 @@ class HelloTriangleApplication { if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { throw std::runtime_error("failed to create instance!"); } + + volkLoadInstance(instance); } void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) { @@ -225,7 +239,7 @@ class HelloTriangleApplication { QueueFamilyIndices indices = findQueueFamilies(physicalDevice); std::vector queueCreateInfos; - std::set uniqueQueueFamilies = {indices.graphicsFamily.value(), indices.presentFamily.value()}; + std::set uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() }; float queuePriority = 1.0f; for (uint32_t queueFamily : uniqueQueueFamilies) { @@ -237,7 +251,14 @@ class HelloTriangleApplication { queueCreateInfos.push_back(queueCreateInfo); } - VkPhysicalDeviceFeatures deviceFeatures{}; + VkPhysicalDeviceShaderObjectFeaturesEXT shaderObjectFeatures{}; + shaderObjectFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT; + shaderObjectFeatures.pNext = nullptr; + shaderObjectFeatures.shaderObject = VK_TRUE; + + VkPhysicalDeviceFeatures2 deviceFeatures2{}; + deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + deviceFeatures2.pNext = &shaderObjectFeatures; VkDeviceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; @@ -245,7 +266,7 @@ class HelloTriangleApplication { createInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size()); createInfo.pQueueCreateInfos = queueCreateInfos.data(); - createInfo.pEnabledFeatures = &deviceFeatures; + createInfo.pNext = &deviceFeatures2; createInfo.enabledExtensionCount = static_cast(deviceExtensions.size()); createInfo.ppEnabledExtensionNames = deviceExtensions.data(); @@ -253,7 +274,8 @@ class HelloTriangleApplication { if (enableValidationLayers) { createInfo.enabledLayerCount = static_cast(validationLayers.size()); createInfo.ppEnabledLayerNames = validationLayers.data(); - } else { + } + else { createInfo.enabledLayerCount = 0; } @@ -289,13 +311,14 @@ class HelloTriangleApplication { createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; QueueFamilyIndices indices = findQueueFamilies(physicalDevice); - uint32_t queueFamilyIndices[] = {indices.graphicsFamily.value(), indices.presentFamily.value()}; + uint32_t queueFamilyIndices[] = { indices.graphicsFamily.value(), indices.presentFamily.value() }; if (indices.graphicsFamily != indices.presentFamily) { createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; createInfo.queueFamilyIndexCount = 2; createInfo.pQueueFamilyIndices = queueFamilyIndices; - } else { + } + else { createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; } @@ -344,9 +367,35 @@ class HelloTriangleApplication { } void createGraphicsPipeline() { + auto vertShaderCode = readFile("shaders/vert.spv"); + auto fragShaderCode = readFile("shaders/frag.spv"); + + vertShader = createShaderObject(vertShaderCode, VK_SHADER_STAGE_VERTEX_BIT); + fragShader = createShaderObject(fragShaderCode, VK_SHADER_STAGE_FRAGMENT_BIT); + } + + VkShaderEXT createShaderObject(const std::vector& code, VkShaderStageFlagBits stageFlags) { + VkShaderCreateInfoEXT shaderCreateInfo{ VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT }; + shaderCreateInfo.stage = stageFlags; + shaderCreateInfo.codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT; + shaderCreateInfo.pCode = reinterpret_cast(code.data()); + shaderCreateInfo.codeSize = code.size(); + shaderCreateInfo.pName = "main"; + + VkShaderEXT shader; + if (vkCreateShadersEXT(device, 1, + &shaderCreateInfo, + nullptr, &shader) != VK_SUCCESS) { + throw std::runtime_error("failed to create shader objects!"); + } + + return shader; + } + + VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector& availableFormats) { for (const auto& availableFormat : availableFormats) { if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { @@ -370,7 +419,8 @@ class HelloTriangleApplication { VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) { if (capabilities.currentExtent.width != std::numeric_limits::max()) { return capabilities.currentExtent; - } else { + } + else { int width, height; glfwGetFramebufferSize(window, &width, &height); @@ -511,6 +561,24 @@ class HelloTriangleApplication { return true; } + static std::vector readFile(const std::string& filename) { + std::ifstream file(filename, std::ios::ate | std::ios::binary); + + if (!file.is_open()) { + throw std::runtime_error("failed to open file!"); + } + + size_t fileSize = (size_t)file.tellg(); + std::vector buffer(fileSize); + + file.seekg(0); + file.read(buffer.data(), fileSize); + + file.close(); + + return buffer; + } + static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) { std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl; @@ -523,7 +591,8 @@ int main() { try { app.run(); - } catch (const std::exception& e) { + } + catch (const std::exception& e) { std::cerr << e.what() << std::endl; return EXIT_FAILURE; } diff --git a/code/14_command_buffers.cpp b/code/09_command_buffers.cpp similarity index 65% rename from code/14_command_buffers.cpp rename to code/09_command_buffers.cpp index 8332b5b1..2c6730b1 100644 --- a/code/14_command_buffers.cpp +++ b/code/09_command_buffers.cpp @@ -1,3 +1,4 @@ +#include "volk.h" #define GLFW_INCLUDE_VULKAN #include @@ -21,7 +22,9 @@ const std::vector validationLayers = { }; const std::vector deviceExtensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + VK_EXT_SHADER_OBJECT_EXTENSION_NAME, + VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME }; #ifdef NDEBUG @@ -31,16 +34,17 @@ const bool enableValidationLayers = true; #endif VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) { - auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); + auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); if (func != nullptr) { return func(instance, pCreateInfo, pAllocator, pDebugMessenger); - } else { + } + else { return VK_ERROR_EXTENSION_NOT_PRESENT; } } void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) { - auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); + auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); if (func != nullptr) { func(instance, debugMessenger, pAllocator); } @@ -64,6 +68,7 @@ struct SwapChainSupportDetails { class HelloTriangleApplication { public: void run() { + volkInitialize(); initWindow(); initVulkan(); mainLoop(); @@ -88,11 +93,9 @@ class HelloTriangleApplication { VkFormat swapChainImageFormat; VkExtent2D swapChainExtent; std::vector swapChainImageViews; - std::vector swapChainFramebuffers; - VkRenderPass renderPass; - VkPipelineLayout pipelineLayout; - VkPipeline graphicsPipeline; + VkShaderEXT vertShader; + VkShaderEXT fragShader; VkCommandPool commandPool; VkCommandBuffer commandBuffer; @@ -114,9 +117,7 @@ class HelloTriangleApplication { createLogicalDevice(); createSwapChain(); createImageViews(); - createRenderPass(); createGraphicsPipeline(); - createFramebuffers(); createCommandPool(); createCommandBuffer(); } @@ -130,18 +131,13 @@ class HelloTriangleApplication { void cleanup() { vkDestroyCommandPool(device, commandPool, nullptr); - for (auto framebuffer : swapChainFramebuffers) { - vkDestroyFramebuffer(device, framebuffer, nullptr); - } - - vkDestroyPipeline(device, graphicsPipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyRenderPass(device, renderPass, nullptr); - for (auto imageView : swapChainImageViews) { vkDestroyImageView(device, imageView, nullptr); } + vkDestroyShaderEXT(device, fragShader, nullptr); + vkDestroyShaderEXT(device, vertShader, nullptr); + vkDestroySwapchainKHR(device, swapChain, nullptr); vkDestroyDevice(device, nullptr); @@ -168,7 +164,7 @@ class HelloTriangleApplication { appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.pEngineName = "No Engine"; appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.apiVersion = VK_API_VERSION_1_0; + appInfo.apiVersion = VK_API_VERSION_1_3; VkInstanceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; @@ -184,8 +180,9 @@ class HelloTriangleApplication { createInfo.ppEnabledLayerNames = validationLayers.data(); populateDebugMessengerCreateInfo(debugCreateInfo); - createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo; - } else { + createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*)&debugCreateInfo; + } + else { createInfo.enabledLayerCount = 0; createInfo.pNext = nullptr; @@ -194,6 +191,8 @@ class HelloTriangleApplication { if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { throw std::runtime_error("failed to create instance!"); } + + volkLoadInstance(instance); } void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) { @@ -248,7 +247,7 @@ class HelloTriangleApplication { QueueFamilyIndices indices = findQueueFamilies(physicalDevice); std::vector queueCreateInfos; - std::set uniqueQueueFamilies = {indices.graphicsFamily.value(), indices.presentFamily.value()}; + std::set uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() }; float queuePriority = 1.0f; for (uint32_t queueFamily : uniqueQueueFamilies) { @@ -260,7 +259,19 @@ class HelloTriangleApplication { queueCreateInfos.push_back(queueCreateInfo); } - VkPhysicalDeviceFeatures deviceFeatures{}; + VkPhysicalDeviceDynamicRenderingFeaturesKHR dynamicRenderingFeatures{}; + dynamicRenderingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR; + dynamicRenderingFeatures.pNext = nullptr; + dynamicRenderingFeatures.dynamicRendering = true; + + VkPhysicalDeviceShaderObjectFeaturesEXT shaderObjectFeatures{}; + shaderObjectFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT; + shaderObjectFeatures.pNext = &dynamicRenderingFeatures; + shaderObjectFeatures.shaderObject = VK_TRUE; + + VkPhysicalDeviceFeatures2 deviceFeatures2{}; + deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + deviceFeatures2.pNext = &shaderObjectFeatures; VkDeviceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; @@ -268,7 +279,7 @@ class HelloTriangleApplication { createInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size()); createInfo.pQueueCreateInfos = queueCreateInfos.data(); - createInfo.pEnabledFeatures = &deviceFeatures; + createInfo.pNext = &deviceFeatures2; createInfo.enabledExtensionCount = static_cast(deviceExtensions.size()); createInfo.ppEnabledExtensionNames = deviceExtensions.data(); @@ -276,7 +287,8 @@ class HelloTriangleApplication { if (enableValidationLayers) { createInfo.enabledLayerCount = static_cast(validationLayers.size()); createInfo.ppEnabledLayerNames = validationLayers.data(); - } else { + } + else { createInfo.enabledLayerCount = 0; } @@ -312,13 +324,14 @@ class HelloTriangleApplication { createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; QueueFamilyIndices indices = findQueueFamilies(physicalDevice); - uint32_t queueFamilyIndices[] = {indices.graphicsFamily.value(), indices.presentFamily.value()}; + uint32_t queueFamilyIndices[] = { indices.graphicsFamily.value(), indices.presentFamily.value() }; if (indices.graphicsFamily != indices.presentFamily) { createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; createInfo.queueFamilyIndexCount = 2; createInfo.pQueueFamilyIndices = queueFamilyIndices; - } else { + } + else { createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; } @@ -366,169 +379,30 @@ class HelloTriangleApplication { } } - void createRenderPass() { - VkAttachmentDescription colorAttachment{}; - colorAttachment.format = swapChainImageFormat; - colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; - colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - VkAttachmentReference colorAttachmentRef{}; - colorAttachmentRef.attachment = 0; - colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass{}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &colorAttachmentRef; - - VkRenderPassCreateInfo renderPassInfo{}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = 1; - renderPassInfo.pAttachments = &colorAttachment; - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - - if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) { - throw std::runtime_error("failed to create render pass!"); - } - } - void createGraphicsPipeline() { auto vertShaderCode = readFile("shaders/vert.spv"); auto fragShaderCode = readFile("shaders/frag.spv"); - VkShaderModule vertShaderModule = createShaderModule(vertShaderCode); - VkShaderModule fragShaderModule = createShaderModule(fragShaderCode); - - VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; - vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; - vertShaderStageInfo.module = vertShaderModule; - vertShaderStageInfo.pName = "main"; - - VkPipelineShaderStageCreateInfo fragShaderStageInfo{}; - fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; - fragShaderStageInfo.module = fragShaderModule; - fragShaderStageInfo.pName = "main"; - - VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo}; - - VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; - vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertexInputInfo.vertexBindingDescriptionCount = 0; - vertexInputInfo.vertexAttributeDescriptionCount = 0; - - VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; - inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - inputAssembly.primitiveRestartEnable = VK_FALSE; - - VkPipelineViewportStateCreateInfo viewportState{}; - viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewportState.viewportCount = 1; - viewportState.scissorCount = 1; - - VkPipelineRasterizationStateCreateInfo rasterizer{}; - rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterizer.depthClampEnable = VK_FALSE; - rasterizer.rasterizerDiscardEnable = VK_FALSE; - rasterizer.polygonMode = VK_POLYGON_MODE_FILL; - rasterizer.lineWidth = 1.0f; - rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; - rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; - rasterizer.depthBiasEnable = VK_FALSE; - - VkPipelineMultisampleStateCreateInfo multisampling{}; - multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisampling.sampleShadingEnable = VK_FALSE; - multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - - VkPipelineColorBlendAttachmentState colorBlendAttachment{}; - colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - colorBlendAttachment.blendEnable = VK_FALSE; - - VkPipelineColorBlendStateCreateInfo colorBlending{}; - colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - colorBlending.logicOpEnable = VK_FALSE; - colorBlending.logicOp = VK_LOGIC_OP_COPY; - colorBlending.attachmentCount = 1; - colorBlending.pAttachments = &colorBlendAttachment; - colorBlending.blendConstants[0] = 0.0f; - colorBlending.blendConstants[1] = 0.0f; - colorBlending.blendConstants[2] = 0.0f; - colorBlending.blendConstants[3] = 0.0f; - - std::vector dynamicStates = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR - }; - VkPipelineDynamicStateCreateInfo dynamicState{}; - dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamicState.dynamicStateCount = static_cast(dynamicStates.size()); - dynamicState.pDynamicStates = dynamicStates.data(); - - VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; - pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipelineLayoutInfo.setLayoutCount = 0; - pipelineLayoutInfo.pushConstantRangeCount = 0; - - if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) { - throw std::runtime_error("failed to create pipeline layout!"); - } - - VkGraphicsPipelineCreateInfo pipelineInfo{}; - pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineInfo.stageCount = 2; - pipelineInfo.pStages = shaderStages; - pipelineInfo.pVertexInputState = &vertexInputInfo; - pipelineInfo.pInputAssemblyState = &inputAssembly; - pipelineInfo.pViewportState = &viewportState; - pipelineInfo.pRasterizationState = &rasterizer; - pipelineInfo.pMultisampleState = &multisampling; - pipelineInfo.pColorBlendState = &colorBlending; - pipelineInfo.pDynamicState = &dynamicState; - pipelineInfo.layout = pipelineLayout; - pipelineInfo.renderPass = renderPass; - pipelineInfo.subpass = 0; - pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; - - if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) { - throw std::runtime_error("failed to create graphics pipeline!"); - } - - vkDestroyShaderModule(device, fragShaderModule, nullptr); - vkDestroyShaderModule(device, vertShaderModule, nullptr); - } - - void createFramebuffers() { - swapChainFramebuffers.resize(swapChainImageViews.size()); - - for (size_t i = 0; i < swapChainImageViews.size(); i++) { - VkImageView attachments[] = { - swapChainImageViews[i] - }; + vertShader = createShaderObject(vertShaderCode, VK_SHADER_STAGE_VERTEX_BIT); + fragShader = createShaderObject(fragShaderCode, VK_SHADER_STAGE_FRAGMENT_BIT); - VkFramebufferCreateInfo framebufferInfo{}; - framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebufferInfo.renderPass = renderPass; - framebufferInfo.attachmentCount = 1; - framebufferInfo.pAttachments = attachments; - framebufferInfo.width = swapChainExtent.width; - framebufferInfo.height = swapChainExtent.height; - framebufferInfo.layers = 1; - - if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) { - throw std::runtime_error("failed to create framebuffer!"); - } - } + /* + // Provide information for dynamic rendering + VkPipelineRenderingCreateInfoKHR pipeline_create{ VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR }; + pipeline_create.pNext = VK_NULL_HANDLE; + pipeline_create.colorAttachmentCount = 1; + pipeline_create.pColorAttachmentFormats = &color_rendering_format; + pipeline_create.depthAttachmentFormat = depth_format; + pipeline_create.stencilAttachmentFormat = depth_format; + + // Use the pNext to point to the rendering create struct + VkGraphicsPipelineCreateInfo graphics_create{ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO }; + graphics_create.pNext = &pipeline_create; // reference the new dynamic structure + graphics_create.renderPass = VK_NULL_HANDLE; // previously required non-null + */ } + void createCommandPool() { QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice); @@ -542,7 +416,9 @@ class HelloTriangleApplication { } } - void createCommandBuffer() { + + void createCommandBuffer() + { VkCommandBufferAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.commandPool = commandPool; @@ -554,66 +430,76 @@ class HelloTriangleApplication { } } + void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) { VkCommandBufferBeginInfo beginInfo{}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = 0; // Optional + beginInfo.pInheritanceInfo = nullptr; // Optional if (vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) { throw std::runtime_error("failed to begin recording command buffer!"); } - VkRenderPassBeginInfo renderPassInfo{}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - renderPassInfo.renderPass = renderPass; - renderPassInfo.framebuffer = swapChainFramebuffers[imageIndex]; - renderPassInfo.renderArea.offset = {0, 0}; - renderPassInfo.renderArea.extent = swapChainExtent; + // swap chain color attachment? + //transitionToColorAttachment(commandBuffer, swapchainImages[imageIndex]); - VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; - renderPassInfo.clearValueCount = 1; - renderPassInfo.pClearValues = &clearColor; - - vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); + VkRenderingAttachmentInfo colorAttachment{}; + colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; + colorAttachment.imageView = swapChainImageViews[imageIndex]; + colorAttachment.imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL; + colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + colorAttachment.clearValue = { 0.0f, 0.0f, 0.0f, 1.0f }; + + VkRenderingInfo renderingInfo{}; + renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; + renderingInfo.renderArea = { {0, 0}, swapChainExtent }; + renderingInfo.layerCount = 1; + renderingInfo.colorAttachmentCount = 1; + renderingInfo.pColorAttachments = &colorAttachment; + + vkCmdBeginRendering(commandBuffer, &renderingInfo); + { + // --- bind shader objects (NO pipeline) --- + VkShaderStageFlagBits stages[] = { + VK_SHADER_STAGE_VERTEX_BIT, + VK_SHADER_STAGE_FRAGMENT_BIT + }; - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); + VkShaderEXT shaders[] = { + vertShader, + fragShader + }; - VkViewport viewport{}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = (float) swapChainExtent.width; - viewport.height = (float) swapChainExtent.height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - vkCmdSetViewport(commandBuffer, 0, 1, &viewport); + vkCmdBindShadersEXT(commandBuffer, 2, stages, shaders); - VkRect2D scissor{}; - scissor.offset = {0, 0}; - scissor.extent = swapChainExtent; - vkCmdSetScissor(commandBuffer, 0, 1, &scissor); + } + vkCmdEndRendering(commandBuffer); - vkCmdDraw(commandBuffer, 3, 1, 0, 0); - vkCmdEndRenderPass(commandBuffer); + }; - if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) { - throw std::runtime_error("failed to record command buffer!"); - } - } - VkShaderModule createShaderModule(const std::vector& code) { - VkShaderModuleCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - createInfo.codeSize = code.size(); - createInfo.pCode = reinterpret_cast(code.data()); + VkShaderEXT createShaderObject(const std::vector& code, VkShaderStageFlagBits stageFlags) { + VkShaderCreateInfoEXT shaderCreateInfo{ VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT }; + shaderCreateInfo.stage = stageFlags; + shaderCreateInfo.codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT; + shaderCreateInfo.pCode = reinterpret_cast(code.data()); + shaderCreateInfo.codeSize = code.size(); + shaderCreateInfo.pName = "main"; - VkShaderModule shaderModule; - if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) { - throw std::runtime_error("failed to create shader module!"); + VkShaderEXT shader; + if (vkCreateShadersEXT(device, 1, + &shaderCreateInfo, + nullptr, &shader) != VK_SUCCESS) { + throw std::runtime_error("failed to create shader objects!"); } - return shaderModule; + return shader; } + VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector& availableFormats) { for (const auto& availableFormat : availableFormats) { if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { @@ -637,7 +523,8 @@ class HelloTriangleApplication { VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) { if (capabilities.currentExtent.width != std::numeric_limits::max()) { return capabilities.currentExtent; - } else { + } + else { int width, height; glfwGetFramebufferSize(window, &width, &height); @@ -785,7 +672,7 @@ class HelloTriangleApplication { throw std::runtime_error("failed to open file!"); } - size_t fileSize = (size_t) file.tellg(); + size_t fileSize = (size_t)file.tellg(); std::vector buffer(fileSize); file.seekg(0); @@ -808,7 +695,8 @@ int main() { try { app.run(); - } catch (const std::exception& e) { + } + catch (const std::exception& e) { std::cerr << e.what() << std::endl; return EXIT_FAILURE; } diff --git a/code/09_shader_modules.cpp b/code/10_dynamic_rendering.cpp similarity index 90% rename from code/09_shader_modules.cpp rename to code/10_dynamic_rendering.cpp index 9de7078c..e7929815 100644 --- a/code/09_shader_modules.cpp +++ b/code/10_dynamic_rendering.cpp @@ -1,3 +1,4 @@ +#include "volk.h" #define GLFW_INCLUDE_VULKAN #include @@ -21,7 +22,9 @@ const std::vector validationLayers = { }; const std::vector deviceExtensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + VK_EXT_SHADER_OBJECT_EXTENSION_NAME, + VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME, }; #ifdef NDEBUG @@ -64,6 +67,7 @@ struct SwapChainSupportDetails { class HelloTriangleApplication { public: void run() { + volkInitialize(); initWindow(); initVulkan(); mainLoop(); @@ -89,6 +93,9 @@ class HelloTriangleApplication { VkExtent2D swapChainExtent; std::vector swapChainImageViews; + VkShaderEXT vertShader; + VkShaderEXT fragShader; + void initWindow() { glfwInit(); @@ -120,6 +127,9 @@ class HelloTriangleApplication { vkDestroyImageView(device, imageView, nullptr); } + vkDestroyShaderEXT(device, fragShader, nullptr); + vkDestroyShaderEXT(device, vertShader, nullptr); + vkDestroySwapchainKHR(device, swapChain, nullptr); vkDestroyDevice(device, nullptr); @@ -146,7 +156,7 @@ class HelloTriangleApplication { appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.pEngineName = "No Engine"; appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.apiVersion = VK_API_VERSION_1_0; + appInfo.apiVersion = VK_API_VERSION_1_3; VkInstanceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; @@ -172,6 +182,8 @@ class HelloTriangleApplication { if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { throw std::runtime_error("failed to create instance!"); } + + volkLoadInstance(instance); } void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) { @@ -238,7 +250,15 @@ class HelloTriangleApplication { queueCreateInfos.push_back(queueCreateInfo); } - VkPhysicalDeviceFeatures deviceFeatures{}; + VkPhysicalDeviceDynamicRenderingFeatures dynamicRenderingFeature{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES }; + dynamicRenderingFeature.dynamicRendering = VK_TRUE; + + VkPhysicalDeviceShaderObjectFeaturesEXT shaderObjectFeature { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT }; + shaderObjectFeature.pNext = &dynamicRenderingFeature; + shaderObjectFeature.shaderObject = VK_TRUE; + + VkPhysicalDeviceFeatures2 deviceFeatures2{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 }; + deviceFeatures2.pNext = &shaderObjectFeature; VkDeviceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; @@ -246,7 +266,7 @@ class HelloTriangleApplication { createInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size()); createInfo.pQueueCreateInfos = queueCreateInfos.data(); - createInfo.pEnabledFeatures = &deviceFeatures; + createInfo.pNext = &deviceFeatures2; createInfo.enabledExtensionCount = static_cast(deviceExtensions.size()); createInfo.ppEnabledExtensionNames = deviceExtensions.data(); @@ -348,41 +368,33 @@ class HelloTriangleApplication { auto vertShaderCode = readFile("shaders/vert.spv"); auto fragShaderCode = readFile("shaders/frag.spv"); - VkShaderModule vertShaderModule = createShaderModule(vertShaderCode); - VkShaderModule fragShaderModule = createShaderModule(fragShaderCode); - - VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; - vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; - vertShaderStageInfo.module = vertShaderModule; - vertShaderStageInfo.pName = "main"; + vertShader = createShaderObject(vertShaderCode, VK_SHADER_STAGE_VERTEX_BIT); + fragShader = createShaderObject(fragShaderCode, VK_SHADER_STAGE_FRAGMENT_BIT); - VkPipelineShaderStageCreateInfo fragShaderStageInfo{}; - fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; - fragShaderStageInfo.module = fragShaderModule; - fragShaderStageInfo.pName = "main"; - VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo}; - vkDestroyShaderModule(device, fragShaderModule, nullptr); - vkDestroyShaderModule(device, vertShaderModule, nullptr); } - VkShaderModule createShaderModule(const std::vector& code) { - VkShaderModuleCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - createInfo.codeSize = code.size(); - createInfo.pCode = reinterpret_cast(code.data()); - VkShaderModule shaderModule; - if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) { - throw std::runtime_error("failed to create shader module!"); + VkShaderEXT createShaderObject(const std::vector& code, VkShaderStageFlagBits stageFlags) { + VkShaderCreateInfoEXT shaderCreateInfo{ VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT }; + shaderCreateInfo.stage = stageFlags; + shaderCreateInfo.codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT; + shaderCreateInfo.pCode = reinterpret_cast(code.data()); + shaderCreateInfo.codeSize = code.size(); + shaderCreateInfo.pName = "main"; + + VkShaderEXT shader; + if (vkCreateShadersEXT(device, 1, + &shaderCreateInfo, + nullptr, &shader) != VK_SUCCESS) { + throw std::runtime_error("failed to create shader objects!"); } - return shaderModule; + return shader; } + VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector& availableFormats) { for (const auto& availableFormat : availableFormats) { if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 4c409f92..27124b18 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -6,6 +6,7 @@ find_package (glfw3 REQUIRED) find_package (glm REQUIRED) find_package (Vulkan REQUIRED) find_package (tinyobjloader REQUIRED) +find_package (volk REQUIRED) find_package (PkgConfig) pkg_get_variable (STB_INCLUDEDIR stb includedir) @@ -54,9 +55,11 @@ function (add_chapter CHAPTER_NAME) set_target_properties (${CHAPTER_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CHAPTER_NAME}) set_target_properties (${CHAPTER_NAME} PROPERTIES CXX_STANDARD 17) - target_link_libraries (${CHAPTER_NAME} Vulkan::Vulkan glfw) + target_link_libraries (${CHAPTER_NAME} glfw volk::volk) target_include_directories (${CHAPTER_NAME} PRIVATE ${STB_INCLUDEDIR}) + set_target_properties(${CHAPTER_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/${CHAPTER_NAME} ) + if (DEFINED CHAPTER_SHADER) set (CHAPTER_SHADER_TARGET ${CHAPTER_NAME}_shader) file (GLOB SHADER_SOURCES ${CHAPTER_SHADER}.frag ${CHAPTER_SHADER}.vert ${CHAPTER_SHADER}.comp) @@ -90,34 +93,35 @@ add_chapter (06_swap_chain_creation) add_chapter (07_image_views) -add_chapter (08_graphics_pipeline) +add_chapter (08_shader_objects + SHADER 08_shader_base) -add_chapter (09_shader_modules - SHADER 09_shader_base) +add_chapter (09_command_buffers + SHADER 08_shader_base) -add_chapter (10_fixed_functions - SHADER 09_shader_base) +add_chapter (10_dynamic_rendering + SHADER 08_shader_base) add_chapter (11_render_passes - SHADER 09_shader_base) + SHADER 08_shader_base) add_chapter (12_graphics_pipeline_complete - SHADER 09_shader_base) + SHADER 08_shader_base) add_chapter (13_framebuffers - SHADER 09_shader_base) + SHADER 08_shader_base) add_chapter (14_command_buffers - SHADER 09_shader_base) + SHADER 08_shader_base) add_chapter (15_hello_triangle - SHADER 09_shader_base) + SHADER 08_shader_base) add_chapter (16_frames_in_flight - SHADER 09_shader_base) + SHADER 08_shader_base) add_chapter (17_swap_chain_recreation - SHADER 09_shader_base) + SHADER 08_shader_base) add_chapter (18_vertex_input SHADER 18_shader_vertexbuffer diff --git a/code/create_patches.sh b/code/create_patches.sh new file mode 100644 index 00000000..8f37cc3f --- /dev/null +++ b/code/create_patches.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +# Check if at least two .cpp files exist +cpp_files=$(ls -Sr *.cpp 2>/dev/null) +file_count=$(echo "$cpp_files" | wc -l) + +if [ "$file_count" -lt 2 ]; then + echo "Need at least two .cpp files to generate patches." + exit 1 +fi + +# Initialize variables +prev_file="" +i=1 + +# Iterate through sorted .cpp files by size +for current_file in $cpp_files; do + if [ -n "$prev_file" ]; then + patch_name="patch_${i}_${prev_file}_to_${current_file}.diff" + echo "Generating patch: $patch_name" + diff -u "$prev_file" "$current_file" > "$patch_name" + i=$((i + 1)) + fi + prev_file="$current_file" +done + +echo "All patches generated." +exit 0 diff --git a/windows.sh b/windows.sh new file mode 100644 index 00000000..8a786304 --- /dev/null +++ b/windows.sh @@ -0,0 +1,54 @@ +#!/bin/bash +set -e + +exit_on_error() +{ + errcode=$? + echo "❌ Error $errcode" + echo "⚠️ The command executing at the time of the error was:" + echo "$BASH_COMMAND" + echo "on line ${BASH_LINENO[0]}" + sleep 5 + exit $errcode +} +trap exit_on_error ERR + +pushd . + +# === vcpkg setup === +VCPKG_DIR="$HOME/dev/vcpkg" # You can customize this +VCPKG_TOOLCHAIN_FILE="$VCPKG_DIR/scripts/buildsystems/vcpkg.cmake" + +# Clone vcpkg if missing +if [ ! -d "$VCPKG_DIR" ]; then + echo "📦 Cloning vcpkg..." + git clone https://github.com/microsoft/vcpkg.git "$VCPKG_DIR" +fi + +# Bootstrap vcpkg if needed +cd "$VCPKG_DIR" +echo "$VCPKG_DIR" +if [ ! -f "./vcpkg.exe" ]; then + echo "🔧 Bootstrapping vcpkg..." + ./bootstrap-vcpkg.bat +fi + +# Install required packages +echo "📥 Installing glfw3, glm, stb, volk, tinyobjloader..." +./vcpkg install glfw3 glm stb volk tinyobjloader --triplet x64-windows + +# === back to project and build === +cd "$OLDPWD" + +mkdir -p build/ +cd build + +# Configure with Visual Studio and vcpkg toolchain +echo "🛠️ Running CMake configuration with vcpkg toolchain..." +cmake -G "Visual Studio 17 2022" -A "x64" ../code \ + -DCMAKE_TOOLCHAIN_FILE="$VCPKG_TOOLCHAIN_FILE" "$@" + +popd + +echo "✅ Build system is ready. You can now build the solution in Visual Studio or with cmake --build build" +sleep 5