#include "detail/graphics.h" #include "detail/vertex_layout.h" #include namespace deerith { namespace graphics { std::vector read_file(const std::string& filename); VkShaderModule create_shader_module(const std::vector& 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& code) { VkShaderModuleCreateInfo create_info{}; create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; create_info.codeSize = code.size(); create_info.pCode = reinterpret_cast(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 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 buffer(file_size); file.seekg(0); file.read(buffer.data(), file_size); file.close(); return buffer; } } // namespace deerith