diff options
Diffstat (limited to 'src/renderer.c')
| -rw-r--r-- | src/renderer.c | 214 | 
1 files changed, 214 insertions, 0 deletions
diff --git a/src/renderer.c b/src/renderer.c index cacd3bd..f04fea9 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -862,6 +862,197 @@ err:    return false;  } +static bool create_shader_module(VkDevice device, const unsigned char *code, +                                 int size, VkShaderModule *out) { +  VkShaderModuleCreateInfo create_info = { +      .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, +      .codeSize = size, +      .pCode = (const uint32_t *)code, +  }; +  if (vkCreateShaderModule(device, &create_info, nullptr, out) != VK_SUCCESS) { +    VGLTF_LOG_ERR("Couldn't create shader module"); +    goto err; +  } +  return true; +err: +  return false; +} + +static bool vgltf_renderer_create_render_pass(struct vgltf_renderer *renderer) { +  VkAttachmentDescription color_attachment = { +      .format = renderer->swapchain_image_format, +      .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 color_attachment_ref = { +      .attachment = 0, +      .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, +  }; +  VkSubpassDescription subpass = {.pipelineBindPoint = +                                      VK_PIPELINE_BIND_POINT_GRAPHICS, +                                  .pColorAttachments = &color_attachment_ref}; +  VkRenderPassCreateInfo render_pass_info = { +      .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, +      .attachmentCount = 1, +      .pAttachments = &color_attachment, +      .subpassCount = 1, +      .pSubpasses = &subpass}; + +  if (vkCreateRenderPass(renderer->device, &render_pass_info, nullptr, +                         &renderer->render_pass) != VK_SUCCESS) { +    VGLTF_LOG_ERR("Failed to create render pass"); +    goto err; +  } + +  return true; +err: +  return false; +} + +static bool +vgltf_renderer_create_graphics_pipeline(struct vgltf_renderer *renderer) { +  static constexpr unsigned char triangle_shader_vert_code[] = { +#embed "../compiled_shaders/triangle.vert.spv" +  }; +  static constexpr unsigned char triangle_shader_frag_code[] = { +#embed "../compiled_shaders/triangle.frag.spv" +  }; + +  VkShaderModule triangle_shader_vert_module; +  if (!create_shader_module(renderer->device, triangle_shader_vert_code, +                            sizeof(triangle_shader_vert_code), +                            &triangle_shader_vert_module)) { +    VGLTF_LOG_ERR("Couldn't create triangle vert shader module"); +    goto err; +  } + +  VkShaderModule triangle_shader_frag_module; +  if (!create_shader_module(renderer->device, triangle_shader_frag_code, +                            sizeof(triangle_shader_frag_code), +                            &triangle_shader_frag_module)) { +    VGLTF_LOG_ERR("Couldn't create triangle frag shader module"); +    goto destroy_vert_shader_module; +  } + +  VkPipelineShaderStageCreateInfo triangle_shader_vert_stage_create_info = { +      .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, +      .stage = VK_SHADER_STAGE_VERTEX_BIT, +      .module = triangle_shader_vert_module, +      .pName = "main"}; +  VkPipelineShaderStageCreateInfo triangle_shader_frag_stage_create_info = { +      .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, +      .stage = VK_SHADER_STAGE_FRAGMENT_BIT, +      .module = triangle_shader_frag_module, +      .pName = "main"}; +  VkPipelineShaderStageCreateInfo shader_stages[] = { +      triangle_shader_vert_stage_create_info, +      triangle_shader_frag_stage_create_info}; + +  VkDynamicState dynamic_states[] = { +      VK_DYNAMIC_STATE_VIEWPORT, +      VK_DYNAMIC_STATE_SCISSOR, +  }; + +  VkPipelineDynamicStateCreateInfo dynamic_state = { +      .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, +      .dynamicStateCount = sizeof(dynamic_states) / sizeof(dynamic_states[0]), +      .pDynamicStates = dynamic_states}; + +  VkPipelineVertexInputStateCreateInfo vertex_input_info = { +      .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, +      .vertexBindingDescriptionCount = 0, +      .vertexAttributeDescriptionCount = 0, +  }; + +  VkPipelineInputAssemblyStateCreateInfo input_assembly = { +      .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, +      .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, +      .primitiveRestartEnable = VK_FALSE, +  }; + +  VkPipelineViewportStateCreateInfo viewport_state = { +      .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, +      .viewportCount = 1, +      .scissorCount = 1}; + +  VkPipelineRasterizationStateCreateInfo rasterizer = { +      .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, +      .depthClampEnable = VK_FALSE, +      .rasterizerDiscardEnable = VK_FALSE, +      .polygonMode = VK_POLYGON_MODE_FILL, +      .lineWidth = 1.f, +      .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 color_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_blending = { +      .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, +      .logicOpEnable = VK_FALSE, +      .attachmentCount = 1, +      .pAttachments = &color_blend_attachment}; + +  VkPipelineLayoutCreateInfo pipeline_layout_info = { +      .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, +  }; + +  if (vkCreatePipelineLayout(renderer->device, &pipeline_layout_info, nullptr, +                             &renderer->pipeline_layout) != VK_SUCCESS) { +    VGLTF_LOG_ERR("Couldn't create pipeline layout"); +    goto destroy_frag_shader_module; +  } + +  VkGraphicsPipelineCreateInfo pipeline_info = { +      .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, +      .stageCount = 2, +      .pStages = shader_stages, +      .pVertexInputState = &vertex_input_info, +      .pInputAssemblyState = &input_assembly, +      .pViewportState = &viewport_state, +      .pRasterizationState = &rasterizer, +      .pMultisampleState = &multisampling, +      .pColorBlendState = &color_blending, +      .pDynamicState = &dynamic_state, +      .layout = renderer->pipeline_layout, +      .renderPass = renderer->render_pass, +      .subpass = 0, +  }; + +  if (vkCreateGraphicsPipelines(renderer->device, VK_NULL_HANDLE, 1, +                                &pipeline_info, nullptr, +                                &renderer->graphics_pipeline) != VK_SUCCESS) { +    VGLTF_LOG_ERR("Couldn't create pipeline"); +    goto destroy_pipeline_layout; +  } + +  vkDestroyShaderModule(renderer->device, triangle_shader_frag_module, nullptr); +  vkDestroyShaderModule(renderer->device, triangle_shader_vert_module, nullptr); +  return true; +destroy_pipeline_layout: +  vkDestroyPipelineLayout(renderer->device, renderer->pipeline_layout, nullptr); +destroy_frag_shader_module: +  vkDestroyShaderModule(renderer->device, triangle_shader_frag_module, nullptr); +destroy_vert_shader_module: +  vkDestroyShaderModule(renderer->device, triangle_shader_vert_module, nullptr); +err: +  return false; +} +  bool vgltf_renderer_init(struct vgltf_renderer *renderer,                           struct vgltf_platform *platform) {    if (!vgltf_renderer_create_instance(renderer, platform)) { @@ -899,7 +1090,27 @@ bool vgltf_renderer_init(struct vgltf_renderer *renderer,      goto destroy_swapchain;    } +  if (!vgltf_renderer_create_render_pass(renderer)) { +    VGLTF_LOG_ERR("Couldn't create render pass"); +    goto destroy_image_views; +  } + +  if (!vgltf_renderer_create_graphics_pipeline(renderer)) { +    VGLTF_LOG_ERR("Couldn't create graphics pipeline"); +    goto destroy_render_pass; +  } +    return true; +destroy_render_pass: +  vkDestroyRenderPass(renderer->device, renderer->render_pass, nullptr); +destroy_image_views: +  for (uint32_t swapchain_image_view_index = 0; +       swapchain_image_view_index < renderer->swapchain_image_count; +       swapchain_image_view_index++) { +    vkDestroyImageView( +        renderer->device, +        renderer->swapchain_image_views[swapchain_image_view_index], nullptr); +  }  destroy_swapchain:    vkDestroySwapchainKHR(renderer->device, renderer->swapchain, nullptr);  destroy_device: @@ -916,6 +1127,9 @@ err:    return false;  }  void vgltf_renderer_deinit(struct vgltf_renderer *renderer) { +  vkDestroyPipeline(renderer->device, renderer->graphics_pipeline, nullptr); +  vkDestroyPipelineLayout(renderer->device, renderer->pipeline_layout, nullptr); +  vkDestroyRenderPass(renderer->device, renderer->render_pass, nullptr);    for (uint32_t swapchain_image_view_index = 0;         swapchain_image_view_index < renderer->swapchain_image_count;         swapchain_image_view_index++) {  | 
