From e0b7e93bd88236b461dc177620df3ce112c212b5 Mon Sep 17 00:00:00 2001 From: pupbrained Date: Tue, 1 Oct 2024 18:30:31 -0400 Subject: [PATCH] FInished graphics pipeline basics --- .envrc | 1 + flake.nix | 1 + src/main.cpp | 179 ++++++++++++++++++++++++++++++++++++++-- src/shaders/frag.spv | Bin 0 -> 572 bytes src/shaders/shader.frag | 9 ++ src/shaders/shader.vert | 20 +++++ src/shaders/shaderc | 7 ++ src/shaders/vert.spv | Bin 0 -> 1504 bytes 8 files changed, 209 insertions(+), 8 deletions(-) create mode 100644 src/shaders/frag.spv create mode 100644 src/shaders/shader.frag create mode 100644 src/shaders/shader.vert create mode 100755 src/shaders/shaderc create mode 100644 src/shaders/vert.spv diff --git a/.envrc b/.envrc index c4b17d7..78f3220 100644 --- a/.envrc +++ b/.envrc @@ -1 +1,2 @@ +PATH_add ./src/shaders use_flake diff --git a/flake.nix b/flake.nix index 913b99a..33adc34 100644 --- a/flake.nix +++ b/flake.nix @@ -42,6 +42,7 @@ fmt glfw glm + shaderc vulkan-extension-layer vulkan-memory-allocator vulkan-utility-libraries diff --git a/src/main.cpp b/src/main.cpp index b83d866..3d12239 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -61,6 +62,10 @@ class VulkanApp { vk::Extent2D mSwapChainExtent; std::vector mSwapChainImageViews; + vk::UniqueRenderPass mRenderPass; + vk::UniquePipelineLayout mPipelineLayout; + vk::UniquePipeline mGraphicsPipeline; + struct QueueFamilyIndices { std::optional graphics_family; std::optional present_family; @@ -74,6 +79,23 @@ class VulkanApp { std::vector present_modes; }; + static fn readFile(const std::string& filename) -> std::vector { + std::ifstream file(filename, std::ios::ate | std::ios::binary); + + if (!file.is_open()) + throw std::runtime_error("Failed to open file! " + filename); + + usize fileSize = static_cast(file.tellg()); + std::vector buffer(fileSize); + + file.seekg(0); + file.read(buffer.data(), static_cast(fileSize)); + + file.close(); + + return buffer; + } + fn initWindow() -> void { mGLFWInstance = vkfw::initUnique(); @@ -93,6 +115,8 @@ class VulkanApp { createLogicalDevice(); createSwapChain(); createImageViews(); + createRenderPass(); + createGraphicsPipeline(); } fn mainLoop() -> void { @@ -254,7 +278,7 @@ class VulkanApp { .preTransform = swapChainSupport.capabilities.currentTransform, .compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque, .presentMode = presentMode, - .clipped = VK_TRUE, + .clipped = vk::True, .oldSwapchain = nullptr, }; @@ -274,20 +298,159 @@ class VulkanApp { .viewType = vk::ImageViewType::e2D, .format = mSwapChainImageFormat, .components = { .r = vk::ComponentSwizzle::eIdentity, - .g = vk::ComponentSwizzle::eIdentity, - .b = vk::ComponentSwizzle::eIdentity, - .a = vk::ComponentSwizzle::eIdentity }, + .g = vk::ComponentSwizzle::eIdentity, + .b = vk::ComponentSwizzle::eIdentity, + .a = vk::ComponentSwizzle::eIdentity }, .subresourceRange = { .aspectMask = vk::ImageAspectFlagBits::eColor, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1 }, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1 }, }; mSwapChainImageViews[i] = mDevice->createImageViewUnique(createInfo); } } + fn createRenderPass() -> void { + vk::AttachmentDescription colorAttachment { + .format = mSwapChainImageFormat, + .samples = vk::SampleCountFlagBits::e1, + .loadOp = vk::AttachmentLoadOp::eClear, + .storeOp = vk::AttachmentStoreOp::eStore, + .stencilLoadOp = vk::AttachmentLoadOp::eDontCare, + .stencilStoreOp = vk::AttachmentStoreOp::eDontCare, + .initialLayout = vk::ImageLayout::eUndefined, + .finalLayout = vk::ImageLayout::ePresentSrcKHR, + }; + + vk::AttachmentReference colorAttachmentRef { + .attachment = 0, + .layout = vk::ImageLayout::eColorAttachmentOptimal, + }; + + vk::SubpassDescription subpass { + .pipelineBindPoint = vk::PipelineBindPoint::eGraphics, + .colorAttachmentCount = 1, + .pColorAttachments = &colorAttachmentRef, + }; + + vk::RenderPassCreateInfo renderPassInfo { + .attachmentCount = 1, + .pAttachments = &colorAttachment, + .subpassCount = 1, + .pSubpasses = &subpass, + }; + + mRenderPass = mDevice->createRenderPassUnique(renderPassInfo); + } + + fn createGraphicsPipeline() -> void { + std::vector vertShaderCode = readFile("src/shaders/vert.spv"); + std::vector fragShaderCode = readFile("src/shaders/frag.spv"); + + vk::UniqueShaderModule vertShaderModule = createShaderModule(vertShaderCode); + vk::UniqueShaderModule fragShaderModule = createShaderModule(fragShaderCode); + + vk::PipelineShaderStageCreateInfo vertShaderStageInfo { + .stage = vk::ShaderStageFlagBits::eVertex, + .module = vertShaderModule.get(), + .pName = "main", + }; + + vk::PipelineShaderStageCreateInfo fragShaderStageInfo { + .stage = vk::ShaderStageFlagBits::eFragment, + .module = fragShaderModule.get(), + .pName = "main", + }; + + std::array shaderStages = { vertShaderStageInfo, + fragShaderStageInfo }; + + vk::PipelineVertexInputStateCreateInfo vertexInputInfo { + .vertexBindingDescriptionCount = 0, + .pVertexBindingDescriptions = nullptr, + .vertexAttributeDescriptionCount = 0, + .pVertexAttributeDescriptions = nullptr, + }; + + vk::PipelineInputAssemblyStateCreateInfo inputAssembly { + .topology = vk::PrimitiveTopology::eTriangleList, + .primitiveRestartEnable = vk::False, + }; + + vk::PipelineViewportStateCreateInfo viewportState { + .viewportCount = 1, + .scissorCount = 1, + }; + + vk::PipelineRasterizationStateCreateInfo rasterizer { + .depthClampEnable = vk::False, + .rasterizerDiscardEnable = vk::False, + .polygonMode = vk::PolygonMode::eFill, + .cullMode = vk::CullModeFlagBits::eBack, + .frontFace = vk::FrontFace::eClockwise, + .depthBiasEnable = vk::False, + .lineWidth = 1.0F, + }; + + vk::PipelineMultisampleStateCreateInfo multisampling { + .rasterizationSamples = vk::SampleCountFlagBits::e1, + .sampleShadingEnable = vk::False, + }; + + vk::PipelineColorBlendAttachmentState colorBlendAttachment { + .blendEnable = vk::False, + .colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | + vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA, + }; + + vk::PipelineColorBlendStateCreateInfo colorBlending { + .logicOpEnable = vk::False, + .logicOp = vk::LogicOp::eCopy, + .attachmentCount = 1, + .pAttachments = &colorBlendAttachment, + .blendConstants = std::array { 0.0F, 0.0F, 0.0F, 0.0F }, + }; + std::vector dynamicStates = { vk::DynamicState::eViewport, vk::DynamicState::eScissor }; + + vk::PipelineDynamicStateCreateInfo dynamicState { + .dynamicStateCount = static_cast(dynamicStates.size()), + .pDynamicStates = dynamicStates.data(), + }; + + vk::PipelineLayoutCreateInfo pipelineLayoutInfo { + .setLayoutCount = 0, + .pushConstantRangeCount = 0, + }; + + mPipelineLayout = mDevice->createPipelineLayoutUnique(pipelineLayoutInfo); + + vk::GraphicsPipelineCreateInfo pipelineInfo { + .stageCount = static_cast(shaderStages.size()), + .pStages = shaderStages.data(), + .pVertexInputState = &vertexInputInfo, + .pInputAssemblyState = &inputAssembly, + .pViewportState = &viewportState, + .pRasterizationState = &rasterizer, + .pMultisampleState = &multisampling, + .pColorBlendState = &colorBlending, + .pDynamicState = &dynamicState, + .layout = mPipelineLayout.get(), + .renderPass = mRenderPass.get(), + .subpass = 0, + }; + + mGraphicsPipeline = mDevice->createGraphicsPipelineUnique(nullptr, pipelineInfo).value; + } + + fn createShaderModule(const std::vector& code) -> vk::UniqueShaderModule { + vk::ShaderModuleCreateInfo createInfo { .codeSize = code.size(), + .pCode = std::bit_cast(code.data()) }; + + return mDevice->createShaderModuleUnique(createInfo); + } + static fn chooseSwapSurfaceFormat(const std::vector& availableFormats ) -> vk::SurfaceFormatKHR { for (const auto& availableFormat : availableFormats) diff --git a/src/shaders/frag.spv b/src/shaders/frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..da37f7ede672fe162b5322c32f5938a7836409a7 GIT binary patch literal 572 zcmYk2PfNo<6vUrx)7IAhv!FMrcod2U6+zU4NG^dYet=MtD1q3NHWj@2+5A*q1n0LV z(uK*}H#=`OEEHA71Yeo8+BI6MPEqd}+{a8uKdhAl0+aGA( z6gLqLrRPob_)qk0tMXUiuge|}IP@J=^z`Vvs`?d4G32BH#;R0mT<^MFnDF)EG3?WD_tXer-10N+zk@OW-Q!$6U%CCwBbK=EWe5;z^DZB6pD_lbols z;A~j*!x>3aHS;kY(h;+8ZeOy&`7ymK{vghmXU$b^!qFcb-s$KIjvgFG49B?z%J}l= z0x|SK?oo}|e?!JvmI~dbYWN26s-mvEFI!W+9#DzNtqAiXd>L!E#+MXRzb-s0PYs+e z%-(zt{$-81PdMuF^D>sh3l;pmr?cT(i!wCuPIE=E)*Gi;5`e=TcU3Vp71u3$SQh4c z=*ctVHF^4QGps0vb2F^gd3a_3^ZuGMTo*Rxm-^|JwKs&|=o@qV%^JI$<8L*zhH;ugQp(6Q*-1WD5ekY5ZsgJ+w=n7uQ6v$J(%~2hWvAR>d7DJE${}JnT6)B z7*GDS5O0dRCFX88w^vfr+kF{*y_K4t9?H(LSvj4QYY=-~< literal 0 HcmV?d00001