From 75acd0104448d7c5f43f99700decff39b8a034b2 Mon Sep 17 00:00:00 2001 From: ladevieq Date: Fri, 3 Feb 2023 00:15:19 +0100 Subject: Graphics pipeline and rendering implementation --- api-test/CMakeLists.txt | 1 + api-test/command-buffer.cpp | 20 +- api-test/main.cpp | 223 +++++++++++---- api-test/vk-bindless.cpp | 125 ++++++--- api-test/vk-device.cpp | 655 +++++++++++++++++++++++++------------------- 5 files changed, 666 insertions(+), 358 deletions(-) (limited to 'api-test') diff --git a/api-test/CMakeLists.txt b/api-test/CMakeLists.txt index 93eceee..3fcad92 100644 --- a/api-test/CMakeLists.txt +++ b/api-test/CMakeLists.txt @@ -16,3 +16,4 @@ target_include_directories(api-test SYSTEM PUBLIC ${Vulkan_INCLUDE_DIRS}) target_include_directories(api-test SYSTEM PUBLIC ${CMAKE_SOURCE_DIR}/thirdparty) target_include_directories(api-test PUBLIC ${CMAKE_SOURCE_DIR}/include) target_include_directories(api-test PUBLIC ${CMAKE_SOURCE_DIR}/include/api-test) +target_link_libraries(api-test PRIVATE imgui::imgui) diff --git a/api-test/command-buffer.cpp b/api-test/command-buffer.cpp index b130d3d..78b1505 100644 --- a/api-test/command-buffer.cpp +++ b/api-test/command-buffer.cpp @@ -12,7 +12,7 @@ void command_buffer::start() const { VkCommandBufferBeginInfo begin_info{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .pNext = nullptr, - .flags = 0U, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, .pInheritanceInfo = nullptr }; @@ -112,7 +112,8 @@ void command_buffer::copy(handle buffer_handle, ::handleget_pipeline(params.pipeline); const auto& bindless = vkdevice::get_render_device()->get_bindingmodel(); - vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.layout, static_cast(BindlessSetType::UNIFORMS), 1U, &bindless.sets[BindlessSetType::UNIFORMS], 1U, ¶ms.uniforms_offset); + vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.layout, static_cast(BindlessSetType::INSTANCES_UNIFORMS), 1U, &bindless.sets[BindlessSetType::INSTANCES_UNIFORMS], 1U, ¶ms.uniforms_offset); + vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.layout, static_cast(BindlessSetType::DRAWS_UNIFORMS), 1U, &bindless.sets[BindlessSetType::DRAWS_UNIFORMS], 1U, ¶ms.uniforms_offset); vkCmdBindPipeline(vk_command_buffer, pipeline.bind_point, pipeline.vk_pipeline); @@ -179,10 +180,21 @@ void graphics_command_buffer::begin_renderpass(const renderpass_params& params) } void graphics_command_buffer::render(const draw_params& params) const { - const auto& pipeline = vkdevice::get_render_device()->get_pipeline(params.pipeline); + auto* device = vkdevice::get_render_device(); + const auto& pipeline = device->get_pipeline(params.pipeline); + + const auto& bindless = device->get_bindingmodel(); + vkCmdBindDescriptorSets(vk_command_buffer, pipeline.bind_point, bindless.layout, static_cast(BindlessSetType::DRAWS_UNIFORMS), 1U, &bindless.sets[BindlessSetType::DRAWS_UNIFORMS], 1U, ¶ms.uniforms_offset); vkCmdBindPipeline(vk_command_buffer, pipeline.bind_point, pipeline.vk_pipeline); - vkCmdDraw(vk_command_buffer, params.vertex_count, params.instance_count, 0U, 0U); + + if (params.index_buffer.is_valid()) { + const auto& index_buffer = device->get_buffer(params.index_buffer); + vkCmdBindIndexBuffer(vk_command_buffer, index_buffer.vk_buffer, 0U, VK_INDEX_TYPE_UINT16); + vkCmdDrawIndexed(vk_command_buffer, params.vertex_count, params.instance_count, params.index_offset, static_cast(params.vertex_offset), 0U); + } else { + vkCmdDraw(vk_command_buffer, params.vertex_count, params.instance_count, params.vertex_offset, 0U); + } } void graphics_command_buffer::end_renderpass() const { diff --git a/api-test/main.cpp b/api-test/main.cpp index d6a4b3b..2f973ff 100644 --- a/api-test/main.cpp +++ b/api-test/main.cpp @@ -7,6 +7,8 @@ #define STB_IMAGE_IMPLEMENTATION #include +#include "imgui.h" + #include "window.hpp" #include "vk-device.hpp" #include "utils.hpp" @@ -18,9 +20,20 @@ struct device_texture; #ifdef ENABLE_RENDERDOC #include +#define RD_START_CAPTURE if(rdoc_api != nullptr) rdoc_api->StartFrameCapture(nullptr, nullptr) +#define RD_END_CAPTURE if(rdoc_api != nullptr) rdoc_api->EndFrameCapture(nullptr, nullptr) + RENDERDOC_API_1_4_1 *rdoc_api = nullptr; #endif +void ui() { + ImGui::NewFrame(); + bool open = true; + ImGui::ShowDemoWindow(&open); + ImGui::EndFrame(); + ImGui::Render(); +} + int main() { #ifdef ENABLE_RENDERDOC @@ -37,9 +50,10 @@ int main() { constexpr size_t window_height = 360U; window wnd { window_width, window_height }; -#ifdef ENABLE_RENDERDOC - if(rdoc_api != nullptr) rdoc_api->StartFrameCapture(nullptr, nullptr); -#endif + ImGui::CreateContext(); + ImGuiIO &io = ImGui::GetIO(); + io.DisplaySize.x = 1024.f; + io.DisplaySize.y = 1024.f; auto* device = vkdevice::init_device(wnd); @@ -90,40 +104,71 @@ int main() { .type = VK_IMAGE_TYPE_2D, }); - // auto gpu_buffer = vkdevice::get_buffer(device.create_buffer({ - // .size = 1024U * sizeof(uint32_t), - // .usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - // .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - // .memory_usage = VMA_MEMORY_USAGE_GPU_ONLY, - // })); + uint8_t *pixels = nullptr; + int atlas_width; + int atlas_height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &atlas_width, &atlas_height); + const auto ui_texture_handle = device->create_texture({ + .width = static_cast(atlas_width), + .height = static_cast(atlas_height), + .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + .format = VK_FORMAT_R8G8B8A8_UNORM, + .type = VK_IMAGE_TYPE_2D, + }); + const auto& ui_texture = device->get_texture(ui_texture_handle); + io.Fonts->SetTexID(*(void **)&ui_texture_handle.id); + + off_t ui_offset = 2L * offset; + size = static_cast(atlas_width) * atlas_height * 4U; + addr = static_cast(static_cast(staging_buffer.mapped_ptr) + ui_offset); + memcpy(addr, pixels, size); + + auto vertex_buffer = device->get_buffer(device->create_buffer({ + .size = 1024U * 1024U * sizeof(uint32_t), + .usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU, + })); + + auto index_buffer_handle = device->create_buffer({ + .size = 1024U * 1024U * sizeof(uint32_t), + .usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, + .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU, + }); + auto index_buffer = device->get_buffer(index_buffer_handle); auto code = read_file("shaders/test.comp.spv"); auto compute = device->create_pipeline({ - .cs_code = std::span(code), + .cs_code = code, }); std::array formats { VK_FORMAT_R8G8B8A8_UNORM }; auto vertex_code = read_file("shaders/api-test-ui.vert.spv"); auto fragment_code = read_file("shaders/api-test-ui.frag.spv"); auto graphics = device->create_pipeline({ - .vs_code = std::span(vertex_code), - .fs_code = std::span(fragment_code), + .vs_code = vertex_code, + .fs_code = fragment_code, .color_attachments_format = formats }); + auto semaphore = device->create_semaphore(); + std::array command_buffers; + device->allocate_command_buffers(command_buffers.data(), 2, QueueType::GRAPHICS); - graphics_command_buffer command_buffer; - device->allocate_command_buffers(&command_buffer, 1, QueueType::GRAPHICS); + RD_START_CAPTURE; - command_buffer.start(); + command_buffers[0].start(); - command_buffer.barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - command_buffer.barrier(second_texture, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - command_buffer.copy(staging_buffer_handle, gpu_texture_handle); - command_buffer.copy(staging_buffer_handle, second_texture, static_cast(offset)); + command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + command_buffers[0].barrier(second_texture, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + command_buffers[0].barrier(ui_texture_handle, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + command_buffers[0].copy(staging_buffer_handle, gpu_texture_handle); + command_buffers[0].copy(staging_buffer_handle, second_texture, static_cast(offset)); + command_buffers[0].copy(staging_buffer_handle, ui_texture_handle, static_cast(ui_offset)); - command_buffer.barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL); - command_buffer.barrier(second_texture, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL); + command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL); + command_buffers[0].barrier(second_texture, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL); struct compute_params { uint32_t input1; @@ -138,42 +183,128 @@ int main() { }; memcpy(uniform_buffer.mapped_ptr, ¶ms, sizeof(params)); - command_buffer.dispatch({ + command_buffers[0].dispatch({ .pipeline = compute, .group_size = { image_size, image_size, 1U }, .local_group_size = { 8U, 8U, 1U }, .uniforms_offset = 0U, }); - std::array, 1U> color_attachment {gpu_texture_handle}; - - command_buffer.barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - command_buffer.begin_renderpass({ - .render_area = { - .x = 0, - .y = 0, - .width = window_width, - .height = window_height, - }, - .color_attachments = color_attachment, - }); - command_buffer.render({ - .pipeline = graphics, - .vertex_count = 3U, - .instance_count = 1U, - }); - command_buffer.end_renderpass(); - - command_buffer.stop(); + command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - device->submit(&command_buffer, 1); + command_buffers[0].stop(); + std::array compute_command_buffers = {command_buffers[0]}; + device->submit(compute_command_buffers, nullptr, &semaphore); -#ifdef ENABLE_RENDERDOC - if(rdoc_api != nullptr) rdoc_api->EndFrameCapture(nullptr, nullptr); -#endif + RD_END_CAPTURE; + std::array ui_command_buffers = {command_buffers[1]}; + std::array, 1U> color_attachment {gpu_texture_handle}; while(wnd.isOpen) { wnd.poll_events(); + + ui(); + + auto* draw_data = ImGui::GetDrawData(); + struct vertex { + ImVec2 pos; + ImVec2 uv; + uint32_t color; + uint32_t padding; + }; + + off_t vertex_offset = 0; + off_t index_offset = 0; + for (auto index {0U} ; index < draw_data->CmdListsCount; index++) { + auto* cmd_list = draw_data->CmdLists[index]; + + size_t vertex_bytes_size = sizeof(ImDrawVert) * cmd_list->VtxBuffer.size(); + auto* vtx_ptr = static_cast(vertex_buffer.mapped_ptr) + vertex_offset; + for (auto vtx_index{0}; vtx_index < cmd_list->VtxBuffer.size(); vtx_index++, vtx_ptr++) { + auto& vtx = cmd_list->VtxBuffer[vtx_index]; + vtx_ptr->pos = vtx.pos; + vtx_ptr->uv = vtx.uv; + vtx_ptr->color = vtx.col; + } + // memcpy(static_cast(vertex_buffer.mapped_ptr) + vertex_offset, cmd_list->VtxBuffer.Data, vertex_bytes_size); + vertex_offset += static_cast(vertex_bytes_size); + + size_t index_bytes_size = sizeof(ImDrawIdx) * cmd_list->IdxBuffer.size(); + memcpy(static_cast(index_buffer.mapped_ptr) + index_offset, cmd_list->IdxBuffer.Data, index_bytes_size); + index_offset += static_cast(index_bytes_size); + } + + device->wait(semaphore); + + RD_START_CAPTURE; + command_buffers[1].start(), + + command_buffers[1].begin_renderpass({ + .render_area = { + .x = static_cast(draw_data->DisplayPos.x), + .y = static_cast(draw_data->DisplayPos.y), + .width = static_cast(draw_data->DisplaySize.x), + .height = static_cast(draw_data->DisplaySize.y), + }, + .color_attachments = color_attachment, + }); + + struct draw_params { + uintptr_t vertex_buffer; + float scale[2U]; + float translate[2U]; + uint32_t texture_index; + }; + + printf("%llu\n", sizeof(ImDrawVert)); + + uint32_t draw_index = 0U; + uint32_t vtx_offset = 0U; + uint32_t idx_offset = 0U; + std::array draws; + for (auto index {0U} ; index < draw_data->CmdListsCount; index++) { + auto* cmd_list = draw_data->CmdLists[index]; + + for (auto& draw_command : cmd_list->CmdBuffer) { + draws[draw_index] = draw_params{ + .vertex_buffer = vertex_buffer.device_address, + .scale { + 2.f / draw_data->DisplaySize.x, + 2.f / draw_data->DisplaySize.y, + }, + .translate { + -1.f - draw_data->DisplayPos.x * (2.f / draw_data->DisplaySize.x), + -1.f - draw_data->DisplayPos.y * (2.f / draw_data->DisplaySize.y), + }, + .texture_index = ui_texture.sampled_index, + }; + + command_buffers[1].render({ + .pipeline = graphics, + .index_buffer = index_buffer_handle, + .vertex_count = draw_command.ElemCount, + .vertex_offset = draw_command.VtxOffset, + .index_offset = draw_command.IdxOffset, + .instance_count = 1U, + .uniforms_offset = 0U, + }); + + draw_index++; + // vtx_offset += draw_command. + } + } + + memcpy(uniform_buffer.mapped_ptr, draws.data(), sizeof(draw_params) * draw_index); + + command_buffers[1].end_renderpass(); + + command_buffers[1].stop(); + + device->submit(ui_command_buffers, nullptr, &semaphore); + RD_END_CAPTURE; + + // std::system("PAUSE"); + break; } return 0; diff --git a/api-test/vk-bindless.cpp b/api-test/vk-bindless.cpp index c07db8e..654ce0c 100644 --- a/api-test/vk-bindless.cpp +++ b/api-test/vk-bindless.cpp @@ -8,7 +8,7 @@ const device_buffer& bindless_model::get_uniform_buffer() const { auto* render_device = vkdevice::get_render_device(); - return render_device->get_buffer(uniform_buffer); + return render_device->get_buffer(draws_uniform_buffer_handle); } bindless_model bindless_model::create_bindless_model() { @@ -20,34 +20,68 @@ bindless_model bindless_model::create_bindless_model() { bindless.create_layout(device); bindless.create_descriptor_pool(device); bindless.allocate_sets(device); - bindless.uniform_buffer = render_device->create_buffer({ - .size = 64U * 1024U, - .usages = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU, - }); - - const auto& buffer = render_device->get_buffer(bindless.uniform_buffer); - VkDescriptorBufferInfo buffer_info { - .buffer = buffer.vk_buffer, - .offset = 0U, - .range = VK_WHOLE_SIZE, - }; - VkWriteDescriptorSet write_descriptor_set { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .pNext = nullptr, - .dstSet = bindless.sets[BindlessSetType::UNIFORMS], - .dstBinding = 0U, - .dstArrayElement = 0U, - .descriptorCount = 1U, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, - .pImageInfo = nullptr, - .pBufferInfo = &buffer_info, - .pTexelBufferView = nullptr, - }; + VkWriteDescriptorSet writes_descriptor_set[2U]; + + { + bindless.instances_uniform_buffer_handle = render_device->create_buffer({ + .size = instances_uniform_buffer_size, + .usages = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU, + }); + + const auto& buffer = render_device->get_buffer(bindless.instances_uniform_buffer_handle); + VkDescriptorBufferInfo buffer_info { + .buffer = buffer.vk_buffer, + .offset = 0U, + .range = VK_WHOLE_SIZE, + }; + + writes_descriptor_set[0U] = { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .pNext = nullptr, + .dstSet = bindless.sets[BindlessSetType::INSTANCES_UNIFORMS], + .dstBinding = 0U, + .dstArrayElement = 0U, + .descriptorCount = 1U, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + .pImageInfo = nullptr, + .pBufferInfo = &buffer_info, + .pTexelBufferView = nullptr, + }; + } + + { + bindless.draws_uniform_buffer_handle = render_device->create_buffer({ + .size = draws_uniform_buffer_size, + .usages = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU, + }); + + const auto& buffer = render_device->get_buffer(bindless.draws_uniform_buffer_handle); + VkDescriptorBufferInfo buffer_info { + .buffer = buffer.vk_buffer, + .offset = 0U, + .range = VK_WHOLE_SIZE, + }; + + writes_descriptor_set[1U] = { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .pNext = nullptr, + .dstSet = bindless.sets[BindlessSetType::DRAWS_UNIFORMS], + .dstBinding = 0U, + .dstArrayElement = 0U, + .descriptorCount = 1U, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + .pImageInfo = nullptr, + .pBufferInfo = &buffer_info, + .pTexelBufferView = nullptr, + }; + } - vkUpdateDescriptorSets(device, 1U, &write_descriptor_set, 0U, nullptr); + vkUpdateDescriptorSets(device, sizeof(writes_descriptor_set) / sizeof(VkWriteDescriptorSet), writes_descriptor_set, 0U, nullptr); #else VkBufferCreateInfo create_info{ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, @@ -150,8 +184,32 @@ void bindless_model::create_layout(VkDevice device) { VKCHECK(vkCreateDescriptorSetLayout(device, &create_info, nullptr, &sets_layout[BindlessSetType::GLOBAL])); } - // Set 1 uniforms - // Binding 0 Uniforms + // Set 1 per instance uniforms + // Binding 0 Dynamic Uniform Buffer + { + VkDescriptorSetLayoutBinding set_layout_bindings[]{ + { + .binding = 0U, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, + .pImmutableSamplers = nullptr, + }, + }; + + VkDescriptorSetLayoutCreateInfo create_info{ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, + .bindingCount = sizeof(set_layout_bindings) / sizeof(VkDescriptorSetLayoutBinding), + .pBindings = set_layout_bindings, + }; + + VKCHECK(vkCreateDescriptorSetLayout(device, &create_info, nullptr, &sets_layout[BindlessSetType::INSTANCES_UNIFORMS])); + } + + // Set 2 per draw uniforms + // Binding 0 Dynamic Uniform Buffer { VkDescriptorSetLayoutBinding set_layout_bindings[]{ { @@ -171,7 +229,7 @@ void bindless_model::create_layout(VkDevice device) { .pBindings = set_layout_bindings, }; - VKCHECK(vkCreateDescriptorSetLayout(device, &create_info, nullptr, &sets_layout[BindlessSetType::UNIFORMS])); + VKCHECK(vkCreateDescriptorSetLayout(device, &create_info, nullptr, &sets_layout[BindlessSetType::DRAWS_UNIFORMS])); } VkPipelineLayoutCreateInfo create_info{ @@ -229,8 +287,11 @@ void bindless_model::allocate_sets(VkDevice device) { }; VKCHECK(vkAllocateDescriptorSets(device, &allocate_info, &sets[BindlessSetType::GLOBAL])); - allocate_info.pSetLayouts = &sets_layout[BindlessSetType::UNIFORMS], - VKCHECK(vkAllocateDescriptorSets(device, &allocate_info, &sets[BindlessSetType::UNIFORMS])); + allocate_info.pSetLayouts = &sets_layout[BindlessSetType::INSTANCES_UNIFORMS], + VKCHECK(vkAllocateDescriptorSets(device, &allocate_info, &sets[BindlessSetType::INSTANCES_UNIFORMS])); + + allocate_info.pSetLayouts = &sets_layout[BindlessSetType::DRAWS_UNIFORMS], + VKCHECK(vkAllocateDescriptorSets(device, &allocate_info, &sets[BindlessSetType::DRAWS_UNIFORMS])); } void bindless_model::create_immutable_samplers(VkDevice device) { diff --git a/api-test/vk-device.cpp b/api-test/vk-device.cpp index 6967e41..296d76c 100644 --- a/api-test/vk-device.cpp +++ b/api-test/vk-device.cpp @@ -6,26 +6,26 @@ #define VMA_IMPLEMENTATION #include +#include "vk-utils.hpp" #include "vulkan-loader.hpp" #include "window.hpp" -#include "vk-utils.hpp" vkdevice* vkdevice::render_device = nullptr; vkdevice::vkdevice(const window& window) : queues{ - { - .usages = VK_QUEUE_GRAPHICS_BIT | - VK_QUEUE_COMPUTE_BIT | - VK_QUEUE_TRANSFER_BIT, - }, - { - .usages = VK_QUEUE_COMPUTE_BIT, - }, - { - .usages = VK_QUEUE_TRANSFER_BIT, - }, - } { + { + .usages = VK_QUEUE_GRAPHICS_BIT | + VK_QUEUE_COMPUTE_BIT | + VK_QUEUE_TRANSFER_BIT, + }, + { + .usages = VK_QUEUE_COMPUTE_BIT, + }, + { + .usages = VK_QUEUE_TRANSFER_BIT, + }, + } { load_vulkan(); create_instance(); @@ -96,23 +96,22 @@ vkdevice::~vkdevice() { } handle vkdevice::create_texture(const texture_desc& desc) { - device_texture device_texture { + device_texture device_texture{ .desc = desc, }; assert(desc.mips <= texture_desc::max_mips); - VkImageCreateInfo create_info { - .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .pNext = nullptr, - .flags = 0U, - .imageType = desc.type, - .format = desc.format, - .extent = { - .width = desc.width, - .height = desc.height, - .depth = desc.depth - }, + VkImageCreateInfo create_info{ + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, + .imageType = desc.type, + .format = desc.format, + .extent = { + .width = desc.width, + .height = desc.height, + .depth = desc.depth }, .mipLevels = desc.mips, .arrayLayers = 1, .samples = VK_SAMPLE_COUNT_1_BIT, @@ -124,14 +123,14 @@ handle vkdevice::create_texture(const texture_desc& desc) { .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, }; - VmaAllocationCreateInfo alloc_create_info { - .flags = 0U, - .usage = VMA_MEMORY_USAGE_GPU_ONLY, - .requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - .preferredFlags = 0U, - .memoryTypeBits = 0U, - .pool = nullptr, - .pUserData = nullptr, + VmaAllocationCreateInfo alloc_create_info{ + .flags = 0U, + .usage = VMA_MEMORY_USAGE_GPU_ONLY, + .requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + .preferredFlags = 0U, + .memoryTypeBits = 0U, + .pool = nullptr, + .pUserData = nullptr, }; VKCHECK(vmaCreateImage(gpu_allocator, &create_info, &alloc_create_info, &device_texture.vk_image, &device_texture.alloc, nullptr)); @@ -139,27 +138,28 @@ handle vkdevice::create_texture(const texture_desc& desc) { create_views(device_texture); // TODO: Handle mips views - std::vector images_info; - images_info.push_back({ - .sampler = nullptr, - .imageView = device_texture.whole_view, - .imageLayout = VK_IMAGE_LAYOUT_GENERAL, - }); + VkDescriptorImageInfo images_info[]{ + { + nullptr, + device_texture.whole_view, + VK_IMAGE_LAYOUT_GENERAL, + }, + }; std::vector write_descriptor_sets; if ((desc.usages & VK_IMAGE_USAGE_STORAGE_BIT) != 0) { device_texture.storage_index = storage_indices.add(&device_texture); write_descriptor_sets.push_back({ - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .pNext = nullptr, - .dstSet = bindless.sets[BindlessSetType::GLOBAL], - .dstBinding = 2U, - .dstArrayElement = device_texture.storage_index, - .descriptorCount = static_cast(images_info.size()), - .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, - .pImageInfo = images_info.data(), - .pBufferInfo = nullptr, + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .pNext = nullptr, + .dstSet = bindless.sets[BindlessSetType::GLOBAL], + .dstBinding = 2U, + .dstArrayElement = device_texture.storage_index, + .descriptorCount = sizeof(images_info) / sizeof(VkDescriptorImageInfo), + .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .pImageInfo = images_info, + .pBufferInfo = nullptr, .pTexelBufferView = nullptr, }); } @@ -167,15 +167,15 @@ handle vkdevice::create_texture(const texture_desc& desc) { device_texture.sampled_index = sampled_indices.add(&device_texture); write_descriptor_sets.push_back({ - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .pNext = nullptr, - .dstSet = bindless.sets[BindlessSetType::GLOBAL], - .dstBinding = 1U, - .dstArrayElement = device_texture.sampled_index, - .descriptorCount = static_cast(images_info.size()), - .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, - .pImageInfo = images_info.data(), - .pBufferInfo = nullptr, + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .pNext = nullptr, + .dstSet = bindless.sets[BindlessSetType::GLOBAL], + .dstBinding = 1U, + .dstArrayElement = device_texture.sampled_index, + .descriptorCount = sizeof(images_info) / sizeof(VkDescriptorImageInfo), + .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + .pImageInfo = images_info, + .pBufferInfo = nullptr, .pTexelBufferView = nullptr, }); } @@ -186,11 +186,11 @@ handle vkdevice::create_texture(const texture_desc& desc) { } handle vkdevice::create_buffer(const buffer_desc& desc) { - device_buffer device_buffer { + device_buffer device_buffer{ .desc = desc, }; - VkBufferCreateInfo create_info { + VkBufferCreateInfo create_info{ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, .flags = 0U, @@ -201,11 +201,10 @@ handle vkdevice::create_buffer(const buffer_desc& desc) { .pQueueFamilyIndices = nullptr, }; - VmaAllocatorCreateFlags alloc_create_flags = - desc.memory_usage != VMA_MEMORY_USAGE_GPU_ONLY ? - VMA_ALLOCATION_CREATE_MAPPED_BIT : 0U; + VmaAllocatorCreateFlags alloc_create_flags = + desc.memory_usage != VMA_MEMORY_USAGE_GPU_ONLY ? VMA_ALLOCATION_CREATE_MAPPED_BIT : 0U; - VmaAllocationCreateInfo alloc_create_info { + VmaAllocationCreateInfo alloc_create_info{ .flags = alloc_create_flags, .usage = static_cast(desc.memory_usage), .requiredFlags = desc.memory_properties, @@ -215,53 +214,62 @@ handle vkdevice::create_buffer(const buffer_desc& desc) { .pUserData = nullptr, }; - VmaAllocationInfo alloc_info {}; + VmaAllocationInfo alloc_info{}; VKCHECK(vmaCreateBuffer(gpu_allocator, &create_info, &alloc_create_info, &device_buffer.vk_buffer, &device_buffer.alloc, &alloc_info)); + if ((desc.usages & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) != 0U) { + VkBufferDeviceAddressInfo address_info { + .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + .pNext = nullptr, + .buffer = device_buffer.vk_buffer, + }; + device_buffer.device_address = vkGetBufferDeviceAddress(device, &address_info); + } + device_buffer.mapped_ptr = alloc_info.pMappedData; return { buffers.add(device_buffer) }; } handle vkdevice::create_pipeline(const pipeline_desc& desc) { - device_pipeline device_pipeline { - .desc = desc, + device_pipeline device_pipeline{ + .desc = desc, .bindless = &bindless, }; if (!desc.cs_code.empty()) { VkShaderModule shader_module; { - const auto& code = desc.cs_code; - VkShaderModuleCreateInfo create_info { - .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .pNext = nullptr, - .flags = 0U, + const auto& code = desc.cs_code; + VkShaderModuleCreateInfo create_info{ + .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, .codeSize = code.size(), - .pCode = (uint32_t*)code.data(), + .pCode = (uint32_t*)code.data(), }; VKCHECK(vkCreateShaderModule(device, &create_info, nullptr, &shader_module)); } - VkPipelineShaderStageCreateInfo stage_create_info { - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .pNext = nullptr, - .flags = 0U, - .stage = VK_SHADER_STAGE_COMPUTE_BIT, - .module = shader_module, - .pName = "main", + VkPipelineShaderStageCreateInfo stage_create_info{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, + .stage = VK_SHADER_STAGE_COMPUTE_BIT, + .module = shader_module, + .pName = "main", .pSpecializationInfo = nullptr, }; - VkComputePipelineCreateInfo create_info { - .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - .pNext = nullptr, - .flags = 0U, - .stage = stage_create_info, - .layout = bindless.layout, + VkComputePipelineCreateInfo create_info{ + .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, + .stage = stage_create_info, + .layout = bindless.layout, .basePipelineHandle = nullptr, - .basePipelineIndex = 0, + .basePipelineIndex = 0, }; device_pipeline.bind_point = VK_PIPELINE_BIND_POINT_COMPUTE; @@ -269,158 +277,157 @@ handle vkdevice::create_pipeline(const pipeline_desc& desc) { vkDestroyShaderModule(device, shader_module, nullptr); } else { - VkPipelineShaderStageCreateInfo shader_stages_create_info[2U] { + VkPipelineShaderStageCreateInfo shader_stages_create_info[2U]{ { - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .pNext = nullptr, - .flags = 0U, - .stage = VK_SHADER_STAGE_VERTEX_BIT, - .pName = "main", + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, + .stage = VK_SHADER_STAGE_VERTEX_BIT, + .pName = "main", .pSpecializationInfo = nullptr, }, { - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .pNext = nullptr, - .flags = 0U, - .stage = VK_SHADER_STAGE_FRAGMENT_BIT, - .pName = "main", + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, + .stage = VK_SHADER_STAGE_FRAGMENT_BIT, + .pName = "main", .pSpecializationInfo = nullptr, }, }; { - const auto& code = desc.vs_code; - VkShaderModuleCreateInfo module_create_info { - .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .pNext = nullptr, - .flags = 0U, + const auto& code = desc.vs_code; + VkShaderModuleCreateInfo module_create_info{ + .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, .codeSize = code.size(), - .pCode = (uint32_t*)code.data(), + .pCode = (uint32_t*)code.data(), }; VKCHECK(vkCreateShaderModule(device, &module_create_info, nullptr, &shader_stages_create_info[0U].module)); - } { - const auto& code = desc.fs_code; - VkShaderModuleCreateInfo module_create_info { - .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .pNext = nullptr, - .flags = 0U, + const auto& code = desc.fs_code; + VkShaderModuleCreateInfo module_create_info{ + .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, .codeSize = code.size(), - .pCode = (uint32_t*)code.data(), + .pCode = (uint32_t*)code.data(), }; VKCHECK(vkCreateShaderModule(device, &module_create_info, nullptr, &shader_stages_create_info[1U].module)); } - VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info { + VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info{ .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, }; - VkPipelineInputAssemblyStateCreateInfo input_assembly_create_info { - .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0U, - .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + VkPipelineInputAssemblyStateCreateInfo input_assembly_create_info{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, + .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, .primitiveRestartEnable = VK_FALSE, }; - VkPipelineViewportStateCreateInfo viewport_state_create_info { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0U, + VkPipelineViewportStateCreateInfo viewport_state_create_info{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, .viewportCount = 1U, - .pViewports = nullptr, - .scissorCount = 1U, - .pScissors = nullptr, + .pViewports = nullptr, + .scissorCount = 1U, + .pScissors = nullptr, }; - VkPipelineRasterizationStateCreateInfo rasterization_state_create_info { - .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0U, - .depthClampEnable = VK_FALSE, + VkPipelineRasterizationStateCreateInfo rasterization_state_create_info{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, + .depthClampEnable = VK_FALSE, .rasterizerDiscardEnable = VK_FALSE, - .polygonMode = VK_POLYGON_MODE_FILL, - .cullMode = VK_CULL_MODE_NONE, - .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, - .depthBiasEnable = VK_FALSE, - .lineWidth = 1.f, + .polygonMode = VK_POLYGON_MODE_FILL, + .cullMode = VK_CULL_MODE_NONE, + .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, + .depthBiasEnable = VK_FALSE, + .lineWidth = 1.f, }; - VkPipelineMultisampleStateCreateInfo multisample_state_create_info { - .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, + VkPipelineMultisampleStateCreateInfo multisample_state_create_info{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, - .sampleShadingEnable = VK_FALSE, - .minSampleShading = 1.f, + .sampleShadingEnable = VK_FALSE, + .minSampleShading = 1.f, }; - VkPipelineColorBlendAttachmentState color_attachment_state { - .blendEnable = VK_TRUE, + VkPipelineColorBlendAttachmentState color_attachment_state{ + .blendEnable = VK_TRUE, .srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA, .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, - .colorBlendOp = VK_BLEND_OP_ADD, + .colorBlendOp = VK_BLEND_OP_ADD, .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE, .dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, - .alphaBlendOp = VK_BLEND_OP_ADD, - .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, + .alphaBlendOp = VK_BLEND_OP_ADD, + .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, }; - VkPipelineColorBlendStateCreateInfo color_blend_state_create_info { - .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .logicOpEnable = VK_FALSE, + VkPipelineColorBlendStateCreateInfo color_blend_state_create_info{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .logicOpEnable = VK_FALSE, .attachmentCount = 1, - .pAttachments = &color_attachment_state, + .pAttachments = &color_attachment_state, }; - VkDynamicState dynamic_states[] { + VkDynamicState dynamic_states[]{ VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, }; - VkPipelineDynamicStateCreateInfo dynamic_state_create_info { - .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0U, + VkPipelineDynamicStateCreateInfo dynamic_state_create_info{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, .dynamicStateCount = sizeof(dynamic_states) / sizeof(VkDynamicState), - .pDynamicStates = dynamic_states, + .pDynamicStates = dynamic_states, }; - VkPipelineRenderingCreateInfo pipeline_rendering_create_info { - .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, - .pNext = nullptr, - .viewMask = 0U, - .colorAttachmentCount = static_cast(desc.color_attachments_format.size()), + VkPipelineRenderingCreateInfo pipeline_rendering_create_info{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, + .pNext = nullptr, + .viewMask = 0U, + .colorAttachmentCount = static_cast(desc.color_attachments_format.size()), .pColorAttachmentFormats = desc.color_attachments_format.data(), - .depthAttachmentFormat = VK_FORMAT_UNDEFINED, + .depthAttachmentFormat = VK_FORMAT_UNDEFINED, .stencilAttachmentFormat = VK_FORMAT_UNDEFINED, }; - VkGraphicsPipelineCreateInfo create_info { - .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = &pipeline_rendering_create_info, - .flags = 0U, - .stageCount = sizeof(shader_stages_create_info) / sizeof(VkPipelineShaderStageCreateInfo), - .pStages = shader_stages_create_info, - .pVertexInputState = &vertex_input_state_create_info, + VkGraphicsPipelineCreateInfo create_info{ + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .pNext = &pipeline_rendering_create_info, + .flags = 0U, + .stageCount = sizeof(shader_stages_create_info) / sizeof(VkPipelineShaderStageCreateInfo), + .pStages = shader_stages_create_info, + .pVertexInputState = &vertex_input_state_create_info, .pInputAssemblyState = &input_assembly_create_info, - .pTessellationState = nullptr, - .pViewportState = &viewport_state_create_info, + .pTessellationState = nullptr, + .pViewportState = &viewport_state_create_info, .pRasterizationState = &rasterization_state_create_info, - .pMultisampleState = &multisample_state_create_info, - .pDepthStencilState = nullptr, - .pColorBlendState = &color_blend_state_create_info, - .pDynamicState = &dynamic_state_create_info, - .layout = bindless.layout, - .renderPass = nullptr, - .subpass = 0U, - .basePipelineHandle = nullptr, - .basePipelineIndex = 0, + .pMultisampleState = &multisample_state_create_info, + .pDepthStencilState = nullptr, + .pColorBlendState = &color_blend_state_create_info, + .pDynamicState = &dynamic_state_create_info, + .layout = bindless.layout, + .renderPass = nullptr, + .subpass = 0U, + .basePipelineHandle = nullptr, + .basePipelineIndex = 0, }; device_pipeline.bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS; @@ -430,6 +437,28 @@ handle vkdevice::create_pipeline(const pipeline_desc& desc) { return { pipelines.add(device_pipeline) }; } +vksemaphore vkdevice::create_semaphore() { + vksemaphore semaphore{ + .value = 0, + }; + VkSemaphoreTypeCreateInfo semaphore_type_create_info{ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, + .pNext = nullptr, + .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, + .initialValue = 0U, + }; + + VkSemaphoreCreateInfo create_info{ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + .pNext = &semaphore_type_create_info, + .flags = 0U, + }; + + VKCHECK(vkCreateSemaphore(device, &create_info, nullptr, &semaphore.vk_semaphore)); + + return semaphore; +} + void vkdevice::destroy_texture(const device_texture& texture) { destroy_texture({ .id = textures.find(texture) }); } @@ -467,17 +496,31 @@ void vkdevice::destroy_pipeline(handle handle) { vkDestroyPipeline(device, pipeline.vk_pipeline, nullptr); } -void vkdevice::submit(command_buffer* buffers, size_t count) { - assert((max_submitable_command_buffers - count) >= 0); +void vkdevice::wait(vksemaphore& semaphore) { + VkSemaphoreWaitInfo wait_info { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, + .pNext = nullptr, + .flags = 0U, + .semaphoreCount = 1U, + .pSemaphores = &semaphore.vk_semaphore, + .pValues = &semaphore.value, + }; + VKCHECK(vkWaitSemaphores(device, &wait_info, -1)); +} + +void vkdevice::submit(std::span buffers, vksemaphore* wait, vksemaphore* signal) { +#define USE_SUBMIT2 + assert((max_submitable_command_buffers - buffers.size()) >= 0); const auto queue_type = buffers[0].queue_type; +#ifndef USE_SUBMIT2 VkCommandBuffer to_submit[max_submitable_command_buffers]; - for (auto index { 0U }; index < count; index++) { + for (auto index{ 0U }; index < count; index++) { assert(queue_type == buffers[index].queue_type); to_submit[index] = buffers[index].vk_command_buffer; } - VkSubmitInfo submit_info { + VkSubmitInfo submit_info{ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .pNext = nullptr, .waitSemaphoreCount = 0U, @@ -490,25 +533,85 @@ void vkdevice::submit(command_buffer* buffers, size_t count) { }; VKCHECK(vkQueueSubmit(queues[static_cast(queue_type)].vk_queue, 1, &submit_info, nullptr)); +#else + VkCommandBufferSubmitInfo command_buffers_info[buffers.size()]; + + for (auto index{ 0U }; index < buffers.size(); index++) { + assert(queue_type == buffers[index].queue_type); + + auto& command_buffer_info = command_buffers_info[index]; + command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO; + command_buffer_info.pNext = nullptr; + command_buffer_info.commandBuffer = buffers[index].vk_command_buffer; + command_buffer_info.deviceMask = 0U; + } + + VkSemaphoreSubmitInfo wait_semaphore_info{ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, + .pNext = nullptr, + .stageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, + .deviceIndex = 0U, + }; + + VkSemaphoreSubmitInfo signal_semaphore_info{ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, + .pNext = nullptr, + .stageMask = VK_PIPELINE_STAGE_2_NONE, + .deviceIndex = 0U, + }; + + VkSubmitInfo2 submit_info{ + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2, + .pNext = nullptr, + .flags = 0U, + .commandBufferInfoCount = static_cast(buffers.size()), + .pCommandBufferInfos = command_buffers_info, + }; + + if (wait != nullptr) { + wait_semaphore_info.semaphore = wait->vk_semaphore; + wait_semaphore_info.value = wait->value; + submit_info.waitSemaphoreInfoCount = 1U; + submit_info.pWaitSemaphoreInfos = &wait_semaphore_info; + } + + if (signal != nullptr) { + signal_semaphore_info.semaphore = signal->vk_semaphore; + signal_semaphore_info.value = ++signal->value; + + submit_info.signalSemaphoreInfoCount = 1U; + submit_info.pSignalSemaphoreInfos = &signal_semaphore_info; + } + + VKCHECK(vkQueueSubmit2(queues[static_cast(queue_type)].vk_queue, 1, &submit_info, nullptr)); +#endif } -void vkdevice::present() { - VkPresentInfoKHR present_info { +void vkdevice::present(vksurface& surface, const vksemaphore& semaphore) { + VkResult result; + VkPresentInfoKHR present_info{ .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, .pNext = nullptr, + .waitSemaphoreCount = 1U, + .pWaitSemaphores = &semaphore.vk_semaphore, + .swapchainCount = 1U, + .pSwapchains = &surface.vk_swapchain, + .pImageIndices = &surface.image_index, + .pResults = &result, }; - // VKCHECK(vkQueuePresentKHR(queues[static_cast(QueueType::GRAPHICS)].vk_queue, &present_info)); -} + VKCHECK(vkQueuePresentKHR(queues[static_cast(QueueType::GRAPHICS)].vk_queue, &present_info)); + VKCHECK(result); +} // private void vkdevice::allocate_command_buffers(command_buffer* buffers, size_t count, QueueType type) { assert((max_allocable_command_buffers - count) >= 0); - const auto& queue = queues[static_cast(type)]; - VkCommandBuffer command_buffers[max_allocable_command_buffers]; + const auto& queue = queues[static_cast(type)]; + VkCommandBuffer command_buffers[max_allocable_command_buffers]; - VkCommandBufferAllocateInfo allocate_info { + VkCommandBufferAllocateInfo allocate_info{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, .pNext = nullptr, .commandPool = queue.command_pool, @@ -518,28 +621,28 @@ void vkdevice::allocate_command_buffers(command_buffer* buffers, size_t count, Q VKCHECK(vkAllocateCommandBuffers(device, &allocate_info, command_buffers)); - for (auto index { 0U }; index < count; index++) { + for (auto index{ 0U }; index < count; index++) { buffers[index].vk_command_buffer = command_buffers[index]; - buffers[index].queue_type = type; + buffers[index].queue_type = type; } } void vkdevice::create_views(device_texture& texture) { - VkImageAspectFlags aspect_mask = ((texture.desc.usages & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0U) - ? VK_IMAGE_ASPECT_DEPTH_BIT - : VK_IMAGE_ASPECT_COLOR_BIT; - VkImageViewCreateInfo create_info { - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .pNext = nullptr, - .flags = 0U, - .image = texture.vk_image, - .viewType = VK_IMAGE_VIEW_TYPE_2D, - .format = texture.desc.format, - .components = { - .r = VK_COMPONENT_SWIZZLE_R, - .g = VK_COMPONENT_SWIZZLE_G, - .b = VK_COMPONENT_SWIZZLE_B, - .a = VK_COMPONENT_SWIZZLE_A, + VkImageAspectFlags aspect_mask = ((texture.desc.usages & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0U) + ? VK_IMAGE_ASPECT_DEPTH_BIT + : VK_IMAGE_ASPECT_COLOR_BIT; + VkImageViewCreateInfo create_info{ + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, + .image = texture.vk_image, + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .format = texture.desc.format, + .components = { + .r = VK_COMPONENT_SWIZZLE_R, + .g = VK_COMPONENT_SWIZZLE_G, + .b = VK_COMPONENT_SWIZZLE_B, + .a = VK_COMPONENT_SWIZZLE_A, }, .subresourceRange = { .aspectMask = aspect_mask, @@ -562,12 +665,12 @@ void vkdevice::create_views(device_texture& texture) { // Presentation stuff void vkdevice::create_surface(const window& window) { - VkWin32SurfaceCreateInfoKHR create_info { - .sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, - .pNext = nullptr, - .flags = 0U, - .hinstance = GetModuleHandle(nullptr), - .hwnd = window.handle, + VkWin32SurfaceCreateInfoKHR create_info{ + .sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, + .pNext = nullptr, + .flags = 0U, + .hinstance = GetModuleHandle(nullptr), + .hwnd = window.handle, }; VKCHECK(vkCreateWin32SurfaceKHR(instance, &create_info, nullptr, &surface)); @@ -575,7 +678,7 @@ void vkdevice::create_surface(const window& window) { void vkdevice::create_swapchain() { VkBool32 supported = VK_FALSE; - auto& queue = queues[static_cast(QueueType::GRAPHICS)]; + auto& queue = queues[static_cast(QueueType::GRAPHICS)]; VKCHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, queue.index, surface, &supported)); assert(supported); @@ -611,43 +714,43 @@ void vkdevice::create_swapchain() { VKCHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &supported_present_modes_count, supported_present_modes.data())); - auto min_image_count = (surface_capabilities.minImageCount <= virtual_frames_count) ? virtual_frames_count : surface_capabilities.minImageCount; - - VkSwapchainCreateInfoKHR create_info = { - .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, - .pNext = nullptr, - .flags = 0U, - .surface = surface, - .minImageCount = min_image_count, - .imageFormat = supported_formats[0].format, - .imageColorSpace = supported_formats[0].colorSpace, - .imageExtent = extent, - .imageArrayLayers = 1U, - .imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT, - .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, - .queueFamilyIndexCount = 0U, - .pQueueFamilyIndices = nullptr, - .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, - .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, - .presentMode = supported_present_modes[0], - .clipped = VK_TRUE, - .oldSwapchain = nullptr, + auto min_image_count = (surface_capabilities.minImageCount <= virtual_frames_count) ? virtual_frames_count : surface_capabilities.minImageCount; + + VkSwapchainCreateInfoKHR create_info = { + .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, + .pNext = nullptr, + .flags = 0U, + .surface = surface, + .minImageCount = min_image_count, + .imageFormat = supported_formats[0].format, + .imageColorSpace = supported_formats[0].colorSpace, + .imageExtent = extent, + .imageArrayLayers = 1U, + .imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT, + .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 0U, + .pQueueFamilyIndices = nullptr, + .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, + .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + .presentMode = supported_present_modes[0], + .clipped = VK_TRUE, + .oldSwapchain = nullptr, }; VKCHECK(vkCreateSwapchainKHR(device, &create_info, nullptr, &swapchain)); } void vkdevice::create_virtual_frames() { - for (auto index { 0U }; index < virtual_frames_count; index++) { + for (auto index{ 0U }; index < virtual_frames_count; index++) { { - VkSemaphoreTypeCreateInfo semaphore_type_create_info { - .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, - .pNext = nullptr, - .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, - .initialValue = 0U, + VkSemaphoreTypeCreateInfo semaphore_type_create_info{ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, + .pNext = nullptr, + .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, + .initialValue = 0U, }; - VkSemaphoreCreateInfo create_info { + VkSemaphoreCreateInfo create_info{ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, .pNext = &semaphore_type_create_info, .flags = 0U, @@ -661,7 +764,7 @@ void vkdevice::create_virtual_frames() { // ----------------- vkadapter ----------------- void vkdevice::create_instance() { - VkApplicationInfo app_info { + VkApplicationInfo app_info{ .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pApplicationName = "path-tracer", .applicationVersion = VK_MAKE_VERSION(1, 0, 0), @@ -670,17 +773,17 @@ void vkdevice::create_instance() { .apiVersion = VK_API_VERSION_1_3, }; - constexpr const char* instance_layers[] { + constexpr const char* instance_layers[]{ "VK_LAYER_KHRONOS_validation", }; - constexpr const char* instance_extensions[] { + constexpr const char* instance_extensions[]{ VK_EXT_DEBUG_UTILS_EXTENSION_NAME, "VK_KHR_surface", "VK_KHR_win32_surface" }; - VkInstanceCreateInfo create_info { + VkInstanceCreateInfo create_info{ .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .pNext = nullptr, .flags = 0U, @@ -703,28 +806,28 @@ void vkdevice::create_device() { VkDeviceQueueCreateInfo queue_create_infos[static_cast(QueueType::MAX)]; for (auto& queue_create_info : queue_create_infos) { - queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_create_info.pNext = nullptr; - queue_create_info.flags = 0U; - queue_create_info.queueCount = 1; - queue_create_info.pQueuePriorities = &queue_priority; + queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_create_info.pNext = nullptr; + queue_create_info.flags = 0U; + queue_create_info.queueCount = 1; + queue_create_info.pQueuePriorities = &queue_priority; } auto queue_properties_count = 0U; vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_properties_count, nullptr); - std::vector queue_properties { queue_properties_count }; + std::vector queue_properties{ queue_properties_count }; vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_properties_count, queue_properties.data()); for (auto index{ 0U }; index < static_cast(QueueType::MAX); index++) { - auto& queue = queues[index]; + auto& queue = queues[index]; - for (auto properties_index { 0U }; properties_index < queue_properties_count; properties_index++) { + for (auto properties_index{ 0U }; properties_index < queue_properties_count; properties_index++) { auto& queue_property = queue_properties[properties_index]; if ((queue_property.queueFlags & queue.usages) == queue.usages) { queue_create_infos[index].queueFamilyIndex = queue.index = properties_index; - queue_property.queueFlags = 0U; + queue_property.queueFlags = 0U; } } } @@ -734,7 +837,7 @@ void vkdevice::create_device() { // VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME }; - VkPhysicalDeviceVulkan12Features physical_device_12_features { + VkPhysicalDeviceVulkan12Features physical_device_12_features{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, .pNext = nullptr, .shaderSampledImageArrayNonUniformIndexing = VK_TRUE, @@ -746,14 +849,14 @@ void vkdevice::create_device() { .bufferDeviceAddress = VK_TRUE, }; - VkPhysicalDeviceVulkan13Features physical_device_13_features { + VkPhysicalDeviceVulkan13Features physical_device_13_features{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES, .pNext = &physical_device_12_features, .synchronization2 = VK_TRUE, .dynamicRendering = VK_TRUE, }; - VkDeviceCreateInfo create_info { + VkDeviceCreateInfo create_info{ .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .pNext = &physical_device_13_features, .flags = 0U, @@ -778,22 +881,22 @@ void vkdevice::create_device() { } void vkdevice::create_memory_allocator() { - VmaAllocatorCreateInfo create_info { - .flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT, - .physicalDevice = physical_device, - .device = device, - .instance = instance, - .vulkanApiVersion = VK_API_VERSION_1_2, + VmaAllocatorCreateInfo create_info{ + .flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT, + .physicalDevice = physical_device, + .device = device, + .instance = instance, + .vulkanApiVersion = VK_API_VERSION_1_2, }; VKCHECK(vmaCreateAllocator(&create_info, &gpu_allocator)); } void vkdevice::create_command_pools() { - VkCommandPoolCreateInfo create_info { + VkCommandPoolCreateInfo create_info{ .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, .pNext = nullptr, - .flags = 0U, + .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, }; for (auto& queue : queues) { @@ -809,7 +912,7 @@ void vkdevice::pick_physical_device() { assert(physical_devices_count > 0); - std::vector physical_devices { physical_devices_count }; + std::vector physical_devices{ physical_devices_count }; vkEnumeratePhysicalDevices(instance, &physical_devices_count, physical_devices.data()); for (auto& physical_dev : physical_devices) { @@ -825,11 +928,11 @@ void vkdevice::pick_physical_device() { bool vkdevice::device_support_features(VkPhysicalDevice physical_dev) { // Vulkan 1.2 physical device features support { - VkPhysicalDeviceVulkan12Features vulkan_12_features { + VkPhysicalDeviceVulkan12Features vulkan_12_features{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, }; - VkPhysicalDeviceFeatures2 physical_device_features { + VkPhysicalDeviceFeatures2 physical_device_features{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, .pNext = &vulkan_12_features, }; @@ -851,11 +954,11 @@ bool vkdevice::device_support_features(VkPhysicalDevice physical_dev) { // Vulkan 1.3 physical device features support { - VkPhysicalDeviceVulkan13Features vulkan_13_features { + VkPhysicalDeviceVulkan13Features vulkan_13_features{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES, }; - VkPhysicalDeviceFeatures2 physical_device_features { + VkPhysicalDeviceFeatures2 physical_device_features{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, .pNext = &vulkan_13_features, }; @@ -872,15 +975,15 @@ bool vkdevice::device_support_features(VkPhysicalDevice physical_dev) { } void vkdevice::create_debug_layer_callback() { - VkDebugUtilsMessengerCreateInfoEXT create_info { + VkDebugUtilsMessengerCreateInfoEXT create_info{ .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, .pNext = nullptr, .flags = 0U, .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, - .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT, + .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT, .pfnUserCallback = debug_callback, .pUserData = nullptr, }; -- cgit v1.3