|
|
|
@ -6,6 +6,7 @@
@@ -6,6 +6,7 @@
|
|
|
|
|
#include <string.h> |
|
|
|
|
#include <stdlib.h> |
|
|
|
|
#include <stdbool.h> |
|
|
|
|
#include <cglm/cglm.h> |
|
|
|
|
|
|
|
|
|
#define WIDTH 2560 |
|
|
|
|
#define HEIGHT 1440 |
|
|
|
@ -69,6 +70,9 @@ typedef struct ApplicationState {
@@ -69,6 +70,9 @@ typedef struct ApplicationState {
|
|
|
|
|
VkSemaphore image_available_semaph[MAX_FRAMES_IN_FLIGHT]; |
|
|
|
|
VkSemaphore render_finished_sempah[MAX_FRAMES_IN_FLIGHT]; |
|
|
|
|
VkFence in_flight_frames[MAX_FRAMES_IN_FLIGHT]; |
|
|
|
|
|
|
|
|
|
VkBuffer vertex_buffer; |
|
|
|
|
VkDeviceMemory vertex_buffer_memory; |
|
|
|
|
} ApplicationState; |
|
|
|
|
|
|
|
|
|
typedef struct QueueFamilyIndices { |
|
|
|
@ -78,6 +82,17 @@ typedef struct QueueFamilyIndices {
@@ -78,6 +82,17 @@ typedef struct QueueFamilyIndices {
|
|
|
|
|
uint32_t present_queue; |
|
|
|
|
} QueueFamilyIndices; |
|
|
|
|
|
|
|
|
|
typedef struct Vertex { |
|
|
|
|
vec2 position; |
|
|
|
|
vec3 color; |
|
|
|
|
} Vertex; |
|
|
|
|
|
|
|
|
|
const Vertex vertices[] = { |
|
|
|
|
{{0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}}, |
|
|
|
|
{{0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}}, |
|
|
|
|
{{-0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
void create_window(ApplicationState* state) { |
|
|
|
|
glfwInit(); |
|
|
|
|
|
|
|
|
@ -692,15 +707,27 @@ void create_graphics_pipeline(ApplicationState* state) {
@@ -692,15 +707,27 @@ void create_graphics_pipeline(ApplicationState* state) {
|
|
|
|
|
dynamic_state.dynamicStateCount = ARRSIZE(dynamic_states); |
|
|
|
|
dynamic_state.pDynamicStates = dynamic_states; |
|
|
|
|
|
|
|
|
|
VkVertexInputBindingDescription binding = { |
|
|
|
|
.binding = 0, |
|
|
|
|
.stride = sizeof(Vertex), |
|
|
|
|
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//We have position and color, so we need two descriptions
|
|
|
|
|
VkVertexInputAttributeDescription attribute_description[2] = { |
|
|
|
|
{.binding = 0, .location = 0, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(Vertex, position)}, |
|
|
|
|
{.binding = 0, .location = 1, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(Vertex, color)}, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//vertex input format
|
|
|
|
|
//bindings: spacing between data, what data is per-vertex and what data is per instance
|
|
|
|
|
//attribute types, which bindings to load them from and at which offset
|
|
|
|
|
VkPipelineVertexInputStateCreateInfo vertex_input_info = {0}; |
|
|
|
|
vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; |
|
|
|
|
vertex_input_info.vertexBindingDescriptionCount = 0; |
|
|
|
|
vertex_input_info.pVertexBindingDescriptions = NULL; |
|
|
|
|
vertex_input_info.vertexAttributeDescriptionCount = 0; |
|
|
|
|
vertex_input_info.pVertexAttributeDescriptions = NULL; |
|
|
|
|
vertex_input_info.vertexBindingDescriptionCount = 1; |
|
|
|
|
vertex_input_info.pVertexBindingDescriptions = &binding; |
|
|
|
|
vertex_input_info.vertexAttributeDescriptionCount = ARRSIZE(attribute_description); |
|
|
|
|
vertex_input_info.pVertexAttributeDescriptions = attribute_description; |
|
|
|
|
|
|
|
|
|
//input assembly
|
|
|
|
|
//type of geometry and primitive restart, which allows one to break lines and triangles
|
|
|
|
@ -862,13 +889,61 @@ void create_command_pool(ApplicationState* state) {
@@ -862,13 +889,61 @@ void create_command_pool(ApplicationState* state) {
|
|
|
|
|
pool_info.queueFamilyIndex = families.graphics_queue; |
|
|
|
|
|
|
|
|
|
if (vkCreateCommandPool(state->device, &pool_info, NULL, &state->commandPool) != VK_SUCCESS) { |
|
|
|
|
printf("failed to create command pool"); |
|
|
|
|
printf("failed to create command pool\n"); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
printf("created command pools\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint32_t find_memory_type (ApplicationState* state, uint32_t type_filter, VkMemoryPropertyFlags props) { |
|
|
|
|
VkPhysicalDeviceMemoryProperties mem_props; |
|
|
|
|
vkGetPhysicalDeviceMemoryProperties(state->physical_device, &mem_props); |
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < mem_props.memoryTypeCount; i++) { |
|
|
|
|
if ((type_filter & (1 << i)) && (mem_props.memoryTypes[i].propertyFlags & props) == props) { |
|
|
|
|
return i; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
printf("no suitable memory type\n"); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void create_vertex_buffer(ApplicationState* state) { |
|
|
|
|
VkBufferCreateInfo buffer_info = {0}; |
|
|
|
|
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; |
|
|
|
|
buffer_info.size = sizeof(Vertex) * ARRSIZE(vertices); |
|
|
|
|
buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; |
|
|
|
|
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
|
|
|
|
|
|
|
|
|
if (vkCreateBuffer(state->device, &buffer_info, NULL, &state->vertex_buffer) != VK_SUCCESS) { |
|
|
|
|
printf("Failed to create vertex buffer\n"); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
VkMemoryRequirements mem_req; |
|
|
|
|
vkGetBufferMemoryRequirements(state->device, state->vertex_buffer, &mem_req); |
|
|
|
|
|
|
|
|
|
VkMemoryAllocateInfo alloc_info = {0}; |
|
|
|
|
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; |
|
|
|
|
alloc_info.allocationSize = mem_req.size; |
|
|
|
|
alloc_info.memoryTypeIndex = find_memory_type(state, mem_req.memoryTypeBits, |
|
|
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); |
|
|
|
|
|
|
|
|
|
if (vkAllocateMemory(state->device, &alloc_info, NULL, &state->vertex_buffer_memory) != VK_SUCCESS) { |
|
|
|
|
printf("failed to allocate memory for buffer\n"); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
vkBindBufferMemory(state->device, state->vertex_buffer, state->vertex_buffer_memory, 0); |
|
|
|
|
|
|
|
|
|
void* data; |
|
|
|
|
vkMapMemory(state->device, state->vertex_buffer_memory, 0, buffer_info.size, 0, &data); |
|
|
|
|
memcpy(data, vertices, buffer_info.size); |
|
|
|
|
vkUnmapMemory(state->device, state->vertex_buffer_memory); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void create_command_buffer(ApplicationState* state) { |
|
|
|
|
VkCommandBufferAllocateInfo command_buf_allocate_info = {0}; |
|
|
|
|
command_buf_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; |
|
|
|
@ -916,6 +991,10 @@ void record_command_buffer(ApplicationState* state, VkCommandBuffer command_buff
@@ -916,6 +991,10 @@ void record_command_buffer(ApplicationState* state, VkCommandBuffer command_buff
|
|
|
|
|
|
|
|
|
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, state->graphics_pipeline); |
|
|
|
|
|
|
|
|
|
VkBuffer vertex_buffers[] = {state->vertex_buffer}; |
|
|
|
|
VkDeviceSize offsets[] = {0}; |
|
|
|
|
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets); |
|
|
|
|
|
|
|
|
|
//setup dynamic state
|
|
|
|
|
VkViewport viewport = {0}; |
|
|
|
|
viewport.x = 0.0f; |
|
|
|
@ -935,7 +1014,7 @@ void record_command_buffer(ApplicationState* state, VkCommandBuffer command_buff
@@ -935,7 +1014,7 @@ void record_command_buffer(ApplicationState* state, VkCommandBuffer command_buff
|
|
|
|
|
vkCmdSetScissor(command_buffer, 0, 1, &scissor); |
|
|
|
|
|
|
|
|
|
//vertex count, instance count, first vertex and first instance
|
|
|
|
|
vkCmdDraw(command_buffer, 3, 1, 0, 0); |
|
|
|
|
vkCmdDraw(command_buffer, ARRSIZE(vertices), 1, 0, 0); |
|
|
|
|
|
|
|
|
|
vkCmdEndRenderPass(command_buffer); |
|
|
|
|
|
|
|
|
@ -977,6 +1056,7 @@ void init_vulkan(ApplicationState* state) {
@@ -977,6 +1056,7 @@ void init_vulkan(ApplicationState* state) {
|
|
|
|
|
create_graphics_pipeline(state); |
|
|
|
|
create_framebuffers(state); |
|
|
|
|
create_command_pool(state); |
|
|
|
|
create_vertex_buffer(state); |
|
|
|
|
create_command_buffer(state); |
|
|
|
|
create_sync_objects(state); |
|
|
|
|
} |
|
|
|
@ -1057,6 +1137,9 @@ void terminate(ApplicationState* state) {
@@ -1057,6 +1137,9 @@ void terminate(ApplicationState* state) {
|
|
|
|
|
for (int i = 0; i < state->swapchain_image_count; i++) { |
|
|
|
|
vkDestroyImageView(state->device, state->swapchain_image_views[i], NULL); |
|
|
|
|
} |
|
|
|
|
vkDestroyBuffer(state->device, state->vertex_buffer, NULL); |
|
|
|
|
vkFreeMemory(state->device, state->vertex_buffer_memory, NULL); |
|
|
|
|
|
|
|
|
|
vkDestroySwapchainKHR(state->device, state->swapchain, NULL); |
|
|
|
|
vkDestroyDevice(state->device, NULL); |
|
|
|
|
vkDestroySurfaceKHR(state->instance, state->surface, NULL); |
|
|
|
|