198 lines
5.4 KiB
C
198 lines
5.4 KiB
C
/* SPDX-License-Identifier:BSD-3-Clause */
|
|
#include "pipeline.h"
|
|
#include "../../core/log.h"
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
static u8 *read_file(const char *path, usize *size)
|
|
{
|
|
FILE *file = fopen(path, "rb");
|
|
if (!file) {
|
|
return NULL;
|
|
}
|
|
|
|
fseek(file, 0, SEEK_END);
|
|
*size = ftell(file);
|
|
fseek(file, 0, SEEK_SET);
|
|
|
|
u8 *data = malloc(*size);
|
|
fread(data, 1, *size, file);
|
|
fclose(file);
|
|
|
|
return data;
|
|
}
|
|
|
|
static VkShaderModule create_shader_module(VkDevice device, u8 *code, usize size)
|
|
{
|
|
VkShaderModuleCreateInfo create_info = {
|
|
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
|
.codeSize = size,
|
|
.pCode = (u32 *)code
|
|
};
|
|
|
|
VkShaderModule module;
|
|
if (vkCreateShaderModule(device, &create_info, NULL, &module) != VK_SUCCESS) {
|
|
fatal("Can't create shader module.\n");
|
|
}
|
|
|
|
return module;
|
|
}
|
|
|
|
void vk_pipeline_init(struct renderer_context *context)
|
|
{
|
|
usize vert_size, frag_size;
|
|
u8 *vert_code = read_file("assets/shaders/quad.vert.spv", &vert_size);
|
|
u8 *frag_code = read_file("assets/shaders/quad.frag.spv", &frag_size);
|
|
|
|
if (!vert_code || !frag_code) {
|
|
fatal("Can't read shader files.\n");
|
|
}
|
|
|
|
VkShaderModule vert_module = create_shader_module(context->device, vert_code, vert_size);
|
|
VkShaderModule frag_module = create_shader_module(context->device, frag_code, frag_size);
|
|
|
|
free(vert_code);
|
|
free(frag_code);
|
|
|
|
VkPipelineShaderStageCreateInfo shader_stages[] = {
|
|
{
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
|
.stage = VK_SHADER_STAGE_VERTEX_BIT,
|
|
.module = vert_module,
|
|
.pName = "main"
|
|
},
|
|
{
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
|
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
.module = frag_module,
|
|
.pName = "main"
|
|
}
|
|
};
|
|
|
|
VkVertexInputBindingDescription binding = {
|
|
.binding = 0,
|
|
.stride = sizeof(f32) * 5,
|
|
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
|
|
};
|
|
|
|
VkVertexInputAttributeDescription attributes[] = {
|
|
{
|
|
.binding = 0,
|
|
.location = 0,
|
|
.format = VK_FORMAT_R32G32_SFLOAT,
|
|
.offset = 0
|
|
},
|
|
{
|
|
.binding = 0,
|
|
.location = 1,
|
|
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
|
.offset = sizeof(f32) * 2
|
|
}
|
|
};
|
|
|
|
VkPipelineVertexInputStateCreateInfo vertex_input = {
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
|
.vertexBindingDescriptionCount = 1,
|
|
.pVertexBindingDescriptions = &binding,
|
|
.vertexAttributeDescriptionCount = 2,
|
|
.pVertexAttributeDescriptions = attributes
|
|
};
|
|
|
|
VkPipelineInputAssemblyStateCreateInfo input_assembly = {
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
|
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
|
.primitiveRestartEnable = VK_FALSE
|
|
};
|
|
|
|
VkViewport viewport = {
|
|
.x = 0.0f,
|
|
.y = 0.0f,
|
|
.width = (f32)context->swapchain.extent.width,
|
|
.height = (f32)context->swapchain.extent.height,
|
|
.minDepth = 0.0f,
|
|
.maxDepth = 1.0f
|
|
};
|
|
|
|
VkRect2D scissor = {
|
|
.offset = { 0, 0 },
|
|
.extent = context->swapchain.extent
|
|
};
|
|
|
|
VkPipelineViewportStateCreateInfo viewport_state = {
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
|
.viewportCount = 1,
|
|
.pViewports = &viewport,
|
|
.scissorCount = 1,
|
|
.pScissors = &scissor
|
|
};
|
|
|
|
VkPipelineRasterizationStateCreateInfo rasterizer = {
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
|
.depthClampEnable = VK_FALSE,
|
|
.rasterizerDiscardEnable = VK_FALSE,
|
|
.polygonMode = VK_POLYGON_MODE_FILL,
|
|
.lineWidth = 1.0f,
|
|
.cullMode = VK_CULL_MODE_BACK_BIT,
|
|
.frontFace = VK_FRONT_FACE_CLOCKWISE,
|
|
.depthBiasEnable = VK_FALSE
|
|
};
|
|
|
|
VkPipelineMultisampleStateCreateInfo multisampling = {
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
|
.sampleShadingEnable = VK_FALSE,
|
|
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT
|
|
};
|
|
|
|
VkPipelineColorBlendAttachmentState blend_attachment = {
|
|
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
|
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
|
|
.blendEnable = VK_FALSE
|
|
};
|
|
|
|
VkPipelineColorBlendStateCreateInfo color_blend = {
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
|
.logicOpEnable = VK_FALSE,
|
|
.attachmentCount = 1,
|
|
.pAttachments = &blend_attachment
|
|
};
|
|
|
|
VkPipelineLayoutCreateInfo layout_info = {
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
|
.setLayoutCount = 0,
|
|
.pushConstantRangeCount = 0
|
|
};
|
|
|
|
if (vkCreatePipelineLayout(context->device, &layout_info, NULL, &context->pipeline_layout) != VK_SUCCESS) {
|
|
fatal("Can't create pipeline layout.\n");
|
|
}
|
|
|
|
VkGraphicsPipelineCreateInfo pipeline_info = {
|
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
|
.stageCount = 2,
|
|
.pStages = shader_stages,
|
|
.pVertexInputState = &vertex_input,
|
|
.pInputAssemblyState = &input_assembly,
|
|
.pViewportState = &viewport_state,
|
|
.pRasterizationState = &rasterizer,
|
|
.pMultisampleState = &multisampling,
|
|
.pColorBlendState = &color_blend,
|
|
.layout = context->pipeline_layout,
|
|
.renderPass = context->render_pass,
|
|
.subpass = 0
|
|
};
|
|
|
|
if (vkCreateGraphicsPipelines(context->device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &context->pipeline) != VK_SUCCESS) {
|
|
fatal("Can't create graphics pipeline.\n");
|
|
}
|
|
|
|
vkDestroyShaderModule(context->device, vert_module, NULL);
|
|
vkDestroyShaderModule(context->device, frag_module, NULL);
|
|
|
|
log_info("Graphics pipeline created.\n");
|
|
}
|
|
|
|
void vk_pipeline_deinit(struct renderer_context *context)
|
|
{
|
|
vkDestroyPipeline(context->device, context->pipeline, NULL);
|
|
vkDestroyPipelineLayout(context->device, context->pipeline_layout, NULL);
|
|
}
|