kiba-engine
pipeline.c
1 #include <kiba/renderer/vulkan/pipeline.h>
2 
3 #include <kiba/renderer/vulkan/shader.h>
4 #include <kiba/renderer/vulkan/vertex_buffer.h>
5 
6 b8 vulkan_pipeline_create(vulkan_context *context) {
7  if ((context->pipeline.shaders = array_create(VkPipelineShaderStageCreateInfo, 2, &context->alloc.kiba_alloc))
8  == KB_NULL) {
9  KB_ERROR("could not create array to hold shader info");
10  return false;
11  }
12  if (!vulkan_shader_create(context, "assets/shaders/builtin.test-shader.vert.spv", SHADER_TYPE_VERTEX)) {
13  KB_ERROR("could not load vertex shader code");
14  return false;
15  }
16  if (!vulkan_shader_create(context, "assets/shaders/builtin.test-shader.frag.spv", SHADER_TYPE_FRAGMENT)) {
17  KB_ERROR("could not load fragment shader code");
18  return false;
19  }
20 
21  VkDynamicState dynamic_states[] = {
22  VK_DYNAMIC_STATE_VIEWPORT,
23  VK_DYNAMIC_STATE_SCISSOR,
24  };
25 
26  // state that can be changed after pipeline creation
27  VkPipelineDynamicStateCreateInfo dynamic_state_info = {
28  .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
29  .dynamicStateCount = 2,
30  .pDynamicStates = dynamic_states,
31  };
32 
33  // format of vertex data
34  VkVertexInputBindingDescription input_binding_description = {
35  .binding = 0,
36  .inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
37  .stride = sizeof(vulkan_vertex),
38  };
39  VkVertexInputAttributeDescription attribute_descriptions[3] = {
40  {
41  .binding = 0,
42  .location = 0,
43  .format = VK_FORMAT_R32G32B32_SFLOAT,
44  .offset = 0,
45  },
46  {
47  .binding = 0,
48  .location = 1,
49  .format = VK_FORMAT_R32G32B32_SFLOAT,
50  .offset = sizeof(float) * 3,
51  },
52  {
53  .binding = 0,
54  .location = 2,
55  .format = VK_FORMAT_R32G32_SFLOAT,
56  .offset = sizeof(float) * 6,
57  },
58  };
59  VkPipelineVertexInputStateCreateInfo vertex_input_info = {
60  .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
61  .vertexBindingDescriptionCount = 1,
62  .pVertexBindingDescriptions = &input_binding_description,
63  .vertexAttributeDescriptionCount = sizeof(attribute_descriptions) / sizeof(attribute_descriptions[0]),
64  .pVertexAttributeDescriptions = attribute_descriptions,
65  };
66 
67  // kind of geometry
68  VkPipelineInputAssemblyStateCreateInfo input_assembly_info = {
69  .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
70  .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
71  .primitiveRestartEnable = VK_FALSE,
72  };
73 
74  // viewports and scissors, if dynamic must be added before drawing instead of here
75  /*VkViewport viewport = {
76  .x = 0.0f,
77  .y = 0.0f,
78  .width = (float) context->swap_chain.extent.width,
79  .height = (float) context->swap_chain.extent.height,
80  .minDepth = 0.0f,
81  .maxDepth = 1.0f,
82  };
83  VkRect2D scissors = {
84  .offset = {0, 0},
85  .extent = context->swap_chain.extent,
86  };*/
87  VkPipelineViewportStateCreateInfo viewport_state_info = {
88  .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
89  .viewportCount = 1,
90  .scissorCount = 1,
91  };
92 
93  // rasterization
94  VkPipelineRasterizationStateCreateInfo rasterizer_info = {
95  .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
96  .depthClampEnable = VK_FALSE,
97  .rasterizerDiscardEnable = VK_FALSE,
98  .polygonMode = VK_POLYGON_MODE_FILL,
99  .lineWidth = 1.0f,
100  .cullMode = VK_CULL_MODE_BACK_BIT,
101  .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
102  .depthBiasEnable = VK_FALSE,
103  .depthBiasConstantFactor = 0.0f,
104  .depthBiasClamp = 0.0f,
105  .depthBiasSlopeFactor = 0.0f,
106  };
107 
108  // multisampling
109  VkPipelineMultisampleStateCreateInfo multisampling_info = {
110  .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
111  .sampleShadingEnable = VK_FALSE,
112  .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
113  .minSampleShading = 1.0f,
114  .pSampleMask = NULL,
115  .alphaToCoverageEnable = VK_FALSE,
116  .alphaToOneEnable = VK_FALSE,
117  };
118 
119  // color blending
120  VkPipelineColorBlendAttachmentState color_blend_attachment = {
121  .colorWriteMask =
122  VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
123  .blendEnable = VK_FALSE,
124  .srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
125  .dstColorBlendFactor = VK_BLEND_FACTOR_ZERO,
126  .colorBlendOp = VK_BLEND_OP_ADD,
127  .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
128  .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
129  .alphaBlendOp = VK_BLEND_OP_ADD,
130  };
131  VkPipelineColorBlendStateCreateInfo color_blend_info = {
132  .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
133  .logicOpEnable = VK_FALSE,
134  .logicOp = VK_LOGIC_OP_COPY,
135  .attachmentCount = 1,
136  .pAttachments = &color_blend_attachment,
137  .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
138  };
139 
140  // pipeline layout (uniforms etc)
141  VkPipelineLayoutCreateInfo pipeline_layout_info = {
142  .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
143  .setLayoutCount = 1,
144  .pSetLayouts = &context->pipeline.descriptor_set_layout,
145  .pushConstantRangeCount = 0,
146  .pPushConstantRanges = NULL,
147  };
148  VK_CALL_B8(vkCreatePipelineLayout(context->device.logical,
149  &pipeline_layout_info,
150  &context->alloc.vulkan_callbacks,
151  &context->pipeline.layout));
152 
153  VkPipelineDepthStencilStateCreateInfo depth_info = {
154  .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
155  .depthTestEnable = VK_TRUE,
156  .depthWriteEnable = VK_TRUE,
157  .depthCompareOp = VK_COMPARE_OP_LESS,
158  .depthBoundsTestEnable = VK_FALSE, // could be used to discard fragments outside of bounds
159  .minDepthBounds = 0.f,
160  .maxDepthBounds = 1.f,
161  .stencilTestEnable = VK_FALSE, // could be used to perform stencil tests, uses `front` and `back` fields
162  };
163 
164  VkGraphicsPipelineCreateInfo pipeline_info = {
165  .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
166  .stageCount = 2,
167  .pStages = context->pipeline.shaders,
168  .pVertexInputState = &vertex_input_info,
169  .pInputAssemblyState = &input_assembly_info,
170  .pViewportState = &viewport_state_info,
171  .pRasterizationState = &rasterizer_info,
172  .pMultisampleState = &multisampling_info,
173  .pDepthStencilState = &depth_info,
174  .pColorBlendState = &color_blend_info,
175  .pDynamicState = &dynamic_state_info,
176  .layout = context->pipeline.layout,
177  .renderPass = context->pipeline.renderpass,
178  .subpass = 0,
179  .basePipelineHandle = VK_NULL_HANDLE,
180  .basePipelineIndex = -1,
181  };
182  VK_CALL_B8(vkCreateGraphicsPipelines(context->device.logical,
183  VK_NULL_HANDLE,
184  1,
185  &pipeline_info,
186  &context->alloc.vulkan_callbacks,
187  &context->pipeline.graphics_pipeline));
188 
189  return true;
190 }
191 
192 void vulkan_pipeline_destroy(vulkan_context *context) {
193  vkDestroyPipeline(context->device.logical, context->pipeline.graphics_pipeline, &context->alloc.vulkan_callbacks);
194  vkDestroyPipelineLayout(context->device.logical, context->pipeline.layout, &context->alloc.vulkan_callbacks);
195  array_for_each(VkPipelineShaderStageCreateInfo, shader_create_info, context->pipeline.shaders) {
196  vkDestroyShaderModule(context->device.logical, shader_create_info->module, &context->alloc.vulkan_callbacks);
197  }
198  array_destroy(&context->pipeline.shaders);
199 }
#define KB_NULL
Value of an invalid ptr (nullptr).
Definition: defines.h:18
#define KB_ERROR(...)
Log entry with error log level.
Definition: log.h:142