Deerith/graphics/src/vulkan_graphics_pipeline.cpp
2026-03-24 12:49:09 +01:00

164 lines
6.7 KiB
C++

#include "detail/graphics.h"
#include "detail/vertex_layout.h"
#include <fstream>
namespace deerith {
namespace graphics {
std::vector<char> read_file(const std::string& filename);
VkShaderModule create_shader_module(const std::vector<char>& code);
} // namespace graphics
void graphics::create_vulkan_graphics_pipeline() {
auto vert_shader_code = read_file("shaders/vert.spv");
auto frag_shader_code = read_file("shaders/frag.spv");
VkShaderModule vert_shader_module = create_shader_module(vert_shader_code);
VkShaderModule frag_shader_module = create_shader_module(frag_shader_code);
VkPipelineShaderStageCreateInfo vert_shader_stage_info{};
vert_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vert_shader_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT;
vert_shader_stage_info.module = vert_shader_module;
vert_shader_stage_info.pName = "main";
VkPipelineShaderStageCreateInfo frag_shader_stage_info{};
frag_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
frag_shader_stage_info.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
frag_shader_stage_info.module = frag_shader_module;
frag_shader_stage_info.pName = "main";
VkPipelineShaderStageCreateInfo shader_stages[] = {vert_shader_stage_info, frag_shader_stage_info};
VkPipelineVertexInputStateCreateInfo vertex_input_info{};
vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertex_input_info.vertexBindingDescriptionCount = 0;
vertex_input_info.pVertexBindingDescriptions = nullptr; // Optional
vertex_input_info.vertexAttributeDescriptionCount = 0;
vertex_input_info.pVertexAttributeDescriptions = nullptr; // Optional
VkPipelineInputAssemblyStateCreateInfo input_assembly{};
input_assembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
input_assembly.primitiveRestartEnable = VK_FALSE;
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = (float)swap_chain_extent.width;
viewport.height = (float)swap_chain_extent.height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
VkRect2D scissor{};
scissor.offset = {0, 0};
scissor.extent = swap_chain_extent;
VkPipelineViewportStateCreateInfo viewport_state{};
viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewport_state.viewportCount = 1;
viewport_state.pViewports = &viewport;
viewport_state.scissorCount = 1;
viewport_state.pScissors = &scissor;
VkPipelineRasterizationStateCreateInfo rasterizer{};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.depthBiasEnable = VK_FALSE;
rasterizer.lineWidth = 1.0f;
rasterizer.depthBiasConstantFactor = 0.0f; // Optional
rasterizer.depthBiasClamp = 0.0f; // Optional
rasterizer.depthBiasSlopeFactor = 0.0f; // Optional
VkPipelineColorBlendAttachmentState color_blend_attachment{};
color_blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
color_blend_attachment.blendEnable = VK_FALSE;
VkPipelineLayoutCreateInfo pipeline_layout_info{};
pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipeline_layout_info.setLayoutCount = 0; // Optional
pipeline_layout_info.pSetLayouts = nullptr; // Optional
pipeline_layout_info.pushConstantRangeCount = 0; // Optional
pipeline_layout_info.pPushConstantRanges = nullptr; // Optional
VkPipelineMultisampleStateCreateInfo multisampling{};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
multisampling.minSampleShading = 1.0f; // Optional
multisampling.pSampleMask = nullptr; // Optional
multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
multisampling.alphaToOneEnable = VK_FALSE; // Optional
VkPipelineColorBlendStateCreateInfo color_blending{};
color_blending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
color_blending.logicOpEnable = VK_FALSE;
color_blending.logicOp = VK_LOGIC_OP_COPY; // Optional
color_blending.attachmentCount = 1;
color_blending.pAttachments = &color_blend_attachment;
color_blending.blendConstants[0] = 0.0f; // Optional
color_blending.blendConstants[1] = 0.0f; // Optional
color_blending.blendConstants[2] = 0.0f; // Optional
color_blending.blendConstants[3] = 0.0f; // Optional
if (vkCreatePipelineLayout(device, &pipeline_layout_info, nullptr, &pipeline_layout) != VK_SUCCESS) {
deerith_graphics_error("failed to create pipeline layout!");
}
VkGraphicsPipelineCreateInfo pipline_info{};
pipline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipline_info.stageCount = 2;
pipline_info.pStages = shader_stages;
pipline_info.pVertexInputState = &vertex_input_info;
pipline_info.pInputAssemblyState = &input_assembly;
pipline_info.pViewportState = &viewport_state;
pipline_info.pRasterizationState = &rasterizer;
pipline_info.pMultisampleState = &multisampling;
pipline_info.pDepthStencilState = nullptr; // Optional
pipline_info.pColorBlendState = &color_blending;
pipline_info.pDynamicState = nullptr;
pipline_info.layout = pipeline_layout;
pipline_info.renderPass = render_pass;
pipline_info.subpass = 0;
if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipline_info, nullptr, &graphics_pipeline) != VK_SUCCESS) {
deerith_graphics_error("failed to create graphics pipeline!");
}
vkDestroyShaderModule(device, frag_shader_module, nullptr);
vkDestroyShaderModule(device, vert_shader_module, nullptr);
}
VkShaderModule graphics::create_shader_module(const std::vector<char>& code) {
VkShaderModuleCreateInfo create_info{};
create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
create_info.codeSize = code.size();
create_info.pCode = reinterpret_cast<const uint32_t*>(code.data());
VkShaderModule shader_module;
if (vkCreateShaderModule(device, &create_info, nullptr, &shader_module) != VK_SUCCESS) {
deerith_graphics_error("failed to create shader module!");
}
return shader_module;
}
std::vector<char> graphics::read_file(const std::string& filename) {
std::ifstream file(filename, std::ios::ate | std::ios::binary);
if (!file.is_open()) {
deerith_graphics_error("failed to open file!");
}
size_t file_size = (size_t)file.tellg();
std::vector<char> buffer(file_size);
file.seekg(0);
file.read(buffer.data(), file_size);
file.close();
return buffer;
}
} // namespace deerith