blob: 8e2ffaf2452be6a52cd3094b3a276ff412469af3 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "vulkan_graphics_pipeline.h"
#include <unistd.h>
#include <vector>
#include "utils.h"
#include "vulkan_fixed_functions.h"
#include "vulkan_shader.h"
VulkanGraphicsPipeline::VulkanGraphicsPipeline(std::shared_ptr<VulkanLogicalDevice> device,
const vk::Extent2D &extent,
std::shared_ptr<VulkanRenderPass> render_pass)
: initialized_(false), device_(device), extent_(extent), render_pass_(render_pass) {}
bool VulkanGraphicsPipeline::Init() {
if (initialized_) {
RTN_MSG(false, "VulkanGraphicsPipeline is already initialized.\n");
}
std::vector<char> vert_shader_buffer;
std::vector<char> frag_shader_buffer;
#ifdef __Fuchsia__
const char *vert_shader = "/pkg/data/shaders/vert.spv";
const char *frag_shader = "/pkg/data/shaders/frag.spv";
#else
char cwd[PATH_MAX];
if (getcwd(cwd, sizeof(cwd)) == NULL) {
RTN_MSG(false, "Can't get current working directory.\n");
}
char vert_shader[PATH_MAX];
snprintf(vert_shader, PATH_MAX, "%s/host_x64/obj/src/graphics/examples/vkprimer/vert.spv", cwd);
char frag_shader[PATH_MAX];
snprintf(frag_shader, PATH_MAX, "%s/host_x64/obj/src/graphics/examples/vkprimer/frag.spv", cwd);
#endif
if (!VulkanShader::ReadFile(vert_shader, &vert_shader_buffer)) {
RTN_MSG(false, "Can't read vertex spv file.\n");
}
if (!VulkanShader::ReadFile(frag_shader, &frag_shader_buffer)) {
RTN_MSG(false, "Can't read fragment spv file.\n");
}
const vk::Device &device = *device_->device();
auto rv = VulkanShader::CreateShaderModule(device, vert_shader_buffer);
if (vk::Result::eSuccess != rv.result) {
RTN_MSG(false, "VK Error: 0x%x - Failed to create vtx shader module.\n", rv.result);
}
vk::UniqueShaderModule vert_shader_module = std::move(rv.value);
rv = VulkanShader::CreateShaderModule(device, frag_shader_buffer);
if (vk::Result::eSuccess != rv.result) {
RTN_MSG(false, "VK Error: 0x%x - Failed to create frag shader module.\n", rv.result);
}
vk::UniqueShaderModule frag_shader_module = std::move(rv.value);
vk::PipelineShaderStageCreateInfo shader_stages[2];
shader_stages[0].module = *vert_shader_module;
shader_stages[0].pName = "main";
shader_stages[1].module = *frag_shader_module;
shader_stages[1].stage = vk::ShaderStageFlagBits::eFragment;
shader_stages[1].pName = "main";
VulkanFixedFunctions fixed_functions(extent_);
vk::PipelineLayoutCreateInfo pipeline_layout_info;
auto rv_layout = device.createPipelineLayoutUnique(pipeline_layout_info);
if (vk::Result::eSuccess != rv_layout.result) {
RTN_MSG(false, "VK Error: 0x%x - Failed to create pipeline layout.\n", rv_layout.result);
}
pipeline_layout_ = std::move(rv_layout.value);
VulkanFixedFunctions &ff = fixed_functions;
vk::GraphicsPipelineCreateInfo pipeline_info;
pipeline_info.stageCount = 2;
pipeline_info.pStages = shader_stages;
pipeline_info.setPVertexInputState(&ff.vertex_input_info());
pipeline_info.setPInputAssemblyState(&ff.input_assembly_info());
pipeline_info.setPViewportState(&ff.viewport_info());
pipeline_info.setPRasterizationState(&ff.rasterizer_info());
pipeline_info.setPMultisampleState(&ff.multisample_info());
pipeline_info.setPColorBlendState(&ff.color_blending_info());
pipeline_info.layout = *pipeline_layout_;
pipeline_info.renderPass = *render_pass_->render_pass();
pipeline_info.basePipelineIndex = -1;
auto rv_pipelines = device.createGraphicsPipelinesUnique(vk::PipelineCache(), {pipeline_info});
if (vk::Result::eSuccess != rv_pipelines.result) {
RTN_MSG(false, "VK Error: 0x%x - Failed to create pipelines.\n", rv_pipelines.result);
}
graphics_pipeline_ = std::move(rv_pipelines.value[0]);
initialized_ = true;
return true;
}
const vk::UniquePipeline &VulkanGraphicsPipeline::graphics_pipeline() const {
return graphics_pipeline_;
}