|
|
|
@ -17,6 +17,39 @@ PFN_vkCreateDebugUtilsMessengerEXT vkeCreateDebugUtilsMessengerEXT = nullptr; |
|
|
|
PFN_vkDestroyDebugUtilsMessengerEXT vkeDestroyDebugUtilsMessengerEXT = nullptr; |
|
|
|
|
|
|
|
|
|
|
|
VkVertexInputBindingDescription Vertex::binding_description() { |
|
|
|
return { |
|
|
|
.binding = 0, |
|
|
|
.stride = sizeof(Vertex), |
|
|
|
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX, |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
std::array<VkVertexInputAttributeDescription, 2> Vertex::attributes_description() { |
|
|
|
return { |
|
|
|
VkVertexInputAttributeDescription { |
|
|
|
.location = 0, |
|
|
|
.binding = 0, |
|
|
|
.format = VK_FORMAT_R32G32_SFLOAT, |
|
|
|
.offset = offsetof(Vertex, position), |
|
|
|
}, |
|
|
|
{ |
|
|
|
.location = 1, |
|
|
|
.binding = 0, |
|
|
|
.format = VK_FORMAT_R32G32B32_SFLOAT, |
|
|
|
.offset = offsetof(Vertex, color), |
|
|
|
}, |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const std::vector<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}} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
VulkanTutorial::VulkanTutorial() { |
|
|
|
} |
|
|
|
|
|
|
|
@ -36,6 +69,7 @@ void VulkanTutorial::initialize(SDL_Window* window) { |
|
|
|
create_graphic_pipeline(); |
|
|
|
create_framebuffers(); |
|
|
|
create_command_pool(); |
|
|
|
create_vertex_buffer(); |
|
|
|
create_command_buffers(); |
|
|
|
create_sync_objects(); |
|
|
|
} |
|
|
|
@ -64,6 +98,16 @@ void VulkanTutorial::shutdown() { |
|
|
|
m_command_pool = VK_NULL_HANDLE; |
|
|
|
} |
|
|
|
|
|
|
|
if(m_vertex_buffer != VK_NULL_HANDLE) { |
|
|
|
vkDestroyBuffer(m_device, m_vertex_buffer, nullptr); |
|
|
|
m_vertex_buffer = VK_NULL_HANDLE; |
|
|
|
} |
|
|
|
|
|
|
|
if(m_vertex_buffer_memory != VK_NULL_HANDLE) { |
|
|
|
vkFreeMemory(m_device, m_vertex_buffer_memory, nullptr); |
|
|
|
m_vertex_buffer_memory = VK_NULL_HANDLE; |
|
|
|
} |
|
|
|
|
|
|
|
cleanup_swap_chain(); |
|
|
|
|
|
|
|
if(m_device) { |
|
|
|
@ -600,12 +644,17 @@ void VulkanTutorial::create_graphic_pipeline() { |
|
|
|
}, |
|
|
|
}; |
|
|
|
|
|
|
|
const VkVertexInputBindingDescription vertex_bindings[] = { |
|
|
|
Vertex::binding_description(), |
|
|
|
}; |
|
|
|
const auto vertex_attributes = Vertex::attributes_description(); |
|
|
|
|
|
|
|
VkPipelineVertexInputStateCreateInfo vertex_info { |
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, |
|
|
|
.vertexBindingDescriptionCount = 0, |
|
|
|
.pVertexBindingDescriptions = nullptr, |
|
|
|
.vertexAttributeDescriptionCount = 0, |
|
|
|
.pVertexAttributeDescriptions = nullptr, |
|
|
|
.vertexBindingDescriptionCount = 1, |
|
|
|
.pVertexBindingDescriptions = vertex_bindings, |
|
|
|
.vertexAttributeDescriptionCount = uint32_t(vertex_attributes.size()), |
|
|
|
.pVertexAttributeDescriptions = vertex_attributes.data(), |
|
|
|
}; |
|
|
|
|
|
|
|
VkPipelineInputAssemblyStateCreateInfo assembly_info { |
|
|
|
@ -748,6 +797,42 @@ void VulkanTutorial::create_command_pool() { |
|
|
|
throw std::runtime_error("failed to create command pool"); |
|
|
|
} |
|
|
|
|
|
|
|
void VulkanTutorial::create_vertex_buffer() { |
|
|
|
VkBufferCreateInfo buffer_info { |
|
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
|
|
|
.size = sizeof(vertices[0]) * vertices.size(), |
|
|
|
.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, |
|
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
|
|
|
}; |
|
|
|
|
|
|
|
if(vkCreateBuffer(m_device, &buffer_info, nullptr, &m_vertex_buffer) != VK_SUCCESS) |
|
|
|
throw std::runtime_error("failed to create vertex buffer"); |
|
|
|
|
|
|
|
VkMemoryRequirements memory_requirements; |
|
|
|
vkGetBufferMemoryRequirements(m_device, m_vertex_buffer, &memory_requirements); |
|
|
|
|
|
|
|
const auto memory_type = find_memory(memory_requirements.memoryTypeBits, |
|
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); |
|
|
|
if(memory_type < 0) |
|
|
|
throw std::runtime_error("failed to find suitable memory type for vertex buffer"); |
|
|
|
|
|
|
|
VkMemoryAllocateInfo alloc_info { |
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, |
|
|
|
.allocationSize = memory_requirements.size, |
|
|
|
.memoryTypeIndex = uint32_t(memory_type), |
|
|
|
}; |
|
|
|
|
|
|
|
if(vkAllocateMemory(m_device, &alloc_info, nullptr, &m_vertex_buffer_memory) != VK_SUCCESS) |
|
|
|
throw std::runtime_error("failed to allocate vertex buffer memory"); |
|
|
|
|
|
|
|
vkBindBufferMemory(m_device, m_vertex_buffer, m_vertex_buffer_memory, 0); |
|
|
|
|
|
|
|
void* buffer = nullptr; |
|
|
|
vkMapMemory(m_device, m_vertex_buffer_memory, 0, buffer_info.size, 0, &buffer); |
|
|
|
memcpy(buffer, vertices.data(), size_t(buffer_info.size)); |
|
|
|
vkUnmapMemory(m_device, m_vertex_buffer_memory); |
|
|
|
} |
|
|
|
|
|
|
|
void VulkanTutorial::create_command_buffers() { |
|
|
|
m_command_buffers.resize(m_framebuffers.size()); |
|
|
|
|
|
|
|
@ -794,8 +879,19 @@ void VulkanTutorial::create_command_buffers() { |
|
|
|
}; |
|
|
|
|
|
|
|
vkCmdBeginRenderPass(command_buffer, &pass_info, VK_SUBPASS_CONTENTS_INLINE); |
|
|
|
|
|
|
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline); |
|
|
|
vkCmdDraw(command_buffer, 3, 1, 0, 0); |
|
|
|
|
|
|
|
VkBuffer vertex_buffers[] = { |
|
|
|
m_vertex_buffer, |
|
|
|
}; |
|
|
|
VkDeviceSize offsets[] = { |
|
|
|
0, |
|
|
|
}; |
|
|
|
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets); |
|
|
|
|
|
|
|
vkCmdDraw(command_buffer, uint32_t(vertices.size()), 1, 0, 0); |
|
|
|
|
|
|
|
vkCmdEndRenderPass(command_buffer); |
|
|
|
|
|
|
|
if(vkEndCommandBuffer(command_buffer) != VK_SUCCESS) |
|
|
|
@ -902,6 +998,19 @@ VkShaderModule VulkanTutorial::create_shader_module_from_file(const char* path) |
|
|
|
return VK_NULL_HANDLE; |
|
|
|
} |
|
|
|
|
|
|
|
int32_t VulkanTutorial::find_memory(uint32_t type_filter, VkMemoryPropertyFlags properties) { |
|
|
|
VkPhysicalDeviceMemoryProperties memory_properties; |
|
|
|
vkGetPhysicalDeviceMemoryProperties(m_physical_device, &memory_properties); |
|
|
|
|
|
|
|
for(uint32_t type_index = 0; type_index < memory_properties.memoryTypeCount; type_index += 1) { |
|
|
|
if(((1 << type_index) & type_filter) && |
|
|
|
(memory_properties.memoryTypes[type_index].propertyFlags & properties) == properties) |
|
|
|
return type_index; |
|
|
|
} |
|
|
|
|
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
std::vector<VkPhysicalDevice> VulkanTutorial::get_physical_devices() const { |
|
|
|
uint32_t devices_count = 0; |
|
|
|
vkEnumeratePhysicalDevices(m_instance, &devices_count, nullptr); |
|
|
|
|