Browse Source

Create VkQueue and VkPipeline

master
Brian Ho 6 years ago
parent
commit
7fe317c4f6
5 changed files with 252 additions and 1 deletions
  1. 2
    0
      .gitignore
  2. 6
    0
      Makefile
  3. 213
    1
      triangle.cc
  4. 10
    0
      triangle.frag
  5. 21
    0
      triangle.vert

+ 2
- 0
.gitignore View File

@@ -1,2 +1,4 @@
triangle
triangle.png
triangle.vert.spv
triangle.frag.spv

+ 6
- 0
Makefile View File

@@ -42,9 +42,15 @@ else
@./$(NAME)
endif

shaders:
@glslc -c ${NAME}.vert
@glslc -c ${NAME}.frag

clean: check
@rm -f ${NAME}
@rm -f ${NAME}.png
@rm -f ${NAME}.vert.spv
@rm -f ${NAME}.frag.spv
ifneq ($(target), local)
@ssh $(SSH_DUT) 'rm -f ~/${NAME} ~/${NAME}.png'
endif

+ 213
- 1
triangle.cc View File

@@ -1,12 +1,17 @@
#include <png.h>
#include <vulkan/vulkan.h>

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

const uint32_t kWidth = 16;
const uint32_t kHeight = 16;
const VkFormat kVulkanFormat = VK_FORMAT_A8B8G8R8_UNORM_PACK32;
const std::string kVertexShaderPath = "triangle.vert.spv";
const std::string kFragmentShaderPath = "triangle.frag.spv";

#define ERROR(message) \
std::cerr << message << std::endl; \
@@ -106,16 +111,223 @@ VkDevice CreateVkDevice(VkPhysicalDevice physical_device, uint32_t device_queue_
VkDevice device;
VkResult result = vkCreateDevice(physical_device, &device_create_info, nullptr, &device);
if (result != VK_SUCCESS) {
ERROR("Unable to create logical device");
ERROR("Unable to create logical device: " << result);
}
return device;
}

VkQueue GetVkQueue(VkDevice device, uint32_t device_queue_family_index) {
VkQueue queue;
vkGetDeviceQueue(device, device_queue_family_index, /*queueIndex*/ 0, &queue);
return queue;
}

VkCommandPool CreateVkCommandPool(VkDevice device, uint32_t device_queue_family_index) {
VkCommandPool command_pool;
VkCommandPoolCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
create_info.flags = 0;
create_info.queueFamilyIndex = device_queue_family_index;
VkResult result = vkCreateCommandPool(device, &create_info, nullptr, &command_pool);
if (result != VK_SUCCESS) {
ERROR("Unable to create command pool: " << result);
}
return command_pool;
}

VkRenderPass CreateVkRenderPass(VkDevice device) {
VkAttachmentDescription attachment_description = {};
attachment_description.format = kVulkanFormat;
attachment_description.samples = VK_SAMPLE_COUNT_1_BIT;
attachment_description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachment_description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment_description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment_description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachment_description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachment_description.finalLayout = VK_IMAGE_LAYOUT_GENERAL;

VkAttachmentReference attachment_reference = {};
attachment_reference.attachment = 0;
attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

VkSubpassDescription subpass_description = {};
subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass_description.colorAttachmentCount = 1;
subpass_description.pColorAttachments = &attachment_reference;

VkSubpassDependency subpass_dependency = {};
subpass_dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
subpass_dependency.dstSubpass = 0;
subpass_dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
subpass_dependency.srcAccessMask = 0;
subpass_dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
subpass_dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

VkRenderPassCreateInfo render_pass_info = {};
render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
render_pass_info.attachmentCount = 1;
render_pass_info.pAttachments = &attachment_description;
render_pass_info.subpassCount = 1;
render_pass_info.pSubpasses = &subpass_description;
render_pass_info.dependencyCount = 1;
render_pass_info.pDependencies = &subpass_dependency;

VkRenderPass render_pass;
VkResult result = vkCreateRenderPass(device, &render_pass_info, nullptr, &render_pass);
if (result != VK_SUCCESS) {
ERROR("Unable to create render pass: " << result);
}
return render_pass;
}

VkShaderModule CreateVkShaderModule(VkDevice device, std::string path) {
std::ifstream fstream(path);
if (!fstream) {
ERROR("Unable to open: " << path);
}
std::stringstream buffer;
buffer << fstream.rdbuf();
std::string spirv_source = buffer.str();

VkShaderModuleCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
create_info.codeSize = spirv_source.length();
create_info.pCode = (const uint32_t*)spirv_source.c_str();

VkShaderModule shader_module;
VkResult result = vkCreateShaderModule(device, &create_info, nullptr, &shader_module);
if (result != VK_SUCCESS) {
ERROR("Unable to create shader module for " << path << ": ");
}
return shader_module;
}

VkPipeline CreateVkPipeline(VkDevice device, VkRenderPass render_pass) {
VkShaderModule vertex_shader_module = CreateVkShaderModule(device, kVertexShaderPath);
VkShaderModule fragment_shader_module = CreateVkShaderModule(device, kFragmentShaderPath);

VkPipelineShaderStageCreateInfo vertex_shader_stage_info = {};
vertex_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertex_shader_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertex_shader_stage_info.module = vertex_shader_module;
vertex_shader_stage_info.pName = "main";

VkPipelineShaderStageCreateInfo fragment_shader_stage_info = {};
fragment_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragment_shader_stage_info.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragment_shader_stage_info.module = fragment_shader_module;
fragment_shader_stage_info.pName = "main";

std::vector<VkPipelineShaderStageCreateInfo> shader_stages =
{vertex_shader_stage_info, fragment_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;
vertex_input_info.vertexAttributeDescriptionCount = 0;
vertex_input_info.pVertexAttributeDescriptions = nullptr;

VkPipelineInputAssemblyStateCreateInfo input_assembly_info = {};
input_assembly_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
input_assembly_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
input_assembly_info.primitiveRestartEnable = VK_FALSE;

VkViewport viewport = {};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = (float)kWidth;
viewport.height = (float)kHeight;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;

VkExtent2D extent = {};
extent.width = kWidth;
extent.height = kHeight;
VkRect2D scissor = {};
scissor.offset = {0, 0};
scissor.extent = extent;

VkPipelineViewportStateCreateInfo viewport_state_info = {};
viewport_state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewport_state_info.viewportCount = 1;
viewport_state_info.pViewports = &viewport;
viewport_state_info.scissorCount = 1;
viewport_state_info.pScissors = &scissor;

VkPipelineRasterizationStateCreateInfo rasterization_state_info = {};
rasterization_state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterization_state_info.depthClampEnable = VK_FALSE;
rasterization_state_info.rasterizerDiscardEnable = VK_FALSE;
rasterization_state_info.polygonMode = VK_POLYGON_MODE_FILL;
rasterization_state_info.lineWidth = 1.0f;
rasterization_state_info.cullMode = VK_CULL_MODE_BACK_BIT;
rasterization_state_info.frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterization_state_info.depthBiasEnable = VK_FALSE;

VkPipelineMultisampleStateCreateInfo multisampling_state_info = {};
multisampling_state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling_state_info.sampleShadingEnable = VK_FALSE;
multisampling_state_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;

VkPipelineColorBlendAttachmentState color_blend_attachment_state = {};
color_blend_attachment_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
color_blend_attachment_state.blendEnable = VK_FALSE;

VkPipelineColorBlendStateCreateInfo color_blend_state = {};
color_blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
color_blend_state.logicOpEnable = VK_FALSE;
color_blend_state.attachmentCount = 1;
color_blend_state.pAttachments = &color_blend_attachment_state;

VkPipelineLayoutCreateInfo pipeline_layout_create_info = {};
pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;

VkPipelineLayout pipeline_layout;
VkResult result = vkCreatePipelineLayout(device, &pipeline_layout_create_info, nullptr,
&pipeline_layout);
if (result != VK_SUCCESS) {
ERROR("Unable to create VkPipelineLayout: " << result);
}

VkGraphicsPipelineCreateInfo pipeline_create_info = {};
pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipeline_create_info.stageCount = 2;
pipeline_create_info.pStages = shader_stages.data();
pipeline_create_info.pVertexInputState = &vertex_input_info;
pipeline_create_info.pInputAssemblyState = &input_assembly_info;
pipeline_create_info.pViewportState = &viewport_state_info;
pipeline_create_info.pRasterizationState = &rasterization_state_info;
pipeline_create_info.pMultisampleState = &multisampling_state_info;
pipeline_create_info.pDepthStencilState = nullptr;
pipeline_create_info.pColorBlendState = &color_blend_state;
pipeline_create_info.pDynamicState = nullptr;
pipeline_create_info.layout = pipeline_layout;
pipeline_create_info.renderPass = render_pass;
pipeline_create_info.subpass = 0;
pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE;
pipeline_create_info.basePipelineIndex = -1;

VkPipeline pipeline;
result = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr,
&pipeline);
if (result != VK_SUCCESS) {
ERROR("Unable to create VkPipeline: " << result);
}
return pipeline;
}

int main() {
VkInstance instance = CreateVkInstance();
VkPhysicalDevice physical_device = ChooseVkPhysicalDevice(instance);
uint32_t device_queue_family_index = ChooseDeviceQueueFamilyIndex(physical_device);
VkDevice device = CreateVkDevice(physical_device, device_queue_family_index);
VkQueue queue = GetVkQueue(device, device_queue_family_index);
VkCommandPool command_pool = CreateVkCommandPool(device, device_queue_family_index);
VkRenderPass render_pass = CreateVkRenderPass(device);
VkPipeline pipeline = CreateVkPipeline(device, render_pass);

// Example code for exporting a PNG.
FILE *f = fopen("triangle.png", "wb");

+ 10
- 0
triangle.frag View File

@@ -0,0 +1,10 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(location = 0) in vec3 fragColor;

layout(location = 0) out vec4 outColor;

void main() {
outColor = vec4(fragColor, 1.0);
}

+ 21
- 0
triangle.vert View File

@@ -0,0 +1,21 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(location = 0) out vec3 fragColor;

vec2 positions[3] = vec2[](
vec2(0.0, -0.5),
vec2(0.5, 0.5),
vec2(-0.5, 0.5)
);

vec3 colors[3] = vec3[](
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 0.0, 1.0)
);

void main() {
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
fragColor = colors[gl_VertexIndex];
}

Loading…
Cancel
Save