Skip to content

Commit c75bec1

Browse files
committed
Pipeline and colored triangle
1 parent c90f3e1 commit c75bec1

8 files changed

Lines changed: 136 additions & 3 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ set(CMAKE_CXX_STANDARD 11)
77

88
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/bin")
99

10-
set(SOURCE_FILES src/main.cpp src/simple_logger.cpp src/vulkan_base/vulkan_device.cpp src/vulkan_base/vulkan_swapchain.cpp src/vulkan_base/vulkan_renderpass.cpp)
10+
set(SOURCE_FILES src/main.cpp src/simple_logger.cpp src/vulkan_base/vulkan_device.cpp src/vulkan_base/vulkan_swapchain.cpp src/vulkan_base/vulkan_renderpass.cpp src/vulkan_base/vulkan_pipeline.cpp)
1111

1212
# Find SDL2
1313
add_subdirectory(libs/SDL)

shaders/triangle_frag.glsl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#version 450 core
22

3+
layout(location = 0) in vec3 vertex_color;
4+
35
layout(location = 0) out vec4 color_out;
46

57
void main() {
6-
color_out = vec4(1.0, 1.0, 0.0, 1.0);
8+
color_out = vec4(vertex_color, 1.0);
79
}

shaders/triangle_frag.spv

152 Bytes
Binary file not shown.

shaders/triangle_vert.glsl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ vec2 positions[3] = vec2[](
66
vec2(-0.5, 0.5)
77
);
88

9+
vec3 colors[3] = vec3[](
10+
vec3(1.0, 0.0, 0.0),
11+
vec3(0.0, 1.0, 0.0),
12+
vec3(0.0, 0.0, 1.0)
13+
);
14+
15+
layout(location = 0) out vec3 vertex_color;
16+
917
void main() {
1018
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
19+
vertex_color = colors[gl_VertexIndex];
1120
}

shaders/triangle_vert.spv

344 Bytes
Binary file not shown.

src/main.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ VkSurfaceKHR surface;
1010
VulkanSwapchain swapchain;
1111
VkRenderPass renderPass;
1212
std::vector<VkFramebuffer> framebuffers;
13+
VulkanPipeline pipeline;
1314
VkCommandPool commandPool;
1415
VkCommandBuffer commandBuffer;
1516
VkFence fence;
@@ -50,6 +51,8 @@ void initApplication(SDL_Window* window) {
5051
VKA(vkCreateFramebuffer(context->device, &createInfo, 0, &framebuffers[i]));
5152
}
5253

54+
pipeline = createPipeline(context, "../shaders/triangle_vert.spv", "../shaders/triangle_frag.spv", renderPass, swapchain.width, swapchain.height);
55+
5356
{
5457
VkFenceCreateInfo createInfo = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO };
5558
VKA(vkCreateFence(context->device, &createInfo, 0, &fence));
@@ -92,6 +95,9 @@ void renderApplication() {
9295
beginInfo.pClearValues = &clearValue;
9396
vkCmdBeginRenderPass(commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
9497

98+
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline);
99+
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
100+
95101
vkCmdEndRenderPass(commandBuffer);
96102
}
97103
VKA(vkEndCommandBuffer(commandBuffer));
@@ -119,6 +125,8 @@ void shutdownApplication() {
119125
VK(vkDestroyFence(context->device, fence, 0));
120126
VK(vkDestroyCommandPool(context->device, commandPool, 0));
121127

128+
destroyPipeline(context, &pipeline);
129+
122130
for (uint32_t i = 0; i < framebuffers.size(); ++i) {
123131
VK(vkDestroyFramebuffer(context->device, framebuffers[i], 0));
124132
}

src/vulkan_base/vulkan_base.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ struct VulkanSwapchain {
2828
std::vector<VkImageView> imageViews;
2929
};
3030

31+
struct VulkanPipeline {
32+
VkPipeline pipeline;
33+
VkPipelineLayout pipelineLayout;
34+
};
35+
3136
struct VulkanContext {
3237
VkInstance instance;
3338
VkPhysicalDevice physicalDevice;
@@ -43,4 +48,7 @@ VulkanSwapchain createSwapchain(VulkanContext* context, VkSurfaceKHR surface, Vk
4348
void destroySwapchain(VulkanContext* context, VulkanSwapchain* swapchain);
4449

4550
VkRenderPass createRenderPass(VulkanContext* context, VkFormat format);
46-
void destroyRenderpass(VulkanContext* context, VkRenderPass renderPass);
51+
void destroyRenderpass(VulkanContext* context, VkRenderPass renderPass);
52+
53+
VulkanPipeline createPipeline(VulkanContext* context, const char* vertexShaderFilename, const char* fragmentShaderFilename, VkRenderPass renderPass, uint32_t width, uint32_t height);
54+
void destroyPipeline(VulkanContext* context, VulkanPipeline* pipeline);
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#include "vulkan_base.h"
2+
3+
VkShaderModule createShaderModule(VulkanContext* context, const char* shaderFilename) {
4+
VkShaderModule result = {};
5+
6+
// Read shader file
7+
FILE* file = fopen(shaderFilename, "rb");
8+
if (!file) {
9+
LOG_ERROR("Shader not found: ", shaderFilename);
10+
return result;
11+
}
12+
fseek(file, 0, SEEK_END);
13+
long fileSize = ftell(file);
14+
fseek(file, 0, SEEK_SET);
15+
assert((fileSize & 0x03) == 0);
16+
uint8_t* buffer = new uint8_t[fileSize];
17+
fread(buffer, 1, fileSize, file);
18+
19+
VkShaderModuleCreateInfo createInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
20+
createInfo.codeSize = fileSize;
21+
createInfo.pCode = (uint32_t*)buffer;
22+
VKA(vkCreateShaderModule(context->device, &createInfo, 0, &result));
23+
24+
delete[] buffer;
25+
fclose(file);
26+
27+
return result;
28+
}
29+
30+
VulkanPipeline createPipeline(VulkanContext* context, const char* vertexShaderFilename, const char* fragmentShaderFilename, VkRenderPass renderPass, uint32_t width, uint32_t height) {
31+
VkShaderModule vertexShaderModule = createShaderModule(context, vertexShaderFilename);
32+
VkShaderModule fragmentShaderModule = createShaderModule(context, fragmentShaderFilename);
33+
34+
VkPipelineShaderStageCreateInfo shaderStages[2];
35+
shaderStages[0] = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO };
36+
shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
37+
shaderStages[0].module = vertexShaderModule;
38+
shaderStages[0].pName = "main";
39+
shaderStages[1] = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO };
40+
shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
41+
shaderStages[1].module = fragmentShaderModule;
42+
shaderStages[1].pName = "main";
43+
44+
VkPipelineVertexInputStateCreateInfo vertexInputState = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
45+
46+
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
47+
inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
48+
49+
VkPipelineViewportStateCreateInfo viewportState = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
50+
viewportState.viewportCount = 1;
51+
VkViewport viewport = { 0.0f, 0.0f, (float)width, (float)height };
52+
viewportState.pViewports = &viewport;
53+
viewportState.scissorCount = 1;
54+
VkRect2D scissor = { {0, 0}, {width, height} };
55+
viewportState.pScissors = &scissor;
56+
57+
VkPipelineRasterizationStateCreateInfo rasterizationState = { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO };
58+
rasterizationState.lineWidth = 1.0f;
59+
60+
VkPipelineMultisampleStateCreateInfo multisampleState = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
61+
multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
62+
63+
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
64+
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
65+
colorBlendAttachment.blendEnable = VK_FALSE;
66+
VkPipelineColorBlendStateCreateInfo colorBlendState = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO };
67+
colorBlendState.attachmentCount = 1;
68+
colorBlendState.pAttachments = &colorBlendAttachment;
69+
70+
VkPipelineLayout pipelineLayout;
71+
{
72+
VkPipelineLayoutCreateInfo createInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
73+
VKA(vkCreatePipelineLayout(context->device, &createInfo, 0, &pipelineLayout));
74+
}
75+
76+
VkPipeline pipeline;
77+
{
78+
VkGraphicsPipelineCreateInfo createInfo = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
79+
createInfo.stageCount = ARRAY_COUNT(shaderStages);
80+
createInfo.pStages = shaderStages;
81+
createInfo.pVertexInputState = &vertexInputState;
82+
createInfo.pInputAssemblyState = &inputAssemblyState;
83+
createInfo.pViewportState = &viewportState;
84+
createInfo.pRasterizationState = &rasterizationState;
85+
createInfo.pMultisampleState = &multisampleState;
86+
createInfo.pColorBlendState = &colorBlendState;
87+
createInfo.layout = pipelineLayout;
88+
createInfo.renderPass = renderPass;
89+
createInfo.subpass = 0;
90+
VKA(vkCreateGraphicsPipelines(context->device, 0, 1, &createInfo, 0, &pipeline));
91+
}
92+
93+
// Module can be destroyed after pipeline creation
94+
VK(vkDestroyShaderModule(context->device, vertexShaderModule, 0));
95+
VK(vkDestroyShaderModule(context->device, fragmentShaderModule, 0));
96+
97+
VulkanPipeline result = {};
98+
result.pipeline = pipeline;
99+
result.pipelineLayout = pipelineLayout;
100+
return result;
101+
}
102+
103+
void destroyPipeline(VulkanContext* context, VulkanPipeline* pipeline) {
104+
VK(vkDestroyPipeline(context->device, pipeline->pipeline, 0));
105+
VK(vkDestroyPipelineLayout(context->device, pipeline->pipelineLayout, 0));
106+
}

0 commit comments

Comments
 (0)