create graphics pipeline ...
This commit is contained in:
parent
ee8f06292d
commit
c5dd75f29f
5 changed files with 267 additions and 9 deletions
|
|
@ -5,3 +5,5 @@ set(CMAKE_CXX_STANDARD 26)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} main.cpp)
|
add_executable(${PROJECT_NAME} main.cpp)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC vulkan glfw)
|
target_link_libraries(${PROJECT_NAME} PUBLIC vulkan glfw)
|
||||||
|
|
||||||
|
file(COPY shaders DESTINATION ${PROJECT_BINARY_DIR}/)
|
||||||
242
main.cpp
242
main.cpp
|
|
@ -1,12 +1,13 @@
|
||||||
#define GLFW_INCLUDE_VULKAN
|
#define GLFW_INCLUDE_VULKAN
|
||||||
|
|
||||||
#include <cstring>
|
#include <GLFW/glfw3.h>
|
||||||
#include "GLFW/glfw3.h"
|
|
||||||
|
|
||||||
#include "iostream"
|
#include <iostream>
|
||||||
#include "stdexcept"
|
#include <stdexcept>
|
||||||
#include "cstdlib"
|
#include <cstdlib>
|
||||||
#include "vector"
|
#include <vector>
|
||||||
|
#include <cstring>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
const std::vector<const char*> deviceExtensions = {
|
const std::vector<const char*> deviceExtensions = {
|
||||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
||||||
|
|
@ -52,6 +53,8 @@ private:
|
||||||
getQueues();
|
getQueues();
|
||||||
createSwapChain();
|
createSwapChain();
|
||||||
createSwapChainImageViews();
|
createSwapChainImageViews();
|
||||||
|
createRenderPass();
|
||||||
|
createGraphicsPipeline();
|
||||||
}
|
}
|
||||||
|
|
||||||
void mainLoop() {
|
void mainLoop() {
|
||||||
|
|
@ -61,7 +64,11 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup() {
|
void cleanup() {
|
||||||
|
vkDestroyRenderPass(mDevice, mGraphicsRenderPass, nullptr);
|
||||||
|
|
||||||
|
destroyGraphicsPipeline();
|
||||||
destroySwapChainImageViews();
|
destroySwapChainImageViews();
|
||||||
|
|
||||||
vkDestroySwapchainKHR(mDevice, mSwapChain, nullptr);
|
vkDestroySwapchainKHR(mDevice, mSwapChain, nullptr);
|
||||||
vkDestroyDevice(mDevice, nullptr);
|
vkDestroyDevice(mDevice, nullptr);
|
||||||
vkDestroySurfaceKHR(mInstance, mSurface, nullptr);
|
vkDestroySurfaceKHR(mInstance, mSurface, nullptr);
|
||||||
|
|
@ -416,6 +423,219 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void createGraphicsPipeline() {
|
||||||
|
std::vector<char> 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<char> 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<VkDynamicState> 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<char>& 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<char> 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<char> buffer(fileSize);
|
||||||
|
|
||||||
|
file.seekg(0);
|
||||||
|
file.read(buffer.data(), (std::streamsize) fileSize);
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLFWwindow* mWindow = nullptr;
|
GLFWwindow* mWindow = nullptr;
|
||||||
|
|
||||||
|
|
@ -430,14 +650,18 @@ private:
|
||||||
VkQueue mPresentQueue = VK_NULL_HANDLE;
|
VkQueue mPresentQueue = VK_NULL_HANDLE;
|
||||||
|
|
||||||
VkSurfaceKHR mSurface = VK_NULL_HANDLE;
|
VkSurfaceKHR mSurface = VK_NULL_HANDLE;
|
||||||
|
|
||||||
VkSwapchainKHR mSwapChain = VK_NULL_HANDLE;
|
VkSwapchainKHR mSwapChain = VK_NULL_HANDLE;
|
||||||
|
|
||||||
VkFormat mSwapChainFormat {};
|
VkFormat mSwapChainFormat {};
|
||||||
VkExtent2D mSwapChainExtent {};
|
VkExtent2D mSwapChainExtent {};
|
||||||
|
|
||||||
std::vector<VkImage> mSwapChainImages;
|
std::vector<VkImage> mSwapChainImages;
|
||||||
std::vector<VkImageView> mSwapChainImageViews;
|
std::vector<VkImageView> 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() {
|
int main() {
|
||||||
|
|
|
||||||
4
shaders/compile.sh
Executable file
4
shaders/compile.sh
Executable file
|
|
@ -0,0 +1,4 @@
|
||||||
|
mkdir ../bin
|
||||||
|
|
||||||
|
glslc shader.vert -o ../bin/vert.spv
|
||||||
|
glslc shader.frag -o ../bin/frag.spv
|
||||||
8
shaders/shader.frag
Normal file
8
shaders/shader.frag
Normal file
|
|
@ -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);
|
||||||
|
}
|
||||||
20
shaders/shader.vert
Normal file
20
shaders/shader.vert
Normal file
|
|
@ -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];
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue