diff options
Diffstat (limited to 'api-test')
| -rw-r--r-- | api-test/CMakeLists.txt | 10 | ||||
| -rw-r--r-- | api-test/command-buffer.cpp | 68 | ||||
| -rw-r--r-- | api-test/main.cpp | 238 | ||||
| -rw-r--r-- | api-test/vk-bindless.cpp | 201 | ||||
| -rw-r--r-- | api-test/vk-device.cpp | 605 |
5 files changed, 753 insertions, 369 deletions
diff --git a/api-test/CMakeLists.txt b/api-test/CMakeLists.txt index dc92ee3..b41c325 100644 --- a/api-test/CMakeLists.txt +++ b/api-test/CMakeLists.txt @@ -8,12 +8,18 @@ add_executable( ${CMAKE_SOURCE_DIR}/src/window.cpp ${CMAKE_SOURCE_DIR}/src/utils.cpp ${CMAKE_SOURCE_DIR}/src/vulkan-loader.cpp + ${CMAKE_SOURCE_DIR}/src/gltf.cpp + ${CMAKE_SOURCE_DIR}/src/vec3.cpp + ${CMAKE_SOURCE_DIR}/src/mesh.cpp + ${CMAKE_SOURCE_DIR}/src/scene.cpp + ${CMAKE_SOURCE_DIR}/src/camera.cpp + ${CMAKE_SOURCE_DIR}/src/bvh.cpp ) -target_compile_definitions(api-test PUBLIC WINDOWS VK_NO_PROTOTYPES VK_USE_PLATFORM_WIN32_KHR) +target_compile_definitions(api-test PUBLIC WINDOWS VK_NO_PROTOTYPES VK_USE_PLATFORM_WIN32_KHR API_TEST NOMINMAX) target_compile_options(api-test - PRIVATE -Wall -Wextra + PRIVATE -Wall -Wextra -msse4.1 ) target_include_directories(api-test SYSTEM PUBLIC ${Vulkan_INCLUDE_DIRS}) diff --git a/api-test/command-buffer.cpp b/api-test/command-buffer.cpp index 79b8aef..d694f9f 100644 --- a/api-test/command-buffer.cpp +++ b/api-test/command-buffer.cpp @@ -1,6 +1,5 @@ #include "command-buffer.hpp" -#include <cassert> #include <vulkan/vulkan_core.h> #include "vulkan-loader.hpp" @@ -20,11 +19,18 @@ void command_buffer::start() const { const auto& bindless = vkdevice::get_render_device().get_bindingmodel(); const auto* global_set = &bindless.sets[BindlessSetType::GLOBAL]; + // const auto global_uniforms = bindless.get_globals_uniform_buffer(); + // if (queue_type == QueueType::GRAPHICS) { + // vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bindless.graphics_layout, 0, 1U, global_set, 1U, &global_uniforms.offset); + // vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.compute_layout, 0, 1U, global_set, 1U, &global_uniforms.offset); + // } else if (queue_type == QueueType::ASYNC_COMPUTE) { + // vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.compute_layout, 0, 1U, global_set, 1U, &global_uniforms.offset); + // } if (queue_type == QueueType::GRAPHICS) { - vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bindless.layout, 0, 1U, global_set, 0U, nullptr); - vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.layout, 0, 1U, global_set, 0U, nullptr); + vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bindless.graphics_layout, 0, 1U, global_set, 0U, nullptr); + vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.compute_layout, 0, 1U, global_set, 0U, nullptr); } else if (queue_type == QueueType::ASYNC_COMPUTE) { - vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.layout, 0, 1U, global_set, 0U, nullptr); + vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.compute_layout, 0, 1U, global_set, 0U, nullptr); } } @@ -107,12 +113,19 @@ void command_buffer::copy(handle<device_buffer> buffer_handle, ::handle<device_t void graphics_command_buffer::dispatch(const dispatch_params& params) const { const auto& pipeline = vkdevice::get_render_device().get_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<uint32_t>(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<uint32_t>(BindlessSetType::DRAWS_UNIFORMS), 1U, &bindless.sets[BindlessSetType::DRAWS_UNIFORMS], 1U, ¶ms.uniforms_offset); + // vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.compute_layout, static_cast<uint32_t>(BindlessSetType::INSTANCES_UNIFORMS), 1U, &bindless.sets[BindlessSetType::INSTANCES_UNIFORMS], 1U, ¶ms.uniforms_offset); + // vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.compute_layout, static_cast<uint32_t>(BindlessSetType::DRAWS_UNIFORMS), 1U, &bindless.sets[BindlessSetType::DRAWS_UNIFORMS], 1U, ¶ms.uniforms_offset); + + for (uint32_t push_index = 0U; push_index < bindless_model::max_push_constants_slots; push_index++) { + vkCmdPushConstants(vk_command_buffer, bindless.compute_layout, VK_SHADER_STAGE_COMPUTE_BIT, push_index * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, ¶ms.params[push_index]); + } vkCmdBindPipeline(vk_command_buffer, pipeline.bind_point, pipeline.vk_pipeline); - vkCmdDispatch(vk_command_buffer, params.group_size.x / params.local_group_size.x, params.group_size.y / params.local_group_size.y, params.group_size.z / params.local_group_size.z); + auto x = params.group_size.vec.x / params.local_group_size.vec.x; + auto y = params.group_size.vec.y / params.local_group_size.vec.y; + auto z = params.group_size.vec.z / params.local_group_size.vec.z; + vkCmdDispatch(vk_command_buffer, x, y, z); } void graphics_command_buffer::begin_renderpass(const renderpass_params& params) const { @@ -172,24 +185,47 @@ void graphics_command_buffer::begin_renderpass(const renderpass_params& params) vkCmdSetScissor(vk_command_buffer, 0U, 1U, &scissor); vkCmdSetViewport(vk_command_buffer, 0U, 1U, &viewport); + + // auto& device = vkdevice::get_render_device(); + // const auto& bindless = device.get_bindingmodel(); + // vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.layout, static_cast<uint32_t>(BindlessSetType::GLOBAL), 1U, &bindless.sets[BindlessSetType::GLOBAL], 1U, ¶ms.uniforms_offset); + // vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bindless.layout, static_cast<uint32_t>(BindlessSetType::GLOBAL), 1U, &bindless.sets[BindlessSetType::GLOBAL], 1U, ¶ms.uniforms_offset); } -void graphics_command_buffer::render(const draw_params& params) const { +void graphics_command_buffer::draw(const draw_params& params) const { 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<uint32_t>(BindlessSetType::DRAWS_UNIFORMS), 1U, &bindless.sets[BindlessSetType::DRAWS_UNIFORMS], 1U, ¶ms.uniforms_offset); + // vkCmdBindDescriptorSets(vk_command_buffer, pipeline.bind_point, bindless.layout, static_cast<uint32_t>(BindlessSetType::DRAWS_UNIFORMS), 1U, &bindless.sets[BindlessSetType::DRAWS_UNIFORMS], 1U, ¶ms.uniforms_offset); vkCmdBindPipeline(vk_command_buffer, pipeline.bind_point, pipeline.vk_pipeline); - 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<int32_t>(params.vertex_offset), 0U); - } else { - vkCmdDraw(vk_command_buffer, params.vertex_count, params.instance_count, params.vertex_offset, 0U); - } + vkCmdPushConstants(vk_command_buffer, bindless.graphics_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, ConstantType::GLOBALS * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, ¶ms.globals_address); + vkCmdPushConstants(vk_command_buffer, bindless.graphics_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, ConstantType::INSTANCES * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, ¶ms.instances_address); + vkCmdPushConstants(vk_command_buffer, bindless.graphics_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, ConstantType::DRAWS * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, ¶ms.uniforms_address); + vkCmdPushConstants(vk_command_buffer, bindless.graphics_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, ConstantType::VERTEX_BUFFER * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, ¶ms.vertex_address); + + vkCmdDraw(vk_command_buffer, params.vertex_count, params.instance_count, params.vertex_offset, 0U); +} + +void graphics_command_buffer::draw_indexed(const draw_indexed_params& params) const { + 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<uint32_t>(BindlessSetType::DRAWS_UNIFORMS), 1U, &bindless.sets[BindlessSetType::DRAWS_UNIFORMS], 1U, ¶ms.uniforms_offset); + + vkCmdBindPipeline(vk_command_buffer, pipeline.bind_point, pipeline.vk_pipeline); + + vkCmdPushConstants(vk_command_buffer, bindless.graphics_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, ConstantType::GLOBALS * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, ¶ms.globals_address); + vkCmdPushConstants(vk_command_buffer, bindless.graphics_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, ConstantType::INSTANCES * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, ¶ms.instances_address); + vkCmdPushConstants(vk_command_buffer, bindless.graphics_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, ConstantType::DRAWS * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, ¶ms.uniforms_address); + vkCmdPushConstants(vk_command_buffer, bindless.graphics_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, ConstantType::VERTEX_BUFFER * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, ¶ms.vertex_address); + + 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<int32_t>(params.vertex_offset), 0U); } void graphics_command_buffer::end_renderpass() const { diff --git a/api-test/main.cpp b/api-test/main.cpp index 583bced..0761070 100644 --- a/api-test/main.cpp +++ b/api-test/main.cpp @@ -1,7 +1,6 @@ #include <cassert> #include <cstdio> #include <ratio> -#include <span> #include <array> #include <chrono> #include <vk_mem_alloc.h> @@ -22,6 +21,9 @@ struct device_texture; #define ENABLE_RENDERDOC #endif // _DEBUG +#include "camera.hpp" +#include "scene.hpp" + #ifdef ENABLE_RENDERDOC #include <renderdoc.h> @@ -93,9 +95,19 @@ int main() { io.DisplaySize.x = window_width; io.DisplaySize.y = window_height; + const float aspect_ratio = 16.0 / 9.0; + + point3 position { 13.f, 2.f, -3.f }; + point3 target {}; + const auto v_fov = 90.f; + const auto aperture = 0.1f; + const auto focus_distance = 10.f; + auto& device = vkdevice::get_render_device(); device.init(); + auto main_scene = scene(camera(position, target, v_fov, aspect_ratio, aperture, focus_distance), window_width, window_height); + auto surface_handle = device.create_surface({ .window_handle = wnd.handle, .surface_format = { @@ -103,7 +115,7 @@ int main() { .colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, }, .present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR, - .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT, }); auto& surface = device.get_surface(surface_handle); @@ -190,38 +202,47 @@ int main() { auto index_buffer = device.get_buffer(index_buffer_handle); auto code = read_file("shaders/test.comp.spv"); - auto compute = device.create_pipeline({ + auto compute = device.create_compute_pipeline({ .cs_code = code, }); + auto rt_code = read_file("shaders/compute.comp.spv"); + auto raytracing = device.create_compute_pipeline({ + .cs_code = rt_code, + }); + auto tonemapping_code = read_file("shaders/tonemapping.comp.spv"); + auto tonemapping = device.create_compute_pipeline({ + .cs_code = tonemapping_code, + }); + const auto acc_handle = device.create_texture({ + .width = static_cast<uint32_t>(window_width), + .height = static_cast<uint32_t>(window_height), + .usages = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .type = VK_IMAGE_TYPE_2D, + }); + auto acc_storage_index = device.get_texture(acc_handle).get_storage_index(); + + const auto result_handle = device.create_texture({ + .width = static_cast<uint32_t>(window_width), + .height = static_cast<uint32_t>(window_height), + .usages = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .type = VK_IMAGE_TYPE_2D, + }); + auto result_storage_index = device.get_texture(result_handle).get_storage_index(); + std::array<VkFormat, 1U> formats { surface.surface_format.format }; 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({ + auto graphics = device.create_graphics_pipeline({ .vs_code = vertex_code, .fs_code = fragment_code, .color_attachments_format = formats }); - auto semaphore = device.create_semaphore({ - .type = VK_SEMAPHORE_TYPE_TIMELINE, - }); - constexpr uint32_t virtual_frames_count = 2U; - handle<device_semaphore> submit_semaphores[virtual_frames_count]; - for (auto& submit_semaphore : submit_semaphores) { - submit_semaphore = device.create_semaphore({ - .type = VK_SEMAPHORE_TYPE_BINARY, - }); - } - handle<device_semaphore> acquire_semaphores[virtual_frames_count]; - for (auto& acquire_semaphore : acquire_semaphores) { - acquire_semaphore = device.create_semaphore({ - .type = VK_SEMAPHORE_TYPE_BINARY, - }); - } - std::array<graphics_command_buffer, 4U> graphics_command_buffers; - device.allocate_command_buffers(graphics_command_buffers, QueueType::GRAPHICS); + device.allocate_command_buffers(graphics_command_buffers.data(), graphics_command_buffers.size(), QueueType::GRAPHICS); RD_START_CAPTURE; @@ -237,47 +258,38 @@ int main() { graphics_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); graphics_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; - uint32_t input2; - uint32_t output; - }; - const auto& uniform_buffer = device.get_bindingmodel().get_uniform_buffer(); - compute_params params { - device.get_texture(second_texture).get_storage_index(), - device.get_texture(gpu_texture_handle).get_storage_index(), - device.get_texture(output_texture_handle).get_storage_index(), - }; - memcpy(uniform_buffer.mapped_ptr, ¶ms, sizeof(params)); - - graphics_command_buffers[0].dispatch({ - .pipeline = compute, - .group_size = { .vec = { image_size, image_size, 1U }}, - .local_group_size = { .vec = { 8U, 8U, 1U }}, - .uniforms_offset = 0U, - }); + { + graphics_command_buffers[0].dispatch({ + .pipeline = compute, + .group_size = { .vec = { image_size, image_size, 1U }}, + .local_group_size = { .vec = { 8U, 8U, 1U }}, + .params = { + device.get_texture(second_texture).get_storage_index(), // Input 1 + device.get_texture(gpu_texture_handle).get_storage_index(), // Input 2 + device.get_texture(output_texture_handle).get_storage_index(), // Output + }, + }); + } graphics_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); graphics_command_buffers[0].stop(); - device.submit(std::span { static_cast<command_buffer*>(graphics_command_buffers.data()), 1 }, {}, semaphore); + device.submit(graphics_command_buffers.data(), 1); + device.wait(); RD_END_CAPTURE; - // std::array<struct command_buffer, 1U> ui_command_buffers = {command_buffers[1]}; std::array<handle<device_texture>, 1U> color_attachment {}; - uint32_t frame_time; + constexpr uint32_t virtual_frames_count = 2U; + uint32_t frame_time = 1U; uint32_t frame_count = 0U; while(wnd.isOpen) { auto start = std::chrono::system_clock::now(); wnd.poll_events(); uint32_t virtual_frame_index = frame_count % virtual_frames_count; - auto& submit_semaphore = submit_semaphores[virtual_frame_index]; - auto& acquire_semaphore = acquire_semaphores[virtual_frame_index]; - auto command_buffers = std::span<struct command_buffer> { static_cast<struct command_buffer*>(graphics_command_buffers.data() + virtual_frame_index + 1U), 1 }; - graphics_command_buffer& command_buffer = graphics_command_buffers[virtual_frame_index + 1U]; + auto command_buffer = graphics_command_buffers[2U + virtual_frame_index]; for (auto& event : wnd.events) { if (event.type == EVENT_TYPES::MOUSE_MOVE) { io.MousePos.x = static_cast<float>(event.x); @@ -292,16 +304,71 @@ int main() { auto* draw_data = ImGui::GetDrawData(); update_buffers(draw_data, vertex_buffer, index_buffer); - // device.wait(semaphore); - device.wait(submit_semaphore); + const auto& scene_buffer = device.get_buffer(main_scene.scene_buffer_handle); + main_scene.meta.sample_index = frame_count; + uint8_t* ptr = static_cast<uint8_t*>(scene_buffer.mapped_ptr); + memcpy(static_cast<void*>(ptr), &main_scene.meta, sizeof(main_scene.meta)); + memcpy(static_cast<void*>(ptr + sizeof(main_scene.meta)), &main_scene.meta, sizeof(main_scene.meta)); + memcpy(static_cast<void*>(ptr + sizeof(main_scene.meta) * 2U), &main_scene.meta, sizeof(main_scene.meta)); - surface.acquire_image_index(acquire_semaphore); - color_attachment[0] = surface.get_backbuffer_image(); + // TODO: Refactor backbuffer acquisition + auto backbuffer = surface.swapchain_images[device.acquire_image_index(surface_handle)]; + color_attachment[0] = backbuffer; RD_START_CAPTURE; - command_buffer.start(), + command_buffer.start(); + + command_buffer.barrier(backbuffer, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL); + + { + uint64_t textures = (virtual_frame_index == 0U) ? ((uint64_t(acc_storage_index) << 32U) | result_storage_index) : ((uint64_t(result_storage_index) << 32U) | acc_storage_index); + + if (virtual_frame_index == 0) { + command_buffer.barrier(result_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL); + command_buffer.barrier(acc_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL); + } else { + command_buffer.barrier(result_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL); + command_buffer.barrier(acc_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL); + } + + command_buffer.dispatch({ + .pipeline = raytracing, + .group_size = { .vec { window_width, window_height, 1U, } }, + .local_group_size = { .vec { 8U, 8U, 1U, } }, + .params = { + main_scene.scene_buffer_address(), + main_scene.bvh_buffer_address(), + main_scene.indices_buffer_address(), + main_scene.positions_buffer_address(), + main_scene.normals_buffer_address(), + main_scene.uvs_buffer_address(), + main_scene.materials_buffer_address(), + textures, + }, + }); + + // TODO: Refactor backbuffer acquisition + auto backbuffer_storage_index = device.get_texture(backbuffer).get_storage_index(); + uint64_t out = (virtual_frame_index == 0U) ? ((uint64_t(result_storage_index) << 32U) | backbuffer_storage_index) : ((uint64_t(acc_storage_index) << 32U) | backbuffer_storage_index); + command_buffer.dispatch({ + .pipeline = tonemapping, + .group_size = { .vec { window_width, window_height, 1U, } }, + .local_group_size = { .vec { 8U, 8U, 1U, } }, + .params = { + main_scene.scene_buffer_address(), + main_scene.bvh_buffer_address(), + main_scene.indices_buffer_address(), + main_scene.positions_buffer_address(), + main_scene.normals_buffer_address(), + main_scene.uvs_buffer_address(), + main_scene.materials_buffer_address(), + out, + }, + }); + } + + command_buffer.barrier(backbuffer, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - command_buffer.barrier(surface.get_backbuffer_image(), VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, VK_ACCESS_2_NONE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); command_buffer.begin_renderpass({ .render_area = { .x = static_cast<int32_t>(draw_data->DisplayPos.x), @@ -312,21 +379,20 @@ int main() { .color_attachments = color_attachment, }); - struct draw_params { - uintptr_t vertex_buffer; - float scale[2U]; - float translate[2U]; - uint32_t texture_index; - }; - - uint32_t draw_index = 0U; - std::array<draw_params, 100U> draws; + auto& draws_uniform_buffer = device.get_bindingmodel().get_draws_uniform_buffer(); for (auto index {0} ; 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, + auto offset = draws_uniform_buffer.offset; + { + struct ui_params { + // uintptr_t vertex_buffer; + float scale[2U]; + float translate[2U]; + uint32_t texture_index; + }; + auto* ui_param = draws_uniform_buffer.allocate<ui_params>(); + *ui_param = ui_params{ + // .vertex_buffer = vertex_buffer.device_address, .scale { 2.f / draw_data->DisplaySize.x, 2.f / draw_data->DisplaySize.y, @@ -337,60 +403,52 @@ int main() { }, .texture_index = ui_texture.get_sampled_index(), }; + } - command_buffer.render({ + for (auto& draw_command : cmd_list->CmdBuffer) { + command_buffer.draw_indexed({ .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, + .uniforms_address = draws_uniform_buffer.device_address + offset, + .vertex_address = vertex_buffer.device_address, }); - - draw_index++; } } - memcpy(uniform_buffer.mapped_ptr, draws.data(), sizeof(draw_params) * draw_index); - command_buffer.end_renderpass(); - command_buffer.barrier(surface.get_backbuffer_image(), VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + command_buffer.barrier(backbuffer, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); command_buffer.stop(); - // device.submit(command_buffers, acquire_semaphore, semaphore); - // device.wait(semaphore); - // device.present(surface_handle, {}); - - device.submit(command_buffers, acquire_semaphore, submit_semaphore); - device.present(surface_handle, submit_semaphore); + device.submit_before_present(surface_handle, &command_buffer, 1U); + device.present(surface_handle); + device.wait(); auto end = std::chrono::system_clock::now(); frame_time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count(); + frame_count++; RD_END_CAPTURE; } - device.wait(semaphore); - + device.wait(); device.destroy_surface(surface_handle); device.destroy_pipeline(compute); device.destroy_pipeline(graphics); - - device.destroy_semaphore(semaphore); - for (auto& submit_semaphore : submit_semaphores) { - device.destroy_semaphore(submit_semaphore); - } - for (auto& acquire_semaphore : acquire_semaphores) { - device.destroy_semaphore(acquire_semaphore); - } + device.destroy_pipeline(raytracing); + device.destroy_pipeline(tonemapping); device.destroy_texture(gpu_texture_handle); device.destroy_texture(second_texture); device.destroy_texture(output_texture_handle); device.destroy_texture(ui_texture_handle); + device.destroy_texture(acc_handle); + device.destroy_texture(result_handle); device.destroy_buffer(staging_buffer_handle); device.destroy_buffer(vertex_buffer_handle); diff --git a/api-test/vk-bindless.cpp b/api-test/vk-bindless.cpp index 66fd59c..d3d6415 100644 --- a/api-test/vk-bindless.cpp +++ b/api-test/vk-bindless.cpp @@ -1,12 +1,18 @@ #include "vk-bindless.hpp" #include <vk_mem_alloc.h> +#include <vulkan/vulkan_core.h> #include "vk-device.hpp" #include "vk-utils.hpp" #include "vulkan-loader.hpp" -const device_buffer& bindless_model::get_uniform_buffer() const { +device_buffer& bindless_model::get_globals_uniform_buffer() const { + auto& render_device = vkdevice::get_render_device(); + return render_device.get_buffer(globals_uniform_buffer_handle); +} + +device_buffer& bindless_model::get_draws_uniform_buffer() const { auto& render_device = vkdevice::get_render_device(); return render_device.get_buffer(draws_uniform_buffer_handle); } @@ -21,67 +27,96 @@ bindless_model bindless_model::create_bindless_model() { bindless.create_descriptor_pool(device); bindless.allocate_sets(device); - VkWriteDescriptorSet writes_descriptor_set[2U]; + // VkWriteDescriptorSet writes_descriptor_set[BindlessSetType::MAX]; - { - bindless.instances_uniform_buffer_handle = render_device.create_buffer({ - .size = instances_uniform_buffer_size, + // { + bindless.globals_uniform_buffer_handle = render_device.create_buffer({ + .size = globals_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, - }; + // const auto& buffer = render_device.get_buffer(bindless.globals_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, - }; - } + // writes_descriptor_set[BindlessSetType::GLOBAL] = { + // .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + // .pNext = nullptr, + // .dstSet = bindless.sets[BindlessSetType::GLOBAL], + // .dstBinding = 3U, + // .dstArrayElement = 0U, + // .descriptorCount = 1U, + // .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + // .pImageInfo = nullptr, + // .pBufferInfo = &buffer_info, + // .pTexelBufferView = nullptr, + // }; + // } - { + // { + // 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[BindlessSetType::INSTANCES_UNIFORMS] = { + // .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, + .usages = VK_BUFFER_USAGE_UNIFORM_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, }); - 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, - }; + // const auto& buffer = render_device.get_buffer(bindless.draws_uniform_buffer_handle); + // VkDescriptorBufferInfo buffer_info { + // .buffer = buffer.vk_buffer, + // .offset = 0U, + // .range = draws_uniform_buffer_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, - }; - } + // writes_descriptor_set[BindlessSetType::DRAWS_UNIFORMS] = { + // .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, sizeof(writes_descriptor_set) / sizeof(VkWriteDescriptorSet), writes_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, @@ -126,11 +161,12 @@ void bindless_model::destroy_bindless_model(bindless_model& bindless) { vkDestroyDescriptorSetLayout(device, bindless.sets_layout[index], nullptr); } - vkDestroyPipelineLayout(device, bindless.layout, nullptr); + vkDestroyPipelineLayout(device, bindless.graphics_layout, nullptr); + vkDestroyPipelineLayout(device, bindless.compute_layout, nullptr); bindless.destroy_immutable_samplers(device); - render_device.destroy_buffer(bindless.instances_uniform_buffer_handle); + // render_device.destroy_buffer(bindless.instances_uniform_buffer_handle); render_device.destroy_buffer(bindless.draws_uniform_buffer_handle); } @@ -139,6 +175,7 @@ void bindless_model::create_layout(VkDevice device) { // Binding 0 Storage images // Binding 1 Sampled images // Binding 2 Samplers + // Binding 3 Dynamic Uniform Buffer { VkDescriptorSetLayoutBinding set_layout_bindings[]{ { @@ -162,12 +199,21 @@ void bindless_model::create_layout(VkDevice device) { .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, .pImmutableSamplers = nullptr, }, + // { + // .binding = 3U, + // .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + // .descriptorCount = 1U, + // .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, + // .pImmutableSamplers = nullptr, + // }, }; VkDescriptorBindingFlags flags[]{ VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT, VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT, VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT, + // VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT, + // 0U, }; VkDescriptorSetLayoutBindingFlagsCreateInfo layout_binding_flags{ @@ -195,7 +241,7 @@ void bindless_model::create_layout(VkDevice device) { { .binding = 0U, .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, - .descriptorCount = 1, + .descriptorCount = 1U, .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, .pImmutableSamplers = nullptr, }, @@ -236,17 +282,50 @@ void bindless_model::create_layout(VkDevice device) { VKCHECK(vkCreateDescriptorSetLayout(device, &create_info, nullptr, &sets_layout[BindlessSetType::DRAWS_UNIFORMS])); } - VkPipelineLayoutCreateInfo create_info{ - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .pNext = nullptr, - .flags = 0U, - .setLayoutCount = sizeof(sets_layout) / sizeof(VkDescriptorSetLayout), - .pSetLayouts = sets_layout, - .pushConstantRangeCount = 0U, - .pPushConstantRanges = nullptr, - }; + { + VkPushConstantRange push_constants[] { + { + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, + .offset = 0U, + .size = max_push_constants_slots_size * (max_push_constants_slots), + }, + }; + + VkPipelineLayoutCreateInfo create_info{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, + .setLayoutCount = sizeof(sets_layout) / sizeof(VkDescriptorSetLayout), + .pSetLayouts = sets_layout, + .pushConstantRangeCount = sizeof(push_constants) / sizeof(push_constants[0]), + .pPushConstantRanges = push_constants, + }; - VKCHECK(vkCreatePipelineLayout(device, &create_info, nullptr, &layout)); + VKCHECK(vkCreatePipelineLayout(device, &create_info, nullptr, &graphics_layout)); + } + + { + VkPushConstantRange push_constants[] { + { + .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, + .offset = 0U, + .size = max_push_constants_slots_size * max_push_constants_slots, + }, + }; + + + VkPipelineLayoutCreateInfo create_info{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, + .setLayoutCount = sizeof(sets_layout) / sizeof(VkDescriptorSetLayout), + .pSetLayouts = sets_layout, + .pushConstantRangeCount = sizeof(push_constants) / sizeof(push_constants[0]), + .pPushConstantRanges = push_constants, + }; + + VKCHECK(vkCreatePipelineLayout(device, &create_info, nullptr, &compute_layout)); + } } #ifndef USE_VK_DESCRIPTOR_BUFFER @@ -266,7 +345,7 @@ void bindless_model::create_descriptor_pool(VkDevice device) { }, { .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, - .descriptorCount = set_descriptors_count, + .descriptorCount = 8U, }, }; @@ -307,7 +386,7 @@ void bindless_model::create_immutable_samplers(VkDevice device) { .mipLodBias = 0.f, .anisotropyEnable = VK_FALSE, .compareEnable = VK_FALSE, - .compareOp = VK_COMPARE_OP_ALWAYS, + .compareOp = VK_COMPARE_OP_NEVER, .minLod = 0.f, .maxLod = 0.f, .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, diff --git a/api-test/vk-device.cpp b/api-test/vk-device.cpp index 2b9f7eb..e1d671f 100644 --- a/api-test/vk-device.cpp +++ b/api-test/vk-device.cpp @@ -37,6 +37,11 @@ void vkdevice::init() { create_memory_allocator(); bindless = bindless_model::create_bindless_model(); + + auto semaphore = create_semaphore({ + .type = VK_SEMAPHORE_TYPE_TIMELINE, + }); + timeline_semaphore = get_semaphore(semaphore); } vkdevice::~vkdevice() { @@ -50,6 +55,8 @@ vkdevice::~vkdevice() { vkDestroyCommandPool(device, queue.command_pool, nullptr); } + vkDestroySemaphore(device, timeline_semaphore.vk_semaphore, nullptr); + vkDestroyDevice(device, nullptr); #ifdef _DEBUG @@ -59,6 +66,8 @@ vkdevice::~vkdevice() { vkDestroyInstance(instance, nullptr); } +void vkdevice::wait() { vkDeviceWaitIdle(device); }; + handle<device_texture> vkdevice::create_texture(const texture_desc& desc) { device_texture device_texture; device_texture.init(desc); @@ -66,6 +75,13 @@ handle<device_texture> vkdevice::create_texture(const texture_desc& desc) { return textures.add(device_texture); } +handle<device_sampler> vkdevice::create_sampler(const sampler_desc& desc) { + device_sampler device_sampler; + device_sampler.init(desc); + + return samplers.add(device_sampler); +} + handle<device_buffer> vkdevice::create_buffer(const buffer_desc& desc) { device_buffer device_buffer{ .size = desc.size, @@ -113,172 +129,177 @@ handle<device_buffer> vkdevice::create_buffer(const buffer_desc& desc) { return buffers.add(device_buffer); } -handle<device_pipeline> vkdevice::create_pipeline(const pipeline_desc& desc) { +handle<device_pipeline> vkdevice::create_graphics_pipeline(const graphics_pipeline_desc& desc) { device_pipeline device_pipeline{ }; - if (!desc.cs_code.empty()) { - VkPipelineShaderStageCreateInfo stage_create_info{ + + VkPipelineShaderStageCreateInfo shader_stages_create_info[2U]{ { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .pNext = nullptr, .flags = 0U, - .stage = VK_SHADER_STAGE_COMPUTE_BIT, - .module = create_shader_module(desc.cs_code), + .stage = VK_SHADER_STAGE_VERTEX_BIT, + .module = create_shader_module(desc.vs_code), .pName = "main", .pSpecializationInfo = nullptr, - }; + }, + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, + .stage = VK_SHADER_STAGE_FRAGMENT_BIT, + .module = create_shader_module(desc.fs_code), + .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, - .basePipelineHandle = nullptr, - .basePipelineIndex = 0, - }; + VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + }; - device_pipeline.bind_point = VK_PIPELINE_BIND_POINT_COMPUTE; - VKCHECK(vkCreateComputePipelines(device, nullptr, 1U, &create_info, nullptr, &device_pipeline.vk_pipeline)); + 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, + }; - vkDestroyShaderModule(device, stage_create_info.module, nullptr); - } else { - 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, - .module = create_shader_module(desc.vs_code), - .pName = "main", - .pSpecializationInfo = nullptr, - }, - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .pNext = nullptr, - .flags = 0U, - .stage = VK_SHADER_STAGE_FRAGMENT_BIT, - .module = create_shader_module(desc.fs_code), - .pName = "main", - .pSpecializationInfo = nullptr, - }, - }; + 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, + }; - VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info{ - .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - }; + 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, + }; - 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, - }; + 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, + }; - 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, - }; + 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, + .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, + }; - 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, - }; + 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, + }; - 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, - }; + VkDynamicState dynamic_states[]{ + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + }; - 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, - .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, - }; + 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, + }; - 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, - }; + VkPipelineRenderingCreateInfo pipeline_rendering_create_info{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, + .pNext = nullptr, + .viewMask = 0U, + .colorAttachmentCount = static_cast<uint32_t>(desc.color_attachments_format.size()), + .pColorAttachmentFormats = desc.color_attachments_format.data(), + .depthAttachmentFormat = VK_FORMAT_UNDEFINED, + .stencilAttachmentFormat = VK_FORMAT_UNDEFINED, + }; - VkDynamicState dynamic_states[]{ - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - }; + 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, + .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.graphics_layout, + .renderPass = nullptr, + .subpass = 0U, + .basePipelineHandle = nullptr, + .basePipelineIndex = 0, + }; - 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, - }; + device_pipeline.bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS; + VKCHECK(vkCreateGraphicsPipelines(device, nullptr, 1U, &create_info, nullptr, &device_pipeline.vk_pipeline)); - VkPipelineRenderingCreateInfo pipeline_rendering_create_info{ - .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, - .pNext = nullptr, - .viewMask = 0U, - .colorAttachmentCount = static_cast<uint32_t>(desc.color_attachments_format.size()), - .pColorAttachmentFormats = desc.color_attachments_format.data(), - .depthAttachmentFormat = VK_FORMAT_UNDEFINED, - .stencilAttachmentFormat = VK_FORMAT_UNDEFINED, - }; + for(auto& stage_create_info : shader_stages_create_info) { + vkDestroyShaderModule(device, stage_create_info.module, nullptr); + } - 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, - .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, - }; + return pipelines.add(device_pipeline); +} - device_pipeline.bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS; - VKCHECK(vkCreateGraphicsPipelines(device, nullptr, 1U, &create_info, nullptr, &device_pipeline.vk_pipeline)); +handle<device_pipeline> vkdevice::create_compute_pipeline(const compute_pipeline_desc& desc) { + device_pipeline device_pipeline{ + }; - for(auto& stage_create_info : shader_stages_create_info) { - vkDestroyShaderModule(device, stage_create_info.module, nullptr); - } - } + VkPipelineShaderStageCreateInfo stage_create_info{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, + .stage = VK_SHADER_STAGE_COMPUTE_BIT, + .module = create_shader_module(desc.cs_code), + .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.compute_layout, + .basePipelineHandle = nullptr, + .basePipelineIndex = 0, + }; + + device_pipeline.bind_point = VK_PIPELINE_BIND_POINT_COMPUTE; + VKCHECK(vkCreateComputePipelines(device, nullptr, 1U, &create_info, nullptr, &device_pipeline.vk_pipeline)); + + vkDestroyShaderModule(device, stage_create_info.module, nullptr); return pipelines.add(device_pipeline); } @@ -301,6 +322,17 @@ handle<device_surface> vkdevice::create_surface(const surface_desc& desc) { create_swapchain(desc, device_surface); + assert(surface_desc::max_image_count >= device_surface.image_count); + + for (uint32_t index = 0u; index < device_surface.image_count; index++) { + device_surface.acquire_semaphores[index] = create_semaphore({ + .type = VK_SEMAPHORE_TYPE_BINARY, + }); + device_surface.submit_semaphores[index] = create_semaphore({ + .type = VK_SEMAPHORE_TYPE_BINARY, + }); + } + return surfaces.add(device_surface); } @@ -355,39 +387,107 @@ void vkdevice::destroy_semaphore(handle<device_semaphore> handle) { } void vkdevice::destroy_surface(handle<device_surface> handle) { - const auto& surface = vkdevice::get_surface(handle); + auto& surface = vkdevice::get_surface(handle); for (auto texture_index{0U}; texture_index < surface.image_count; texture_index++) { auto texture_handle = surface.swapchain_images[texture_index]; destroy_texture(texture_handle); } + for (uint32_t index = 0u; index < surface.image_count; index++) { + destroy_semaphore(surface.acquire_semaphores[index]); + destroy_semaphore(surface.submit_semaphores[index]); + } + vkDestroySwapchainKHR(device, surface.vk_swapchain, nullptr); vkDestroySurfaceKHR(instance, surface.vk_surface, nullptr); } -void vkdevice::wait(handle<device_semaphore> semaphore_handle) { - const auto& semaphore = vkdevice::get_render_device().get_semaphore(semaphore_handle); - 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)); - vkDeviceWaitIdle(device); -} +// uint64_t vkdevice::submit(std::span<command_buffer> buffers, handle<device_semaphore> wait_handle, handle<device_semaphore> signal_handle, handle<device_semaphore> fence_handle) { +// assert((max_submitable_command_buffers - buffers.size()) >= 0); +// const auto queue_type = buffers[0].queue_type; +// +// 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_infos[2U]; +// +// VkSubmitInfo2 submit_info{ +// .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2, +// .pNext = nullptr, +// .flags = 0U, +// .waitSemaphoreInfoCount = 0U, +// .commandBufferInfoCount = static_cast<uint32_t>(buffers.size()), +// .pCommandBufferInfos = command_buffers_info, +// .pSignalSemaphoreInfos = signal_semaphore_infos, +// }; +// +// if (wait_handle.is_valid()) { +// const auto& wait = vkdevice::get_render_device().get_semaphore(wait_handle); +// wait_semaphore_info.semaphore = wait.vk_semaphore; +// wait_semaphore_info.value = wait.value; +// submit_info.waitSemaphoreInfoCount++; +// submit_info.pWaitSemaphoreInfos = &wait_semaphore_info; +// } +// +// if (signal_handle.is_valid()) { +// auto& signal = vkdevice::get_render_device().get_semaphore(signal_handle); +// signal_semaphore_infos[0U] = { +// .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, +// .pNext = nullptr, +// .semaphore = signal.vk_semaphore, +// .value = signal.value, +// .stageMask = VK_PIPELINE_STAGE_2_NONE, +// .deviceIndex = 0U, +// }; +// submit_info.signalSemaphoreInfoCount++; +// } +// +// uint64_t ret = -1; +// +// if (fence_handle.is_valid()) { +// auto& fence = vkdevice::get_render_device().get_semaphore(fence_handle); +// auto fence_index = submit_info.signalSemaphoreInfoCount; +// signal_semaphore_infos[fence_index] = { +// .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, +// .pNext = nullptr, +// .semaphore = fence.vk_semaphore, +// .value = ++fence.value, +// .stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, +// .deviceIndex = 0U, +// }; +// ret = fence.value; +// } +// +// VKCHECK(vkQueueSubmit2(queues[static_cast<uint32_t>(queue_type)].vk_queue, 1, &submit_info, nullptr)); +// +// return ret; +// } -void vkdevice::submit(std::span<command_buffer> buffers, handle<device_semaphore> wait_handle, handle<device_semaphore> signal_handle) { - assert((max_submitable_command_buffers - buffers.size()) >= 0); +uint32_t vkdevice::submit(command_buffer* buffers, uint32_t count) { + assert((max_submitable_command_buffers - count) >= 0); const auto queue_type = buffers[0].queue_type; - VkCommandBufferSubmitInfo command_buffers_info[buffers.size()]; + VkCommandBufferSubmitInfo command_buffers_info[count]; - for (auto index{ 0U }; index < buffers.size(); index++) { + for (auto index{ 0U }; index < count; index++) { assert(queue_type == buffers[index].queue_type); auto& command_buffer_info = command_buffers_info[index]; @@ -397,50 +497,102 @@ void vkdevice::submit(std::span<command_buffer> buffers, handle<device_semaphore 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, + VkSubmitInfo2 submit_info{ + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2, + .pNext = nullptr, + .flags = 0U, + .waitSemaphoreInfoCount = 0U, + .pWaitSemaphoreInfos = nullptr, + .commandBufferInfoCount = count, + .pCommandBufferInfos = command_buffers_info, + }; + + auto& fence = timeline_semaphore; + VkSemaphoreSubmitInfo signal_semaphore_infos[] = { + { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, + .pNext = nullptr, + .semaphore = fence.vk_semaphore, + .value = ++fence.value, + .stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + .deviceIndex = 0U, + }, }; + submit_info.signalSemaphoreInfoCount = sizeof(signal_semaphore_infos) / sizeof(signal_semaphore_infos[0U]); + submit_info.pSignalSemaphoreInfos = signal_semaphore_infos; + + VKCHECK(vkQueueSubmit2(queues[static_cast<uint32_t>(queue_type)].vk_queue, 1, &submit_info, nullptr)); + + return fence.value; +} + +uint32_t vkdevice::submit_before_present(handle<device_surface> surface_handle, command_buffer* buffers, uint32_t count) { + assert((max_submitable_command_buffers - count) >= 0); + const auto queue_type = buffers[0].queue_type; + + VkCommandBufferSubmitInfo command_buffers_info[count]; + + for (auto index{ 0U }; index < count; index++) { + assert(queue_type == buffers[index].queue_type); - VkSemaphoreSubmitInfo signal_semaphore_info{ - .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, - .pNext = nullptr, - .stageMask = VK_PIPELINE_STAGE_2_NONE, - .deviceIndex = 0U, + 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; + } + + const auto& surface = get_surface(surface_handle); + auto& wait = get_semaphore(surface.acquire_semaphores[surface.frame_index]); + VkSemaphoreSubmitInfo wait_semaphore_info = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, + .pNext = nullptr, + .semaphore = wait.vk_semaphore, + .value = wait.value, + .stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + .deviceIndex = 0U, }; VkSubmitInfo2 submit_info{ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2, .pNext = nullptr, .flags = 0U, - .commandBufferInfoCount = static_cast<uint32_t>(buffers.size()), + .waitSemaphoreInfoCount = 1U, + .pWaitSemaphoreInfos = &wait_semaphore_info, + .commandBufferInfoCount = count, .pCommandBufferInfos = command_buffers_info, }; - if (wait_handle.is_valid()) { - const auto& wait = vkdevice::get_render_device().get_semaphore(wait_handle); - 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_handle.is_valid()) { - auto& signal = vkdevice::get_render_device().get_semaphore(signal_handle); - signal_semaphore_info.semaphore = signal.vk_semaphore; - signal_semaphore_info.value = ++signal.value; - - submit_info.signalSemaphoreInfoCount = 1U; - submit_info.pSignalSemaphoreInfos = &signal_semaphore_info; - } + auto& fence = timeline_semaphore; + auto& signal = get_semaphore(surface.submit_semaphores[surface.frame_index]); + VkSemaphoreSubmitInfo signal_semaphore_infos[] = { + { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, + .pNext = nullptr, + .semaphore = fence.vk_semaphore, + .value = ++fence.value, + .stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + .deviceIndex = 0U, + }, + { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, + .pNext = nullptr, + .semaphore = signal.vk_semaphore, + .value = signal.value, + .stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + .deviceIndex = 0U, + }, + }; + submit_info.signalSemaphoreInfoCount = sizeof(signal_semaphore_infos) / sizeof(signal_semaphore_infos[0U]); + submit_info.pSignalSemaphoreInfos = signal_semaphore_infos; VKCHECK(vkQueueSubmit2(queues[static_cast<uint32_t>(queue_type)].vk_queue, 1, &submit_info, nullptr)); + + return fence.value; } -void vkdevice::present(handle<device_surface> surface_handle, handle<device_semaphore> semaphore_handle) { - const auto& surface = vkdevice::get_render_device().get_surface(surface_handle); +void vkdevice::present(handle<device_surface> surface_handle) { + auto& surface = vkdevice::get_render_device().get_surface(surface_handle); VkResult result; VkPresentInfoKHR present_info{ .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, @@ -451,15 +603,14 @@ void vkdevice::present(handle<device_surface> surface_handle, handle<device_sema .pResults = &result, }; - if (semaphore_handle.is_valid()) { - const auto& semaphore = vkdevice::get_render_device().get_semaphore(semaphore_handle); - present_info.waitSemaphoreCount = 1U; - present_info.pWaitSemaphores = &semaphore.vk_semaphore; - } + const auto& semaphore = get_semaphore(surface.submit_semaphores[surface.frame_index]); + present_info.waitSemaphoreCount = 1U; + present_info.pWaitSemaphores = &semaphore.vk_semaphore; VKCHECK(vkQueuePresentKHR(queues[static_cast<uint32_t>(QueueType::GRAPHICS)].vk_queue, &present_info)); VKCHECK(result); + surface.frame_index = (surface.frame_index + 1) % surface.image_count; } // private @@ -847,6 +998,7 @@ void vkdevice::create_debug_layer_callback() { idlist<> device_texture::sampled_indices = {}; idlist<> device_texture::storage_indices = {}; +idlist<> device_sampler::sampler_indices = {}; void device_texture::init(const texture_desc& desc) { auto& render_device = vkdevice::get_render_device(); @@ -1009,14 +1161,67 @@ void device_texture::create_views() { } -void device_surface::acquire_image_index(handle<device_semaphore> signal_handle) { +void device_sampler::init(const sampler_desc& desc) { auto& render_device = vkdevice::get_render_device(); + // const auto& bindless = render_device.get_bindingmodel(); auto* device = render_device.get_device(); - const auto& signal = render_device.get_semaphore(signal_handle); - vkAcquireNextImageKHR(device, vk_swapchain, -1, signal.vk_semaphore, nullptr, &image_index); + VkSamplerCreateInfo sampler_create_info{ + .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, + .magFilter = desc.mag_filter, + .minFilter = desc.min_filter, + .mipmapMode = desc.mipmap_mode, + .addressModeU = desc.address_mode_u, + .addressModeV = desc.address_mode_v, + .addressModeW = desc.address_mode_w, + .mipLodBias = desc.mip_lod_bias, + .anisotropyEnable = desc.anisotropy, + .maxAnisotropy = desc.max_anisotropy, + .compareEnable = desc.compare_enabled, + .compareOp = desc.compare_op, + .minLod = desc.min_lod, + .maxLod = desc.max_lod, + .borderColor = desc.border_color, + .unnormalizedCoordinates = desc.unnomalized_coords, + }; + + VKCHECK(vkCreateSampler(device, &sampler_create_info, nullptr, &vk_sampler)); + + sampler_index = sampler_indices.add(); + + // VkWriteDescriptorSet write_descriptor_set{ + // .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + // .pNext = nullptr, + // .dstSet = bindless.sets[BindlessSetType::GLOBAL], + // .dstBinding = 1U, + // .dstArrayElement = sampler_index.id, + // .descriptorCount = 1U, + // .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + // .pImageInfo = images_info, + // .pBufferInfo = nullptr, + // .pTexelBufferView = nullptr, + // }); } -handle<device_texture> device_surface::get_backbuffer_image() const { - return swapchain_images[image_index]; + +uint32_t vkdevice::acquire_image_index(handle<device_surface> surface_handle) { + auto& render_device = vkdevice::get_render_device(); + auto* device = render_device.get_device(); + auto& surface = get_surface(surface_handle); + const auto& signal = get_semaphore(surface.acquire_semaphores[surface.frame_index]); + + VkSemaphoreWaitInfo wait_info { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, + .pNext = nullptr, + .flags = 0U, + .semaphoreCount = 1U, + .pSemaphores = &timeline_semaphore.vk_semaphore, + .pValues = &timeline_semaphore.value, + }; + vkWaitSemaphores(device, &wait_info, -1); + VKCHECK(vkAcquireNextImageKHR(device, surface.vk_swapchain, -1, signal.vk_semaphore, nullptr, &surface.image_index)); + + return surface.image_index; } |
