VulkanTutorial refactoring.
This commit is contained in:
@@ -43,7 +43,7 @@ void VkExpe::initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VkExpe::shutdown() {
|
void VkExpe::shutdown() {
|
||||||
m_vulkan.shutdown();
|
recreate_object(m_vulkan);
|
||||||
|
|
||||||
m_window.reset();
|
m_window.reset();
|
||||||
|
|
||||||
|
|||||||
@@ -100,9 +100,7 @@ struct Uniforms {
|
|||||||
|
|
||||||
VulkanTutorial::VulkanTutorial() {
|
VulkanTutorial::VulkanTutorial() {
|
||||||
m_swapchain.register_creation_callback(
|
m_swapchain.register_creation_callback(
|
||||||
std::bind(&VulkanTutorial::create_swapchain_objects, this, std::placeholders::_1));
|
std::bind(&VulkanTutorial::create_swapchain_objects, this));
|
||||||
m_swapchain.register_destruction_callback(
|
|
||||||
std::bind(&VulkanTutorial::destroy_swapchain_objects, this));
|
|
||||||
|
|
||||||
auto const subdiv_count = 4;
|
auto const subdiv_count = 4;
|
||||||
|
|
||||||
@@ -154,9 +152,11 @@ VulkanTutorial::VulkanTutorial() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VulkanTutorial::~VulkanTutorial() {
|
VulkanTutorial::~VulkanTutorial() {
|
||||||
shutdown();
|
if(m_context)
|
||||||
|
vkDeviceWaitIdle(m_context.device());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VulkanTutorial::initialize(SDL_Window* window) {
|
void VulkanTutorial::initialize(SDL_Window* window) {
|
||||||
auto const context_settings = vk::ContextSettings()
|
auto const context_settings = vk::ContextSettings()
|
||||||
#if defined(VKEXPE_ENABLE_VALIDATION) || !defined(NDEBUG)
|
#if defined(VKEXPE_ENABLE_VALIDATION) || !defined(NDEBUG)
|
||||||
@@ -167,7 +167,13 @@ void VulkanTutorial::initialize(SDL_Window* window) {
|
|||||||
m_context.initialize(context_settings);
|
m_context.initialize(context_settings);
|
||||||
|
|
||||||
create_command_pool();
|
create_command_pool();
|
||||||
|
|
||||||
create_descriptor_set_layout();
|
create_descriptor_set_layout();
|
||||||
|
create_pipeline_layout();
|
||||||
|
create_render_pass();
|
||||||
|
|
||||||
|
// m_uniform_buffer_memory is allocated when uniform buffer is first created.
|
||||||
|
|
||||||
create_vertex_buffer();
|
create_vertex_buffer();
|
||||||
create_index_buffer();
|
create_index_buffer();
|
||||||
|
|
||||||
@@ -176,24 +182,6 @@ void VulkanTutorial::initialize(SDL_Window* window) {
|
|||||||
m_swapchain.initialize(swapchain_settings);
|
m_swapchain.initialize(swapchain_settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanTutorial::shutdown() {
|
|
||||||
if(!m_context.instance())
|
|
||||||
return;
|
|
||||||
|
|
||||||
vkDeviceWaitIdle(m_context.device());
|
|
||||||
|
|
||||||
destroy_swapchain_objects();
|
|
||||||
|
|
||||||
m_command_pool.destroy();
|
|
||||||
m_index_buffer.destroy();
|
|
||||||
m_vertex_buffer.destroy();
|
|
||||||
m_descriptor_set_layout.destroy();
|
|
||||||
|
|
||||||
m_render_done.clear();
|
|
||||||
|
|
||||||
m_swapchain.shutdown();
|
|
||||||
m_context.shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanTutorial::set_camera(const Vector3& camera_position, const Vector3& camera_z, const Vector3& camera_y) {
|
void VulkanTutorial::set_camera(const Vector3& camera_position, const Vector3& camera_z, const Vector3& camera_y) {
|
||||||
m_camera_position = camera_position;
|
m_camera_position = camera_position;
|
||||||
@@ -201,9 +189,11 @@ void VulkanTutorial::set_camera(const Vector3& camera_position, const Vector3& c
|
|||||||
m_camera_y = camera_y;
|
m_camera_y = camera_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VulkanTutorial::draw_frame() {
|
void VulkanTutorial::draw_frame() {
|
||||||
m_swapchain.begin_frame();
|
m_swapchain.begin_frame();
|
||||||
auto const image_index = m_swapchain.current_image_index();
|
const auto image_index = m_swapchain.current_image_index();
|
||||||
|
auto& image_states = m_image_states[image_index];
|
||||||
|
|
||||||
const auto now = Clock::now();
|
const auto now = Clock::now();
|
||||||
if(m_last_frame_time.time_since_epoch() != Duration(0)) {
|
if(m_last_frame_time.time_since_epoch() != Duration(0)) {
|
||||||
@@ -245,7 +235,7 @@ void VulkanTutorial::draw_frame() {
|
|||||||
|
|
||||||
void* uniform_buffer = m_uniform_buffer_memory.map(
|
void* uniform_buffer = m_uniform_buffer_memory.map(
|
||||||
m_context,
|
m_context,
|
||||||
m_uniform_buffer_offsets[image_index],
|
image_states.m_uniform_buffer_offset,
|
||||||
sizeof(Uniforms)
|
sizeof(Uniforms)
|
||||||
);
|
);
|
||||||
std::memcpy(uniform_buffer, &uniforms, sizeof(Uniforms));
|
std::memcpy(uniform_buffer, &uniforms, sizeof(Uniforms));
|
||||||
@@ -255,13 +245,13 @@ void VulkanTutorial::draw_frame() {
|
|||||||
m_swapchain.ready_to_render(),
|
m_swapchain.ready_to_render(),
|
||||||
};
|
};
|
||||||
VkSemaphore done_semaphores[] = {
|
VkSemaphore done_semaphores[] = {
|
||||||
m_render_done[image_index],
|
image_states.m_render_done,
|
||||||
};
|
};
|
||||||
VkPipelineStageFlags stages[] = {
|
VkPipelineStageFlags stages[] = {
|
||||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
};
|
};
|
||||||
VkCommandBuffer command_buffers[] = {
|
VkCommandBuffer command_buffers[] = {
|
||||||
m_command_buffers[image_index],
|
image_states.m_command_buffer,
|
||||||
};
|
};
|
||||||
VkSubmitInfo submit_info {
|
VkSubmitInfo submit_info {
|
||||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||||
@@ -288,39 +278,45 @@ void VulkanTutorial::invalidate_swapchain() {
|
|||||||
m_swapchain.invalidate();
|
m_swapchain.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanTutorial::create_swapchain_objects(uint32_t image_count) {
|
|
||||||
create_render_pass();
|
|
||||||
create_framebuffers();
|
|
||||||
create_uniform_buffer();
|
|
||||||
create_descriptor_pool();
|
|
||||||
create_descriptor_sets();
|
|
||||||
create_graphic_pipeline();
|
|
||||||
create_command_buffers();
|
|
||||||
|
|
||||||
m_render_done.clear();
|
void VulkanTutorial::create_swapchain_objects() {
|
||||||
for(size_t index = 0; index < m_swapchain.image_count(); index += 1) {
|
m_image_states.clear();
|
||||||
m_render_done.emplace_back(m_context);
|
m_swapchain_states.~SwapchainStates();
|
||||||
}
|
|
||||||
|
new(&m_swapchain_states) SwapchainStates();
|
||||||
|
initialize_swapchain_states();
|
||||||
|
|
||||||
|
m_image_states.resize(m_swapchain.image_count());
|
||||||
|
for(size_t image_index = 0; image_index < m_image_states.size(); image_index += 1)
|
||||||
|
initialize_image_states(image_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanTutorial::destroy_swapchain_objects() {
|
|
||||||
if(m_command_pool == VK_NULL_HANDLE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_command_buffers.clear();
|
void VulkanTutorial::create_command_pool() {
|
||||||
|
m_command_pool = vk::CommandPool(
|
||||||
|
m_context,
|
||||||
|
m_context.queue_family(GRAPHIC_QUEUE)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
for(auto& buffer: m_uniform_buffers)
|
|
||||||
buffer.destroy();
|
|
||||||
m_uniform_buffers.clear();
|
|
||||||
m_uniform_buffer_memory.free();
|
|
||||||
|
|
||||||
m_descriptor_pool.destroy();
|
void VulkanTutorial::create_descriptor_set_layout() {
|
||||||
|
VkDescriptorSetLayoutBinding binding[] {
|
||||||
|
{
|
||||||
|
.binding = 0,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
m_descriptor_set_layout = vk::DescriptorSetLayout(m_context, binding);
|
||||||
|
}
|
||||||
|
|
||||||
m_framebuffers.clear();
|
void VulkanTutorial::create_pipeline_layout() {
|
||||||
|
VkDescriptorSetLayout set_layouts[] {
|
||||||
m_pipeline.destroy();
|
m_descriptor_set_layout,
|
||||||
m_pipeline_layout.destroy();
|
};
|
||||||
m_render_pass.destroy();
|
m_pipeline_layout = vk::PipelineLayout(m_context, set_layouts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanTutorial::create_render_pass() {
|
void VulkanTutorial::create_render_pass() {
|
||||||
@@ -368,17 +364,51 @@ void VulkanTutorial::create_render_pass() {
|
|||||||
m_render_pass = vk::RenderPass(m_context, render_pass_info);
|
m_render_pass = vk::RenderPass(m_context, render_pass_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanTutorial::create_descriptor_set_layout() {
|
|
||||||
VkDescriptorSetLayoutBinding binding[] {
|
void VulkanTutorial::create_vertex_buffer() {
|
||||||
|
VkDeviceSize size = sizeof(vertices[0]) * vertices.size();
|
||||||
|
m_vertex_buffer = vk::Buffer(
|
||||||
|
m_context,
|
||||||
|
size,
|
||||||
|
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
|
||||||
|
| VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||||
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
||||||
|
);
|
||||||
|
m_vertex_buffer.upload(size, vertices.data(), m_context.queue_family(GRAPHIC_QUEUE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanTutorial::create_index_buffer() {
|
||||||
|
VkDeviceSize size = sizeof(indices[0]) * indices.size();
|
||||||
|
m_index_buffer = vk::Buffer(
|
||||||
|
m_context,
|
||||||
|
size,
|
||||||
|
VK_BUFFER_USAGE_INDEX_BUFFER_BIT
|
||||||
|
| VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||||
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
||||||
|
);
|
||||||
|
m_index_buffer.upload(size, indices.data(), m_context.queue_family(GRAPHIC_QUEUE));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VulkanTutorial::initialize_swapchain_states() {
|
||||||
|
create_descriptor_pool();
|
||||||
|
create_graphic_pipeline();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VulkanTutorial::create_descriptor_pool() {
|
||||||
|
VkDescriptorPoolSize pool_sizes[] {
|
||||||
{
|
{
|
||||||
.binding = 0,
|
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
.descriptorCount = uint32_t(m_swapchain.image_count()),
|
||||||
.descriptorCount = 1,
|
|
||||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT,
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
m_descriptor_set_layout = vk::DescriptorSetLayout(m_context, binding);
|
m_swapchain_states.m_descriptor_pool = vk::DescriptorPool(
|
||||||
|
m_context,
|
||||||
|
uint32_t(m_swapchain.image_count()),
|
||||||
|
pool_sizes
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanTutorial::create_graphic_pipeline() {
|
void VulkanTutorial::create_graphic_pipeline() {
|
||||||
@@ -497,11 +527,6 @@ void VulkanTutorial::create_graphic_pipeline() {
|
|||||||
.blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f },
|
.blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f },
|
||||||
};
|
};
|
||||||
|
|
||||||
VkDescriptorSetLayout set_layouts[] {
|
|
||||||
m_descriptor_set_layout,
|
|
||||||
};
|
|
||||||
m_pipeline_layout = vk::PipelineLayout(m_context, set_layouts);
|
|
||||||
|
|
||||||
VkGraphicsPipelineCreateInfo pipeline_info {
|
VkGraphicsPipelineCreateInfo pipeline_info {
|
||||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
.stageCount = 3,
|
.stageCount = 3,
|
||||||
@@ -521,228 +546,187 @@ void VulkanTutorial::create_graphic_pipeline() {
|
|||||||
.basePipelineIndex = -1,
|
.basePipelineIndex = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
m_pipeline = vk::Pipeline(m_context, pipeline_info);
|
m_swapchain_states.m_pipeline = vk::Pipeline(m_context, pipeline_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanTutorial::create_framebuffers() {
|
|
||||||
m_framebuffers.clear();
|
void VulkanTutorial::initialize_image_states(size_t image_index) {
|
||||||
for(size_t index = 0; index < m_swapchain.image_count(); index += 1) {
|
auto& image_states = m_image_states[image_index];
|
||||||
VkImageView view = m_swapchain.image_view(index);
|
image_states.m_image_index = image_index;
|
||||||
m_framebuffers.emplace_back(
|
|
||||||
m_context,
|
create_framebuffer(image_states);
|
||||||
m_render_pass,
|
|
||||||
&view,
|
create_uniform_buffer(image_states);
|
||||||
m_swapchain.extent()
|
create_descriptor_set(image_states);
|
||||||
|
|
||||||
|
create_command_buffer(image_states);
|
||||||
|
|
||||||
|
image_states.m_render_done = vk::Semaphore(m_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VulkanTutorial::create_framebuffer(ImageStates& image_states) {
|
||||||
|
auto view = m_swapchain.image_view(image_states.m_image_index);
|
||||||
|
image_states.m_framebuffer = vk::Framebuffer(
|
||||||
|
m_context,
|
||||||
|
m_render_pass,
|
||||||
|
&view,
|
||||||
|
m_swapchain.extent()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VulkanTutorial::create_uniform_buffer(ImageStates& image_states) {
|
||||||
|
const auto image_index = image_states.m_image_index;
|
||||||
|
|
||||||
|
image_states.m_uniform_buffer = vk::Buffer(
|
||||||
|
m_context,
|
||||||
|
sizeof(Uniforms),
|
||||||
|
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
|
||||||
|
);
|
||||||
|
auto& buffer = image_states.m_uniform_buffer;
|
||||||
|
|
||||||
|
if(!m_uniform_buffer_memory) {
|
||||||
|
VkMemoryRequirements memory_requirements =
|
||||||
|
buffer.memory_requirements();
|
||||||
|
|
||||||
|
m_uniform_buffer_memory = m_context.allocator().allocate(
|
||||||
|
memory_requirements.size * m_swapchain.image_count(),
|
||||||
|
memory_requirements.memoryTypeBits,
|
||||||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
||||||
|
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanTutorial::create_command_pool() {
|
for (size_t index = 0; index < m_swapchain.image_count(); index += 1)
|
||||||
if(!m_command_pool.is_null())
|
m_image_states[index].m_uniform_buffer_offset =
|
||||||
return;
|
index * memory_requirements.size;
|
||||||
|
|
||||||
m_command_pool = vk::CommandPool(
|
|
||||||
m_context,
|
|
||||||
m_context.queue_family(GRAPHIC_QUEUE)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanTutorial::create_vertex_buffer() {
|
|
||||||
if(m_vertex_buffer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
VkDeviceSize size = sizeof(vertices[0]) * vertices.size();
|
|
||||||
m_vertex_buffer = vk::Buffer(
|
|
||||||
m_context,
|
|
||||||
size,
|
|
||||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
|
|
||||||
| VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
|
||||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
|
||||||
);
|
|
||||||
m_vertex_buffer.upload(size, vertices.data(), m_context.queue_family(GRAPHIC_QUEUE));
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanTutorial::create_index_buffer() {
|
|
||||||
if(m_index_buffer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
VkDeviceSize size = sizeof(indices[0]) * indices.size();
|
|
||||||
m_index_buffer = vk::Buffer(
|
|
||||||
m_context,
|
|
||||||
size,
|
|
||||||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT
|
|
||||||
| VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
|
||||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
|
||||||
);
|
|
||||||
m_index_buffer.upload(size, indices.data(), m_context.queue_family(GRAPHIC_QUEUE));
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanTutorial::create_uniform_buffer() {
|
|
||||||
m_uniform_buffers.resize(m_swapchain.image_count());
|
|
||||||
for(size_t index = 0; index < m_uniform_buffers.size(); index += 1) {
|
|
||||||
m_uniform_buffers[index] = vk::Buffer(
|
|
||||||
m_context,
|
|
||||||
sizeof(Uniforms),
|
|
||||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VkMemoryRequirements memory_requirements =
|
buffer.bind_memory(
|
||||||
m_uniform_buffers[0].memory_requirements();
|
m_uniform_buffer_memory,
|
||||||
|
image_states.m_uniform_buffer_offset
|
||||||
m_uniform_buffer_memory = m_context.allocator().allocate(
|
|
||||||
memory_requirements.size * m_swapchain.image_count(),
|
|
||||||
memory_requirements.memoryTypeBits,
|
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
|
||||||
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
|
||||||
);
|
);
|
||||||
|
|
||||||
m_uniform_buffer_offsets.resize(m_uniform_buffers.size());
|
|
||||||
for(size_t index = 0; index < m_uniform_buffers.size(); index += 1) {
|
|
||||||
m_uniform_buffer_offsets[index] = index * memory_requirements.size;
|
|
||||||
m_uniform_buffers[index].bind_memory(
|
|
||||||
m_uniform_buffer_memory,
|
|
||||||
m_uniform_buffer_offsets[index]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanTutorial::create_descriptor_pool() {
|
void VulkanTutorial::create_descriptor_set(ImageStates& image_states) {
|
||||||
VkDescriptorPoolSize pool_sizes[] {
|
image_states.m_descriptor_set = vk::DescriptorSet(
|
||||||
{
|
m_context,
|
||||||
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
m_swapchain_states.m_descriptor_pool,
|
||||||
.descriptorCount = uint32_t(m_swapchain.image_count()),
|
m_descriptor_set_layout
|
||||||
|
);
|
||||||
|
|
||||||
|
VkDescriptorBufferInfo buffer_info {
|
||||||
|
.buffer = image_states.m_uniform_buffer,
|
||||||
|
.offset = 0,
|
||||||
|
.range = sizeof(Uniforms),
|
||||||
|
};
|
||||||
|
VkWriteDescriptorSet write {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
.dstSet = image_states.m_descriptor_set,
|
||||||
|
.dstBinding = 0,
|
||||||
|
.dstArrayElement = 0,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
.pBufferInfo = &buffer_info,
|
||||||
|
};
|
||||||
|
vkUpdateDescriptorSets(
|
||||||
|
m_context.device(),
|
||||||
|
1, &write,
|
||||||
|
0, nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanTutorial::create_command_buffer(ImageStates& image_states) {
|
||||||
|
image_states.m_command_buffer = vk::CommandBuffer(m_context, m_command_pool);
|
||||||
|
|
||||||
|
VkCommandBufferBeginInfo begin_info {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||||
|
.flags = 0,
|
||||||
|
.pInheritanceInfo = nullptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
logger.debug() << "record command buffer " << image_states.m_image_index
|
||||||
|
<< " (" << image_states.m_command_buffer << ")";
|
||||||
|
|
||||||
|
if(vkBeginCommandBuffer(
|
||||||
|
image_states.m_command_buffer,
|
||||||
|
&begin_info
|
||||||
|
) != VK_SUCCESS)
|
||||||
|
throw std::runtime_error("failed to begin command buffer");
|
||||||
|
|
||||||
|
VkClearValue clear_color = {
|
||||||
|
.color = {
|
||||||
|
.float32 = { 0.0f, 0.0f, 0.0f, 1.0f }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
m_descriptor_pool = vk::DescriptorPool(
|
VkRenderPassBeginInfo pass_info {
|
||||||
m_context,
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||||
uint32_t(m_swapchain.image_count()),
|
.renderPass = m_render_pass,
|
||||||
pool_sizes
|
.framebuffer = image_states.m_framebuffer,
|
||||||
|
.renderArea = {
|
||||||
|
.offset = { 0, 0 },
|
||||||
|
.extent = m_swapchain.extent(),
|
||||||
|
},
|
||||||
|
.clearValueCount = 1,
|
||||||
|
.pClearValues = &clear_color,
|
||||||
|
};
|
||||||
|
|
||||||
|
vkCmdBeginRenderPass(
|
||||||
|
image_states.m_command_buffer,
|
||||||
|
&pass_info,
|
||||||
|
VK_SUBPASS_CONTENTS_INLINE
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
vkCmdBindPipeline(
|
||||||
void VulkanTutorial::create_descriptor_sets() {
|
image_states.m_command_buffer,
|
||||||
m_descriptor_sets.clear();
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
for(size_t index = 0; index < m_swapchain.image_count(); index += 1) {
|
m_swapchain_states.m_pipeline
|
||||||
m_descriptor_sets.emplace_back(m_context, m_descriptor_pool, m_descriptor_set_layout);
|
);
|
||||||
VkDescriptorBufferInfo buffer_info {
|
|
||||||
.buffer = m_uniform_buffers[index],
|
VkBuffer vertex_buffers[] = {
|
||||||
.offset = 0,
|
m_vertex_buffer,
|
||||||
.range = sizeof(Uniforms),
|
};
|
||||||
};
|
VkDeviceSize offsets[] = {
|
||||||
|
0,
|
||||||
VkWriteDescriptorSet write {
|
};
|
||||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
vkCmdBindVertexBuffers(
|
||||||
.dstSet = m_descriptor_sets[index],
|
image_states.m_command_buffer,
|
||||||
.dstBinding = 0,
|
0,
|
||||||
.dstArrayElement = 0,
|
1,
|
||||||
.descriptorCount = 1,
|
vertex_buffers,
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
offsets
|
||||||
.pBufferInfo = &buffer_info,
|
);
|
||||||
};
|
|
||||||
vkUpdateDescriptorSets(
|
vkCmdBindIndexBuffer(
|
||||||
m_context.device(),
|
image_states.m_command_buffer,
|
||||||
1, &write,
|
m_index_buffer,
|
||||||
0, nullptr
|
0,
|
||||||
);
|
VK_INDEX_TYPE_UINT32
|
||||||
}
|
);
|
||||||
}
|
|
||||||
|
VkDescriptorSet descriptor_sets[] {
|
||||||
void VulkanTutorial::create_command_buffers() {
|
image_states.m_descriptor_set,
|
||||||
m_command_buffers.clear();
|
};
|
||||||
for(size_t index = 0; index < m_framebuffers.size(); index += 1) {
|
vkCmdBindDescriptorSets(
|
||||||
m_command_buffers.emplace_back(m_context, m_command_pool);
|
image_states.m_command_buffer,
|
||||||
VkCommandBuffer command_buffer = m_command_buffers[index];
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
m_pipeline_layout,
|
||||||
VkCommandBufferBeginInfo begin_info {
|
0, 1, descriptor_sets,
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
0, nullptr
|
||||||
.flags = 0,
|
);
|
||||||
.pInheritanceInfo = nullptr,
|
|
||||||
};
|
vkCmdDrawIndexed(
|
||||||
|
image_states.m_command_buffer,
|
||||||
logger.debug() << "record command buffer " << index << " (" << command_buffer << ")";
|
uint32_t(indices.size()),
|
||||||
|
1,
|
||||||
if(vkBeginCommandBuffer(
|
0,
|
||||||
command_buffer,
|
0,
|
||||||
&begin_info
|
0
|
||||||
) != VK_SUCCESS)
|
);
|
||||||
throw std::runtime_error("failed to begin command buffer");
|
|
||||||
|
vkCmdEndRenderPass(image_states.m_command_buffer);
|
||||||
VkClearValue clear_color = {
|
|
||||||
.color = {
|
if(vkEndCommandBuffer(image_states.m_command_buffer) != VK_SUCCESS)
|
||||||
.float32 = { 0.0f, 0.0f, 0.0f, 1.0f }
|
throw("failed to record command buffer");
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
VkRenderPassBeginInfo pass_info {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
|
||||||
.renderPass = m_render_pass,
|
|
||||||
.framebuffer = m_framebuffers[index],
|
|
||||||
.renderArea = {
|
|
||||||
.offset = { 0, 0 },
|
|
||||||
.extent = m_swapchain.extent(),
|
|
||||||
},
|
|
||||||
.clearValueCount = 1,
|
|
||||||
.pClearValues = &clear_color,
|
|
||||||
};
|
|
||||||
|
|
||||||
vkCmdBeginRenderPass(
|
|
||||||
command_buffer,
|
|
||||||
&pass_info,
|
|
||||||
VK_SUBPASS_CONTENTS_INLINE
|
|
||||||
);
|
|
||||||
|
|
||||||
vkCmdBindPipeline(
|
|
||||||
command_buffer,
|
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
||||||
m_pipeline
|
|
||||||
);
|
|
||||||
|
|
||||||
VkBuffer vertex_buffers[] = {
|
|
||||||
m_vertex_buffer,
|
|
||||||
};
|
|
||||||
VkDeviceSize offsets[] = {
|
|
||||||
0,
|
|
||||||
};
|
|
||||||
vkCmdBindVertexBuffers(
|
|
||||||
command_buffer,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
vertex_buffers,
|
|
||||||
offsets
|
|
||||||
);
|
|
||||||
|
|
||||||
vkCmdBindIndexBuffer(
|
|
||||||
command_buffer,
|
|
||||||
m_index_buffer,
|
|
||||||
0,
|
|
||||||
VK_INDEX_TYPE_UINT32
|
|
||||||
);
|
|
||||||
|
|
||||||
VkDescriptorSet descriptor_sets[] {
|
|
||||||
m_descriptor_sets[index],
|
|
||||||
};
|
|
||||||
vkCmdBindDescriptorSets(
|
|
||||||
command_buffer,
|
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
||||||
m_pipeline_layout,
|
|
||||||
0, 1, descriptor_sets,
|
|
||||||
0, nullptr
|
|
||||||
);
|
|
||||||
|
|
||||||
vkCmdDrawIndexed(
|
|
||||||
command_buffer,
|
|
||||||
uint32_t(indices.size()),
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
vkCmdEndRenderPass(command_buffer);
|
|
||||||
|
|
||||||
if(vkEndCommandBuffer(command_buffer) != VK_SUCCESS)
|
|
||||||
throw("failed to record command buffer");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ public:
|
|||||||
VulkanTutorial& operator=(const VulkanTutorial&) = delete;
|
VulkanTutorial& operator=(const VulkanTutorial&) = delete;
|
||||||
|
|
||||||
void initialize(SDL_Window* window);
|
void initialize(SDL_Window* window);
|
||||||
void shutdown();
|
|
||||||
|
|
||||||
void set_camera(const Vector3& camera_position, const Vector3& camera_z, const Vector3& camera_y);
|
void set_camera(const Vector3& camera_position, const Vector3& camera_z, const Vector3& camera_y);
|
||||||
|
|
||||||
@@ -58,42 +57,71 @@ public:
|
|||||||
void invalidate_swapchain();
|
void invalidate_swapchain();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void create_swapchain_objects(uint32_t image_count);
|
struct SwapchainStates;
|
||||||
void destroy_swapchain_objects();
|
struct ImageStates;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void create_swapchain_objects();
|
||||||
|
|
||||||
void create_render_pass();
|
|
||||||
void create_descriptor_set_layout();
|
|
||||||
void create_graphic_pipeline();
|
|
||||||
void create_framebuffers();
|
|
||||||
void create_command_pool();
|
void create_command_pool();
|
||||||
|
|
||||||
|
void create_descriptor_set_layout();
|
||||||
|
void create_pipeline_layout();
|
||||||
|
void create_render_pass();
|
||||||
|
|
||||||
void create_vertex_buffer();
|
void create_vertex_buffer();
|
||||||
void create_index_buffer();
|
void create_index_buffer();
|
||||||
void create_uniform_buffer();
|
|
||||||
|
void initialize_swapchain_states();
|
||||||
|
|
||||||
void create_descriptor_pool();
|
void create_descriptor_pool();
|
||||||
void create_descriptor_sets();
|
void create_graphic_pipeline();
|
||||||
void create_command_buffers();
|
|
||||||
|
void initialize_image_states(size_t image_index);
|
||||||
|
|
||||||
|
void create_framebuffer(ImageStates& image_states);
|
||||||
|
|
||||||
|
void create_uniform_buffer(ImageStates& image_states);
|
||||||
|
void create_descriptor_set(ImageStates& image_states);
|
||||||
|
|
||||||
|
void create_command_buffer(ImageStates& image_states);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vk::Context m_context;
|
vk::Context m_context;
|
||||||
vk::Swapchain m_swapchain;
|
|
||||||
VkQueue m_graphic_queue = nullptr;
|
|
||||||
VkQueue m_presentation_queue = nullptr;
|
|
||||||
|
|
||||||
vk::RenderPass m_render_pass;
|
vk::CommandPool m_command_pool;
|
||||||
|
|
||||||
vk::DescriptorSetLayout m_descriptor_set_layout;
|
vk::DescriptorSetLayout m_descriptor_set_layout;
|
||||||
vk::PipelineLayout m_pipeline_layout;
|
vk::PipelineLayout m_pipeline_layout;
|
||||||
vk::Pipeline m_pipeline;
|
vk::RenderPass m_render_pass;
|
||||||
std::vector<vk::Framebuffer> m_framebuffers;
|
|
||||||
vk::CommandPool m_command_pool;
|
|
||||||
vk::Buffer m_vertex_buffer;
|
vk::Buffer m_vertex_buffer;
|
||||||
vk::Buffer m_index_buffer;
|
vk::Buffer m_index_buffer;
|
||||||
std::vector<vk::Buffer> m_uniform_buffers;
|
|
||||||
std::vector<VkDeviceSize> m_uniform_buffer_offsets;
|
|
||||||
vk::MemoryBlock m_uniform_buffer_memory;
|
vk::MemoryBlock m_uniform_buffer_memory;
|
||||||
vk::DescriptorPool m_descriptor_pool;
|
|
||||||
std::vector<vk::DescriptorSet> m_descriptor_sets;
|
vk::Swapchain m_swapchain;
|
||||||
std::vector<vk::CommandBuffer> m_command_buffers;
|
|
||||||
std::vector<vk::Semaphore> m_render_done;
|
struct SwapchainStates {
|
||||||
|
vk::DescriptorPool m_descriptor_pool;
|
||||||
|
vk::Pipeline m_pipeline;
|
||||||
|
};
|
||||||
|
SwapchainStates m_swapchain_states;
|
||||||
|
|
||||||
|
struct ImageStates {
|
||||||
|
size_t m_image_index;
|
||||||
|
|
||||||
|
vk::Framebuffer m_framebuffer;
|
||||||
|
|
||||||
|
vk::Buffer m_uniform_buffer;
|
||||||
|
VkDeviceSize m_uniform_buffer_offset;
|
||||||
|
vk::DescriptorSet m_descriptor_set;
|
||||||
|
|
||||||
|
vk::CommandBuffer m_command_buffer;
|
||||||
|
vk::Semaphore m_render_done;
|
||||||
|
};
|
||||||
|
std::vector<ImageStates> m_image_states;
|
||||||
|
|
||||||
|
|
||||||
Vector3 m_camera_position = Vector3(0.0f, 0.0f, -3.0f);
|
Vector3 m_camera_position = Vector3(0.0f, 0.0f, -3.0f);
|
||||||
Vector3 m_camera_z = Vector3(0.0f, 0.0f, 1.0f);
|
Vector3 m_camera_z = Vector3(0.0f, 0.0f, 1.0f);
|
||||||
|
|||||||
@@ -33,6 +33,14 @@ Guard<T> make_guard(T&& teardown) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T& recreate_object(T& object) {
|
||||||
|
object.~T();
|
||||||
|
new(&object) T;
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
std::string cat(Args&&... args) {
|
std::string cat(Args&&... args) {
|
||||||
std::ostringstream ostream;
|
std::ostringstream ostream;
|
||||||
|
|||||||
@@ -56,10 +56,8 @@ Buffer::Buffer(Buffer&& other) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Buffer::~Buffer() noexcept {
|
Buffer::~Buffer() noexcept {
|
||||||
if(!is_null()) {
|
if(!is_null())
|
||||||
logger.warning() << "Buffer deleted before being destroyed";
|
|
||||||
destroy();
|
destroy();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer& Buffer::operator=(Buffer&& other) noexcept {
|
Buffer& Buffer::operator=(Buffer&& other) noexcept {
|
||||||
|
|||||||
@@ -42,10 +42,8 @@ MemoryBlock::MemoryBlock(MemoryBlock&& other) noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
MemoryBlock::~MemoryBlock() noexcept {
|
MemoryBlock::~MemoryBlock() noexcept {
|
||||||
if(!is_null()) {
|
if(!is_null())
|
||||||
logger.warning() << "MemoryBlock deleted before being freed";
|
|
||||||
free();
|
free();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryBlock& MemoryBlock::operator=(MemoryBlock&& other) noexcept {
|
MemoryBlock& MemoryBlock::operator=(MemoryBlock&& other) noexcept {
|
||||||
@@ -176,6 +174,8 @@ MemoryBlock MemoryPage::allocate(VkDeviceSize size) noexcept {
|
|||||||
if(block_it == m_blocks.end())
|
if(block_it == m_blocks.end())
|
||||||
return MemoryBlock();
|
return MemoryBlock();
|
||||||
|
|
||||||
|
const auto offset = block_it->offset;
|
||||||
|
|
||||||
block_it[0].is_free = false;
|
block_it[0].is_free = false;
|
||||||
if (block_it[0].offset != block_it[1].offset) {
|
if (block_it[0].offset != block_it[1].offset) {
|
||||||
m_blocks.emplace(std::next(block_it), Block{
|
m_blocks.emplace(std::next(block_it), Block{
|
||||||
@@ -183,7 +183,7 @@ MemoryBlock MemoryPage::allocate(VkDeviceSize size) noexcept {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return MemoryBlock(m_device_memory, size, block_it[0].offset, this, m_memory_type);
|
return MemoryBlock(m_device_memory, size, offset, this, m_memory_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryPage::p_free(MemoryBlock& block) noexcept {
|
void MemoryPage::p_free(MemoryBlock& block) noexcept {
|
||||||
|
|||||||
@@ -324,7 +324,7 @@ void Swapchain::create() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(auto& callback: m_creation_callbacks)
|
for(auto& callback: m_creation_callbacks)
|
||||||
callback(image_count);
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Swapchain::destroy() {
|
void Swapchain::destroy() {
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public:
|
|||||||
static constexpr uint32_t CURRENT_IMAGE_INDEX = UINT32_MAX;
|
static constexpr uint32_t CURRENT_IMAGE_INDEX = UINT32_MAX;
|
||||||
static constexpr uint32_t MAX_FRAMES_IN_FLIGHT = 2;
|
static constexpr uint32_t MAX_FRAMES_IN_FLIGHT = 2;
|
||||||
|
|
||||||
using CreationCallback = std::function<void(uint32_t)>;
|
using CreationCallback = std::function<void()>;
|
||||||
using DestructionCallback = std::function<void()>;
|
using DestructionCallback = std::function<void()>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
Reference in New Issue
Block a user