From c5dd75f29fb8448bb916d6fb2b6f2a94fdaddf92 Mon Sep 17 00:00:00 2001 From: IlyaShurupov Date: Fri, 8 Nov 2024 14:11:44 +0300 Subject: [PATCH] create graphics pipeline ... --- CMakeLists.txt | 2 + main.cpp | 242 ++++++++++++++++++++++++++++++++++++++++++-- shaders/compile.sh | 4 + shaders/shader.frag | 8 ++ shaders/shader.vert | 20 ++++ 5 files changed, 267 insertions(+), 9 deletions(-) create mode 100755 shaders/compile.sh create mode 100644 shaders/shader.frag create mode 100644 shaders/shader.vert diff --git a/CMakeLists.txt b/CMakeLists.txt index be7aab9..02c4c10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,3 +5,5 @@ set(CMAKE_CXX_STANDARD 26) add_executable(${PROJECT_NAME} main.cpp) target_link_libraries(${PROJECT_NAME} PUBLIC vulkan glfw) + +file(COPY shaders DESTINATION ${PROJECT_BINARY_DIR}/) \ No newline at end of file diff --git a/main.cpp b/main.cpp index a8e00d3..aa26a4c 100644 --- a/main.cpp +++ b/main.cpp @@ -1,12 +1,13 @@ #define GLFW_INCLUDE_VULKAN -#include -#include "GLFW/glfw3.h" +#include -#include "iostream" -#include "stdexcept" -#include "cstdlib" -#include "vector" +#include +#include +#include +#include +#include +#include const std::vector deviceExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, @@ -52,6 +53,8 @@ private: getQueues(); createSwapChain(); createSwapChainImageViews(); + createRenderPass(); + createGraphicsPipeline(); } void mainLoop() { @@ -61,7 +64,11 @@ private: } void cleanup() { + vkDestroyRenderPass(mDevice, mGraphicsRenderPass, nullptr); + + destroyGraphicsPipeline(); destroySwapChainImageViews(); + vkDestroySwapchainKHR(mDevice, mSwapChain, nullptr); vkDestroyDevice(mDevice, nullptr); vkDestroySurfaceKHR(mInstance, mSurface, nullptr); @@ -416,6 +423,219 @@ private: } } + void createGraphicsPipeline() { + std::vector vertShaderByteCode = readFile("bin/vert.spv"); + mShaderModuleVert = createShaderModule(vertShaderByteCode); + + VkPipelineShaderStageCreateInfo vertShaderStageCreateInfo { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_VERTEX_BIT, + .module = mShaderModuleVert, + .pName = "main", + }; + + std::vector fragShaderByteCode = readFile("bin/frag.spv"); + mShaderModuleFrag = createShaderModule(fragShaderByteCode); + + VkPipelineShaderStageCreateInfo fragShaderStageCreateInfo { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_FRAGMENT_BIT, + .module = mShaderModuleFrag, + .pName = "main", + }; + + VkPipelineShaderStageCreateInfo shaderStageCreateInfos[] = { + vertShaderStageCreateInfo, + fragShaderStageCreateInfo + }; + + std::vector dynamicStates = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + }; + + VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + .dynamicStateCount = (uint32_t) dynamicStates.size(), + .pDynamicStates = dynamicStates.data(), + }; + + VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + .vertexBindingDescriptionCount = 0, + .vertexAttributeDescriptionCount = 0, + }; + + VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo { + .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + .primitiveRestartEnable = VK_FALSE, + }; + + VkViewport viewport { + .x = 0, + .y = 0, + .width = (float) mSwapChainExtent.width, + .height = (float) mSwapChainExtent.height, + .minDepth = 0.f, + .maxDepth = 1.f, + }; + + VkRect2D scissor { + .offset = { 0, 0 }, + .extent = mSwapChainExtent, + }; + + VkPipelineViewportStateCreateInfo viewportState { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + .viewportCount = 1, + .pViewports = &viewport, + .scissorCount = 1, + .pScissors = &scissor, + }; + + VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + .depthClampEnable = VK_FALSE, + .rasterizerDiscardEnable = VK_FALSE, + .polygonMode = VK_POLYGON_MODE_FILL, + .cullMode = VK_CULL_MODE_BACK_BIT, + .frontFace = VK_FRONT_FACE_CLOCKWISE, + + .depthBiasEnable = VK_FALSE, + .depthBiasConstantFactor = 0.f, + .depthBiasClamp = 0.f, + .depthBiasSlopeFactor = 0.f, + + .lineWidth = 1, + }; + + VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo { + .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, + .sampleShadingEnable = VK_FALSE, + }; + + VkPipelineColorBlendAttachmentState colorBlendAttachmentState { + .blendEnable = VK_FALSE, + .colorWriteMask = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | + VK_COLOR_COMPONENT_A_BIT), + }; + + VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo { + .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + .logicOpEnable = VK_FALSE, + .attachmentCount = 1, + .pAttachments = &colorBlendAttachmentState, + }; + + + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + }; + + if (vkCreatePipelineLayout(mDevice, &pipelineLayoutCreateInfo, nullptr, &mGraphicsPipelineLayout) != VK_SUCCESS) { + throw std::runtime_error("failed to create pipeline layout"); + } + + VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo { + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .stageCount = 1, + .pStages = shaderStageCreateInfos, + .pVertexInputState = &vertexInputStateCreateInfo, + .pInputAssemblyState = &inputAssemblyStateCreateInfo, + .pViewportState = &viewportState, + .pRasterizationState = &rasterizationStateCreateInfo, + .pMultisampleState = &multisampleStateCreateInfo, + .pColorBlendState = &colorBlendStateCreateInfo, + .pDynamicState = &dynamicStateCreateInfo, + .layout = mGraphicsPipelineLayout, + .renderPass = mGraphicsRenderPass, + .subpass = 0, + }; + + if (vkCreateGraphicsPipelines(mDevice, nullptr, 1, &graphicsPipelineCreateInfo, nullptr, &mGraphicsPipeline) != VK_SUCCESS) { + throw std::runtime_error("failed to create graphics pipeline"); + } + } + + void createRenderPass() { + VkAttachmentDescription colorAttachment { + .format = mSwapChainFormat, + .samples = VK_SAMPLE_COUNT_1_BIT, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + }; + + VkAttachmentReference colorAttachmentReference { + .attachment = 0, + .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + }; + + VkSubpassDescription subpassDescription { + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .colorAttachmentCount = 1, + .pColorAttachments = &colorAttachmentReference, + }; + + VkRenderPassCreateInfo renderPassCreateInfo { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + .attachmentCount = 1, + .pAttachments = &colorAttachment, + .subpassCount = 1, + .pSubpasses = &subpassDescription, + }; + + if (vkCreateRenderPass(mDevice, &renderPassCreateInfo, nullptr, &mGraphicsRenderPass) != VK_SUCCESS) { + throw std::runtime_error("failed to create render pass"); + } + } + + void destroyGraphicsPipeline() { + vkDestroyShaderModule(mDevice, mShaderModuleVert, nullptr); + vkDestroyShaderModule(mDevice, mShaderModuleFrag, nullptr); + vkDestroyPipelineLayout(mDevice, mGraphicsPipelineLayout, nullptr); + vkDestroyPipeline(mDevice, mGraphicsPipeline, nullptr); + } + + VkShaderModule createShaderModule(const std::vector& bytecode) { + VkShaderModuleCreateInfo createInfo { + .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + .codeSize = (uint32_t) bytecode.size(), + .pCode = (uint32_t*) bytecode.data(), + }; + + VkShaderModule shaderModule; + + if (vkCreateShaderModule(mDevice, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) { + throw std::runtime_error("cannot create shader module"); + } + + return shaderModule; + } + + 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("cannot open file"); + } + + size_t fileSize = (size_t) file.tellg(); + std::vector buffer(fileSize); + + file.seekg(0); + file.read(buffer.data(), (std::streamsize) fileSize); + + file.close(); + + return buffer; + } + private: GLFWwindow* mWindow = nullptr; @@ -430,14 +650,18 @@ private: VkQueue mPresentQueue = VK_NULL_HANDLE; VkSurfaceKHR mSurface = VK_NULL_HANDLE; - VkSwapchainKHR mSwapChain = VK_NULL_HANDLE; - VkFormat mSwapChainFormat {}; VkExtent2D mSwapChainExtent {}; - std::vector mSwapChainImages; std::vector mSwapChainImageViews; + + + VkPipeline mGraphicsPipeline = VK_NULL_HANDLE; + VkShaderModule mShaderModuleVert = VK_NULL_HANDLE; + VkShaderModule mShaderModuleFrag = VK_NULL_HANDLE; + VkRenderPass mGraphicsRenderPass = VK_NULL_HANDLE; + VkPipelineLayout mGraphicsPipelineLayout {}; // no uniforms used in the shader }; int main() { diff --git a/shaders/compile.sh b/shaders/compile.sh new file mode 100755 index 0000000..3c2f8ae --- /dev/null +++ b/shaders/compile.sh @@ -0,0 +1,4 @@ +mkdir ../bin + +glslc shader.vert -o ../bin/vert.spv +glslc shader.frag -o ../bin/frag.spv \ No newline at end of file diff --git a/shaders/shader.frag b/shaders/shader.frag new file mode 100644 index 0000000..c866683 --- /dev/null +++ b/shaders/shader.frag @@ -0,0 +1,8 @@ +#version 450 + +layout(location = 0) in vec3 vertexColor; +layout(location = 0) out vec4 outColor; + +void main() { + outColor = vec4(vertexColor, 1.f); +} \ No newline at end of file diff --git a/shaders/shader.vert b/shaders/shader.vert new file mode 100644 index 0000000..ff4b88b --- /dev/null +++ b/shaders/shader.vert @@ -0,0 +1,20 @@ +#version 450 + +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) +); + +layout(location = 0) out vec3 fragColor; + +void main() { + gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); + fragColor = colors[gl_VertexIndex]; +} \ No newline at end of file