diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000000000000000000000000000000000..7e8c88a738406dd40cc4665a6eab907fa566f435 --- /dev/null +++ b/.clang-format @@ -0,0 +1,75 @@ +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +# AlignConsecutiveMacros: false +AlignEscapedNewlines: DontAlign +AlignOperands: true +AlignTrailingComments: false +# AllowAllArgumentsOnNextLine: false +# AllowAllConstructorInitializersOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +# AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +# AllowShortIfStatementsOnASingleLine: Always +# AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +# AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BinPackParameters: true +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +# BreakInheritanceList: BeforeColon +BreakStringLiterals: false +ColumnLimit: 0 +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 0 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +IncludeBlocks: Merge +IncludeCategories: + - Regex: '^<.*\.h>' + Priority: 1 + - Regex: '^<.*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IndentCaseLabels: false +# IndentGotoLabels: false +IndentPPDirectives: AfterHash +IndentWidth: 4 +IndentWrappedFunctionNames: true +KeepEmptyLinesAtTheStartOfBlocks: false +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: All +PointerAlignment: Left +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +# SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +# SpaceBeforeCpp11BracedList: true +# SpaceBeforeCtorInitializerColon: false +# SpaceBeforeInheritanceColon: false +SpaceBeforeParens: ControlStatements +# SpaceBeforeRangeBasedForLoopColon: true +# SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +# Standard: Latest +UseTab: Never diff --git a/DOCS.md b/DOCS.md index 6de27feda18a1b3237f5f0758087e395eed220bd..3ddc0ac65bb66f3308cbfc5fa8ffa6fda6eafdbf 100644 --- a/DOCS.md +++ b/DOCS.md @@ -36,7 +36,7 @@ Here are a few examples to get to know `lava` int main(int argc, char* argv[]) { lava::frame frame( {argc, argv} ); - + return frame.ready() ? 0 : error::not_ready; } ``` @@ -53,7 +53,6 @@ if (!frame.ready()) auto count = 0; frame.add_run([&]() { - sleep(seconds(1)); count++; @@ -87,7 +86,6 @@ lava::input input; window.assign(&input); input.key.listeners.add([&](key_event::ref event) { - if (event.pressed(key::escape)) return frame.shut_down(); @@ -95,7 +93,6 @@ input.key.listeners.add([&](key_event::ref event) { }); frame.add_run([&]() { - input.handle_events(); if (window.close_request()) @@ -124,7 +121,6 @@ lava::input input; window.assign(&input); input.key.listeners.add([&](key_event::ref event) { - if (event.pressed(key::escape)) return frame.shut_down(); @@ -149,30 +145,26 @@ VkCommandPool cmd_pool; VkCommandBuffers cmd_bufs(frame_count); auto build_cmd_bufs = [&]() { - if (!device->vkCreateCommandPool(device->graphics_queue().family, &cmd_pool)) return false; if (!device->vkAllocateCommandBuffers(cmd_pool, frame_count, cmd_bufs.data())) return false; - VkCommandBufferBeginInfo const begin_info - { + VkCommandBufferBeginInfo const begin_info{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, }; VkClearColorValue const clear_color = { random(0.f, 1.f), random(0.f, 1.f), random(0.f, 1.f), 0.f }; - VkImageSubresourceRange const image_range - { + VkImageSubresourceRange const image_range{ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .levelCount = 1, .layerCount = 1, }; for (auto i = 0u; i < frame_count; i++) { - auto cmd_buf = cmd_bufs[i]; auto frame_image = render_target->get_image(i); @@ -202,7 +194,6 @@ auto build_cmd_bufs = [&]() { }; auto clean_cmd_bufs = [&]() { - device->vkFreeCommandBuffers(cmd_pool, frame_count, cmd_bufs.data()); device->vkDestroyCommandPool(cmd_pool); }; @@ -214,7 +205,6 @@ render_target->on_swapchain_start = build_cmd_bufs; render_target->on_swapchain_stop = clean_cmd_bufs; frame.add_run([&]() { - input.handle_events(); if (window.close_request()) @@ -231,7 +221,6 @@ frame.add_run([&]() { }); frame.add_run_end([&]() { - clean_cmd_bufs(); plotter.destroy(); @@ -265,11 +254,9 @@ if (!block.create(device, frame_count, device->graphics_queue().family)) return error::create_failed; block.add_command([&](VkCommandBuffer cmd_buf) { - VkClearColorValue const clear_color = { random(0.f, 1.f), random(0.f, 1.f), random(0.f, 1.f), 0.f }; - VkImageSubresourceRange const image_range - { + VkImageSubresourceRange const image_range{ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .levelCount = 1, .layerCount = 1, @@ -331,7 +318,6 @@ int main(int argc, char* argv[]) { return error::not_ready; app.gui.on_draw = []() { - ImGui::ShowDemoWindow(); }; diff --git a/liblava/app/app.cpp b/liblava/app/app.cpp index 769114eeb6a5e4ad8208858419061cb2f9945233..6ffed770d51b58dc3a211ca024eff569e886ece9 100644 --- a/liblava/app/app.cpp +++ b/liblava/app/app.cpp @@ -2,438 +2,396 @@ // copyright : Copyright (c) 2018-present, Lava Block OÜ // license : MIT; see accompanying LICENSE file +#include <imgui.h> #include <liblava/app/app.hpp> #include <liblava/app/def.hpp> -#include <imgui.h> - namespace lava { -app::app(frame_config config) + app::app(frame_config config) : frame(config), window(config.app) {} -app::app(name name, argh::parser cmd_line) + app::app(name name, argh::parser cmd_line) : frame(frame_config(name, cmd_line)), window(name) {} -void app::handle_config() { - - config_file.add(&config_callback); - - config_callback.on_load = [&](json& j) { - - if (j.count(_paused_)) - run_time.paused = j[_paused_]; - - if (j.count(_speed_)) - run_time.speed = j[_speed_]; + void app::handle_config() { + config_file.add(&config_callback); - if (j.count(_auto_save_)) - config.auto_save = j[_auto_save_]; + config_callback.on_load = [&](json& j) { + if (j.count(_paused_)) + run_time.paused = j[_paused_]; - if (j.count(_save_interval_)) - config.save_interval = seconds((j[_save_interval_])); + if (j.count(_speed_)) + run_time.speed = j[_speed_]; - if (j.count(_auto_load_)) - config.auto_load = j[_auto_load_]; + if (j.count(_auto_save_)) + config.auto_save = j[_auto_save_]; - if (j.count(_fixed_delta_)) - run_time.use_fix_delta = j[_fixed_delta_]; + if (j.count(_save_interval_)) + config.save_interval = seconds((j[_save_interval_])); - if (j.count(_delta_)) - run_time.fix_delta = ms(j[_delta_]); + if (j.count(_auto_load_)) + config.auto_load = j[_auto_load_]; - if (j.count(_gui_)) - gui.set_active(j[_gui_]); + if (j.count(_fixed_delta_)) + run_time.use_fix_delta = j[_fixed_delta_]; - if (j.count(_v_sync_)) - config.v_sync = j[_v_sync_]; + if (j.count(_delta_)) + run_time.fix_delta = ms(j[_delta_]); - if (j.count(_physical_device_)) - config.physical_device = j[_physical_device_]; - }; + if (j.count(_gui_)) + gui.set_active(j[_gui_]); - config_callback.on_save = [&](json& j) { + if (j.count(_v_sync_)) + config.v_sync = j[_v_sync_]; - j[_paused_] = run_time.paused; - j[_speed_] = run_time.speed; - j[_auto_save_] = config.auto_save; - j[_save_interval_] = config.save_interval.count(); - j[_auto_load_] = config.auto_load; - j[_fixed_delta_] = run_time.use_fix_delta; - j[_delta_] = run_time.fix_delta.count(); - j[_gui_] = gui.activated(); - j[_v_sync_] = config.v_sync; - j[_physical_device_] = config.physical_device; - }; + if (j.count(_physical_device_)) + config.physical_device = j[_physical_device_]; + }; - config_file.load(); -} + config_callback.on_save = [&](json& j) { + j[_paused_] = run_time.paused; + j[_speed_] = run_time.speed; + j[_auto_save_] = config.auto_save; + j[_save_interval_] = config.save_interval.count(); + j[_auto_load_] = config.auto_load; + j[_fixed_delta_] = run_time.use_fix_delta; + j[_delta_] = run_time.fix_delta.count(); + j[_gui_] = gui.activated(); + j[_v_sync_] = config.v_sync; + j[_physical_device_] = config.physical_device; + }; -bool app::create_block() { - - if (!block.create(device, target->get_frame_count(), device->graphics_queue().family)) - return false; - - block_command = block.add_cmd([&](VkCommandBuffer cmd_buf) { - - auto current_frame = block.get_current_frame(); - - staging.stage(cmd_buf, current_frame); - - if (on_process) - on_process(cmd_buf, current_frame); + config_file.load(); + } - shading.get_pass()->process(cmd_buf, current_frame); - }); + bool app::create_block() { + if (!block.create(device, target->get_frame_count(), device->graphics_queue().family)) + return false; - return true; -} + block_command = block.add_cmd([&](VkCommandBuffer cmd_buf) { + auto current_frame = block.get_current_frame(); -bool app::setup() { + staging.stage(cmd_buf, current_frame); - if (!frame::ready()) - return false; + if (on_process) + on_process(cmd_buf, current_frame); - handle_config(); + shading.get_pass()->process(cmd_buf, current_frame); + }); - auto& cmd_line = get_cmd_line(); - cmd_line({ "-vs", "--v_sync" }) >> config.v_sync; - cmd_line({ "-pd", "--physical_device" }) >> config.physical_device; + return true; + } - if (!window.create(load_window_state(window.get_save_name()))) - return false; + bool app::setup() { + if (!frame::ready()) + return false; - set_window_icon(); + handle_config(); - if (!device) { + auto& cmd_line = get_cmd_line(); + cmd_line({ "-vs", "--v_sync" }) >> config.v_sync; + cmd_line({ "-pd", "--physical_device" }) >> config.physical_device; - device = create_device(config.physical_device); - if (!device) + if (!window.create(load_window_state(window.get_save_name()))) return false; - } - if (!create_target()) - return false; + set_window_icon(); - if (!camera.create(device)) - return false; - - if (!create_gui()) - return false; + if (!device) { + device = create_device(config.physical_device); + if (!device) + return false; + } - if (!create_block()) - return false; + if (!create_target()) + return false; - handle_input(); - handle_window(); - - update(); - render(); + if (!camera.create(device)) + return false; - add_run_end([&]() { + if (!create_gui()) + return false; - camera.destroy(); + if (!create_block()) + return false; - destroy_gui(); + handle_input(); + handle_window(); - block.destroy(); + update(); + render(); - destroy_target(); + add_run_end([&]() { + camera.destroy(); - if (config.save_window) - save_window_file(window); + destroy_gui(); - window.destroy(); + block.destroy(); - config_file.save(); - config_file.remove(&config_callback); - }); + destroy_target(); - add_run_once([&]() { + if (config.save_window) + save_window_file(window); - return on_create ? on_create() : true; - }); + window.destroy(); - frame_counter = 0; + config_file.save(); + config_file.remove(&config_callback); + }); - return true; -} + add_run_once([&]() { + return on_create ? on_create() : true; + }); -bool app::create_gui() { + frame_counter = 0; - if (config.font.file.empty()) { - - auto font_files = file_system::enumerate_files(_gui_font_path_); - if (!font_files.empty()) - config.font.file = fmt::format("{}{}", _gui_font_path_, str(font_files.front())); + return true; } - setup_font(gui_config, config.font); - - gui_config.ini_file_dir = file_system::get_pref_dir(); - - gui.setup(window.get(), gui_config); - if (!gui.create(device, target->get_frame_count(), shading.get_vk_pass())) - return false; - - shading.get_pass()->add(gui.get_pipeline()); - - fonts = make_texture(); - if (!gui.upload_fonts(fonts)) - return false; - - staging.add(fonts); - - return true; -} - -void app::destroy_gui() { - - gui.destroy(); - fonts->destroy(); -} - -bool app::create_target() { - - target = lava::create_target(&window, device, config.v_sync); - if (!target) - return false; + bool app::create_gui() { + if (config.font.file.empty()) { + auto font_files = file_system::enumerate_files(_gui_font_path_); + if (!font_files.empty()) + config.font.file = fmt::format("{}{}", _gui_font_path_, str(font_files.front())); + } - if (!shading.create(target)) - return false; + setup_font(gui_config, config.font); - if (!plotter.create(target->get_swapchain())) - return false; + gui_config.ini_file_dir = file_system::get_pref_dir(); - window.assign(&input); + gui.setup(window.get(), gui_config); + if (!gui.create(device, target->get_frame_count(), shading.get_vk_pass())) + return false; - return on_create ? on_create() : true; -} + shading.get_pass()->add(gui.get_pipeline()); -void app::destroy_target() { + fonts = make_texture(); + if (!gui.upload_fonts(fonts)) + return false; - if (on_destroy) - on_destroy(); + staging.add(fonts); - plotter.destroy(); + return true; + } - shading.destroy(); - target->destroy(); -} + void app::destroy_gui() { + gui.destroy(); + fonts->destroy(); + } -void app::handle_input() { + bool app::create_target() { + target = lava::create_target(&window, device, config.v_sync); + if (!target) + return false; - input.add(&gui); + if (!shading.create(target)) + return false; - input.key.listeners.add([&](key_event::ref event) { + if (!plotter.create(target->get_swapchain())) + return false; - if (gui.capture_keyboard()) { + window.assign(&input); - camera.stop(); - return false; - } + return on_create ? on_create() : true; + } - if (config.handle_key_events) { + void app::destroy_target() { + if (on_destroy) + on_destroy(); - if (event.pressed(key::tab)) - gui.toggle(); + plotter.destroy(); - if (event.pressed(key::escape)) - return shut_down(); + shading.destroy(); + target->destroy(); + } - if (event.pressed(key::enter, mod::alt)) { + void app::handle_input() { + input.add(&gui); - window.set_fullscreen(!window.fullscreen()); - return true; + input.key.listeners.add([&](key_event::ref event) { + if (gui.capture_keyboard()) { + camera.stop(); + return false; } - if (event.pressed(key::backspace, mod::alt)) { + if (config.handle_key_events) { + if (event.pressed(key::tab)) + gui.toggle(); - toggle_v_sync = true; - return true; - } + if (event.pressed(key::escape)) + return shut_down(); - if (event.pressed(key::space)) - run_time.paused = !run_time.paused; - } + if (event.pressed(key::enter, mod::alt)) { + window.set_fullscreen(!window.fullscreen()); + return true; + } - if (camera.activated()) - return camera.handle(event); + if (event.pressed(key::backspace, mod::alt)) { + toggle_v_sync = true; + return true; + } - return false; - }); + if (event.pressed(key::space)) + run_time.paused = !run_time.paused; + } - input.mouse_button.listeners.add([&](mouse_button_event::ref event) { + if (camera.activated()) + return camera.handle(event); - if (gui.capture_mouse()) return false; + }); - if (camera.activated()) - return camera.handle(event, input.get_mouse_position()); - - return false; - }); + input.mouse_button.listeners.add([&](mouse_button_event::ref event) { + if (gui.capture_mouse()) + return false; - input.scroll.listeners.add([&](scroll_event::ref event) { + if (camera.activated()) + return camera.handle(event, input.get_mouse_position()); - if (gui.capture_mouse()) return false; + }); - if (camera.activated()) - return camera.handle(event); - - return false; - }); - - add_run([&]() { + input.scroll.listeners.add([&](scroll_event::ref event) { + if (gui.capture_mouse()) + return false; - input.handle_events(); - input.set_mouse_position(window.get_mouse_position()); + if (camera.activated()) + return camera.handle(event); - return true; - }); + return false; + }); - add_run_end([&]() { + add_run([&]() { + input.handle_events(); + input.set_mouse_position(window.get_mouse_position()); - input.remove(&gui); - }); -} + return true; + }); -void app::handle_window() { + add_run_end([&]() { + input.remove(&gui); + }); + } - add_run([&]() { + void app::handle_window() { + add_run([&]() { + if (window.close_request()) + return shut_down(); - if (window.close_request()) - return shut_down(); + if (window.switch_mode_request() || toggle_v_sync || target->reload_request()) { + device->wait_for_idle(); - if (window.switch_mode_request() || toggle_v_sync || target->reload_request()) { + destroy_target(); + destroy_gui(); - device->wait_for_idle(); + if (window.switch_mode_request()) { + if (config.save_window) + save_window_file(window); - destroy_target(); - destroy_gui(); + auto window_state = load_window_state(window.get_save_name()); + if (window_state) + window_state->fullscreen = !window.fullscreen(); - if (window.switch_mode_request()) { + if (!window.switch_mode(window_state)) + return false; - if (config.save_window) - save_window_file(window); + set_window_icon(); + } - auto window_state = load_window_state(window.get_save_name()); - if (window_state) - window_state->fullscreen = !window.fullscreen(); + if (toggle_v_sync) { + config.v_sync = !config.v_sync; + toggle_v_sync = false; + } - if (!window.switch_mode(window_state)) + if (!create_target()) return false; - set_window_icon(); + return create_gui(); } - if (toggle_v_sync) { + if (window.resize_request()) { + camera.aspect_ratio = window.get_aspect_ratio(); + camera.update_projection(); - config.v_sync = !config.v_sync; - toggle_v_sync = false; + return window.handle_resize(); } - if (!create_target()) - return false; - - return create_gui(); - } - - if (window.resize_request()) { - - camera.aspect_ratio = window.get_aspect_ratio(); - camera.update_projection(); + return true; + }); + } - return window.handle_resize(); - } + void app::update() { + run_time.system = now(); - return true; - }); -} + add_run([&]() { + auto dt = ms(0); + auto time = now(); -void app::update() { + if (run_time.system != time) { + dt = time - run_time.system; + run_time.system = time; + } - run_time.system = now(); + run_time.delta = dt; - add_run([&]() { + if (!run_time.paused) { + if (run_time.use_fix_delta) + dt = run_time.fix_delta; - auto dt = ms(0); - auto time = now(); + dt = to_ms(to_sec(dt) * run_time.speed); + run_time.current += dt; + } else + dt = ms(0); - if (run_time.system != time) { + return on_update ? on_update(to_delta(dt)) : true; + }); + } - dt = time - run_time.system; - run_time.system = time; - } + void app::render() { + add_run([&]() { + if (window.iconified()) { + sleep(ms(1)); + return true; + } - run_time.delta = dt; + auto frame_index = plotter.begin_frame(); + if (!frame_index) + return true; - if (!run_time.paused) { + frame_counter++; - if (run_time.use_fix_delta) - dt = run_time.fix_delta; + if (!block.process(*frame_index)) + return false; - dt = to_ms(to_sec(dt) * run_time.speed); - run_time.current += dt; - } - else - dt = ms(0); + return plotter.end_frame(block.get_buffers()); + }); + } - return on_update ? on_update(to_delta(dt)) : true; - }); -} + void app::draw_about(bool separator) const { + if (separator) + ImGui::Separator(); -void app::render() { + ImGui::Text("%s %s", _liblava_, to_string(_version).c_str()); - add_run([&]() { + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("alt + enter = fullscreen\nalt + backspace = v-sync\nspace = pause\ntab = gui"); - if (window.iconified()) { + if (v_sync()) + ImGui::Text("%.f fps (v-sync)", ImGui::GetIO().Framerate); + else + ImGui::Text("%.f fps", ImGui::GetIO().Framerate); - sleep(ms(1)); - return true; + if (run_time.paused) { + ImGui::SameLine(); + ImGui::TextUnformatted(_paused_); } - - auto frame_index = plotter.begin_frame(); - if (!frame_index) - return true; - - frame_counter++; - - if (!block.process(*frame_index)) - return false; - - return plotter.end_frame(block.get_buffers()); - }); -} - -void app::draw_about(bool separator) const { - - if (separator) - ImGui::Separator(); - - ImGui::Text("%s %s", _liblava_, to_string(_version).c_str()); - - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("alt + enter = fullscreen\nalt + backspace = v-sync\nspace = pause\ntab = gui"); - - if (v_sync()) - ImGui::Text("%.f fps (v-sync)", ImGui::GetIO().Framerate); - else - ImGui::Text("%.f fps", ImGui::GetIO().Framerate); - - if (run_time.paused) { - - ImGui::SameLine(); - ImGui::TextUnformatted(_paused_); } -} - -void app::set_window_icon() { - scope_image icon("icon.png"); - if (icon.ready) - window.set_icon(icon.data, icon.size); -} + void app::set_window_icon() { + scope_image icon("icon.png"); + if (icon.ready) + window.set_icon(icon.data, icon.size); + } -} // lava +} // namespace lava diff --git a/liblava/app/app.hpp b/liblava/app/app.hpp index 1b511a70349c1a845705e1ca94def12b34399839..58d690a2864be68ff6512e90e437e1fa3e8921a4 100644 --- a/liblava/app/app.hpp +++ b/liblava/app/app.hpp @@ -4,102 +4,105 @@ #pragma once -#include <liblava/frame.hpp> -#include <liblava/block.hpp> - -#include <liblava/app/forward_shading.hpp> #include <liblava/app/camera.hpp> +#include <liblava/app/forward_shading.hpp> #include <liblava/app/gui.hpp> +#include <liblava/block.hpp> +#include <liblava/frame.hpp> namespace lava { -struct app : frame { - - struct config { + struct app : frame { + struct config { + bool save_window = true; + bool handle_key_events = true; - bool save_window = true; - bool handle_key_events = true; + bool auto_load = true; + bool auto_save = true; + seconds save_interval{ 300 }; - bool auto_load = true; - bool auto_save = true; - seconds save_interval{ 300 }; + bool v_sync = false; + index physical_device = 0; - bool v_sync = false; - index physical_device = 0; + lava::font font; + }; - lava::font font; - }; + explicit app(frame_config config); + explicit app(name name, argh::parser cmd_line = {}); - explicit app(frame_config config); - explicit app(name name, argh::parser cmd_line = {}); + bool setup(); - bool setup(); + lava::window window; + lava::input input; - lava::window window; - lava::input input; + lava::gui gui; + gui::config gui_config; - lava::gui gui; - gui::config gui_config; + device_ptr device = nullptr; + lava::camera camera; - device_ptr device = nullptr; - lava::camera camera; + lava::staging staging; + lava::block block; - lava::staging staging; - lava::block block; + renderer plotter; + forward_shading shading; + render_target::ptr target; - renderer plotter; - forward_shading shading; - render_target::ptr target; + lava::run_time run_time; - lava::run_time run_time; + using update_func = std::function<bool(delta)>; + update_func on_update; - using update_func = std::function<bool(delta)>; - update_func on_update; + using create_func = std::function<bool()>; + create_func on_create; - using create_func = std::function<bool()>; - create_func on_create; + using destroy_func = std::function<void()>; + destroy_func on_destroy; - using destroy_func = std::function<void()>; - destroy_func on_destroy; + bool v_sync() const { + return config.v_sync; + } + ui32 get_frame_counter() const { + return frame_counter; + } - bool v_sync() const { return config.v_sync; } - ui32 get_frame_counter() const { return frame_counter; } + void draw_about(bool separator = true) const; - void draw_about(bool separator = true) const; + config config; + json_file config_file; - config config; - json_file config_file; + using process_func = std::function<void(VkCommandBuffer, index)>; + process_func on_process; - using process_func = std::function<void(VkCommandBuffer, index)>; - process_func on_process; + id::ref block_cmd() const { + return block_command; + } - id::ref block_cmd() const { return block_command; } + private: + void handle_config(); + void handle_input(); + void handle_window(); -private: - void handle_config(); - void handle_input(); - void handle_window(); + void update(); + void render(); - void update(); - void render(); + bool create_gui(); + void destroy_gui(); - bool create_gui(); - void destroy_gui(); + bool create_target(); + void destroy_target(); - bool create_target(); - void destroy_target(); + bool create_block(); + void set_window_icon(); - bool create_block(); - void set_window_icon(); + texture::ptr fonts; - texture::ptr fonts; + bool toggle_v_sync = false; + ui32 frame_counter = 0; - bool toggle_v_sync = false; - ui32 frame_counter = 0; + file_callback config_callback; - file_callback config_callback; - - id block_command; -}; + id block_command; + }; -} // lava +} // namespace lava diff --git a/liblava/app/camera.cpp b/liblava/app/camera.cpp index 724878f67c7720cb68ea95742ee2b67cda5fe59d..529ffc58f1ef44b73b9f1bb84fb8efacced060fb 100644 --- a/liblava/app/camera.cpp +++ b/liblava/app/camera.cpp @@ -6,231 +6,218 @@ namespace lava { -bool camera::create(device_ptr device) { + bool camera::create(device_ptr device) { + update_projection(); - update_projection(); + data = make_buffer(); - data = make_buffer(); - - return data->create_mapped(device, &projection, size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); -} - -void camera::destroy() { - - if (!data) - return; + return data->create_mapped(device, &projection, size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + } - data->destroy(); - data = nullptr; -} + void camera::destroy() { + if (!data) + return; -void camera::update_view(delta dt, mouse_position mouse_pos) { + data->destroy(); + data = nullptr; + } - if (translate || rotate) { + void camera::update_view(delta dt, mouse_position mouse_pos) { + if (translate || rotate) { + auto dx = mouse_pos_x - mouse_pos.x; + auto dy = mouse_pos_y - mouse_pos.y; - auto dx = mouse_pos_x - mouse_pos.x; - auto dy = mouse_pos_y - mouse_pos.y; + if (rotate && !lock_rotation) { + auto speed = dt * rotation_speed; + rotation += v3(dy * speed, -dx * speed, 0.f); + } - if (rotate && !lock_rotation) { + if (translate) { + auto speed = dt * movement_speed; + position -= v3(-dx * speed, -dy * speed, 0.f); + } - auto speed = dt * rotation_speed; - rotation += v3(dy * speed, -dx * speed, 0.f); + mouse_pos_x = mouse_pos.x; + mouse_pos_y = mouse_pos.y; } - if (translate) { - - auto speed = dt * movement_speed; - position -= v3(-dx * speed, -dy * speed, 0.f); + if ((scroll_pos != 0.0)) { + auto speed = dt * zoom_speed; + position -= v3(-0.f, 0.f, scroll_pos * speed); + scroll_pos = 0.0; } - mouse_pos_x = mouse_pos.x; - mouse_pos_y = mouse_pos.y; - } - - if ((scroll_pos != 0.0)) { - - auto speed = dt * zoom_speed; - position -= v3(-0.f, 0.f, scroll_pos * speed); - scroll_pos = 0.0; - } + if (type == camera_type::first_person && moving()) { + v3 front; + front.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y)); + front.y = sin(glm::radians(rotation.x)); + front.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y)); - if (type == camera_type::first_person && moving()) { + front = glm::normalize(front); - v3 front; - front.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y)); - front.y = sin(glm::radians(rotation.x)); - front.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y)); + auto speed = dt * movement_speed * 2.f; - front = glm::normalize(front); + if (up) { + if (lock_z) + position -= glm::normalize(glm::cross(front, v3(1.f, 0.f, 0.f))) * speed; + else + position -= (front * speed); + } - auto speed = dt * movement_speed * 2.f; + if (down) { + if (lock_z) + position += glm::normalize(glm::cross(front, v3(1.f, 0.f, 0.f))) * speed; + else + position += (front * speed); + } - if (up) { + if (left) + position += glm::normalize(glm::cross(front, v3(0.f, 1.f, 0.f))) * speed; - if (lock_z) - position -= glm::normalize(glm::cross(front, v3(1.f, 0.f, 0.f))) * speed; - else - position -= (front * speed); + if (right) + position -= glm::normalize(glm::cross(front, v3(0.f, 1.f, 0.f))) * speed; } - if (down) { + auto rot_m = mat4(1.f); + rot_m = glm::rotate(rot_m, glm::radians(rotation.x), v3(1.f, 0.f, 0.f)); + rot_m = glm::rotate(rot_m, glm::radians(rotation.y), v3(0.f, 1.f, 0.f)); + rot_m = glm::rotate(rot_m, glm::radians(rotation.z), v3(0.f, 0.f, 1.f)); - if (lock_z) - position += glm::normalize(glm::cross(front, v3(1.f, 0.f, 0.f))) * speed; - else - position += (front * speed); - } + auto trans_m = glm::translate(mat4(1.f), -position); - if (left) - position += glm::normalize(glm::cross(front, v3(0.f, 1.f, 0.f))) * speed; + if (type == camera_type::first_person) + view = rot_m * trans_m; + else + view = trans_m * rot_m; - if (right) - position -= glm::normalize(glm::cross(front, v3(0.f, 1.f, 0.f))) * speed; + if (valid()) + memcpy(as_ptr(data->get_mapped_data()) + sizeof(mat4), &view, sizeof(mat4)); } - auto rot_m = mat4(1.f); - rot_m = glm::rotate(rot_m, glm::radians(rotation.x), v3(1.f, 0.f, 0.f)); - rot_m = glm::rotate(rot_m, glm::radians(rotation.y), v3(0.f, 1.f, 0.f)); - rot_m = glm::rotate(rot_m, glm::radians(rotation.z), v3(0.f, 0.f, 1.f)); - - auto trans_m = glm::translate(mat4(1.f), -position); - - if (type == camera_type::first_person) - view = rot_m * trans_m; - else - view = trans_m * rot_m; - - if (valid()) - memcpy(as_ptr(data->get_mapped_data()) + sizeof(mat4), &view, sizeof(mat4)); -} - -void camera::update_view(delta dt, gamepad::ref pad) { - - const r32 dead_zone = 0.2f; - const r32 range = 1.f - dead_zone; - - if (type == camera_type::first_person) { - - v3 front; - front.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y)); - front.y = sin(glm::radians(rotation.x)); - front.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y)); - front = glm::normalize(front); + void camera::update_view(delta dt, gamepad::ref pad) { + const r32 dead_zone = 0.2f; + const r32 range = 1.f - dead_zone; + + if (type == camera_type::first_person) { + v3 front; + front.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y)); + front.y = sin(glm::radians(rotation.x)); + front.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y)); + front = glm::normalize(front); + + // move + + auto movement_factor = dt * movement_speed * 2.f; + + auto axis_left_y = pad.value(gamepad_axis::left_y); + if (fabsf(axis_left_y) > dead_zone) { + auto pos = (fabsf(axis_left_y) - dead_zone) / range; + if (lock_z) + position -= glm::normalize(glm::cross(front, v3(1.f, 0.f, 0.f))) * ((axis_left_y < 0.f) ? 1.f : -1.f) * movement_factor; + else + position -= front * pos * ((axis_left_y < 0.f) ? 1.f : -1.f) * movement_factor; + } + + auto axis_left_x = pad.value(gamepad_axis::left_x); + if (fabsf(axis_left_x) > dead_zone) { + auto pos = (fabsf(axis_left_x) - dead_zone) / range; + position += glm::normalize(glm::cross(front, glm::vec3(0.f, 1.f, 0.f))) * pos * ((axis_left_x < 0.f) ? 1.f : -1.f) * movement_factor; + } + } - // move + // rotate - auto movement_factor = dt * movement_speed * 2.f; + if (lock_rotation) + return; - auto axis_left_y = pad.value(gamepad_axis::left_y); - if (fabsf(axis_left_y) > dead_zone) { + auto rotation_factor = dt * rotation_speed * 2.5f; - auto pos = (fabsf(axis_left_y) - dead_zone) / range; - if (lock_z) - position -= glm::normalize(glm::cross(front, v3(1.f, 0.f, 0.f))) * ((axis_left_y < 0.f) ? 1.f : -1.f) * movement_factor; - else - position -= front * pos * ((axis_left_y < 0.f) ? 1.f : -1.f) * movement_factor; + auto axis_right_x = pad.value(gamepad_axis::right_x); + if (fabsf(axis_right_x) > dead_zone) { + auto pos = (fabsf(axis_right_x) - dead_zone) / range; + rotation.y += pos * ((axis_right_x < 0.f) ? -1.f : 1.f) * rotation_factor; } - auto axis_left_x = pad.value(gamepad_axis::left_x); - if (fabsf(axis_left_x) > dead_zone) { - - auto pos = (fabsf(axis_left_x) - dead_zone) / range; - position += glm::normalize(glm::cross(front, glm::vec3(0.f, 1.f, 0.f))) * pos * ((axis_left_x < 0.f) ? 1.f : -1.f) * movement_factor; + auto axis_right_y = pad.value(gamepad_axis::right_y); + if (fabsf(axis_right_y) > dead_zone) { + auto pos = (fabsf(axis_right_y) - dead_zone) / range; + rotation.x -= pos * ((axis_right_y < 0.f) ? -1.f : 1.f) * rotation_factor; } } - // rotate - - if (lock_rotation) - return; + void camera::update_projection() { + projection = glm::perspective(glm::radians(fov), aspect_ratio, z_near, z_far); - auto rotation_factor = dt * rotation_speed * 2.5f; - - auto axis_right_x = pad.value(gamepad_axis::right_x); - if (fabsf(axis_right_x) > dead_zone) { - - auto pos = (fabsf(axis_right_x) - dead_zone) / range; - rotation.y += pos * ((axis_right_x < 0.f) ? -1.f : 1.f) * rotation_factor; + if (valid()) + memcpy(as_ptr(data->get_mapped_data()), &projection, sizeof(mat4)); } - auto axis_right_y = pad.value(gamepad_axis::right_y); - if (fabsf(axis_right_y) > dead_zone) { - - auto pos = (fabsf(axis_right_y) - dead_zone) / range; - rotation.x -= pos * ((axis_right_y < 0.f) ? -1.f : 1.f) * rotation_factor; + void camera::upload() { + memcpy(data->get_mapped_data(), &projection, size); } -} -void camera::update_projection() { - - projection = glm::perspective(glm::radians(fov), aspect_ratio, z_near, z_far); - - if (valid()) - memcpy(as_ptr(data->get_mapped_data()), &projection, sizeof(mat4)); -} - -void camera::upload() { - - memcpy(data->get_mapped_data(), &projection, size); -} - -bool camera::handle(key_event::ref event) { - - switch (event.key) - { - case key::w: { up = event.active(); break; } - case key::s: { down = event.active(); break; } - case key::a: { left = event.active(); break; } - case key::d: { right = event.active(); break; } + bool camera::handle(key_event::ref event) { + switch (event.key) { + case key::w: { + up = event.active(); + break; + } + case key::s: { + down = event.active(); + break; + } + case key::a: { + left = event.active(); + break; + } + case key::d: { + right = event.active(); + break; + } default: return false; - } - - return true; -} - -bool camera::handle(mouse_button_event::ref event, mouse_position mouse_pos) { - - rotate = event.pressed(mouse_button::left); - translate = event.pressed(mouse_button::right); - - if (rotate || translate) { - - mouse_pos_x = mouse_pos.x; - mouse_pos_y = mouse_pos.y; + } return true; } - return false; -} + bool camera::handle(mouse_button_event::ref event, mouse_position mouse_pos) { + rotate = event.pressed(mouse_button::left); + translate = event.pressed(mouse_button::right); -bool camera::handle(scroll_event::ref event) { + if (rotate || translate) { + mouse_pos_x = mouse_pos.x; + mouse_pos_y = mouse_pos.y; - scroll_pos += event.offset.y; + return true; + } - return true; -} + return false; + } -void camera::stop() { + bool camera::handle(scroll_event::ref event) { + scroll_pos += event.offset.y; - up = false; - down = false; - left = false; - right = false; + return true; + } - rotate = false; - translate = false; + void camera::stop() { + up = false; + down = false; + left = false; + right = false; - mouse_pos_x = 0.0; - mouse_pos_y = 0.0; - scroll_pos = 0.0; -} + rotate = false; + translate = false; -void camera::reset() { + mouse_pos_x = 0.0; + mouse_pos_y = 0.0; + scroll_pos = 0.0; + } - position = v3(0.f); - rotation = v3(0.f); -} + void camera::reset() { + position = v3(0.f); + rotation = v3(0.f); + } -} // lava +} // namespace lava diff --git a/liblava/app/camera.hpp b/liblava/app/camera.hpp index 95955ec265c66e6d20a46d020a29409bf5c5f065..b4bc33f02745d42860945041e7b21b08d21e0512 100644 --- a/liblava/app/camera.hpp +++ b/liblava/app/camera.hpp @@ -4,82 +4,90 @@ #pragma once -#include <liblava/resource/buffer.hpp> #include <liblava/frame/input.hpp> +#include <liblava/resource/buffer.hpp> namespace lava { -enum class camera_type : type -{ - first_person, - look_at, -}; + enum class camera_type : type { + first_person, + look_at, + }; -struct camera : id_obj { + struct camera : id_obj { + using map = std::map<id, camera>; + using list = std::vector<camera*>; - using map = std::map<id, camera>; - using list = std::vector<camera*>; + bool create(device_ptr device); + void destroy(); - bool create(device_ptr device); - void destroy(); + void update_projection(); + void update_view(delta dt, mouse_position mouse_pos); + void update_view(delta dt, gamepad::ref pad); - void update_projection(); - void update_view(delta dt, mouse_position mouse_pos); - void update_view(delta dt, gamepad::ref pad); + bool handle(key_event::ref event); + bool handle(mouse_button_event::ref event, mouse_position mouse_pos); + bool handle(scroll_event::ref event); - bool handle(key_event::ref event); - bool handle(mouse_button_event::ref event, mouse_position mouse_pos); - bool handle(scroll_event::ref event); - - bool valid() const { return data ? data->valid() : false; } - VkDescriptorBufferInfo const* get_info() const { return data ? data->get_info() : nullptr; } + bool valid() const { + return data ? data->valid() : false; + } + VkDescriptorBufferInfo const* get_info() const { + return data ? data->get_info() : nullptr; + } - void upload(); + void upload(); - void stop(); - void reset(); + void stop(); + void reset(); - void set_active(bool value = true) { active = value; } - bool activated() const { return active; } - bool moving() const { return up || down || left || right; } + void set_active(bool value = true) { + active = value; + } + bool activated() const { + return active; + } + bool moving() const { + return up || down || left || right; + } - v3 position = v3(0.f); - v3 rotation = v3(0.f); + v3 position = v3(0.f); + v3 rotation = v3(0.f); - r32 rotation_speed = 20.f; - r32 movement_speed = 1.f; - r32 zoom_speed = 20.f; + r32 rotation_speed = 20.f; + r32 movement_speed = 1.f; + r32 zoom_speed = 20.f; - r32 fov = 60.f; - r32 z_near = 0.1f; - r32 z_far = 256.f; - r32 aspect_ratio = 1.77f; + r32 fov = 60.f; + r32 z_near = 0.1f; + r32 z_far = 256.f; + r32 aspect_ratio = 1.77f; - camera_type type = camera_type::first_person; + camera_type type = camera_type::first_person; - bool lock_z = false; - bool lock_rotation = false; + bool lock_z = false; + bool lock_rotation = false; -private: - bool active = true; + private: + bool active = true; - bool up = false; - bool down = false; - bool left = false; - bool right = false; + bool up = false; + bool down = false; + bool left = false; + bool right = false; - bool rotate = false; - bool translate = false; + bool rotate = false; + bool translate = false; - r64 mouse_pos_x = 0.0; - r64 mouse_pos_y = 0.0; - r64 scroll_pos = 0.0; + r64 mouse_pos_x = 0.0; + r64 mouse_pos_y = 0.0; + r64 scroll_pos = 0.0; - buffer::ptr data; - size_t size = sizeof(mat4) * 2; // projection + view + buffer::ptr data; + size_t size = sizeof(mat4) * 2; // projection + view - mat4 projection = mat4(0.f); - mat4 view = mat4(0.f); -}; + mat4 projection = mat4(0.f); + mat4 view = mat4(0.f); + }; -} // lava +} // namespace lava diff --git a/liblava/app/def.hpp b/liblava/app/def.hpp index c2523b583b64422d67378d46fcc680dc52c71ad9..b1762a05fa61479776724b3791db0a186ed4af5f 100644 --- a/liblava/app/def.hpp +++ b/liblava/app/def.hpp @@ -8,16 +8,16 @@ namespace lava { -// config -constexpr name _paused_ = "paused"; -constexpr name _speed_ = "speed"; -constexpr name _auto_save_ = "auto save"; -constexpr name _save_interval_ = "save interval"; -constexpr name _auto_load_ = "auto load"; -constexpr name _fixed_delta_ = "fixed delta"; -constexpr name _delta_ = "delta"; -constexpr name _gui_ = "gui"; -constexpr name _v_sync_ = "v-sync"; -constexpr name _physical_device_ = "physical device"; + // config + constexpr name _paused_ = "paused"; + constexpr name _speed_ = "speed"; + constexpr name _auto_save_ = "auto save"; + constexpr name _save_interval_ = "save interval"; + constexpr name _auto_load_ = "auto load"; + constexpr name _fixed_delta_ = "fixed delta"; + constexpr name _delta_ = "delta"; + constexpr name _gui_ = "gui"; + constexpr name _v_sync_ = "v-sync"; + constexpr name _physical_device_ = "physical device"; -} // lava +} // namespace lava diff --git a/liblava/app/forward_shading.cpp b/liblava/app/forward_shading.cpp index 4333e9a9cba0f7a684ecaa47a683887141d3e8b5..85a95be329852db5a87768d1bc2a12b239c723c9 100644 --- a/liblava/app/forward_shading.cpp +++ b/liblava/app/forward_shading.cpp @@ -7,102 +7,97 @@ namespace lava { -bool forward_shading::create(render_target::ptr t) { - - target = t; - - auto depth_format = VK_FORMAT_UNDEFINED; - if (!get_supported_depth_format(target->get_device()->get_vk_physical_device(), &depth_format)) - return false; - - pass = make_render_pass(target->get_device()); - { - auto color_attachment = make_attachment(target->get_format()); - color_attachment->set_op(VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE); - color_attachment->set_stencil_op(VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE); - color_attachment->set_layouts(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); - pass->add(color_attachment); - - auto depth_attachment = make_attachment(depth_format); - depth_attachment->set_op(VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE); - depth_attachment->set_stencil_op(VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE); - depth_attachment->set_layouts(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - pass->add(depth_attachment); - - auto subpass = make_subpass(VK_PIPELINE_BIND_POINT_GRAPHICS); - subpass->set_color_attachment(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - subpass->set_depth_stencil_attachment(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - pass->add(subpass); - - auto first_subpass_dependency = make_subpass_dependency(VK_SUBPASS_EXTERNAL, 0); - first_subpass_dependency->set_stage_mask(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); - first_subpass_dependency->set_access_mask(VK_ACCESS_MEMORY_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); - pass->add(first_subpass_dependency); - - auto second_subpass_dependency = make_subpass_dependency(0, VK_SUBPASS_EXTERNAL); - second_subpass_dependency->set_stage_mask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); - second_subpass_dependency->set_access_mask(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT); - pass->add(second_subpass_dependency); - } - - depth_stencil = make_image(depth_format); - if (!depth_stencil) - return false; - - depth_stencil->set_usage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); - depth_stencil->set_layout(VK_IMAGE_LAYOUT_UNDEFINED); - depth_stencil->set_aspect_mask(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); - depth_stencil->set_component(); + bool forward_shading::create(render_target::ptr t) { + target = t; + + auto depth_format = VK_FORMAT_UNDEFINED; + if (!get_supported_depth_format(target->get_device()->get_vk_physical_device(), &depth_format)) + return false; + + pass = make_render_pass(target->get_device()); + { + auto color_attachment = make_attachment(target->get_format()); + color_attachment->set_op(VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE); + color_attachment->set_stencil_op(VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE); + color_attachment->set_layouts(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + pass->add(color_attachment); + + auto depth_attachment = make_attachment(depth_format); + depth_attachment->set_op(VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE); + depth_attachment->set_stencil_op(VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE); + depth_attachment->set_layouts(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + pass->add(depth_attachment); + + auto subpass = make_subpass(VK_PIPELINE_BIND_POINT_GRAPHICS); + subpass->set_color_attachment(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + subpass->set_depth_stencil_attachment(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + pass->add(subpass); + + auto first_subpass_dependency = make_subpass_dependency(VK_SUBPASS_EXTERNAL, 0); + first_subpass_dependency->set_stage_mask(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + first_subpass_dependency->set_access_mask(VK_ACCESS_MEMORY_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); + pass->add(first_subpass_dependency); + + auto second_subpass_dependency = make_subpass_dependency(0, VK_SUBPASS_EXTERNAL); + second_subpass_dependency->set_stage_mask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); + second_subpass_dependency->set_access_mask(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT); + pass->add(second_subpass_dependency); + } - target->on_create_attachments = [&]() -> VkAttachments { + depth_stencil = make_image(depth_format); + if (!depth_stencil) + return false; - VkAttachments result; + depth_stencil->set_usage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); + depth_stencil->set_layout(VK_IMAGE_LAYOUT_UNDEFINED); + depth_stencil->set_aspect_mask(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); + depth_stencil->set_component(); - if (!depth_stencil->create(target->get_device(), target->get_size())) - return {}; + target->on_create_attachments = [&]() -> VkAttachments { + VkAttachments result; - for (auto& backbuffer : target->get_backbuffers()) { + if (!depth_stencil->create(target->get_device(), target->get_size())) + return {}; - VkImageViews attachments; + for (auto& backbuffer : target->get_backbuffers()) { + VkImageViews attachments; - attachments.push_back(backbuffer->get_view()); - attachments.push_back(depth_stencil->get_view()); + attachments.push_back(backbuffer->get_view()); + attachments.push_back(depth_stencil->get_view()); - result.push_back(attachments); - } + result.push_back(attachments); + } - return result; - }; + return result; + }; - target->on_destroy_attachments = [&]() { + target->on_destroy_attachments = [&]() { + depth_stencil->destroy(); + }; - depth_stencil->destroy(); - }; + if (!pass->create(target->on_create_attachments(), { {}, target->get_size() })) + return false; - if (!pass->create(target->on_create_attachments(), { {}, target->get_size() })) - return false; + target->add_callback(pass.get()); - target->add_callback(pass.get()); + pass->set_clear_color(); - pass->set_clear_color(); - - return true; -} - -void forward_shading::destroy() { + return true; + } - if (!target) - return; + void forward_shading::destroy() { + if (!target) + return; - target->remove_callback(pass.get()); + target->remove_callback(pass.get()); - pass->destroy(); - pass = nullptr; + pass->destroy(); + pass = nullptr; - depth_stencil->destroy(); - depth_stencil = nullptr; + depth_stencil->destroy(); + depth_stencil = nullptr; - target = nullptr; -} + target = nullptr; + } -} // lava +} // namespace lava diff --git a/liblava/app/forward_shading.hpp b/liblava/app/forward_shading.hpp index 502c4e873a2d437fccab5f332cdba24e83a32439..5627d982fdac5ec4b65eab20bb2ff7e9fdb4f949 100644 --- a/liblava/app/forward_shading.hpp +++ b/liblava/app/forward_shading.hpp @@ -4,29 +4,36 @@ #pragma once -#include <liblava/frame/render_target.hpp> #include <liblava/block/render_pass.hpp> +#include <liblava/frame/render_target.hpp> namespace lava { -struct forward_shading : id_obj { - - explicit forward_shading() = default; - ~forward_shading() { destroy(); } + struct forward_shading : id_obj { + explicit forward_shading() = default; + ~forward_shading() { + destroy(); + } - bool create(render_target::ptr target); - void destroy(); + bool create(render_target::ptr target); + void destroy(); - render_pass::ptr get_pass() const { return pass; } - VkRenderPass get_vk_pass() const { return pass->get(); } + render_pass::ptr get_pass() const { + return pass; + } + VkRenderPass get_vk_pass() const { + return pass->get(); + } - image::ptr get_depth_stencil() const { return depth_stencil; } + image::ptr get_depth_stencil() const { + return depth_stencil; + } -private: - render_target::ptr target; + private: + render_target::ptr target; - render_pass::ptr pass; - image::ptr depth_stencil; -}; + render_pass::ptr pass; + image::ptr depth_stencil; + }; -} // lava +} // namespace lava diff --git a/liblava/app/gui.cpp b/liblava/app/gui.cpp index f01a6a92ac86b831bed5ae51f89596ec415e167b..23a1f5096a6530a9d03e7313f6764c8d02f2fe3d 100644 --- a/liblava/app/gui.cpp +++ b/liblava/app/gui.cpp @@ -2,668 +2,616 @@ // copyright : Copyright (c) 2018-present, Lava Block OÜ // license : MIT; see accompanying LICENSE file -#include <liblava/app/gui.hpp> #include <liblava/app/def.hpp> +#include <liblava/app/gui.hpp> #define GLFW_INCLUDE_NONE #define GLFW_INCLUDE_VULKAN #include <GLFW/glfw3.h> #ifdef _WIN32 -#undef APIENTRY -#define GLFW_EXPOSE_NATIVE_WIN32 -#include <GLFW/glfw3native.h> // glfwGetWin32Window +# undef APIENTRY +# define GLFW_EXPOSE_NATIVE_WIN32 +# include <GLFW/glfw3native.h> // glfwGetWin32Window #endif #include <imgui.h> namespace lava { -name get_clipboard_text(void* user_data) { - - return glfwGetClipboardString(static_cast<GLFWwindow*>(user_data)); -} - -void set_clipboard_text(void* user_data, name text) { - - glfwSetClipboardString(static_cast<GLFWwindow*>(user_data), text); -} - -void gui::handle_mouse_button_event(i32 button, i32 action, i32 mods) { - - if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(mouse_just_pressed)) - mouse_just_pressed[button] = true; -} - -void gui::handle_scroll_event(r64 x_offset, r64 y_offset) { - - auto& io = ImGui::GetIO(); - io.MouseWheelH += static_cast<float>(x_offset); - io.MouseWheel += static_cast<float>(y_offset); -} - -void gui::handle_key_event(i32 key, i32 scancode, i32 action, i32 mods) { - - auto& io = ImGui::GetIO(); - - if (action == GLFW_PRESS) - io.KeysDown[key] = true; - - if (action == GLFW_RELEASE) - io.KeysDown[key] = false; - - io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; - io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; - io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; - io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; -} - -void gui::update_mouse_pos_and_buttons() { - - auto& io = ImGui::GetIO(); + name get_clipboard_text(void* user_data) { + return glfwGetClipboardString(static_cast<GLFWwindow*>(user_data)); + } - for (i32 i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) { + void set_clipboard_text(void* user_data, name text) { + glfwSetClipboardString(static_cast<GLFWwindow*>(user_data), text); + } - io.MouseDown[i] = mouse_just_pressed[i] || glfwGetMouseButton(window, i) != 0; - mouse_just_pressed[i] = false; + void gui::handle_mouse_button_event(i32 button, i32 action, i32 mods) { + if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(mouse_just_pressed)) + mouse_just_pressed[button] = true; } - ImVec2 const mouse_pos_backup = io.MousePos; - io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + void gui::handle_scroll_event(r64 x_offset, r64 y_offset) { + auto& io = ImGui::GetIO(); + io.MouseWheelH += static_cast<float>(x_offset); + io.MouseWheel += static_cast<float>(y_offset); + } - if (glfwGetWindowAttrib(window, GLFW_FOCUSED)) { + void gui::handle_key_event(i32 key, i32 scancode, i32 action, i32 mods) { + auto& io = ImGui::GetIO(); - if (io.WantSetMousePos) { + if (action == GLFW_PRESS) + io.KeysDown[key] = true; - glfwSetCursorPos(window, (double)mouse_pos_backup.x, (double)mouse_pos_backup.y); - } - else { + if (action == GLFW_RELEASE) + io.KeysDown[key] = false; - double mouse_x, mouse_y; - glfwGetCursorPos(window, &mouse_x, &mouse_y); - io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); - } + io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; + io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; + io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; + io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; } -} - -void gui::update_mouse_cursor() { - auto& io = ImGui::GetIO(); - if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) - return; + void gui::update_mouse_pos_and_buttons() { + auto& io = ImGui::GetIO(); - ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); - if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) { + for (i32 i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) { + io.MouseDown[i] = mouse_just_pressed[i] || glfwGetMouseButton(window, i) != 0; + mouse_just_pressed[i] = false; + } - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); - } - else { + ImVec2 const mouse_pos_backup = io.MousePos; + io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - glfwSetCursor(window, mouse_cursors[imgui_cursor] ? mouse_cursors[imgui_cursor] : mouse_cursors[ImGuiMouseCursor_Arrow]); - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + if (glfwGetWindowAttrib(window, GLFW_FOCUSED)) { + if (io.WantSetMousePos) { + glfwSetCursorPos(window, (double) mouse_pos_backup.x, (double) mouse_pos_backup.y); + } else { + double mouse_x, mouse_y; + glfwGetCursorPos(window, &mouse_x, &mouse_y); + io.MousePos = ImVec2((float) mouse_x, (float) mouse_y); + } + } } -} -void gui::setup(GLFWwindow* w, config config) { - - window = w; - current_time = 0.0; - - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - - auto& io = ImGui::GetIO(); - io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; - io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; - - io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; - io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; - io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; - io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; - io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN; - io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP; - io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; - io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; - io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; - io.KeyMap[ImGuiKey_Insert] = GLFW_KEY_INSERT; - io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; - io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; - io.KeyMap[ImGuiKey_Space] = GLFW_KEY_SPACE; - io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; - io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; - io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; - io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; - io.KeyMap[ImGuiKey_V] = GLFW_KEY_V; - io.KeyMap[ImGuiKey_X] = GLFW_KEY_X; - io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; - io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; - - auto& style = ImGui::GetStyle(); - style.Colors[ImGuiCol_TitleBg] = ImVec4(0.8f, 0.f, 0.f, 0.4f); - style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.8f, 0.f, 0.0f, 1.f); - style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(1.f, 0.f, 0.f, 0.1f); - style.Colors[ImGuiCol_MenuBarBg] = ImVec4(1.f, 0.f, 0.f, 0.4f); - style.Colors[ImGuiCol_Header] = ImVec4(0.8f, 0.f, 0.f, 0.4f); - style.Colors[ImGuiCol_HeaderActive] = ImVec4(1.f, 0.f, 0.f, 0.4f); - style.Colors[ImGuiCol_HeaderHovered] = ImVec4(1.f, 0.f, 0.f, 0.5f); - style.Colors[ImGuiCol_CheckMark] = ImVec4(1.f, 0.f, 0.f, 0.8f); - style.Colors[ImGuiCol_WindowBg] = ImVec4(0.059f, 0.059f, 0.059f, 0.863f); - style.Colors[ImGuiCol_ResizeGrip] = ImVec4(0.f, 0.f, 0.f, 0.0f); - - if (config.font_data.ptr) { - - ImFontConfig font_config; - font_config.FontDataOwnedByAtlas = false; - - io.Fonts->AddFontFromMemoryTTF(config.font_data.ptr, to_i32(config.font_data.size), config.font_size, &font_config); - } - else { + void gui::update_mouse_cursor() { + auto& io = ImGui::GetIO(); + if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) + return; - io.Fonts->AddFontDefault(); + ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); + if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) { + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + } else { + glfwSetCursor(window, mouse_cursors[imgui_cursor] ? mouse_cursors[imgui_cursor] : mouse_cursors[ImGuiMouseCursor_Arrow]); + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + } } - if (config.icon.font_data.ptr) { + void gui::setup(GLFWwindow* w, config config) { + window = w; + current_time = 0.0; + + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + + auto& io = ImGui::GetIO(); + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; + io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; + + io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; + io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; + io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN; + io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP; + io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; + io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; + io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; + io.KeyMap[ImGuiKey_Insert] = GLFW_KEY_INSERT; + io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; + io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; + io.KeyMap[ImGuiKey_Space] = GLFW_KEY_SPACE; + io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; + io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; + io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; + io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; + io.KeyMap[ImGuiKey_V] = GLFW_KEY_V; + io.KeyMap[ImGuiKey_X] = GLFW_KEY_X; + io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; + io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; + + auto& style = ImGui::GetStyle(); + style.Colors[ImGuiCol_TitleBg] = ImVec4(0.8f, 0.f, 0.f, 0.4f); + style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.8f, 0.f, 0.0f, 1.f); + style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(1.f, 0.f, 0.f, 0.1f); + style.Colors[ImGuiCol_MenuBarBg] = ImVec4(1.f, 0.f, 0.f, 0.4f); + style.Colors[ImGuiCol_Header] = ImVec4(0.8f, 0.f, 0.f, 0.4f); + style.Colors[ImGuiCol_HeaderActive] = ImVec4(1.f, 0.f, 0.f, 0.4f); + style.Colors[ImGuiCol_HeaderHovered] = ImVec4(1.f, 0.f, 0.f, 0.5f); + style.Colors[ImGuiCol_CheckMark] = ImVec4(1.f, 0.f, 0.f, 0.8f); + style.Colors[ImGuiCol_WindowBg] = ImVec4(0.059f, 0.059f, 0.059f, 0.863f); + style.Colors[ImGuiCol_ResizeGrip] = ImVec4(0.f, 0.f, 0.f, 0.0f); + + if (config.font_data.ptr) { + ImFontConfig font_config; + font_config.FontDataOwnedByAtlas = false; + + io.Fonts->AddFontFromMemoryTTF(config.font_data.ptr, to_i32(config.font_data.size), config.font_size, &font_config); + } else { + io.Fonts->AddFontDefault(); + } - static const ImWchar icons_ranges[] = { config.icon.range_begin, config.icon.range_end, 0 }; + if (config.icon.font_data.ptr) { + static const ImWchar icons_ranges[] = { config.icon.range_begin, config.icon.range_end, 0 }; - ImFontConfig icons_config; - icons_config.MergeMode = true; - icons_config.PixelSnapH = true; - icons_config.FontDataOwnedByAtlas = false; + ImFontConfig icons_config; + icons_config.MergeMode = true; + icons_config.PixelSnapH = true; + icons_config.FontDataOwnedByAtlas = false; - io.Fonts->AddFontFromMemoryTTF(config.icon.font_data.ptr, to_i32(config.icon.font_data.size), - config.icon.size, &icons_config, icons_ranges); - } + io.Fonts->AddFontFromMemoryTTF(config.icon.font_data.ptr, to_i32(config.icon.font_data.size), + config.icon.size, &icons_config, icons_ranges); + } - io.RenderDrawListsFn = nullptr; - io.SetClipboardTextFn = set_clipboard_text; - io.GetClipboardTextFn = get_clipboard_text; - io.ClipboardUserData = window; + io.RenderDrawListsFn = nullptr; + io.SetClipboardTextFn = set_clipboard_text; + io.GetClipboardTextFn = get_clipboard_text; + io.ClipboardUserData = window; #if defined(_WIN32) - io.ImeWindowHandle = (void*)glfwGetWin32Window(window); + io.ImeWindowHandle = (void*) glfwGetWin32Window(window); #endif // _WIN32 - mouse_cursors.resize(ImGuiMouseCursor_Count_); - mouse_cursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); - mouse_cursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR); - mouse_cursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); - mouse_cursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR); - mouse_cursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR); - mouse_cursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); - mouse_cursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); - mouse_cursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR); - - glfwSetCharCallback(window, [](GLFWwindow*, unsigned int c) { - - if (c > 0 && c < 0x10000) - ImGui::GetIO().AddInputCharacter(static_cast<unsigned short>(c)); - }); - - set_ini_file(config.ini_file_dir); + mouse_cursors.resize(ImGuiMouseCursor_Count_); + mouse_cursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + mouse_cursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR); + mouse_cursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + mouse_cursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR); + mouse_cursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR); + mouse_cursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + mouse_cursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + mouse_cursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR); - on_key_event = [&](key_event const& event) { + glfwSetCharCallback(window, [](GLFWwindow*, unsigned int c) { + if (c > 0 && c < 0x10000) + ImGui::GetIO().AddInputCharacter(static_cast<unsigned short>(c)); + }); - if (activated()) - handle_key_event(to_i32(event.key), event.scancode, to_i32(event.action), to_i32(event.mod)); + set_ini_file(config.ini_file_dir); - return capture_keyboard(); - }; - - on_scroll_event = [&](scroll_event const& event) { + on_key_event = [&](key_event const& event) { + if (activated()) + handle_key_event(to_i32(event.key), event.scancode, to_i32(event.action), to_i32(event.mod)); - if (activated()) - handle_scroll_event(event.offset.x, event.offset.y); + return capture_keyboard(); + }; - return capture_mouse(); - }; + on_scroll_event = [&](scroll_event const& event) { + if (activated()) + handle_scroll_event(event.offset.x, event.offset.y); - on_mouse_button_event = [&](mouse_button_event const& event) { + return capture_mouse(); + }; - if (activated()) - handle_mouse_button_event(to_i32(event.button), to_i32(event.action), to_i32(event.mod)); + on_mouse_button_event = [&](mouse_button_event const& event) { + if (activated()) + handle_mouse_button_event(to_i32(event.button), to_i32(event.action), to_i32(event.mod)); - return capture_mouse(); - }; -} + return capture_mouse(); + }; + } -#define MAP_BUTTON(NAV_NO, BUTTON_NO) \ - { \ +#define MAP_BUTTON(NAV_NO, BUTTON_NO) \ + { \ if (buttons_count > BUTTON_NO && buttons[BUTTON_NO] == GLFW_PRESS) \ - io.NavInputs[NAV_NO] = 1.0f; \ + io.NavInputs[NAV_NO] = 1.0f; \ } -#define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) \ - { \ +#define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) \ + { \ float v = (axes_count > AXIS_NO) ? axes[AXIS_NO] : V0; \ - v = (v - V0) / (V1 - V0); \ - if (v > 1.f) \ - v = 1.f; \ - if (io.NavInputs[NAV_NO] < v) \ - io.NavInputs[NAV_NO] = v; \ + v = (v - V0) / (V1 - V0); \ + if (v > 1.f) \ + v = 1.f; \ + if (io.NavInputs[NAV_NO] < v) \ + io.NavInputs[NAV_NO] = v; \ } -void gui::new_frame() { - - auto& io = ImGui::GetIO(); - IM_ASSERT(io.Fonts->IsBuilt()); - - i32 w, h = 0; - i32 display_w, display_h = 0; - - glfwGetWindowSize(window, &w, &h); - glfwGetFramebufferSize(window, &display_w, &display_h); - io.DisplaySize = ImVec2((r32)w, (r32)h); - io.DisplayFramebufferScale = ImVec2(w > 0 ? ((r32)display_w / w) : 0, h > 0 ? ((r32)display_h / h) : 0); - - auto now = glfwGetTime(); - io.DeltaTime = current_time > 0.0 ? (r32)(now - current_time) : (1.f / 60.f); - current_time = now; - - update_mouse_pos_and_buttons(); - update_mouse_cursor(); - - memset(io.NavInputs, 0, sizeof(io.NavInputs)); - if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) { - - int axes_count = 0, buttons_count = 0; - float const* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &axes_count); - unsigned char const* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &buttons_count); - - MAP_BUTTON(ImGuiNavInput_Activate, 0); // Cross / A - MAP_BUTTON(ImGuiNavInput_Cancel, 1); // Circle / B - MAP_BUTTON(ImGuiNavInput_Menu, 2); // Square / X - MAP_BUTTON(ImGuiNavInput_Input, 3); // Triangle / Y - MAP_BUTTON(ImGuiNavInput_DpadLeft, 13); // D-Pad Left - MAP_BUTTON(ImGuiNavInput_DpadRight, 11); // D-Pad Right - MAP_BUTTON(ImGuiNavInput_DpadUp, 10); // D-Pad Up - MAP_BUTTON(ImGuiNavInput_DpadDown, 12); // D-Pad Down - MAP_BUTTON(ImGuiNavInput_FocusPrev, 4); // L1 / LB - MAP_BUTTON(ImGuiNavInput_FocusNext, 5); // R1 / RB - MAP_BUTTON(ImGuiNavInput_TweakSlow, 4); // L1 / LB - MAP_BUTTON(ImGuiNavInput_TweakFast, 5); // R1 / RB - MAP_ANALOG(ImGuiNavInput_LStickLeft, 0, -0.3f, -0.9f); - MAP_ANALOG(ImGuiNavInput_LStickRight, 0, +0.3f, +0.9f); - MAP_ANALOG(ImGuiNavInput_LStickUp, 1, +0.3f, +0.9f); - MAP_ANALOG(ImGuiNavInput_LStickDown, 1, -0.3f, -0.9f); - - if (axes_count > 0 && buttons_count > 0) - io.BackendFlags |= ImGuiBackendFlags_HasGamepad; - else - io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; - } + void gui::new_frame() { + auto& io = ImGui::GetIO(); + IM_ASSERT(io.Fonts->IsBuilt()); + + i32 w, h = 0; + i32 display_w, display_h = 0; + + glfwGetWindowSize(window, &w, &h); + glfwGetFramebufferSize(window, &display_w, &display_h); + io.DisplaySize = ImVec2((r32) w, (r32) h); + io.DisplayFramebufferScale = ImVec2(w > 0 ? ((r32) display_w / w) : 0, h > 0 ? ((r32) display_h / h) : 0); + + auto now = glfwGetTime(); + io.DeltaTime = current_time > 0.0 ? (r32)(now - current_time) : (1.f / 60.f); + current_time = now; + + update_mouse_pos_and_buttons(); + update_mouse_cursor(); + + memset(io.NavInputs, 0, sizeof(io.NavInputs)); + if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) { + int axes_count = 0, buttons_count = 0; + float const* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &axes_count); + unsigned char const* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &buttons_count); + + MAP_BUTTON(ImGuiNavInput_Activate, 0); // Cross / A + MAP_BUTTON(ImGuiNavInput_Cancel, 1); // Circle / B + MAP_BUTTON(ImGuiNavInput_Menu, 2); // Square / X + MAP_BUTTON(ImGuiNavInput_Input, 3); // Triangle / Y + MAP_BUTTON(ImGuiNavInput_DpadLeft, 13); // D-Pad Left + MAP_BUTTON(ImGuiNavInput_DpadRight, 11); // D-Pad Right + MAP_BUTTON(ImGuiNavInput_DpadUp, 10); // D-Pad Up + MAP_BUTTON(ImGuiNavInput_DpadDown, 12); // D-Pad Down + MAP_BUTTON(ImGuiNavInput_FocusPrev, 4); // L1 / LB + MAP_BUTTON(ImGuiNavInput_FocusNext, 5); // R1 / RB + MAP_BUTTON(ImGuiNavInput_TweakSlow, 4); // L1 / LB + MAP_BUTTON(ImGuiNavInput_TweakFast, 5); // R1 / RB + MAP_ANALOG(ImGuiNavInput_LStickLeft, 0, -0.3f, -0.9f); + MAP_ANALOG(ImGuiNavInput_LStickRight, 0, +0.3f, +0.9f); + MAP_ANALOG(ImGuiNavInput_LStickUp, 1, +0.3f, +0.9f); + MAP_ANALOG(ImGuiNavInput_LStickDown, 1, -0.3f, -0.9f); + + if (axes_count > 0 && buttons_count > 0) + io.BackendFlags |= ImGuiBackendFlags_HasGamepad; + else + io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; + } - ImGui::NewFrame(); -} + ImGui::NewFrame(); + } #undef MAP_BUTTON #undef MAP_ANALOG -static ui32 imgui_vert_shader[] = { - - 0x07230203,0x00010000,0x00080007,0x0000002e,0x00000000,0x00020011,0x00000001,0x0006000b, - 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, - 0x000a000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000b,0x0000000f,0x00000015, - 0x0000001b,0x0000001c,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d, - 0x00000000,0x00030005,0x00000009,0x00000000,0x00050006,0x00000009,0x00000000,0x6f6c6f43, - 0x00000072,0x00040006,0x00000009,0x00000001,0x00005655,0x00030005,0x0000000b,0x0074754f, - 0x00040005,0x0000000f,0x6c6f4361,0x0000726f,0x00030005,0x00000015,0x00565561,0x00060005, - 0x00000019,0x505f6c67,0x65567265,0x78657472,0x00000000,0x00060006,0x00000019,0x00000000, - 0x505f6c67,0x7469736f,0x006e6f69,0x00030005,0x0000001b,0x00000000,0x00040005,0x0000001c, - 0x736f5061,0x00000000,0x00060005,0x0000001e,0x73755075,0x6e6f4368,0x6e617473,0x00000074, - 0x00050006,0x0000001e,0x00000000,0x61635375,0x0000656c,0x00060006,0x0000001e,0x00000001, - 0x61725475,0x616c736e,0x00006574,0x00030005,0x00000020,0x00006370,0x00040047,0x0000000b, - 0x0000001e,0x00000000,0x00040047,0x0000000f,0x0000001e,0x00000002,0x00040047,0x00000015, - 0x0000001e,0x00000001,0x00050048,0x00000019,0x00000000,0x0000000b,0x00000000,0x00030047, - 0x00000019,0x00000002,0x00040047,0x0000001c,0x0000001e,0x00000000,0x00050048,0x0000001e, - 0x00000000,0x00000023,0x00000000,0x00050048,0x0000001e,0x00000001,0x00000023,0x00000008, - 0x00030047,0x0000001e,0x00000002,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002, - 0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040017, - 0x00000008,0x00000006,0x00000002,0x0004001e,0x00000009,0x00000007,0x00000008,0x00040020, - 0x0000000a,0x00000003,0x00000009,0x0004003b,0x0000000a,0x0000000b,0x00000003,0x00040015, - 0x0000000c,0x00000020,0x00000001,0x0004002b,0x0000000c,0x0000000d,0x00000000,0x00040020, - 0x0000000e,0x00000001,0x00000007,0x0004003b,0x0000000e,0x0000000f,0x00000001,0x00040020, - 0x00000011,0x00000003,0x00000007,0x0004002b,0x0000000c,0x00000013,0x00000001,0x00040020, - 0x00000014,0x00000001,0x00000008,0x0004003b,0x00000014,0x00000015,0x00000001,0x00040020, - 0x00000017,0x00000003,0x00000008,0x0003001e,0x00000019,0x00000007,0x00040020,0x0000001a, - 0x00000003,0x00000019,0x0004003b,0x0000001a,0x0000001b,0x00000003,0x0004003b,0x00000014, - 0x0000001c,0x00000001,0x0004001e,0x0000001e,0x00000008,0x00000008,0x00040020,0x0000001f, - 0x00000009,0x0000001e,0x0004003b,0x0000001f,0x00000020,0x00000009,0x00040020,0x00000021, - 0x00000009,0x00000008,0x0004002b,0x00000006,0x00000028,0x00000000,0x0004002b,0x00000006, - 0x00000029,0x3f800000,0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8, - 0x00000005,0x0004003d,0x00000007,0x00000010,0x0000000f,0x00050041,0x00000011,0x00000012, - 0x0000000b,0x0000000d,0x0003003e,0x00000012,0x00000010,0x0004003d,0x00000008,0x00000016, - 0x00000015,0x00050041,0x00000017,0x00000018,0x0000000b,0x00000013,0x0003003e,0x00000018, - 0x00000016,0x0004003d,0x00000008,0x0000001d,0x0000001c,0x00050041,0x00000021,0x00000022, - 0x00000020,0x0000000d,0x0004003d,0x00000008,0x00000023,0x00000022,0x00050085,0x00000008, - 0x00000024,0x0000001d,0x00000023,0x00050041,0x00000021,0x00000025,0x00000020,0x00000013, - 0x0004003d,0x00000008,0x00000026,0x00000025,0x00050081,0x00000008,0x00000027,0x00000024, - 0x00000026,0x00050051,0x00000006,0x0000002a,0x00000027,0x00000000,0x00050051,0x00000006, - 0x0000002b,0x00000027,0x00000001,0x00070050,0x00000007,0x0000002c,0x0000002a,0x0000002b, - 0x00000028,0x00000029,0x00050041,0x00000011,0x0000002d,0x0000001b,0x0000000d,0x0003003e, - 0x0000002d,0x0000002c,0x000100fd,0x00010038 -}; - -static ui32 imgui_frag_shader[] = { - - 0x07230203,0x00010000,0x00080007,0x0000001e,0x00000000,0x00020011,0x00000001,0x0006000b, - 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, - 0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000d,0x00030010, - 0x00000004,0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d, - 0x00000000,0x00040005,0x00000009,0x6c6f4366,0x0000726f,0x00030005,0x0000000b,0x00000000, - 0x00050006,0x0000000b,0x00000000,0x6f6c6f43,0x00000072,0x00040006,0x0000000b,0x00000001, - 0x00005655,0x00030005,0x0000000d,0x00006e49,0x00050005,0x00000016,0x78655473,0x65727574, - 0x00000000,0x00040047,0x00000009,0x0000001e,0x00000000,0x00040047,0x0000000d,0x0000001e, - 0x00000000,0x00040047,0x00000016,0x00000022,0x00000000,0x00040047,0x00000016,0x00000021, - 0x00000000,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006, - 0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,0x00000003, - 0x00000007,0x0004003b,0x00000008,0x00000009,0x00000003,0x00040017,0x0000000a,0x00000006, - 0x00000002,0x0004001e,0x0000000b,0x00000007,0x0000000a,0x00040020,0x0000000c,0x00000001, - 0x0000000b,0x0004003b,0x0000000c,0x0000000d,0x00000001,0x00040015,0x0000000e,0x00000020, - 0x00000001,0x0004002b,0x0000000e,0x0000000f,0x00000000,0x00040020,0x00000010,0x00000001, - 0x00000007,0x00090019,0x00000013,0x00000006,0x00000001,0x00000000,0x00000000,0x00000000, - 0x00000001,0x00000000,0x0003001b,0x00000014,0x00000013,0x00040020,0x00000015,0x00000000, - 0x00000014,0x0004003b,0x00000015,0x00000016,0x00000000,0x0004002b,0x0000000e,0x00000018, - 0x00000001,0x00040020,0x00000019,0x00000001,0x0000000a,0x00050036,0x00000002,0x00000004, - 0x00000000,0x00000003,0x000200f8,0x00000005,0x00050041,0x00000010,0x00000011,0x0000000d, - 0x0000000f,0x0004003d,0x00000007,0x00000012,0x00000011,0x0004003d,0x00000014,0x00000017, - 0x00000016,0x00050041,0x00000019,0x0000001a,0x0000000d,0x00000018,0x0004003d,0x0000000a, - 0x0000001b,0x0000001a,0x00050057,0x00000007,0x0000001c,0x00000017,0x0000001b,0x00050085, - 0x00000007,0x0000001d,0x00000012,0x0000001c,0x0003003e,0x00000009,0x0000001d,0x000100fd, - 0x00010038 -}; - -bool gui::create(graphics_pipeline::ptr p, index mf) { - - pipeline = std::move(p); - - device = pipeline->get_device(); - max_frames = mf; - - for (auto i = 0u; i < max_frames; ++i) { - - vertex_buffers.push_back(make_buffer()); - index_buffers.push_back(make_buffer()); - } - - pipeline->set_vertex_input_binding({ 0, sizeof(ImDrawVert), VK_VERTEX_INPUT_RATE_VERTEX }); - pipeline->set_vertex_input_attributes({ - { 0, 0, VK_FORMAT_R32G32_SFLOAT, to_ui32(offsetof(ImDrawVert, pos)) }, - { 1, 0, VK_FORMAT_R32G32_SFLOAT, to_ui32(offsetof(ImDrawVert, uv)) }, - { 2, 0, VK_FORMAT_R8G8B8A8_UNORM, to_ui32(offsetof(ImDrawVert, col)) }, - }); - - if (!pipeline->add_shader({ imgui_vert_shader, sizeof(imgui_vert_shader) }, VK_SHADER_STAGE_VERTEX_BIT)) - return false; - - if (!pipeline->add_shader({ imgui_frag_shader, sizeof(imgui_frag_shader) }, VK_SHADER_STAGE_FRAGMENT_BIT)) - return false; - - pipeline->add_color_blend_attachment(); - - descriptor = make_descriptor(); - descriptor->add_binding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT); - if (!descriptor->create(device)) - return false; - - layout = make_pipeline_layout(); - layout->add(descriptor); - layout->add({ VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(r32) * 4 }); - - if (!layout->create(device)) - return false; - - pipeline->set_layout(layout); - pipeline->set_auto_size(false); - - descriptor_set = descriptor->allocate(); - - pipeline->on_process = [&](VkCommandBuffer cmd_buf) { - - if (!activated() || !on_draw) - return; - - new_frame(); - - if (on_draw) - on_draw(); - - render(cmd_buf); + static ui32 imgui_vert_shader[] = { + + 0x07230203, 0x00010000, 0x00080007, 0x0000002e, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, + 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, + 0x000a000f, 0x00000000, 0x00000004, 0x6e69616d, 0x00000000, 0x0000000b, 0x0000000f, 0x00000015, + 0x0000001b, 0x0000001c, 0x00030003, 0x00000002, 0x000001c2, 0x00040005, 0x00000004, 0x6e69616d, + 0x00000000, 0x00030005, 0x00000009, 0x00000000, 0x00050006, 0x00000009, 0x00000000, 0x6f6c6f43, + 0x00000072, 0x00040006, 0x00000009, 0x00000001, 0x00005655, 0x00030005, 0x0000000b, 0x0074754f, + 0x00040005, 0x0000000f, 0x6c6f4361, 0x0000726f, 0x00030005, 0x00000015, 0x00565561, 0x00060005, + 0x00000019, 0x505f6c67, 0x65567265, 0x78657472, 0x00000000, 0x00060006, 0x00000019, 0x00000000, + 0x505f6c67, 0x7469736f, 0x006e6f69, 0x00030005, 0x0000001b, 0x00000000, 0x00040005, 0x0000001c, + 0x736f5061, 0x00000000, 0x00060005, 0x0000001e, 0x73755075, 0x6e6f4368, 0x6e617473, 0x00000074, + 0x00050006, 0x0000001e, 0x00000000, 0x61635375, 0x0000656c, 0x00060006, 0x0000001e, 0x00000001, + 0x61725475, 0x616c736e, 0x00006574, 0x00030005, 0x00000020, 0x00006370, 0x00040047, 0x0000000b, + 0x0000001e, 0x00000000, 0x00040047, 0x0000000f, 0x0000001e, 0x00000002, 0x00040047, 0x00000015, + 0x0000001e, 0x00000001, 0x00050048, 0x00000019, 0x00000000, 0x0000000b, 0x00000000, 0x00030047, + 0x00000019, 0x00000002, 0x00040047, 0x0000001c, 0x0000001e, 0x00000000, 0x00050048, 0x0000001e, + 0x00000000, 0x00000023, 0x00000000, 0x00050048, 0x0000001e, 0x00000001, 0x00000023, 0x00000008, + 0x00030047, 0x0000001e, 0x00000002, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, + 0x00030016, 0x00000006, 0x00000020, 0x00040017, 0x00000007, 0x00000006, 0x00000004, 0x00040017, + 0x00000008, 0x00000006, 0x00000002, 0x0004001e, 0x00000009, 0x00000007, 0x00000008, 0x00040020, + 0x0000000a, 0x00000003, 0x00000009, 0x0004003b, 0x0000000a, 0x0000000b, 0x00000003, 0x00040015, + 0x0000000c, 0x00000020, 0x00000001, 0x0004002b, 0x0000000c, 0x0000000d, 0x00000000, 0x00040020, + 0x0000000e, 0x00000001, 0x00000007, 0x0004003b, 0x0000000e, 0x0000000f, 0x00000001, 0x00040020, + 0x00000011, 0x00000003, 0x00000007, 0x0004002b, 0x0000000c, 0x00000013, 0x00000001, 0x00040020, + 0x00000014, 0x00000001, 0x00000008, 0x0004003b, 0x00000014, 0x00000015, 0x00000001, 0x00040020, + 0x00000017, 0x00000003, 0x00000008, 0x0003001e, 0x00000019, 0x00000007, 0x00040020, 0x0000001a, + 0x00000003, 0x00000019, 0x0004003b, 0x0000001a, 0x0000001b, 0x00000003, 0x0004003b, 0x00000014, + 0x0000001c, 0x00000001, 0x0004001e, 0x0000001e, 0x00000008, 0x00000008, 0x00040020, 0x0000001f, + 0x00000009, 0x0000001e, 0x0004003b, 0x0000001f, 0x00000020, 0x00000009, 0x00040020, 0x00000021, + 0x00000009, 0x00000008, 0x0004002b, 0x00000006, 0x00000028, 0x00000000, 0x0004002b, 0x00000006, + 0x00000029, 0x3f800000, 0x00050036, 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, + 0x00000005, 0x0004003d, 0x00000007, 0x00000010, 0x0000000f, 0x00050041, 0x00000011, 0x00000012, + 0x0000000b, 0x0000000d, 0x0003003e, 0x00000012, 0x00000010, 0x0004003d, 0x00000008, 0x00000016, + 0x00000015, 0x00050041, 0x00000017, 0x00000018, 0x0000000b, 0x00000013, 0x0003003e, 0x00000018, + 0x00000016, 0x0004003d, 0x00000008, 0x0000001d, 0x0000001c, 0x00050041, 0x00000021, 0x00000022, + 0x00000020, 0x0000000d, 0x0004003d, 0x00000008, 0x00000023, 0x00000022, 0x00050085, 0x00000008, + 0x00000024, 0x0000001d, 0x00000023, 0x00050041, 0x00000021, 0x00000025, 0x00000020, 0x00000013, + 0x0004003d, 0x00000008, 0x00000026, 0x00000025, 0x00050081, 0x00000008, 0x00000027, 0x00000024, + 0x00000026, 0x00050051, 0x00000006, 0x0000002a, 0x00000027, 0x00000000, 0x00050051, 0x00000006, + 0x0000002b, 0x00000027, 0x00000001, 0x00070050, 0x00000007, 0x0000002c, 0x0000002a, 0x0000002b, + 0x00000028, 0x00000029, 0x00050041, 0x00000011, 0x0000002d, 0x0000001b, 0x0000000d, 0x0003003e, + 0x0000002d, 0x0000002c, 0x000100fd, 0x00010038 }; - initialized = true; - - return true; -} - -void gui::destroy() { - - if (!initialized) - return; - - for (auto& mouse_cursor : mouse_cursors) { - - glfwDestroyCursor(mouse_cursor); - mouse_cursor = nullptr; - } + static ui32 imgui_frag_shader[] = { + + 0x07230203, 0x00010000, 0x00080007, 0x0000001e, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, + 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, + 0x0007000f, 0x00000004, 0x00000004, 0x6e69616d, 0x00000000, 0x00000009, 0x0000000d, 0x00030010, + 0x00000004, 0x00000007, 0x00030003, 0x00000002, 0x000001c2, 0x00040005, 0x00000004, 0x6e69616d, + 0x00000000, 0x00040005, 0x00000009, 0x6c6f4366, 0x0000726f, 0x00030005, 0x0000000b, 0x00000000, + 0x00050006, 0x0000000b, 0x00000000, 0x6f6c6f43, 0x00000072, 0x00040006, 0x0000000b, 0x00000001, + 0x00005655, 0x00030005, 0x0000000d, 0x00006e49, 0x00050005, 0x00000016, 0x78655473, 0x65727574, + 0x00000000, 0x00040047, 0x00000009, 0x0000001e, 0x00000000, 0x00040047, 0x0000000d, 0x0000001e, + 0x00000000, 0x00040047, 0x00000016, 0x00000022, 0x00000000, 0x00040047, 0x00000016, 0x00000021, + 0x00000000, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00030016, 0x00000006, + 0x00000020, 0x00040017, 0x00000007, 0x00000006, 0x00000004, 0x00040020, 0x00000008, 0x00000003, + 0x00000007, 0x0004003b, 0x00000008, 0x00000009, 0x00000003, 0x00040017, 0x0000000a, 0x00000006, + 0x00000002, 0x0004001e, 0x0000000b, 0x00000007, 0x0000000a, 0x00040020, 0x0000000c, 0x00000001, + 0x0000000b, 0x0004003b, 0x0000000c, 0x0000000d, 0x00000001, 0x00040015, 0x0000000e, 0x00000020, + 0x00000001, 0x0004002b, 0x0000000e, 0x0000000f, 0x00000000, 0x00040020, 0x00000010, 0x00000001, + 0x00000007, 0x00090019, 0x00000013, 0x00000006, 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000000, 0x0003001b, 0x00000014, 0x00000013, 0x00040020, 0x00000015, 0x00000000, + 0x00000014, 0x0004003b, 0x00000015, 0x00000016, 0x00000000, 0x0004002b, 0x0000000e, 0x00000018, + 0x00000001, 0x00040020, 0x00000019, 0x00000001, 0x0000000a, 0x00050036, 0x00000002, 0x00000004, + 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x00050041, 0x00000010, 0x00000011, 0x0000000d, + 0x0000000f, 0x0004003d, 0x00000007, 0x00000012, 0x00000011, 0x0004003d, 0x00000014, 0x00000017, + 0x00000016, 0x00050041, 0x00000019, 0x0000001a, 0x0000000d, 0x00000018, 0x0004003d, 0x0000000a, + 0x0000001b, 0x0000001a, 0x00050057, 0x00000007, 0x0000001c, 0x00000017, 0x0000001b, 0x00050085, + 0x00000007, 0x0000001d, 0x00000012, 0x0000001c, 0x0003003e, 0x00000009, 0x0000001d, 0x000100fd, + 0x00010038 + }; - invalidate_device_objects(); - ImGui::DestroyContext(); + bool gui::create(graphics_pipeline::ptr p, index mf) { + pipeline = std::move(p); - initialized = false; -} + device = pipeline->get_device(); + max_frames = mf; -bool gui::capture_mouse() const { + for (auto i = 0u; i < max_frames; ++i) { + vertex_buffers.push_back(make_buffer()); + index_buffers.push_back(make_buffer()); + } - return ImGui::GetIO().WantCaptureMouse; -} + pipeline->set_vertex_input_binding({ 0, sizeof(ImDrawVert), VK_VERTEX_INPUT_RATE_VERTEX }); + pipeline->set_vertex_input_attributes({ + { 0, 0, VK_FORMAT_R32G32_SFLOAT, to_ui32(offsetof(ImDrawVert, pos)) }, + { 1, 0, VK_FORMAT_R32G32_SFLOAT, to_ui32(offsetof(ImDrawVert, uv)) }, + { 2, 0, VK_FORMAT_R8G8B8A8_UNORM, to_ui32(offsetof(ImDrawVert, col)) }, + }); -bool gui::capture_keyboard() const { + if (!pipeline->add_shader({ imgui_vert_shader, sizeof(imgui_vert_shader) }, VK_SHADER_STAGE_VERTEX_BIT)) + return false; - return ImGui::GetIO().WantCaptureKeyboard; -} + if (!pipeline->add_shader({ imgui_frag_shader, sizeof(imgui_frag_shader) }, VK_SHADER_STAGE_FRAGMENT_BIT)) + return false; -void gui::set_ini_file(fs::path dir) { - - dir.append(_gui_file_); + pipeline->add_color_blend_attachment(); - ini_file = dir.string(); + descriptor = make_descriptor(); + descriptor->add_binding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT); + if (!descriptor->create(device)) + return false; - ImGui::GetIO().IniFilename = str(ini_file); -} + layout = make_pipeline_layout(); + layout->add(descriptor); + layout->add({ VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(r32) * 4 }); -void gui::invalidate_device_objects() { + if (!layout->create(device)) + return false; - vertex_buffers.clear(); - index_buffers.clear(); + pipeline->set_layout(layout); + pipeline->set_auto_size(false); - descriptor->free(descriptor_set); - descriptor->destroy(); - descriptor = nullptr; + descriptor_set = descriptor->allocate(); - pipeline = nullptr; + pipeline->on_process = [&](VkCommandBuffer cmd_buf) { + if (!activated() || !on_draw) + return; - layout->destroy(); - layout = nullptr; -} + new_frame(); -void gui::render(VkCommandBuffer cmd_buf) { + if (on_draw) + on_draw(); - ImGui::Render(); + render(cmd_buf); + }; - render_draw_lists(cmd_buf); + initialized = true; - frame = (frame + 1) % max_frames; -} + return true; + } -void gui::render_draw_lists(VkCommandBuffer cmd_buf) { + void gui::destroy() { + if (!initialized) + return; - auto draw_data = ImGui::GetDrawData(); - if (draw_data->TotalVtxCount == 0) - return; + for (auto& mouse_cursor : mouse_cursors) { + glfwDestroyCursor(mouse_cursor); + mouse_cursor = nullptr; + } - auto& io = ImGui::GetIO(); + invalidate_device_objects(); + ImGui::DestroyContext(); - auto vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); - if (!vertex_buffers[frame]->valid() || vertex_buffers[frame]->get_size() < vertex_size) { + initialized = false; + } - if (vertex_buffers[frame]->valid()) - vertex_buffers[frame]->destroy(); + bool gui::capture_mouse() const { + return ImGui::GetIO().WantCaptureMouse; + } - if (!vertex_buffers[frame]->create(device, nullptr, ((vertex_size - 1) / buffer_memory_alignment + 1) * buffer_memory_alignment, - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, true, VMA_MEMORY_USAGE_CPU_TO_GPU)) - return; + bool gui::capture_keyboard() const { + return ImGui::GetIO().WantCaptureKeyboard; } - auto index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); - if (!index_buffers[frame]->valid() || index_buffers[frame]->get_size() < index_size) { + void gui::set_ini_file(fs::path dir) { + dir.append(_gui_file_); - if (index_buffers[frame]->valid()) - index_buffers[frame]->destroy(); + ini_file = dir.string(); - if (!index_buffers[frame]->create(device, nullptr, ((index_size - 1) / buffer_memory_alignment + 1) * buffer_memory_alignment, - VK_BUFFER_USAGE_INDEX_BUFFER_BIT, true, VMA_MEMORY_USAGE_CPU_TO_GPU)) - return; + ImGui::GetIO().IniFilename = str(ini_file); } - auto vtx_dst = (ImDrawVert*)vertex_buffers[frame]->get_mapped_data(); - auto idx_dst = (ImDrawIdx*)index_buffers[frame]->get_mapped_data(); + void gui::invalidate_device_objects() { + vertex_buffers.clear(); + index_buffers.clear(); - for (auto i = 0; i < draw_data->CmdListsCount; ++i) { + descriptor->free(descriptor_set); + descriptor->destroy(); + descriptor = nullptr; - auto const* cmd_list = draw_data->CmdLists[i]; + pipeline = nullptr; - memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); - memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); - - vtx_dst += cmd_list->VtxBuffer.Size; - idx_dst += cmd_list->IdxBuffer.Size; + layout->destroy(); + layout = nullptr; } - VkMappedMemoryRange const vertex_range - { - .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, - .memory = vertex_buffers[frame]->get_device_memory(), - .offset = 0, - .size = VK_WHOLE_SIZE, - }; - - VkMappedMemoryRange const index_range - { - .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, - .memory = index_buffers[frame]->get_device_memory(), - .offset = 0, - .size = VK_WHOLE_SIZE, - }; + void gui::render(VkCommandBuffer cmd_buf) { + ImGui::Render(); - std::array<VkMappedMemoryRange, 2> const ranges = { vertex_range, index_range }; - check(device->call().vkFlushMappedMemoryRanges(device->get(), to_ui32(ranges.size()), ranges.data())); + render_draw_lists(cmd_buf); - layout->bind(cmd_buf, descriptor_set); - - std::array<VkDeviceSize, 1> const vertex_offset = { 0 }; - std::array<VkBuffer, 1> const buffers = { vertex_buffers[frame]->get() }; - device->call().vkCmdBindVertexBuffers(cmd_buf, 0, to_ui32(buffers.size()), buffers.data(), vertex_offset.data()); + frame = (frame + 1) % max_frames; + } - device->call().vkCmdBindIndexBuffer(cmd_buf, index_buffers[frame]->get(), 0, VK_INDEX_TYPE_UINT16); + void gui::render_draw_lists(VkCommandBuffer cmd_buf) { + auto draw_data = ImGui::GetDrawData(); + if (draw_data->TotalVtxCount == 0) + return; - VkViewport viewport; - viewport.x = 0; - viewport.y = 0; - viewport.width = ImGui::GetIO().DisplaySize.x; - viewport.height = ImGui::GetIO().DisplaySize.y; - viewport.minDepth = 0.f; - viewport.maxDepth = 1.f; + auto& io = ImGui::GetIO(); - std::array<VkViewport, 1> const viewports = { viewport }; - device->call().vkCmdSetViewport(cmd_buf, 0, to_ui32(viewports.size()), viewports.data()); + auto vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); + if (!vertex_buffers[frame]->valid() || vertex_buffers[frame]->get_size() < vertex_size) { + if (vertex_buffers[frame]->valid()) + vertex_buffers[frame]->destroy(); - float scale[2]; - scale[0] = 2.f / io.DisplaySize.x; - scale[1] = 2.f / io.DisplaySize.y; - device->call().vkCmdPushConstants(cmd_buf, layout->get(), VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale); - - float translate[2]; - translate[0] = -1.f; - translate[1] = -1.f; - device->call().vkCmdPushConstants(cmd_buf, layout->get(), VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); + if (!vertex_buffers[frame]->create(device, nullptr, ((vertex_size - 1) / buffer_memory_alignment + 1) * buffer_memory_alignment, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, true, VMA_MEMORY_USAGE_CPU_TO_GPU)) + return; + } - auto vtx_offset = 0u; - auto idx_offset = 0u; - for (auto i = 0; i < draw_data->CmdListsCount; ++i) { + auto index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); + if (!index_buffers[frame]->valid() || index_buffers[frame]->get_size() < index_size) { + if (index_buffers[frame]->valid()) + index_buffers[frame]->destroy(); - auto const* cmd_list = draw_data->CmdLists[i]; - for (auto c = 0; c < cmd_list->CmdBuffer.Size; ++c) { + if (!index_buffers[frame]->create(device, nullptr, ((index_size - 1) / buffer_memory_alignment + 1) * buffer_memory_alignment, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT, true, VMA_MEMORY_USAGE_CPU_TO_GPU)) + return; + } - auto const* cmd = &cmd_list->CmdBuffer[c]; - if (cmd->UserCallback) { + auto vtx_dst = (ImDrawVert*) vertex_buffers[frame]->get_mapped_data(); + auto idx_dst = (ImDrawIdx*) index_buffers[frame]->get_mapped_data(); - cmd->UserCallback(cmd_list, cmd); - } - else { + for (auto i = 0; i < draw_data->CmdListsCount; ++i) { + auto const* cmd_list = draw_data->CmdLists[i]; - VkRect2D scissor; - scissor.offset = { - (i32)(cmd->ClipRect.x) > 0 ? (i32)(cmd->ClipRect.x) : 0, - (i32)(cmd->ClipRect.y) > 0 ? (i32)(cmd->ClipRect.y) : 0 - }; - scissor.extent = { (ui32)(cmd->ClipRect.z - cmd->ClipRect.x), - (ui32)(cmd->ClipRect.w - cmd->ClipRect.y + 1) }; + memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); + memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); - std::array<VkRect2D, 1> const scissors = { scissor }; - device->call().vkCmdSetScissor(cmd_buf, 0, to_ui32(scissors.size()), scissors.data()); + vtx_dst += cmd_list->VtxBuffer.Size; + idx_dst += cmd_list->IdxBuffer.Size; + } - device->call().vkCmdDrawIndexed(cmd_buf, cmd->ElemCount, 1, idx_offset, vtx_offset, 0); + VkMappedMemoryRange const vertex_range{ + .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + .memory = vertex_buffers[frame]->get_device_memory(), + .offset = 0, + .size = VK_WHOLE_SIZE, + }; + + VkMappedMemoryRange const index_range{ + .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + .memory = index_buffers[frame]->get_device_memory(), + .offset = 0, + .size = VK_WHOLE_SIZE, + }; + + std::array<VkMappedMemoryRange, 2> const ranges = { vertex_range, index_range }; + check(device->call().vkFlushMappedMemoryRanges(device->get(), to_ui32(ranges.size()), ranges.data())); + + layout->bind(cmd_buf, descriptor_set); + + std::array<VkDeviceSize, 1> const vertex_offset = { 0 }; + std::array<VkBuffer, 1> const buffers = { vertex_buffers[frame]->get() }; + device->call().vkCmdBindVertexBuffers(cmd_buf, 0, to_ui32(buffers.size()), buffers.data(), vertex_offset.data()); + + device->call().vkCmdBindIndexBuffer(cmd_buf, index_buffers[frame]->get(), 0, VK_INDEX_TYPE_UINT16); + + VkViewport viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = ImGui::GetIO().DisplaySize.x; + viewport.height = ImGui::GetIO().DisplaySize.y; + viewport.minDepth = 0.f; + viewport.maxDepth = 1.f; + + std::array<VkViewport, 1> const viewports = { viewport }; + device->call().vkCmdSetViewport(cmd_buf, 0, to_ui32(viewports.size()), viewports.data()); + + float scale[2]; + scale[0] = 2.f / io.DisplaySize.x; + scale[1] = 2.f / io.DisplaySize.y; + device->call().vkCmdPushConstants(cmd_buf, layout->get(), VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale); + + float translate[2]; + translate[0] = -1.f; + translate[1] = -1.f; + device->call().vkCmdPushConstants(cmd_buf, layout->get(), VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); + + auto vtx_offset = 0u; + auto idx_offset = 0u; + for (auto i = 0; i < draw_data->CmdListsCount; ++i) { + auto const* cmd_list = draw_data->CmdLists[i]; + for (auto c = 0; c < cmd_list->CmdBuffer.Size; ++c) { + auto const* cmd = &cmd_list->CmdBuffer[c]; + if (cmd->UserCallback) { + cmd->UserCallback(cmd_list, cmd); + } else { + VkRect2D scissor; + scissor.offset = { + (i32)(cmd->ClipRect.x) > 0 ? (i32)(cmd->ClipRect.x) : 0, + (i32)(cmd->ClipRect.y) > 0 ? (i32)(cmd->ClipRect.y) : 0 + }; + scissor.extent = { (ui32)(cmd->ClipRect.z - cmd->ClipRect.x), + (ui32)(cmd->ClipRect.w - cmd->ClipRect.y + 1) }; + + std::array<VkRect2D, 1> const scissors = { scissor }; + device->call().vkCmdSetScissor(cmd_buf, 0, to_ui32(scissors.size()), scissors.data()); + + device->call().vkCmdDrawIndexed(cmd_buf, cmd->ElemCount, 1, idx_offset, vtx_offset, 0); + } + + idx_offset += cmd->ElemCount; } - idx_offset += cmd->ElemCount; + vtx_offset += cmd_list->VtxBuffer.Size; } - - vtx_offset += cmd_list->VtxBuffer.Size; } -} -bool gui::upload_fonts(texture::ptr texture) { + bool gui::upload_fonts(texture::ptr texture) { + uchar* pixels = nullptr; - uchar* pixels = nullptr; + auto width = 0; + auto height = 0; + ImGui::GetIO().Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - auto width = 0; - auto height = 0; - ImGui::GetIO().Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + if (!texture->create(device, { width, height }, VK_FORMAT_R8G8B8A8_UNORM)) + return false; - if (!texture->create(device, { width, height }, VK_FORMAT_R8G8B8A8_UNORM)) - return false; + auto upload_size = width * height * sizeof(char) * 4; + if (!texture->upload(pixels, upload_size)) + return false; - auto upload_size = width * height * sizeof(char) * 4; - if (!texture->upload(pixels, upload_size)) - return false; + VkWriteDescriptorSet const write_desc{ + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = descriptor_set, + .dstBinding = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = texture->get_info(), + }; - VkWriteDescriptorSet const write_desc - { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = descriptor_set, - .dstBinding = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .pImageInfo = texture->get_info(), - }; + device->vkUpdateDescriptorSets({ write_desc }); - device->vkUpdateDescriptorSets({ write_desc }); - - return true; -} + return true; + } -} // lava +} // namespace lava void lava::setup_font(gui::config& config, font::ref font) { - if (load_file_data(str(font.file), config.font_data)) { - config.font_size = font.size; log()->debug("load {}", str(font.file)); } if (load_file_data(str(font.icon_file), config.icon.font_data)) { - config.icon.size = font.icon_size; config.icon.font_data = config.icon.font_data; diff --git a/liblava/app/gui.hpp b/liblava/app/gui.hpp index bf06b83c8c1406790f33736060d8bc2c5cfc08fc..36682333dd6c919941320f9974d80df09f3cf436 100644 --- a/liblava/app/gui.hpp +++ b/liblava/app/gui.hpp @@ -4,8 +4,8 @@ #pragma once -#include <liblava/frame/input.hpp> #include <liblava/block/pipeline.hpp> +#include <liblava/frame/input.hpp> #include <liblava/resource/texture.hpp> // fwd @@ -14,131 +14,143 @@ struct GLFWcursor; namespace lava { -constexpr const r32 default_font_size = 18.f; -constexpr name _gui_file_ = "gui.ini"; - -struct gui : input_callback { - - explicit gui() = default; - explicit gui(GLFWwindow* window) { setup(window); } - ~gui() { destroy(); } - - struct icon_font { + constexpr const r32 default_font_size = 18.f; + constexpr name _gui_file_ = "gui.ini"; - data font_data; + struct gui : input_callback { + explicit gui() = default; + explicit gui(GLFWwindow* window) { + setup(window); + } + ~gui() { + destroy(); + } - ui16 range_begin = 0; - ui16 range_end = 0; + struct icon_font { + data font_data; - r32 size = default_font_size; - }; - - struct config { + ui16 range_begin = 0; + ui16 range_end = 0; - data font_data; - r32 font_size = default_font_size; + r32 size = default_font_size; + }; - icon_font icon; + struct config { + data font_data; + r32 font_size = default_font_size; - fs::path ini_file_dir; - }; + icon_font icon; - void setup(GLFWwindow* window, config config); - void setup(GLFWwindow* window) { setup(window, config()); } + fs::path ini_file_dir; + }; - bool create(graphics_pipeline::ptr pipeline, index max_frames); - bool create(device_ptr device, index max_frames) { - - return create(make_graphics_pipeline(device), max_frames); - } - bool create(device_ptr device, index max_frames, VkRenderPass pass) { + void setup(GLFWwindow* window, config config); + void setup(GLFWwindow* window) { + setup(window, config()); + } - if (!create(device, max_frames)) - return false; + bool create(graphics_pipeline::ptr pipeline, index max_frames); + bool create(device_ptr device, index max_frames) { + return create(make_graphics_pipeline(device), max_frames); + } + bool create(device_ptr device, index max_frames, VkRenderPass pass) { + if (!create(device, max_frames)) + return false; - return pipeline->create(pass); - } + return pipeline->create(pass); + } - bool upload_fonts(texture::ptr texture); - - void destroy(); + bool upload_fonts(texture::ptr texture); - bool ready() const { return initialized; } - graphics_pipeline::ptr get_pipeline() { return pipeline; } + void destroy(); - using draw_func = std::function<void()>; - draw_func on_draw; + bool ready() const { + return initialized; + } + graphics_pipeline::ptr get_pipeline() { + return pipeline; + } - bool capture_mouse() const; - bool capture_keyboard() const; + using draw_func = std::function<void()>; + draw_func on_draw; - void set_active(bool value = true) { active = value; } - bool activated() const { return active; } + bool capture_mouse() const; + bool capture_keyboard() const; - void toggle() { active = !active; } + void set_active(bool value = true) { + active = value; + } + bool activated() const { + return active; + } - void set_ini_file(fs::path dir); - fs::path get_ini_file() const { return fs::path(ini_file); } + void toggle() { + active = !active; + } -private: - void handle_key_event(i32 key, i32 scancode, i32 action, i32 mods); - void handle_mouse_button_event(i32 button, i32 action, i32 mods); - void handle_scroll_event(r64 x_offset, r64 y_offset); + void set_ini_file(fs::path dir); + fs::path get_ini_file() const { + return fs::path(ini_file); + } - void render_draw_lists(VkCommandBuffer cmd_buf); - void invalidate_device_objects(); + private: + void handle_key_event(i32 key, i32 scancode, i32 action, i32 mods); + void handle_mouse_button_event(i32 button, i32 action, i32 mods); + void handle_scroll_event(r64 x_offset, r64 y_offset); - void update_mouse_pos_and_buttons(); - void update_mouse_cursor(); + void render_draw_lists(VkCommandBuffer cmd_buf); + void invalidate_device_objects(); - void new_frame(); - void render(VkCommandBuffer cmd_buf); + void update_mouse_pos_and_buttons(); + void update_mouse_cursor(); - device_ptr device = nullptr; - bool initialized = false; + void new_frame(); + void render(VkCommandBuffer cmd_buf); - graphics_pipeline::ptr pipeline; - pipeline_layout::ptr layout; + device_ptr device = nullptr; + bool initialized = false; - size_t buffer_memory_alignment = 256; - index frame = 0; - index max_frames = 4; + graphics_pipeline::ptr pipeline; + pipeline_layout::ptr layout; - buffer::list vertex_buffers; - buffer::list index_buffers; + size_t buffer_memory_alignment = 256; + index frame = 0; + index max_frames = 4; - lava::descriptor::ptr descriptor; - VkDescriptorSet descriptor_set = 0; + buffer::list vertex_buffers; + buffer::list index_buffers; - GLFWwindow* window = nullptr; + lava::descriptor::ptr descriptor; + VkDescriptorSet descriptor_set = 0; - bool mouse_just_pressed[5] = { false, false, false, false, false }; - r64 current_time = 0.0; + GLFWwindow* window = nullptr; - std::vector<GLFWcursor*> mouse_cursors; + bool mouse_just_pressed[5] = { false, false, false, false, false }; + r64 current_time = 0.0; - string ini_file; + std::vector<GLFWcursor*> mouse_cursors; - bool active = true; -}; + string ini_file; -constexpr name _gui_font_path_ = "font/gui/"; -constexpr name _gui_font_icon_path_ = "font/icon/"; + bool active = true; + }; -struct font { + constexpr name _gui_font_path_ = "font/gui/"; + constexpr name _gui_font_icon_path_ = "font/icon/"; - using ref = font const&; + struct font { + using ref = font const&; - string file; - r32 size = 21.f; + string file; + r32 size = 21.f; - string icon_file; - r32 icon_size = 21.f; + string icon_file; + r32 icon_size = 21.f; - ui16 icon_range_begin = 0; - ui16 icon_range_end = 0; -}; + ui16 icon_range_begin = 0; + ui16 icon_range_end = 0; + }; -void setup_font(gui::config& config, font::ref font); + void setup_font(gui::config& config, font::ref font); -} // lava +} // namespace lava diff --git a/liblava/base.hpp b/liblava/base.hpp index ba1990caf85a8d452ce66a4fad519ffe053edc34..ac61ab1fe9a82222147b9737dcbe70bac6459f63 100644 --- a/liblava/base.hpp +++ b/liblava/base.hpp @@ -5,8 +5,8 @@ #pragma once #include <liblava/base/base.hpp> -#include <liblava/base/device_table.hpp> #include <liblava/base/device.hpp> +#include <liblava/base/device_table.hpp> #include <liblava/base/instance.hpp> #include <liblava/base/memory.hpp> #include <liblava/base/physical_device.hpp> diff --git a/liblava/base/base.cpp b/liblava/base/base.cpp index 4041e2e0bc112d49faa9925c9076da43565fbbf3..afc28d1958bd8042c38f3914955003ee45e7a76e 100644 --- a/liblava/base/base.cpp +++ b/liblava/base/base.cpp @@ -5,12 +5,10 @@ #include <liblava/base/base.hpp> bool lava::check(VkResult result) { - if (result == VK_SUCCESS) return true; if (result > 0) { - log()->critical("VkResult {}", to_string(result)); return false; } @@ -20,11 +18,11 @@ bool lava::check(VkResult result) { } lava::string lava::to_string(VkResult result) { - -#define RETURN_STR(result_code) case result_code: return string(#result_code); +#define RETURN_STR(result_code) \ + case result_code: \ + return string(#result_code); switch (result) { - RETURN_STR(VK_SUCCESS) RETURN_STR(VK_NOT_READY) RETURN_STR(VK_TIMEOUT) @@ -66,6 +64,5 @@ lava::string lava::to_string(VkResult result) { } lava::string lava::version_to_string(ui32 version) { - return fmt::format("{}.{}.{}", VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version), VK_VERSION_PATCH(version)); } diff --git a/liblava/base/base.hpp b/liblava/base/base.hpp index 6b0b13bbcc6e9cd27479893a8a1a46cf94353690..b02d7acc471cc3441f8685af531ed8dfd5e164e4 100644 --- a/liblava/base/base.hpp +++ b/liblava/base/base.hpp @@ -4,95 +4,100 @@ #pragma once -#include <liblava/util.hpp> #include <liblava/core/math.hpp> +#include <liblava/util.hpp> + +// clang-format off #define VK_NO_PROTOTYPES #include <vulkan/vulkan.h> - #include <volk.h> -namespace lava { - -using VkFormats = std::vector<VkFormat>; +// clang-format on -using VkImages = std::vector<VkImage>; -using VkImagesRef = VkImages const&; +namespace lava { -using VkImageViews = std::vector<VkImageView>; -using VkFramebuffers = std::vector<VkFramebuffer>; + using VkFormats = std::vector<VkFormat>; -using VkCommandPools = std::vector<VkCommandPool>; -using VkCommandBuffers = std::vector<VkCommandBuffer>; + using VkImages = std::vector<VkImage>; + using VkImagesRef = VkImages const&; -using VkFences = std::vector<VkFence>; -using VkSemaphores = std::vector<VkSemaphore>; + using VkImageViews = std::vector<VkImageView>; + using VkFramebuffers = std::vector<VkFramebuffer>; -using VkPresentModeKHRs = std::vector<VkPresentModeKHR>; + using VkCommandPools = std::vector<VkCommandPool>; + using VkCommandBuffers = std::vector<VkCommandBuffer>; -using VkDescriptorSets = std::vector<VkDescriptorSet>; -using VkDescriptorSetLayouts = std::vector<VkDescriptorSetLayout>; -using VkDescriptorSetLayoutBindings = std::vector<VkDescriptorSetLayoutBinding>; + using VkFences = std::vector<VkFence>; + using VkSemaphores = std::vector<VkSemaphore>; -using VkPushConstantRanges = std::vector<VkPushConstantRange>; + using VkPresentModeKHRs = std::vector<VkPresentModeKHR>; -using VkAttachmentReferences = std::vector<VkAttachmentReference>; + using VkDescriptorSets = std::vector<VkDescriptorSet>; + using VkDescriptorSetLayouts = std::vector<VkDescriptorSetLayout>; + using VkDescriptorSetLayoutBindings = std::vector<VkDescriptorSetLayoutBinding>; -using VkClearValues = std::vector<VkClearValue>; + using VkPushConstantRanges = std::vector<VkPushConstantRange>; -using VkPipelineShaderStageCreateInfos = std::vector<VkPipelineShaderStageCreateInfo>; -using VkSpecializationMapEntries = std::vector<VkSpecializationMapEntry>; + using VkAttachmentReferences = std::vector<VkAttachmentReference>; -using VkVertexInputBindingDescriptions = std::vector<VkVertexInputBindingDescription>; -using VkVertexInputAttributeDescriptions = std::vector<VkVertexInputAttributeDescription>; + using VkClearValues = std::vector<VkClearValue>; -using VkPipelineColorBlendAttachmentStates = std::vector<VkPipelineColorBlendAttachmentState>; -using VkDynamicStates = std::vector<VkDynamicState>; + using VkPipelineShaderStageCreateInfos = std::vector<VkPipelineShaderStageCreateInfo>; + using VkSpecializationMapEntries = std::vector<VkSpecializationMapEntry>; -using VkQueueFamilyPropertiesList = std::vector<VkQueueFamilyProperties>; -using VkExtensionPropertiesList = std::vector<VkExtensionProperties>; + using VkVertexInputBindingDescriptions = std::vector<VkVertexInputBindingDescription>; + using VkVertexInputAttributeDescriptions = std::vector<VkVertexInputAttributeDescription>; -using VkLayerPropertiesList = std::vector<VkLayerProperties>; -using VkExtensionPropertiesList = std::vector<VkExtensionProperties>; + using VkPipelineColorBlendAttachmentStates = std::vector<VkPipelineColorBlendAttachmentState>; + using VkDynamicStates = std::vector<VkDynamicState>; -using VkPhysicalDevices = std::vector<VkPhysicalDevice>; + using VkQueueFamilyPropertiesList = std::vector<VkQueueFamilyProperties>; + using VkExtensionPropertiesList = std::vector<VkExtensionProperties>; -bool check(VkResult result); -inline bool failed(VkResult result) { return !check(result); } + using VkLayerPropertiesList = std::vector<VkLayerProperties>; + using VkExtensionPropertiesList = std::vector<VkExtensionProperties>; -string to_string(VkResult result); -string version_to_string(ui32 version); + using VkPhysicalDevices = std::vector<VkPhysicalDevice>; -struct vk_result { + bool check(VkResult result); + inline bool failed(VkResult result) { + return !check(result); + } - bool state = false; - VkResult value = VK_NOT_READY; + string to_string(VkResult result); + string version_to_string(ui32 version); - operator bool() { return state; } -}; + struct vk_result { + bool state = false; + VkResult value = VK_NOT_READY; -using VkAttachments = std::vector<VkImageViews>; -using VkAttachmentsRef = VkAttachments const&; + operator bool() { + return state; + } + }; -struct target_callback { + using VkAttachments = std::vector<VkImageViews>; + using VkAttachmentsRef = VkAttachments const&; - using list = std::vector<target_callback*>; + struct target_callback { + using list = std::vector<target_callback*>; - using created_func = std::function<bool(VkAttachmentsRef, rect)>; - created_func on_created; + using created_func = std::function<bool(VkAttachmentsRef, rect)>; + created_func on_created; - using destroyed_func = std::function<void()>; - destroyed_func on_destroyed; -}; + using destroyed_func = std::function<void()>; + destroyed_func on_destroyed; + }; -// limits + // limits -static constexpr ui32 const Vk_Limit_DescriptorSets = 4; -static constexpr ui32 const Vk_Limit_Bindings = 16; -static constexpr ui32 const Vk_Limit_Attachments = 8; -static constexpr ui32 const Vk_Limit_VertexAttribs = 16; -static constexpr ui32 const Vk_Limit_VertexBuffers = 4; -static constexpr ui32 const Vk_Limit_PushConstant_Size = 128; -static constexpr ui32 const Vk_Limit_UBO_Size = 16 * 1024; + static constexpr ui32 const Vk_Limit_DescriptorSets = 4; + static constexpr ui32 const Vk_Limit_Bindings = 16; + static constexpr ui32 const Vk_Limit_Attachments = 8; + static constexpr ui32 const Vk_Limit_VertexAttribs = 16; + static constexpr ui32 const Vk_Limit_VertexBuffers = 4; + static constexpr ui32 const Vk_Limit_PushConstant_Size = 128; + static constexpr ui32 const Vk_Limit_UBO_Size = 16 * 1024; -} // lava +} // namespace lava diff --git a/liblava/base/device.cpp b/liblava/base/device.cpp index 2739a67d399f9dcf0f06c8b64ca708cdb8b5b0b0..ce40bdcc934b108e692018f4750c336105f8b559 100644 --- a/liblava/base/device.cpp +++ b/liblava/base/device.cpp @@ -8,211 +8,194 @@ namespace lava { -bool device::create(create_param::ref param) { - - physical_device = param.physical_device; - if (!physical_device) - return false; + bool device::create(create_param::ref param) { + physical_device = param.physical_device; + if (!physical_device) + return false; - std::vector<VkDeviceQueueCreateInfo> queue_create_info_list(param.queue_info_list.size()); + std::vector<VkDeviceQueueCreateInfo> queue_create_info_list(param.queue_info_list.size()); - for (size_t i = 0, e = param.queue_info_list.size(); i != e; ++i) { + for (size_t i = 0, e = param.queue_info_list.size(); i != e; ++i) { + queue_create_info_list[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_create_info_list[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + ui32 index = 0; + if (!physical_device->get_queue_family(index, param.queue_info_list[i].flags)) { + log()->error("create device queue family"); + return false; + } - ui32 index = 0; - if (!physical_device->get_queue_family(index, param.queue_info_list[i].flags)) { + queue_create_info_list[i].queueFamilyIndex = index; + queue_create_info_list[i].queueCount = param.queue_info_list[i].count(); + queue_create_info_list[i].pQueuePriorities = param.queue_info_list[i].priorities.data(); + } - log()->error("create device queue family"); + VkDeviceCreateInfo create_info{ + .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, + .pNext = param.next, + .queueCreateInfoCount = to_ui32(queue_create_info_list.size()), + .pQueueCreateInfos = queue_create_info_list.data(), + .enabledLayerCount = 0, + .ppEnabledLayerNames = nullptr, + .enabledExtensionCount = to_ui32(param.extensions.size()), + .ppEnabledExtensionNames = param.extensions.data(), + .pEnabledFeatures = ¶m.features, + }; + + if (failed(vkCreateDevice(physical_device->get(), &create_info, memory::alloc(), &vk_device))) { + log()->error("create device"); return false; } - queue_create_info_list[i].queueFamilyIndex = index; - queue_create_info_list[i].queueCount = param.queue_info_list[i].count(); - queue_create_info_list[i].pQueuePriorities = param.queue_info_list[i].priorities.data(); - } - - VkDeviceCreateInfo create_info - { - .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - .pNext = param.next, - .queueCreateInfoCount = to_ui32(queue_create_info_list.size()), - .pQueueCreateInfos = queue_create_info_list.data(), - .enabledLayerCount = 0, - .ppEnabledLayerNames = nullptr, - .enabledExtensionCount = to_ui32(param.extensions.size()), - .ppEnabledExtensionNames = param.extensions.data(), - .pEnabledFeatures = ¶m.features, - }; - - if (failed(vkCreateDevice(physical_device->get(), &create_info, memory::alloc(), &vk_device))) { + features = param.features; - log()->error("create device"); - return false; - } - - features = param.features; - - load_table(); - - graphics_queue_list.clear(); - compute_queue_list.clear(); - transfer_queue_list.clear(); + load_table(); - index_map queue_family_map; + graphics_queue_list.clear(); + compute_queue_list.clear(); + transfer_queue_list.clear(); - for (size_t i = 0, ei = queue_create_info_list.size(); i != ei; ++i) { + index_map queue_family_map; - if (!queue_family_map.count(queue_create_info_list[i].queueFamilyIndex)) - queue_family_map.emplace(queue_create_info_list[i].queueFamilyIndex, 0); + for (size_t i = 0, ei = queue_create_info_list.size(); i != ei; ++i) { + if (!queue_family_map.count(queue_create_info_list[i].queueFamilyIndex)) + queue_family_map.emplace(queue_create_info_list[i].queueFamilyIndex, 0); - for (size_t j = 0, ej = queue_create_info_list[i].queueCount; j != ej; ++j) { + for (size_t j = 0, ej = queue_create_info_list[i].queueCount; j != ej; ++j) { + auto counter = queue_family_map[queue_create_info_list[i].queueFamilyIndex]; + queue_family_map[queue_create_info_list[i].queueFamilyIndex]++; - auto counter = queue_family_map[queue_create_info_list[i].queueFamilyIndex]; - queue_family_map[queue_create_info_list[i].queueFamilyIndex]++; + VkQueue queue = nullptr; + call().vkGetDeviceQueue(vk_device, queue_create_info_list[i].queueFamilyIndex, counter, &queue); - VkQueue queue = nullptr; - call().vkGetDeviceQueue(vk_device, queue_create_info_list[i].queueFamilyIndex, counter, &queue); - - if (param.queue_info_list[i].flags & VK_QUEUE_GRAPHICS_BIT) - graphics_queue_list.push_back({ queue, queue_create_info_list[i].queueFamilyIndex }); - if (param.queue_info_list[i].flags & VK_QUEUE_COMPUTE_BIT) - compute_queue_list.push_back({ queue, queue_create_info_list[i].queueFamilyIndex }); - if (param.queue_info_list[i].flags & VK_QUEUE_TRANSFER_BIT) - transfer_queue_list.push_back({ queue, queue_create_info_list[i].queueFamilyIndex }); + if (param.queue_info_list[i].flags & VK_QUEUE_GRAPHICS_BIT) + graphics_queue_list.push_back({ queue, queue_create_info_list[i].queueFamilyIndex }); + if (param.queue_info_list[i].flags & VK_QUEUE_COMPUTE_BIT) + compute_queue_list.push_back({ queue, queue_create_info_list[i].queueFamilyIndex }); + if (param.queue_info_list[i].flags & VK_QUEUE_TRANSFER_BIT) + transfer_queue_list.push_back({ queue, queue_create_info_list[i].queueFamilyIndex }); + } } - } - - return create_descriptor_pool(); -} - -void device::destroy() { - - if (!vk_device) - return; - - graphics_queue_list.clear(); - compute_queue_list.clear(); - transfer_queue_list.clear(); - - call().vkDestroyDescriptorPool(vk_device, descriptor_pool, memory::alloc()); - descriptor_pool = 0; - - mem_allocator = nullptr; - - call().vkDestroyDevice(vk_device, memory::alloc()); - vk_device = nullptr; - - table = {}; -} - -bool device::create_descriptor_pool() { - - auto const count = 11u; - auto const size = 1000u; - - VkDescriptorPoolSize const pool_size[count] = - { - { VK_DESCRIPTOR_TYPE_SAMPLER, size }, - { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, size }, - { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, size }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, size }, - { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, size }, - { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, size }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, size }, - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, size }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, size }, - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, size }, - { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, size }, - }; - - VkDescriptorPoolCreateInfo const pool_info - { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, - .maxSets = size * count, - .poolSizeCount = count, - .pPoolSizes = pool_size, - }; - return check(call().vkCreateDescriptorPool(vk_device, &pool_info, memory::alloc(), &descriptor_pool)); -} + return create_descriptor_pool(); + } -bool device::surface_supported(VkSurfaceKHR surface) const { + void device::destroy() { + if (!vk_device) + return; - return physical_device->surface_supported(get_graphics_queue().family, surface); -} + graphics_queue_list.clear(); + compute_queue_list.clear(); + transfer_queue_list.clear(); -VkPhysicalDevice device::get_vk_physical_device() const { + call().vkDestroyDescriptorPool(vk_device, descriptor_pool, memory::alloc()); + descriptor_pool = 0; - return physical_device->get(); -} + mem_allocator = nullptr; -VkPhysicalDeviceFeatures const& device::get_features() const { return features; } + call().vkDestroyDevice(vk_device, memory::alloc()); + vk_device = nullptr; -VkPhysicalDeviceProperties const& device::get_properties() const { return physical_device->get_properties(); } - -device::ptr device_manager::create(index pd) { + table = {}; + } - auto physical_device = &instance::get_first_physical_device(); + bool device::create_descriptor_pool() { + auto const count = 11u; + auto const size = 1000u; + + VkDescriptorPoolSize const pool_size[count] = { + { VK_DESCRIPTOR_TYPE_SAMPLER, size }, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, size }, + { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, size }, + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, size }, + { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, size }, + { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, size }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, size }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, size }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, size }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, size }, + { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, size }, + }; + + VkDescriptorPoolCreateInfo const pool_info{ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, + .maxSets = size * count, + .poolSizeCount = count, + .pPoolSizes = pool_size, + }; + + return check(call().vkCreateDescriptorPool(vk_device, &pool_info, memory::alloc(), &descriptor_pool)); + } - if (pd > 0) { + bool device::surface_supported(VkSurfaceKHR surface) const { + return physical_device->surface_supported(get_graphics_queue().family, surface); + } - if (pd >= instance::singleton().get_physical_devices().size()) { + VkPhysicalDevice device::get_vk_physical_device() const { + return physical_device->get(); + } - log()->error("create device - no physical device {}", pd); - return nullptr; - } + VkPhysicalDeviceFeatures const& device::get_features() const { + return features; + } - physical_device = &instance::singleton().get_physical_devices().at(pd); + VkPhysicalDeviceProperties const& device::get_properties() const { + return physical_device->get_properties(); } - if (!physical_device->swapchain_supported()) - return nullptr; + device::ptr device_manager::create(index pd) { + auto physical_device = &instance::get_first_physical_device(); - auto param = physical_device->create_default_device_param(); - if (on_create_param) - on_create_param(param); + if (pd > 0) { + if (pd >= instance::singleton().get_physical_devices().size()) { + log()->error("create device - no physical device {}", pd); + return nullptr; + } - return create(param); -} + physical_device = &instance::singleton().get_physical_devices().at(pd); + } -device::ptr device_manager::create(device::create_param::ref param) { + if (!physical_device->swapchain_supported()) + return nullptr; - auto result = std::make_shared<device>(); - if (!result->create(param)) - return nullptr; + auto param = physical_device->create_default_device_param(); + if (on_create_param) + on_create_param(param); - auto allocator = make_allocator(result->get_vk_physical_device(), result->get()); - if (!allocator) - return nullptr; + return create(param); + } - result->set_allocator(allocator); + device::ptr device_manager::create(device::create_param::ref param) { + auto result = std::make_shared<device>(); + if (!result->create(param)) + return nullptr; - list.push_back(result); - return result; -} + auto allocator = make_allocator(result->get_vk_physical_device(), result->get()); + if (!allocator) + return nullptr; -void device_manager::wait_idle() { + result->set_allocator(allocator); - for (auto& device : list) - device->wait_for_idle(); -} + list.push_back(result); + return result; + } -void device_manager::clear() { + void device_manager::wait_idle() { + for (auto& device : list) + device->wait_for_idle(); + } - for (auto& device : list) - device->destroy(); + void device_manager::clear() { + for (auto& device : list) + device->destroy(); - list.clear(); -} + list.clear(); + } -} // lava +} // namespace lava VkShaderModule lava::create_shader_module(device_ptr device, data const& data) { - - VkShaderModuleCreateInfo shader_module_create_info - { + VkShaderModuleCreateInfo shader_module_create_info{ .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, .codeSize = data.size, .pCode = reinterpret_cast<ui32*>(data.ptr), diff --git a/liblava/base/device.hpp b/liblava/base/device.hpp index bb302832b2eae39890da0fdf6e8cac3faf425b8f..4ab48d916ff304d6cc6f3b4a116964e00cd794a8 100644 --- a/liblava/base/device.hpp +++ b/liblava/base/device.hpp @@ -8,141 +8,180 @@ namespace lava { -// fwd -struct physical_device; -using physical_device_cptr = physical_device const*; + // fwd + struct physical_device; + using physical_device_cptr = physical_device const*; -struct device : device_table { + struct device : device_table { + using ptr = std::shared_ptr<device>; + using list = std::vector<device::ptr>; - using ptr = std::shared_ptr<device>; - using list = std::vector<device::ptr>; + struct create_param { + using ref = create_param const&; - struct create_param { + physical_device_cptr physical_device = nullptr; - using ref = create_param const&; + struct queue_info { + using list = std::vector<queue_info>; - physical_device_cptr physical_device = nullptr; - - struct queue_info { + VkQueueFlags flags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT; - using list = std::vector<queue_info>; + using priority_list = std::vector<float>; + priority_list priorities; - VkQueueFlags flags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT; + ui32 count() const { + return to_ui32(priorities.size()); + } - using priority_list = std::vector<float>; - priority_list priorities; + explicit queue_info(ui32 count = 1) { + for (auto i = 0u; i < count; ++i) + priorities.push_back(1.f); + } + }; - ui32 count() const { return to_ui32(priorities.size()); } + queue_info::list queue_info_list; - explicit queue_info(ui32 count = 1) { + names extensions; + VkPhysicalDeviceFeatures features{}; + void const* next = nullptr; // pNext - for (auto i = 0u; i < count; ++i) - priorities.push_back(1.f); + void set_default_queues() { + extensions.push_back("VK_KHR_swapchain"); + queue_info_list.resize(1); } }; - queue_info::list queue_info_list; - - names extensions; - VkPhysicalDeviceFeatures features{}; - void const* next = nullptr; // pNext - - void set_default_queues() { - - extensions.push_back("VK_KHR_swapchain"); - queue_info_list.resize(1); + ~device() { + destroy(); } - }; - - ~device() { destroy(); } - - bool create(create_param::ref param); - void destroy(); - - struct queue { - using list = std::vector<queue>; - using ref = queue const&; + bool create(create_param::ref param); + void destroy(); - VkQueue vk_queue = nullptr; - index family = 0; - }; + struct queue { + using list = std::vector<queue>; + using ref = queue const&; - queue::ref get_graphics_queue(index index = 0) const { return get_graphics_queues().at(index); } - queue::ref graphics_queue(index index = 0) const { return get_graphics_queue(index); } + VkQueue vk_queue = nullptr; + index family = 0; + }; - queue::ref get_compute_queue(index index = 0) const { return get_compute_queues().at(index); } - queue::ref compute_queue(index index = 0) const { return get_compute_queue(index); } + queue::ref get_graphics_queue(index index = 0) const { + return get_graphics_queues().at(index); + } + queue::ref graphics_queue(index index = 0) const { + return get_graphics_queue(index); + } - queue::ref get_transfer_queue(index index = 0) const { return get_transfer_queues().at(index); } - queue::ref transfer_queue(index index = 0) const { return get_transfer_queue(index); } + queue::ref get_compute_queue(index index = 0) const { + return get_compute_queues().at(index); + } + queue::ref compute_queue(index index = 0) const { + return get_compute_queue(index); + } - queue::list const& get_graphics_queues() const { return graphics_queue_list; } - queue::list const& graphics_queues() const { return get_graphics_queues(); } + queue::ref get_transfer_queue(index index = 0) const { + return get_transfer_queues().at(index); + } + queue::ref transfer_queue(index index = 0) const { + return get_transfer_queue(index); + } - queue::list const& get_compute_queues() const { return compute_queue_list; } - queue::list const& compute_queues() const { return get_compute_queues(); } + queue::list const& get_graphics_queues() const { + return graphics_queue_list; + } + queue::list const& graphics_queues() const { + return get_graphics_queues(); + } - queue::list const& get_transfer_queues() const { return transfer_queue_list; } - queue::list const& transfer_queues() const { return get_transfer_queues(); } + queue::list const& get_compute_queues() const { + return compute_queue_list; + } + queue::list const& compute_queues() const { + return get_compute_queues(); + } - VkDevice get() const { return vk_device; } - VolkDeviceTable const& call() const { return table; } + queue::list const& get_transfer_queues() const { + return transfer_queue_list; + } + queue::list const& transfer_queues() const { + return get_transfer_queues(); + } - bool wait_for_idle() const { return check(call().vkDeviceWaitIdle(vk_device)); } + VkDevice get() const { + return vk_device; + } + VolkDeviceTable const& call() const { + return table; + } - VkDescriptorPool get_descriptor_pool() const { return descriptor_pool; } + bool wait_for_idle() const { + return check(call().vkDeviceWaitIdle(vk_device)); + } - physical_device_cptr get_physical_device() const { return physical_device; } - VkPhysicalDevice get_vk_physical_device() const; + VkDescriptorPool get_descriptor_pool() const { + return descriptor_pool; + } - VkPhysicalDeviceFeatures const& get_features() const; - VkPhysicalDeviceProperties const& get_properties() const; + physical_device_cptr get_physical_device() const { + return physical_device; + } + VkPhysicalDevice get_vk_physical_device() const; - bool surface_supported(VkSurfaceKHR surface) const; + VkPhysicalDeviceFeatures const& get_features() const; + VkPhysicalDeviceProperties const& get_properties() const; - void set_allocator(allocator::ptr value) { mem_allocator = value; } - allocator::ptr get_allocator() { return mem_allocator; } + bool surface_supported(VkSurfaceKHR surface) const; - VmaAllocator alloc() const { return mem_allocator != nullptr ? mem_allocator->get() : nullptr; } + void set_allocator(allocator::ptr value) { + mem_allocator = value; + } + allocator::ptr get_allocator() { + return mem_allocator; + } -private: - bool create_descriptor_pool(); + VmaAllocator alloc() const { + return mem_allocator != nullptr ? mem_allocator->get() : nullptr; + } - physical_device_cptr physical_device = nullptr; + private: + bool create_descriptor_pool(); - VkDescriptorPool descriptor_pool = 0; + physical_device_cptr physical_device = nullptr; - device::queue::list graphics_queue_list; - device::queue::list compute_queue_list; - device::queue::list transfer_queue_list; + VkDescriptorPool descriptor_pool = 0; - VkPhysicalDeviceFeatures features; + device::queue::list graphics_queue_list; + device::queue::list compute_queue_list; + device::queue::list transfer_queue_list; - allocator::ptr mem_allocator; -}; + VkPhysicalDeviceFeatures features; -struct device_manager { + allocator::ptr mem_allocator; + }; - device::ptr create(index physical_device = 0); + struct device_manager { + device::ptr create(index physical_device = 0); - device::ptr create(device::create_param::ref param); + device::ptr create(device::create_param::ref param); - device::list const& get_all() const { return list; } + device::list const& get_all() const { + return list; + } - void wait_idle(); + void wait_idle(); - void clear(); + void clear(); - using create_param_func = std::function<void(device::create_param&)>; - create_param_func on_create_param; + using create_param_func = std::function<void(device::create_param&)>; + create_param_func on_create_param; -private: - device::list list; -}; + private: + device::list list; + }; -using device_ptr = device*; + using device_ptr = device*; -VkShaderModule create_shader_module(device_ptr device, data const& data); + VkShaderModule create_shader_module(device_ptr device, data const& data); -} // lava +} // namespace lava diff --git a/liblava/base/device_table.hpp b/liblava/base/device_table.hpp index c78a929c8b6aefc464faa576507842f964366f45..2db416605097a76f7afe13065b71b8129358bda6 100644 --- a/liblava/base/device_table.hpp +++ b/liblava/base/device_table.hpp @@ -8,238 +8,197 @@ namespace lava { -struct device_table : id_obj, no_copy_no_move { - - void load_table() { - - volkLoadDeviceTable(&table, vk_device); - } - - vk_result vkCreateImageView(const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView) { - - auto result = table.vkCreateImageView(vk_device, pCreateInfo, pAllocator, pView); - return { check(result), result }; - } - - vk_result vkCreateImageView(const VkImageViewCreateInfo* pCreateInfo, VkImageView* pView) { - - return vkCreateImageView(pCreateInfo, memory::alloc(), pView); - } - - vk_result vkCreateSampler(const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler) { - - auto result = table.vkCreateSampler(vk_device, pCreateInfo, pAllocator, pSampler); - return { check(result), result }; - } - - vk_result vkCreateSampler(const VkSamplerCreateInfo* pCreateInfo, VkSampler* pSampler) { - - return vkCreateSampler(pCreateInfo, memory::alloc(), pSampler); - } - - vk_result vkCreateShaderModule(const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule) { - - auto result = table.vkCreateShaderModule(vk_device, pCreateInfo, pAllocator, pShaderModule); - return { check(result), result }; - } - - vk_result vkCreateShaderModule(const VkShaderModuleCreateInfo* pCreateInfo, VkShaderModule* pShaderModule) { - - return vkCreateShaderModule(pCreateInfo, memory::alloc(), pShaderModule); - } - - vk_result vkCreateFence(const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence) { - - auto result = table.vkCreateFence(vk_device, pCreateInfo, pAllocator, pFence); - return { check(result), result }; - } - - vk_result vkCreateFence(const VkFenceCreateInfo* pCreateInfo, VkFence* pFence) { - - return vkCreateFence(pCreateInfo, memory::alloc(), pFence); - } - - vk_result vkCreateSemaphore(const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore) { - - auto result = table.vkCreateSemaphore(vk_device, pCreateInfo, pAllocator, pSemaphore); - return { check(result), result }; - } - - vk_result vkCreateSemaphore(const VkSemaphoreCreateInfo* pCreateInfo, VkSemaphore* pSemaphore) { - - return vkCreateSemaphore(pCreateInfo, memory::alloc(), pSemaphore); - } - - vk_result vkWaitForFences(uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout) { - - auto result = table.vkWaitForFences(vk_device, fenceCount, pFences, waitAll, timeout); - if ((result == VK_TIMEOUT) && (timeout != UINT64_MAX)) - return { false, result }; - - return { check(result), result }; - } - - vk_result vkAcquireNextImageKHR(VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex) { - - auto result = table.vkAcquireNextImageKHR(vk_device, swapchain, timeout, semaphore, fence, pImageIndex); - return { check(result), result }; - } - - vk_result vkResetFences(uint32_t fenceCount, const VkFence* pFences) { - - auto result = table.vkResetFences(vk_device, fenceCount, pFences); - return { check(result), result }; - } - - vk_result vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence) { - - auto result = table.vkQueueSubmit(queue, submitCount, pSubmits, fence); - return { check(result), result }; - } - - vk_result vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo) { - - auto result = table.vkQueuePresentKHR(queue, pPresentInfo); - return { check(result), result }; - } - - vk_result vkCreateSwapchainKHR(const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain) { - - auto result = table.vkCreateSwapchainKHR(vk_device, pCreateInfo, pAllocator, pSwapchain); - return { check(result), result }; - } - - vk_result vkCreateSwapchainKHR(const VkSwapchainCreateInfoKHR* pCreateInfo, VkSwapchainKHR* pSwapchain) { - - return vkCreateSwapchainKHR(pCreateInfo, memory::alloc(), pSwapchain); - } - - vk_result vkGetSwapchainImagesKHR(VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages) { - - auto result = table.vkGetSwapchainImagesKHR(vk_device, swapchain, pSwapchainImageCount, pSwapchainImages); - return { check(result), result }; - } - - vk_result vkCreateCommandPool(const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool) { - - auto result = table.vkCreateCommandPool(vk_device, pCreateInfo, pAllocator, pCommandPool); - return { check(result), result }; - } - - vk_result vkCreateCommandPool(const VkCommandPoolCreateInfo* pCreateInfo, VkCommandPool* pCommandPool) { - - return vkCreateCommandPool(pCreateInfo, memory::alloc(), pCommandPool); - } - - vk_result vkCreateCommandPool(index queue_family, VkCommandPool* pCommandPool) { - - VkCommandPoolCreateInfo create_info - { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .queueFamilyIndex = queue_family, - }; - return vkCreateCommandPool(&create_info, pCommandPool); - } - - vk_result vkAllocateCommandBuffers(const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers) { - - auto result = table.vkAllocateCommandBuffers(vk_device, pAllocateInfo, pCommandBuffers); - return { check(result), result }; - } - - vk_result vkAllocateCommandBuffers(VkCommandPool commandPool, ui32 commandBufferCount, - VkCommandBuffer* pCommandBuffers, VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY) { - - VkCommandBufferAllocateInfo alloc_info - { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, - .commandPool = commandPool, - .level = level, - .commandBufferCount = commandBufferCount, - }; - return vkAllocateCommandBuffers(&alloc_info, pCommandBuffers); - } - - void vkDestroyImageView(VkImageView imageView, const VkAllocationCallbacks* pAllocator = memory::alloc()) { - - table.vkDestroyImageView(vk_device, imageView, pAllocator); - } - - void vkDestroyFence(VkFence fence, const VkAllocationCallbacks* pAllocator = memory::alloc()) { - - table.vkDestroyFence(vk_device, fence, pAllocator); - } - - void vkDestroySemaphore(VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator = memory::alloc()) { - - table.vkDestroySemaphore(vk_device, semaphore, pAllocator); - } - - void vkDestroySwapchainKHR(VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator = memory::alloc()) { - - table.vkDestroySwapchainKHR(vk_device, swapchain, pAllocator); - } - - void vkFreeCommandBuffers(VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers) { - - table.vkFreeCommandBuffers(vk_device, commandPool, commandBufferCount, pCommandBuffers); - } - - void vkDestroyCommandPool(VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator = memory::alloc()) { - - table.vkDestroyCommandPool(vk_device, commandPool, pAllocator); - } - - void vkDestroySampler(VkSampler sampler, const VkAllocationCallbacks* pAllocator = memory::alloc()) { - - table.vkDestroySampler(vk_device, sampler, pAllocator); - } - - void vkUpdateDescriptorSets(uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, - uint32_t descriptorCopyCount = 0, const VkCopyDescriptorSet* pDescriptorCopies = nullptr) { - - table.vkUpdateDescriptorSets(vk_device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies); - } - - template<std::size_t SIZE> - void vkUpdateDescriptorSets(std::array<VkWriteDescriptorSet, SIZE> const& descriptor_writes) { - - vkUpdateDescriptorSets(to_i32(descriptor_writes.size()), descriptor_writes.data()); - } - - template<std::size_t SIZE> - void vkUpdateDescriptorSets(std::array<VkCopyDescriptorSet, SIZE> const& descriptor_copies) { - - vkUpdateDescriptorSets(0, nullptr, to_i32(descriptor_copies.size()), descriptor_copies.data()); - } - - template<std::size_t WRITE_SIZE, std::size_t COPY_SIZE> - void vkUpdateDescriptorSets(std::array<VkWriteDescriptorSet, WRITE_SIZE> const& descriptor_writes, - std::array<VkCopyDescriptorSet, COPY_SIZE> const& descriptor_copies) { - - vkUpdateDescriptorSets(to_i32(descriptor_writes.size()), descriptor_writes.data(), - to_i32(descriptor_copies.size()), descriptor_copies.data()); - } - - void vkUpdateDescriptorSets(std::initializer_list<VkWriteDescriptorSet> descriptor_writes) { - - vkUpdateDescriptorSets(to_i32(descriptor_writes.size()), descriptor_writes.begin()); - } - - void vkUpdateDescriptorSets(std::initializer_list<VkCopyDescriptorSet> descriptor_copies) { - - vkUpdateDescriptorSets(0, nullptr, to_i32(descriptor_copies.size()), descriptor_copies.begin()); - } - - void vkUpdateDescriptorSets(std::initializer_list<VkWriteDescriptorSet> descriptor_writes, - std::initializer_list<VkCopyDescriptorSet> descriptor_copies) { - - vkUpdateDescriptorSets(to_i32(descriptor_writes.size()), descriptor_writes.begin(), - to_i32(descriptor_copies.size()), descriptor_copies.begin()); - } - - VkDevice vk_device = nullptr; - VolkDeviceTable table = {}; -}; - -} // lava + struct device_table : id_obj, no_copy_no_move { + void load_table() { + volkLoadDeviceTable(&table, vk_device); + } + + vk_result vkCreateImageView(const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView) { + auto result = table.vkCreateImageView(vk_device, pCreateInfo, pAllocator, pView); + return { check(result), result }; + } + + vk_result vkCreateImageView(const VkImageViewCreateInfo* pCreateInfo, VkImageView* pView) { + return vkCreateImageView(pCreateInfo, memory::alloc(), pView); + } + + vk_result vkCreateSampler(const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler) { + auto result = table.vkCreateSampler(vk_device, pCreateInfo, pAllocator, pSampler); + return { check(result), result }; + } + + vk_result vkCreateSampler(const VkSamplerCreateInfo* pCreateInfo, VkSampler* pSampler) { + return vkCreateSampler(pCreateInfo, memory::alloc(), pSampler); + } + + vk_result vkCreateShaderModule(const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule) { + auto result = table.vkCreateShaderModule(vk_device, pCreateInfo, pAllocator, pShaderModule); + return { check(result), result }; + } + + vk_result vkCreateShaderModule(const VkShaderModuleCreateInfo* pCreateInfo, VkShaderModule* pShaderModule) { + return vkCreateShaderModule(pCreateInfo, memory::alloc(), pShaderModule); + } + + vk_result vkCreateFence(const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence) { + auto result = table.vkCreateFence(vk_device, pCreateInfo, pAllocator, pFence); + return { check(result), result }; + } + + vk_result vkCreateFence(const VkFenceCreateInfo* pCreateInfo, VkFence* pFence) { + return vkCreateFence(pCreateInfo, memory::alloc(), pFence); + } + + vk_result vkCreateSemaphore(const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore) { + auto result = table.vkCreateSemaphore(vk_device, pCreateInfo, pAllocator, pSemaphore); + return { check(result), result }; + } + + vk_result vkCreateSemaphore(const VkSemaphoreCreateInfo* pCreateInfo, VkSemaphore* pSemaphore) { + return vkCreateSemaphore(pCreateInfo, memory::alloc(), pSemaphore); + } + + vk_result vkWaitForFences(uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout) { + auto result = table.vkWaitForFences(vk_device, fenceCount, pFences, waitAll, timeout); + if ((result == VK_TIMEOUT) && (timeout != UINT64_MAX)) + return { false, result }; + + return { check(result), result }; + } + + vk_result vkAcquireNextImageKHR(VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex) { + auto result = table.vkAcquireNextImageKHR(vk_device, swapchain, timeout, semaphore, fence, pImageIndex); + return { check(result), result }; + } + + vk_result vkResetFences(uint32_t fenceCount, const VkFence* pFences) { + auto result = table.vkResetFences(vk_device, fenceCount, pFences); + return { check(result), result }; + } + + vk_result vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence) { + auto result = table.vkQueueSubmit(queue, submitCount, pSubmits, fence); + return { check(result), result }; + } + + vk_result vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo) { + auto result = table.vkQueuePresentKHR(queue, pPresentInfo); + return { check(result), result }; + } + + vk_result vkCreateSwapchainKHR(const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain) { + auto result = table.vkCreateSwapchainKHR(vk_device, pCreateInfo, pAllocator, pSwapchain); + return { check(result), result }; + } + + vk_result vkCreateSwapchainKHR(const VkSwapchainCreateInfoKHR* pCreateInfo, VkSwapchainKHR* pSwapchain) { + return vkCreateSwapchainKHR(pCreateInfo, memory::alloc(), pSwapchain); + } + + vk_result vkGetSwapchainImagesKHR(VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages) { + auto result = table.vkGetSwapchainImagesKHR(vk_device, swapchain, pSwapchainImageCount, pSwapchainImages); + return { check(result), result }; + } + + vk_result vkCreateCommandPool(const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool) { + auto result = table.vkCreateCommandPool(vk_device, pCreateInfo, pAllocator, pCommandPool); + return { check(result), result }; + } + + vk_result vkCreateCommandPool(const VkCommandPoolCreateInfo* pCreateInfo, VkCommandPool* pCommandPool) { + return vkCreateCommandPool(pCreateInfo, memory::alloc(), pCommandPool); + } + + vk_result vkCreateCommandPool(index queue_family, VkCommandPool* pCommandPool) { + VkCommandPoolCreateInfo create_info{ + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .queueFamilyIndex = queue_family, + }; + return vkCreateCommandPool(&create_info, pCommandPool); + } + + vk_result vkAllocateCommandBuffers(const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers) { + auto result = table.vkAllocateCommandBuffers(vk_device, pAllocateInfo, pCommandBuffers); + return { check(result), result }; + } + + vk_result vkAllocateCommandBuffers(VkCommandPool commandPool, ui32 commandBufferCount, + VkCommandBuffer* pCommandBuffers, VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY) { + VkCommandBufferAllocateInfo alloc_info{ + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .commandPool = commandPool, + .level = level, + .commandBufferCount = commandBufferCount, + }; + return vkAllocateCommandBuffers(&alloc_info, pCommandBuffers); + } + + void vkDestroyImageView(VkImageView imageView, const VkAllocationCallbacks* pAllocator = memory::alloc()) { + table.vkDestroyImageView(vk_device, imageView, pAllocator); + } + + void vkDestroyFence(VkFence fence, const VkAllocationCallbacks* pAllocator = memory::alloc()) { + table.vkDestroyFence(vk_device, fence, pAllocator); + } + + void vkDestroySemaphore(VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator = memory::alloc()) { + table.vkDestroySemaphore(vk_device, semaphore, pAllocator); + } + + void vkDestroySwapchainKHR(VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator = memory::alloc()) { + table.vkDestroySwapchainKHR(vk_device, swapchain, pAllocator); + } + + void vkFreeCommandBuffers(VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers) { + table.vkFreeCommandBuffers(vk_device, commandPool, commandBufferCount, pCommandBuffers); + } + + void vkDestroyCommandPool(VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator = memory::alloc()) { + table.vkDestroyCommandPool(vk_device, commandPool, pAllocator); + } + + void vkDestroySampler(VkSampler sampler, const VkAllocationCallbacks* pAllocator = memory::alloc()) { + table.vkDestroySampler(vk_device, sampler, pAllocator); + } + + void vkUpdateDescriptorSets(uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, + uint32_t descriptorCopyCount = 0, const VkCopyDescriptorSet* pDescriptorCopies = nullptr) { + table.vkUpdateDescriptorSets(vk_device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies); + } + + template<std::size_t SIZE> + void vkUpdateDescriptorSets(std::array<VkWriteDescriptorSet, SIZE> const& descriptor_writes) { + vkUpdateDescriptorSets(to_i32(descriptor_writes.size()), descriptor_writes.data()); + } + + template<std::size_t SIZE> + void vkUpdateDescriptorSets(std::array<VkCopyDescriptorSet, SIZE> const& descriptor_copies) { + vkUpdateDescriptorSets(0, nullptr, to_i32(descriptor_copies.size()), descriptor_copies.data()); + } + + template<std::size_t WRITE_SIZE, std::size_t COPY_SIZE> + void vkUpdateDescriptorSets(std::array<VkWriteDescriptorSet, WRITE_SIZE> const& descriptor_writes, + std::array<VkCopyDescriptorSet, COPY_SIZE> const& descriptor_copies) { + vkUpdateDescriptorSets(to_i32(descriptor_writes.size()), descriptor_writes.data(), + to_i32(descriptor_copies.size()), descriptor_copies.data()); + } + + void vkUpdateDescriptorSets(std::initializer_list<VkWriteDescriptorSet> descriptor_writes) { + vkUpdateDescriptorSets(to_i32(descriptor_writes.size()), descriptor_writes.begin()); + } + + void vkUpdateDescriptorSets(std::initializer_list<VkCopyDescriptorSet> descriptor_copies) { + vkUpdateDescriptorSets(0, nullptr, to_i32(descriptor_copies.size()), descriptor_copies.begin()); + } + + void vkUpdateDescriptorSets(std::initializer_list<VkWriteDescriptorSet> descriptor_writes, + std::initializer_list<VkCopyDescriptorSet> descriptor_copies) { + vkUpdateDescriptorSets(to_i32(descriptor_writes.size()), descriptor_writes.begin(), + to_i32(descriptor_copies.size()), descriptor_copies.begin()); + } + + VkDevice vk_device = nullptr; + VolkDeviceTable table = {}; + }; + +} // namespace lava diff --git a/liblava/base/instance.cpp b/liblava/base/instance.cpp index 18c14795f57a85c142d5ac9426a4516909a8f777..f4f6ba1d69c62c2181f02e14560b3c4c474ed6eb 100644 --- a/liblava/base/instance.cpp +++ b/liblava/base/instance.cpp @@ -10,250 +10,225 @@ namespace lava { -instance::~instance() { - - destroy(); -} - -bool instance::create(create_param& param, debug_config::ref d, app_info::ref i) { - - debug = d; - info = i; - - if (debug.validation) { - - if (!exists(param.layers, VK_LAYER_KHRONOS_VALIDATION_NAME)) - param.layers.push_back(VK_LAYER_KHRONOS_VALIDATION_NAME); - } - - if (debug.render_doc) { - - if (!exists(param.layers, VK_LAYER_RENDERDOC_CAPTURE_NAME)) - param.layers.push_back(VK_LAYER_RENDERDOC_CAPTURE_NAME); - } - - if (debug.utils) { - - if (!exists(param.extensions, VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) - param.extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + instance::~instance() { + destroy(); } - if (!check(param)) { + bool instance::create(create_param& param, debug_config::ref d, app_info::ref i) { + debug = d; + info = i; - log()->error("create instance param"); - - for (auto& extension : param.extensions) - log()->debug("extension: {}", extension); - - for (auto& layer : param.layers) - log()->debug("layer: {}", layer); - - return false; - } + if (debug.validation) { + if (!exists(param.layers, VK_LAYER_KHRONOS_VALIDATION_NAME)) + param.layers.push_back(VK_LAYER_KHRONOS_VALIDATION_NAME); + } - ui32 app_version = VK_MAKE_VERSION(info.app_version.major, - info.app_version.minor, - info.app_version.patch); + if (debug.render_doc) { + if (!exists(param.layers, VK_LAYER_RENDERDOC_CAPTURE_NAME)) + param.layers.push_back(VK_LAYER_RENDERDOC_CAPTURE_NAME); + } - VkApplicationInfo application_info - { - .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, - .pApplicationName = info.app_name ? info.app_name : _lava_, - .applicationVersion = app_version, - .pEngineName = _liblava_, - }; + if (debug.utils) { + if (!exists(param.extensions, VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) + param.extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + } - application_info.engineVersion = VK_MAKE_VERSION(_internal_version.major, - _internal_version.minor, - _internal_version.patch); + if (!check(param)) { + log()->error("create instance param"); - application_info.apiVersion = VK_API_VERSION_1_0; + for (auto& extension : param.extensions) + log()->debug("extension: {}", extension); - switch (info.req_api_version) { + for (auto& layer : param.layers) + log()->debug("layer: {}", layer); - case api_version::v1_1: application_info.apiVersion = VK_API_VERSION_1_1; break; - case api_version::v1_2: application_info.apiVersion = VK_API_VERSION_1_2; break; - } - - VkInstanceCreateInfo create_info - { - .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - .pApplicationInfo = &application_info, - .enabledLayerCount = to_ui32(param.layers.size()), - .ppEnabledLayerNames = param.layers.data(), - .enabledExtensionCount = to_ui32(param.extensions.size()), - .ppEnabledExtensionNames = param.extensions.data(), - }; - - auto result = vkCreateInstance(&create_info, memory::alloc(), &vk_instance); - if (failed(result)) - return false; - - volkLoadInstance(vk_instance); - - if (!enumerate_physical_devices()) - return false; - - if (debug.utils) - if (!create_validation_report()) + return false; + } + + ui32 app_version = VK_MAKE_VERSION(info.app_version.major, + info.app_version.minor, + info.app_version.patch); + + VkApplicationInfo application_info{ + .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, + .pApplicationName = info.app_name ? info.app_name : _lava_, + .applicationVersion = app_version, + .pEngineName = _liblava_, + }; + + application_info.engineVersion = VK_MAKE_VERSION(_internal_version.major, + _internal_version.minor, + _internal_version.patch); + + application_info.apiVersion = VK_API_VERSION_1_0; + + switch (info.req_api_version) { + case api_version::v1_1: + application_info.apiVersion = VK_API_VERSION_1_1; + break; + case api_version::v1_2: + application_info.apiVersion = VK_API_VERSION_1_2; + break; + } + + VkInstanceCreateInfo create_info{ + .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + .pApplicationInfo = &application_info, + .enabledLayerCount = to_ui32(param.layers.size()), + .ppEnabledLayerNames = param.layers.data(), + .enabledExtensionCount = to_ui32(param.extensions.size()), + .ppEnabledExtensionNames = param.extensions.data(), + }; + + auto result = vkCreateInstance(&create_info, memory::alloc(), &vk_instance); + if (failed(result)) return false; - return true; -} - -void instance::destroy() { - - if (!vk_instance) - return - - physical_devices.clear(); + volkLoadInstance(vk_instance); - if (debug.utils) - destroy_validation_report(); + if (!enumerate_physical_devices()) + return false; - vkDestroyInstance(vk_instance, memory::alloc()); - vk_instance = nullptr; -} + if (debug.utils) + if (!create_validation_report()) + return false; -static VKAPI_ATTR VkBool32 VKAPI_CALL validation_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, - VkDebugUtilsMessageTypeFlagsEXT message_type, const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) { + return true; + } - auto message_header = fmt::format("validation: {} ({})", callback_data->pMessageIdName, - callback_data->messageIdNumber); + void instance::destroy() { + if (!vk_instance) + return - if (message_severity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { + physical_devices.clear(); - log()->error(str(message_header)); - log()->error(callback_data->pMessage); + if (debug.utils) + destroy_validation_report(); - assert(!"check validation error"); + vkDestroyInstance(vk_instance, memory::alloc()); + vk_instance = nullptr; } - else if (message_severity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { - log()->warn(str(message_header)); - log()->warn(callback_data->pMessage); - } - else if (message_severity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) { - - log()->info(str(message_header)); - log()->info(callback_data->pMessage); - } - else if (message_severity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) { - - log()->trace(str(message_header)); - log()->trace(callback_data->pMessage); + static VKAPI_ATTR VkBool32 VKAPI_CALL validation_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, + VkDebugUtilsMessageTypeFlagsEXT message_type, const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) { + auto message_header = fmt::format("validation: {} ({})", callback_data->pMessageIdName, + callback_data->messageIdNumber); + + if (message_severity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { + log()->error(str(message_header)); + log()->error(callback_data->pMessage); + + assert(!"check validation error"); + } else if (message_severity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { + log()->warn(str(message_header)); + log()->warn(callback_data->pMessage); + } else if (message_severity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) { + log()->info(str(message_header)); + log()->info(callback_data->pMessage); + } else if (message_severity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) { + log()->trace(str(message_header)); + log()->trace(callback_data->pMessage); + } + + return VK_FALSE; } - return VK_FALSE; -} - -bool instance::create_validation_report() { - - VkDebugUtilsMessengerCreateInfoEXT create_info - { - .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, - .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, - .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, - .pfnUserCallback = validation_callback, - }; - - if (debug.verbose) - create_info.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT; - - return check(vkCreateDebugUtilsMessengerEXT(vk_instance, &create_info, memory::alloc(), &debug_messenger)); -} + bool instance::create_validation_report() { + VkDebugUtilsMessengerCreateInfoEXT create_info{ + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, + .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, + .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, + .pfnUserCallback = validation_callback, + }; -void instance::destroy_validation_report() { + if (debug.verbose) + create_info.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT; - if (!debug_messenger) - return; - - vkDestroyDebugUtilsMessengerEXT(vk_instance, debug_messenger, memory::alloc()); - - debug_messenger = 0; -} + return check(vkCreateDebugUtilsMessengerEXT(vk_instance, &create_info, memory::alloc(), &debug_messenger)); + } -VkLayerPropertiesList instance::enumerate_layer_properties() { + void instance::destroy_validation_report() { + if (!debug_messenger) + return; - auto layer_count = 0u; - auto result = vkEnumerateInstanceLayerProperties(&layer_count, nullptr); - if (failed(result)) - return {}; + vkDestroyDebugUtilsMessengerEXT(vk_instance, debug_messenger, memory::alloc()); - VkLayerPropertiesList list(layer_count); - result = vkEnumerateInstanceLayerProperties(&layer_count, list.data()); - if (failed(result)) - return {}; + debug_messenger = 0; + } - return list; -} + VkLayerPropertiesList instance::enumerate_layer_properties() { + auto layer_count = 0u; + auto result = vkEnumerateInstanceLayerProperties(&layer_count, nullptr); + if (failed(result)) + return {}; -VkExtensionPropertiesList instance::enumerate_extension_properties(name layer_name) { + VkLayerPropertiesList list(layer_count); + result = vkEnumerateInstanceLayerProperties(&layer_count, list.data()); + if (failed(result)) + return {}; - auto property_count = 0u; - auto result = vkEnumerateInstanceExtensionProperties(layer_name, &property_count, nullptr); - if (failed(result)) - return {}; + return list; + } - VkExtensionPropertiesList list(property_count); - result = vkEnumerateInstanceExtensionProperties(layer_name, &property_count, list.data()); - if (failed(result)) - return {}; + VkExtensionPropertiesList instance::enumerate_extension_properties(name layer_name) { + auto property_count = 0u; + auto result = vkEnumerateInstanceExtensionProperties(layer_name, &property_count, nullptr); + if (failed(result)) + return {}; - return list; -} + VkExtensionPropertiesList list(property_count); + result = vkEnumerateInstanceExtensionProperties(layer_name, &property_count, list.data()); + if (failed(result)) + return {}; -bool instance::enumerate_physical_devices() { + return list; + } - physical_devices.clear(); + bool instance::enumerate_physical_devices() { + physical_devices.clear(); - auto count = 0u; - auto result = vkEnumeratePhysicalDevices(vk_instance, &count, nullptr); - if (failed(result)) - return false; + auto count = 0u; + auto result = vkEnumeratePhysicalDevices(vk_instance, &count, nullptr); + if (failed(result)) + return false; - VkPhysicalDevices devices(count); - result = vkEnumeratePhysicalDevices(vk_instance, &count, devices.data()); - if (failed(result)) - return false; + VkPhysicalDevices devices(count); + result = vkEnumeratePhysicalDevices(vk_instance, &count, devices.data()); + if (failed(result)) + return false; - for (auto& device : devices) { + for (auto& device : devices) { + physical_device physical_device; + physical_device.initialize(device); + physical_devices.push_back(std::move(physical_device)); + } - physical_device physical_device; - physical_device.initialize(device); - physical_devices.push_back(std::move(physical_device)); + return true; } - return true; -} - -internal_version instance::get_version() { - - ui32 instance_version = VK_API_VERSION_1_0; + internal_version instance::get_version() { + ui32 instance_version = VK_API_VERSION_1_0; - auto enumerate_instance_version = (PFN_vkEnumerateInstanceVersion)vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"); - if (enumerate_instance_version) - enumerate_instance_version(&instance_version); + auto enumerate_instance_version = (PFN_vkEnumerateInstanceVersion) vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"); + if (enumerate_instance_version) + enumerate_instance_version(&instance_version); - internal_version version; - version.major = VK_VERSION_MAJOR(instance_version); - version.minor = VK_VERSION_MINOR(instance_version); - version.patch = VK_VERSION_PATCH(VK_HEADER_VERSION); - return version; -} + internal_version version; + version.major = VK_VERSION_MAJOR(instance_version); + version.minor = VK_VERSION_MINOR(instance_version); + version.patch = VK_VERSION_PATCH(VK_HEADER_VERSION); + return version; + } -} // lava +} // namespace lava bool lava::check(instance::create_param::ref param) { - auto layer_properties = instance::enumerate_layer_properties(); for (auto const& layer_name : param.layers) { - auto itr = std::find_if(layer_properties.begin(), layer_properties.end(), - [&](VkLayerProperties const& extProp) { - - return strcmp(layer_name, extProp.layerName) == 0; - }); + [&](VkLayerProperties const& extProp) { + return strcmp(layer_name, extProp.layerName) == 0; + }); if (itr == layer_properties.end()) return false; @@ -261,12 +236,10 @@ bool lava::check(instance::create_param::ref param) { auto extensions_properties = instance::enumerate_extension_properties(); for (auto const& ext_name : param.extensions) { - auto itr = std::find_if(extensions_properties.begin(), extensions_properties.end(), - [&](VkExtensionProperties const& extProp) { - - return strcmp(ext_name, extProp.extensionName) == 0; - }); + [&](VkExtensionProperties const& extProp) { + return strcmp(ext_name, extProp.extensionName) == 0; + }); if (itr == extensions_properties.end()) return false; diff --git a/liblava/base/instance.hpp b/liblava/base/instance.hpp index 881990845f4bdbea7f4abc31f89f01a47cb818e3..3dd8053864ffd01072060fea6415d1fcf9e694e3 100644 --- a/liblava/base/instance.hpp +++ b/liblava/base/instance.hpp @@ -8,85 +8,90 @@ namespace lava { -struct instance : no_copy_no_move { + struct instance : no_copy_no_move { + struct create_param { + using ref = create_param const&; - struct create_param { + names layers{}; + names extensions{}; + }; - using ref = create_param const&; + struct debug_config { + using ref = debug_config const&; - names layers{}; - names extensions{}; - }; + bool validation = false; + bool render_doc = false; + bool verbose = false; + bool utils = false; + }; - struct debug_config { + enum class api_version : type { - using ref = debug_config const&; + v1_0 = 0, + v1_1, + v1_2 + }; - bool validation = false; - bool render_doc = false; - bool verbose = false; - bool utils = false; - }; + struct app_info { + using ref = app_info const&; - enum class api_version : type { + name app_name = nullptr; - v1_0 = 0, - v1_1, - v1_2 - }; + internal_version app_version; + api_version req_api_version = api_version::v1_0; + }; - struct app_info { + static instance& singleton() { + static instance instance; + return instance; + } - using ref = app_info const&; - - name app_name = nullptr; - - internal_version app_version; - api_version req_api_version = api_version::v1_0; - }; + bool create(create_param& param, debug_config::ref debug, app_info::ref info); + void destroy(); - static instance& singleton() { + static VkLayerPropertiesList enumerate_layer_properties(); + static VkExtensionPropertiesList enumerate_extension_properties(name layer_name = nullptr); - static instance instance; - return instance; - } + physical_device::list const& get_physical_devices() const { + return physical_devices; + } - bool create(create_param& param, debug_config::ref debug, app_info::ref info); - void destroy(); + static physical_device::ref get_first_physical_device() { + return singleton().physical_devices.front(); + } - static VkLayerPropertiesList enumerate_layer_properties(); - static VkExtensionPropertiesList enumerate_extension_properties(name layer_name = nullptr); + static VkInstance get() { + return singleton().vk_instance; + } - physical_device::list const& get_physical_devices() const { return physical_devices; } + static internal_version get_version(); - static physical_device::ref get_first_physical_device() { return singleton().physical_devices.front(); } + debug_config::ref get_debug_config() const { + return debug; + } + app_info::ref get_app_info() const { + return info; + } - static VkInstance get() { return singleton().vk_instance; } + private: + explicit instance() = default; + ~instance(); - static internal_version get_version(); + bool enumerate_physical_devices(); - debug_config::ref get_debug_config() const { return debug; } - app_info::ref get_app_info() const { return info; } + bool create_validation_report(); + void destroy_validation_report(); -private: - explicit instance() = default; - ~instance(); + VkInstance vk_instance = nullptr; - bool enumerate_physical_devices(); + physical_device::list physical_devices; - bool create_validation_report(); - void destroy_validation_report(); + debug_config debug; + app_info info; - VkInstance vk_instance = nullptr; - - physical_device::list physical_devices; - - debug_config debug; - app_info info; - - VkDebugUtilsMessengerEXT debug_messenger = 0; -}; + VkDebugUtilsMessengerEXT debug_messenger = 0; + }; -bool check(instance::create_param::ref param); + bool check(instance::create_param::ref param); -} // lava +} // namespace lava diff --git a/liblava/base/memory.cpp b/liblava/base/memory.cpp index e09618460dd7916ede44f02674e37e93a93ffeda..0c00cd0dd9b9ace2e052f531c76e6a6c33cbb25f 100644 --- a/liblava/base/memory.cpp +++ b/liblava/base/memory.cpp @@ -2,20 +2,20 @@ // copyright : Copyright (c) 2018-present, Lava Block OÜ // license : MIT; see accompanying LICENSE file -#include <liblava/base/memory.hpp> #include <liblava/base/instance.hpp> +#include <liblava/base/memory.hpp> #ifdef _WIN32 -#pragma warning(push, 4) -#pragma warning(disable : 4127) // conditional expression is constant -#pragma warning(disable : 4100) // unreferenced formal parameter -#pragma warning(disable : 4189) // local variable is initialized but not referenced -#pragma warning(disable : 4324) // structure was padded due to alignment specifier +# pragma warning(push, 4) +# pragma warning(disable : 4127) // conditional expression is constant +# pragma warning(disable : 4100) // unreferenced formal parameter +# pragma warning(disable : 4189) // local variable is initialized but not referenced +# pragma warning(disable : 4324) // structure was padded due to alignment specifier #else -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wtype-limits" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmissing-field-initializers" +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic ignored "-Wtype-limits" #endif #define VMA_STATIC_VULKAN_FUNCTIONS 0 @@ -23,123 +23,112 @@ #include <vk_mem_alloc.h> #ifdef _WIN32 -#pragma warning(pop) +# pragma warning(pop) #else -#pragma GCC diagnostic pop +# pragma GCC diagnostic pop #endif -#define LAVA_CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA (void*)(intptr_t) 20180208 +#define LAVA_CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA (void*) (intptr_t) 20180208 namespace lava { -static void* VKAPI_PTR custom_cpu_allocation(void* user_data, size_t size, size_t alignment, VkSystemAllocationScope allocation_scope) { - - assert(user_data == LAVA_CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA); - return alloc_data(size, alignment); -} - -static void* VKAPI_PTR custom_cpu_reallocation(void* user_data, void* original, size_t size, size_t alignment, VkSystemAllocationScope allocation_scope) { + static void* VKAPI_PTR custom_cpu_allocation(void* user_data, size_t size, size_t alignment, VkSystemAllocationScope allocation_scope) { + assert(user_data == LAVA_CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA); + return alloc_data(size, alignment); + } - assert(user_data == LAVA_CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA); - return realloc_data(original, size, alignment); -} + static void* VKAPI_PTR custom_cpu_reallocation(void* user_data, void* original, size_t size, size_t alignment, VkSystemAllocationScope allocation_scope) { + assert(user_data == LAVA_CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA); + return realloc_data(original, size, alignment); + } -static void VKAPI_PTR custom_cpu_free(void* user_Data, void* memory) { + static void VKAPI_PTR custom_cpu_free(void* user_Data, void* memory) { + assert(user_Data == LAVA_CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA); + free_data(memory); + } - assert(user_Data == LAVA_CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA); - free_data(memory); -} + memory::memory() { + if (!use_custom_cpu_callbacks) + return; -memory::memory() { + vk_callbacks.pUserData = LAVA_CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA; + vk_callbacks.pfnAllocation = reinterpret_cast<PFN_vkAllocationFunction>(&custom_cpu_allocation); + vk_callbacks.pfnReallocation = reinterpret_cast<PFN_vkReallocationFunction>(&custom_cpu_reallocation); + vk_callbacks.pfnFree = reinterpret_cast<PFN_vkFreeFunction>(&custom_cpu_free); + } - if (!use_custom_cpu_callbacks) - return; + type memory::find_type_with_properties(VkPhysicalDeviceMemoryProperties properties, ui32 type_bits, VkMemoryPropertyFlags required_properties) { + auto bits = type_bits; + auto len = std::min(properties.memoryTypeCount, 32u); - vk_callbacks.pUserData = LAVA_CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA; - vk_callbacks.pfnAllocation = reinterpret_cast<PFN_vkAllocationFunction>(&custom_cpu_allocation); - vk_callbacks.pfnReallocation = reinterpret_cast<PFN_vkReallocationFunction>(&custom_cpu_reallocation); - vk_callbacks.pfnFree = reinterpret_cast<PFN_vkFreeFunction>(&custom_cpu_free); -} + for (auto i = 0u; i < len; ++i) { + if ((bits & 1) == 1) + if ((properties.memoryTypes[i].propertyFlags & required_properties) == required_properties) + return (int) i; -type memory::find_type_with_properties(VkPhysicalDeviceMemoryProperties properties, ui32 type_bits, VkMemoryPropertyFlags required_properties) { + bits >>= 1; + } - auto bits = type_bits; - auto len = std::min(properties.memoryTypeCount, 32u); + return no_type; + } - for (auto i = 0u; i < len; ++i) { + type memory::find_type(VkPhysicalDevice gpu, VkMemoryPropertyFlags properties, ui32 type_bits) { + VkPhysicalDeviceMemoryProperties prop{}; + vkGetPhysicalDeviceMemoryProperties(gpu, &prop); - if ((bits & 1) == 1) - if ((properties.memoryTypes[i].propertyFlags & required_properties) == required_properties) - return (int)i; + for (auto i = 0u; i < prop.memoryTypeCount; ++i) + if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1 << i)) + return i; - bits >>= 1; + return no_type; } - return no_type; -} - -type memory::find_type(VkPhysicalDevice gpu, VkMemoryPropertyFlags properties, ui32 type_bits) { - - VkPhysicalDeviceMemoryProperties prop{}; - vkGetPhysicalDeviceMemoryProperties(gpu, &prop); - - for (auto i = 0u; i < prop.memoryTypeCount; ++i) - if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1 << i)) - return i; - - return no_type; -} - -allocator::allocator(VkPhysicalDevice physical_device, VkDevice device) { - - VmaVulkanFunctions vulkan_function - { - .vkGetPhysicalDeviceProperties = vkGetPhysicalDeviceProperties, - .vkGetPhysicalDeviceMemoryProperties = vkGetPhysicalDeviceMemoryProperties, - .vkAllocateMemory = vkAllocateMemory, - .vkFreeMemory = vkFreeMemory, - .vkMapMemory = vkMapMemory, - .vkUnmapMemory = vkUnmapMemory, - .vkFlushMappedMemoryRanges = vkFlushMappedMemoryRanges, - .vkInvalidateMappedMemoryRanges = vkInvalidateMappedMemoryRanges, - .vkBindBufferMemory = vkBindBufferMemory, - .vkBindImageMemory = vkBindImageMemory, - .vkGetBufferMemoryRequirements = vkGetBufferMemoryRequirements, - .vkGetImageMemoryRequirements = vkGetImageMemoryRequirements, - .vkCreateBuffer = vkCreateBuffer, - .vkDestroyBuffer = vkDestroyBuffer, - .vkCreateImage = vkCreateImage, - .vkDestroyImage = vkDestroyImage, - .vkCmdCopyBuffer = vkCmdCopyBuffer, + allocator::allocator(VkPhysicalDevice physical_device, VkDevice device) { + VmaVulkanFunctions vulkan_function { + .vkGetPhysicalDeviceProperties = vkGetPhysicalDeviceProperties, + .vkGetPhysicalDeviceMemoryProperties = vkGetPhysicalDeviceMemoryProperties, + .vkAllocateMemory = vkAllocateMemory, + .vkFreeMemory = vkFreeMemory, + .vkMapMemory = vkMapMemory, + .vkUnmapMemory = vkUnmapMemory, + .vkFlushMappedMemoryRanges = vkFlushMappedMemoryRanges, + .vkInvalidateMappedMemoryRanges = vkInvalidateMappedMemoryRanges, + .vkBindBufferMemory = vkBindBufferMemory, + .vkBindImageMemory = vkBindImageMemory, + .vkGetBufferMemoryRequirements = vkGetBufferMemoryRequirements, + .vkGetImageMemoryRequirements = vkGetImageMemoryRequirements, + .vkCreateBuffer = vkCreateBuffer, + .vkDestroyBuffer = vkDestroyBuffer, + .vkCreateImage = vkCreateImage, + .vkDestroyImage = vkDestroyImage, + .vkCmdCopyBuffer = vkCmdCopyBuffer, #if VMA_DEDICATED_ALLOCATION - .vkGetBufferMemoryRequirements2KHR = vkGetBufferMemoryRequirements2KHR, - .vkGetImageMemoryRequirements2KHR = vkGetImageMemoryRequirements2KHR, + .vkGetBufferMemoryRequirements2KHR = vkGetBufferMemoryRequirements2KHR, + .vkGetImageMemoryRequirements2KHR = vkGetImageMemoryRequirements2KHR, #endif #if VMA_BIND_MEMORY2 - .vkBindBufferMemory2KHR = vkBindBufferMemory2KHR, - .vkBindImageMemory2KHR = vkBindImageMemory2KHR, + .vkBindBufferMemory2KHR = vkBindBufferMemory2KHR, + .vkBindImageMemory2KHR = vkBindImageMemory2KHR, #endif - }; + }; - VmaAllocatorCreateInfo allocator_info - { - .physicalDevice = physical_device, - .device = device, - .pAllocationCallbacks = memory::alloc(), - .pVulkanFunctions = &vulkan_function, - .instance = instance::get(), - }; + VmaAllocatorCreateInfo allocator_info{ + .physicalDevice = physical_device, + .device = device, + .pAllocationCallbacks = memory::alloc(), + .pVulkanFunctions = &vulkan_function, + .instance = instance::get(), + }; - check(vmaCreateAllocator(&allocator_info, &vma_allocator)); -} - -allocator::~allocator() { + check(vmaCreateAllocator(&allocator_info, &vma_allocator)); + } - if (!vma_allocator) - return; + allocator::~allocator() { + if (!vma_allocator) + return; - vmaDestroyAllocator(vma_allocator); - vma_allocator = nullptr; -} + vmaDestroyAllocator(vma_allocator); + vma_allocator = nullptr; + } -} // lava +} // namespace lava diff --git a/liblava/base/memory.hpp b/liblava/base/memory.hpp index 5d336b08c7c9afdf8043c7b0308a3ce3cd7ee583..cf476328729782351d347dd1850403bcbaf847d3 100644 --- a/liblava/base/memory.hpp +++ b/liblava/base/memory.hpp @@ -4,61 +4,67 @@ #pragma once -#include <liblava/base/base.hpp> +// clang-format off +#include <liblava/base/base.hpp> #include <vk_mem_alloc.h> -namespace lava { - -struct allocator { - - explicit allocator(VkPhysicalDevice physical_device, VkDevice device); - ~allocator(); +// clang-format on - using ptr = std::shared_ptr<allocator>; - - bool valid() const { return vma_allocator != nullptr; } - - VmaAllocator get() const { return vma_allocator; } +namespace lava { -private: - VmaAllocator vma_allocator = nullptr; -}; + struct allocator { + explicit allocator(VkPhysicalDevice physical_device, VkDevice device); + ~allocator(); -inline allocator::ptr make_allocator(VkPhysicalDevice physical_device, VkDevice device) { + using ptr = std::shared_ptr<allocator>; - return std::make_shared<allocator>(physical_device, device); -} + bool valid() const { + return vma_allocator != nullptr; + } -struct memory : no_copy_no_move { + VmaAllocator get() const { + return vma_allocator; + } - static memory& get() { + private: + VmaAllocator vma_allocator = nullptr; + }; - static memory memory; - return memory; + inline allocator::ptr make_allocator(VkPhysicalDevice physical_device, VkDevice device) { + return std::make_shared<allocator>(physical_device, device); } - static VkAllocationCallbacks* alloc() { + struct memory : no_copy_no_move { + static memory& get() { + static memory memory; + return memory; + } - if (get().use_custom_cpu_callbacks) - return &get().vk_callbacks; + static VkAllocationCallbacks* alloc() { + if (get().use_custom_cpu_callbacks) + return &get().vk_callbacks; - return nullptr; - } + return nullptr; + } - static type find_type_with_properties(VkPhysicalDeviceMemoryProperties properties, ui32 type_bits, - VkMemoryPropertyFlags required_properties); + static type find_type_with_properties(VkPhysicalDeviceMemoryProperties properties, ui32 type_bits, + VkMemoryPropertyFlags required_properties); - static type find_type(VkPhysicalDevice gpu, VkMemoryPropertyFlags properties, ui32 type_bits); + static type find_type(VkPhysicalDevice gpu, VkMemoryPropertyFlags properties, ui32 type_bits); - void set_callbacks(VkAllocationCallbacks const& callbacks) { vk_callbacks = callbacks; } - void set_use_custom_cpu_callbacks(bool value) { use_custom_cpu_callbacks = value; } + void set_callbacks(VkAllocationCallbacks const& callbacks) { + vk_callbacks = callbacks; + } + void set_use_custom_cpu_callbacks(bool value) { + use_custom_cpu_callbacks = value; + } -private: - memory(); + private: + memory(); - bool use_custom_cpu_callbacks = true; - VkAllocationCallbacks vk_callbacks = {}; -}; + bool use_custom_cpu_callbacks = true; + VkAllocationCallbacks vk_callbacks = {}; + }; -} // lava +} // namespace lava diff --git a/liblava/base/physical_device.cpp b/liblava/base/physical_device.cpp index 0040a22a69b07901d6ad5c9bbb3e03d461d9ff40..99a8fc9ba33b4702d87f98c5edb70e201c6a8938 100644 --- a/liblava/base/physical_device.cpp +++ b/liblava/base/physical_device.cpp @@ -6,70 +6,59 @@ namespace lava { -void physical_device::initialize(VkPhysicalDevice pd) { - - vk_physical_device = pd; - - vkGetPhysicalDeviceProperties(vk_physical_device, &properties); - vkGetPhysicalDeviceFeatures(vk_physical_device, &features); - vkGetPhysicalDeviceMemoryProperties(vk_physical_device, &memory_properties); - - auto queue_family_count = 0u; - vkGetPhysicalDeviceQueueFamilyProperties(vk_physical_device, &queue_family_count, nullptr); - if (queue_family_count > 0) { + void physical_device::initialize(VkPhysicalDevice pd) { + vk_physical_device = pd; + + vkGetPhysicalDeviceProperties(vk_physical_device, &properties); + vkGetPhysicalDeviceFeatures(vk_physical_device, &features); + vkGetPhysicalDeviceMemoryProperties(vk_physical_device, &memory_properties); + + auto queue_family_count = 0u; + vkGetPhysicalDeviceQueueFamilyProperties(vk_physical_device, &queue_family_count, nullptr); + if (queue_family_count > 0) { + queue_family_properties.resize(queue_family_count); + vkGetPhysicalDeviceQueueFamilyProperties(vk_physical_device, &queue_family_count, queue_family_properties.data()); + } - queue_family_properties.resize(queue_family_count); - vkGetPhysicalDeviceQueueFamilyProperties(vk_physical_device, &queue_family_count, queue_family_properties.data()); + auto extension_count = 0u; + vkEnumerateDeviceExtensionProperties(vk_physical_device, nullptr, &extension_count, nullptr); + if (extension_count > 0) { + extension_properties.resize(extension_count); + vkEnumerateDeviceExtensionProperties(vk_physical_device, nullptr, &extension_count, extension_properties.data()); + } } - auto extension_count = 0u; - vkEnumerateDeviceExtensionProperties(vk_physical_device, nullptr, &extension_count, nullptr); - if (extension_count > 0) { + bool physical_device::supported(string_ref extension) const { + for (auto& extension_property : extension_properties) { + if (string(extension_property.extensionName) == extension) + return true; + } - extension_properties.resize(extension_count); - vkEnumerateDeviceExtensionProperties(vk_physical_device, nullptr, &extension_count, extension_properties.data()); + return false; } -} -bool physical_device::supported(string_ref extension) const { - - for (auto& extension_property : extension_properties) { + bool physical_device::get_queue_family(index& index, VkQueueFlags flags) const { + for (size_t i = 0, e = queue_family_properties.size(); i != e; ++i) { + if (queue_family_properties[i].queueFlags & flags) { + index = to_index(i); + return true; + } + } - if (string(extension_property.extensionName) == extension) - return true; + return false; } - return false; -} - -bool physical_device::get_queue_family(index& index, VkQueueFlags flags) const { - - for (size_t i = 0, e = queue_family_properties.size(); i != e; ++i) { - - if (queue_family_properties[i].queueFlags & flags) { + device::create_param physical_device::create_default_device_param() const { + device::create_param create_param; + create_param.physical_device = this; + create_param.set_default_queues(); - index = to_index(i); - return true; - } + return create_param; } - return false; -} - -device::create_param physical_device::create_default_device_param() const { - - device::create_param create_param; - create_param.physical_device = this; - create_param.set_default_queues(); - - return create_param; -} - -string physical_device::get_device_type_string() const { - - string result; - switch (properties.deviceType) { - + string physical_device::get_device_type_string() const { + string result; + switch (properties.deviceType) { case VK_PHYSICAL_DEVICE_TYPE_OTHER: result = "OTHER"; break; @@ -88,22 +77,20 @@ string physical_device::get_device_type_string() const { default: result = "UNKNOWN"; break; + } + return result; } - return result; -} - -bool physical_device::swapchain_supported() const { - - return supported(VK_KHR_SWAPCHAIN_EXTENSION_NAME); -} -bool physical_device::surface_supported(index queue_family, VkSurfaceKHR surface) const { + bool physical_device::swapchain_supported() const { + return supported(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + } - VkBool32 res = VK_FALSE; - if (failed(vkGetPhysicalDeviceSurfaceSupportKHR(vk_physical_device, queue_family, surface, &res))) - return false; + bool physical_device::surface_supported(index queue_family, VkSurfaceKHR surface) const { + VkBool32 res = VK_FALSE; + if (failed(vkGetPhysicalDeviceSurfaceSupportKHR(vk_physical_device, queue_family, surface, &res))) + return false; - return res == VK_TRUE; -} + return res == VK_TRUE; + } -} // lava +} // namespace lava diff --git a/liblava/base/physical_device.hpp b/liblava/base/physical_device.hpp index 366556486825c360c9f27b77dbf95a995e036cb8..6439b20519153f7fc206deecee42cc7fea8bc4ef 100644 --- a/liblava/base/physical_device.hpp +++ b/liblava/base/physical_device.hpp @@ -8,45 +8,56 @@ namespace lava { -struct physical_device : id_obj { + struct physical_device : id_obj { + using list = std::vector<physical_device>; + using ref = physical_device const&; - using list = std::vector<physical_device>; - using ref = physical_device const&; + physical_device() = default; - physical_device() = default; + void initialize(VkPhysicalDevice vk_physical_device); - void initialize(VkPhysicalDevice vk_physical_device); + bool supported(string_ref extension) const; + bool get_queue_family(index& index, VkQueueFlags flags) const; - bool supported(string_ref extension) const; - bool get_queue_family(index& index, VkQueueFlags flags) const; + device::create_param create_default_device_param() const; - device::create_param create_default_device_param() const; + VkPhysicalDeviceProperties const& get_properties() const { + return properties; + } + VkPhysicalDeviceFeatures const& get_features() const { + return features; + } + VkPhysicalDeviceMemoryProperties const& get_memory_properties() const { + return memory_properties; + } - VkPhysicalDeviceProperties const& get_properties() const { return properties; } - VkPhysicalDeviceFeatures const& get_features() const { return features; } - VkPhysicalDeviceMemoryProperties const& get_memory_properties() const { return memory_properties; } + VkQueueFamilyPropertiesList const& get_queue_family_properties() const { + return queue_family_properties; + } + VkExtensionPropertiesList const& get_extension_properties() const { + return extension_properties; + } - VkQueueFamilyPropertiesList const& get_queue_family_properties() const { return queue_family_properties; } - VkExtensionPropertiesList const& get_extension_properties() const { return extension_properties; } + VkPhysicalDevice get() const { + return vk_physical_device; + } - VkPhysicalDevice get() const { return vk_physical_device; } + string get_device_type_string() const; - string get_device_type_string() const; + bool swapchain_supported() const; + bool surface_supported(index queue_family, VkSurfaceKHR surface) const; - bool swapchain_supported() const; - bool surface_supported(index queue_family, VkSurfaceKHR surface) const; + private: + VkPhysicalDevice vk_physical_device = nullptr; -private: - VkPhysicalDevice vk_physical_device = nullptr; + VkPhysicalDeviceProperties properties = {}; + VkPhysicalDeviceFeatures features = {}; + VkPhysicalDeviceMemoryProperties memory_properties = {}; - VkPhysicalDeviceProperties properties = {}; - VkPhysicalDeviceFeatures features = {}; - VkPhysicalDeviceMemoryProperties memory_properties = {}; + VkQueueFamilyPropertiesList queue_family_properties; + VkExtensionPropertiesList extension_properties; + }; - VkQueueFamilyPropertiesList queue_family_properties; - VkExtensionPropertiesList extension_properties; -}; + using physical_device_ptr = physical_device; -using physical_device_ptr = physical_device; - -} // lava +} // namespace lava diff --git a/liblava/block/attachment.hpp b/liblava/block/attachment.hpp index 1e487845f53666fa5d465240828ea185a89efe04..4a1e2bca02b0fc303386c1d17442844d9079150d 100644 --- a/liblava/block/attachment.hpp +++ b/liblava/block/attachment.hpp @@ -8,64 +8,76 @@ namespace lava { -struct attachment : id_obj { - - using ptr = std::shared_ptr<attachment>; - using list = std::vector<ptr>; - - explicit attachment(VkFormat format = VK_FORMAT_UNDEFINED, VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT) { - - description.flags = 0; - description.format = format; - description.samples = samples; - description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - description.finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; + struct attachment : id_obj { + using ptr = std::shared_ptr<attachment>; + using list = std::vector<ptr>; + + explicit attachment(VkFormat format = VK_FORMAT_UNDEFINED, VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT) { + description.flags = 0; + description.format = format; + description.samples = samples; + description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; + description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + description.finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } + + VkAttachmentDescription get_description() const { + return description; + } + + void set_format(VkFormat format) { + description.format = format; + } + void set_samples(VkSampleCountFlagBits samples) { + description.samples = samples; + } + + void set_op(VkAttachmentLoadOp load_op, VkAttachmentStoreOp store_op) { + set_load_op(load_op); + set_store_op(store_op); + } + + void set_load_op(VkAttachmentLoadOp load_op) { + description.loadOp = load_op; + } + void set_store_op(VkAttachmentStoreOp store_op) { + description.storeOp = store_op; + } + + void set_stencil_op(VkAttachmentLoadOp load_op, VkAttachmentStoreOp store_op) { + set_stencil_load_op(load_op); + set_stencil_store_op(store_op); + } + + void set_stencil_load_op(VkAttachmentLoadOp load_op) { + description.stencilLoadOp = load_op; + } + void set_stencil_store_op(VkAttachmentStoreOp store_op) { + description.stencilStoreOp = store_op; + } + + void set_layouts(VkImageLayout initial, VkImageLayout final) { + set_initial_layout(initial); + set_final_layout(final); + } + + void set_initial_layout(VkImageLayout layout) { + description.initialLayout = layout; + } + void set_final_layout(VkImageLayout layout) { + description.finalLayout = layout; + } + + private: + VkAttachmentDescription description; + }; + + inline attachment::ptr make_attachment(VkFormat format = VK_FORMAT_UNDEFINED, + VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT) { + return std::make_shared<attachment>(format, samples); } - VkAttachmentDescription get_description() const { return description; } - - void set_format(VkFormat format) { description.format = format; } - void set_samples(VkSampleCountFlagBits samples) { description.samples = samples; } - - void set_op(VkAttachmentLoadOp load_op, VkAttachmentStoreOp store_op) { - - set_load_op(load_op); - set_store_op(store_op); - } - - void set_load_op(VkAttachmentLoadOp load_op) { description.loadOp = load_op; } - void set_store_op(VkAttachmentStoreOp store_op) { description.storeOp = store_op; } - - void set_stencil_op(VkAttachmentLoadOp load_op, VkAttachmentStoreOp store_op) { - - set_stencil_load_op(load_op); - set_stencil_store_op(store_op); - } - - void set_stencil_load_op(VkAttachmentLoadOp load_op) { description.stencilLoadOp = load_op; } - void set_stencil_store_op(VkAttachmentStoreOp store_op) { description.stencilStoreOp = store_op; } - - void set_layouts(VkImageLayout initial, VkImageLayout final) { - - set_initial_layout(initial); - set_final_layout(final); - } - - void set_initial_layout(VkImageLayout layout) { description.initialLayout = layout; } - void set_final_layout(VkImageLayout layout) { description.finalLayout = layout; } - -private: - VkAttachmentDescription description; -}; - -inline attachment::ptr make_attachment(VkFormat format = VK_FORMAT_UNDEFINED, - VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT) { - - return std::make_shared<attachment>(format, samples); -} - -} // lava +} // namespace lava diff --git a/liblava/block/block.cpp b/liblava/block/block.cpp index 71333b022447ce8b8e703f63197e59c61bfebbfa..7cf2ffffe9c049bef55703ad19dda47daadae408 100644 --- a/liblava/block/block.cpp +++ b/liblava/block/block.cpp @@ -6,158 +6,140 @@ namespace lava { -bool command::create(device_ptr device, index frame_count, VkCommandPools cmd_pools) { - - buffers.resize(frame_count); - - for (auto i = 0u; i < frame_count; ++i) { - - VkCommandBufferAllocateInfo const allocate_info - { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, - .commandPool = cmd_pools.at(i), - .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, - .commandBufferCount = 1, - }; - if (failed(device->call().vkAllocateCommandBuffers(device->get(), &allocate_info, &buffers.at(i)))) { - - log()->error("create command buffers"); - return false; + bool command::create(device_ptr device, index frame_count, VkCommandPools cmd_pools) { + buffers.resize(frame_count); + + for (auto i = 0u; i < frame_count; ++i) { + VkCommandBufferAllocateInfo const allocate_info{ + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .commandPool = cmd_pools.at(i), + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandBufferCount = 1, + }; + if (failed(device->call().vkAllocateCommandBuffers(device->get(), &allocate_info, &buffers.at(i)))) { + log()->error("create command buffers"); + return false; + } } - } - return true; -} -void command::destroy(device_ptr device, VkCommandPools cmd_pools) { - - for (auto i = 0u; i < buffers.size(); ++i) - device->call().vkFreeCommandBuffers(device->get(), cmd_pools.at(i), 1, &buffers.at(i)); -} + return true; + } + void command::destroy(device_ptr device, VkCommandPools cmd_pools) { + for (auto i = 0u; i < buffers.size(); ++i) + device->call().vkFreeCommandBuffers(device->get(), cmd_pools.at(i), 1, &buffers.at(i)); + } -bool block::create(lava::device_ptr d, index frame_count, index queue_family) { + bool block::create(lava::device_ptr d, index frame_count, index queue_family) { + device = d; - device = d; - - current_frame = 0; + current_frame = 0; - cmd_pools.resize(frame_count); + cmd_pools.resize(frame_count); - for (auto i = 0u; i < frame_count; ++i) { + for (auto i = 0u; i < frame_count; ++i) { + VkCommandPoolCreateInfo const create_info{ + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .flags = 0, + .queueFamilyIndex = queue_family, + }; + if (failed(device->call().vkCreateCommandPool(device->get(), &create_info, memory::alloc(), &cmd_pools.at(i)))) { + log()->error("create block command pool"); + return false; + } + } - VkCommandPoolCreateInfo const create_info - { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .flags = 0, - .queueFamilyIndex = queue_family, - }; - if (failed(device->call().vkCreateCommandPool(device->get(), &create_info, memory::alloc(), &cmd_pools.at(i)))) { + for (auto& command : commands) + if (!command.second.create(device, frame_count, cmd_pools)) + return false; - log()->error("create block command pool"); - return false; - } + return true; } - for (auto& command : commands) - if (!command.second.create(device, frame_count, cmd_pools)) - return false; - - return true; -} + void block::destroy() { + for (auto& command : commands) + command.second.destroy(device, cmd_pools); -void block::destroy() { + for (auto i = 0u; i < cmd_pools.size(); ++i) + device->call().vkDestroyCommandPool(device->get(), cmd_pools.at(i), memory::alloc()); - for (auto& command : commands) - command.second.destroy(device, cmd_pools); + cmd_pools.clear(); + cmd_order.clear(); + commands.clear(); + } - for (auto i = 0u; i < cmd_pools.size(); ++i) - device->call().vkDestroyCommandPool(device->get(), cmd_pools.at(i), memory::alloc()); + id block::add_cmd(command::func func, bool active) { + command cmd; + cmd.on_func = func; + cmd.active = active; - cmd_pools.clear(); - cmd_order.clear(); - commands.clear(); -} + if (device && !cmd_pools.empty()) + if (!cmd.create(device, get_frame_count(), cmd_pools)) + return undef_id; -id block::add_cmd(command::func func, bool active) { + auto result = cmd.get_id(); - command cmd; - cmd.on_func = func; - cmd.active = active; + commands.emplace(result, std::move(cmd)); + cmd_order.push_back(&commands.at(result)); - if (device && !cmd_pools.empty()) - if (!cmd.create(device, get_frame_count(), cmd_pools)) - return undef_id; + return result; + } - auto result = cmd.get_id(); + void block::remove_cmd(id::ref cmd) { + if (!commands.count(cmd)) + return; - commands.emplace(result, std::move(cmd)); - cmd_order.push_back(&commands.at(result)); + auto& command = commands.at(cmd); + command.destroy(device, cmd_pools); - return result; -} + remove(cmd_order, &command); -void block::remove_cmd(id::ref cmd) { + commands.erase(cmd); + } - if (!commands.count(cmd)) - return; + bool block::process(index frame) { + current_frame = frame; - auto& command = commands.at(cmd); - command.destroy(device, cmd_pools); + if (failed(device->call().vkResetCommandPool(device->get(), cmd_pools.at(frame), 0))) { + log()->error("block reset command pool"); + return false; + } - remove(cmd_order, &command); + for (auto& command : cmd_order) { + if (!command->active) + continue; - commands.erase(cmd); -} + auto& cmd_buf = command->buffers.at(frame); -bool block::process(index frame) { + VkCommandBufferBeginInfo const begin_info{ + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, + }; + if (failed(device->call().vkBeginCommandBuffer(cmd_buf, &begin_info))) + return false; - current_frame = frame; + if (command->on_func) + command->on_func(cmd_buf); - if (failed(device->call().vkResetCommandPool(device->get(), cmd_pools.at(frame), 0))) { + if (failed(device->call().vkEndCommandBuffer(cmd_buf))) + return false; + } - log()->error("block reset command pool"); - return false; + return true; } - for (auto& command : cmd_order) { - - if (!command->active) - continue; - - auto& cmd_buf = command->buffers.at(frame); - - VkCommandBufferBeginInfo const begin_info - { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, - }; - if (failed(device->call().vkBeginCommandBuffer(cmd_buf, &begin_info))) + bool block::activated(id::ref command) { + if (!commands.count(command)) return false; - if (command->on_func) - command->on_func(cmd_buf); - - if (failed(device->call().vkEndCommandBuffer(cmd_buf))) - return false; + return commands.at(command).active; } - return true; -} - -bool block::activated(id::ref command) { - - if (!commands.count(command)) - return false; - - return commands.at(command).active; -} - -bool block::set_active(id::ref command, bool active) { - - if (!commands.count(command)) - return false; + bool block::set_active(id::ref command, bool active) { + if (!commands.count(command)) + return false; - commands.at(command).active = active; - return true; -} + commands.at(command).active = active; + return true; + } -} // lava +} // namespace lava diff --git a/liblava/block/block.hpp b/liblava/block/block.hpp index dd0bb0d509fa26df21dcdbff85cbc020766b1034..bd98d4209a0fcc0479ae3f1b08959fe6b7ace976 100644 --- a/liblava/block/block.hpp +++ b/liblava/block/block.hpp @@ -8,76 +8,95 @@ namespace lava { -struct command : id_obj { + struct command : id_obj { + using map = std::map<id, command>; + using list = std::vector<command*>; - using map = std::map<id, command>; - using list = std::vector<command*>; + VkCommandBuffers buffers = {}; - VkCommandBuffers buffers = {}; + using func = std::function<void(VkCommandBuffer)>; + func on_func; - using func = std::function<void(VkCommandBuffer)>; - func on_func; + bool active = true; - bool active = true; + bool create(device_ptr device, index frame_count, VkCommandPools command_pools); + void destroy(device_ptr device, VkCommandPools command_pools); + }; - bool create(device_ptr device, index frame_count, VkCommandPools command_pools); - void destroy(device_ptr device, VkCommandPools command_pools); -}; + struct block : id_obj { + using ptr = std::shared_ptr<block>; + using map = std::map<id, block>; + using list = std::vector<block*>; -struct block : id_obj { + ~block() { + destroy(); + } - using ptr = std::shared_ptr<block>; - using map = std::map<id, block>; - using list = std::vector<block*>; + bool create(device_ptr device, index frame_count, index queue_family); + void destroy(); - ~block() { destroy(); } + auto get_frame_count() const { + return to_index(cmd_pools.size()); + } - bool create(device_ptr device, index frame_count, index queue_family); - void destroy(); + id add_cmd(command::func func, bool active = true); + id add_command(command::func func, bool active = true) { + return add_cmd(func, active); + } - auto get_frame_count() const { return to_index(cmd_pools.size()); } + void remove_cmd(id::ref cmd); + void remove_command(id::ref cmd) { + remove_cmd(cmd); + } - id add_cmd(command::func func, bool active = true); - id add_command(command::func func, bool active = true) { return add_cmd(func, active); } + bool process(index frame); - void remove_cmd(id::ref cmd); - void remove_command(id::ref cmd) { remove_cmd(cmd); } + auto get_current_frame() const { + return current_frame; + } + auto get_command_buffer(id::ref cmd) const { + return commands.at(cmd).buffers.at(current_frame); + } + auto get_command_buffer(id::ref cmd, index frame) const { + return commands.at(cmd).buffers.at(frame); + } - bool process(index frame); - - auto get_current_frame() const { return current_frame; } - auto get_command_buffer(id::ref cmd) const { return commands.at(cmd).buffers.at(current_frame); } - auto get_command_buffer(id::ref cmd, index frame) const { return commands.at(cmd).buffers.at(frame); } + auto get_buffers() { + VkCommandBuffers result; - auto get_buffers() { + for (auto& cmd : cmd_order) + if (cmd->active) + result.push_back(cmd->buffers.at(current_frame)); - VkCommandBuffers result; + return result; + } - for (auto& cmd : cmd_order) - if (cmd->active) - result.push_back(cmd->buffers.at(current_frame)); + auto const& get_commands() const { + return commands; + } + auto const& get_cmd_order() const { + return cmd_order; + } - return result; - } - - auto const& get_commands() const { return commands; } - auto const& get_cmd_order() const { return cmd_order; } + bool activated(id::ref command); + bool set_active(id::ref command, bool active = true); - bool activated(id::ref command); - bool set_active(id::ref command, bool active = true); + auto get_device() { + return device; + } - auto get_device() { return device; } + private: + device_ptr device = nullptr; -private: - device_ptr device = nullptr; + index current_frame = 0; + VkCommandPools cmd_pools = {}; - index current_frame = 0; - VkCommandPools cmd_pools = {}; + command::map commands; + command::list cmd_order; + }; - command::map commands; - command::list cmd_order; -}; - -inline block::ptr make_block() { return std::make_shared<block>(); } + inline block::ptr make_block() { + return std::make_shared<block>(); + } -} // lava +} // namespace lava diff --git a/liblava/block/descriptor.cpp b/liblava/block/descriptor.cpp index c4b86ba92ba8e2e26591bbffc3eba4438e8cdf18..89534e20cf0a3d92ef23d6138dc1889ad7569f1b 100644 --- a/liblava/block/descriptor.cpp +++ b/liblava/block/descriptor.cpp @@ -6,112 +6,100 @@ namespace lava { -descriptor::binding::binding() { + descriptor::binding::binding() { + vk_binding.binding = 0; + vk_binding.descriptorType = VK_DESCRIPTOR_TYPE_MAX_ENUM; + vk_binding.descriptorCount = 0; + vk_binding.stageFlags = VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM; + vk_binding.pImmutableSamplers = nullptr; + } - vk_binding.binding = 0; - vk_binding.descriptorType = VK_DESCRIPTOR_TYPE_MAX_ENUM; - vk_binding.descriptorCount = 0; - vk_binding.stageFlags = VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM; - vk_binding.pImmutableSamplers = nullptr; -} + bool descriptor::create(device_ptr d) { + device = d; -bool descriptor::create(device_ptr d) { + VkDescriptorSetLayoutBindings layoutBindings; - device = d; + for (auto& binding : bindings) + layoutBindings.push_back(binding->get()); - VkDescriptorSetLayoutBindings layoutBindings; + VkDescriptorSetLayoutCreateInfo create_info{ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .bindingCount = to_ui32(layoutBindings.size()), + .pBindings = layoutBindings.data(), + }; - for (auto& binding : bindings) - layoutBindings.push_back(binding->get()); + return check(device->call().vkCreateDescriptorSetLayout(device->get(), &create_info, memory::alloc(), &layout)); + } - VkDescriptorSetLayoutCreateInfo create_info - { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .bindingCount = to_ui32(layoutBindings.size()), - .pBindings = layoutBindings.data(), - }; - - return check(device->call().vkCreateDescriptorSetLayout(device->get(), &create_info, memory::alloc(), &layout)); -} + void descriptor::destroy() { + if (!layout) + return; -void descriptor::destroy() { + device->call().vkDestroyDescriptorSetLayout(device->get(), layout, memory::alloc()); + layout = 0; - if (!layout) - return; + // keep device for descriptors + } - device->call().vkDestroyDescriptorSetLayout(device->get(), layout, memory::alloc()); - layout = 0; + void descriptor::add_binding(index binding, VkDescriptorType descriptor_type, VkShaderStageFlags stage_flags) { + auto item = make_descriptor_binding(binding); - // keep device for descriptors -} + item->set_type(descriptor_type); + item->set_stage_flags(stage_flags); -void descriptor::add_binding(index binding, VkDescriptorType descriptor_type, VkShaderStageFlags stage_flags) { + add(item); + } - auto item = make_descriptor_binding(binding); - - item->set_type(descriptor_type); - item->set_stage_flags(stage_flags); + VkDescriptorSet descriptor::allocate_set() { + VkDescriptorSet descriptor_set = 0; - add(item); -} + VkDescriptorSetAllocateInfo const alloc_info{ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .descriptorPool = device->get_descriptor_pool(), + .descriptorSetCount = 1, + .pSetLayouts = &layout, + }; -VkDescriptorSet descriptor::allocate_set() { + if (failed(device->call().vkAllocateDescriptorSets(device->get(), &alloc_info, &descriptor_set))) + return 0; - VkDescriptorSet descriptor_set = 0; + return descriptor_set; + } - VkDescriptorSetAllocateInfo const alloc_info - { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - .descriptorPool = device->get_descriptor_pool(), - .descriptorSetCount = 1, - .pSetLayouts = &layout, - }; + bool descriptor::free_set(VkDescriptorSet descriptor_set) { + std::array<VkDescriptorSet, 1> const descriptor_sets = { descriptor_set }; - if (failed(device->call().vkAllocateDescriptorSets(device->get(), &alloc_info, &descriptor_set))) - return 0; + return check(device->call().vkFreeDescriptorSets(device->get(), device->get_descriptor_pool(), + to_ui32(descriptor_sets.size()), descriptor_sets.data())); + } - return descriptor_set; -} + VkDescriptorSets descriptor::allocate_sets(ui32 size) { + VkDescriptorSets result(size); -bool descriptor::free_set(VkDescriptorSet descriptor_set) { + VkDescriptorSetAllocateInfo const alloc_info{ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .descriptorPool = device->get_descriptor_pool(), + .descriptorSetCount = size, + .pSetLayouts = &layout, + }; - std::array<VkDescriptorSet, 1> const descriptor_sets = { descriptor_set }; + if (failed(device->call().vkAllocateDescriptorSets(device->get(), &alloc_info, result.data()))) + return {}; - return check(device->call().vkFreeDescriptorSets(device->get(), device->get_descriptor_pool(), - to_ui32(descriptor_sets.size()), descriptor_sets.data())); -} + return result; + } -VkDescriptorSets descriptor::allocate_sets(ui32 size) { + bool descriptor::free_sets(VkDescriptorSets const& descriptor_sets) { + return check(device->call().vkFreeDescriptorSets(device->get(), device->get_descriptor_pool(), + to_ui32(descriptor_sets.size()), descriptor_sets.data())); + } - VkDescriptorSets result(size); + descriptor::binding::ptr make_descriptor_binding(index index) { + auto binding = std::make_shared<descriptor::binding>(); - VkDescriptorSetAllocateInfo const alloc_info - { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - .descriptorPool = device->get_descriptor_pool(), - .descriptorSetCount = size, - .pSetLayouts = &layout, - }; + binding->set(index); + binding->set_count(1); + return binding; + } - if (failed(device->call().vkAllocateDescriptorSets(device->get(), &alloc_info, result.data()))) - return {}; - - return result; -} - -bool descriptor::free_sets(VkDescriptorSets const& descriptor_sets) { - - return check(device->call().vkFreeDescriptorSets(device->get(), device->get_descriptor_pool(), - to_ui32(descriptor_sets.size()), descriptor_sets.data())); -} - -descriptor::binding::ptr make_descriptor_binding(index index) { - - auto binding = std::make_shared<descriptor::binding>(); - - binding->set(index); - binding->set_count(1); - return binding; -} - -} // lava +} // namespace lava diff --git a/liblava/block/descriptor.hpp b/liblava/block/descriptor.hpp index ff8a3022fabf633bf7a17ad42dfa57482b6213e4..2675246ba6870c125ed5b4542cb92ab7e54d3917 100644 --- a/liblava/block/descriptor.hpp +++ b/liblava/block/descriptor.hpp @@ -8,67 +8,95 @@ namespace lava { -struct descriptor : id_obj { + struct descriptor : id_obj { + struct binding : id_obj { + using ptr = std::shared_ptr<binding>; + using list = std::vector<ptr>; - struct binding : id_obj { + explicit binding(); - using ptr = std::shared_ptr<binding>; - using list = std::vector<ptr>; - - explicit binding(); + VkDescriptorSetLayoutBinding get() const { + return vk_binding; + } - VkDescriptorSetLayoutBinding get() const { return vk_binding; } + void set(index index) { + vk_binding.binding = index; + } - void set(index index) { vk_binding.binding = index; } + void set_type(VkDescriptorType descriptor_type) { + vk_binding.descriptorType = descriptor_type; + } - void set_type(VkDescriptorType descriptor_type) { vk_binding.descriptorType = descriptor_type; } + void set_count(ui32 descriptor_count) { + vk_binding.descriptorCount = descriptor_count; + } - void set_count(ui32 descriptor_count) { vk_binding.descriptorCount = descriptor_count; } + void set_stage_flags(VkShaderStageFlags stage_flags) { + vk_binding.stageFlags = stage_flags; + } - void set_stage_flags(VkShaderStageFlags stage_flags) { vk_binding.stageFlags = stage_flags; } + void set_samplers(VkSampler const* immutable_samplers) { + vk_binding.pImmutableSamplers = immutable_samplers; + } - void set_samplers(VkSampler const* immutable_samplers) { vk_binding.pImmutableSamplers = immutable_samplers; } - - private: - VkDescriptorSetLayoutBinding vk_binding; - }; + private: + VkDescriptorSetLayoutBinding vk_binding; + }; - using ptr = std::shared_ptr<descriptor>; - using list = std::vector<ptr>; + using ptr = std::shared_ptr<descriptor>; + using list = std::vector<ptr>; - void add_binding(index binding, VkDescriptorType descriptor_type, VkShaderStageFlags stage_flags); + void add_binding(index binding, VkDescriptorType descriptor_type, VkShaderStageFlags stage_flags); - void add(binding::ptr const& binding) { bindings.push_back(binding); } + void add(binding::ptr const& binding) { + bindings.push_back(binding); + } - bool create(device_ptr device); - void destroy(); + bool create(device_ptr device); + void destroy(); - ui32 get_binding_count() const { return to_ui32(bindings.size()); } - binding::list const& get_bindings() { return bindings; } + ui32 get_binding_count() const { + return to_ui32(bindings.size()); + } + binding::list const& get_bindings() { + return bindings; + } - VkDescriptorSetLayout get() const { return layout; } + VkDescriptorSetLayout get() const { + return layout; + } - VkDescriptorSet allocate_set(); - VkDescriptorSet allocate() { return allocate_set(); } + VkDescriptorSet allocate_set(); + VkDescriptorSet allocate() { + return allocate_set(); + } - bool free_set(VkDescriptorSet descriptor_set); - bool free(VkDescriptorSet descriptor_set) { return free_set(descriptor_set); } + bool free_set(VkDescriptorSet descriptor_set); + bool free(VkDescriptorSet descriptor_set) { + return free_set(descriptor_set); + } - VkDescriptorSets allocate_sets(ui32 size); - VkDescriptorSets allocate(ui32 size) { return allocate_sets(size); } + VkDescriptorSets allocate_sets(ui32 size); + VkDescriptorSets allocate(ui32 size) { + return allocate_sets(size); + } - bool free_sets(VkDescriptorSets const& descriptor_sets); - bool free(VkDescriptorSets const& descriptor_sets) { return free_sets(descriptor_sets); } + bool free_sets(VkDescriptorSets const& descriptor_sets); + bool free(VkDescriptorSets const& descriptor_sets) { + return free_sets(descriptor_sets); + } -private: - device_ptr device = nullptr; + private: + device_ptr device = nullptr; - VkDescriptorSetLayout layout = 0; - binding::list bindings; -}; + VkDescriptorSetLayout layout = 0; + binding::list bindings; + }; -inline descriptor::ptr make_descriptor() { return std::make_shared<descriptor>(); } + inline descriptor::ptr make_descriptor() { + return std::make_shared<descriptor>(); + } -descriptor::binding::ptr make_descriptor_binding(index index); + descriptor::binding::ptr make_descriptor_binding(index index); -} // lava +} // namespace lava diff --git a/liblava/block/pipeline.cpp b/liblava/block/pipeline.cpp index 803632fb176a3d2618d379e3dd710cb1dbd7268e..d1299ebc0e602a070aff4d73beaa08879654bded 100644 --- a/liblava/block/pipeline.cpp +++ b/liblava/block/pipeline.cpp @@ -6,500 +6,457 @@ namespace lava { -bool pipeline_layout::create(device_ptr d) { - - device = d; - - VkDescriptorSetLayouts layouts; - for (auto& layout : descriptors) - layouts.push_back(layout->get()); - - VkPipelineLayoutCreateInfo const pipelineLayoutInfo - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .setLayoutCount = to_ui32(layouts.size()), - .pSetLayouts = layouts.data(), - .pushConstantRangeCount = to_ui32(push_constant_ranges.size()), - .pPushConstantRanges = push_constant_ranges.data(), - }; - - return check(device->call().vkCreatePipelineLayout(device->get(), &pipelineLayoutInfo, memory::alloc(), &layout)); -} - -void pipeline_layout::destroy() { - - if (!layout) - return; - - device->call().vkDestroyPipelineLayout(device->get(), layout, memory::alloc()); - layout = 0; -} - -void pipeline_layout::bind_descriptor_set(VkCommandBuffer cmd_buf, VkDescriptorSet descriptor_set, offset_list offsets, VkPipelineBindPoint bind_point) { - - std::array<VkDescriptorSet, 1> const descriptor_sets = { descriptor_set }; - - vkCmdBindDescriptorSets(cmd_buf, bind_point, layout, 0, to_ui32(descriptor_sets.size()), descriptor_sets.data(), to_ui32(offsets.size()), offsets.data()); -} - -pipeline::pipeline(device_ptr device_, VkPipelineCache pipeline_cache) : device(device_), pipeline_cache(pipeline_cache) {} - -pipeline::~pipeline() { - - pipeline_cache = 0; - layout = nullptr; -} - -bool pipeline::create() { return create_internal(); } - -void pipeline::destroy() { - - destroy_internal(); - - if (vk_pipeline) { - - device->call().vkDestroyPipeline(device->get(), vk_pipeline, memory::alloc()); - vk_pipeline = 0; + bool pipeline_layout::create(device_ptr d) { + device = d; + + VkDescriptorSetLayouts layouts; + for (auto& layout : descriptors) + layouts.push_back(layout->get()); + + VkPipelineLayoutCreateInfo const pipelineLayoutInfo{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = to_ui32(layouts.size()), + .pSetLayouts = layouts.data(), + .pushConstantRangeCount = to_ui32(push_constant_ranges.size()), + .pPushConstantRanges = push_constant_ranges.data(), + }; + + return check(device->call().vkCreatePipelineLayout(device->get(), &pipelineLayoutInfo, memory::alloc(), &layout)); } - layout = nullptr; -} - -pipeline::shader_stage::shader_stage() { - - create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - create_info.pNext = nullptr; - create_info.flags = 0; - create_info.stage = VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM; - create_info.module = 0; - create_info.pName = _main_; - create_info.pSpecializationInfo = &specialization_info; - - specialization_info.mapEntryCount = 0; - specialization_info.pMapEntries = nullptr; - specialization_info.dataSize = 0; - specialization_info.pData = nullptr; -} - -pipeline::shader_stage::~shader_stage() { - - destroy(); -} - -void pipeline::shader_stage::add_specialization_entry(VkSpecializationMapEntry const& specialization) { - - specialization_entries.push_back(specialization); - specialization_info.mapEntryCount = to_ui32(specialization_entries.size()); - specialization_info.pMapEntries = specialization_entries.data(); -} - -bool pipeline::shader_stage::create(device_ptr d, data const& shader_data, data const& specialization_data) { - - device = d; + void pipeline_layout::destroy() { + if (!layout) + return; - if (specialization_data.size > 0) { - specialization_data_copy.free(); - specialization_data_copy.set(specialization_data.size); - memcpy(specialization_data_copy.ptr, specialization_data.ptr, specialization_data.size); - - specialization_info.dataSize = specialization_data_copy.size; - specialization_info.pData = specialization_data_copy.ptr; + device->call().vkDestroyPipelineLayout(device->get(), layout, memory::alloc()); + layout = 0; } - create_info.module = create_shader_module(device, shader_data); - - return create_info.module != 0; -} - -void pipeline::shader_stage::destroy() { - - if (!create_info.module) - return; - - device->call().vkDestroyShaderModule(device->get(), create_info.module, memory::alloc()); - - create_info.module = 0; - device = nullptr; -} - -pipeline::shader_stage::ptr make_pipeline_shader_stage(VkShaderStageFlagBits stage) { - - auto shaderStage = std::make_shared<pipeline::shader_stage>(); - - shaderStage->set_stage(stage); - return shaderStage; -} - -pipeline::shader_stage::ptr create_pipeline_shader_stage(device_ptr device, data const& data, VkShaderStageFlagBits stage) { - - auto shaderStage = make_pipeline_shader_stage(stage); - - if (!shaderStage->create(device, data)) - return nullptr; - - return shaderStage; -} - -graphics_pipeline::graphics_pipeline(device_ptr device_, VkPipelineCache pipeline_cache) : pipeline(device_, pipeline_cache) { - - info.vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - info.vertex_input_state.pNext = nullptr; - info.vertex_input_state.flags = 0; - info.vertex_input_state.vertexBindingDescriptionCount = 0; - info.vertex_input_state.pVertexBindingDescriptions = nullptr; - info.vertex_input_state.vertexAttributeDescriptionCount = 0; - info.vertex_input_state.pVertexAttributeDescriptions = nullptr; - - info.input_assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - info.input_assembly_state.pNext = nullptr; - info.input_assembly_state.flags = 0; - info.input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - info.input_assembly_state.primitiveRestartEnable = VK_FALSE; - - info.viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - info.viewport_state.pNext = nullptr; - info.viewport_state.flags = 0; - info.viewport_state.viewportCount = 1; - info.viewport_state.pViewports = nullptr; - info.viewport_state.scissorCount = 1; - info.viewport_state.pScissors = nullptr; - - info.multisample_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - info.multisample_state.pNext = nullptr; - info.multisample_state.flags = 0; - info.multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - info.multisample_state.sampleShadingEnable = VK_FALSE; - info.multisample_state.minSampleShading = 0.f; - info.multisample_state.pSampleMask = nullptr; - info.multisample_state.alphaToCoverageEnable = VK_FALSE; - info.multisample_state.alphaToOneEnable = VK_FALSE; - - info.depth_stencil_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - info.depth_stencil_state.pNext = nullptr; - info.depth_stencil_state.flags = 0; - info.depth_stencil_state.depthTestEnable = VK_FALSE; - info.depth_stencil_state.depthWriteEnable = VK_FALSE; - info.depth_stencil_state.depthCompareOp = VK_COMPARE_OP_NEVER; - info.depth_stencil_state.depthBoundsTestEnable = VK_FALSE; - info.depth_stencil_state.stencilTestEnable = VK_FALSE; - info.depth_stencil_state.front = {}; - info.depth_stencil_state.back = {}; - info.depth_stencil_state.minDepthBounds = 0.f; - info.depth_stencil_state.maxDepthBounds = 0.f; - - info.rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - info.rasterization_state.pNext = nullptr; - info.rasterization_state.flags = 0; - info.rasterization_state.depthClampEnable = VK_FALSE; - info.rasterization_state.rasterizerDiscardEnable = VK_FALSE; - info.rasterization_state.polygonMode = VK_POLYGON_MODE_FILL; - info.rasterization_state.cullMode = VK_CULL_MODE_NONE; - info.rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - info.rasterization_state.depthBiasEnable = VK_FALSE; - info.rasterization_state.depthBiasConstantFactor = 0.f; - info.rasterization_state.depthBiasClamp = 0.f; - info.rasterization_state.depthBiasSlopeFactor = 0.f; - info.rasterization_state.lineWidth = 1.f; - - color_blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - color_blend_state.pNext = nullptr; - color_blend_state.flags = 0; - color_blend_state.logicOpEnable = VK_FALSE; - color_blend_state.logicOp = VK_LOGIC_OP_CLEAR; - color_blend_state.attachmentCount = 0; - color_blend_state.pAttachments = nullptr; - color_blend_state.blendConstants[0] = 0.f; - color_blend_state.blendConstants[1] = 0.f; - color_blend_state.blendConstants[2] = 0.f; - color_blend_state.blendConstants[3] = 0.f; - - dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamic_state.pNext = nullptr; - dynamic_state.flags = 0; - dynamic_state.dynamicStateCount = 0; - dynamic_state.pDynamicStates = nullptr; - - set_dynamic_states({ VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }); -} - -void graphics_pipeline::set_vertex_input_binding(VkVertexInputBindingDescription const& description) { - - VkVertexInputBindingDescriptions descriptions; - descriptions.push_back(description); + void pipeline_layout::bind_descriptor_set(VkCommandBuffer cmd_buf, VkDescriptorSet descriptor_set, offset_list offsets, VkPipelineBindPoint bind_point) { + std::array<VkDescriptorSet, 1> const descriptor_sets = { descriptor_set }; - set_vertex_input_bindings(descriptions); -} - -void graphics_pipeline::set_vertex_input_bindings(VkVertexInputBindingDescriptions const& descriptions) { - - vertex_input_bindings = descriptions; - - info.vertex_input_state.vertexBindingDescriptionCount = to_ui32(vertex_input_bindings.size()); - info.vertex_input_state.pVertexBindingDescriptions = vertex_input_bindings.data(); -} - -void graphics_pipeline::set_vertex_input_attribute(VkVertexInputAttributeDescription const& attribute) { - - VkVertexInputAttributeDescriptions attributes; - attributes.push_back(attribute); - - set_vertex_input_attributes(attributes); -} - -void graphics_pipeline::set_vertex_input_attributes(VkVertexInputAttributeDescriptions const& attributes) { + vkCmdBindDescriptorSets(cmd_buf, bind_point, layout, 0, to_ui32(descriptor_sets.size()), descriptor_sets.data(), to_ui32(offsets.size()), offsets.data()); + } - vertex_input_attributes = attributes; + pipeline::pipeline(device_ptr device_, VkPipelineCache pipeline_cache) + : device(device_), pipeline_cache(pipeline_cache) {} - info.vertex_input_state.vertexAttributeDescriptionCount = to_ui32(vertex_input_attributes.size()); - info.vertex_input_state.pVertexAttributeDescriptions = vertex_input_attributes.data(); -} + pipeline::~pipeline() { + pipeline_cache = 0; + layout = nullptr; + } -void graphics_pipeline::set_depth_test_and_write(bool test_enable, bool write_enable) { + bool pipeline::create() { + return create_internal(); + } - info.depth_stencil_state.depthTestEnable = test_enable ? VK_TRUE : VK_FALSE; - info.depth_stencil_state.depthWriteEnable = write_enable ? VK_TRUE : VK_FALSE; -} + void pipeline::destroy() { + destroy_internal(); -void graphics_pipeline::set_depth_compare_op(VkCompareOp compare_op) { + if (vk_pipeline) { + device->call().vkDestroyPipeline(device->get(), vk_pipeline, memory::alloc()); + vk_pipeline = 0; + } - info.depth_stencil_state.depthCompareOp = compare_op; -} + layout = nullptr; + } -void graphics_pipeline::set_rasterization_cull_mode(VkCullModeFlags cull_mode) { + pipeline::shader_stage::shader_stage() { + create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = 0; + create_info.stage = VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM; + create_info.module = 0; + create_info.pName = _main_; + create_info.pSpecializationInfo = &specialization_info; + + specialization_info.mapEntryCount = 0; + specialization_info.pMapEntries = nullptr; + specialization_info.dataSize = 0; + specialization_info.pData = nullptr; + } - info.rasterization_state.cullMode = cull_mode; -} + pipeline::shader_stage::~shader_stage() { + destroy(); + } -void graphics_pipeline::set_rasterization_front_face(VkFrontFace front_face) { + void pipeline::shader_stage::add_specialization_entry(VkSpecializationMapEntry const& specialization) { + specialization_entries.push_back(specialization); + specialization_info.mapEntryCount = to_ui32(specialization_entries.size()); + specialization_info.pMapEntries = specialization_entries.data(); + } - info.rasterization_state.frontFace = front_face; -} + bool pipeline::shader_stage::create(device_ptr d, data const& shader_data, data const& specialization_data) { + device = d; -void graphics_pipeline::set_rasterization_polygon_mode(VkPolygonMode polygon_mode) { + if (specialization_data.size > 0) { + specialization_data_copy.free(); + specialization_data_copy.set(specialization_data.size); + memcpy(specialization_data_copy.ptr, specialization_data.ptr, specialization_data.size); - info.rasterization_state.polygonMode = polygon_mode; -} + specialization_info.dataSize = specialization_data_copy.size; + specialization_info.pData = specialization_data_copy.ptr; + } -VkPipelineColorBlendAttachmentState graphics_pipeline::create_color_blend_attachment() { + create_info.module = create_shader_module(device, shader_data); - return - { - .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_MINUS_SRC_ALPHA, - .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, - .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, - }; -} + return create_info.module != 0; + } -void graphics_pipeline::add_color_blend_attachment(VkPipelineColorBlendAttachmentState const& attachment) { + void pipeline::shader_stage::destroy() { + if (!create_info.module) + return; - color_blend_attachment_states.push_back(attachment); + device->call().vkDestroyShaderModule(device->get(), create_info.module, memory::alloc()); - color_blend_state.attachmentCount = to_ui32(color_blend_attachment_states.size()); - color_blend_state.pAttachments = color_blend_attachment_states.data(); -} + create_info.module = 0; + device = nullptr; + } -void graphics_pipeline::set_dynamic_states(VkDynamicStates const& states) { + pipeline::shader_stage::ptr make_pipeline_shader_stage(VkShaderStageFlagBits stage) { + auto shaderStage = std::make_shared<pipeline::shader_stage>(); - dynamic_states = states; + shaderStage->set_stage(stage); + return shaderStage; + } - dynamic_state.dynamicStateCount = to_ui32(dynamic_states.size()); - dynamic_state.pDynamicStates = dynamic_states.data(); -} + pipeline::shader_stage::ptr create_pipeline_shader_stage(device_ptr device, data const& data, VkShaderStageFlagBits stage) { + auto shaderStage = make_pipeline_shader_stage(stage); -void graphics_pipeline::add_dynamic_state(VkDynamicState state) { + if (!shaderStage->create(device, data)) + return nullptr; - dynamic_states.push_back(state); - set_dynamic_states(dynamic_states); -} + return shaderStage; + } -bool graphics_pipeline::add_shader_stage(data const& data, VkShaderStageFlagBits stage) { + graphics_pipeline::graphics_pipeline(device_ptr device_, VkPipelineCache pipeline_cache) + : pipeline(device_, pipeline_cache) { + info.vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + info.vertex_input_state.pNext = nullptr; + info.vertex_input_state.flags = 0; + info.vertex_input_state.vertexBindingDescriptionCount = 0; + info.vertex_input_state.pVertexBindingDescriptions = nullptr; + info.vertex_input_state.vertexAttributeDescriptionCount = 0; + info.vertex_input_state.pVertexAttributeDescriptions = nullptr; + + info.input_assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + info.input_assembly_state.pNext = nullptr; + info.input_assembly_state.flags = 0; + info.input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + info.input_assembly_state.primitiveRestartEnable = VK_FALSE; + + info.viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + info.viewport_state.pNext = nullptr; + info.viewport_state.flags = 0; + info.viewport_state.viewportCount = 1; + info.viewport_state.pViewports = nullptr; + info.viewport_state.scissorCount = 1; + info.viewport_state.pScissors = nullptr; + + info.multisample_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + info.multisample_state.pNext = nullptr; + info.multisample_state.flags = 0; + info.multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + info.multisample_state.sampleShadingEnable = VK_FALSE; + info.multisample_state.minSampleShading = 0.f; + info.multisample_state.pSampleMask = nullptr; + info.multisample_state.alphaToCoverageEnable = VK_FALSE; + info.multisample_state.alphaToOneEnable = VK_FALSE; + + info.depth_stencil_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + info.depth_stencil_state.pNext = nullptr; + info.depth_stencil_state.flags = 0; + info.depth_stencil_state.depthTestEnable = VK_FALSE; + info.depth_stencil_state.depthWriteEnable = VK_FALSE; + info.depth_stencil_state.depthCompareOp = VK_COMPARE_OP_NEVER; + info.depth_stencil_state.depthBoundsTestEnable = VK_FALSE; + info.depth_stencil_state.stencilTestEnable = VK_FALSE; + info.depth_stencil_state.front = {}; + info.depth_stencil_state.back = {}; + info.depth_stencil_state.minDepthBounds = 0.f; + info.depth_stencil_state.maxDepthBounds = 0.f; + + info.rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + info.rasterization_state.pNext = nullptr; + info.rasterization_state.flags = 0; + info.rasterization_state.depthClampEnable = VK_FALSE; + info.rasterization_state.rasterizerDiscardEnable = VK_FALSE; + info.rasterization_state.polygonMode = VK_POLYGON_MODE_FILL; + info.rasterization_state.cullMode = VK_CULL_MODE_NONE; + info.rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + info.rasterization_state.depthBiasEnable = VK_FALSE; + info.rasterization_state.depthBiasConstantFactor = 0.f; + info.rasterization_state.depthBiasClamp = 0.f; + info.rasterization_state.depthBiasSlopeFactor = 0.f; + info.rasterization_state.lineWidth = 1.f; + + color_blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + color_blend_state.pNext = nullptr; + color_blend_state.flags = 0; + color_blend_state.logicOpEnable = VK_FALSE; + color_blend_state.logicOp = VK_LOGIC_OP_CLEAR; + color_blend_state.attachmentCount = 0; + color_blend_state.pAttachments = nullptr; + color_blend_state.blendConstants[0] = 0.f; + color_blend_state.blendConstants[1] = 0.f; + color_blend_state.blendConstants[2] = 0.f; + color_blend_state.blendConstants[3] = 0.f; + + dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamic_state.pNext = nullptr; + dynamic_state.flags = 0; + dynamic_state.dynamicStateCount = 0; + dynamic_state.pDynamicStates = nullptr; + + set_dynamic_states({ VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }); + } - if (!data.ptr) { + void graphics_pipeline::set_vertex_input_binding(VkVertexInputBindingDescription const& description) { + VkVertexInputBindingDescriptions descriptions; + descriptions.push_back(description); - log()->error("graphics pipeline shader stage data"); - return false; + set_vertex_input_bindings(descriptions); } - auto shader_stage = create_pipeline_shader_stage(device, data, stage); - if (!shader_stage) { + void graphics_pipeline::set_vertex_input_bindings(VkVertexInputBindingDescriptions const& descriptions) { + vertex_input_bindings = descriptions; - log()->error("create graphics pipeline shader stage"); - return false; + info.vertex_input_state.vertexBindingDescriptionCount = to_ui32(vertex_input_bindings.size()); + info.vertex_input_state.pVertexBindingDescriptions = vertex_input_bindings.data(); } - add(shader_stage); - return true; -} + void graphics_pipeline::set_vertex_input_attribute(VkVertexInputAttributeDescription const& attribute) { + VkVertexInputAttributeDescriptions attributes; + attributes.push_back(attribute); -bool graphics_pipeline::add_shader_stage(name filename, VkShaderStageFlagBits stage) { + set_vertex_input_attributes(attributes); + } - return add_shader_stage(file_data(filename).get(), stage); -} + void graphics_pipeline::set_vertex_input_attributes(VkVertexInputAttributeDescriptions const& attributes) { + vertex_input_attributes = attributes; -void graphics_pipeline::copy_to(graphics_pipeline* target) const { + info.vertex_input_state.vertexAttributeDescriptionCount = to_ui32(vertex_input_attributes.size()); + info.vertex_input_state.pVertexAttributeDescriptions = vertex_input_attributes.data(); + } - target->set_layout(layout); + void graphics_pipeline::set_depth_test_and_write(bool test_enable, bool write_enable) { + info.depth_stencil_state.depthTestEnable = test_enable ? VK_TRUE : VK_FALSE; + info.depth_stencil_state.depthWriteEnable = write_enable ? VK_TRUE : VK_FALSE; + } - target->info = info; + void graphics_pipeline::set_depth_compare_op(VkCompareOp compare_op) { + info.depth_stencil_state.depthCompareOp = compare_op; + } - target->shader_stages = shader_stages; - target->vertex_input_bindings = vertex_input_bindings; - target->vertex_input_attributes = vertex_input_attributes; + void graphics_pipeline::set_rasterization_cull_mode(VkCullModeFlags cull_mode) { + info.rasterization_state.cullMode = cull_mode; + } - target->color_blend_attachment_states = color_blend_attachment_states; - target->color_blend_state = color_blend_state; - target->dynamic_states = dynamic_states; -} + void graphics_pipeline::set_rasterization_front_face(VkFrontFace front_face) { + info.rasterization_state.frontFace = front_face; + } -bool graphics_pipeline::create_internal() { + void graphics_pipeline::set_rasterization_polygon_mode(VkPolygonMode polygon_mode) { + info.rasterization_state.polygonMode = polygon_mode; + } - if(on_create){ - if(!on_create(info)) - return false; + VkPipelineColorBlendAttachmentState graphics_pipeline::create_color_blend_attachment() { + return { + .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_MINUS_SRC_ALPHA, + .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, + .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, + }; } - VkPipelineShaderStageCreateInfos stages; + void graphics_pipeline::add_color_blend_attachment(VkPipelineColorBlendAttachmentState const& attachment) { + color_blend_attachment_states.push_back(attachment); - for (auto& shader_stage : shader_stages) - stages.push_back(shader_stage->get_create_info()); + color_blend_state.attachmentCount = to_ui32(color_blend_attachment_states.size()); + color_blend_state.pAttachments = color_blend_attachment_states.data(); + } - VkGraphicsPipelineCreateInfo const vk_create_info - { - .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .stageCount = to_ui32(stages.size()), - .pStages = stages.data(), - .pVertexInputState = &info.vertex_input_state, - .pInputAssemblyState = &info.input_assembly_state, - .pTessellationState = nullptr, - .pViewportState = &info.viewport_state, - .pRasterizationState = &info.rasterization_state, - .pMultisampleState = &info.multisample_state, - .pDepthStencilState = &info.depth_stencil_state, - .pColorBlendState = &color_blend_state, - .pDynamicState = &dynamic_state, - .layout = layout->get(), - .renderPass = render_pass, - .subpass = to_ui32(subpass), - .basePipelineHandle = 0, - .basePipelineIndex = -1, - }; + void graphics_pipeline::set_dynamic_states(VkDynamicStates const& states) { + dynamic_states = states; - std::array<VkGraphicsPipelineCreateInfo, 1> const vk_info = { vk_create_info }; + dynamic_state.dynamicStateCount = to_ui32(dynamic_states.size()); + dynamic_state.pDynamicStates = dynamic_states.data(); + } - return check(device->call().vkCreateGraphicsPipelines(device->get(), pipeline_cache, - to_ui32(vk_info.size()), vk_info.data(), - memory::alloc(), &vk_pipeline)); -} + void graphics_pipeline::add_dynamic_state(VkDynamicState state) { + dynamic_states.push_back(state); + set_dynamic_states(dynamic_states); + } -void graphics_pipeline::destroy_internal() { shader_stages.clear(); } + bool graphics_pipeline::add_shader_stage(data const& data, VkShaderStageFlagBits stage) { + if (!data.ptr) { + log()->error("graphics pipeline shader stage data"); + return false; + } -void graphics_pipeline::bind(VkCommandBuffer cmd_buf) { + auto shader_stage = create_pipeline_shader_stage(device, data, stage); + if (!shader_stage) { + log()->error("create graphics pipeline shader stage"); + return false; + } - vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, vk_pipeline); -} + add(shader_stage); + return true; + } -void graphics_pipeline::set_viewport_and_scissor(VkCommandBuffer cmd_buf, uv2 size) { + bool graphics_pipeline::add_shader_stage(name filename, VkShaderStageFlagBits stage) { + return add_shader_stage(file_data(filename).get(), stage); + } - VkViewport viewportParam; - viewportParam.x = 0.f; - viewportParam.y = 0.f; - viewportParam.width = to_r32(size.x); - viewportParam.height = to_r32(size.y); - viewportParam.minDepth = 0.f; - viewportParam.maxDepth = 1.f; + void graphics_pipeline::copy_to(graphics_pipeline* target) const { + target->set_layout(layout); - VkRect2D scissorParam; - scissorParam.offset = { 0, 0 }; - scissorParam.extent = { size.x, size.y }; + target->info = info; - if (size_type == size_type::absolute) { + target->shader_stages = shader_stages; + target->vertex_input_bindings = vertex_input_bindings; + target->vertex_input_attributes = vertex_input_attributes; - viewportParam = viewport; - scissorParam = scissor; + target->color_blend_attachment_states = color_blend_attachment_states; + target->color_blend_state = color_blend_state; + target->dynamic_states = dynamic_states; } - else if (size_type == size_type::relative) { - - viewportParam.x = viewport.x * size.x; - viewportParam.y = viewport.y * size.y; - viewportParam.width = viewport.width * size.x; - viewportParam.height = viewport.height * size.y; - scissorParam.offset.x = scissor.offset.x * size.x; - scissorParam.offset.y = scissor.offset.y * size.y; - scissorParam.extent.width = scissor.extent.width * size.x; - scissorParam.extent.height = scissor.extent.height * size.y; + bool graphics_pipeline::create_internal() { + if (on_create) { + if (!on_create(info)) + return false; + } + + VkPipelineShaderStageCreateInfos stages; + + for (auto& shader_stage : shader_stages) + stages.push_back(shader_stage->get_create_info()); + + VkGraphicsPipelineCreateInfo const vk_create_info{ + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .stageCount = to_ui32(stages.size()), + .pStages = stages.data(), + .pVertexInputState = &info.vertex_input_state, + .pInputAssemblyState = &info.input_assembly_state, + .pTessellationState = nullptr, + .pViewportState = &info.viewport_state, + .pRasterizationState = &info.rasterization_state, + .pMultisampleState = &info.multisample_state, + .pDepthStencilState = &info.depth_stencil_state, + .pColorBlendState = &color_blend_state, + .pDynamicState = &dynamic_state, + .layout = layout->get(), + .renderPass = render_pass, + .subpass = to_ui32(subpass), + .basePipelineHandle = 0, + .basePipelineIndex = -1, + }; + + std::array<VkGraphicsPipelineCreateInfo, 1> const vk_info = { vk_create_info }; + + return check(device->call().vkCreateGraphicsPipelines(device->get(), pipeline_cache, + to_ui32(vk_info.size()), vk_info.data(), + memory::alloc(), &vk_pipeline)); } - else { - viewport = viewportParam; - scissor = scissorParam; + void graphics_pipeline::destroy_internal() { + shader_stages.clear(); } - std::array<VkViewport, 1> const viewports = { viewportParam }; - vkCmdSetViewport(cmd_buf, 0, to_ui32(viewports.size()), viewports.data()); - - std::array<VkRect2D, 1> const scissors = { scissorParam }; - vkCmdSetScissor(cmd_buf, 0, to_ui32(scissors.size()), scissors.data()); -} - -void compute_pipeline::bind(VkCommandBuffer cmd_buf) { - - vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline); -} - -bool compute_pipeline::set_shader_stage(data const& data, VkShaderStageFlagBits stage) { - - if (!data.ptr) { - - log()->error("compute pipeline shader stage data"); - return false; + void graphics_pipeline::bind(VkCommandBuffer cmd_buf) { + vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, vk_pipeline); } - auto shader_stage = create_pipeline_shader_stage(device, data, stage); - if (!shader_stage) { - - log()->error("create compute pipeline shader stage"); - return false; + void graphics_pipeline::set_viewport_and_scissor(VkCommandBuffer cmd_buf, uv2 size) { + VkViewport viewportParam; + viewportParam.x = 0.f; + viewportParam.y = 0.f; + viewportParam.width = to_r32(size.x); + viewportParam.height = to_r32(size.y); + viewportParam.minDepth = 0.f; + viewportParam.maxDepth = 1.f; + + VkRect2D scissorParam; + scissorParam.offset = { 0, 0 }; + scissorParam.extent = { size.x, size.y }; + + if (size_type == size_type::absolute) { + viewportParam = viewport; + scissorParam = scissor; + } else if (size_type == size_type::relative) { + viewportParam.x = viewport.x * size.x; + viewportParam.y = viewport.y * size.y; + viewportParam.width = viewport.width * size.x; + viewportParam.height = viewport.height * size.y; + + scissorParam.offset.x = scissor.offset.x * size.x; + scissorParam.offset.y = scissor.offset.y * size.y; + scissorParam.extent.width = scissor.extent.width * size.x; + scissorParam.extent.height = scissor.extent.height * size.y; + } else { + viewport = viewportParam; + scissor = scissorParam; + } + + std::array<VkViewport, 1> const viewports = { viewportParam }; + vkCmdSetViewport(cmd_buf, 0, to_ui32(viewports.size()), viewports.data()); + + std::array<VkRect2D, 1> const scissors = { scissorParam }; + vkCmdSetScissor(cmd_buf, 0, to_ui32(scissors.size()), scissors.data()); } - set(shader_stage); - return true; -} + void compute_pipeline::bind(VkCommandBuffer cmd_buf) { + vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline); + } -bool compute_pipeline::set_shader_stage(name filename, VkShaderStageFlagBits stage) { + bool compute_pipeline::set_shader_stage(data const& data, VkShaderStageFlagBits stage) { + if (!data.ptr) { + log()->error("compute pipeline shader stage data"); + return false; + } - return set_shader_stage(file_data(filename).get(), stage); -} + auto shader_stage = create_pipeline_shader_stage(device, data, stage); + if (!shader_stage) { + log()->error("create compute pipeline shader stage"); + return false; + } -bool compute_pipeline::create_internal() { + set(shader_stage); + return true; + } - VkComputePipelineCreateInfo const create_info - { - .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - .stage = shader_stage->get_create_info(), - .layout = layout->get(), - .basePipelineHandle = 0, - .basePipelineIndex = -1, - }; + bool compute_pipeline::set_shader_stage(name filename, VkShaderStageFlagBits stage) { + return set_shader_stage(file_data(filename).get(), stage); + } - std::array<VkComputePipelineCreateInfo, 1> const info = { create_info }; + bool compute_pipeline::create_internal() { + VkComputePipelineCreateInfo const create_info{ + .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, + .stage = shader_stage->get_create_info(), + .layout = layout->get(), + .basePipelineHandle = 0, + .basePipelineIndex = -1, + }; - return check(device->call().vkCreateComputePipelines(device->get(), pipeline_cache, to_ui32(info.size()), - info.data(), memory::alloc(), &vk_pipeline)); -} + std::array<VkComputePipelineCreateInfo, 1> const info = { create_info }; -void compute_pipeline::destroy_internal() { shader_stage = nullptr; } + return check(device->call().vkCreateComputePipelines(device->get(), pipeline_cache, to_ui32(info.size()), + info.data(), memory::alloc(), &vk_pipeline)); + } -void compute_pipeline::copy_to(compute_pipeline* target) const { + void compute_pipeline::destroy_internal() { + shader_stage = nullptr; + } - target->set_layout(layout); + void compute_pipeline::copy_to(compute_pipeline* target) const { + target->set_layout(layout); - target->shader_stage = shader_stage; -} + target->shader_stage = shader_stage; + } -} // lava +} // namespace lava diff --git a/liblava/block/pipeline.hpp b/liblava/block/pipeline.hpp index ca2c1236788fa91d0648649fee4e3c8c8ed2b7f0..7118246f3ba32b06b8204f709274a15dcd450738 100644 --- a/liblava/block/pipeline.hpp +++ b/liblava/block/pipeline.hpp @@ -4,292 +4,376 @@ #pragma once -#include <liblava/block/descriptor.hpp> #include <liblava/base/base.hpp> +#include <liblava/block/descriptor.hpp> #include <liblava/core/math.hpp> namespace lava { -struct pipeline_layout : id_obj { - - using ptr = std::shared_ptr<pipeline_layout>; - using list = std::vector<ptr>; + struct pipeline_layout : id_obj { + using ptr = std::shared_ptr<pipeline_layout>; + using list = std::vector<ptr>; - void add(descriptor::ptr const& descriptor) { descriptors.push_back(descriptor); } - void add(VkPushConstantRange const& range) { push_constant_ranges.push_back(range); } - - void add_layout(descriptor::ptr const& layout) { add(layout); } - void add_range(VkPushConstantRange const& range) { add(range); } + void add(descriptor::ptr const& descriptor) { + descriptors.push_back(descriptor); + } + void add(VkPushConstantRange const& range) { + push_constant_ranges.push_back(range); + } + + void add_layout(descriptor::ptr const& layout) { + add(layout); + } + void add_range(VkPushConstantRange const& range) { + add(range); + } + + bool create(device_ptr device); + void destroy(); - bool create(device_ptr device); - void destroy(); + VkPipelineLayout get() const { + return layout; + } - VkPipelineLayout get() const { return layout; } + descriptor::list const& get_descriptors() const { + return descriptors; + } - descriptor::list const& get_descriptors() const { return descriptors; } + VkPushConstantRanges const& get_push_constant_ranges() const { + return push_constant_ranges; + } - VkPushConstantRanges const& get_push_constant_ranges() const { return push_constant_ranges; } + using offset_list = std::vector<ui32>; - using offset_list = std::vector<ui32>; + void bind_descriptor_set(VkCommandBuffer cmd_buf, VkDescriptorSet descriptor_set, offset_list offsets = {}, VkPipelineBindPoint bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS); + void bind(VkCommandBuffer cmd_buf, VkDescriptorSet descriptor_set, offset_list offsets = {}, VkPipelineBindPoint bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS) { + bind_descriptor_set(cmd_buf, descriptor_set, offsets, bind_point); + } - void bind_descriptor_set(VkCommandBuffer cmd_buf, VkDescriptorSet descriptor_set, offset_list offsets = {}, VkPipelineBindPoint bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS); - void bind(VkCommandBuffer cmd_buf, VkDescriptorSet descriptor_set, offset_list offsets = {}, VkPipelineBindPoint bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS) { + private: + device_ptr device = nullptr; - bind_descriptor_set(cmd_buf, descriptor_set, offsets, bind_point); - } + VkPipelineLayout layout = 0; -private: - device_ptr device = nullptr; + descriptor::list descriptors; + VkPushConstantRanges push_constant_ranges; + }; - VkPipelineLayout layout = 0; + inline pipeline_layout::ptr make_pipeline_layout() { + return std::make_shared<pipeline_layout>(); + } - descriptor::list descriptors; - VkPushConstantRanges push_constant_ranges; -}; + constexpr name _main_ = "main"; -inline pipeline_layout::ptr make_pipeline_layout() { return std::make_shared<pipeline_layout>(); } + struct pipeline : id_obj { + using ptr = std::shared_ptr<pipeline>; + using list = std::vector<ptr>; -constexpr name _main_ = "main"; + using process_func = std::function<void(VkCommandBuffer)>; + process_func on_process; -struct pipeline : id_obj { + explicit pipeline(device_ptr device, VkPipelineCache pipeline_cache = 0); + ~pipeline() override; - using ptr = std::shared_ptr<pipeline>; - using list = std::vector<ptr>; + bool create(); + void destroy(); - using process_func = std::function<void(VkCommandBuffer)>; - process_func on_process; + virtual void bind(VkCommandBuffer cmd_buf) = 0; - explicit pipeline(device_ptr device, VkPipelineCache pipeline_cache = 0); - ~pipeline() override; + void set_active(bool value = true) { + active = value; + } + bool activated() const { + return active; + } - bool create(); - void destroy(); + void toggle() { + active = !active; + } - virtual void bind(VkCommandBuffer cmd_buf) = 0; + void set_auto_bind(bool value = true) { + auto_bind_active = value; + } + bool auto_bind() const { + return auto_bind_active; + } - void set_active(bool value = true) { active = value; } - bool activated() const { return active; } + bool ready() const { + return vk_pipeline != 0; + } - void toggle() { active = !active; } + VkPipeline get() const { + return vk_pipeline; + } + device_ptr get_device() { + return device; + } - void set_auto_bind(bool value = true) { auto_bind_active = value; } - bool auto_bind() const { return auto_bind_active; } + pipeline_layout::ptr get_layout() const { + return layout; + } + void set_layout(pipeline_layout::ptr const& value) { + layout = value; + } - bool ready() const { return vk_pipeline != 0; } + struct shader_stage { + using ptr = std::shared_ptr<shader_stage>; + using list = std::vector<ptr>; - VkPipeline get() const { return vk_pipeline; } - device_ptr get_device() { return device; } + explicit shader_stage(); + ~shader_stage(); - pipeline_layout::ptr get_layout() const { return layout; } - void set_layout(pipeline_layout::ptr const& value) { layout = value; } + void set_stage(VkShaderStageFlagBits stage) { + create_info.stage = stage; + } - struct shader_stage { + void add_specialization_entry(VkSpecializationMapEntry const& specialization); - using ptr = std::shared_ptr<shader_stage>; - using list = std::vector<ptr>; + bool create(device_ptr device, data const& shader_data, data const& specialization_data = data()); + void destroy(); - explicit shader_stage(); - ~shader_stage(); + VkPipelineShaderStageCreateInfo const& get_create_info() const { + return create_info; + } - void set_stage(VkShaderStageFlagBits stage) { create_info.stage = stage; } + private: + device_ptr device = nullptr; - void add_specialization_entry(VkSpecializationMapEntry const& specialization); + VkPipelineShaderStageCreateInfo create_info; + VkSpecializationInfo specialization_info; - bool create(device_ptr device, data const& shader_data, data const& specialization_data = data()); - void destroy(); + VkSpecializationMapEntries specialization_entries; + data specialization_data_copy; + }; - VkPipelineShaderStageCreateInfo const& get_create_info() const { return create_info; } + protected: + virtual bool create_internal() = 0; + virtual void destroy_internal() = 0; - private: device_ptr device = nullptr; + VkPipeline vk_pipeline = 0; - VkPipelineShaderStageCreateInfo create_info; - VkSpecializationInfo specialization_info; + VkPipelineCache pipeline_cache = 0; + pipeline_layout::ptr layout; - VkSpecializationMapEntries specialization_entries; - data specialization_data_copy; + private: + bool active = true; + bool auto_bind_active = true; }; -protected: - virtual bool create_internal() = 0; - virtual void destroy_internal() = 0; + pipeline::shader_stage::ptr make_pipeline_shader_stage(VkShaderStageFlagBits stage); + pipeline::shader_stage::ptr create_pipeline_shader_stage(device_ptr device, data const& data, VkShaderStageFlagBits stage); - device_ptr device = nullptr; - VkPipeline vk_pipeline = 0; + struct graphics_pipeline : pipeline { + using ptr = std::shared_ptr<graphics_pipeline>; + using map = std::map<id, ptr>; + using list = std::vector<ptr>; - VkPipelineCache pipeline_cache = 0; - pipeline_layout::ptr layout; + enum class size_type : type { + + input = 0, + absolute, + relative + }; + + struct create_info { + VkPipelineVertexInputStateCreateInfo vertex_input_state; + + VkPipelineInputAssemblyStateCreateInfo input_assembly_state; + VkPipelineViewportStateCreateInfo viewport_state; + VkPipelineMultisampleStateCreateInfo multisample_state; + VkPipelineDepthStencilStateCreateInfo depth_stencil_state; + VkPipelineRasterizationStateCreateInfo rasterization_state; + }; + + explicit graphics_pipeline(device_ptr device, VkPipelineCache pipeline_cache); + + void bind(VkCommandBuffer cmd_buf) override; + void set_viewport_and_scissor(VkCommandBuffer cmd_buf, uv2 size); + + void set_render_pass(VkRenderPass pass) { + render_pass = pass; + } + void set(VkRenderPass pass) { + set_render_pass(pass); + } + + VkRenderPass get_render_pass() const { + return render_pass; + } + + index get_subpass() const { + return subpass; + } + void set_subpass(index value) { + subpass = value; + } + + bool create(VkRenderPass pass) { + set(pass); + + return pipeline::create(); + } + + void set_vertex_input_binding(VkVertexInputBindingDescription const& description); + void set_vertex_input_bindings(VkVertexInputBindingDescriptions const& descriptions); + + void set_vertex_input_attribute(VkVertexInputAttributeDescription const& attribute); + void set_vertex_input_attributes(VkVertexInputAttributeDescriptions const& attributes); + + void set_depth_test_and_write(bool test_enable = true, bool write_enable = true); + void set_depth_compare_op(VkCompareOp compare_op); + + void set_rasterization_cull_mode(VkCullModeFlags cull_mode); + void set_rasterization_front_face(VkFrontFace front_face); + void set_rasterization_polygon_mode(VkPolygonMode polygon_mode); + + static VkPipelineColorBlendAttachmentState create_color_blend_attachment(); + void add_color_blend_attachment(VkPipelineColorBlendAttachmentState const& attachment = create_color_blend_attachment()); + + void set_dynamic_states(VkDynamicStates const& states); + void add_dynamic_state(VkDynamicState state); + + bool add_shader_stage(data const& data, VkShaderStageFlagBits stage); + bool add_shader(data const& data, VkShaderStageFlagBits stage) { + return add_shader_stage(data, stage); + } + + bool add_shader_stage(name filename, VkShaderStageFlagBits stage); + bool add_shader(name filename, VkShaderStageFlagBits stage) { + return add_shader_stage(filename, stage); + } + + void add(shader_stage::ptr const& shader_stage) { + shader_stages.push_back(shader_stage); + } + + shader_stage::list const& get_shader_stages() const { + return shader_stages; + } + void clear_shader_stages() { + shader_stages.clear(); + } + + void set_auto_size(bool value = true) { + auto_size = value; + } + bool auto_sizing() const { + return auto_size; + } + + VkViewport get_viewport() const { + return viewport; + } + void set_viewport(VkViewport value) { + viewport = value; + } + + VkRect2D get_scissor() const { + return scissor; + } + void set_scissor(VkRect2D value) { + scissor = value; + } + + size_type get_size_type() const { + return size_type; + } + void set_size_type(size_type value) { + size_type = value; + } + + void copy_to(graphics_pipeline* target) const; + void copy_from(ptr const& source) { + source->copy_to(this); + } + + void set_line_width(r32 value) { + line_width = value; + } + r32 get_line_width() const { + return line_width; + } + + bool auto_line_width() const { + return auto_line_width_active; + } + void set_auto_line_width(bool value = true) { + auto_line_width_active = value; + } + + void set_line_width(VkCommandBuffer cmd_buf) { + vkCmdSetLineWidth(cmd_buf, line_width); + } + + using create_func = std::function<bool(create_info&)>; + create_func on_create; -private: - bool active = true; - bool auto_bind_active = true; -}; + private: + bool create_internal() override; + void destroy_internal() override; -pipeline::shader_stage::ptr make_pipeline_shader_stage(VkShaderStageFlagBits stage); -pipeline::shader_stage::ptr create_pipeline_shader_stage(device_ptr device, data const& data, VkShaderStageFlagBits stage); + VkRenderPass render_pass = 0; + index subpass = 0; -struct graphics_pipeline : pipeline { + create_info info; - using ptr = std::shared_ptr<graphics_pipeline>; - using map = std::map<id, ptr>; - using list = std::vector<ptr>; + VkVertexInputBindingDescriptions vertex_input_bindings; + VkVertexInputAttributeDescriptions vertex_input_attributes; - enum class size_type : type { + VkPipelineColorBlendAttachmentStates color_blend_attachment_states; + VkPipelineColorBlendStateCreateInfo color_blend_state; + VkPipelineDynamicStateCreateInfo dynamic_state; - input = 0, - absolute, - relative - }; + VkDynamicStates dynamic_states; - struct create_info{ + shader_stage::list shader_stages; - VkPipelineVertexInputStateCreateInfo vertex_input_state; + graphics_pipeline::size_type size_type = size_type::input; + VkViewport viewport; + VkRect2D scissor; - VkPipelineInputAssemblyStateCreateInfo input_assembly_state; - VkPipelineViewportStateCreateInfo viewport_state; - VkPipelineMultisampleStateCreateInfo multisample_state; - VkPipelineDepthStencilStateCreateInfo depth_stencil_state; - VkPipelineRasterizationStateCreateInfo rasterization_state; + bool auto_size = true; + bool auto_line_width_active = false; + r32 line_width = 1.f; }; - explicit graphics_pipeline(device_ptr device, VkPipelineCache pipeline_cache); - - void bind(VkCommandBuffer cmd_buf) override; - void set_viewport_and_scissor(VkCommandBuffer cmd_buf, uv2 size); - - void set_render_pass(VkRenderPass pass) { render_pass = pass; } - void set(VkRenderPass pass) { set_render_pass(pass); } - - VkRenderPass get_render_pass() const { return render_pass; } - - index get_subpass() const { return subpass; } - void set_subpass(index value) { subpass = value; } - - bool create(VkRenderPass pass) { - - set(pass); - - return pipeline::create(); + inline graphics_pipeline::ptr make_graphics_pipeline(device_ptr device, VkPipelineCache pipeline_cache = 0) { + return std::make_shared<graphics_pipeline>(device, pipeline_cache); } - void set_vertex_input_binding(VkVertexInputBindingDescription const& description); - void set_vertex_input_bindings(VkVertexInputBindingDescriptions const& descriptions); - - void set_vertex_input_attribute(VkVertexInputAttributeDescription const& attribute); - void set_vertex_input_attributes(VkVertexInputAttributeDescriptions const& attributes); - - void set_depth_test_and_write(bool test_enable = true, bool write_enable = true); - void set_depth_compare_op(VkCompareOp compare_op); - - void set_rasterization_cull_mode(VkCullModeFlags cull_mode); - void set_rasterization_front_face(VkFrontFace front_face); - void set_rasterization_polygon_mode(VkPolygonMode polygon_mode); - - static VkPipelineColorBlendAttachmentState create_color_blend_attachment(); - void add_color_blend_attachment(VkPipelineColorBlendAttachmentState const& attachment = create_color_blend_attachment()); - - void set_dynamic_states(VkDynamicStates const& states); - void add_dynamic_state(VkDynamicState state); - - bool add_shader_stage(data const& data, VkShaderStageFlagBits stage); - bool add_shader(data const& data, VkShaderStageFlagBits stage) { return add_shader_stage(data, stage); } - - bool add_shader_stage(name filename, VkShaderStageFlagBits stage); - bool add_shader(name filename, VkShaderStageFlagBits stage) { return add_shader_stage(filename, stage); } - - void add(shader_stage::ptr const& shader_stage) { shader_stages.push_back(shader_stage); } - - shader_stage::list const& get_shader_stages() const { return shader_stages; } - void clear_shader_stages() { shader_stages.clear(); } - - void set_auto_size(bool value = true) { auto_size = value; } - bool auto_sizing() const { return auto_size; } - - VkViewport get_viewport() const { return viewport; } - void set_viewport(VkViewport value) { viewport = value; } - - VkRect2D get_scissor() const { return scissor; } - void set_scissor(VkRect2D value) { scissor = value; } - - size_type get_size_type() const { return size_type; } - void set_size_type(size_type value) { size_type = value; } - - void copy_to(graphics_pipeline* target) const; - void copy_from(ptr const& source) { source->copy_to(this); } - - void set_line_width(r32 value) { line_width = value; } - r32 get_line_width() const { return line_width; } - - bool auto_line_width() const { return auto_line_width_active; } - void set_auto_line_width(bool value = true) { auto_line_width_active = value; } - - void set_line_width(VkCommandBuffer cmd_buf) { vkCmdSetLineWidth(cmd_buf, line_width); } - - using create_func = std::function<bool(create_info&)>; - create_func on_create; - -private: - bool create_internal() override; - void destroy_internal() override; - - VkRenderPass render_pass = 0; - index subpass = 0; - - create_info info; - - VkVertexInputBindingDescriptions vertex_input_bindings; - VkVertexInputAttributeDescriptions vertex_input_attributes; - - VkPipelineColorBlendAttachmentStates color_blend_attachment_states; - VkPipelineColorBlendStateCreateInfo color_blend_state; - VkPipelineDynamicStateCreateInfo dynamic_state; - - VkDynamicStates dynamic_states; - - shader_stage::list shader_stages; - - graphics_pipeline::size_type size_type = size_type::input; - VkViewport viewport; - VkRect2D scissor; - - bool auto_size = true; - bool auto_line_width_active = false; - r32 line_width = 1.f; -}; - -inline graphics_pipeline::ptr make_graphics_pipeline(device_ptr device, VkPipelineCache pipeline_cache = 0) { - - return std::make_shared<graphics_pipeline>(device, pipeline_cache); -} - -struct compute_pipeline : pipeline { - - using ptr = std::shared_ptr<compute_pipeline>; - using map = std::map<id, ptr>; - using list = std::vector<ptr>; - - using pipeline::pipeline; + struct compute_pipeline : pipeline { + using ptr = std::shared_ptr<compute_pipeline>; + using map = std::map<id, ptr>; + using list = std::vector<ptr>; - void bind(VkCommandBuffer cmdBuffer) override; + using pipeline::pipeline; - bool set_shader_stage(data const& data, VkShaderStageFlagBits stage); - bool set_shader_stage(name filename, VkShaderStageFlagBits stage); - void set(shader_stage::ptr const& stage) { shader_stage = stage; } - shader_stage::ptr const& get_shader_stage() const { return shader_stage; } + void bind(VkCommandBuffer cmdBuffer) override; - void copy_to(compute_pipeline* target) const; - void copy_from(ptr const& source) { source->copy_to(this); } + bool set_shader_stage(data const& data, VkShaderStageFlagBits stage); + bool set_shader_stage(name filename, VkShaderStageFlagBits stage); + void set(shader_stage::ptr const& stage) { + shader_stage = stage; + } + shader_stage::ptr const& get_shader_stage() const { + return shader_stage; + } -private: - bool create_internal() override; - void destroy_internal() override; + void copy_to(compute_pipeline* target) const; + void copy_from(ptr const& source) { + source->copy_to(this); + } - shader_stage::ptr shader_stage; -}; + private: + bool create_internal() override; + void destroy_internal() override; -inline compute_pipeline::ptr make_compute_pipeline(device_ptr device, VkPipelineCache pipeline_cache = 0) { + shader_stage::ptr shader_stage; + }; - return std::make_shared<compute_pipeline>(device, pipeline_cache); -} + inline compute_pipeline::ptr make_compute_pipeline(device_ptr device, VkPipelineCache pipeline_cache = 0) { + return std::make_shared<compute_pipeline>(device, pipeline_cache); + } -} // lava +} // namespace lava diff --git a/liblava/block/render_pass.cpp b/liblava/block/render_pass.cpp index a833b9391ca9c7bd8e7c981f49b22a0af91c1b48..13b56d16a9369a49eae5f0ffdab56ce84fefe0e3 100644 --- a/liblava/block/render_pass.cpp +++ b/liblava/block/render_pass.cpp @@ -6,183 +6,164 @@ namespace lava { -render_pass::render_pass(device_ptr d) : device(d) { - - on_created = [&](VkAttachmentsRef target_attachments, rect area) { return on_target_created(target_attachments, area); }; - on_destroyed = [&]() { on_target_destroyed(); }; -} - -bool render_pass::create(VkAttachmentsRef target_attachments, rect area) { + render_pass::render_pass(device_ptr d) + : device(d) { + on_created = [&](VkAttachmentsRef target_attachments, rect area) { return on_target_created(target_attachments, area); }; + on_destroyed = [&]() { on_target_destroyed(); }; + } - std::vector<VkAttachmentDescription> attachment_descriptions; + bool render_pass::create(VkAttachmentsRef target_attachments, rect area) { + std::vector<VkAttachmentDescription> attachment_descriptions; - for (auto& attachment : attachments) - attachment_descriptions.push_back(attachment->get_description()); + for (auto& attachment : attachments) + attachment_descriptions.push_back(attachment->get_description()); - std::vector<VkSubpassDescription> subpass_descriptions; + std::vector<VkSubpassDescription> subpass_descriptions; - for (auto& subpass : subpasses) - subpass_descriptions.push_back(subpass->get_description()); + for (auto& subpass : subpasses) + subpass_descriptions.push_back(subpass->get_description()); - std::vector<VkSubpassDependency> subpass_dependencies; + std::vector<VkSubpassDependency> subpass_dependencies; - for (auto& dependency : dependencies) - subpass_dependencies.push_back(dependency->get_dependency()); + for (auto& dependency : dependencies) + subpass_dependencies.push_back(dependency->get_dependency()); - VkRenderPassCreateInfo const create_info - { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .attachmentCount = to_ui32(attachment_descriptions.size()), - .pAttachments = attachment_descriptions.data(), - .subpassCount = to_ui32(subpass_descriptions.size()), - .pSubpasses = subpass_descriptions.data(), - .dependencyCount = to_ui32(subpass_dependencies.size()), - .pDependencies = subpass_dependencies.data(), - }; + VkRenderPassCreateInfo const create_info{ + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + .attachmentCount = to_ui32(attachment_descriptions.size()), + .pAttachments = attachment_descriptions.data(), + .subpassCount = to_ui32(subpass_descriptions.size()), + .pSubpasses = subpass_descriptions.data(), + .dependencyCount = to_ui32(subpass_dependencies.size()), + .pDependencies = subpass_dependencies.data(), + }; - if (!check(device->call().vkCreateRenderPass(device->get(), &create_info, memory::alloc(), &vk_render_pass))) { + if (!check(device->call().vkCreateRenderPass(device->get(), &create_info, memory::alloc(), &vk_render_pass))) { + log()->error("create render pass"); + return false; + } - log()->error("create render pass"); - return false; + return on_target_created(target_attachments, area); } - return on_target_created(target_attachments, area); -} - -void render_pass::destroy() { - - attachments.clear(); - dependencies.clear(); + void render_pass::destroy() { + attachments.clear(); + dependencies.clear(); - for (auto& subpass : subpasses) - subpass->destroy(); + for (auto& subpass : subpasses) + subpass->destroy(); - subpasses.clear(); + subpasses.clear(); - on_target_destroyed(); + on_target_destroyed(); - if (vk_render_pass) { + if (vk_render_pass) { + device->call().vkDestroyRenderPass(device->get(), vk_render_pass, memory::alloc()); + vk_render_pass = 0; + } - device->call().vkDestroyRenderPass(device->get(), vk_render_pass, memory::alloc()); - vk_render_pass = 0; + device = nullptr; } - device = nullptr; -} - -void render_pass::begin(VkCommandBuffer cmd_buf, index frame) { - - auto origin = area.get_origin(); - auto size = area.get_size(); - - VkRenderPassBeginInfo const info - { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderPass = vk_render_pass, - .framebuffer = framebuffers[frame], - .renderArea = { { origin.x, origin.y }, { size.x, size.y } }, - .clearValueCount = to_ui32(clear_values.size()), - .pClearValues = clear_values.data(), - }; + void render_pass::begin(VkCommandBuffer cmd_buf, index frame) { + auto origin = area.get_origin(); + auto size = area.get_size(); - device->call().vkCmdBeginRenderPass(cmd_buf, &info, VK_SUBPASS_CONTENTS_INLINE); -} - -void render_pass::end(VkCommandBuffer cmd_buf) { + VkRenderPassBeginInfo const info{ + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderPass = vk_render_pass, + .framebuffer = framebuffers[frame], + .renderArea = { { origin.x, origin.y }, { size.x, size.y } }, + .clearValueCount = to_ui32(clear_values.size()), + .pClearValues = clear_values.data(), + }; - device->call().vkCmdEndRenderPass(cmd_buf); -} + device->call().vkCmdBeginRenderPass(cmd_buf, &info, VK_SUBPASS_CONTENTS_INLINE); + } -void render_pass::process(VkCommandBuffer cmd_buf, index frame) { + void render_pass::end(VkCommandBuffer cmd_buf) { + device->call().vkCmdEndRenderPass(cmd_buf); + } - begin(cmd_buf, frame); + void render_pass::process(VkCommandBuffer cmd_buf, index frame) { + begin(cmd_buf, frame); - ui32 count = 0; + ui32 count = 0; - for (auto& subpass : subpasses) { + for (auto& subpass : subpasses) { + if (count > 0) + device->call().vkCmdNextSubpass(cmd_buf, VK_SUBPASS_CONTENTS_INLINE); - if (count > 0) - device->call().vkCmdNextSubpass(cmd_buf, VK_SUBPASS_CONTENTS_INLINE); + if (!subpass->activated()) + continue; - if (!subpass->activated()) - continue; + subpass->process(cmd_buf, area.get_size()); - subpass->process(cmd_buf, area.get_size()); + ++count; + } - ++count; + end(cmd_buf); } - end(cmd_buf); -} + void render_pass::set_clear_color(v3 value) { + clear_values.resize(2); -void render_pass::set_clear_color(v3 value) { + clear_values[0].color.float32[0] = value.r; + clear_values[0].color.float32[1] = value.g; + clear_values[0].color.float32[2] = value.b; + clear_values[0].color.float32[3] = 1.f; - clear_values.resize(2); - - clear_values[0].color.float32[0] = value.r; - clear_values[0].color.float32[1] = value.g; - clear_values[0].color.float32[2] = value.b; - clear_values[0].color.float32[3] = 1.f; - - clear_values[1].depthStencil = { 1.f, 0 }; -} + clear_values[1].depthStencil = { 1.f, 0 }; + } -v3 render_pass::get_clear_color() const { - - return - { - clear_values[0].color.float32[0], - clear_values[0].color.float32[1], - clear_values[0].color.float32[2], - }; -} + v3 render_pass::get_clear_color() const { + return { + clear_values[0].color.float32[0], + clear_values[0].color.float32[1], + clear_values[0].color.float32[2], + }; + } -bool render_pass::on_target_created(VkAttachmentsRef target_attachments, rect a) { + bool render_pass::on_target_created(VkAttachmentsRef target_attachments, rect a) { + area = a; + framebuffers.resize(target_attachments.size()); - area = a; - framebuffers.resize(target_attachments.size()); + auto size = area.get_size(); - auto size = area.get_size(); + ui32 count = 0; - ui32 count = 0; + for (auto& attachment : target_attachments) { + VkFramebufferCreateInfo const create_info{ + .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + .renderPass = vk_render_pass, + .attachmentCount = to_ui32(attachment.size()), + .pAttachments = attachment.data(), + .width = size.x, + .height = size.y, + .layers = 1, + }; - for (auto& attachment : target_attachments) { + if (failed(device->call().vkCreateFramebuffer(device->get(), &create_info, memory::alloc(), &framebuffers[count]))) { + log()->error("create render pass target"); + return false; + } - VkFramebufferCreateInfo const create_info - { - .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - .renderPass = vk_render_pass, - .attachmentCount = to_ui32(attachment.size()), - .pAttachments = attachment.data(), - .width = size.x, - .height = size.y, - .layers = 1, - }; - - if (failed(device->call().vkCreateFramebuffer(device->get(), &create_info, memory::alloc(), &framebuffers[count]))) { - - log()->error("create render pass target"); - return false; + ++count; } - ++count; + return true; } - return true; -} - -void render_pass::on_target_destroyed() { + void render_pass::on_target_destroyed() { + for (auto& framebuffer : framebuffers) { + if (!framebuffer) + continue; - for (auto& framebuffer : framebuffers) { - - if (!framebuffer) - continue; + device->call().vkDestroyFramebuffer(device->get(), framebuffer, memory::alloc()); + framebuffer = 0; + } - device->call().vkDestroyFramebuffer(device->get(), framebuffer, memory::alloc()); - framebuffer = 0; + framebuffers.clear(); } - framebuffers.clear(); -} - -} // lava +} // namespace lava diff --git a/liblava/block/render_pass.hpp b/liblava/block/render_pass.hpp index 814f7535ce950345720dc7cf8ac29a682f8383f8..fab22d6a9af80c5164399f6658dd2b9554f08013 100644 --- a/liblava/block/render_pass.hpp +++ b/liblava/block/render_pass.hpp @@ -4,67 +4,96 @@ #pragma once +#include <liblava/base/device.hpp> #include <liblava/block/attachment.hpp> #include <liblava/block/subpass.hpp> -#include <liblava/base/device.hpp> namespace lava { -struct render_pass : id_obj, target_callback { - - using ptr = std::shared_ptr<render_pass>; - using list = std::vector<ptr>; - - explicit render_pass(device_ptr device); - - bool create(VkAttachmentsRef target_attachments, rect area); - void destroy(); - - void process(VkCommandBuffer cmd_buf, index frame); - - device_ptr get_device() { return device; } - VkRenderPass get() const { return vk_render_pass; } - - ui32 get_subpass_count() const { return to_ui32(subpasses.size()); } - bool exists_subpass(index index = 0) const { return index < subpasses.size(); } - - subpass* get_subpass(index index = 0) { return subpasses.at(index).get(); } - subpass::list const& get_subpasses() const { return subpasses; } - - void add(attachment::ptr const& attachment) { attachments.push_back(attachment); } - void add(subpass_dependency::ptr const& dependency) { dependencies.push_back(dependency); } - void add(subpass::ptr const& subpass) { subpasses.push_back(subpass); } - - void set_clear_values(VkClearValues const& values) { clear_values = values; } - VkClearValues const& get_clear_values() const { return clear_values; } - - void set_clear_color(v3 value = v3(0.086f, 0.086f, 0.094f)); - v3 get_clear_color() const; - - void add(graphics_pipeline::ptr pipeline, index subpass = 0) { subpasses.at(subpass)->add(pipeline); } - void add_front(graphics_pipeline::ptr pipeline, index subpass = 0) { subpasses.at(subpass)->add_front(pipeline); } - void remove(graphics_pipeline::ptr pipeline, index subpass = 0) { subpasses.at(subpass)->remove(pipeline); } - -private: - device_ptr device = nullptr; - - VkRenderPass vk_render_pass = 0; - VkFramebuffers framebuffers = {}; - - attachment::list attachments; - subpass_dependency::list dependencies; - subpass::list subpasses; - - VkClearValues clear_values = {}; - rect area; - - void begin(VkCommandBuffer cmd_buf, index frame); - void end(VkCommandBuffer cmd_buf); - - bool on_target_created(VkAttachmentsRef target_attachments, rect area); - void on_target_destroyed(); -}; - -inline render_pass::ptr make_render_pass(device_ptr device) { return std::make_shared<render_pass>(device); } - -} // lava + struct render_pass : id_obj, target_callback { + using ptr = std::shared_ptr<render_pass>; + using list = std::vector<ptr>; + + explicit render_pass(device_ptr device); + + bool create(VkAttachmentsRef target_attachments, rect area); + void destroy(); + + void process(VkCommandBuffer cmd_buf, index frame); + + device_ptr get_device() { + return device; + } + VkRenderPass get() const { + return vk_render_pass; + } + + ui32 get_subpass_count() const { + return to_ui32(subpasses.size()); + } + bool exists_subpass(index index = 0) const { + return index < subpasses.size(); + } + + subpass* get_subpass(index index = 0) { + return subpasses.at(index).get(); + } + subpass::list const& get_subpasses() const { + return subpasses; + } + + void add(attachment::ptr const& attachment) { + attachments.push_back(attachment); + } + void add(subpass_dependency::ptr const& dependency) { + dependencies.push_back(dependency); + } + void add(subpass::ptr const& subpass) { + subpasses.push_back(subpass); + } + + void set_clear_values(VkClearValues const& values) { + clear_values = values; + } + VkClearValues const& get_clear_values() const { + return clear_values; + } + + void set_clear_color(v3 value = v3(0.086f, 0.086f, 0.094f)); + v3 get_clear_color() const; + + void add(graphics_pipeline::ptr pipeline, index subpass = 0) { + subpasses.at(subpass)->add(pipeline); + } + void add_front(graphics_pipeline::ptr pipeline, index subpass = 0) { + subpasses.at(subpass)->add_front(pipeline); + } + void remove(graphics_pipeline::ptr pipeline, index subpass = 0) { + subpasses.at(subpass)->remove(pipeline); + } + + private: + device_ptr device = nullptr; + + VkRenderPass vk_render_pass = 0; + VkFramebuffers framebuffers = {}; + + attachment::list attachments; + subpass_dependency::list dependencies; + subpass::list subpasses; + + VkClearValues clear_values = {}; + rect area; + + void begin(VkCommandBuffer cmd_buf, index frame); + void end(VkCommandBuffer cmd_buf); + + bool on_target_created(VkAttachmentsRef target_attachments, rect area); + void on_target_destroyed(); + }; + + inline render_pass::ptr make_render_pass(device_ptr device) { + return std::make_shared<render_pass>(device); + } + +} // namespace lava diff --git a/liblava/block/subpass.cpp b/liblava/block/subpass.cpp index 0dcc2f2ebf6c1117ef354b2c4fb1546af77e4562..dd0408ca0acb7d52eecb086960bb87b8b1c87ec6 100644 --- a/liblava/block/subpass.cpp +++ b/liblava/block/subpass.cpp @@ -6,193 +6,171 @@ namespace lava { -subpass::subpass() { - - description.flags = 0; - description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - description.inputAttachmentCount = 0; - description.pInputAttachments = nullptr; - description.colorAttachmentCount = 0; - description.pColorAttachments = nullptr; - description.pResolveAttachments = nullptr; - description.pDepthStencilAttachment = nullptr; - description.preserveAttachmentCount = 0; - description.pPreserveAttachments = nullptr; -} - -void subpass::destroy() { - - clear_pipelines(); -} - -void subpass::clear_pipelines() { - - for (auto& pipeline : pipelines) - pipeline->destroy(); - - pipelines.clear(); -} - -void subpass::remove(graphics_pipeline::ptr pipeline) { - - lava::remove(pipelines, std::move(pipeline)); -} - -void subpass::set_color_attachment(index attachment, VkImageLayout layout) { - - VkAttachmentReference reference; - reference.attachment = attachment; - reference.layout = layout; - - set_color_attachment(reference); -} - -void subpass::set_color_attachment(VkAttachmentReference attachment) { - - VkAttachmentReferences attachments; - attachments.push_back(attachment); - - set_color_attachments(attachments); -} - -void subpass::set_color_attachments(VkAttachmentReferences const& attachments) { - - color_attachments = attachments; - - description.colorAttachmentCount = to_ui32(color_attachments.size()); - description.pColorAttachments = color_attachments.data(); -} - -void subpass::set_depth_stencil_attachment(index attachment, VkImageLayout layout) { - - VkAttachmentReference reference; - reference.attachment = attachment; - reference.layout = layout; + subpass::subpass() { + description.flags = 0; + description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + description.inputAttachmentCount = 0; + description.pInputAttachments = nullptr; + description.colorAttachmentCount = 0; + description.pColorAttachments = nullptr; + description.pResolveAttachments = nullptr; + description.pDepthStencilAttachment = nullptr; + description.preserveAttachmentCount = 0; + description.pPreserveAttachments = nullptr; + } - set_depth_stencil_attachment(reference); -} + void subpass::destroy() { + clear_pipelines(); + } -void subpass::set_depth_stencil_attachment(VkAttachmentReference attachment) { + void subpass::clear_pipelines() { + for (auto& pipeline : pipelines) + pipeline->destroy(); - depth_stencil_attachment = attachment; + pipelines.clear(); + } - description.pDepthStencilAttachment = &depth_stencil_attachment; -} + void subpass::remove(graphics_pipeline::ptr pipeline) { + lava::remove(pipelines, std::move(pipeline)); + } -void subpass::set_input_attachment(index attachment, VkImageLayout layout) { + void subpass::set_color_attachment(index attachment, VkImageLayout layout) { + VkAttachmentReference reference; + reference.attachment = attachment; + reference.layout = layout; - VkAttachmentReference reference; - reference.attachment = attachment; - reference.layout = layout; + set_color_attachment(reference); + } - set_input_attachment(reference); -} + void subpass::set_color_attachment(VkAttachmentReference attachment) { + VkAttachmentReferences attachments; + attachments.push_back(attachment); -void subpass::set_input_attachment(VkAttachmentReference attachment) { + set_color_attachments(attachments); + } - VkAttachmentReferences attachments; - attachments.push_back(attachment); + void subpass::set_color_attachments(VkAttachmentReferences const& attachments) { + color_attachments = attachments; - set_input_attachments(attachments); -} + description.colorAttachmentCount = to_ui32(color_attachments.size()); + description.pColorAttachments = color_attachments.data(); + } -void subpass::set_input_attachments(VkAttachmentReferences const& attachments) { + void subpass::set_depth_stencil_attachment(index attachment, VkImageLayout layout) { + VkAttachmentReference reference; + reference.attachment = attachment; + reference.layout = layout; - input_attachments = attachments; + set_depth_stencil_attachment(reference); + } - description.inputAttachmentCount = to_ui32(input_attachments.size()); - description.pInputAttachments = input_attachments.data(); -} + void subpass::set_depth_stencil_attachment(VkAttachmentReference attachment) { + depth_stencil_attachment = attachment; -void subpass::set_resolve_attachment(index attachment, VkImageLayout layout) { + description.pDepthStencilAttachment = &depth_stencil_attachment; + } - VkAttachmentReference reference; - reference.attachment = attachment; - reference.layout = layout; + void subpass::set_input_attachment(index attachment, VkImageLayout layout) { + VkAttachmentReference reference; + reference.attachment = attachment; + reference.layout = layout; - set_resolve_attachment(reference); -} + set_input_attachment(reference); + } -void subpass::set_resolve_attachment(VkAttachmentReference attachment) { + void subpass::set_input_attachment(VkAttachmentReference attachment) { + VkAttachmentReferences attachments; + attachments.push_back(attachment); - VkAttachmentReferences attachments; - attachments.push_back(attachment); + set_input_attachments(attachments); + } - set_resolve_attachments(attachments); -} + void subpass::set_input_attachments(VkAttachmentReferences const& attachments) { + input_attachments = attachments; -void subpass::set_resolve_attachments(VkAttachmentReferences const& attachments) { + description.inputAttachmentCount = to_ui32(input_attachments.size()); + description.pInputAttachments = input_attachments.data(); + } - resolve_attachments = attachments; + void subpass::set_resolve_attachment(index attachment, VkImageLayout layout) { + VkAttachmentReference reference; + reference.attachment = attachment; + reference.layout = layout; - description.pResolveAttachments = resolve_attachments.data(); -} + set_resolve_attachment(reference); + } -void subpass::add_preserve_attachment(ui32 attachment) { + void subpass::set_resolve_attachment(VkAttachmentReference attachment) { + VkAttachmentReferences attachments; + attachments.push_back(attachment); - preserve_attachments.push_back(attachment); + set_resolve_attachments(attachments); + } - set_preserve_attachments(preserve_attachments); -} + void subpass::set_resolve_attachments(VkAttachmentReferences const& attachments) { + resolve_attachments = attachments; -void subpass::set_preserve_attachments(index_list const& attachments) { + description.pResolveAttachments = resolve_attachments.data(); + } - preserve_attachments = attachments; + void subpass::add_preserve_attachment(ui32 attachment) { + preserve_attachments.push_back(attachment); - description.preserveAttachmentCount = to_ui32(preserve_attachments.size()); - description.pPreserveAttachments = preserve_attachments.data(); -} + set_preserve_attachments(preserve_attachments); + } -void subpass::process(VkCommandBuffer cmd_buf, uv2 size) { + void subpass::set_preserve_attachments(index_list const& attachments) { + preserve_attachments = attachments; - for (auto& pipeline : pipelines) { + description.preserveAttachmentCount = to_ui32(preserve_attachments.size()); + description.pPreserveAttachments = preserve_attachments.data(); + } - if (!pipeline->activated()) - continue; + void subpass::process(VkCommandBuffer cmd_buf, uv2 size) { + for (auto& pipeline : pipelines) { + if (!pipeline->activated()) + continue; - if (!pipeline->on_process) - continue; + if (!pipeline->on_process) + continue; - if (pipeline->auto_bind()) - pipeline->bind(cmd_buf); + if (pipeline->auto_bind()) + pipeline->bind(cmd_buf); - if (pipeline->auto_sizing()) - pipeline->set_viewport_and_scissor(cmd_buf, size); + if (pipeline->auto_sizing()) + pipeline->set_viewport_and_scissor(cmd_buf, size); - if (pipeline->auto_line_width()) - pipeline->set_line_width(cmd_buf); + if (pipeline->auto_line_width()) + pipeline->set_line_width(cmd_buf); - pipeline->on_process(cmd_buf); + pipeline->on_process(cmd_buf); + } } -} - -subpass::ptr make_subpass(VkPipelineBindPoint pipeline_bind_point) { - auto result = std::make_shared<subpass>(); + subpass::ptr make_subpass(VkPipelineBindPoint pipeline_bind_point) { + auto result = std::make_shared<subpass>(); - result->set(pipeline_bind_point); - return result; -} - -subpass_dependency::subpass_dependency() { - - dependency.srcSubpass = 0; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM; - dependency.dstStageMask = VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM; - dependency.srcAccessMask = VK_ACCESS_FLAG_BITS_MAX_ENUM; - dependency.dstAccessMask = VK_ACCESS_FLAG_BITS_MAX_ENUM; - dependency.dependencyFlags = VK_DEPENDENCY_FLAG_BITS_MAX_ENUM; -} + result->set(pipeline_bind_point); + return result; + } -subpass_dependency::ptr make_subpass_dependency(ui32 src_subpass, ui32 dst_subpass, VkDependencyFlags dependency_flags) { + subpass_dependency::subpass_dependency() { + dependency.srcSubpass = 0; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM; + dependency.dstStageMask = VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM; + dependency.srcAccessMask = VK_ACCESS_FLAG_BITS_MAX_ENUM; + dependency.dstAccessMask = VK_ACCESS_FLAG_BITS_MAX_ENUM; + dependency.dependencyFlags = VK_DEPENDENCY_FLAG_BITS_MAX_ENUM; + } - auto dependency = std::make_shared<subpass_dependency>(); + subpass_dependency::ptr make_subpass_dependency(ui32 src_subpass, ui32 dst_subpass, VkDependencyFlags dependency_flags) { + auto dependency = std::make_shared<subpass_dependency>(); - dependency->set_subpass(src_subpass, dst_subpass); - dependency->set_dependency_flags(dependency_flags); + dependency->set_subpass(src_subpass, dst_subpass); + dependency->set_dependency_flags(dependency_flags); - return dependency; -} + return dependency; + } -} // lava +} // namespace lava diff --git a/liblava/block/subpass.hpp b/liblava/block/subpass.hpp index 3894e457ef5f5bce0fb99eb2244cc0fde001d422..4092140ac279dd97c3dd45cc87440bd7db0c2741 100644 --- a/liblava/block/subpass.hpp +++ b/liblava/block/subpass.hpp @@ -8,108 +8,132 @@ namespace lava { -struct subpass : id_obj { + struct subpass : id_obj { + using ptr = std::shared_ptr<subpass>; + using list = std::vector<ptr>; - using ptr = std::shared_ptr<subpass>; - using list = std::vector<ptr>; + void destroy(); - void destroy(); + explicit subpass(); - explicit subpass(); + void add(graphics_pipeline::ptr const& pipeline) { + pipelines.push_back(pipeline); + } - void add(graphics_pipeline::ptr const& pipeline) { pipelines.push_back(pipeline); } + void add_front(graphics_pipeline::ptr const& pipeline) { + pipelines.insert(pipelines.begin(), pipeline); + } + + void remove(graphics_pipeline::ptr pipeline); - void add_front(graphics_pipeline::ptr const& pipeline) { pipelines.insert(pipelines.begin(), pipeline); } + void clear_pipelines(); + + void process(VkCommandBuffer cmd_buf, uv2 size); + ; - void remove(graphics_pipeline::ptr pipeline); + VkSubpassDescription get_description() const { + return description; + } - void clear_pipelines(); + void set(VkPipelineBindPoint pipeline_bind_point) { + description.pipelineBindPoint = pipeline_bind_point; + } - void process(VkCommandBuffer cmd_buf, uv2 size);; + void set_color_attachment(index attachment, VkImageLayout layout); + void set_color_attachment(VkAttachmentReference attachment); + void set_color_attachments(VkAttachmentReferences const& attachments); - VkSubpassDescription get_description() const { return description; } + void set_depth_stencil_attachment(index attachment, VkImageLayout layout); + void set_depth_stencil_attachment(VkAttachmentReference attachment); - void set(VkPipelineBindPoint pipeline_bind_point) { description.pipelineBindPoint = pipeline_bind_point; } + void set_input_attachment(index attachment, VkImageLayout layout); + void set_input_attachment(VkAttachmentReference attachment); + void set_input_attachments(VkAttachmentReferences const& attachments); - void set_color_attachment(index attachment, VkImageLayout layout); - void set_color_attachment(VkAttachmentReference attachment); - void set_color_attachments(VkAttachmentReferences const& attachments); + void set_resolve_attachment(index attachment, VkImageLayout layout); + void set_resolve_attachment(VkAttachmentReference attachment); + void set_resolve_attachments(VkAttachmentReferences const& attachments); - void set_depth_stencil_attachment(index attachment, VkImageLayout layout); - void set_depth_stencil_attachment(VkAttachmentReference attachment); + void add_preserve_attachment(index attachment); + void set_preserve_attachments(index_list const& attachments); - void set_input_attachment(index attachment, VkImageLayout layout); - void set_input_attachment(VkAttachmentReference attachment); - void set_input_attachments(VkAttachmentReferences const& attachments); + void set_active(bool value = true) { + active = value; + } + bool activated() const { + return active; + } - void set_resolve_attachment(index attachment, VkImageLayout layout); - void set_resolve_attachment(VkAttachmentReference attachment); - void set_resolve_attachments(VkAttachmentReferences const& attachments); + private: + VkSubpassDescription description; + bool active = true; - void add_preserve_attachment(index attachment); - void set_preserve_attachments(index_list const& attachments); + VkAttachmentReferences color_attachments; + VkAttachmentReference depth_stencil_attachment; + VkAttachmentReferences input_attachments; + VkAttachmentReferences resolve_attachments; + index_list preserve_attachments; - void set_active(bool value = true) { active = value; } - bool activated() const { return active; } + graphics_pipeline::list pipelines; + }; -private: - VkSubpassDescription description; - bool active = true; + subpass::ptr make_subpass(VkPipelineBindPoint pipeline_bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS); - VkAttachmentReferences color_attachments; - VkAttachmentReference depth_stencil_attachment; - VkAttachmentReferences input_attachments; - VkAttachmentReferences resolve_attachments; - index_list preserve_attachments; + struct subpass_dependency : id_obj { + using ptr = std::shared_ptr<subpass_dependency>; + using list = std::vector<ptr>; - graphics_pipeline::list pipelines; -}; + explicit subpass_dependency(); -subpass::ptr make_subpass(VkPipelineBindPoint pipeline_bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS); + VkSubpassDependency get_dependency() const { + return dependency; + } -struct subpass_dependency : id_obj { + void set_subpass(ui32 src, ui32 dst) { + set_src_subpass(src); + set_dst_subpass(dst); + } - using ptr = std::shared_ptr<subpass_dependency>; - using list = std::vector<ptr>; + void set_src_subpass(ui32 src) { + dependency.srcSubpass = src; + } + void set_dst_subpass(ui32 dst) { + dependency.dstSubpass = dst; + } - explicit subpass_dependency(); + void set_stage_mask(VkPipelineStageFlags src, VkPipelineStageFlags dst) { + set_src_stage_mask(src); + set_dst_stage_mask(dst); + } - VkSubpassDependency get_dependency() const { return dependency; } + void set_src_stage_mask(VkPipelineStageFlags mask) { + dependency.srcStageMask = mask; + } + void set_dst_stage_mask(VkPipelineStageFlags mask) { + dependency.dstStageMask = mask; + } - void set_subpass(ui32 src, ui32 dst) { - - set_src_subpass(src); - set_dst_subpass(dst); - } - - void set_src_subpass(ui32 src) { dependency.srcSubpass = src; } - void set_dst_subpass(ui32 dst) { dependency.dstSubpass = dst; } - - void set_stage_mask(VkPipelineStageFlags src, VkPipelineStageFlags dst) { - - set_src_stage_mask(src); - set_dst_stage_mask(dst); - } - - void set_src_stage_mask(VkPipelineStageFlags mask) { dependency.srcStageMask = mask; } - void set_dst_stage_mask(VkPipelineStageFlags mask) { dependency.dstStageMask = mask; } - - void set_access_mask(VkAccessFlags src, VkAccessFlags dst) { - - set_src_access_mask(src); - set_dst_access_mask(dst); - } - - void set_src_access_mask(VkAccessFlags mask) { dependency.srcAccessMask = mask; } - void set_dst_access_mask(VkAccessFlags mask) { dependency.dstAccessMask = mask; } - - void set_dependency_flags(VkDependencyFlags flags) { dependency.dependencyFlags = flags; } - -private: - VkSubpassDependency dependency; -}; - -subpass_dependency::ptr make_subpass_dependency(ui32 src_subpass, ui32 dst_subpass, - VkDependencyFlags dependency_flags = VK_DEPENDENCY_BY_REGION_BIT); - -} // lava + void set_access_mask(VkAccessFlags src, VkAccessFlags dst) { + set_src_access_mask(src); + set_dst_access_mask(dst); + } + + void set_src_access_mask(VkAccessFlags mask) { + dependency.srcAccessMask = mask; + } + void set_dst_access_mask(VkAccessFlags mask) { + dependency.dstAccessMask = mask; + } + + void set_dependency_flags(VkDependencyFlags flags) { + dependency.dependencyFlags = flags; + } + + private: + VkSubpassDependency dependency; + }; + + subpass_dependency::ptr make_subpass_dependency(ui32 src_subpass, ui32 dst_subpass, + VkDependencyFlags dependency_flags = VK_DEPENDENCY_BY_REGION_BIT); + +} // namespace lava diff --git a/liblava/core/data.hpp b/liblava/core/data.hpp index fc9b6196591df6af1407147c9060ffb66a1231e4..ae53d64104bb9047d0460d63fc192d745f1477a8 100644 --- a/liblava/core/data.hpp +++ b/liblava/core/data.hpp @@ -4,166 +4,160 @@ #pragma once -#include <liblava/core/types.hpp> - #include <string.h> +#include <liblava/core/types.hpp> namespace lava { -using data_ptr = char*; -using data_cptr = char const*; - -struct data_provider { - - using alloc_func = std::function<data_ptr(size_t, size_t)>; - alloc_func on_alloc; + using data_ptr = char*; + using data_cptr = char const*; - using free_func = std::function<void()>; - free_func on_free; + struct data_provider { + using alloc_func = std::function<data_ptr(size_t, size_t)>; + alloc_func on_alloc; - using realloc_func = std::function<data_ptr(data_ptr, size_t, size_t)>; - realloc_func on_realloc; -}; + using free_func = std::function<void()>; + free_func on_free; -template <typename T> -inline data_ptr as_ptr(T* value) { return (data_ptr)value; } + using realloc_func = std::function<data_ptr(data_ptr, size_t, size_t)>; + realloc_func on_realloc; + }; -template <typename T> -inline T align_up(T val, T align) { return (val + align - T(1)) / align * align; } + template<typename T> + inline data_ptr as_ptr(T* value) { + return (data_ptr) value; + } -inline size_t align(size_t size, size_t min = 0) { + template<typename T> + inline T align_up(T val, T align) { + return (val + align - T(1)) / align * align; + } - if (min == 0) - return align_up(size, sizeof(void*)); + inline size_t align(size_t size, size_t min = 0) { + if (min == 0) + return align_up(size, sizeof(void*)); - return align_up((size + min - 1) & ~(min - 1), sizeof(void*)); -} + return align_up((size + min - 1) & ~(min - 1), sizeof(void*)); + } -template <typename T> -inline size_t align(size_t min = 0) { return align(sizeof(T), min); } + template<typename T> + inline size_t align(size_t min = 0) { + return align(sizeof(T), min); + } -inline void* alloc_data(size_t size, size_t alignment = sizeof(c8)) { + inline void* alloc_data(size_t size, size_t alignment = sizeof(c8)) { #if _WIN32 - return _aligned_malloc(size, alignment); + return _aligned_malloc(size, alignment); #else - return aligned_alloc(alignment, size); + return aligned_alloc(alignment, size); #endif -} + } -inline void free_data(void* data) { + inline void free_data(void* data) { #if _WIN32 - _aligned_free(data); + _aligned_free(data); #else - free(data); + free(data); #endif -} + } -inline void* realloc_data(void* data, size_t size, size_t alignment) { + inline void* realloc_data(void* data, size_t size, size_t alignment) { #if _WIN32 - return _aligned_realloc(data, size, alignment); + return _aligned_realloc(data, size, alignment); #else - return realloc(data, align(size, alignment)); + return realloc(data, align(size, alignment)); #endif -} - -struct data { - - data() = default; - data(void* ptr, size_t size) : ptr(as_ptr(ptr)), size(size) {} - - void set(size_t length, bool alloc = true) { - - size = length; - alignment = align<data_ptr>(); - - if (alloc) - allocate(); } - bool allocate() { - - ptr = as_ptr(alloc_data(size, alignment)); - return ptr != nullptr; + struct data { + data() = default; + data(void* ptr, size_t size) + : ptr(as_ptr(ptr)), size(size) {} + + void set(size_t length, bool alloc = true) { + size = length; + alignment = align<data_ptr>(); + + if (alloc) + allocate(); + } + + bool allocate() { + ptr = as_ptr(alloc_data(size, alignment)); + return ptr != nullptr; + } + + void free() { + if (!ptr) + return; + + free_data(ptr); + ptr = nullptr; + } + + data_ptr ptr = nullptr; + + size_t size = 0; + size_t alignment = 0; + }; + + struct scope_data : data { + explicit scope_data(size_t length = 0, bool alloc = true) { + if (length) + set(length, alloc); + } + + explicit scope_data(i64 length, bool alloc = true) + : scope_data(to_size_t(length), alloc) {} + explicit scope_data(data const& data) { + ptr = data.ptr; + size = data.size; + alignment = data.alignment; + } + + ~scope_data() { + free(); + } + }; + + inline size_t next_pow_2(size_t x) { + x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x++; + return x; } - void free() { - - if (!ptr) - return; - - free_data(ptr); - ptr = nullptr; - } - - data_ptr ptr = nullptr; - - size_t size = 0; - size_t alignment = 0; -}; - -struct scope_data : data { - - explicit scope_data(size_t length = 0, bool alloc = true) { - - if (length) - set(length, alloc); - } - - explicit scope_data(i64 length, bool alloc = true) : scope_data(to_size_t(length), alloc) {} - explicit scope_data(data const& data) { - - ptr = data.ptr; - size = data.size; - alignment = data.alignment; - } - - ~scope_data() { - - free(); - } -}; - -inline size_t next_pow_2(size_t x) { - - x--; - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - x++; - return x; -} - #ifndef __GNUC__ -#define strndup(p, n) _strdup(p) +# define strndup(p, n) _strdup(p) #endif -inline char* human_readable(size_t const sz) { + inline char* human_readable(size_t const sz) { + static ui32 const buffer_size = 32; - static ui32 const buffer_size = 32; + char const prefixes[] = "KMGTPEZY"; + char buf[buffer_size]; + i32 which = -1; - char const prefixes[] = "KMGTPEZY"; - char buf[buffer_size]; - i32 which = -1; + auto result = to_r64(sz); + while (result > 1024 && which < 7) { + result /= 1024; + ++which; + } - auto result = to_r64(sz); - while (result > 1024 && which < 7) { + char unit[] = "\0i"; + if (which >= 0) + unit[0] = prefixes[which]; - result /= 1024; - ++which; + snprintf(buf, buffer_size, "%.2f %sB", result, unit); + return strndup(buf, buffer_size); } - char unit[] = "\0i"; - if (which >= 0) - unit[0] = prefixes[which]; - - snprintf(buf, buffer_size, "%.2f %sB", result, unit); - return strndup(buf, buffer_size); -} - #ifndef __GNUC__ -#undef strndup +# undef strndup #endif -} // lava +} // namespace lava diff --git a/liblava/core/id.hpp b/liblava/core/id.hpp index ee0549aa61d60b26be0afa947491356a9f4c4c58..b5031391d64b64a7aaf82f266cb68af4ac0405d6 100644 --- a/liblava/core/id.hpp +++ b/liblava/core/id.hpp @@ -4,208 +4,227 @@ #pragma once -#include <liblava/core/types.hpp> - -#include <memory> #include <atomic> #include <deque> +#include <liblava/core/types.hpp> +#include <memory> #include <mutex> #include <set> namespace lava { -struct id { - - using ref = id const&; - using set = std::set<id>; - using set_ref = set const&; - using list = std::vector<id>; - using map = std::map<id, id>; - using index_map = std::map<id, index>; - using string_map = std::map<id, string>; - - type value = undef; - ui32 version = 0; - - bool valid() const { return value != undef; } - string to_string(bool show_version = false) const { - - char result[32]; - if (show_version) - snprintf(result, sizeof(result), "%u.%u", value, version); - else - snprintf(result, sizeof(result), "%u", value); - return string(result); + struct id { + using ref = id const&; + using set = std::set<id>; + using set_ref = set const&; + using list = std::vector<id>; + using map = std::map<id, id>; + using index_map = std::map<id, index>; + using string_map = std::map<id, string>; + + type value = undef; + ui32 version = 0; + + bool valid() const { + return value != undef; + } + string to_string(bool show_version = false) const { + char result[32]; + if (show_version) + snprintf(result, sizeof(result), "%u.%u", value, version); + else + snprintf(result, sizeof(result), "%u", value); + return string(result); + } + + void invalidate() { + *this = {}; + } + + bool operator==(ref rhs) const { + return (value == rhs.value) && (version == rhs.version); + } + bool operator!=(ref rhs) const { + return !(*this == rhs); + } + bool operator<(ref rhs) const { + return std::tie(value, version) < std::tie(rhs.value, rhs.version); + } + + bool check(id::map& map) { + if (!valid()) + return false; + + if (!map.count(*this)) + return false; + + *this = map.at(*this); + return true; + } + }; + + using string_id_map = std::map<string, id>; + constexpr id const undef_id = id(); + + struct ids { + static ids& global() { + static ids instance; + return instance; + } + + static id next() { + return ids::global().get_next(); + } + static void free(id::ref id) { + ids::global().reuse(id); + } + + id get_next() { + if (!reuse_ids) + return { ++next_id }; + + return get_next_locked(); + } + + void reuse(id::ref id) { + if (reuse_ids) + reuse_locked(id); + } + + void set_reuse(bool state) { + reuse_ids = state; + } + bool reusing() const { + return reuse_ids; + } + + type get_max() const { + return next_id; + } + void set_max(type max) { + if (max > next_id) + next_id = max; + } + + private: + id get_next_locked() { + std::unique_lock<std::mutex> lock(queue_mutex); + if (free_ids.empty()) + return { ++next_id }; + + auto next_id = free_ids.front(); + free_ids.pop_front(); + return { next_id.value, next_id.version + 1 }; + } + + void reuse_locked(id::ref id) { + std::unique_lock<std::mutex> lock(queue_mutex); + free_ids.push_back(id); + } + + std::atomic<type> next_id = { undef }; + std::mutex queue_mutex; + + bool reuse_ids = true; + std::deque<id> free_ids; + }; + + template<typename T> + inline id add_id_map(T const& object, std::map<id, T>& map) { + auto next = ids::next(); + map.emplace(next, std::move(object)); + return next; } - void invalidate() { *this = {}; } - - bool operator==(ref rhs) const { return (value == rhs.value) && (version == rhs.version); } - bool operator!=(ref rhs) const { return !(*this == rhs); } - bool operator<(ref rhs) const { return std::tie(value, version) < std::tie(rhs.value, rhs.version); } - - bool check(id::map& map) { - - if (!valid()) + template<typename T> + inline bool remove_id_map(id::ref object, std::map<id, T>& map) { + if (!map.count(object)) return false; - if (!map.count(*this)) - return false; + map.erase(object); + ids::free(object); - *this = map.at(*this); return true; } -}; - -using string_id_map = std::map<string, id>; -constexpr id const undef_id = id(); - -struct ids { - - static ids& global() { - - static ids instance; - return instance; - } - - static id next() { return ids::global().get_next(); } - static void free(id::ref id) { ids::global().reuse(id); } - - id get_next() { - - if (!reuse_ids) - return { ++next_id }; - - return get_next_locked(); - } - - void reuse(id::ref id) { - - if (reuse_ids) - reuse_locked(id); - } - - void set_reuse(bool state) { reuse_ids = state; } - bool reusing() const { return reuse_ids; } - - type get_max() const { return next_id; } - void set_max(type max) { - - if (max > next_id) - next_id = max; - } - -private: - id get_next_locked() { - - std::unique_lock<std::mutex> lock(queue_mutex); - if (free_ids.empty()) - return { ++next_id }; - - auto next_id = free_ids.front(); - free_ids.pop_front(); - return { next_id.value, next_id.version + 1 }; - } - - void reuse_locked(id::ref id) { - - std::unique_lock<std::mutex> lock(queue_mutex); - free_ids.push_back(id); - } - - std::atomic<type> next_id = { undef }; - std::mutex queue_mutex; - - bool reuse_ids = true; - std::deque<id> free_ids; -}; - -template <typename T> -inline id add_id_map(T const& object, std::map<id, T>& map) { - - auto next = ids::next(); - map.emplace(next, std::move(object)); - return next; -} - -template <typename T> -inline bool remove_id_map(id::ref object, std::map<id, T>& map) { - - if (!map.count(object)) - return false; - - map.erase(object); - ids::free(object); - - return true; -} - -template <typename T> -struct id_listeners { - - id add(typename T::func const& listener) { - - return add_id_map(listener, list); - } - - void remove(id& id) { - - if (remove_id_map(id, list)) - id.invalidate(); - } - - typename T::listeners const& get_list() const { return list; } - -private: - typename T::listeners list = {}; -}; - -struct id_obj : interface { - - id_obj() : obj_id(ids::next()) {} - ~id_obj() { ids::free(obj_id); } - - id::ref get_id() const { return obj_id; } - -private: - id obj_id; -}; - -template <typename T, typename Meta> -struct id_registry { - - using ptr = std::shared_ptr<T>; - using map = std::map<id, ptr>; - - using meta_map = std::map<id, Meta>; - - id create(Meta info = {}) { - - auto object = std::make_shared<T>(); - add(object, info); - - return object->get_id(); - } - - void add(ptr object, Meta info = {}) { - - objects.emplace(object->get_id(), object); - meta.emplace(object->get_id(), info); - } - - bool has(id::ref object) const { return objects.count(object); } - - ptr get(id::ref object) const { return objects.at(object).get(); } - Meta get_meta(id::ref object) const { return meta.at(object).get(); } - - map const& get_all() const { return objects; } - meta_map const& get_all_meta() const { return meta; } - - void remove(id::ref object) { objects.erase(object); } - -private: - map objects; - meta_map meta; -}; -} // lava + template<typename T> + struct id_listeners { + id add(typename T::func const& listener) { + return add_id_map(listener, list); + } + + void remove(id& id) { + if (remove_id_map(id, list)) + id.invalidate(); + } + + typename T::listeners const& get_list() const { + return list; + } + + private: + typename T::listeners list = {}; + }; + + struct id_obj : interface { + id_obj() + : obj_id(ids::next()) {} + ~id_obj() { + ids::free(obj_id); + } + + id::ref get_id() const { + return obj_id; + } + + private: + id obj_id; + }; + + template<typename T, typename Meta> + struct id_registry { + using ptr = std::shared_ptr<T>; + using map = std::map<id, ptr>; + + using meta_map = std::map<id, Meta>; + + id create(Meta info = {}) { + auto object = std::make_shared<T>(); + add(object, info); + + return object->get_id(); + } + + void add(ptr object, Meta info = {}) { + objects.emplace(object->get_id(), object); + meta.emplace(object->get_id(), info); + } + + bool has(id::ref object) const { + return objects.count(object); + } + + ptr get(id::ref object) const { + return objects.at(object).get(); + } + Meta get_meta(id::ref object) const { + return meta.at(object).get(); + } + + map const& get_all() const { + return objects; + } + meta_map const& get_all_meta() const { + return meta; + } + + void remove(id::ref object) { + objects.erase(object); + } + + private: + map objects; + meta_map meta; + }; + +} // namespace lava diff --git a/liblava/core/math.hpp b/liblava/core/math.hpp index 587c8a1e5426213018784af7de0451f3e7d38e25..c61cea95f59c4a4feb3dab76d5444b4f68a19876 100644 --- a/liblava/core/math.hpp +++ b/liblava/core/math.hpp @@ -14,73 +14,73 @@ namespace lava { -using v2 = glm::vec2; -using v3 = glm::vec3; -using v4 = glm::vec4; - -using uv2 = glm::uvec2; - -using mat3 = glm::mat3; -using mat4 = glm::mat4; - -using iv2 = glm::ivec2; -using iv3 = glm::ivec3; - -struct rect { - - rect() = default; - - rect(i32 left, i32 top, ui32 width, ui32 height) : left_top({ left, top }) { - - set_size({ width, height }); - } - - rect(iv2 const& left_top, ui32 width, ui32 height) : left_top(left_top) { - - set_size({ width, height }); - } - - rect(iv2 const& left_top, uv2 const& size) : left_top(left_top) { - - set_size(size); - } - - iv2 const& get_origin() const { return left_top; } - iv2 const& get_end_point() const { return right_bottom; } - - uv2 get_size() const { - - assert(left_top.x <= right_bottom.x); - assert(left_top.y <= right_bottom.y); - return { right_bottom.x - left_top.x, right_bottom.y - left_top.y }; - } - - void set_size(uv2 const& size) { - - right_bottom.x = left_top.x + size.x; - right_bottom.y = left_top.y + size.y; - } - - void move(iv2 const& offset) { - - left_top += offset; - right_bottom += offset; + using v2 = glm::vec2; + using v3 = glm::vec3; + using v4 = glm::vec4; + + using uv2 = glm::uvec2; + + using mat3 = glm::mat3; + using mat4 = glm::mat4; + + using iv2 = glm::ivec2; + using iv3 = glm::ivec3; + + struct rect { + rect() = default; + + rect(i32 left, i32 top, ui32 width, ui32 height) + : left_top({ left, top }) { + set_size({ width, height }); + } + + rect(iv2 const& left_top, ui32 width, ui32 height) + : left_top(left_top) { + set_size({ width, height }); + } + + rect(iv2 const& left_top, uv2 const& size) + : left_top(left_top) { + set_size(size); + } + + iv2 const& get_origin() const { + return left_top; + } + iv2 const& get_end_point() const { + return right_bottom; + } + + uv2 get_size() const { + assert(left_top.x <= right_bottom.x); + assert(left_top.y <= right_bottom.y); + return { right_bottom.x - left_top.x, right_bottom.y - left_top.y }; + } + + void set_size(uv2 const& size) { + right_bottom.x = left_top.x + size.x; + right_bottom.y = left_top.y + size.y; + } + + void move(iv2 const& offset) { + left_top += offset; + right_bottom += offset; + } + + bool contains(iv2 point) const { + return (left_top.x < point.x) && (left_top.y < point.y) && (right_bottom.x > point.x) && (right_bottom.y > point.y); + } + + private: + iv2 left_top = iv2(); + iv2 right_bottom = iv2(); + }; + + template<typename T> + inline T ceil_div(T x, T y) { + return (x + y - 1) / y; } - bool contains(iv2 point) const { - - return (left_top.x < point.x) && (left_top.y < point.y) && - (right_bottom.x > point.x) && (right_bottom.y > point.y); - } - -private: - iv2 left_top = iv2(); - iv2 right_bottom = iv2(); -}; - -template <typename T> -inline T ceil_div(T x, T y) { return (x + y - 1) / y; } - -v3 const default_color = v3{ 0.8118f, 0.0627f, 0.1255f }; // #CF1020 : 207, 16, 32 + v3 const default_color = v3{ 0.8118f, 0.0627f, 0.1255f }; // #CF1020 : 207, 16, 32 -} // lava +} // namespace lava diff --git a/liblava/core/time.hpp b/liblava/core/time.hpp index 49c0017aa02cfdd49f3adef17608834d2d872b34..0f43380fb28e4d0b0584954d08462c4afe98c48f 100644 --- a/liblava/core/time.hpp +++ b/liblava/core/time.hpp @@ -4,79 +4,84 @@ #pragma once -#include <liblava/core/types.hpp> - #include <chrono> #include <iomanip> +#include <liblava/core/types.hpp> #include <sstream> namespace lava { -using seconds = std::chrono::seconds; -using milliseconds = std::chrono::milliseconds; -using ms = milliseconds; - -using clock = std::chrono::high_resolution_clock; -using time_point = clock::time_point; -using duration = clock::duration; + using seconds = std::chrono::seconds; + using milliseconds = std::chrono::milliseconds; + using ms = milliseconds; -inline delta to_delta(milliseconds ms) { return ms.count() / 1000.f; } -inline r64 to_sec(milliseconds ms) { return ms.count() / 1000.; } -inline ms to_ms(delta dt) { return ms(to_i32(dt * 1000.f)); } -inline ms to_ms(r64 sec) { return ms(to_i32(sec * 1000.)); } + using clock = std::chrono::high_resolution_clock; + using time_point = clock::time_point; + using duration = clock::duration; -struct timer { - - timer() : start_time(clock::now()) {} - - void reset() { start_time = clock::now(); } + inline delta to_delta(milliseconds ms) { + return ms.count() / 1000.f; + } + inline r64 to_sec(milliseconds ms) { + return ms.count() / 1000.; + } + inline ms to_ms(delta dt) { + return ms(to_i32(dt * 1000.f)); + } + inline ms to_ms(r64 sec) { + return ms(to_i32(sec * 1000.)); + } - ms elapsed() const { + struct timer { + timer() + : start_time(clock::now()) {} - return std::chrono::duration_cast<ms>(clock::now() - start_time); - } + void reset() { + start_time = clock::now(); + } -private: - time_point start_time; -}; + ms elapsed() const { + return std::chrono::duration_cast<ms>(clock::now() - start_time); + } -struct run_time { + private: + time_point start_time; + }; - ms current{ 0 }; - ms clock{ 16 }; + struct run_time { + ms current{ 0 }; + ms clock{ 16 }; - ms system{ 0 }; - ms delta{ 0 }; + ms system{ 0 }; + ms delta{ 0 }; - bool use_fix_delta = false; - ms fix_delta{ 20 }; + bool use_fix_delta = false; + ms fix_delta{ 20 }; - r32 speed = 1.f; - bool paused = false; -}; + r32 speed = 1.f; + bool paused = false; + }; #pragma warning(push) #pragma warning(disable : 4996) //_CRT_SECURE_NO_WARNINGS -template <typename CLOCK_TYPE = std::chrono::system_clock> -inline string time_stamp(const typename CLOCK_TYPE::time_point& time_point, string_ref format = "%Y-%m-%d %H-%M-%S") { - - auto ms = std::chrono::duration_cast<milliseconds>(time_point.time_since_epoch()) % 1000; + template<typename CLOCK_TYPE = std::chrono::system_clock> + inline string time_stamp(const typename CLOCK_TYPE::time_point& time_point, string_ref format = "%Y-%m-%d %H-%M-%S") { + auto ms = std::chrono::duration_cast<milliseconds>(time_point.time_since_epoch()) % 1000; - const std::time_t t = CLOCK_TYPE::to_time_t(time_point); - const std::tm tm = *std::localtime(std::addressof(t)); + const std::time_t t = CLOCK_TYPE::to_time_t(time_point); + const std::tm tm = *std::localtime(std::addressof(t)); - std::ostringstream stm; - stm << std::put_time(std::addressof(tm), str(format)) << '.' << std::setfill('0') << std::setw(3) << ms.count(); - return stm.str(); -} - -inline string get_current_time_and_date() { + std::ostringstream stm; + stm << std::put_time(std::addressof(tm), str(format)) << '.' << std::setfill('0') << std::setw(3) << ms.count(); + return stm.str(); + } - auto now = std::chrono::system_clock::now(); - return time_stamp(now); -} + inline string get_current_time_and_date() { + auto now = std::chrono::system_clock::now(); + return time_stamp(now); + } #pragma warning(pop) -} // lava +} // namespace lava diff --git a/liblava/core/types.hpp b/liblava/core/types.hpp index a3ef6f52366321cebe22d8d821e880fa391e751b..278913342061a6453c6e6f88b22e267c62a62816 100644 --- a/liblava/core/types.hpp +++ b/liblava/core/types.hpp @@ -4,126 +4,140 @@ #pragma once -#include <liblava/def.hpp> - #include <cassert> #include <cstdint> +#include <functional> +#include <liblava/def.hpp> +#include <map> #include <string> #include <string_view> #include <vector> -#include <map> - -#include <functional> namespace lava { -using int8 = std::int8_t; -using i8 = int8; - -using uint8 = std::uint8_t; -using ui8 = uint8; - -using int16 = std::int16_t; -using i16 = int16; - -using uint16 = std::uint16_t; -using ui16 = uint16; + using int8 = std::int8_t; + using i8 = int8; -using int32 = std::int32_t; -using i32 = int32; + using uint8 = std::uint8_t; + using ui8 = uint8; -using uint32 = std::uint32_t; -using ui32 = uint32; + using int16 = std::int16_t; + using i16 = int16; -using int64 = std::int64_t; -using i64 = int64; + using uint16 = std::uint16_t; + using ui16 = uint16; -using uint64 = std::uint64_t; -using ui64 = uint64; + using int32 = std::int32_t; + using i32 = int32; -using char8 = std::int_fast8_t; -using c8 = char8; + using uint32 = std::uint32_t; + using ui32 = uint32; -using uchar8 = std::uint_fast8_t; -using uc8 = uchar8; + using int64 = std::int64_t; + using i64 = int64; -using char16 = int16; -using c16 = char16; + using uint64 = std::uint64_t; + using ui64 = uint64; -using uchar16 = uint16; -using uc16 = uchar16; + using char8 = std::int_fast8_t; + using c8 = char8; -using char32 = int32; -using c32 = char32; + using uchar8 = std::uint_fast8_t; + using uc8 = uchar8; -using uchar32 = uint32; -using uc32 = uchar32; + using char16 = int16; + using c16 = char16; -using size_t = std::size_t; -using uchar = unsigned char; -using r32 = float; -using r64 = double; -using real = r64; -using delta = r32; + using uchar16 = uint16; + using uc16 = uchar16; -using type = ui32; -constexpr type const no_type = 0xffffffff; -constexpr type const undef = 0; + using char32 = int32; + using c32 = char32; -using index = type; -constexpr index const no_index = no_type; -using index_list = std::vector<index>; -using index_map = std::map<index, index>; + using uchar32 = uint32; + using uc32 = uchar32; -using string = std::string; -using string_ref = string const&; -using string_list = std::vector<string>; -using string_view = std::string_view; + using size_t = std::size_t; + using uchar = unsigned char; + using r32 = float; + using r64 = double; + using real = r64; + using delta = r32; -using name = char const*; -using names = std::vector<name>; -using names_ref = names const&; + using type = ui32; + constexpr type const no_type = 0xffffffff; + constexpr type const undef = 0; -constexpr name _lava_ = "lava"; -constexpr name _liblava_ = "liblava"; + using index = type; + constexpr index const no_index = no_type; + using index_list = std::vector<index>; + using index_map = std::map<index, index>; -inline name str(string_ref value) { return value.c_str(); } + using string = std::string; + using string_ref = string const&; + using string_list = std::vector<string>; + using string_view = std::string_view; -template <typename T> -inline r32 to_r32(T value) { return static_cast<r32>(value); } + using name = char const*; + using names = std::vector<name>; + using names_ref = names const&; -template <typename T> -inline r64 to_r64(T value) { return static_cast<r64>(value); } + constexpr name _lava_ = "lava"; + constexpr name _liblava_ = "liblava"; -template <typename T> -inline i32 to_i32(T value) { return static_cast<i32>(value); } + inline name str(string_ref value) { + return value.c_str(); + } -template <typename T> -inline i64 to_i64(T value) { return static_cast<i64>(value); } + template<typename T> + inline r32 to_r32(T value) { + return static_cast<r32>(value); + } -template <typename T> -inline ui32 to_ui32(T value) { return static_cast<ui32>(value); } + template<typename T> + inline r64 to_r64(T value) { + return static_cast<r64>(value); + } -template <typename T> -inline ui64 to_ui64(T value) { return static_cast<ui64>(value); } + template<typename T> + inline i32 to_i32(T value) { + return static_cast<i32>(value); + } -template <typename T> -inline size_t to_size_t(T value) { return static_cast<size_t>(value); } + template<typename T> + inline i64 to_i64(T value) { + return static_cast<i64>(value); + } -template <typename T> -inline index to_index(T value) { return static_cast<index>(value); } + template<typename T> + inline ui32 to_ui32(T value) { + return static_cast<ui32>(value); + } -struct no_copy_no_move { + template<typename T> + inline ui64 to_ui64(T value) { + return static_cast<ui64>(value); + } - no_copy_no_move() = default; - no_copy_no_move(no_copy_no_move const&) = delete; + template<typename T> + inline size_t to_size_t(T value) { + return static_cast<size_t>(value); + } - void operator=(no_copy_no_move const&) = delete; -}; + template<typename T> + inline index to_index(T value) { + return static_cast<index>(value); + } -struct interface { + struct no_copy_no_move { + no_copy_no_move() = default; + no_copy_no_move(no_copy_no_move const&) = delete; - virtual ~interface() = default; -}; + void operator=(no_copy_no_move const&) = delete; + }; -} // lava + struct interface { + virtual ~interface() = default; + }; + +} // namespace lava diff --git a/liblava/core/version.hpp b/liblava/core/version.hpp index 9b7f3034b3178d4aa4922e9379b59625a1d4d9cc..673d58470aa106cc055fb52da7da8b4752ad3164 100644 --- a/liblava/core/version.hpp +++ b/liblava/core/version.hpp @@ -8,35 +8,33 @@ namespace lava { -struct internal_version { + struct internal_version { + i32 major = LIBLAVA_VERSION_MAJOR; + i32 minor = LIBLAVA_VERSION_MINOR; + i32 patch = LIBLAVA_VERSION_PATCH; + }; - i32 major = LIBLAVA_VERSION_MAJOR; - i32 minor = LIBLAVA_VERSION_MINOR; - i32 patch = LIBLAVA_VERSION_PATCH; -}; + constexpr internal_version const _internal_version = {}; -constexpr internal_version const _internal_version = {}; + enum class version_stage { -enum class version_stage { + preview, + alpha, + beta, + rc, + release + }; - preview, - alpha, - beta, - rc, - release -}; + struct version { + i32 year = 2020; + i32 release = 0; + version_stage stage = version_stage::preview; + i32 rev = 2; + }; -struct version { + constexpr version const _version = {}; - i32 year = 2020; - i32 release = 0; - version_stage stage = version_stage::preview; - i32 rev = 2; -}; + constexpr name _build_date = LIBLAVA_BUILD_DATE; + constexpr name _build_time = LIBLAVA_BUILD_TIME; -constexpr version const _version = {}; - -constexpr name _build_date = LIBLAVA_BUILD_DATE; -constexpr name _build_time = LIBLAVA_BUILD_TIME; - -} // lava +} // namespace lava diff --git a/liblava/def.hpp b/liblava/def.hpp index 619c46c39fc01c73fc7074f74229489f936c2a08..0c5f7a0dca951d6fa94a5985587bf649c6ec1278 100644 --- a/liblava/def.hpp +++ b/liblava/def.hpp @@ -5,11 +5,11 @@ #pragma once #if defined(NDEBUG) -#define LIBLAVA_DEBUG 0 +# define LIBLAVA_DEBUG 0 #endif #ifndef LIBLAVA_DEBUG -#define LIBLAVA_DEBUG 1 +# define LIBLAVA_DEBUG 1 #endif #define LIBLAVA_BUILD_DATE __DATE__ diff --git a/liblava/frame/frame.cpp b/liblava/frame/frame.cpp index 47eb04a18c16433f86808c8272afb44c22919164..b7b373de3a8c722d8f868c79ce6c52096733dc50 100644 --- a/liblava/frame/frame.cpp +++ b/liblava/frame/frame.cpp @@ -2,20 +2,19 @@ // copyright : Copyright (c) 2018-present, Lava Block OÜ // license : MIT; see accompanying LICENSE file -#include <liblava/frame/frame.hpp> #include <liblava/base/memory.hpp> +#include <liblava/frame/frame.hpp> #define GLFW_INCLUDE_NONE #define GLFW_INCLUDE_VULKAN #include <GLFW/glfw3.h> #if !LIBLAVA_DEBUG && _WIN32 -#include <windows.h> -#include <iostream> +# include <windows.h> +# include <iostream> #endif void hide_console(lava::name program) { - #if !LIBLAVA_DEBUG && _WIN32 auto version_str = fmt::format("{} {}", lava::_liblava_, lava::str(lava::to_string(lava::_version))); @@ -25,7 +24,6 @@ void hide_console(lava::name program) { const auto sleep_ms = lava::to_i32(1.0 / dot_count * 1000.f); for (auto i = 0u; i < dot_count; ++i) { - lava::sleep(lava::ms(sleep_ms)); std::cout << "."; } @@ -36,284 +34,262 @@ void hide_console(lava::name program) { } void log_command_line(argh::parser& cmd_line) { - if (!cmd_line.pos_args().empty()) { - for (auto& pos_arg : cmd_line.pos_args()) lava::log()->info("cmd {}", lava::str(pos_arg)); } if (!cmd_line.flags().empty()) { - for (auto& flag : cmd_line.flags()) lava::log()->info("cmd flag {}", lava::str(flag)); } if (!cmd_line.params().empty()) { - for (auto& param : cmd_line.params()) lava::log()->info("cmd para {} = {}", lava::str(param.first), lava::str(param.second)); } } -lava::ms lava::now() { return to_ms(glfwGetTime()); } +lava::ms lava::now() { + return to_ms(glfwGetTime()); +} namespace lava { -static bool frame_initialized = false; + static bool frame_initialized = false; -frame::frame(argh::parser cmd_line) { + frame::frame(argh::parser cmd_line) { + frame_config c; + c.cmd_line = cmd_line; - frame_config c; - c.cmd_line = cmd_line; - - setup(c); -} - -frame::frame(frame_config c) { - - setup(c); -} + setup(c); + } -frame::~frame() { teardown(); } + frame::frame(frame_config c) { + setup(c); + } -bool frame::ready() const { return frame_initialized; } + frame::~frame() { + teardown(); + } -bool frame::setup(frame_config c) { + bool frame::ready() const { + return frame_initialized; + } - if (frame_initialized) - return false; + bool frame::setup(frame_config c) { + if (frame_initialized) + return false; - config = c; + config = c; - if (config.app_info.app_name == nullptr) - config.app_info.app_name = config.app; + if (config.app_info.app_name == nullptr) + config.app_info.app_name = config.app; #if LIBLAVA_DEBUG - config.log.debug = true; - config.debug.validation = true; - config.debug.utils = true; -#endif - - hide_console(config.app); - - auto cmd_line = config.cmd_line; - - if (cmd_line[{ "-d", "--debug" }]) + config.log.debug = true; config.debug.validation = true; - - if (cmd_line[{ "-r", "--renderdoc" }]) - config.debug.render_doc = true; - - if (cmd_line[{ "-v", "--verbose" }]) - config.debug.verbose = true; - - if (cmd_line[{ "-u", "--utils" }]) config.debug.utils = true; +#endif - if (auto log_level = -1; cmd_line({ "-l", "--log" }) >> log_level) - config.log.level = log_level; - - setup_log(config.log); - - log()->info(">>> {} / {} - {} / {} - {} {}", str(to_string(_version)), - str(to_string(_internal_version)), - config.app_info.app_name, - str(to_string(config.app_info.app_version)), - _build_date, _build_time); + hide_console(config.app); - log_command_line(cmd_line); + auto cmd_line = config.cmd_line; - if (config.log.level >= 0) - log()->info("log {}", spdlog::level::to_string_view((spdlog::level::level_enum)config.log.level)); + if (cmd_line[{ "-d", "--debug" }]) + config.debug.validation = true; - glfwSetErrorCallback([](i32 error, name description) { + if (cmd_line[{ "-r", "--renderdoc" }]) + config.debug.render_doc = true; - log()->error("glfw {} - {}", error, description); - }); + if (cmd_line[{ "-v", "--verbose" }]) + config.debug.verbose = true; - log()->debug("glfw {}", glfwGetVersionString()); + if (cmd_line[{ "-u", "--utils" }]) + config.debug.utils = true; - if (glfwInit() != GLFW_TRUE) { + if (auto log_level = -1; cmd_line({ "-l", "--log" }) >> log_level) + config.log.level = log_level; - log()->error("init glfw"); - return false; - } + setup_log(config.log); - if (glfwVulkanSupported() != GLFW_TRUE) { + log()->info(">>> {} / {} - {} / {} - {} {}", str(to_string(_version)), + str(to_string(_internal_version)), + config.app_info.app_name, + str(to_string(config.app_info.app_version)), + _build_date, _build_time); - log()->error("vulkan not supported"); - return false; - } + log_command_line(cmd_line); - glfwDefaultWindowHints(); - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + if (config.log.level >= 0) + log()->info("log {}", spdlog::level::to_string_view((spdlog::level::level_enum) config.log.level)); - auto result = volkInitialize(); - if (failed(result)) { + glfwSetErrorCallback([](i32 error, name description) { + log()->error("glfw {} - {}", error, description); + }); - log()->error("init volk"); - return false; - } + log()->debug("glfw {}", glfwGetVersionString()); - log()->info("vulkan {}", str(to_string(instance::get_version()))); + if (glfwInit() != GLFW_TRUE) { + log()->error("init glfw"); + return false; + } - auto glfw_extensions_count = 0u; - auto glfw_extensions = glfwGetRequiredInstanceExtensions(&glfw_extensions_count); - for (auto i = 0u; i < glfw_extensions_count; ++i) - config.param.extensions.push_back(glfw_extensions[i]); + if (glfwVulkanSupported() != GLFW_TRUE) { + log()->error("vulkan not supported"); + return false; + } - if (!instance::singleton().create(config.param, config.debug, config.app_info)) { + glfwDefaultWindowHints(); + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - log()->error("create instance"); - return false; - } + auto result = volkInitialize(); + if (failed(result)) { + log()->error("init volk"); + return false; + } - log()->debug("physfs {}", str(to_string(file_system::get_version()))); + log()->info("vulkan {}", str(to_string(instance::get_version()))); - if (!file_system::instance().initialize(str(cmd_line[0]), config.org, config.app, config.ext)) { + auto glfw_extensions_count = 0u; + auto glfw_extensions = glfwGetRequiredInstanceExtensions(&glfw_extensions_count); + for (auto i = 0u; i < glfw_extensions_count; ++i) + config.param.extensions.push_back(glfw_extensions[i]); - log()->error("init file system"); - return false; - } + if (!instance::singleton().create(config.param, config.debug, config.app_info)) { + log()->error("create instance"); + return false; + } - file_system::instance().mount_res(); + log()->debug("physfs {}", str(to_string(file_system::get_version()))); - frame_initialized = true; + if (!file_system::instance().initialize(str(cmd_line[0]), config.org, config.app, config.ext)) { + log()->error("init file system"); + return false; + } - log()->info("---"); + file_system::instance().mount_res(); - return true; -} + frame_initialized = true; -void frame::teardown() { + log()->info("---"); - if (!frame_initialized) - return; + return true; + } - manager.clear(); + void frame::teardown() { + if (!frame_initialized) + return; - instance::singleton().destroy(); + manager.clear(); - glfwTerminate(); + instance::singleton().destroy(); - log()->info("<<<"); + glfwTerminate(); - log()->flush(); - spdlog::drop_all(); + log()->info("<<<"); - file_system::instance().terminate(); + log()->flush(); + spdlog::drop_all(); - frame_initialized = false; -} + file_system::instance().terminate(); -frame::result frame::run() { + frame_initialized = false; + } - if (running) - return error::running; + frame::result frame::run() { + if (running) + return error::running; - running = true; - start_time = now(); + running = true; + start_time = now(); - while (running) { + while (running) { + if (!run_step()) + break; + } - if (!run_step()) - break; - } + manager.wait_idle(); - manager.wait_idle(); + trigger_run_end(); - trigger_run_end(); + auto result = 0; + if (running) { + result = error::aborted; + running = false; + } - auto result = 0; - if (running) { + start_time = {}; - result = error::aborted; - running = false; + return result; } - start_time = {}; - - return result; -} + bool frame::run_step() { + handle_events(wait_for_events); -bool frame::run_step() { + if (!run_once_list.empty()) { + for (auto& func : run_once_list) + if (!func()) + return false; - handle_events(wait_for_events); + run_once_list.clear(); + } - if (!run_once_list.empty()) { - - for (auto& func : run_once_list) - if (!func()) + for (auto& func : run_map) + if (!func.second()) return false; - run_once_list.clear(); + return true; } - for (auto& func : run_map) - if (!func.second()) + bool frame::shut_down() { + if (!running) return false; - return true; -} - -bool frame::shut_down() { - - if (!running) - return false; - - running = false; - - return true; -} - -id frame::add_run(run_func_ref func) { + running = false; - auto id = ids::next(); - run_map.emplace(id, func); + return true; + } - return id; -} + id frame::add_run(run_func_ref func) { + auto id = ids::next(); + run_map.emplace(id, func); -id frame::add_run_end(run_end_func_ref func) { + return id; + } - auto id = ids::next(); - run_end_map.emplace(id, func); + id frame::add_run_end(run_end_func_ref func) { + auto id = ids::next(); + run_end_map.emplace(id, func); - return id; -} + return id; + } -bool frame::remove(id::ref id) { + bool frame::remove(id::ref id) { + auto result = false; - auto result = false; + if (run_map.count(id)) { + run_map.erase(id); + result = true; + } else if (run_end_map.count(id)) { + run_end_map.erase(id); + result = true; + } - if (run_map.count(id)) { + if (result) + ids::free(id); - run_map.erase(id); - result = true; + return result; } - else if (run_end_map.count(id)) { - run_end_map.erase(id); - result = true; + void frame::trigger_run_end() { + for (auto& func : reverse(run_end_map)) + func.second(); } - - if (result) - ids::free(id); - return result; -} - -void frame::trigger_run_end() { - - for (auto& func : reverse(run_end_map)) - func.second(); -} - -} // lava +} // namespace lava void lava::handle_events(bool wait) { - if (wait) glfwWaitEvents(); else @@ -321,16 +297,13 @@ void lava::handle_events(bool wait) { } void lava::handle_events(ms timeout) { - glfwWaitEventsTimeout(to_sec(timeout)); } void lava::handle_events(seconds timeout) { - glfwWaitEventsTimeout(to_r64(timeout.count())); } void lava::post_empty_event() { - glfwPostEmptyEvent(); } diff --git a/liblava/frame/frame.hpp b/liblava/frame/frame.hpp index f3e7b709e3b28ca4a87486d4e7686efa013cc376..27bf7f426aedab654fde872e918630cadb4980c3 100644 --- a/liblava/frame/frame.hpp +++ b/liblava/frame/frame.hpp @@ -4,128 +4,135 @@ #pragma once -#include <liblava/base/instance.hpp> -#include <liblava/base/device.hpp> - #include <argh.h> +#include <liblava/base/device.hpp> +#include <liblava/base/instance.hpp> namespace lava { -struct frame_config { - - using ref = frame_config const&; - - explicit frame_config() = default; - explicit frame_config(name a, argh::parser cl) - : app(a), cmd_line(cl) {} - - argh::parser cmd_line; + struct frame_config { + using ref = frame_config const&; - name org = _liblava_; - name app = _lava_; - name ext = _zip_; + explicit frame_config() = default; + explicit frame_config(name a, argh::parser cl) + : app(a), cmd_line(cl) {} - log_config log; + argh::parser cmd_line; - instance::app_info app_info; - instance::create_param param; - instance::debug_config debug; -}; + name org = _liblava_; + name app = _lava_; + name ext = _zip_; -enum error { + log_config log; - not_ready = -1, - create_failed = -2, - aborted = -3, - running = -4, -}; + instance::app_info app_info; + instance::create_param param; + instance::debug_config debug; + }; -ms now(); + enum error { -struct frame : interface, no_copy_no_move { + not_ready = -1, + create_failed = -2, + aborted = -3, + running = -4, + }; - using ptr = std::shared_ptr<frame>; + ms now(); - explicit frame(argh::parser cmd_line); - explicit frame(frame_config config); - ~frame() override; + struct frame : interface, no_copy_no_move { + using ptr = std::shared_ptr<frame>; - bool ready() const; + explicit frame(argh::parser cmd_line); + explicit frame(frame_config config); + ~frame() override; - using result = i32; // error < 0 - result run(); + bool ready() const; - bool shut_down(); + using result = i32; // error < 0 + result run(); - using run_func = std::function<bool()>; - using run_func_ref = run_func const&; + bool shut_down(); - id add_run(run_func_ref func); - - using run_end_func = std::function<void()>; - using run_end_func_ref = run_end_func const&; + using run_func = std::function<bool()>; + using run_func_ref = run_func const&; - id add_run_end(run_end_func_ref func); + id add_run(run_func_ref func); - using run_once_func = std::function<bool()>; - using run_once_func_ref = run_once_func const&; + using run_end_func = std::function<void()>; + using run_end_func_ref = run_end_func const&; - void add_run_once(run_once_func_ref func) { + id add_run_end(run_end_func_ref func); - run_once_list.push_back(func); - } + using run_once_func = std::function<bool()>; + using run_once_func_ref = run_once_func const&; - bool remove(id::ref id); + void add_run_once(run_once_func_ref func) { + run_once_list.push_back(func); + } - ms get_running_time() const { return now() - start_time; } + bool remove(id::ref id); - argh::parser const& get_cmd_line() const { return config.cmd_line; } - frame_config::ref get_config() const { return config; } - name get_name() const { return config.app; } + ms get_running_time() const { + return now() - start_time; + } - bool waiting_for_events() const { return wait_for_events; } - void set_wait_for_events(bool value = true) { wait_for_events = value; } + argh::parser const& get_cmd_line() const { + return config.cmd_line; + } + frame_config::ref get_config() const { + return config; + } + name get_name() const { + return config.app; + } - device_ptr create_device(index physical_device = 0) { + bool waiting_for_events() const { + return wait_for_events; + } + void set_wait_for_events(bool value = true) { + wait_for_events = value; + } - auto device = manager.create(physical_device); - if (!device) - return nullptr; + device_ptr create_device(index physical_device = 0) { + auto device = manager.create(physical_device); + if (!device) + return nullptr; - return device.get(); - } + return device.get(); + } - device_manager manager; + device_manager manager; -private: - bool setup(frame_config config); - void teardown(); + private: + bool setup(frame_config config); + void teardown(); - bool run_step(); + bool run_step(); - void trigger_run_end(); + void trigger_run_end(); - frame_config config; + frame_config config; - bool running = false; - bool wait_for_events = false; - ms start_time; + bool running = false; + bool wait_for_events = false; + ms start_time; - using run_func_map = std::map<id, run_func>; - run_func_map run_map; + using run_func_map = std::map<id, run_func>; + run_func_map run_map; - using run_end_func_map = std::map<id, run_end_func>; - run_end_func_map run_end_map; + using run_end_func_map = std::map<id, run_end_func>; + run_end_func_map run_end_map; - using run_once_func_list = std::vector<run_once_func>; - run_once_func_list run_once_list; -}; + using run_once_func_list = std::vector<run_once_func>; + run_once_func_list run_once_list; + }; -void handle_events(bool wait = false); + void handle_events(bool wait = false); -void handle_events(ms timeout); -void handle_events(seconds timeout); + void handle_events(ms timeout); + void handle_events(seconds timeout); -void post_empty_event(); + void post_empty_event(); -} // lava +} // namespace lava diff --git a/liblava/frame/input.cpp b/liblava/frame/input.cpp index 3d4b4c9b51b638f056ecb26d5cc37b48407a5ec1..d7f338c8d5525f5ea8e36ed2b9ec66b12aa25d0a 100644 --- a/liblava/frame/input.cpp +++ b/liblava/frame/input.cpp @@ -10,153 +10,134 @@ namespace lava { -template <typename T> -void _handle_events(input_events<T>& events, input_callback::func<T> input_callback) { - - for (auto& event : events) { - - auto handled = false; - - for (auto& listener : events.listeners.get_list()) { + template<typename T> + void _handle_events(input_events<T>& events, input_callback::func<T> input_callback) { + for (auto& event : events) { + auto handled = false; + + for (auto& listener : events.listeners.get_list()) { + if (listener.second(event)) { + handled = true; + break; + } + } - if (listener.second(event)) { + if (handled) + continue; - handled = true; - break; - } + if (input_callback) + input_callback(event); } - if (handled) - continue; - - if (input_callback) - input_callback(event); + events.clear(); } - events.clear(); -} - -void input::handle_events() { - - _handle_events<key_event>(key, [&](auto& event) { - - for (auto& callback : callbacks) - if (callback->on_key_event) - if (callback->on_key_event(event)) - return true; - - return false; - }); - - _handle_events<scroll_event>(scroll, [&](auto& event) { - - for (auto& callback : callbacks) - if (callback->on_scroll_event) - if (callback->on_scroll_event(event)) - return true; - - return false; - }); - - _handle_events<mouse_move_event>(mouse_move, [&](auto& event) { - - for (auto& callback : callbacks) - if (callback->on_mouse_move_event) - if (callback->on_mouse_move_event(event)) - return true; - - return false; - }); - - _handle_events<mouse_button_event>(mouse_button, [&](auto& event) { - - for (auto& callback : callbacks) - if (callback->on_mouse_button_event) - if (callback->on_mouse_button_event(event)) - return true; - - return false; - }); - - _handle_events<mouse_active_event>(mouse_active, [&](auto& event) { - - for (auto& callback : callbacks) - if (callback->on_mouse_active_event) - if (callback->on_mouse_active_event(event)) - return true; - - return false; - }); - - _handle_events<path_drop_event>(path_drop, [&](auto& event) { - - for (auto& callback : callbacks) - if (callback->on_path_drop_event) - if (callback->on_path_drop_event(event)) - return true; - - return false; - }); -} - -gamepad::gamepad(gamepad_id id) : id(id) { - - if (ready()) - update(); -} - -name gamepad::get_name() const { - - return glfwGetGamepadName(to_i32(id));; -} - -bool gamepad::ready() const { - - return glfwJoystickIsGamepad(to_i32(id)); -} - -bool gamepad::update() { + void input::handle_events() { + _handle_events<key_event>(key, [&](auto& event) { + for (auto& callback : callbacks) + if (callback->on_key_event) + if (callback->on_key_event(event)) + return true; + + return false; + }); + + _handle_events<scroll_event>(scroll, [&](auto& event) { + for (auto& callback : callbacks) + if (callback->on_scroll_event) + if (callback->on_scroll_event(event)) + return true; + + return false; + }); + + _handle_events<mouse_move_event>(mouse_move, [&](auto& event) { + for (auto& callback : callbacks) + if (callback->on_mouse_move_event) + if (callback->on_mouse_move_event(event)) + return true; + + return false; + }); + + _handle_events<mouse_button_event>(mouse_button, [&](auto& event) { + for (auto& callback : callbacks) + if (callback->on_mouse_button_event) + if (callback->on_mouse_button_event(event)) + return true; + + return false; + }); + + _handle_events<mouse_active_event>(mouse_active, [&](auto& event) { + for (auto& callback : callbacks) + if (callback->on_mouse_active_event) + if (callback->on_mouse_active_event(event)) + return true; + + return false; + }); + + _handle_events<path_drop_event>(path_drop, [&](auto& event) { + for (auto& callback : callbacks) + if (callback->on_path_drop_event) + if (callback->on_path_drop_event(event)) + return true; + + return false; + }); + } - return glfwGetGamepadState(to_i32(id), (GLFWgamepadstate*)&state) == GLFW_TRUE; -} + gamepad::gamepad(gamepad_id id) + : id(id) { + if (ready()) + update(); + } -gamepad_manager::gamepad_manager() { - - glfwSetJoystickCallback([](int jid, int e) { + name gamepad::get_name() const { + return glfwGetGamepadName(to_i32(id)); + ; + } - for (auto& event : instance().map) - if (event.second(gamepad(gamepad_id(jid)), e == GLFW_CONNECTED)) - break; - }); -} + bool gamepad::ready() const { + return glfwJoystickIsGamepad(to_i32(id)); + } -id gamepad_manager::add(listener_func event) { + bool gamepad::update() { + return glfwGetGamepadState(to_i32(id), (GLFWgamepadstate*) &state) == GLFW_TRUE; + } - auto id = ids::next(); + gamepad_manager::gamepad_manager() { + glfwSetJoystickCallback([](int jid, int e) { + for (auto& event : instance().map) + if (event.second(gamepad(gamepad_id(jid)), e == GLFW_CONNECTED)) + break; + }); + } - map.emplace(id, event); + id gamepad_manager::add(listener_func event) { + auto id = ids::next(); - return id; -} + map.emplace(id, event); -void gamepad_manager::remove(id::ref id) { + return id; + } - if (!map.count(id)) - return; + void gamepad_manager::remove(id::ref id) { + if (!map.count(id)) + return; - map.erase(id); + map.erase(id); - ids::free(id); -} + ids::free(id); + } -} // lava +} // namespace lava lava::gamepad::list lava::gamepads() { - gamepad::list result; for (auto id = GLFW_JOYSTICK_1; id < GLFW_JOYSTICK_LAST; ++id) { - if (glfwJoystickIsGamepad(id)) result.emplace_back(gamepad_id(id)); } diff --git a/liblava/frame/input.hpp b/liblava/frame/input.hpp index 943b7abfa678483ca4b053b1ab16422f90ef4ed3..82e9b8a872e503ed1b3b52e744ea685421266c6f 100644 --- a/liblava/frame/input.hpp +++ b/liblava/frame/input.hpp @@ -4,333 +4,472 @@ #pragma once -#include <liblava/util/utility.hpp> #include <liblava/core/id.hpp> +#include <liblava/util/utility.hpp> namespace lava { -enum class key : i32 { - - unknown = -1, - - /* printable keys */ - - space = 32, - apostrophe = 29, /* ' */ - comma = 44, /* , */ - minus = 45, /* - */ - period = 46, /* . */ - slash = 47, /* / */ - - _0 = 48, - _1, _2, _3, _4, _5, _6, _7, _8, _9, - - semicolon = 59, /* ; */ - equal = 61, /* = */ - - a = 65, - b, c, d, e, f, g, h, i, j, k, l, m, n, - o, p, q, r, s, t, u, v, w, x, y, z, - - left_bracket = 91, /* [ */ - backslash = 92, /* \ */ - right_bracket = 93, /* ] */ - grave_accent = 96, /* ` */ - - world_1 = 161, /* non-US #1 */ - world_2 = 162, /* non-US #2 */ - - /* function keys */ - - escape = 256, - enter, tab, backspace, insert, del, /* delete */ - - right, left, down, up, - - page_up, page_down, home, end, - - caps_lock = 280, - scroll_lock, num_lock, print_screen, pause, - - f1 = 290, - f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, - f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, - - kp_0 = 320, - kp_1, kp_2, kp_3, kp_4, kp_5, kp_6, kp_7, kp_8, kp_9, - - kp_decimal, kp_divide, kp_multiply, kp_subtract, - kp_add, kp_enter, kp_equal, - - left_shift = 340, - left_control, left_alt, left_super, - - right_shift, right_control, right_alt, right_super, - - menu, - - last = menu, -}; - -enum class action : type { - - release = 0, press, repeat -}; - -enum class mod : c8 { - - shift = 0x01, - control = 0x02, - alt = 0x04, - super = 0x08, - caps_lock = 0x10, - num_lock = 0x20, -}; - -struct key_event { - - using ref = key_event const&; - using func = std::function<bool(ref)>; - using listeners = std::map<id, func>; - using list = std::vector<key_event>; - - id sender; - - lava::key key; - lava::action action; - lava::mod mod; - - i32 scancode = 0; - - bool pressed(lava::key k) const { return action == action::press && key == k; } - bool released(lava::key k) const { return action == action::release && key == k; } - bool repeated(lava::key k) const { return action == action::repeat && key == k; } - - bool active() const { return action == action::press || action == action::repeat; } - - bool pressed(lava::key k, lava::mod m) const { return pressed(k) && mod == m; } -}; - -struct scroll_offset { - - r64 x = 0.0; - r64 y = 0.0; -}; - -struct scroll_event { - - using ref = scroll_event const&; - using func = std::function<bool(ref)>; - using listeners = std::map<id, func>; - using list = std::vector<scroll_event>; - - id sender; - - scroll_offset offset; -}; - -struct mouse_position { - - r64 x = 0.0; - r64 y = 0.0; -}; + enum class key : i32 { + + unknown = -1, + + /* printable keys */ + + space = 32, + apostrophe = 29, /* ' */ + comma = 44, /* , */ + minus = 45, /* - */ + period = 46, /* . */ + slash = 47, /* / */ + + _0 = 48, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + + semicolon = 59, /* ; */ + equal = 61, /* = */ + + a = 65, + b, + c, + d, + e, + f, + g, + h, + i, + j, + k, + l, + m, + n, + o, + p, + q, + r, + s, + t, + u, + v, + w, + x, + y, + z, + + left_bracket = 91, /* [ */ + backslash = 92, /* \ */ + right_bracket = 93, /* ] */ + grave_accent = 96, /* ` */ + + world_1 = 161, /* non-US #1 */ + world_2 = 162, /* non-US #2 */ + + /* function keys */ + + escape = 256, + enter, + tab, + backspace, + insert, + del, /* delete */ + + right, + left, + down, + up, + + page_up, + page_down, + home, + end, + + caps_lock = 280, + scroll_lock, + num_lock, + print_screen, + pause, + + f1 = 290, + f2, + f3, + f4, + f5, + f6, + f7, + f8, + f9, + f10, + f11, + f12, + f13, + f14, + f15, + f16, + f17, + f18, + f19, + f20, + f21, + f22, + f23, + f24, + f25, + + kp_0 = 320, + kp_1, + kp_2, + kp_3, + kp_4, + kp_5, + kp_6, + kp_7, + kp_8, + kp_9, + + kp_decimal, + kp_divide, + kp_multiply, + kp_subtract, + kp_add, + kp_enter, + kp_equal, + + left_shift = 340, + left_control, + left_alt, + left_super, + + right_shift, + right_control, + right_alt, + right_super, + + menu, + + last = menu, + }; -struct mouse_move_event { + enum class action : type { - using ref = mouse_move_event const&; - using func = std::function<bool(ref)>; - using listeners = std::map<id, func>; - using list = std::vector<mouse_move_event>; + release = 0, + press, + repeat + }; - id sender; + enum class mod : c8 { - mouse_position position; -}; + shift = 0x01, + control = 0x02, + alt = 0x04, + super = 0x08, + caps_lock = 0x10, + num_lock = 0x20, + }; -enum class mouse_button : type { + struct key_event { + using ref = key_event const&; + using func = std::function<bool(ref)>; + using listeners = std::map<id, func>; + using list = std::vector<key_event>; + + id sender; + + lava::key key; + lava::action action; + lava::mod mod; + + i32 scancode = 0; + + bool pressed(lava::key k) const { + return action == action::press && key == k; + } + bool released(lava::key k) const { + return action == action::release && key == k; + } + bool repeated(lava::key k) const { + return action == action::repeat && key == k; + } + + bool active() const { + return action == action::press || action == action::repeat; + } + + bool pressed(lava::key k, lava::mod m) const { + return pressed(k) && mod == m; + } + }; - _1 = 0, _2, _3, _4, _5, _6, _7, _8, + struct scroll_offset { + r64 x = 0.0; + r64 y = 0.0; + }; - last = _8, + struct scroll_event { + using ref = scroll_event const&; + using func = std::function<bool(ref)>; + using listeners = std::map<id, func>; + using list = std::vector<scroll_event>; - left = _1, right = _2, middle = _3, -}; + id sender; -struct mouse_button_event { + scroll_offset offset; + }; - using ref = mouse_button_event const&; - using func = std::function<bool(ref)>; - using listeners = std::map<id, func>; - using list = std::vector<mouse_button_event>; + struct mouse_position { + r64 x = 0.0; + r64 y = 0.0; + }; - id sender; + struct mouse_move_event { + using ref = mouse_move_event const&; + using func = std::function<bool(ref)>; + using listeners = std::map<id, func>; + using list = std::vector<mouse_move_event>; - mouse_button button; + id sender; - lava::action action; - lava::mod mod; + mouse_position position; + }; - bool pressed(mouse_button b) const { return action == action::press && button == b; } - bool released(mouse_button b) const { return action == action::release && button == b; } -}; + enum class mouse_button : type { -struct path_drop_event { + _1 = 0, + _2, + _3, + _4, + _5, + _6, + _7, + _8, - using ref = path_drop_event const&; - using func = std::function<bool(ref)>; - using listeners = std::map<id, func>; - using list = std::vector<path_drop_event>; + last = _8, - id sender; + left = _1, + right = _2, + middle = _3, + }; - string_list files; -}; + struct mouse_button_event { + using ref = mouse_button_event const&; + using func = std::function<bool(ref)>; + using listeners = std::map<id, func>; + using list = std::vector<mouse_button_event>; -struct mouse_active_event { + id sender; - using ref = mouse_active_event const&; - using func = std::function<bool(ref)>; - using listeners = std::map<id, func>; - using list = std::vector<mouse_active_event>; + mouse_button button; - id sender; + lava::action action; + lava::mod mod; - bool active = false; -}; + bool pressed(mouse_button b) const { + return action == action::press && button == b; + } + bool released(mouse_button b) const { + return action == action::release && button == b; + } + }; -struct input_callback { + struct path_drop_event { + using ref = path_drop_event const&; + using func = std::function<bool(ref)>; + using listeners = std::map<id, func>; + using list = std::vector<path_drop_event>; - using list = std::vector<input_callback*>; + id sender; - template <typename T> - using func = std::function<bool(typename T::ref)>; + string_list files; + }; - key_event::func on_key_event; - scroll_event::func on_scroll_event; + struct mouse_active_event { + using ref = mouse_active_event const&; + using func = std::function<bool(ref)>; + using listeners = std::map<id, func>; + using list = std::vector<mouse_active_event>; - mouse_move_event::func on_mouse_move_event; - mouse_button_event::func on_mouse_button_event; - mouse_active_event::func on_mouse_active_event; - path_drop_event::func on_path_drop_event; -}; + id sender; -template <typename T> -struct input_events : T::list { + bool active = false; + }; - void add(typename T::ref event) { this->push_back(event); } + struct input_callback { + using list = std::vector<input_callback*>; - id_listeners<T> listeners; -}; + template<typename T> + using func = std::function<bool(typename T::ref)>; -struct input : id_obj { + key_event::func on_key_event; + scroll_event::func on_scroll_event; - input_events<key_event> key; - input_events<scroll_event> scroll; + mouse_move_event::func on_mouse_move_event; + mouse_button_event::func on_mouse_button_event; + mouse_active_event::func on_mouse_active_event; + path_drop_event::func on_path_drop_event; + }; - input_events<mouse_move_event> mouse_move; - input_events<mouse_button_event> mouse_button; - input_events<mouse_active_event> mouse_active; - input_events<path_drop_event> path_drop; + template<typename T> + struct input_events : T::list { + void add(typename T::ref event) { + this->push_back(event); + } - void handle_events(); + id_listeners<T> listeners; + }; - void add(input_callback* callback) { callbacks.push_back(callback); } - void remove(input_callback* callback) { lava::remove(callbacks, callback); } + struct input : id_obj { + input_events<key_event> key; + input_events<scroll_event> scroll; - mouse_position get_mouse_position() const { return current_position; } - void set_mouse_position(mouse_position const& position) { current_position = position; } + input_events<mouse_move_event> mouse_move; + input_events<mouse_button_event> mouse_button; + input_events<mouse_active_event> mouse_active; + input_events<path_drop_event> path_drop; -private: - mouse_position current_position; + void handle_events(); - input_callback::list callbacks; -}; + void add(input_callback* callback) { + callbacks.push_back(callback); + } + void remove(input_callback* callback) { + lava::remove(callbacks, callback); + } -enum class gamepad_id : ui32 { + mouse_position get_mouse_position() const { + return current_position; + } + void set_mouse_position(mouse_position const& position) { + current_position = position; + } - _1 = 0, _2, _3, _4, _5, _6, _7, _8, _9, - _10, _11, _12, _13, _14, _15, _16, + private: + mouse_position current_position; - last = _16, -}; + input_callback::list callbacks; + }; -enum class gamepad_button : type { + enum class gamepad_id : ui32 { + + _1 = 0, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + _16, + + last = _16, + }; - a = 0, b, x, y, + enum class gamepad_button : type { - left_bumper, right_bumper, + a = 0, + b, + x, + y, - back, start, guide, + left_bumper, + right_bumper, - left_thumb, right_thumb, + back, + start, + guide, - dpad_up, dpad_right, dpad_down, dpad_left, + left_thumb, + right_thumb, - last = dpad_left, + dpad_up, + dpad_right, + dpad_down, + dpad_left, - cross = a, circle = b, - square = x, triangle = y, -}; + last = dpad_left, -enum class gamepad_axis : type { + cross = a, + circle = b, + square = x, + triangle = y, + }; - left_x = 0, left_y, + enum class gamepad_axis : type { - right_x, right_y, + left_x = 0, + left_y, - left_trigger, right_trigger, + right_x, + right_y, - last = right_trigger, -}; + left_trigger, + right_trigger, -struct gamepad { + last = right_trigger, + }; - using list = std::vector<gamepad>; - using ref = gamepad const&; + struct gamepad { + using list = std::vector<gamepad>; + using ref = gamepad const&; - explicit gamepad(gamepad_id id); + explicit gamepad(gamepad_id id); - bool ready() const; - bool update(); + bool ready() const; + bool update(); - bool pressed(gamepad_button button) const { return state.buttons[to_ui32(button)]; } - r32 value(gamepad_axis axis) const { return state.axes[to_ui32(axis)]; } + bool pressed(gamepad_button button) const { + return state.buttons[to_ui32(button)]; + } + r32 value(gamepad_axis axis) const { + return state.axes[to_ui32(axis)]; + } - gamepad_id get_id() const { return id; } - name get_name() const; + gamepad_id get_id() const { + return id; + } + name get_name() const; -private: - gamepad_id id; + private: + gamepad_id id; - struct state { + struct state { + unsigned char buttons[15]; + r32 axes[6]; + }; - unsigned char buttons[15]; - r32 axes[6]; + gamepad::state state; }; - gamepad::state state; -}; + gamepad::list gamepads(); -gamepad::list gamepads(); + struct gamepad_manager { + static gamepad_manager& instance() { + static gamepad_manager manager; + return manager; + } -struct gamepad_manager { + using listener_func = std::function<bool(gamepad, bool)>; - static gamepad_manager& instance() { + id add(listener_func listener); + void remove(id::ref id); - static gamepad_manager manager; - return manager; - } + private: + explicit gamepad_manager(); - using listener_func = std::function<bool(gamepad, bool)>; - - id add(listener_func listener); - void remove(id::ref id); - -private: - explicit gamepad_manager(); - - using listener_map = std::map<id, listener_func>; - listener_map map; -}; + using listener_map = std::map<id, listener_func>; + listener_map map; + }; -} // lava +} // namespace lava diff --git a/liblava/frame/render_target.cpp b/liblava/frame/render_target.cpp index b96a831afb04068453614b97225de2d989e84b38..4d2dba3c80f2b9c84c08dae1b9c59387c3bb3678 100644 --- a/liblava/frame/render_target.cpp +++ b/liblava/frame/render_target.cpp @@ -2,64 +2,58 @@ // copyright : Copyright (c) 2018-present, Lava Block OÜ // license : MIT; see accompanying LICENSE file +#include <liblava/frame/frame.hpp> #include <liblava/frame/render_target.hpp> #include <liblava/frame/window.hpp> -#include <liblava/frame/frame.hpp> namespace lava { -bool render_target::create(device_ptr device, VkSurfaceKHR surface, uv2 size, bool v_sync) { - - if (!target.create(device, surface, size, v_sync)) - return false; - - swapchain_callback.on_created = [&]() { + bool render_target::create(device_ptr device, VkSurfaceKHR surface, uv2 size, bool v_sync) { + if (!target.create(device, surface, size, v_sync)) + return false; - if (on_create_attachments) { + swapchain_callback.on_created = [&]() { + if (on_create_attachments) { + auto target_attachments = on_create_attachments(); - auto target_attachments = on_create_attachments(); + for (auto& callback : target_callbacks) + if (!callback->on_created(target_attachments, { {}, get_size() })) + return false; + } - for (auto& callback : target_callbacks) - if (!callback->on_created(target_attachments, { {}, get_size() })) + if (on_swapchain_start) + if (!on_swapchain_start()) return false; - } - - if (on_swapchain_start) - if (!on_swapchain_start()) - return false; - - return true; - }; - - swapchain_callback.on_destroyed = [&]() { - if (on_swapchain_stop) - on_swapchain_stop(); + return true; + }; - for (auto& callback : target_callbacks) - callback->on_destroyed(); + swapchain_callback.on_destroyed = [&]() { + if (on_swapchain_stop) + on_swapchain_stop(); - if (on_destroy_attachments) - on_destroy_attachments(); - }; + for (auto& callback : target_callbacks) + callback->on_destroyed(); - target.add_callback(&swapchain_callback); + if (on_destroy_attachments) + on_destroy_attachments(); + }; - return true; -} + target.add_callback(&swapchain_callback); -void render_target::destroy() { + return true; + } - target_callbacks.clear(); + void render_target::destroy() { + target_callbacks.clear(); - target.remove_callback(&swapchain_callback); - target.destroy(); -} + target.remove_callback(&swapchain_callback); + target.destroy(); + } -} // lava +} // namespace lava lava::render_target::ptr lava::create_target(window* window, device_ptr device, bool v_sync) { - auto surface = window->create_surface(); if (!surface) return nullptr; diff --git a/liblava/frame/render_target.hpp b/liblava/frame/render_target.hpp index d3012d57ed57dec91817f3c44a79e7f6e693c59c..2934d519766d147ff896f4fee076681ec11123ab 100644 --- a/liblava/frame/render_target.hpp +++ b/liblava/frame/render_target.hpp @@ -9,71 +9,91 @@ namespace lava { -struct render_target : id_obj { - - using ptr = std::shared_ptr<render_target>; - - bool create(device_ptr device, VkSurfaceKHR surface, uv2 size, bool v_sync = false); - void destroy(); - - uv2 get_size() const { return target.get_size(); } - bool resize(uv2 new_size) { return target.resize(new_size); } - - ui32 get_frame_count() const { return target.get_backbuffer_count(); } - - bool reload_request() const { return target.reload_request(); } - void reload() { target.resize(target.get_size()); } - - device_ptr get_device() { return target.get_device(); } - swapchain* get_swapchain() { return ⌖ } - - VkFormat get_format() const { return target.get_format(); } - - image::list const& get_backbuffers() const { return target.get_backbuffers(); } - inline image::ptr get_backbuffer(index index) { - - auto& backbuffers = get_backbuffers(); - if (index >= backbuffers.size()) - return nullptr; - - return backbuffers.at(index); + struct render_target : id_obj { + using ptr = std::shared_ptr<render_target>; + + bool create(device_ptr device, VkSurfaceKHR surface, uv2 size, bool v_sync = false); + void destroy(); + + uv2 get_size() const { + return target.get_size(); + } + bool resize(uv2 new_size) { + return target.resize(new_size); + } + + ui32 get_frame_count() const { + return target.get_backbuffer_count(); + } + + bool reload_request() const { + return target.reload_request(); + } + void reload() { + target.resize(target.get_size()); + } + + device_ptr get_device() { + return target.get_device(); + } + swapchain* get_swapchain() { + return ⌖ + } + + VkFormat get_format() const { + return target.get_format(); + } + + image::list const& get_backbuffers() const { + return target.get_backbuffers(); + } + inline image::ptr get_backbuffer(index index) { + auto& backbuffers = get_backbuffers(); + if (index >= backbuffers.size()) + return nullptr; + + return backbuffers.at(index); + } + + inline VkImage get_backbuffer_image(index index) { + auto result = get_backbuffer(index); + return result ? result->get() : 0; + } + + inline VkImage get_image(index index) { + return get_backbuffer_image(index); + } + + void add_callback(target_callback* callback) { + target_callbacks.push_back(callback); + } + void remove_callback(target_callback* callback) { + remove(target_callbacks, callback); + } + + using swapchain__start_func = std::function<bool()>; + swapchain__start_func on_swapchain_start; + + using swapchain_stop_func = std::function<void()>; + swapchain_stop_func on_swapchain_stop; + + using create_attachments_func = std::function<VkAttachments()>; + create_attachments_func on_create_attachments; + + using destroy_attachments_func = std::function<void()>; + destroy_attachments_func on_destroy_attachments; + + private: + swapchain target; + swapchain::callback swapchain_callback; + + target_callback::list target_callbacks; + }; + + render_target::ptr create_target(window* window, device_ptr device, bool v_sync = false); + + inline render_target::ptr create_target_v_sync(window* window, device_ptr device) { + return create_target(window, device, true); } - inline VkImage get_backbuffer_image(index index) { - - auto result = get_backbuffer(index); - return result ? result->get() : 0; - } - - inline VkImage get_image(index index) { return get_backbuffer_image(index); } - - void add_callback(target_callback* callback) { target_callbacks.push_back(callback); } - void remove_callback(target_callback* callback) { remove(target_callbacks, callback); } - - using swapchain__start_func = std::function<bool()>; - swapchain__start_func on_swapchain_start; - - using swapchain_stop_func = std::function<void()>; - swapchain_stop_func on_swapchain_stop; - - using create_attachments_func = std::function<VkAttachments()>; - create_attachments_func on_create_attachments; - - using destroy_attachments_func = std::function<void()>; - destroy_attachments_func on_destroy_attachments; - -private: - swapchain target; - swapchain::callback swapchain_callback; - - target_callback::list target_callbacks; -}; - -render_target::ptr create_target(window* window, device_ptr device, bool v_sync = false); - -inline render_target::ptr create_target_v_sync(window* window, device_ptr device) { - - return create_target(window, device, true); -} - -} // lava +} // namespace lava diff --git a/liblava/frame/render_thread.hpp b/liblava/frame/render_thread.hpp index f48396cf20d215e1a839df7aa4627be8534f2f2a..e07028721266bb462fec09e29595c31e6c4470ba 100644 --- a/liblava/frame/render_thread.hpp +++ b/liblava/frame/render_thread.hpp @@ -5,71 +5,74 @@ #pragma once #include <liblava/frame/renderer.hpp> - #include <thread> namespace lava { -struct render_thread { - - ~render_thread() { destroy(); } - - bool create(swapchain* swapchain) { - - plotter.on_destroy = [&]() { stop(); }; - - return plotter.create(swapchain); - } - - void destroy() { plotter.destroy(); } - - void start() { thread = std::thread(&render_thread::render_loop, this); } + struct render_thread { + ~render_thread() { + destroy(); + } - void stop() { + bool create(swapchain* swapchain) { + plotter.on_destroy = [&]() { stop(); }; - if (!active) - return; + return plotter.create(swapchain); + } - active = false; - thread.join(); - } + void destroy() { + plotter.destroy(); + } - using render_func = std::function<VkCommandBuffers(ui32)>; - render_func on_render; + void start() { + thread = std::thread(&render_thread::render_loop, this); + } - renderer* get_renderer() { return &plotter; } - bool running() const { return active; } + void stop() { + if (!active) + return; - bool render() { + active = false; + thread.join(); + } - auto frame_index = plotter.begin_frame(); - if (!frame_index) - return false; + using render_func = std::function<VkCommandBuffers(ui32)>; + render_func on_render; - return plotter.end_frame(on_render(*frame_index)); - } + renderer* get_renderer() { + return &plotter; + } + bool running() const { + return active; + } -private: - void render_loop() { + bool render() { + auto frame_index = plotter.begin_frame(); + if (!frame_index) + return false; - active = true; + return plotter.end_frame(on_render(*frame_index)); + } - while (active) { + private: + void render_loop() { + active = true; - if (!plotter.active) - continue; + while (active) { + if (!plotter.active) + continue; - if (!on_render) - continue; + if (!on_render) + continue; - render(); + render(); + } } - } - std::thread thread; - bool active = false; + std::thread thread; + bool active = false; - renderer plotter; -}; + renderer plotter; + }; -} // lava +} // namespace lava diff --git a/liblava/frame/renderer.cpp b/liblava/frame/renderer.cpp index 4a27afca2d9dc72c0d463fb4a9f5988b4c1adc59..2372fec9970a16de84231d7c2852dfb59d08d7bd 100644 --- a/liblava/frame/renderer.cpp +++ b/liblava/frame/renderer.cpp @@ -2,189 +2,172 @@ // copyright : Copyright (c) 2018-present, Lava Block OÜ // license : MIT; see accompanying LICENSE file -#include <liblava/frame/renderer.hpp> - #include <array> +#include <liblava/frame/renderer.hpp> namespace lava { -bool renderer::create(swapchain* t) { - - target = t; - device = target->get_device(); - - queue = device->get_graphics_queue(); - queued_frames = target->get_backbuffer_count(); + bool renderer::create(swapchain* t) { + target = t; + device = target->get_device(); - fences.resize(queued_frames); - fences_in_use.resize(queued_frames, nullptr); - image_acquired_semaphores.resize(queued_frames); - render_complete_semaphores.resize(queued_frames); + queue = device->get_graphics_queue(); + queued_frames = target->get_backbuffer_count(); - for (auto i = 0u; i < queued_frames; ++i) { + fences.resize(queued_frames); + fences_in_use.resize(queued_frames, nullptr); + image_acquired_semaphores.resize(queued_frames); + render_complete_semaphores.resize(queued_frames); - { - VkFenceCreateInfo const create_info + for (auto i = 0u; i < queued_frames; ++i) { { - .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, - .flags = VK_FENCE_CREATE_SIGNALED_BIT, - }; + VkFenceCreateInfo const create_info{ + .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, + .flags = VK_FENCE_CREATE_SIGNALED_BIT, + }; - if (!device->vkCreateFence(&create_info, &fences[i])) - return false; - } + if (!device->vkCreateFence(&create_info, &fences[i])) + return false; + } - { - VkSemaphoreCreateInfo const create_info { - .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, - }; + VkSemaphoreCreateInfo const create_info{ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + }; - if (!device->vkCreateSemaphore(&create_info, &image_acquired_semaphores[i])) - return false; + if (!device->vkCreateSemaphore(&create_info, &image_acquired_semaphores[i])) + return false; - if (!device->vkCreateSemaphore(&create_info, &render_complete_semaphores[i])) - return false; + if (!device->vkCreateSemaphore(&create_info, &render_complete_semaphores[i])) + return false; + } } - } - return true; -} + return true; + } -void renderer::destroy() { + void renderer::destroy() { + if (on_destroy) + on_destroy(); - if (on_destroy) - on_destroy(); + for (auto i = 0u; i < queued_frames; ++i) { + device->vkDestroyFence(fences[i]); + device->vkDestroySemaphore(image_acquired_semaphores[i]); + device->vkDestroySemaphore(render_complete_semaphores[i]); + } - for (auto i = 0u; i < queued_frames; ++i) { + fences.clear(); + fences_in_use.clear(); + image_acquired_semaphores.clear(); + render_complete_semaphores.clear(); - device->vkDestroyFence(fences[i]); - device->vkDestroySemaphore(image_acquired_semaphores[i]); - device->vkDestroySemaphore(render_complete_semaphores[i]); + queued_frames = 0; } - fences.clear(); - fences_in_use.clear(); - image_acquired_semaphores.clear(); - render_complete_semaphores.clear(); - - queued_frames = 0; -} + std::optional<index> renderer::begin_frame() { + if (!active) + return {}; -std::optional<index> renderer::begin_frame() { + std::array<VkFence, 1> const wait_fences = { fences[current_sync] }; - if (!active) - return {}; + for (;;) { + auto result = device->vkWaitForFences(to_ui32(wait_fences.size()), wait_fences.data(), VK_TRUE, 100); + if (result) + break; - std::array<VkFence, 1> const wait_fences = { fences[current_sync] }; + if (result.value == VK_TIMEOUT) + continue; - for (;;) { + if (result.value == VK_ERROR_OUT_OF_DATE_KHR) { + target->request_reload(); + return {}; + } - auto result = device->vkWaitForFences(to_ui32(wait_fences.size()), wait_fences.data(), VK_TRUE, 100); - if (result) - break; + if (!result) + return {}; + } - if (result.value == VK_TIMEOUT) - continue; + auto current_semaphore = image_acquired_semaphores[current_sync]; + auto result = device->vkAcquireNextImageKHR(target->get(), UINT64_MAX, current_semaphore, 0, &frame_index); if (result.value == VK_ERROR_OUT_OF_DATE_KHR) { - target->request_reload(); return {}; } - if (!result) - return {}; - } - - auto current_semaphore = image_acquired_semaphores[current_sync]; - - auto result = device->vkAcquireNextImageKHR(target->get(), UINT64_MAX, current_semaphore, 0, &frame_index); - if (result.value == VK_ERROR_OUT_OF_DATE_KHR) { + // because frames might not come in sequential order current frame might still be locked + if ((fences_in_use[frame_index] != nullptr) && (fences_in_use[frame_index] != fences[current_sync])) { + auto result = device->vkWaitForFences(1, &fences_in_use[frame_index], VK_TRUE, UINT64_MAX); - target->request_reload(); - return {}; - } - - // because frames might not come in sequential order current frame might still be locked - if ((fences_in_use[frame_index] != nullptr) && (fences_in_use[frame_index] != fences[current_sync])) { - - auto result = device->vkWaitForFences(1, &fences_in_use[frame_index], VK_TRUE, UINT64_MAX); - - if (result.value == VK_ERROR_OUT_OF_DATE_KHR) { + if (result.value == VK_ERROR_OUT_OF_DATE_KHR) { + target->request_reload(); + return {}; + } - target->request_reload(); - return {}; + if (!result) + return {}; } + fences_in_use[frame_index] = fences[current_sync]; + if (!result) return {}; - } - - fences_in_use[frame_index] = fences[current_sync]; - if (!result) - return {}; + if (!device->vkResetFences(to_ui32(wait_fences.size()), wait_fences.data())) + return {}; - if (!device->vkResetFences(to_ui32(wait_fences.size()), wait_fences.data())) - return {}; + return get_frame(); + } - return get_frame(); -} + bool renderer::end_frame(VkCommandBuffers const& cmd_buffers) { + assert(!cmd_buffers.empty()); -bool renderer::end_frame(VkCommandBuffers const& cmd_buffers) { + std::array<VkSemaphore, 1> const wait_semaphores = { image_acquired_semaphores[current_sync] }; + std::array<VkSemaphore, 1> const sync_present_semaphores = { render_complete_semaphores[current_sync] }; - assert(!cmd_buffers.empty()); + VkPipelineStageFlags const wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - std::array<VkSemaphore, 1> const wait_semaphores = { image_acquired_semaphores[current_sync] }; - std::array<VkSemaphore, 1> const sync_present_semaphores = { render_complete_semaphores[current_sync] }; + VkSubmitInfo const submit_info{ + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .waitSemaphoreCount = to_ui32(wait_semaphores.size()), + .pWaitSemaphores = wait_semaphores.data(), + .pWaitDstStageMask = &wait_stage, + .commandBufferCount = to_ui32(cmd_buffers.size()), + .pCommandBuffers = cmd_buffers.data(), + .signalSemaphoreCount = to_ui32(sync_present_semaphores.size()), + .pSignalSemaphores = sync_present_semaphores.data(), + }; - VkPipelineStageFlags const wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + std::array<VkSubmitInfo, 1> const submit_infos = { submit_info }; + VkFence current_fence = fences[current_sync]; - VkSubmitInfo const submit_info - { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .waitSemaphoreCount = to_ui32(wait_semaphores.size()), - .pWaitSemaphores = wait_semaphores.data(), - .pWaitDstStageMask = &wait_stage, - .commandBufferCount = to_ui32(cmd_buffers.size()), - .pCommandBuffers = cmd_buffers.data(), - .signalSemaphoreCount = to_ui32(sync_present_semaphores.size()), - .pSignalSemaphores = sync_present_semaphores.data(), - }; + if (!device->vkQueueSubmit(queue.vk_queue, to_ui32(submit_infos.size()), submit_infos.data(), current_fence)) + return false; - std::array<VkSubmitInfo, 1> const submit_infos = { submit_info }; - VkFence current_fence = fences[current_sync]; + std::array<VkSwapchainKHR, 1> const swapchains = { target->get() }; + std::array<ui32, 1> const indices = { frame_index }; - if (!device->vkQueueSubmit(queue.vk_queue, to_ui32(submit_infos.size()), submit_infos.data(), current_fence)) - return false; + VkPresentInfoKHR const present_info{ + .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, + .waitSemaphoreCount = to_ui32(sync_present_semaphores.size()), + .pWaitSemaphores = sync_present_semaphores.data(), + .swapchainCount = to_ui32(swapchains.size()), + .pSwapchains = swapchains.data(), + .pImageIndices = indices.data(), + }; - std::array<VkSwapchainKHR, 1> const swapchains = { target->get() }; - std::array<ui32, 1> const indices = { frame_index }; + auto result = device->vkQueuePresentKHR(queue.vk_queue, &present_info); + if (result.value == VK_ERROR_OUT_OF_DATE_KHR) { + target->request_reload(); + return true; + } - VkPresentInfoKHR const present_info - { - .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, - .waitSemaphoreCount = to_ui32(sync_present_semaphores.size()), - .pWaitSemaphores = sync_present_semaphores.data(), - .swapchainCount = to_ui32(swapchains.size()), - .pSwapchains = swapchains.data(), - .pImageIndices = indices.data(), - }; + if (!result) + return false; - auto result = device->vkQueuePresentKHR(queue.vk_queue, &present_info); - if (result.value == VK_ERROR_OUT_OF_DATE_KHR) { + current_sync = (current_sync + 1) % queued_frames; - target->request_reload(); return true; } - if (!result) - return false; - - current_sync = (current_sync + 1) % queued_frames; - - return true; -} - -} // lava +} // namespace lava diff --git a/liblava/frame/renderer.hpp b/liblava/frame/renderer.hpp index 1ee825b4adf547ff93c890b94b7a7bd3d16cdb36..e5461b05c3c7acb22f4e0173d792e89c33b1cb4d 100644 --- a/liblava/frame/renderer.hpp +++ b/liblava/frame/renderer.hpp @@ -5,48 +5,47 @@ #pragma once #include <liblava/frame/swapchain.hpp> - #include <optional> namespace lava { -struct renderer : id_obj { - - bool create(swapchain* target); - void destroy(); - - std::optional<index> begin_frame(); - bool end_frame(VkCommandBuffers const& cmd_buffers); + struct renderer : id_obj { + bool create(swapchain* target); + void destroy(); - bool frame(VkCommandBuffers const& cmd_buffers) { + std::optional<index> begin_frame(); + bool end_frame(VkCommandBuffers const& cmd_buffers); - if (!begin_frame()) - return false; + bool frame(VkCommandBuffers const& cmd_buffers) { + if (!begin_frame()) + return false; - return end_frame(cmd_buffers); - } + return end_frame(cmd_buffers); + } - index get_frame() const { return frame_index; } + index get_frame() const { + return frame_index; + } - using destroy_func = std::function<void()>; - destroy_func on_destroy; + using destroy_func = std::function<void()>; + destroy_func on_destroy; - bool active = true; + bool active = true; -private: - device_ptr device = nullptr; - device::queue queue; + private: + device_ptr device = nullptr; + device::queue queue; - swapchain* target = nullptr; + swapchain* target = nullptr; - index frame_index = 0; - ui32 queued_frames = 2; + index frame_index = 0; + ui32 queued_frames = 2; - ui32 current_sync = 0; - VkFences fences = {}; - VkFences fences_in_use = {}; - VkSemaphores image_acquired_semaphores = {}; - VkSemaphores render_complete_semaphores = {}; -}; + ui32 current_sync = 0; + VkFences fences = {}; + VkFences fences_in_use = {}; + VkSemaphores image_acquired_semaphores = {}; + VkSemaphores render_complete_semaphores = {}; + }; -} // lava +} // namespace lava diff --git a/liblava/frame/swapchain.cpp b/liblava/frame/swapchain.cpp index 18421939cb4e5ef1f6210edc8d4bcf8d7e43ea6b..0d6009ed3bbdaedd9d9918a0408ef373675cd7c3 100644 --- a/liblava/frame/swapchain.cpp +++ b/liblava/frame/swapchain.cpp @@ -2,247 +2,223 @@ // copyright : Copyright (c) 2018-present, Lava Block OÜ // license : MIT; see accompanying LICENSE file -#include <liblava/frame/swapchain.hpp> #include <liblava/base/instance.hpp> +#include <liblava/frame/swapchain.hpp> namespace lava { -bool swapchain::create(device_ptr d, VkSurfaceKHR s, uv2 sz, bool v) { - - device = d; - surface = s; - size = sz; - v_sync_active = v; - - set_surface_format(); - - return create_internal(); -} - -void swapchain::destroy() { - - device->wait_for_idle(); - - destroy_backbuffer_views(); - destroy_internal(); + bool swapchain::create(device_ptr d, VkSurfaceKHR s, uv2 sz, bool v) { + device = d; + surface = s; + size = sz; + v_sync_active = v; - vkDestroySurfaceKHR(instance::get(), surface, memory::alloc()); - surface = 0; -} + set_surface_format(); -bool swapchain::resize(uv2 new_size) { - - device->wait_for_idle(); - - if (!backbuffers.empty()) { + return create_internal(); + } - for (auto& callback : callbacks) - callback->on_destroyed(); + void swapchain::destroy() { + device->wait_for_idle(); destroy_backbuffer_views(); + destroy_internal(); + + vkDestroySurfaceKHR(instance::get(), surface, memory::alloc()); + surface = 0; } - size = new_size; - if (size.x == 0 || size.y == 0) - return true; + bool swapchain::resize(uv2 new_size) { + device->wait_for_idle(); + + if (!backbuffers.empty()) { + for (auto& callback : callbacks) + callback->on_destroyed(); - auto result = create_internal(); - assert(result); - if (!result) - return false; + destroy_backbuffer_views(); + } - for (auto& callback : reverse(callbacks)) { + size = new_size; + if (size.x == 0 || size.y == 0) + return true; - result = callback->on_created(); + auto result = create_internal(); assert(result); if (!result) return false; - } - - return true; -} -void swapchain::set_surface_format() { - - auto count = 0u; - check(vkGetPhysicalDeviceSurfaceFormatsKHR(device->get_vk_physical_device(), surface, &count, nullptr)); - - std::vector<VkSurfaceFormatKHR> formats(count); - check(vkGetPhysicalDeviceSurfaceFormatsKHR(device->get_vk_physical_device(), surface, &count, formats.data())); - - if (count == 1) { - - if (formats[0].format == VK_FORMAT_UNDEFINED) { - - format.format = VK_FORMAT_B8G8R8A8_UNORM; - format.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; - } - else { - - format = formats[0]; + for (auto& callback : reverse(callbacks)) { + result = callback->on_created(); + assert(result); + if (!result) + return false; } - } else { + return true; + } - VkFormat const requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, - VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM }; + void swapchain::set_surface_format() { + auto count = 0u; + check(vkGetPhysicalDeviceSurfaceFormatsKHR(device->get_vk_physical_device(), surface, &count, nullptr)); - VkColorSpaceKHR const requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; + std::vector<VkSurfaceFormatKHR> formats(count); + check(vkGetPhysicalDeviceSurfaceFormatsKHR(device->get_vk_physical_device(), surface, &count, formats.data())); - auto requestedFound = false; - for (auto& i : requestSurfaceImageFormat) { + if (count == 1) { + if (formats[0].format == VK_FORMAT_UNDEFINED) { + format.format = VK_FORMAT_B8G8R8A8_UNORM; + format.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; + } else { + format = formats[0]; + } - if (requestedFound) - break; + } else { + VkFormat const requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM }; - for (ui32 j = 0; j < count; j++) { + VkColorSpaceKHR const requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; - if (formats[j].format == i && - formats[j].colorSpace == requestSurfaceColorSpace) { + auto requestedFound = false; + for (auto& i : requestSurfaceImageFormat) { + if (requestedFound) + break; - format = formats[j]; - requestedFound = true; + for (ui32 j = 0; j < count; j++) { + if (formats[j].format == i && formats[j].colorSpace == requestSurfaceColorSpace) { + format = formats[j]; + requestedFound = true; + } } } - } - if (!requestedFound) - format = formats[0]; - } -} - -VkPresentModeKHR swapchain::choose_present_mode(VkPresentModeKHRs const& present_modes) const { - - if (v_sync()) - return VK_PRESENT_MODE_FIFO_KHR; - - if (std::find(present_modes.begin(), present_modes.end(), VK_PRESENT_MODE_MAILBOX_KHR) != present_modes.end()) - return VK_PRESENT_MODE_MAILBOX_KHR; - - if (std::find(present_modes.begin(), present_modes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR) != present_modes.end()) - return VK_PRESENT_MODE_IMMEDIATE_KHR; - - return VK_PRESENT_MODE_FIFO_KHR; -} - -bool swapchain::create_internal() { - - auto present_mode_count = 0u; - if (vkGetPhysicalDeviceSurfacePresentModesKHR(device->get_vk_physical_device(), surface, &present_mode_count, nullptr) != VK_SUCCESS || present_mode_count == 0) { - - log()->error("create swapchain present mode count"); - return false; + if (!requestedFound) + format = formats[0]; + } } - VkPresentModeKHRs present_modes(present_mode_count); - if (vkGetPhysicalDeviceSurfacePresentModesKHR(device->get_vk_physical_device(), surface, &present_mode_count, present_modes.data()) != VK_SUCCESS) { + VkPresentModeKHR swapchain::choose_present_mode(VkPresentModeKHRs const& present_modes) const { + if (v_sync()) + return VK_PRESENT_MODE_FIFO_KHR; - log()->error("create swapchain present mode"); - return false; - } + if (std::find(present_modes.begin(), present_modes.end(), VK_PRESENT_MODE_MAILBOX_KHR) != present_modes.end()) + return VK_PRESENT_MODE_MAILBOX_KHR; - VkPresentModeKHR present_mode = choose_present_mode(present_modes); - - VkSwapchainKHR old_swapchain = vk_swapchain; - - VkSwapchainCreateInfoKHR info - { - .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, - .surface = surface, - .minImageCount = 0, - .imageFormat = format.format, - .imageColorSpace = format.colorSpace, - .imageExtent = {}, - .imageArrayLayers = 1, - .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, - .queueFamilyIndexCount = 0, - .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, - .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, - .presentMode = present_mode, - .clipped = VK_TRUE, - .oldSwapchain = old_swapchain, - }; - - VkSurfaceCapabilitiesKHR cap{}; - check(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->get_vk_physical_device(), surface, &cap)); - - if (cap.maxImageCount > 0) - info.minImageCount = (cap.minImageCount + 2 < cap.maxImageCount) ? (cap.minImageCount + 2) : cap.maxImageCount; - else - info.minImageCount = cap.minImageCount + 2; - - if (cap.currentExtent.width == 0xffffffff) { - - info.imageExtent.width = size.x; - info.imageExtent.height = size.y; - } - else { + if (std::find(present_modes.begin(), present_modes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR) != present_modes.end()) + return VK_PRESENT_MODE_IMMEDIATE_KHR; - size.x = cap.currentExtent.width; - size.y = cap.currentExtent.height; - info.imageExtent.width = size.x; - info.imageExtent.height = size.y; + return VK_PRESENT_MODE_FIFO_KHR; } - info.preTransform = cap.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : cap.currentTransform; - - if (!device->vkCreateSwapchainKHR(&info, &vk_swapchain)) - return false; - - auto backbuffer_count = 0u; - if (!device->vkGetSwapchainImagesKHR(vk_swapchain, &backbuffer_count, nullptr)) - return false; + bool swapchain::create_internal() { + auto present_mode_count = 0u; + if (vkGetPhysicalDeviceSurfacePresentModesKHR(device->get_vk_physical_device(), surface, &present_mode_count, nullptr) != VK_SUCCESS || present_mode_count == 0) { + log()->error("create swapchain present mode count"); + return false; + } - VkImages images(backbuffer_count); - if (!device->vkGetSwapchainImagesKHR(vk_swapchain, &backbuffer_count, images.data())) - return false; + VkPresentModeKHRs present_modes(present_mode_count); + if (vkGetPhysicalDeviceSurfacePresentModesKHR(device->get_vk_physical_device(), surface, &present_mode_count, present_modes.data()) != VK_SUCCESS) { + log()->error("create swapchain present mode"); + return false; + } - for (auto& image : images) { + VkPresentModeKHR present_mode = choose_present_mode(present_modes); + + VkSwapchainKHR old_swapchain = vk_swapchain; + + VkSwapchainCreateInfoKHR info{ + .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, + .surface = surface, + .minImageCount = 0, + .imageFormat = format.format, + .imageColorSpace = format.colorSpace, + .imageExtent = {}, + .imageArrayLayers = 1, + .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, + .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 0, + .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, + .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + .presentMode = present_mode, + .clipped = VK_TRUE, + .oldSwapchain = old_swapchain, + }; + + VkSurfaceCapabilitiesKHR cap{}; + check(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->get_vk_physical_device(), surface, &cap)); + + if (cap.maxImageCount > 0) + info.minImageCount = (cap.minImageCount + 2 < cap.maxImageCount) ? (cap.minImageCount + 2) : cap.maxImageCount; + else + info.minImageCount = cap.minImageCount + 2; + + if (cap.currentExtent.width == 0xffffffff) { + info.imageExtent.width = size.x; + info.imageExtent.height = size.y; + } else { + size.x = cap.currentExtent.width; + size.y = cap.currentExtent.height; + info.imageExtent.width = size.x; + info.imageExtent.height = size.y; + } - auto backbuffer = make_image(format.format, image); - if (!backbuffer) { + info.preTransform = cap.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : cap.currentTransform; - log()->error("create swapchain backbuffer image"); + if (!device->vkCreateSwapchainKHR(&info, &vk_swapchain)) return false; - } - if (!backbuffer->create(device, size)) { + auto backbuffer_count = 0u; + if (!device->vkGetSwapchainImagesKHR(vk_swapchain, &backbuffer_count, nullptr)) + return false; - log()->error("create swapchain backBuffer"); + VkImages images(backbuffer_count); + if (!device->vkGetSwapchainImagesKHR(vk_swapchain, &backbuffer_count, images.data())) return false; - } - backbuffers.push_back(backbuffer); - } + for (auto& image : images) { + auto backbuffer = make_image(format.format, image); + if (!backbuffer) { + log()->error("create swapchain backbuffer image"); + return false; + } - if (old_swapchain) - device->vkDestroySwapchainKHR(old_swapchain); + if (!backbuffer->create(device, size)) { + log()->error("create swapchain backBuffer"); + return false; + } - reload_request_active = false; + backbuffers.push_back(backbuffer); + } - return true; -} + if (old_swapchain) + device->vkDestroySwapchainKHR(old_swapchain); -void swapchain::destroy_internal() { + reload_request_active = false; - if (!vk_swapchain) - return; + return true; + } - device->vkDestroySwapchainKHR(vk_swapchain); - vk_swapchain = 0; -} + void swapchain::destroy_internal() { + if (!vk_swapchain) + return; -void swapchain::destroy_backbuffer_views() { + device->vkDestroySwapchainKHR(vk_swapchain); + vk_swapchain = 0; + } - for (auto& backBuffer : backbuffers) - backBuffer->destroy_view(); + void swapchain::destroy_backbuffer_views() { + for (auto& backBuffer : backbuffers) + backBuffer->destroy_view(); - backbuffers.clear(); -} + backbuffers.clear(); + } -void swapchain::add_callback(callback* cb) { callbacks.push_back(cb); } + void swapchain::add_callback(callback* cb) { + callbacks.push_back(cb); + } -void swapchain::remove_callback(callback* cb) { remove(callbacks, cb); } + void swapchain::remove_callback(callback* cb) { + remove(callbacks, cb); + } -} // lava +} // namespace lava diff --git a/liblava/frame/swapchain.hpp b/liblava/frame/swapchain.hpp index cf633db34fbb4a45992c865e10f127603e3a0ca6..387556aee5a6eb25b1c525c2ed59e4453a226387 100644 --- a/liblava/frame/swapchain.hpp +++ b/liblava/frame/swapchain.hpp @@ -8,65 +8,81 @@ namespace lava { -struct swapchain : id_obj { + struct swapchain : id_obj { + bool create(device_ptr device, VkSurfaceKHR surface, uv2 size, bool v_sync = false); - bool create(device_ptr device, VkSurfaceKHR surface, uv2 size, bool v_sync = false); + void destroy(); - void destroy(); + bool resize(uv2 new_size); - bool resize(uv2 new_size); + void request_reload() { + reload_request_active = true; + } + bool reload_request() const { + return reload_request_active; + } - void request_reload() { reload_request_active = true; } - bool reload_request() const { return reload_request_active; } + device_ptr get_device() { + return device; + } - device_ptr get_device() { return device; } + uv2 get_size() const { + return size; + } + VkFormat get_format() const { + return format.format; + } - uv2 get_size() const { return size; } - VkFormat get_format() const { return format.format; } + VkSwapchainKHR get() const { + return vk_swapchain; + } - VkSwapchainKHR get() const { return vk_swapchain; } + ui32 get_backbuffer_count() const { + return to_ui32(backbuffers.size()); + } + image::list const& get_backbuffers() const { + return backbuffers; + } - ui32 get_backbuffer_count() const { return to_ui32(backbuffers.size()); } - image::list const& get_backbuffers() const { return backbuffers; } + struct callback { + using list = std::vector<callback*>; - struct callback { + using created_func = std::function<bool()>; + created_func on_created; - using list = std::vector<callback*>; + using destroyed_func = std::function<void()>; + destroyed_func on_destroyed; + }; - using created_func = std::function<bool()>; - created_func on_created; + void add_callback(callback* cb); + void remove_callback(callback* cb); - using destroyed_func = std::function<void()>; - destroyed_func on_destroyed; - }; - - void add_callback(callback* cb); - void remove_callback(callback* cb); + bool v_sync() const { + return v_sync_active; + } - bool v_sync() const { return v_sync_active; } + private: + void set_surface_format(); -private: - void set_surface_format(); + VkPresentModeKHR choose_present_mode(VkPresentModeKHRs const& present_modes) const; - VkPresentModeKHR choose_present_mode(VkPresentModeKHRs const& present_modes) const; + bool create_internal(); + void destroy_internal(); + void destroy_backbuffer_views(); - bool create_internal(); - void destroy_internal(); - void destroy_backbuffer_views(); + device_ptr device = nullptr; - device_ptr device = nullptr; + VkSurfaceKHR surface = 0; + VkSurfaceFormatKHR format = {}; + VkSwapchainKHR vk_swapchain = 0; - VkSurfaceKHR surface = 0; - VkSurfaceFormatKHR format = {}; - VkSwapchainKHR vk_swapchain = 0; + image::list backbuffers; - image::list backbuffers; + uv2 size; + bool reload_request_active = false; + bool v_sync_active = false; - uv2 size; - bool reload_request_active = false; - bool v_sync_active = false; - - callback::list callbacks; -}; + callback::list callbacks; + }; -} // lava +} // namespace lava diff --git a/liblava/frame/window.cpp b/liblava/frame/window.cpp index 15ef610248e2f333f0261d05eb9212d158ba4d3a..42cff3dc79eabbe9263c8a05bd583a3c4c29ae45 100644 --- a/liblava/frame/window.cpp +++ b/liblava/frame/window.cpp @@ -2,10 +2,9 @@ // copyright : Copyright (c) 2018-present, Lava Block OÜ // license : MIT; see accompanying LICENSE file -#include <liblava/frame/window.hpp> - -#include <liblava/base/instance.hpp> #include <liblava/base/device.hpp> +#include <liblava/base/instance.hpp> +#include <liblava/frame/window.hpp> #define GLFW_INCLUDE_NONE #define GLFW_INCLUDE_VULKAN @@ -13,409 +12,426 @@ namespace lava { -bool window::create(state::optional state) { - - auto monitor = glfwGetPrimaryMonitor(); - auto mode = glfwGetVideoMode(monitor); - - string default_title = title; - if (debug_title_active) - default_title = fmt::format("%s [%s]", str(title), str(save_name)); - - if (state) { - - fullscreen_active = state->fullscreen; + bool window::create(state::optional state) { + auto monitor = glfwGetPrimaryMonitor(); + auto mode = glfwGetVideoMode(monitor); - if (state->monitor != 0) { + string default_title = title; + if (debug_title_active) + default_title = fmt::format("%s [%s]", str(title), str(save_name)); - auto monitor_count = 0; - auto monitors = glfwGetMonitors(&monitor_count); + if (state) { + fullscreen_active = state->fullscreen; - if (state->monitor < monitor_count) { + if (state->monitor != 0) { + auto monitor_count = 0; + auto monitors = glfwGetMonitors(&monitor_count); - monitor = monitors[state->monitor]; - mode = glfwGetVideoMode(monitor); + if (state->monitor < monitor_count) { + monitor = monitors[state->monitor]; + mode = glfwGetVideoMode(monitor); + } } - } - - if (state->fullscreen) { - - handle = glfwCreateWindow(mode->width, mode->height, str(default_title), monitor, nullptr); - if (!handle) { - log()->error("create fullscreen window (state)"); - return false; + if (state->fullscreen) { + handle = glfwCreateWindow(mode->width, mode->height, str(default_title), monitor, nullptr); + if (!handle) { + log()->error("create fullscreen window (state)"); + return false; + } + } else { + handle = glfwCreateWindow(state->width, state->height, str(default_title), nullptr, nullptr); + if (!handle) { + log()->error("create window (state)"); + return false; + } + + glfwSetWindowPos(handle, state->x, state->y); } - } - else { - - handle = glfwCreateWindow(state->width, state->height, str(default_title), nullptr, nullptr); - if (!handle) { - log()->error("create window (state)"); - return false; + pos_x = state->x; + pos_y = state->y; + width = state->width; + height = state->height; + + set_floating(state->floating); + set_resizable(state->resizable); + set_decorated(state->decorated); + + if (state->maximized) + maximize(); + } else { + pos_x = mode->width / 4; + pos_y = mode->height / 4; + width = mode->width / 2; + height = mode->height / 2; + + if (fullscreen_active) { + handle = glfwCreateWindow(mode->width, mode->height, str(default_title), monitor, nullptr); + if (!handle) { + log()->error("create fullscreen window"); + return false; + } + } else { + handle = glfwCreateWindow(width, height, str(default_title), nullptr, nullptr); + if (!handle) { + log()->error("create window"); + return false; + } + + glfwSetWindowPos(handle, pos_x, pos_y); } - - glfwSetWindowPos(handle, state->x, state->y); } - pos_x = state->x; - pos_y = state->y; - width = state->width; - height = state->height; - - set_floating(state->floating); - set_resizable(state->resizable); - set_decorated(state->decorated); + switch_mode_request_active = false; + handle_message(); - if (state->maximized) - maximize(); - } - else { - - pos_x = mode->width / 4; - pos_y = mode->height / 4; - width = mode->width / 2; - height = mode->height / 2; + return true; + } - if (fullscreen_active) { + void window::destroy() { + input = nullptr; - handle = glfwCreateWindow(mode->width, mode->height, str(default_title), monitor, nullptr); - if (!handle) { + glfwDestroyWindow(handle); + handle = nullptr; + } - log()->error("create fullscreen window"); - return false; - } + window::state window::get_state() const { + window::state state; + + if (fullscreen() || iconified() || maximized()) { + state.x = pos_x; + state.y = pos_y; + state.width = width; + state.height = height; + } else { + get_position(state.x, state.y); + get_size(state.width, state.height); } - else { - handle = glfwCreateWindow(width, height, str(default_title), nullptr, nullptr); - if (!handle) { + state.fullscreen = fullscreen(); + state.floating = floating(); + state.resizable = resizable(); + state.decorated = decorated(); + state.maximized = maximized(); - log()->error("create window"); - return false; - } + state.monitor = get_monitor(); - glfwSetWindowPos(handle, pos_x, pos_y); - } + return state; } - switch_mode_request_active = false; - handle_message(); - - return true; -} - -void window::destroy() { - - input = nullptr; + void window::set_title(name text) { + title = text; - glfwDestroyWindow(handle); - handle = nullptr; -} - -window::state window::get_state() const { + if (!handle) + return; - window::state state; + if (debug_title_active) + glfwSetWindowTitle(handle, str(fmt::format("%s [%s]", str(title), str(save_name)))); + else + glfwSetWindowTitle(handle, str(title)); + } - if (fullscreen() || iconified() || maximized()) { + bool window::switch_mode(state::optional state) { + destroy(); - state.x = pos_x; - state.y = pos_y; - state.width = width; - state.height = height; + return create(state); } - else { - get_position(state.x, state.y); - get_size(state.width, state.height); + void window::handle_message() { + glfwSetWindowUserPointer(handle, this); + + glfwSetFramebufferSizeCallback(handle, [](GLFWwindow* handle, i32 w, i32 h) { + auto window = get_window(handle); + if (!window) + return; + + window->framebuffer_width = to_ui32(w); + window->framebuffer_height = to_ui32(h); + window->resize_request_active = true; + + if (!window->fullscreen() && !window->iconified() && !window->maximized()) + window->update_state(); + }); + + glfwSetKeyCallback(handle, [](GLFWwindow* handle, i32 key, i32 scancode, i32 action, i32 mods) { + auto window = get_window(handle); + if (!window) + return; + + window->input->key.add({ window->get_id(), lava::key(key), lava::action(action), lava::mod(mods), scancode }); + }); + + glfwSetScrollCallback(handle, [](GLFWwindow* handle, r64 x_offset, r64 y_offset) { + auto window = get_window(handle); + if (!window) + return; + + if (window->input) + window->input->scroll.add({ window->get_id(), x_offset, y_offset }); + }); + + glfwSetMouseButtonCallback(handle, [](GLFWwindow* handle, i32 button, i32 action, i32 mods) { + auto window = get_window(handle); + if (!window) + return; + + if (window->input) + window->input->mouse_button.add({ window->get_id(), mouse_button(button), lava::action(action), lava::mod(mods) }); + }); + + glfwSetCursorPosCallback(handle, [](GLFWwindow* handle, r64 x_position, r64 y_position) { + auto window = get_window(handle); + if (!window) + return; + + if (window->input) + window->input->mouse_move.add({ window->get_id(), { x_position, y_position } }); + }); + + glfwSetCursorEnterCallback(handle, [](GLFWwindow* handle, i32 entered) { + auto window = get_window(handle); + if (!window) + return; + + if (window->input) + window->input->mouse_active.add({ window->get_id(), entered > 0 }); + }); + + glfwSetDropCallback(handle, [](GLFWwindow* handle, i32 amt, const char** paths) { + auto window = get_window(handle); + if (!window) + return; + + if (window->input) + window->input->path_drop.add({ window->get_id(), { paths, paths + amt } }); + }); } - - state.fullscreen = fullscreen(); - state.floating = floating(); - state.resizable = resizable(); - state.decorated = decorated(); - state.maximized = maximized(); - - state.monitor = get_monitor(); - - return state; -} - -void window::set_title(name text) { - - title = text; - - if (!handle) - return; - - if (debug_title_active) - glfwSetWindowTitle(handle, str(fmt::format("%s [%s]", str(title), str(save_name)))); - else - glfwSetWindowTitle(handle, str(title)); -} - -bool window::switch_mode(state::optional state) { - - destroy(); - - return create(state); -} - -void window::handle_message() { - - glfwSetWindowUserPointer(handle, this); - - glfwSetFramebufferSizeCallback(handle, [](GLFWwindow* handle, i32 w, i32 h) { - - auto window = get_window(handle); - if (!window) - return; - - window->framebuffer_width = to_ui32(w); - window->framebuffer_height = to_ui32(h); - window->resize_request_active = true; - - if (!window->fullscreen() && !window->iconified() && !window->maximized()) - window->update_state(); - }); - - glfwSetKeyCallback(handle, [](GLFWwindow* handle, i32 key, i32 scancode, i32 action, i32 mods) { - - auto window = get_window(handle); - if (!window) - return; - - window->input->key.add({ window->get_id(), lava::key(key), lava::action(action), lava::mod(mods), scancode }); - }); - - glfwSetScrollCallback(handle, [](GLFWwindow* handle, r64 x_offset, r64 y_offset) { - - auto window = get_window(handle); - if (!window) - return; - - if (window->input) - window->input->scroll.add({ window->get_id(), x_offset, y_offset }); - }); - - glfwSetMouseButtonCallback(handle, [](GLFWwindow* handle, i32 button, i32 action, i32 mods) { - - auto window = get_window(handle); - if (!window) - return; - - if (window->input) - window->input->mouse_button.add({ window->get_id(), mouse_button(button), lava::action(action), lava::mod(mods) }); - }); - - glfwSetCursorPosCallback(handle, [](GLFWwindow* handle, r64 x_position, r64 y_position) { - - auto window = get_window(handle); - if (!window) - return; - - if (window->input) - window->input->mouse_move.add({ window->get_id(), { x_position, y_position } }); - }); - - glfwSetCursorEnterCallback(handle, [](GLFWwindow* handle, i32 entered) { - - auto window = get_window(handle); - if (!window) - return; - - if (window->input) - window->input->mouse_active.add({ window->get_id(), entered > 0 }); - }); - - glfwSetDropCallback(handle, [](GLFWwindow* handle, i32 amt, const char** paths) { - - auto window = get_window(handle); - if (!window) - return; - - if (window->input) - window->input->path_drop.add({ window->get_id(), { paths, paths + amt } }); - }); -} - -template <int attr> -static int attribute_set(GLFWwindow* handle) { return glfwGetWindowAttrib(handle, attr); } - -template <int attr> -static bool bool_attribute_set(GLFWwindow* handle) { return attribute_set<attr>(handle) == 1; } -void window::set_position(i32 x, i32 y) { glfwSetWindowPos(handle, x, y); } - -void window::get_position(i32& x, i32& y) const { glfwGetWindowPos(handle, &x, &y); } - -void window::set_size(ui32 w, ui32 h) { glfwSetWindowSize(handle, w, h); } - -void window::get_size(ui32& w, ui32& h) const { glfwGetWindowSize(handle, (i32*)&w, (i32*)&h); } + template<int attr> + static int attribute_set(GLFWwindow* handle) { + return glfwGetWindowAttrib(handle, attr); + } -void window::get_framebuffer_size(ui32& w, ui32& h) const { glfwGetFramebufferSize(handle, (i32*)&w, (i32*)&h); } + template<int attr> + static bool bool_attribute_set(GLFWwindow* handle) { + return attribute_set<attr>(handle) == 1; + } -void window::set_mouse_position(r64 x, r64 y) { glfwSetCursorPos(handle, x, y); } + void window::set_position(i32 x, i32 y) { + glfwSetWindowPos(handle, x, y); + } -void window::get_mouse_position(r64& x, r64& y) const { glfwGetCursorPos(handle, &x, &y); } + void window::get_position(i32& x, i32& y) const { + glfwGetWindowPos(handle, &x, &y); + } -mouse_position window::get_mouse_position() const { + void window::set_size(ui32 w, ui32 h) { + glfwSetWindowSize(handle, w, h); + } - mouse_position result; - get_mouse_position(result.x, result.y); + void window::get_size(ui32& w, ui32& h) const { + glfwGetWindowSize(handle, (i32*) &w, (i32*) &h); + } - return result; -} + void window::get_framebuffer_size(ui32& w, ui32& h) const { + glfwGetFramebufferSize(handle, (i32*) &w, (i32*) &h); + } -void window::hide_mouse_cursor() { glfwSetInputMode(handle, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); } + void window::set_mouse_position(r64 x, r64 y) { + glfwSetCursorPos(handle, x, y); + } -void window::show_mouse_cursor() { glfwSetInputMode(handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL); } + void window::get_mouse_position(r64& x, r64& y) const { + glfwGetCursorPos(handle, &x, &y); + } -float window::get_aspect_ratio() const { return framebuffer_height != 0 ? - to_r32(framebuffer_width) / to_r32(framebuffer_height) : 0.f; } + mouse_position window::get_mouse_position() const { + mouse_position result; + get_mouse_position(result.x, result.y); -void window::show() { glfwShowWindow(handle); } + return result; + } -void window::hide() { glfwHideWindow(handle); } + void window::hide_mouse_cursor() { + glfwSetInputMode(handle, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + } -bool window::visible() const { return bool_attribute_set<GLFW_VISIBLE>(handle); } + void window::show_mouse_cursor() { + glfwSetInputMode(handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + } -void window::iconify() { glfwIconifyWindow(handle); } + float window::get_aspect_ratio() const { + return framebuffer_height != 0 ? to_r32(framebuffer_width) / to_r32(framebuffer_height) : 0.f; + } -bool window::iconified() const { return bool_attribute_set<GLFW_ICONIFIED>(handle); } + void window::show() { + glfwShowWindow(handle); + } -void window::restore() { glfwRestoreWindow(handle); } + void window::hide() { + glfwHideWindow(handle); + } -void window::maximize() { glfwMaximizeWindow(handle); } + bool window::visible() const { + return bool_attribute_set<GLFW_VISIBLE>(handle); + } -bool window::maximized() const { return bool_attribute_set<GLFW_MAXIMIZED>(handle); } + void window::iconify() { + glfwIconifyWindow(handle); + } -void window::focus() { glfwFocusWindow(handle); } + bool window::iconified() const { + return bool_attribute_set<GLFW_ICONIFIED>(handle); + } -bool window::focused() const { return bool_attribute_set<GLFW_FOCUSED>(handle); } + void window::restore() { + glfwRestoreWindow(handle); + } -bool window::hovered() const { return bool_attribute_set<GLFW_HOVERED>(handle); } + void window::maximize() { + glfwMaximizeWindow(handle); + } -bool window::resizable() const { return bool_attribute_set<GLFW_RESIZABLE>(handle); } + bool window::maximized() const { + return bool_attribute_set<GLFW_MAXIMIZED>(handle); + } -void window::set_resizable(bool value) { glfwSetWindowAttrib(handle, GLFW_RESIZABLE, value); } + void window::focus() { + glfwFocusWindow(handle); + } -bool window::decorated() const { return bool_attribute_set<GLFW_DECORATED>(handle); } + bool window::focused() const { + return bool_attribute_set<GLFW_FOCUSED>(handle); + } -void window::set_decorated(bool value) { glfwSetWindowAttrib(handle, GLFW_DECORATED, value); } + bool window::hovered() const { + return bool_attribute_set<GLFW_HOVERED>(handle); + } -bool window::floating() const { return bool_attribute_set<GLFW_FLOATING>(handle); } + bool window::resizable() const { + return bool_attribute_set<GLFW_RESIZABLE>(handle); + } -void window::set_floating(bool value) { glfwSetWindowAttrib(handle, GLFW_FLOATING, value); } + void window::set_resizable(bool value) { + glfwSetWindowAttrib(handle, GLFW_RESIZABLE, value); + } -window* window::get_window(GLFWwindow* handle) { return static_cast<window*>(glfwGetWindowUserPointer(handle)); } + bool window::decorated() const { + return bool_attribute_set<GLFW_DECORATED>(handle); + } -bool window::close_request() const { return glfwWindowShouldClose(handle) == 1; } + void window::set_decorated(bool value) { + glfwSetWindowAttrib(handle, GLFW_DECORATED, value); + } -VkSurfaceKHR window::create_surface() { return lava::create_surface(handle); } + bool window::floating() const { + return bool_attribute_set<GLFW_FLOATING>(handle); + } -void window::set_icon(data_ptr data, uv2 size) { + void window::set_floating(bool value) { + glfwSetWindowAttrib(handle, GLFW_FLOATING, value); + } - GLFWimage images[1]; - images[0].width = size.x; - images[0].height = size.y; - images[0].pixels = (uc8*)data; + window* window::get_window(GLFWwindow* handle) { + return static_cast<window*>(glfwGetWindowUserPointer(handle)); + } - glfwSetWindowIcon(handle, 1, images); -} + bool window::close_request() const { + return glfwWindowShouldClose(handle) == 1; + } -index window::get_monitor() const { + VkSurfaceKHR window::create_surface() { + return lava::create_surface(handle); + } - auto window_x = 0; - auto window_y = 0; - glfwGetWindowPos(handle, &window_x, &window_y); + void window::set_icon(data_ptr data, uv2 size) { + GLFWimage images[1]; + images[0].width = size.x; + images[0].height = size.y; + images[0].pixels = (uc8*) data; - auto window_width = 0; - auto window_height = 0; - glfwGetWindowSize(handle, &window_width, &window_height); + glfwSetWindowIcon(handle, 1, images); + } - auto monitor_count = 0; - auto monitors = glfwGetMonitors(&monitor_count); + index window::get_monitor() const { + auto window_x = 0; + auto window_y = 0; + glfwGetWindowPos(handle, &window_x, &window_y); - index result = 0; + auto window_width = 0; + auto window_height = 0; + glfwGetWindowSize(handle, &window_width, &window_height); - auto overlap = 0; - auto best_overlap = 0; + auto monitor_count = 0; + auto monitors = glfwGetMonitors(&monitor_count); - for (auto i = 0u; i < monitor_count; ++i) { + index result = 0; - auto monitor_x = 0; - auto monitor_y = 0; - glfwGetMonitorPos(monitors[i], &monitor_x, &monitor_y); + auto overlap = 0; + auto best_overlap = 0; - auto mode = glfwGetVideoMode(monitors[i]); - auto monitor_width = mode->width; - auto monitor_height = mode->height; + for (auto i = 0u; i < monitor_count; ++i) { + auto monitor_x = 0; + auto monitor_y = 0; + glfwGetMonitorPos(monitors[i], &monitor_x, &monitor_y); - overlap = std::max(0, std::min(window_x + window_width, monitor_x + monitor_width) - - std::max(window_x, monitor_x)) * - std::max(0, std::min(window_y + window_height, monitor_y + monitor_height) - - std::max(window_y, monitor_y)); + auto mode = glfwGetVideoMode(monitors[i]); + auto monitor_width = mode->width; + auto monitor_height = mode->height; - if (best_overlap < overlap) { + overlap = std::max(0, std::min(window_x + window_width, monitor_x + monitor_width) - std::max(window_x, monitor_x)) * std::max(0, std::min(window_y + window_height, monitor_y + monitor_height) - std::max(window_y, monitor_y)); - best_overlap = overlap; - result = i; + if (best_overlap < overlap) { + best_overlap = overlap; + result = i; + } } - } - - return result; -} -void window::center() { - - auto monitor = glfwGetPrimaryMonitor(); - auto mode = glfwGetVideoMode(monitor); + return result; + } - glfwSetWindowPos(handle, (mode->width - width) / 2, (mode->height - height) / 2); -} + void window::center() { + auto monitor = glfwGetPrimaryMonitor(); + auto mode = glfwGetVideoMode(monitor); -void to_json(json& j, window::state const& w) { + glfwSetWindowPos(handle, (mode->width - width) / 2, (mode->height - height) / 2); + } - j = json{ { _x_, w.x }, { _y_, w.y }, { _width_, w.width }, { _height_, w.height }, - { _fullscreen_, w.fullscreen }, { _floating_, w.floating }, { _resizable_, w.resizable }, - { _decorated_, w.decorated }, { _maximized_, w.maximized }, { _monitor_, w.monitor } }; -} + void to_json(json& j, window::state const& w) { + j = json{ { _x_, w.x }, { _y_, w.y }, { _width_, w.width }, { _height_, w.height }, { _fullscreen_, w.fullscreen }, { _floating_, w.floating }, { _resizable_, w.resizable }, { _decorated_, w.decorated }, { _maximized_, w.maximized }, { _monitor_, w.monitor } }; + } -void from_json(json const& j, window::state& w) { - - if (j.count(_x_)) - w.x = j.at(_x_).get<int>(); - if (j.count(_y_)) - w.y = j.at(_y_).get<int>(); - if (j.count(_width_)) - w.width = j.at(_width_).get<int>(); - if (j.count(_height_)) - w.height = j.at(_height_).get<int>(); - if (j.count(_fullscreen_)) - w.fullscreen = j.at(_fullscreen_).get<bool>(); - if (j.count(_floating_)) - w.floating = j.at(_floating_).get<bool>(); - if (j.count(_resizable_)) - w.resizable = j.at(_resizable_).get<bool>(); - if (j.count(_decorated_)) - w.decorated = j.at(_decorated_).get<bool>(); - if (j.count(_maximized_)) - w.maximized = j.at(_maximized_).get<bool>(); - if (j.count(_monitor_)) - w.monitor = j.at(_monitor_).get<int>(); -} + void from_json(json const& j, window::state& w) { + if (j.count(_x_)) + w.x = j.at(_x_).get<int>(); + if (j.count(_y_)) + w.y = j.at(_y_).get<int>(); + if (j.count(_width_)) + w.width = j.at(_width_).get<int>(); + if (j.count(_height_)) + w.height = j.at(_height_).get<int>(); + if (j.count(_fullscreen_)) + w.fullscreen = j.at(_fullscreen_).get<bool>(); + if (j.count(_floating_)) + w.floating = j.at(_floating_).get<bool>(); + if (j.count(_resizable_)) + w.resizable = j.at(_resizable_).get<bool>(); + if (j.count(_decorated_)) + w.decorated = j.at(_decorated_).get<bool>(); + if (j.count(_maximized_)) + w.maximized = j.at(_maximized_).get<bool>(); + if (j.count(_monitor_)) + w.monitor = j.at(_monitor_).get<int>(); + } -} // lava +} // namespace lava bool lava::window_file() { - return file_system::exists(_window_file_); } lava::window::state::optional lava::load_window_state(name save_name) { - if (!window_file()) return {}; @@ -427,7 +443,6 @@ lava::window::state::optional lava::load_window_state(name save_name) { } bool lava::load_window_file(window::state& state, name save_name) { - scope_data data; if (!load_file_data(_window_file_, data)) return false; @@ -444,7 +459,6 @@ bool lava::load_window_file(window::state& state, name save_name) { } void lava::save_window_file(window::ref window) { - window::state state = window.get_state(); auto index = window.get_save_name(); @@ -452,22 +466,18 @@ void lava::save_window_file(window::ref window) { scope_data data; if (load_file_data(_window_file_, data)) { - j = json::parse({ data.ptr, data.size }); json d; d[index] = state; j.merge_patch(d); - } - else { - + } else { j[index] = state; } file file(str(_window_file_), true); if (!file.opened()) { - log()->error("save window {}", str(j.dump())); return; } @@ -480,7 +490,6 @@ void lava::save_window_file(window::ref window) { } VkSurfaceKHR lava::create_surface(GLFWwindow* window) { - VkSurfaceKHR surface = 0; if (failed(glfwCreateWindowSurface(instance::get(), window, memory::alloc(), &surface))) return 0; diff --git a/liblava/frame/window.hpp b/liblava/frame/window.hpp index 4f5806538c6741d879a2c39dd67ca69dfec3173f..5f097e5322be9e799f9af7d215804a9b3e814bf3 100644 --- a/liblava/frame/window.hpp +++ b/liblava/frame/window.hpp @@ -4,13 +4,12 @@ #pragma once -#include <liblava/frame/input.hpp> #include <liblava/core/data.hpp> #include <liblava/core/math.hpp> +#include <liblava/frame/input.hpp> #define VK_NO_PROTOTYPES #include <vulkan/vulkan.h> - #include <optional> // fwd @@ -18,179 +17,201 @@ struct GLFWwindow; namespace lava { -constexpr name _default_ = "default"; - -constexpr name _window_file_ = "window.json"; -constexpr name _x_ = "x"; -constexpr name _y_ = "y"; -constexpr name _width_ = "width"; -constexpr name _height_ = "height"; -constexpr name _fullscreen_ = "fullscreen"; -constexpr name _floating_ = "floating"; -constexpr name _resizable_ = "resizable"; -constexpr name _decorated_ = "decorated"; -constexpr name _maximized_ = "maximized"; -constexpr name _monitor_ = "monitor"; - -struct window : id_obj { - - struct state { - - using optional = std::optional<window::state>; - - explicit state() {} - - i32 x = 0; - i32 y = 0; - ui32 width = 0; - ui32 height = 0; - bool fullscreen = false; - bool floating = false; - bool resizable = true; - bool decorated = true; - bool maximized = false; - index monitor = 0; - }; - - using ptr = std::shared_ptr<window>; - using event = std::function<void(ptr)>; - using map = std::map<id, ptr>; - using ref = window const&; - - window() = default; - explicit window(name title) : title(title) {} - - bool create(state::optional state = {}); - void destroy(); + constexpr name _default_ = "default"; + + constexpr name _window_file_ = "window.json"; + constexpr name _x_ = "x"; + constexpr name _y_ = "y"; + constexpr name _width_ = "width"; + constexpr name _height_ = "height"; + constexpr name _fullscreen_ = "fullscreen"; + constexpr name _floating_ = "floating"; + constexpr name _resizable_ = "resizable"; + constexpr name _decorated_ = "decorated"; + constexpr name _maximized_ = "maximized"; + constexpr name _monitor_ = "monitor"; - state get_state() const; + struct window : id_obj { + struct state { + using optional = std::optional<window::state>; - void set_title(name text); - name get_title() const { return str(title); } + explicit state() {} - void set_save_name(name save) { save_name = save; } - name get_save_name() const { return str(save_name); } + i32 x = 0; + i32 y = 0; + ui32 width = 0; + ui32 height = 0; + bool fullscreen = false; + bool floating = false; + bool resizable = true; + bool decorated = true; + bool maximized = false; + index monitor = 0; + }; + + using ptr = std::shared_ptr<window>; + using event = std::function<void(ptr)>; + using map = std::map<id, ptr>; + using ref = window const&; + + window() = default; + explicit window(name title) + : title(title) {} + + bool create(state::optional state = {}); + void destroy(); + + state get_state() const; + + void set_title(name text); + name get_title() const { + return str(title); + } + + void set_save_name(name save) { + save_name = save; + } + name get_save_name() const { + return str(save_name); + } + + void set_position(i32 x, i32 y); + void get_position(i32& x, i32& y) const; + void set_size(ui32 width, ui32 height); + void get_size(ui32& width, ui32& height) const; - void set_position(i32 x, i32 y); - void get_position(i32& x, i32& y) const; - void set_size(ui32 width, ui32 height); - void get_size(ui32& width, ui32& height) const; + void get_framebuffer_size(ui32& width, ui32& height) const; - void get_framebuffer_size(ui32& width, ui32& height) const; + void set_mouse_position(r64 x, r64 y); + void get_mouse_position(r64& x, r64& y) const; + mouse_position get_mouse_position() const; - void set_mouse_position(r64 x, r64 y); - void get_mouse_position(r64& x, r64& y) const; - mouse_position get_mouse_position() const; + void hide_mouse_cursor(); + void show_mouse_cursor(); - void hide_mouse_cursor(); - void show_mouse_cursor(); + float get_aspect_ratio() const; - float get_aspect_ratio() const; + void show(); + void hide(); + bool visible() const; - void show(); - void hide(); - bool visible() const; + void iconify(); + bool iconified() const; + void restore(); - void iconify(); - bool iconified() const; - void restore(); + void maximize(); + bool maximized() const; - void maximize(); - bool maximized() const; + void focus(); + bool focused() const; - void focus(); - bool focused() const; + void set_fullscreen(bool active) { + if (fullscreen_active != active) + switch_mode_request_active = true; + } + bool fullscreen() const { + return fullscreen_active; + } - void set_fullscreen(bool active) { + bool hovered() const; - if (fullscreen_active != active) - switch_mode_request_active = true; - } - bool fullscreen() const { return fullscreen_active; } + bool resizable() const; + void set_resizable(bool value); - bool hovered() const; + bool decorated() const; + void set_decorated(bool value); - bool resizable() const; - void set_resizable(bool value); + bool floating() const; + void set_floating(bool value); - bool decorated() const; - void set_decorated(bool value); + static window* get_window(GLFWwindow* handle); - bool floating() const; - void set_floating(bool value); + bool close_request() const; + bool switch_mode_request() const { + return switch_mode_request_active; + } - static window* get_window(GLFWwindow* handle); + bool switch_mode(state::optional state = {}); - bool close_request() const; - bool switch_mode_request() const { return switch_mode_request_active; } + GLFWwindow* get() const { + return handle; + } - bool switch_mode(state::optional state = {}); + bool resize_request() const { + return resize_request_active; + } + bool handle_resize() { + if (on_resize) + if (!on_resize(framebuffer_width, framebuffer_height)) + return false; - GLFWwindow* get() const { return handle; } + resize_request_active = false; + return true; + } - bool resize_request() const { return resize_request_active; } - bool handle_resize() { + void update_state() { + get_position(pos_x, pos_y); + get_size(width, height); + } - if (on_resize) - if (!on_resize(framebuffer_width, framebuffer_height)) - return false; + using resize_func = std::function<bool(ui32, ui32)>; + resize_func on_resize; - resize_request_active = false; - return true; - } + void assign(input* callback) { + input = callback; + } - void update_state() { get_position(pos_x, pos_y); get_size(width, height); } + void set_debug_title(bool value = true) { + debug_title_active = value; + } + bool debug_title() const { + return debug_title_active; + } - using resize_func = std::function<bool(ui32, ui32)>; - resize_func on_resize; + void update_title() { + set_title(str(title)); + } - void assign(input* callback) { input = callback; } + VkSurfaceKHR create_surface(); - void set_debug_title(bool value = true) { debug_title_active = value; } - bool debug_title() const { return debug_title_active; } + void set_icon(data_ptr data, uv2 size); - void update_title() { set_title(str(title)); } + index get_monitor() const; - VkSurfaceKHR create_surface(); + void center(); - void set_icon(data_ptr data, uv2 size); + private: + void handle_message(); - index get_monitor() const; + GLFWwindow* handle = nullptr; + lava::input* input = nullptr; - void center(); + string title = _lava_; + string save_name = _default_; -private: - void handle_message(); + bool fullscreen_active = false; + bool debug_title_active = false; - GLFWwindow* handle = nullptr; - lava::input* input = nullptr; + bool switch_mode_request_active = false; + bool resize_request_active = false; - string title = _lava_; - string save_name = _default_; + ui32 framebuffer_width = 0; + ui32 framebuffer_height = 0; - bool fullscreen_active = false; - bool debug_title_active = false; - - bool switch_mode_request_active = false; - bool resize_request_active = false; - - ui32 framebuffer_width = 0; - ui32 framebuffer_height = 0; - - i32 pos_x = 0; - i32 pos_y = 0; - ui32 width = 0; - ui32 height = 0; -}; + i32 pos_x = 0; + i32 pos_y = 0; + ui32 width = 0; + ui32 height = 0; + }; -bool window_file(); + bool window_file(); -window::state::optional load_window_state(name save_name = _default_); + window::state::optional load_window_state(name save_name = _default_); -bool load_window_file(window::state& state, name save_name); + bool load_window_file(window::state& state, name save_name); -void save_window_file(window::ref window); + void save_window_file(window::ref window); -VkSurfaceKHR create_surface(GLFWwindow* window); + VkSurfaceKHR create_surface(GLFWwindow* window); -} // lava +} // namespace lava diff --git a/liblava/fwd.hpp b/liblava/fwd.hpp index db409bd412ecb6486d7389ec0c358debdcf53ca2..a38658fb48cda3d16ec311f8f7b67ea8f5da01fa 100644 --- a/liblava/fwd.hpp +++ b/liblava/fwd.hpp @@ -97,4 +97,4 @@ namespace lava { struct dispatcher; struct thread_pool; -} // lava +} // namespace lava diff --git a/liblava/lava.hpp b/liblava/lava.hpp index f4db4e81a592c30f1f9d4be1756883777dad72d0..bbe67d0498504e1b2a63269e962682afe0dd642c 100644 --- a/liblava/lava.hpp +++ b/liblava/lava.hpp @@ -4,10 +4,10 @@ #pragma once -#include <liblava/core.hpp> -#include <liblava/util.hpp> +#include <liblava/app.hpp> #include <liblava/base.hpp> #include <liblava/block.hpp> -#include <liblava/resource.hpp> +#include <liblava/core.hpp> #include <liblava/frame.hpp> -#include <liblava/app.hpp> +#include <liblava/resource.hpp> +#include <liblava/util.hpp> diff --git a/liblava/resource/buffer.cpp b/liblava/resource/buffer.cpp index 1bd3e95074ac409da5530419e0dd6da91fb2362e..fe5ec219c360fe39741173975b6e6ba7ada8608d 100644 --- a/liblava/resource/buffer.cpp +++ b/liblava/resource/buffer.cpp @@ -6,121 +6,107 @@ namespace lava { -VkPipelineStageFlags buffer::usage_to_possible_stages(VkBufferUsageFlags usage) { - - VkPipelineStageFlags flags = 0; - - if (usage & (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)) - flags |= VK_PIPELINE_STAGE_TRANSFER_BIT; - if (usage & (VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT)) - flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; - if (usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) - flags |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; - if (usage & (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) - flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - if (usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) - flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; - - return flags; -} - -VkAccessFlags buffer::usage_to_possible_access(VkBufferUsageFlags usage) { - - VkAccessFlags flags = 0; - - if (usage & (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)) - flags |= VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; - if (usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) - flags |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; - if (usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT) - flags |= VK_ACCESS_INDEX_READ_BIT; - if (usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) - flags |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT; - if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) - flags |= VK_ACCESS_UNIFORM_READ_BIT; - if (usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) - flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; - - return flags; -} - -bool buffer::create(device_ptr d, void const* data, size_t size, VkBufferUsageFlags usage, bool mapped, VmaMemoryUsage memory_usage) { - - device = d; - - VkBufferCreateInfo buffer_info - { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = size, - .usage = usage, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .queueFamilyIndexCount = 0, - }; - - VmaAllocationCreateFlags const alloc_flags = mapped ? VMA_ALLOCATION_CREATE_MAPPED_BIT : 0; - - VmaAllocationCreateInfo alloc_info - { - .flags = alloc_flags, - .usage = memory_usage, - }; - - if (failed(vmaCreateBuffer(device->alloc(), &buffer_info, &alloc_info, &vk_buffer, &allocation, &allocation_info))) { - - log()->error("create buffer"); - return false; + VkPipelineStageFlags buffer::usage_to_possible_stages(VkBufferUsageFlags usage) { + VkPipelineStageFlags flags = 0; + + if (usage & (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)) + flags |= VK_PIPELINE_STAGE_TRANSFER_BIT; + if (usage & (VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT)) + flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + if (usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) + flags |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; + if (usage & (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) + flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + if (usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + + return flags; } - if (!mapped) { + VkAccessFlags buffer::usage_to_possible_access(VkBufferUsageFlags usage) { + VkAccessFlags flags = 0; + + if (usage & (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)) + flags |= VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; + if (usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) + flags |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + if (usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT) + flags |= VK_ACCESS_INDEX_READ_BIT; + if (usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) + flags |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT; + if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) + flags |= VK_ACCESS_UNIFORM_READ_BIT; + if (usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + + return flags; + } - if (data) { + bool buffer::create(device_ptr d, void const* data, size_t size, VkBufferUsageFlags usage, bool mapped, VmaMemoryUsage memory_usage) { + device = d; - data_ptr map = nullptr; - if (failed(vmaMapMemory(device->alloc(), allocation, (void**)(&map)))) { - - log()->error("map buffer memory"); - return false; - } + VkBufferCreateInfo buffer_info{ + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .size = size, + .usage = usage, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 0, + }; - memcpy(map, data, size); + VmaAllocationCreateFlags const alloc_flags = mapped ? VMA_ALLOCATION_CREATE_MAPPED_BIT : 0; - vmaUnmapMemory(device->alloc(), allocation); - } - } - else if (data && allocation_info.pMappedData) { + VmaAllocationCreateInfo alloc_info{ + .flags = alloc_flags, + .usage = memory_usage, + }; - memcpy(allocation_info.pMappedData, data, size); + if (failed(vmaCreateBuffer(device->alloc(), &buffer_info, &alloc_info, &vk_buffer, &allocation, &allocation_info))) { + log()->error("create buffer"); + return false; + } - flush(); - } + if (!mapped) { + if (data) { + data_ptr map = nullptr; + if (failed(vmaMapMemory(device->alloc(), allocation, (void**) (&map)))) { + log()->error("map buffer memory"); + return false; + } - descriptor.buffer = vk_buffer; - descriptor.offset = 0; - descriptor.range = size; + memcpy(map, data, size); - return true; -} + vmaUnmapMemory(device->alloc(), allocation); + } + } else if (data && allocation_info.pMappedData) { + memcpy(allocation_info.pMappedData, data, size); -bool buffer::create_mapped(device_ptr d, void const* data, size_t size, VkBufferUsageFlags usage, VmaMemoryUsage memory_usage) { + flush(); + } - return create(d, data, size, usage, true, memory_usage); -} + descriptor.buffer = vk_buffer; + descriptor.offset = 0; + descriptor.range = size; -void buffer::destroy() { + return true; + } - if (!vk_buffer) - return; + bool buffer::create_mapped(device_ptr d, void const* data, size_t size, VkBufferUsageFlags usage, VmaMemoryUsage memory_usage) { + return create(d, data, size, usage, true, memory_usage); + } - vmaDestroyBuffer(device->alloc(), vk_buffer, allocation); - vk_buffer = 0; - allocation = nullptr; + void buffer::destroy() { + if (!vk_buffer) + return; - device = nullptr; -} + vmaDestroyBuffer(device->alloc(), vk_buffer, allocation); + vk_buffer = 0; + allocation = nullptr; -void buffer::flush(VkDeviceSize offset, VkDeviceSize size) { + device = nullptr; + } - vmaFlushAllocation(device->alloc(), allocation, offset, size); -} + void buffer::flush(VkDeviceSize offset, VkDeviceSize size) { + vmaFlushAllocation(device->alloc(), allocation, offset, size); + } -} // lava +} // namespace lava diff --git a/liblava/resource/buffer.hpp b/liblava/resource/buffer.hpp index d836c7c9492c9545e2789b54f7acd16f1a267442..e8310b509b6bb6c26ed58d636360c2365e381073 100644 --- a/liblava/resource/buffer.hpp +++ b/liblava/resource/buffer.hpp @@ -9,51 +9,74 @@ namespace lava { -struct buffer : id_obj { - - using ptr = std::shared_ptr<buffer>; - using list = std::vector<ptr>; - - static VkPipelineStageFlags usage_to_possible_stages(VkBufferUsageFlags usage); - static VkAccessFlags usage_to_possible_access(VkBufferUsageFlags usage); - - ~buffer() { destroy(); } - - bool create(device_ptr device, void const* data, size_t size, VkBufferUsageFlags usage, bool mapped = false, - VmaMemoryUsage memory_usage = VMA_MEMORY_USAGE_GPU_ONLY); - - bool create_mapped(device_ptr device, void const* data, size_t size, VkBufferUsageFlags usage, - VmaMemoryUsage memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU); - - void destroy(); - - device_ptr get_device() { return device; } - - bool valid() const { return vk_buffer != 0; } - - VkBuffer get() const { return vk_buffer; } - VkDescriptorBufferInfo const* get_descriptor() const { return &descriptor; } - VkDescriptorBufferInfo const* get_info() const { return get_descriptor(); } - - VkDeviceSize get_size() const { return allocation_info.size; } - void* get_mapped_data() const { return allocation_info.pMappedData; } - VkDeviceMemory get_device_memory() const { return allocation_info.deviceMemory; } - - void flush(VkDeviceSize offset = 0, VkDeviceSize size = VK_WHOLE_SIZE); - - VmaAllocation const& get_allocation() const { return allocation; } - VmaAllocationInfo const& get_allocation_info() const { return allocation_info; } - -private: - device_ptr device = nullptr; - - VkBuffer vk_buffer = 0; - VmaAllocation allocation = nullptr; - - VmaAllocationInfo allocation_info = {}; - VkDescriptorBufferInfo descriptor = {}; -}; - -inline buffer::ptr make_buffer() { return std::make_shared<buffer>(); } - -} // lava + struct buffer : id_obj { + using ptr = std::shared_ptr<buffer>; + using list = std::vector<ptr>; + + static VkPipelineStageFlags usage_to_possible_stages(VkBufferUsageFlags usage); + static VkAccessFlags usage_to_possible_access(VkBufferUsageFlags usage); + + ~buffer() { + destroy(); + } + + bool create(device_ptr device, void const* data, size_t size, VkBufferUsageFlags usage, bool mapped = false, + VmaMemoryUsage memory_usage = VMA_MEMORY_USAGE_GPU_ONLY); + + bool create_mapped(device_ptr device, void const* data, size_t size, VkBufferUsageFlags usage, + VmaMemoryUsage memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU); + + void destroy(); + + device_ptr get_device() { + return device; + } + + bool valid() const { + return vk_buffer != 0; + } + + VkBuffer get() const { + return vk_buffer; + } + VkDescriptorBufferInfo const* get_descriptor() const { + return &descriptor; + } + VkDescriptorBufferInfo const* get_info() const { + return get_descriptor(); + } + + VkDeviceSize get_size() const { + return allocation_info.size; + } + void* get_mapped_data() const { + return allocation_info.pMappedData; + } + VkDeviceMemory get_device_memory() const { + return allocation_info.deviceMemory; + } + + void flush(VkDeviceSize offset = 0, VkDeviceSize size = VK_WHOLE_SIZE); + + VmaAllocation const& get_allocation() const { + return allocation; + } + VmaAllocationInfo const& get_allocation_info() const { + return allocation_info; + } + + private: + device_ptr device = nullptr; + + VkBuffer vk_buffer = 0; + VmaAllocation allocation = nullptr; + + VmaAllocationInfo allocation_info = {}; + VkDescriptorBufferInfo descriptor = {}; + }; + + inline buffer::ptr make_buffer() { + return std::make_shared<buffer>(); + } + +} // namespace lava diff --git a/liblava/resource/format.cpp b/liblava/resource/format.cpp index 502d40afcf369fe6d081410bb604288382cee777..fae30d4ed8c94ded10773c4d456befb4a3d589f3 100644 --- a/liblava/resource/format.cpp +++ b/liblava/resource/format.cpp @@ -2,65 +2,63 @@ // copyright : Copyright (c) 2018-present, Lava Block OÜ // license : MIT; see accompanying LICENSE file -#include <liblava/resource/format.hpp> #include <liblava/base/memory.hpp> +#include <liblava/resource/format.hpp> bool lava::format_depth(VkFormat format) { - switch (format) { - - case VK_FORMAT_D16_UNORM: - case VK_FORMAT_D16_UNORM_S8_UINT: - case VK_FORMAT_D24_UNORM_S8_UINT: - case VK_FORMAT_D32_SFLOAT: - case VK_FORMAT_X8_D24_UNORM_PACK32: - case VK_FORMAT_D32_SFLOAT_S8_UINT: - return true; - - default: - return false; + case VK_FORMAT_D16_UNORM: + case VK_FORMAT_D16_UNORM_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + case VK_FORMAT_D32_SFLOAT: + case VK_FORMAT_X8_D24_UNORM_PACK32: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return true; + + default: + return false; } } -bool lava::format_stencil(VkFormat format) { return format == VK_FORMAT_S8_UINT; } +bool lava::format_stencil(VkFormat format) { + return format == VK_FORMAT_S8_UINT; +} -bool lava::format_depth_stencil(VkFormat format) { return format_depth(format) || format_stencil(format); } +bool lava::format_depth_stencil(VkFormat format) { + return format_depth(format) || format_stencil(format); +} VkImageAspectFlags lava::format_aspect_mask(VkFormat format) { - switch (format) { + case VK_FORMAT_UNDEFINED: + return 0; - case VK_FORMAT_UNDEFINED: - return 0; + case VK_FORMAT_S8_UINT: + return VK_IMAGE_ASPECT_STENCIL_BIT; - case VK_FORMAT_S8_UINT: - return VK_IMAGE_ASPECT_STENCIL_BIT; + case VK_FORMAT_D16_UNORM_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT; - case VK_FORMAT_D16_UNORM_S8_UINT: - case VK_FORMAT_D24_UNORM_S8_UINT: - case VK_FORMAT_D32_SFLOAT_S8_UINT: - return VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT; + case VK_FORMAT_D16_UNORM: + case VK_FORMAT_D32_SFLOAT: + case VK_FORMAT_X8_D24_UNORM_PACK32: + return VK_IMAGE_ASPECT_DEPTH_BIT; - case VK_FORMAT_D16_UNORM: - case VK_FORMAT_D32_SFLOAT: - case VK_FORMAT_X8_D24_UNORM_PACK32: - return VK_IMAGE_ASPECT_DEPTH_BIT; - - default: - return VK_IMAGE_ASPECT_COLOR_BIT; + default: + return VK_IMAGE_ASPECT_COLOR_BIT; } } void lava::format_block_dim(VkFormat format, ui32& width, ui32& height) { - -#define fmt(x, w, h) \ +#define fmt(x, w, h) \ case VK_FORMAT_##x: \ - width = w; \ - height = h; \ + width = w; \ + height = h; \ break switch (format) { - fmt(ETC2_R8G8B8A8_UNORM_BLOCK, 4, 4); fmt(ETC2_R8G8B8A8_SRGB_BLOCK, 4, 4); fmt(ETC2_R8G8B8A1_UNORM_BLOCK, 4, 4); @@ -110,17 +108,16 @@ void lava::format_block_dim(VkFormat format, ui32& width, ui32& height) { fmt(ASTC_12x10_UNORM_BLOCK, 12, 10); fmt(ASTC_12x12_UNORM_BLOCK, 12, 12); - default: - width = 1; - height = 1; - break; + default: + width = 1; + height = 1; + break; } #undef fmt } void lava::format_align_dim(VkFormat format, ui32& width, ui32& height) { - ui32 align_width, align_height; format_block_dim(format, align_width, align_height); width = ((width + align_width - 1) / align_width) * align_width; @@ -128,7 +125,6 @@ void lava::format_align_dim(VkFormat format, ui32& width, ui32& height) { } void lava::format_num_blocks(VkFormat format, ui32& width, ui32& height) { - ui32 align_width, align_height; format_block_dim(format, align_width, align_height); width = (width + align_width - 1) / align_width; @@ -136,13 +132,11 @@ void lava::format_num_blocks(VkFormat format, ui32& width, ui32& height) { } lava::ui32 lava::format_block_size(VkFormat format) { - -#define fmt(x, bpp) \ +#define fmt(x, bpp) \ case VK_FORMAT_##x: \ return bpp switch (format) { - fmt(R4G4_UNORM_PACK8, 1); fmt(R4G4B4A4_UNORM_PACK16, 2); fmt(B4G4R4A4_UNORM_PACK16, 2); @@ -319,24 +313,21 @@ lava::ui32 lava::format_block_size(VkFormat format) { fmt(ASTC_12x10_UNORM_BLOCK, 16); fmt(ASTC_12x12_UNORM_BLOCK, 16); - default: - assert(0 && "Unknown format."); - return 0; + default: + assert(0 && "Unknown format."); + return 0; } #undef fmt } bool lava::get_supported_depth_format(VkPhysicalDevice physical_device, VkFormat* depth_format) { - VkFormats depth_formats = { VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D32_SFLOAT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D16_UNORM }; for (auto& format : depth_formats) { - VkFormatProperties format_props; vkGetPhysicalDeviceFormatProperties(physical_device, format, &format_props); if (format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) { - *depth_format = format; return true; } @@ -346,7 +337,6 @@ bool lava::get_supported_depth_format(VkPhysicalDevice physical_device, VkFormat } VkImageMemoryBarrier lava::image_memory_barrier(VkImage image, VkImageLayout old_layout, VkImageLayout new_layout) { - return { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -364,79 +354,74 @@ VkImageMemoryBarrier lava::image_memory_barrier(VkImage image, VkImageLayout old void lava::set_image_layout(device_ptr device, VkCommandBuffer cmd_buffer, VkImage image, VkImageLayout old_image_layout, VkImageLayout new_image_layout, VkImageSubresourceRange subresource_range, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask) { - auto barrier = image_memory_barrier(image, old_image_layout, new_image_layout); barrier.subresourceRange = subresource_range; switch (old_image_layout) { - - case VK_IMAGE_LAYOUT_UNDEFINED: - barrier.srcAccessMask = 0; - break; - - case VK_IMAGE_LAYOUT_PREINITIALIZED: - barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; - break; - - case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - break; - - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - barrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - break; - - case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - break; - - case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - break; - - case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - break; - default: - break; + case VK_IMAGE_LAYOUT_UNDEFINED: + barrier.srcAccessMask = 0; + break; + + case VK_IMAGE_LAYOUT_PREINITIALIZED: + barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; + break; + + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + break; + + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + barrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + break; + + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + break; + + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + break; + + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + break; + default: + break; } switch (new_image_layout) { - - case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - break; - - case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - break; - - case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - break; - - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - barrier.dstAccessMask = barrier.dstAccessMask | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - break; - - case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - if (barrier.srcAccessMask == 0) - barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; - - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - break; - default: - break; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + break; + + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + break; + + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + break; + + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + barrier.dstAccessMask = barrier.dstAccessMask | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + break; + + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + if (barrier.srcAccessMask == 0) + barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; + + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + break; + default: + break; } device->call().vkCmdPipelineBarrier(cmd_buffer, src_stage_mask, dst_stage_mask, 0, 0, nullptr, 0, nullptr, 1, &barrier); } void lava::set_image_layout(device_ptr device, VkCommandBuffer cmd_buffer, VkImage image, VkImageAspectFlags aspect_mask, VkImageLayout old_image_layout, - VkImageLayout new_image_layout, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask) { - - VkImageSubresourceRange subresource_range - { + VkImageLayout new_image_layout, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask) { + VkImageSubresourceRange subresource_range{ .aspectMask = aspect_mask, .baseMipLevel = 0, .levelCount = 1, @@ -448,9 +433,8 @@ void lava::set_image_layout(device_ptr device, VkCommandBuffer cmd_buffer, VkIma } void lava::insert_image_memory_barrier(device_ptr device, VkCommandBuffer cmd_buffer, VkImage image, VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask, - VkImageLayout old_image_layout, VkImageLayout new_image_layout, - VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask, VkImageSubresourceRange subresource_range) { - + VkImageLayout old_image_layout, VkImageLayout new_image_layout, + VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask, VkImageSubresourceRange subresource_range) { auto barrier = image_memory_barrier(image, old_image_layout, new_image_layout); barrier.srcAccessMask = src_access_mask; diff --git a/liblava/resource/format.hpp b/liblava/resource/format.hpp index 0d58fc1c2802112bf0a41bb59ab4daea3fde3027..896f232de3b0ebddbf3cb1f008b5a5a92f46556e 100644 --- a/liblava/resource/format.hpp +++ b/liblava/resource/format.hpp @@ -9,40 +9,40 @@ namespace lava { -bool format_depth(VkFormat format); + bool format_depth(VkFormat format); -bool format_stencil(VkFormat format); + bool format_stencil(VkFormat format); -bool format_depth_stencil(VkFormat format); + bool format_depth_stencil(VkFormat format); -VkImageAspectFlags format_aspect_mask(VkFormat format); + VkImageAspectFlags format_aspect_mask(VkFormat format); -void format_block_dim(VkFormat format, ui32& width, ui32& height); + void format_block_dim(VkFormat format, ui32& width, ui32& height); -void format_align_dim(VkFormat format, ui32& width, ui32& height); + void format_align_dim(VkFormat format, ui32& width, ui32& height); -void format_num_blocks(VkFormat format, ui32& width, ui32& height); + void format_num_blocks(VkFormat format, ui32& width, ui32& height); -ui32 format_block_size(VkFormat format); + ui32 format_block_size(VkFormat format); -bool get_supported_depth_format(VkPhysicalDevice physical_device, VkFormat* depth_format); + bool get_supported_depth_format(VkPhysicalDevice physical_device, VkFormat* depth_format); -VkImageMemoryBarrier image_memory_barrier(VkImage image, VkImageLayout old_layout, VkImageLayout new_layout); + VkImageMemoryBarrier image_memory_barrier(VkImage image, VkImageLayout old_layout, VkImageLayout new_layout); -void set_image_layout(device_ptr device, VkCommandBuffer cmd_buffer, VkImage image, VkImageLayout old_image_layout, - VkImageLayout new_image_layout, VkImageSubresourceRange subresource_range, - VkPipelineStageFlags src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VkPipelineStageFlags dst_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + void set_image_layout(device_ptr device, VkCommandBuffer cmd_buffer, VkImage image, VkImageLayout old_image_layout, + VkImageLayout new_image_layout, VkImageSubresourceRange subresource_range, + VkPipelineStageFlags src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VkPipelineStageFlags dst_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); -void set_image_layout(device_ptr device, VkCommandBuffer cmd_buffer, VkImage image, VkImageAspectFlags aspect_mask, - VkImageLayout old_image_layout, VkImageLayout new_image_layout, - VkPipelineStageFlags src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VkPipelineStageFlags dst_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + void set_image_layout(device_ptr device, VkCommandBuffer cmd_buffer, VkImage image, VkImageAspectFlags aspect_mask, + VkImageLayout old_image_layout, VkImageLayout new_image_layout, + VkPipelineStageFlags src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VkPipelineStageFlags dst_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); -void insert_image_memory_barrier(device_ptr device, VkCommandBuffer cmd_buffer, VkImage image, VkAccessFlags src_access_mask, - VkAccessFlags dst_access_mask, VkImageLayout old_image_layout, - VkImageLayout new_image_layout, VkPipelineStageFlags src_stage_mask, - VkPipelineStageFlags dst_stage_mask, - VkImageSubresourceRange subresource_range); + void insert_image_memory_barrier(device_ptr device, VkCommandBuffer cmd_buffer, VkImage image, VkAccessFlags src_access_mask, + VkAccessFlags dst_access_mask, VkImageLayout old_image_layout, + VkImageLayout new_image_layout, VkPipelineStageFlags src_stage_mask, + VkPipelineStageFlags dst_stage_mask, + VkImageSubresourceRange subresource_range); -} // lava +} // namespace lava diff --git a/liblava/resource/image.cpp b/liblava/resource/image.cpp index 1aedd9b271b22c7db056ac4fcfddb1b87ed14f4a..6c89e3810df5addf6156f4e1ebc8cdf8d6b1470e 100644 --- a/liblava/resource/image.cpp +++ b/liblava/resource/image.cpp @@ -6,106 +6,97 @@ namespace lava { -image::image(VkFormat format, VkImage vk_image) : vk_image(vk_image) { - - info = - { - .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .imageType = VK_IMAGE_TYPE_2D, - .format = format, - .extent = { 0, 0, 1 }, - .mipLevels = 1, - .arrayLayers = 1, - .samples = VK_SAMPLE_COUNT_1_BIT, - .tiling = VK_IMAGE_TILING_OPTIMAL, - .usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .queueFamilyIndexCount = 0, - .pQueueFamilyIndices = nullptr, - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, - }; - - subresource_range = - { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }; - - view_info = - { - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .image = vk_image, - .viewType = VK_IMAGE_VIEW_TYPE_2D, - .format = format, - .components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }, - .subresourceRange = subresource_range, - }; -} - -bool image::create(device_ptr d, uv2 size, VmaMemoryUsage memory_usage, bool mip_levels_generation) { - - device = d; - - info.extent = { size.x, size.y, 1 }; - - if (!vk_image) { - - VmaAllocationCreateInfo create_info - { - .usage = memory_usage, + image::image(VkFormat format, VkImage vk_image) + : vk_image(vk_image) { + info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .imageType = VK_IMAGE_TYPE_2D, + .format = format, + .extent = { 0, 0, 1 }, + .mipLevels = 1, + .arrayLayers = 1, + .samples = VK_SAMPLE_COUNT_1_BIT, + .tiling = VK_IMAGE_TILING_OPTIMAL, + .usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 0, + .pQueueFamilyIndices = nullptr, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, }; - if (failed(vmaCreateImage(device->alloc(), &info, &create_info, &vk_image, &allocation, nullptr))) { + subresource_range = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }; - log()->error("create image"); - return false; - } + view_info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .image = vk_image, + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .format = format, + .components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }, + .subresourceRange = subresource_range, + }; } - view_info.image = vk_image; - view_info.subresourceRange = subresource_range; + bool image::create(device_ptr d, uv2 size, VmaMemoryUsage memory_usage, bool mip_levels_generation) { + device = d; - return device->vkCreateImageView(&view_info, &view); -} + info.extent = { size.x, size.y, 1 }; -void image::destroy(bool view_only) { + if (!vk_image) { + VmaAllocationCreateInfo create_info{ + .usage = memory_usage, + }; - if (view) { + if (failed(vmaCreateImage(device->alloc(), &info, &create_info, &vk_image, &allocation, nullptr))) { + log()->error("create image"); + return false; + } + } - device->vkDestroyImageView(view); - view = 0; - } + view_info.image = vk_image; + view_info.subresourceRange = subresource_range; - if (view_only) - return; + return device->vkCreateImageView(&view_info, &view); + } - if (vk_image) { + void image::destroy(bool view_only) { + if (view) { + device->vkDestroyImageView(view); + view = 0; + } - vmaDestroyImage(device->alloc(), vk_image, allocation); - vk_image = 0; - allocation = nullptr; - } + if (view_only) + return; - device = nullptr; -} + if (vk_image) { + vmaDestroyImage(device->alloc(), vk_image, allocation); + vk_image = 0; + allocation = nullptr; + } -image::ptr make_image(VkFormat format, VkImage vk_image) { return std::make_shared<image>(format, vk_image); } + device = nullptr; + } -image::ptr make_image(VkFormat format, device_ptr device, uv2 size, VkImage vk_image) { + image::ptr make_image(VkFormat format, VkImage vk_image) { + return std::make_shared<image>(format, vk_image); + } - auto result = make_image(format, vk_image); + image::ptr make_image(VkFormat format, device_ptr device, uv2 size, VkImage vk_image) { + auto result = make_image(format, vk_image); - if (!result->create(device, size)) - return nullptr; + if (!result->create(device, size)) + return nullptr; - return result; -} + return result; + } -} // lava +} // namespace lava diff --git a/liblava/resource/image.hpp b/liblava/resource/image.hpp index a9327644e2c570dc107fb2f1b24e40a43f4e5345..1f16664e8adaaff96a73ea445b57b3e8719f3b06 100644 --- a/liblava/resource/image.hpp +++ b/liblava/resource/image.hpp @@ -11,59 +11,98 @@ namespace lava { -struct image : id_obj { - - using ptr = std::shared_ptr<image>; - using map = std::map<id, ptr>; - using list = std::vector<ptr>; - - explicit image(VkFormat format, VkImage vk_image = 0); - - bool create(device_ptr device, uv2 size, VmaMemoryUsage memory_usage = VMA_MEMORY_USAGE_GPU_ONLY, bool mip_levels_generation = false); - void destroy(bool view_only = false); - void destroy_view() { destroy(true); } - - device_ptr get_device() { return device; } - - VkFormat get_format() const { return info.format; } - uv2 get_size() const { return { info.extent.width, info.extent.height }; } - ui32 get_depth() const { return info.extent.depth; } - - VkImage get() const { return vk_image; } - VkImageView get_view() const { return view; } - - VkImageCreateInfo const& get_info() const { return info; } - VkImageViewCreateInfo const& get_view_info() const { return view_info; } - VkImageSubresourceRange const& get_subresource_range() const { return subresource_range; } - - void set_flags(VkImageCreateFlagBits flags) { info.flags = flags; } - void set_tiling(VkImageTiling tiling) { info.tiling = tiling; } - void set_usage(VkImageUsageFlags usage) { info.usage = usage; } - void set_layout(VkImageLayout initial) { info.initialLayout = initial; } - - void set_aspect_mask(VkImageAspectFlags aspectMask) { subresource_range.aspectMask = aspectMask; } - - void set_level_count(ui32 levels) { subresource_range.levelCount = levels; info.mipLevels = levels; } - void set_layer_count(ui32 layers) { subresource_range.layerCount = layers; info.arrayLayers = layers; } - - void set_component(VkComponentMapping mapping = {}) { view_info.components = mapping; } - void set_view_type(VkImageViewType type) { view_info.viewType = type; } - -private: - device_ptr device = nullptr; - - VkImage vk_image = 0; - VkImageCreateInfo info; - - VmaAllocation allocation = nullptr; - - VkImageView view = 0; - - VkImageViewCreateInfo view_info; - VkImageSubresourceRange subresource_range; -}; - -image::ptr make_image(VkFormat format, VkImage vk_image = 0); -image::ptr make_image(VkFormat format, device_ptr device, uv2 size, VkImage vk_image = 0); - -} // lava + struct image : id_obj { + using ptr = std::shared_ptr<image>; + using map = std::map<id, ptr>; + using list = std::vector<ptr>; + + explicit image(VkFormat format, VkImage vk_image = 0); + + bool create(device_ptr device, uv2 size, VmaMemoryUsage memory_usage = VMA_MEMORY_USAGE_GPU_ONLY, bool mip_levels_generation = false); + void destroy(bool view_only = false); + void destroy_view() { + destroy(true); + } + + device_ptr get_device() { + return device; + } + + VkFormat get_format() const { + return info.format; + } + uv2 get_size() const { + return { info.extent.width, info.extent.height }; + } + ui32 get_depth() const { + return info.extent.depth; + } + + VkImage get() const { + return vk_image; + } + VkImageView get_view() const { + return view; + } + + VkImageCreateInfo const& get_info() const { + return info; + } + VkImageViewCreateInfo const& get_view_info() const { + return view_info; + } + VkImageSubresourceRange const& get_subresource_range() const { + return subresource_range; + } + + void set_flags(VkImageCreateFlagBits flags) { + info.flags = flags; + } + void set_tiling(VkImageTiling tiling) { + info.tiling = tiling; + } + void set_usage(VkImageUsageFlags usage) { + info.usage = usage; + } + void set_layout(VkImageLayout initial) { + info.initialLayout = initial; + } + + void set_aspect_mask(VkImageAspectFlags aspectMask) { + subresource_range.aspectMask = aspectMask; + } + + void set_level_count(ui32 levels) { + subresource_range.levelCount = levels; + info.mipLevels = levels; + } + void set_layer_count(ui32 layers) { + subresource_range.layerCount = layers; + info.arrayLayers = layers; + } + + void set_component(VkComponentMapping mapping = {}) { + view_info.components = mapping; + } + void set_view_type(VkImageViewType type) { + view_info.viewType = type; + } + + private: + device_ptr device = nullptr; + + VkImage vk_image = 0; + VkImageCreateInfo info; + + VmaAllocation allocation = nullptr; + + VkImageView view = 0; + + VkImageViewCreateInfo view_info; + VkImageSubresourceRange subresource_range; + }; + + image::ptr make_image(VkFormat format, VkImage vk_image = 0); + image::ptr make_image(VkFormat format, device_ptr device, uv2 size, VkImage vk_image = 0); + +} // namespace lava diff --git a/liblava/resource/mesh.cpp b/liblava/resource/mesh.cpp index a07e75edb50954badd068bd75567ee39869cfd6b..846b65553d17f940876f6c56c09869ebe957832c 100644 --- a/liblava/resource/mesh.cpp +++ b/liblava/resource/mesh.cpp @@ -5,117 +5,104 @@ #include <liblava/resource/mesh.hpp> #ifndef LIBLAVA_TINYOBJLOADER -#define LIBLAVA_TINYOBJLOADER 1 +# define LIBLAVA_TINYOBJLOADER 1 #endif #if LIBLAVA_TINYOBJLOADER -#ifdef _WIN32 -#pragma warning(push, 4) -#else -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -#endif +# ifdef _WIN32 +# pragma warning(push, 4) +# else +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +# endif -#define TINYOBJLOADER_IMPLEMENTATION -#include <tiny_obj_loader.h> +# define TINYOBJLOADER_IMPLEMENTATION +# include <tiny_obj_loader.h> -#ifdef _WIN32 -#pragma warning(pop) -#else -#pragma GCC diagnostic pop -#endif +# ifdef _WIN32 +# pragma warning(pop) +# else +# pragma GCC diagnostic pop +# endif #endif namespace lava { -void mesh::add_data(mesh_data const& value) { - - auto index_base = to_ui32(data.vertices.size()); - - data.vertices.insert(data.vertices.end(), value.vertices.begin(),value.vertices.end()); - - for (auto& index : value.indices) - data.indices.push_back(index_base + index); -} + void mesh::add_data(mesh_data const& value) { + auto index_base = to_ui32(data.vertices.size()); -bool mesh::create(device_ptr d, bool m, VmaMemoryUsage mu) { + data.vertices.insert(data.vertices.end(), value.vertices.begin(), value.vertices.end()); - device = d; - mapped = m; - memory_usage = mu; - - if (!data.vertices.empty()) { - - vertex_buffer = make_buffer(); - - if (!vertex_buffer->create(device, data.vertices.data(), sizeof(vertex) * data.vertices.size(), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, mapped, memory_usage)) { - - log()->error("create mesh vertex buffer"); - return false; - } + for (auto& index : value.indices) + data.indices.push_back(index_base + index); } - if (!data.indices.empty()) { + bool mesh::create(device_ptr d, bool m, VmaMemoryUsage mu) { + device = d; + mapped = m; + memory_usage = mu; - index_buffer = make_buffer(); + if (!data.vertices.empty()) { + vertex_buffer = make_buffer(); - if (!index_buffer->create(device, data.indices.data(), sizeof(ui32) * data.indices.size(), VK_BUFFER_USAGE_INDEX_BUFFER_BIT, mapped, memory_usage)) { - - log()->error("create mesh index buffer"); - return false; + if (!vertex_buffer->create(device, data.vertices.data(), sizeof(vertex) * data.vertices.size(), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, mapped, memory_usage)) { + log()->error("create mesh vertex buffer"); + return false; + } } - } - return true; -} + if (!data.indices.empty()) { + index_buffer = make_buffer(); -void mesh::destroy() { + if (!index_buffer->create(device, data.indices.data(), sizeof(ui32) * data.indices.size(), VK_BUFFER_USAGE_INDEX_BUFFER_BIT, mapped, memory_usage)) { + log()->error("create mesh index buffer"); + return false; + } + } - vertex_buffer = nullptr; - index_buffer = nullptr; + return true; + } - device = nullptr; -} + void mesh::destroy() { + vertex_buffer = nullptr; + index_buffer = nullptr; -bool mesh::reload() { + device = nullptr; + } - auto dev = device; - destroy(); + bool mesh::reload() { + auto dev = device; + destroy(); - return create(dev, mapped, memory_usage); -} - -void mesh::bind(VkCommandBuffer cmd_buf) const { + return create(dev, mapped, memory_usage); + } - if (vertex_buffer && vertex_buffer->valid()) { + void mesh::bind(VkCommandBuffer cmd_buf) const { + if (vertex_buffer && vertex_buffer->valid()) { + std::array<VkDeviceSize, 1> const buffer_offsets = { 0 }; + std::array<VkBuffer, 1> const buffers = { vertex_buffer->get() }; - std::array<VkDeviceSize, 1> const buffer_offsets = { 0 }; - std::array<VkBuffer, 1> const buffers = { vertex_buffer->get() }; + vkCmdBindVertexBuffers(cmd_buf, 0, to_ui32(buffers.size()), buffers.data(), buffer_offsets.data()); + } - vkCmdBindVertexBuffers(cmd_buf, 0, to_ui32(buffers.size()), buffers.data(), buffer_offsets.data()); + if (index_buffer && index_buffer->valid()) + vkCmdBindIndexBuffer(cmd_buf, index_buffer->get(), 0, VK_INDEX_TYPE_UINT32); } - if (index_buffer && index_buffer->valid()) - vkCmdBindIndexBuffer(cmd_buf, index_buffer->get(), 0, VK_INDEX_TYPE_UINT32); -} - -void mesh::draw(VkCommandBuffer cmd_buf) const { - - if (!data.indices.empty()) - vkCmdDrawIndexed(cmd_buf, to_ui32(data.indices.size()), 1, 0, 0, 0); - else - vkCmdDraw(cmd_buf, to_ui32(data.vertices.size()), 1, 0, 0); -} + void mesh::draw(VkCommandBuffer cmd_buf) const { + if (!data.indices.empty()) + vkCmdDrawIndexed(cmd_buf, to_ui32(data.indices.size()), 1, 0, 0, 0); + else + vkCmdDraw(cmd_buf, to_ui32(data.vertices.size()), 1, 0, 0); + } -} // lava +} // namespace lava lava::mesh::ptr lava::load_mesh(device_ptr device, name filename) { - #if LIBLAVA_TINYOBJLOADER if (extension(filename, "OBJ")) { - tinyobj::attrib_t attrib; std::vector<tinyobj::shape_t> shapes; std::vector<tinyobj::material_t> materials; @@ -128,7 +115,6 @@ lava::mesh::ptr lava::load_mesh(device_ptr device, name filename) { { file file(filename); if (file.opened() && file.get_type() == file_type::fs) { - string temp_file; temp_file = file_system::get_pref_dir(); temp_file += get_filename_from(target_file, true); @@ -150,13 +136,10 @@ lava::mesh::ptr lava::load_mesh(device_ptr device, name filename) { } if (tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, str(target_file))) { - auto mesh = make_mesh(); for (auto const& shape : shapes) { - for (auto const& index : shape.mesh.indices) { - vertex vertex; vertex.position = v3(attrib.vertices[3 * index.vertex_index], @@ -168,9 +151,7 @@ lava::mesh::ptr lava::load_mesh(device_ptr device, name filename) { if (!attrib.texcoords.empty()) vertex.uv = v2(attrib.texcoords[2 * index.texcoord_index], 1.f - attrib.texcoords[2 * index.texcoord_index + 1]); - vertex.normal = attrib.normals.empty() ? v3(0.f) : v3(attrib.normals[3 * index.normal_index], - attrib.normals[3 * index.normal_index + 1], - attrib.normals[3 * index.normal_index + 2]); + vertex.normal = attrib.normals.empty() ? v3(0.f) : v3(attrib.normals[3 * index.normal_index], attrib.normals[3 * index.normal_index + 1], attrib.normals[3 * index.normal_index + 2]); mesh->get_vertices().push_back(vertex); mesh->get_indices().push_back(mesh->get_indices_count()); @@ -192,63 +173,85 @@ lava::mesh::ptr lava::load_mesh(device_ptr device, name filename) { } lava::mesh::ptr lava::load_mesh(device_ptr device, mesh_type type) { - switch (type) { - case mesh_type::cube: { - auto cube = make_mesh(); cube->get_vertices() = { // front - { { 1.f, 1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 1.f }, { 0.f, 0.f, 1.f } }, - { { -1.f, 1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 1.f }, { 0.f, 0.f, 1.f } }, + { { 1.f, 1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 1.f }, { 0.f, 0.f, 1.f } }, + { { -1.f, 1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 1.f }, { 0.f, 0.f, 1.f } }, { { -1.f, -1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 0.f }, { 0.f, 0.f, 1.f } }, - { { 1.f, -1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 0.f }, { 0.f, 0.f, 1.f } }, + { { 1.f, -1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 0.f }, { 0.f, 0.f, 1.f } }, // back - { { 1.f, 1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 1.f }, { 0.f, 0.f, -1.f } }, - { { -1.f, 1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 1.f }, { 0.f, 0.f, -1.f } }, + { { 1.f, 1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 1.f }, { 0.f, 0.f, -1.f } }, + { { -1.f, 1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 1.f }, { 0.f, 0.f, -1.f } }, { { -1.f, -1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 0.f }, { 0.f, 0.f, -1.f } }, - { { 1.f, -1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 0.f }, { 0.f, 0.f, -1.f } }, + { { 1.f, -1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 0.f }, { 0.f, 0.f, -1.f } }, // left - { { -1.f, 1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 1.f }, { -1.f, 0.f, 0.f } }, - { { -1.f, 1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 1.f }, { -1.f, 0.f, 0.f } }, + { { -1.f, 1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 1.f }, { -1.f, 0.f, 0.f } }, + { { -1.f, 1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 1.f }, { -1.f, 0.f, 0.f } }, { { -1.f, -1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 0.f }, { -1.f, 0.f, 0.f } }, - { { -1.f, -1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 0.f }, { -1.f, 0.f, 0.f } }, + { { -1.f, -1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 0.f }, { -1.f, 0.f, 0.f } }, // right - { { 1.f, 1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 1.f }, { 1.f, 0.f, 0.f } }, - { { 1.f, -1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 0.f }, { 1.f, 0.f, 0.f } }, + { { 1.f, 1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 1.f }, { 1.f, 0.f, 0.f } }, + { { 1.f, -1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 0.f }, { 1.f, 0.f, 0.f } }, { { 1.f, -1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 0.f }, { 1.f, 0.f, 0.f } }, - { { 1.f, 1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 1.f }, { 1.f, 0.f, 0.f } }, + { { 1.f, 1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 1.f }, { 1.f, 0.f, 0.f } }, // bottom - { { 1.f, 1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 0.f }, { 0.f, 1.f, 0.f } }, - { { -1.f, 1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 0.f }, { 0.f, 1.f, 0.f } }, + { { 1.f, 1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 0.f }, { 0.f, 1.f, 0.f } }, + { { -1.f, 1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 0.f }, { 0.f, 1.f, 0.f } }, { { -1.f, 1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 1.f }, { 0.f, 1.f, 0.f } }, - { { 1.f, 1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 1.f }, { 0.f, 1.f, 0.f } }, + { { 1.f, 1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 1.f }, { 0.f, 1.f, 0.f } }, // top - { { 1.f, -1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 1.f }, { 0.f, -1.f, 0.f } }, - { { -1.f, -1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 1.f }, { 0.f, -1.f, 0.f } }, + { { 1.f, -1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 1.f }, { 0.f, -1.f, 0.f } }, + { { -1.f, -1.f, 1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 1.f }, { 0.f, -1.f, 0.f } }, { { -1.f, -1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 0.f }, { 0.f, -1.f, 0.f } }, - { { 1.f, -1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 0.f }, { 0.f, -1.f, 0.f } }, + { { 1.f, -1.f, -1.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 0.f }, { 0.f, -1.f, 0.f } }, }; - cube->get_indices() = { 0, 1, 2, - 2, 3, 0, - 4, 7, 6, - 6, 5, 4, - 8, 9, 10, - 10, 11, 8, - 12, 13, 14, - 14, 15, 12, - 16, 19, 18, - 18, 17, 16, - 20, 21, 22, - 22, 23, 20, + cube->get_indices() = { + 0, + 1, + 2, + 2, + 3, + 0, + 4, + 7, + 6, + 6, + 5, + 4, + 8, + 9, + 10, + 10, + 11, + 8, + 12, + 13, + 14, + 14, + 15, + 12, + 16, + 19, + 18, + 18, + 17, + 16, + 20, + 21, + 22, + 22, + 23, + 20, }; if (!cube->create(device)) @@ -258,12 +261,11 @@ lava::mesh::ptr lava::load_mesh(device_ptr device, mesh_type type) { } case mesh_type::triangle: { - auto triangle = make_mesh(); - triangle->get_vertices().push_back({ { 1.f, 1.f, 0.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 1.f }, { 0.f, 0.f, 1.f } }); - triangle->get_vertices().push_back({ { -1.f, 1.f, 0.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 1.f }, { 0.f, 0.f, 1.f } }); - triangle->get_vertices().push_back({ { 0.f, -1.f, 0.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.5f, 0.f }, { 0.f, 0.f, 1.f } }); + triangle->get_vertices().push_back({ { 1.f, 1.f, 0.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 1.f }, { 0.f, 0.f, 1.f } }); + triangle->get_vertices().push_back({ { -1.f, 1.f, 0.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 1.f }, { 0.f, 0.f, 1.f } }); + triangle->get_vertices().push_back({ { 0.f, -1.f, 0.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.5f, 0.f }, { 0.f, 0.f, 1.f } }); if (!triangle->create(device)) return nullptr; @@ -272,15 +274,13 @@ lava::mesh::ptr lava::load_mesh(device_ptr device, mesh_type type) { } case mesh_type::quad: { - auto quad = make_mesh(); - quad->get_vertices() = - { - { { 1.f, 1.f, 0.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 1.f }, { 0.f, 0.f, 1.f } }, - { { -1.f, 1.f, 0.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 1.f }, { 0.f, 0.f, 1.f } }, + quad->get_vertices() = { + { { 1.f, 1.f, 0.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 1.f }, { 0.f, 0.f, 1.f } }, + { { -1.f, 1.f, 0.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 1.f }, { 0.f, 0.f, 1.f } }, { { -1.f, -1.f, 0.f }, { 1.f, 1.f, 1.f, 1.f }, { 0.f, 0.f }, { 0.f, 0.f, 1.f } }, - { { 1.f, -1.f, 0.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 0.f }, { 0.f, 0.f, 1.f } }, + { { 1.f, -1.f, 0.f }, { 1.f, 1.f, 1.f, 1.f }, { 1.f, 0.f }, { 0.f, 0.f, 1.f } }, }; quad->get_indices() = { 0, 1, 2, 2, 3, 0 }; diff --git a/liblava/resource/mesh.hpp b/liblava/resource/mesh.hpp index 1a63be930d0825d793273ea7ab69e8e09fbd33b1..840ec7ca30002a607500ecac7658696fe5dfc28d 100644 --- a/liblava/resource/mesh.hpp +++ b/liblava/resource/mesh.hpp @@ -4,118 +4,138 @@ #pragma once -#include <liblava/resource/buffer.hpp> -#include <liblava/core/math.hpp> #include <liblava/core/data.hpp> +#include <liblava/core/math.hpp> +#include <liblava/resource/buffer.hpp> namespace lava { -struct vertex { - - using list = std::vector<vertex>; - - v3 position; - v4 color; - v2 uv; - v3 normal; - - bool operator==(vertex const& other) const { - - return position == other.position && color == other.color && uv == other.uv && normal == other.normal; + struct vertex { + using list = std::vector<vertex>; + + v3 position; + v4 color; + v2 uv; + v3 normal; + + bool operator==(vertex const& other) const { + return position == other.position && color == other.color && uv == other.uv && normal == other.normal; + } + }; + + struct mesh_data { + vertex::list vertices; + index_list indices; + + void move(v3 position) { + for (auto& vertex : vertices) + vertex.position += position; + } + + void scale(r32 factor) { + for (auto& vertex : vertices) + vertex.position *= factor; + } + }; + + struct mesh : id_obj { + using ptr = std::shared_ptr<mesh>; + using map = std::map<id, ptr>; + using list = std::vector<ptr>; + + ~mesh() { + destroy(); + } + + bool create(device_ptr device, bool mapped = false, VmaMemoryUsage memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU); + void destroy(); + + void bind(VkCommandBuffer cmd_buf) const; + void draw(VkCommandBuffer cmd_buf) const; + + void bind_draw(VkCommandBuffer cmd_buf) const { + bind(cmd_buf); + draw(cmd_buf); + } + + device_ptr get_device() { + return device; + } + + bool empty() const { + return data.vertices.empty(); + } + + void set_data(mesh_data const& value) { + data = value; + } + mesh_data& get_data() { + return data; + } + void add_data(mesh_data const& value); + + vertex::list& get_vertices() { + return data.vertices; + } + vertex::list const& get_vertices() const { + return data.vertices; + } + ui32 get_vertices_count() const { + return to_ui32(data.vertices.size()); + } + + index_list& get_indices() { + return data.indices; + } + index_list const& get_indices() const { + return data.indices; + } + ui32 get_indices_count() const { + return to_ui32(data.indices.size()); + } + + bool reload(); + + buffer::ptr get_vertex_buffer() { + return vertex_buffer; + } + buffer::ptr get_index_buffer() { + return index_buffer; + } + + private: + device_ptr device = nullptr; + + mesh_data data; + + buffer::ptr vertex_buffer; + buffer::ptr index_buffer; + + bool mapped = false; + VmaMemoryUsage memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU; + }; + + inline mesh::ptr make_mesh() { + return std::make_shared<mesh>(); } -}; - -struct mesh_data { - - vertex::list vertices; - index_list indices; - - void move(v3 position) { - - for (auto& vertex : vertices) - vertex.position += position; - } - - void scale(r32 factor) { - - for (auto& vertex : vertices) - vertex.position *= factor; - } -}; - -struct mesh : id_obj { - - using ptr = std::shared_ptr<mesh>; - using map = std::map<id, ptr>; - using list = std::vector<ptr>; - - ~mesh() { destroy(); } - - bool create(device_ptr device, bool mapped = false, VmaMemoryUsage memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU); - void destroy(); - - void bind(VkCommandBuffer cmd_buf) const; - void draw(VkCommandBuffer cmd_buf) const; - - void bind_draw(VkCommandBuffer cmd_buf) const { - - bind(cmd_buf); - draw(cmd_buf); - } - - device_ptr get_device() { return device; } - - bool empty() const { return data.vertices.empty(); } - - void set_data(mesh_data const& value) { data = value; } - mesh_data& get_data() { return data; } - void add_data(mesh_data const& value); - - vertex::list& get_vertices() { return data.vertices; } - vertex::list const& get_vertices() const { return data.vertices; } - ui32 get_vertices_count() const { return to_ui32(data.vertices.size()); } - - index_list& get_indices() { return data.indices; } - index_list const& get_indices() const { return data.indices; } - ui32 get_indices_count() const { return to_ui32(data.indices.size()); } - - bool reload(); - - buffer::ptr get_vertex_buffer() { return vertex_buffer; } - buffer::ptr get_index_buffer() { return index_buffer; } - -private: - device_ptr device = nullptr; - - mesh_data data; - - buffer::ptr vertex_buffer; - buffer::ptr index_buffer; - - bool mapped = false; - VmaMemoryUsage memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU; -}; - -inline mesh::ptr make_mesh() { return std::make_shared<mesh>(); } - -mesh::ptr load_mesh(device_ptr device, name filename); -enum class mesh_type : type { + mesh::ptr load_mesh(device_ptr device, name filename); - none = 0, - cube, - triangle, - quad -}; + enum class mesh_type : type { -mesh::ptr load_mesh(device_ptr device, mesh_type type); + none = 0, + cube, + triangle, + quad + }; -struct mesh_meta { + mesh::ptr load_mesh(device_ptr device, mesh_type type); - string filename; // empty -> type - mesh_type type = mesh_type::none; -}; + struct mesh_meta { + string filename; // empty -> type + mesh_type type = mesh_type::none; + }; -using mesh_registry = id_registry<mesh, mesh_meta>; + using mesh_registry = id_registry<mesh, mesh_meta>; -} // lava +} // namespace lava diff --git a/liblava/resource/texture.cpp b/liblava/resource/texture.cpp index d7b2841c97f00a75671c473112acca51b3893415..8c7d0536efb9c9f1b9c580145455e862162d635c 100644 --- a/liblava/resource/texture.cpp +++ b/liblava/resource/texture.cpp @@ -2,34 +2,33 @@ // copyright : Copyright (c) 2018-present, Lava Block OÜ // license : MIT; see accompanying LICENSE file -#include <liblava/resource/texture.hpp> -#include <liblava/resource/format.hpp> - #include <bitmap_image.hpp> +#include <liblava/resource/format.hpp> +#include <liblava/resource/texture.hpp> #include <selene/img/pixel/PixelTypeAliases.hpp> #include <selene/img/typed/ImageView.hpp> #include <selene/img_ops/ImageConversions.hpp> #ifdef _WIN32 -#pragma warning(push, 4) -#pragma warning(disable : 4458) -#pragma warning(disable : 4100) -#pragma warning(disable : 5054) +# pragma warning(push, 4) +# pragma warning(disable : 4458) +# pragma warning(disable : 4100) +# pragma warning(disable : 5054) #else -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wignored-qualifiers" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wtype-limits" -#pragma GCC diagnostic ignored "-Wempty-body" -#pragma GCC diagnostic ignored "-Wunused-result" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wignored-qualifiers" +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic ignored "-Wtype-limits" +# pragma GCC diagnostic ignored "-Wempty-body" +# pragma GCC diagnostic ignored "-Wunused-result" #endif #include <gli/gli.hpp> #ifdef _WIN32 -#pragma warning(pop) +# pragma warning(pop) #else -#pragma GCC diagnostic pop +# pragma GCC diagnostic pop #endif #define STB_IMAGE_IMPLEMENTATION @@ -37,289 +36,253 @@ namespace lava { -bool texture::create(device_ptr device, uv2 size, VkFormat format, layer::list const& l, texture_type t) { - - layers = l; - type = t; - - if (layers.empty()) { + bool texture::create(device_ptr device, uv2 size, VkFormat format, layer::list const& l, texture_type t) { + layers = l; + type = t; - layer layer; + if (layers.empty()) { + layer layer; - mip_level level; - level.extent = size; + mip_level level; + level.extent = size; - layer.levels.push_back(level); - layers.push_back(layer); - } + layer.levels.push_back(level); + layers.push_back(layer); + } - VkSamplerAddressMode sampler_address_mode = VK_SAMPLER_ADDRESS_MODE_REPEAT; - if (type == texture_type::array || type == texture_type::cube_map) - sampler_address_mode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - - VkSamplerCreateInfo sampler_info - { - .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, - .magFilter = VK_FILTER_LINEAR, - .minFilter = VK_FILTER_LINEAR, - .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, - .addressModeU = sampler_address_mode, - .addressModeV = sampler_address_mode, - .addressModeW = sampler_address_mode, - .mipLodBias = 0.f, - .anisotropyEnable = device->get_features().samplerAnisotropy, - .maxAnisotropy = device->get_properties().limits.maxSamplerAnisotropy, - .compareEnable = VK_FALSE, - .compareOp = VK_COMPARE_OP_NEVER, - .minLod = 0.f, - .maxLod = to_r32(layers.front().levels.size()), - .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, - .unnormalizedCoordinates = VK_FALSE, - }; - - if (!device->vkCreateSampler(&sampler_info, &sampler)) { - - log()->error("create texture sampler"); - return false; - } + VkSamplerAddressMode sampler_address_mode = VK_SAMPLER_ADDRESS_MODE_REPEAT; + if (type == texture_type::array || type == texture_type::cube_map) + sampler_address_mode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + + VkSamplerCreateInfo sampler_info{ + .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, + .magFilter = VK_FILTER_LINEAR, + .minFilter = VK_FILTER_LINEAR, + .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, + .addressModeU = sampler_address_mode, + .addressModeV = sampler_address_mode, + .addressModeW = sampler_address_mode, + .mipLodBias = 0.f, + .anisotropyEnable = device->get_features().samplerAnisotropy, + .maxAnisotropy = device->get_properties().limits.maxSamplerAnisotropy, + .compareEnable = VK_FALSE, + .compareOp = VK_COMPARE_OP_NEVER, + .minLod = 0.f, + .maxLod = to_r32(layers.front().levels.size()), + .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, + .unnormalizedCoordinates = VK_FALSE, + }; - img = make_image(format); + if (!device->vkCreateSampler(&sampler_info, &sampler)) { + log()->error("create texture sampler"); + return false; + } - if (type == texture_type::cube_map) - img->set_flags(VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT); + img = make_image(format); - auto view_type = VK_IMAGE_VIEW_TYPE_2D; - if (type == texture_type::array) { + if (type == texture_type::cube_map) + img->set_flags(VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT); - view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; - } - else if (type == texture_type::cube_map) { + auto view_type = VK_IMAGE_VIEW_TYPE_2D; + if (type == texture_type::array) { + view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + } else if (type == texture_type::cube_map) { + view_type = VK_IMAGE_VIEW_TYPE_CUBE; + } - view_type = VK_IMAGE_VIEW_TYPE_CUBE; - } + img->set_level_count(to_ui32(layers.front().levels.size())); + img->set_layer_count(to_ui32(layers.size())); + img->set_view_type(view_type); - img->set_level_count(to_ui32(layers.front().levels.size())); - img->set_layer_count(to_ui32(layers.size())); - img->set_view_type(view_type); + if (!img->create(device, size, VMA_MEMORY_USAGE_GPU_ONLY)) { + log()->error("create texture image"); + return false; + } - if (!img->create(device, size, VMA_MEMORY_USAGE_GPU_ONLY)) { + descriptor.sampler = sampler; + descriptor.imageView = img->get_view(); + descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - log()->error("create texture image"); - return false; + return true; } - descriptor.sampler = sampler; - descriptor.imageView = img->get_view(); - descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - return true; -} + void texture::destroy() { + destroy_upload_buffer(); -void texture::destroy() { + if (sampler) { + if (img) + if (auto device = img->get_device()) + device->vkDestroySampler(sampler); - destroy_upload_buffer(); - - if (sampler) { - - if (img) - if (auto device = img->get_device()) - device->vkDestroySampler(sampler); + sampler = 0; + } - sampler = 0; + if (img) { + img->destroy(); + img = nullptr; + } } - if (img) { - - img->destroy(); - img = nullptr; + void texture::destroy_upload_buffer() { + upload_buffer = nullptr; } -} - -void texture::destroy_upload_buffer() { - - upload_buffer = nullptr; -} - -bool texture::upload(void const* data, size_t data_size) { - upload_buffer = make_buffer(); + bool texture::upload(void const* data, size_t data_size) { + upload_buffer = make_buffer(); - return upload_buffer->create(img->get_device(), data, data_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, false, VMA_MEMORY_USAGE_CPU_TO_GPU); -} - -bool texture::stage(VkCommandBuffer cmd_buffer) { - - if (!upload_buffer || !upload_buffer->valid()) { - - log()->error("stage texture"); - return false; + return upload_buffer->create(img->get_device(), data, data_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, false, VMA_MEMORY_USAGE_CPU_TO_GPU); } - VkImageSubresourceRange subresource_range - { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = to_ui32(layers.front().levels.size()), - .baseArrayLayer = 0, - .layerCount = to_ui32(layers.size()), - }; - - auto device = img->get_device(); - - set_image_layout(device, cmd_buffer, img->get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresource_range, - VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + bool texture::stage(VkCommandBuffer cmd_buffer) { + if (!upload_buffer || !upload_buffer->valid()) { + log()->error("stage texture"); + return false; + } - std::vector<VkBufferImageCopy> regions; + VkImageSubresourceRange subresource_range{ + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = to_ui32(layers.front().levels.size()), + .baseArrayLayer = 0, + .layerCount = to_ui32(layers.size()), + }; - if (to_ui32(layers.front().levels.size()) > 1) { + auto device = img->get_device(); - auto offset = 0u; + set_image_layout(device, cmd_buffer, img->get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresource_range, + VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - for (auto layer = 0u; layer < layers.size(); ++layer) { + std::vector<VkBufferImageCopy> regions; - for (auto level = 0u; level < to_ui32(layers.front().levels.size()); ++level) { + if (to_ui32(layers.front().levels.size()) > 1) { + auto offset = 0u; - VkImageSubresourceLayers image_subresource - { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = level, - .baseArrayLayer = layer, - .layerCount = 1, - }; + for (auto layer = 0u; layer < layers.size(); ++layer) { + for (auto level = 0u; level < to_ui32(layers.front().levels.size()); ++level) { + VkImageSubresourceLayers image_subresource{ + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = level, + .baseArrayLayer = layer, + .layerCount = 1, + }; - VkExtent3D image_extent - { - .width = layers[layer].levels[level].extent.x, - .height = layers[layer].levels[level].extent.y, - .depth = 1, - }; + VkExtent3D image_extent{ + .width = layers[layer].levels[level].extent.x, + .height = layers[layer].levels[level].extent.y, + .depth = 1, + }; - VkBufferImageCopy buffer_copy_region - { - .bufferOffset = offset, - .imageSubresource = image_subresource, - .imageExtent = image_extent, - }; + VkBufferImageCopy buffer_copy_region{ + .bufferOffset = offset, + .imageSubresource = image_subresource, + .imageExtent = image_extent, + }; - regions.push_back(buffer_copy_region); + regions.push_back(buffer_copy_region); - offset += layers[layer].levels[level].size; + offset += layers[layer].levels[level].size; + } } + } else { + VkImageSubresourceLayers subresource_layers{ + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = to_ui32(layers.size()), + }; + + auto size = img->get_size(); + + VkBufferImageCopy region{ + .bufferOffset = 0, + .bufferRowLength = size.x, + .bufferImageHeight = size.y, + .imageSubresource = subresource_layers, + .imageOffset = {}, + .imageExtent = { size.x, size.y, 1 }, + }; + + regions.push_back(region); } - } - else { - VkImageSubresourceLayers subresource_layers - { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = to_ui32(layers.size()), - }; + device->call().vkCmdCopyBufferToImage(cmd_buffer, upload_buffer->get(), img->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + to_ui32(regions.size()), regions.data()); - auto size = img->get_size(); + set_image_layout(device, cmd_buffer, img->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresource_range, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - VkBufferImageCopy region - { - .bufferOffset = 0, - .bufferRowLength = size.x, - .bufferImageHeight = size.y, - .imageSubresource = subresource_layers, - .imageOffset = {}, - .imageExtent = { size.x, size.y, 1 }, - }; - - regions.push_back(region); + return true; } - device->call().vkCmdCopyBufferToImage(cmd_buffer, upload_buffer->get(), img->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - to_ui32(regions.size()), regions.data()); - - set_image_layout(device, cmd_buffer, img->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresource_range, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + bool staging::stage(VkCommandBuffer cmd_buf, index frame) { + if (!staged.empty() && staged.count(frame) && !staged.at(frame).empty()) { + for (auto& texture : staged.at(frame)) + texture->destroy_upload_buffer(); - return true; -} - -bool staging::stage(VkCommandBuffer cmd_buf, index frame) { + staged.erase(frame); + } - if (!staged.empty() && staged.count(frame) && !staged.at(frame).empty()) { + if (todo.empty()) + return false; - for (auto& texture : staged.at(frame)) - texture->destroy_upload_buffer(); + texture::list stage_done; - staged.erase(frame); - } + for (auto& texture : todo) { + if (!texture->stage(cmd_buf)) + continue; - if (todo.empty()) - return false; + stage_done.push_back(texture); + } - texture::list stage_done; + if (!staged.count(frame)) + staged.emplace(frame, texture::list()); - for (auto& texture : todo) { + for (auto& texture : stage_done) { + if (!contains(staged.at(frame), texture)) + staged.at(frame).push_back(texture); - if (!texture->stage(cmd_buf)) - continue; + remove(todo, texture); + } - stage_done.push_back(texture); + return true; } - if (!staged.count(frame)) - staged.emplace(frame, texture::list()); - - for (auto& texture : stage_done) { + scope_image::scope_image(string_ref filename) + : image_file(str(filename)), file_data(image_file.get_size(), false) { + if (image_file.opened()) { + if (!file_data.allocate()) + return; - if (!contains(staged.at(frame), texture)) - staged.at(frame).push_back(texture); - - remove(todo, texture); - } - - return true; -} + if (file_error(image_file.read(file_data.ptr))) + return; + } -scope_image::scope_image(string_ref filename) : image_file(str(filename)), file_data(image_file.get_size(), false) { + i32 tex_width, tex_height, tex_channels = 0; - if (image_file.opened()) { + if (image_file.opened()) + data = as_ptr(stbi_load_from_memory((stbi_uc const*) file_data.ptr, to_i32(file_data.size), + &tex_width, &tex_height, &tex_channels, STBI_rgb_alpha)); + else + data = as_ptr(stbi_load(str(filename), &tex_width, &tex_height, &tex_channels, STBI_rgb_alpha)); - if (!file_data.allocate()) + if (!data) return; - if (file_error(image_file.read(file_data.ptr))) - return; + size = { tex_width, tex_height }; + channels = tex_channels; + ready = true; } - i32 tex_width, tex_height, tex_channels = 0; - - if (image_file.opened()) - data = as_ptr(stbi_load_from_memory((stbi_uc const*)file_data.ptr, to_i32(file_data.size), - &tex_width, &tex_height, &tex_channels, STBI_rgb_alpha)); - else - data = as_ptr(stbi_load(str(filename), &tex_width, &tex_height, &tex_channels, STBI_rgb_alpha)); - - if (!data) - return; - - size = { tex_width, tex_height }; - channels = tex_channels; - ready = true; -} - -scope_image::~scope_image() { - - if (data) - stbi_image_free(data); -} + scope_image::~scope_image() { + if (data) + stbi_image_free(data); + } -} // lava +} // namespace lava lava::texture::ptr lava::load_texture(device_ptr device, file_format filename, texture_type type) { - - auto supported = (filename.format == VK_FORMAT_R8G8B8A8_UNORM) || - (device->get_features().textureCompressionBC && (filename.format == VK_FORMAT_BC3_UNORM_BLOCK)) || - (device->get_features().textureCompressionASTC_LDR && (filename.format == VK_FORMAT_ASTC_8x8_UNORM_BLOCK)) || - (device->get_features().textureCompressionETC2 && (filename.format == VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK)); + auto supported = (filename.format == VK_FORMAT_R8G8B8A8_UNORM) || (device->get_features().textureCompressionBC && (filename.format == VK_FORMAT_BC3_UNORM_BLOCK)) || (device->get_features().textureCompressionASTC_LDR && (filename.format == VK_FORMAT_ASTC_8x8_UNORM_BLOCK)) || (device->get_features().textureCompressionETC2 && (filename.format == VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK)); if (!supported) return nullptr; @@ -336,7 +299,6 @@ lava::texture::ptr lava::load_texture(device_ptr device, file_format filename, t scope_data temp_data(file.get_size(), false); if (file.opened()) { - if (!temp_data.allocate()) return nullptr; @@ -347,126 +309,115 @@ lava::texture::ptr lava::load_texture(device_ptr device, file_format filename, t auto texture = make_texture(); if (use_gli) { - texture::layer::list layers; switch (type) { + case texture_type::tex_2d: { + gli::texture2d tex(file.opened() ? gli::load(temp_data.ptr, temp_data.size) + : gli::load(filename.path)); + assert(!tex.empty()); + if (tex.empty()) + return nullptr; - case texture_type::tex_2d: { - - gli::texture2d tex(file.opened() ? gli::load(temp_data.ptr, temp_data.size) - : gli::load(filename.path)); - assert(!tex.empty()); - if (tex.empty()) - return nullptr; - - auto mip_levels = to_ui32(tex.levels()); - - texture::layer layer; - - for (auto m = 0u; m < mip_levels; ++m) { - - texture::mip_level level; - level.extent = { tex[m].extent().x, tex[m].extent().y }; - level.size = to_ui32(tex[m].size()); + auto mip_levels = to_ui32(tex.levels()); - layer.levels.push_back(level); - } + texture::layer layer; - layers.push_back(layer); + for (auto m = 0u; m < mip_levels; ++m) { + texture::mip_level level; + level.extent = { tex[m].extent().x, tex[m].extent().y }; + level.size = to_ui32(tex[m].size()); - uv2 size = { tex[0].extent().x, tex[0].extent().y }; - if (!texture->create(device, size, filename.format, layers, type)) - return nullptr; - - if (!texture->upload(tex.data(), tex.size())) - return nullptr; - - break; + layer.levels.push_back(level); } - case texture_type::array: { + layers.push_back(layer); - gli::texture2d_array tex(file.opened() ? gli::load(temp_data.ptr, temp_data.size) - : gli::load(filename.path)); - assert(!tex.empty()); - if (tex.empty()) - return nullptr; + uv2 size = { tex[0].extent().x, tex[0].extent().y }; + if (!texture->create(device, size, filename.format, layers, type)) + return nullptr; - auto layer_count = to_ui32(tex.layers()); - auto mip_levels = to_ui32(tex.levels()); + if (!texture->upload(tex.data(), tex.size())) + return nullptr; - for (auto i = 0u; i < layer_count; ++i) { + break; + } - texture::layer layer; + case texture_type::array: { + gli::texture2d_array tex(file.opened() ? gli::load(temp_data.ptr, temp_data.size) + : gli::load(filename.path)); + assert(!tex.empty()); + if (tex.empty()) + return nullptr; - for (auto m = 0u; m < mip_levels; ++m) { + auto layer_count = to_ui32(tex.layers()); + auto mip_levels = to_ui32(tex.levels()); - texture::mip_level level; - level.extent = { tex[i][m].extent().x, tex[i][m].extent().y }; - level.size = to_ui32(tex[i][m].size()); + for (auto i = 0u; i < layer_count; ++i) { + texture::layer layer; - layer.levels.push_back(level); - } + for (auto m = 0u; m < mip_levels; ++m) { + texture::mip_level level; + level.extent = { tex[i][m].extent().x, tex[i][m].extent().y }; + level.size = to_ui32(tex[i][m].size()); - layers.push_back(layer); + layer.levels.push_back(level); } - uv2 size = { tex[0].extent().x, tex[0].extent().y }; - if (!texture->create(device, size, filename.format, layers, type)) - return nullptr; - - if (!texture->upload(tex.data(), tex.size())) - return nullptr; - - break; + layers.push_back(layer); } - case texture_type::cube_map: { + uv2 size = { tex[0].extent().x, tex[0].extent().y }; + if (!texture->create(device, size, filename.format, layers, type)) + return nullptr; - gli::texture_cube tex(file.opened() ? gli::load(temp_data.ptr, temp_data.size) - : gli::load(filename.path)); - assert(!tex.empty()); - if (tex.empty()) - return nullptr; + if (!texture->upload(tex.data(), tex.size())) + return nullptr; - auto layer_count = to_ui32(tex.faces()); - auto mip_levels = to_ui32(tex.levels()); - - for (auto i = 0u; i < layer_count; ++i) { + break; + } - texture::layer layer; + case texture_type::cube_map: { + gli::texture_cube tex(file.opened() ? gli::load(temp_data.ptr, temp_data.size) + : gli::load(filename.path)); + assert(!tex.empty()); + if (tex.empty()) + return nullptr; - for (auto m = 0u; m < mip_levels; ++m) { + auto layer_count = to_ui32(tex.faces()); + auto mip_levels = to_ui32(tex.levels()); - texture::mip_level level; - level.extent = { tex[i][m].extent().x, tex[i][m].extent().y }; - level.size = to_ui32(tex[i][m].size()); + for (auto i = 0u; i < layer_count; ++i) { + texture::layer layer; - layer.levels.push_back(level); - } + for (auto m = 0u; m < mip_levels; ++m) { + texture::mip_level level; + level.extent = { tex[i][m].extent().x, tex[i][m].extent().y }; + level.size = to_ui32(tex[i][m].size()); - layers.push_back(layer); + layer.levels.push_back(level); } - uv2 size = { tex[0].extent().x, tex[0].extent().y }; - if (!texture->create(device, size, filename.format, layers, type)) - return nullptr; + layers.push_back(layer); + } - if (!texture->upload(tex.data(), tex.size())) - return nullptr; + uv2 size = { tex[0].extent().x, tex[0].extent().y }; + if (!texture->create(device, size, filename.format, layers, type)) + return nullptr; - break; - } + if (!texture->upload(tex.data(), tex.size())) + return nullptr; + + break; } - } - else { // use_stbi + } + } else { // use_stbi i32 tex_width = 0, tex_height = 0; stbi_uc* data = nullptr; if (file.opened()) - data = stbi_load_from_memory((stbi_uc const*)temp_data.ptr, to_i32(temp_data.size), + data = stbi_load_from_memory((stbi_uc const*) temp_data.ptr, to_i32(temp_data.size), &tex_width, &tex_height, nullptr, STBI_rgb_alpha); else data = stbi_load(str(filename.path), &tex_width, &tex_height, nullptr, STBI_rgb_alpha); @@ -492,7 +443,6 @@ lava::texture::ptr lava::load_texture(device_ptr device, file_format filename, t } lava::texture::ptr lava::create_default_texture(device_ptr device, uv2 size) { - auto result = make_texture(); if (!result->create(device, size, VK_FORMAT_R8G8B8A8_UNORM)) @@ -503,9 +453,9 @@ lava::texture::ptr lava::create_default_texture(device_ptr device, uv2 size) { image.bgr_to_rgb(); - sln::TypedLayout typed_layout((sln::PixelLength)size.x, (sln::PixelLength)size.y, (sln::Stride)(image.width() * image.bytes_per_pixel())); + sln::TypedLayout typed_layout((sln::PixelLength) size.x, (sln::PixelLength) size.y, (sln::Stride)(image.width() * image.bytes_per_pixel())); - sln::ImageView<sln::PixelRGB_8u, sln::ImageModifiability::Mutable> img_rgb((uint8_t*)image.data(), typed_layout); + sln::ImageView<sln::PixelRGB_8u, sln::ImageModifiability::Mutable> img_rgb((uint8_t*) image.data(), typed_layout); sln::Image<sln::PixelRGBA_8u> const img_rgba = sln::convert_image<sln::PixelFormat::RGBA>(img_rgb, std::uint8_t{ 192 }); diff --git a/liblava/resource/texture.hpp b/liblava/resource/texture.hpp index ea36355f5aec9d726c4eaf9f4a265cd06f2697e7..3e3ce2eb485eb31eef16ebb5f41eb9616859e0ea 100644 --- a/liblava/resource/texture.hpp +++ b/liblava/resource/texture.hpp @@ -9,120 +9,136 @@ namespace lava { -enum class texture_type : type { + enum class texture_type : type { - none = 0, - tex_2d, - array, - cube_map -}; - -struct file_format { - - using list = std::vector<file_format>; - - string path; - VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; -}; - -struct texture : id_obj { - - using ptr = std::shared_ptr<texture>; - using map = std::map<id, ptr>; - using list = std::vector<ptr>; - - struct mip_level { + none = 0, + tex_2d, + array, + cube_map + }; - using list = std::vector<mip_level>; + struct file_format { + using list = std::vector<file_format>; - uv2 extent; - ui32 size = 0; + string path; + VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; }; - struct layer { - - using list = std::vector<layer>; + struct texture : id_obj { + using ptr = std::shared_ptr<texture>; + using map = std::map<id, ptr>; + using list = std::vector<ptr>; - mip_level::list levels; - }; + struct mip_level { + using list = std::vector<mip_level>; - ~texture() { destroy(); } + uv2 extent; + ui32 size = 0; + }; - bool create(device_ptr device, uv2 size, VkFormat format, - layer::list const& layers = {}, texture_type type = texture_type::tex_2d); - void destroy(); + struct layer { + using list = std::vector<layer>; - bool upload(void const* data, size_t data_size); - bool stage(VkCommandBuffer cmd_buffer); - void destroy_upload_buffer(); + mip_level::list levels; + }; - VkDescriptorImageInfo const* get_descriptor() const { return &descriptor; } - VkDescriptorImageInfo const* get_info() const { return get_descriptor(); } + ~texture() { + destroy(); + } - image::ptr get_image() { return img; } + bool create(device_ptr device, uv2 size, VkFormat format, + layer::list const& layers = {}, texture_type type = texture_type::tex_2d); + void destroy(); - uv2 get_size() const { return img ? img->get_size() : uv2(); } - texture_type get_type() const { return type; } + bool upload(void const* data, size_t data_size); + bool stage(VkCommandBuffer cmd_buffer); + void destroy_upload_buffer(); - VkFormat get_format() const { return img ? img->get_format() : VK_FORMAT_UNDEFINED; } + VkDescriptorImageInfo const* get_descriptor() const { + return &descriptor; + } + VkDescriptorImageInfo const* get_info() const { + return get_descriptor(); + } -private: - image::ptr img; + image::ptr get_image() { + return img; + } - texture_type type = texture_type::none; - layer::list layers; + uv2 get_size() const { + return img ? img->get_size() : uv2(); + } + texture_type get_type() const { + return type; + } - VkSampler sampler = 0; - VkDescriptorImageInfo descriptor = {}; + VkFormat get_format() const { + return img ? img->get_format() : VK_FORMAT_UNDEFINED; + } - buffer::ptr upload_buffer; -}; + private: + image::ptr img; -inline texture::ptr make_texture() { return std::make_shared<texture>(); } + texture_type type = texture_type::none; + layer::list layers; -texture::ptr load_texture(device_ptr device, file_format filename, texture_type type = texture_type::tex_2d); + VkSampler sampler = 0; + VkDescriptorImageInfo descriptor = {}; -inline texture::ptr load_texture(device_ptr device, string_ref filename, - VkFormat format = VK_FORMAT_R8G8B8A8_UNORM, texture_type type = texture_type::tex_2d) { + buffer::ptr upload_buffer; + }; - return load_texture(device, { filename, format }, type); -} + inline texture::ptr make_texture() { + return std::make_shared<texture>(); + } -texture::ptr create_default_texture(device_ptr device, uv2 size = { 512, 512}); + texture::ptr load_texture(device_ptr device, file_format filename, texture_type type = texture_type::tex_2d); -struct staging { + inline texture::ptr load_texture(device_ptr device, string_ref filename, + VkFormat format = VK_FORMAT_R8G8B8A8_UNORM, texture_type type = texture_type::tex_2d) { + return load_texture(device, { filename, format }, type); + } - void add(texture::ptr texture) { todo.push_back(texture); } + texture::ptr create_default_texture(device_ptr device, uv2 size = { 512, 512 }); - bool stage(VkCommandBuffer cmd_buf, index frame); + struct staging { + void add(texture::ptr texture) { + todo.push_back(texture); + } - void clear() { todo.clear(); staged.clear(); } + bool stage(VkCommandBuffer cmd_buf, index frame); - bool busy() const { return !todo.empty() || !staged.empty(); } + void clear() { + todo.clear(); + staged.clear(); + } -private: - texture::list todo; + bool busy() const { + return !todo.empty() || !staged.empty(); + } - using frame_stage_map = std::map<index, texture::list>; - frame_stage_map staged; -}; + private: + texture::list todo; -using texture_registry = id_registry<texture, file_format>; + using frame_stage_map = std::map<index, texture::list>; + frame_stage_map staged; + }; -struct scope_image { + using texture_registry = id_registry<texture, file_format>; - explicit scope_image(string_ref filename); - ~scope_image(); + struct scope_image { + explicit scope_image(string_ref filename); + ~scope_image(); - bool ready = false; + bool ready = false; - data_ptr data = nullptr; - uv2 size = uv2(0, 0); - ui32 channels = 0; + data_ptr data = nullptr; + uv2 size = uv2(0, 0); + ui32 channels = 0; -private: - file image_file; - scope_data file_data; -}; + private: + file image_file; + scope_data file_data; + }; -} // lava +} // namespace lava diff --git a/liblava/util/file.cpp b/liblava/util/file.cpp index d7b9c1304e2102865a981cf4f243009167cfa52c..d304b040f4a25a98b5681480b3c9cc253ccb8a33 100644 --- a/liblava/util/file.cpp +++ b/liblava/util/file.cpp @@ -2,13 +2,11 @@ // copyright : Copyright (c) 2018-present, Lava Block OÜ // license : MIT; see accompanying LICENSE file +#include <physfs.h> #include <liblava/util/file.hpp> #include <liblava/util/utility.hpp> -#include <physfs.h> - bool lava::read_file(std::vector<char>& out, name filename) { - std::ifstream file(filename, std::ios::ate | std::ios::binary); assert(file.is_open()); @@ -19,7 +17,6 @@ bool lava::read_file(std::vector<char>& out, name filename) { auto file_size = to_size_t(file.tellg()); if (file_size > 0) { - out.resize(file_size); file.seekg(0, std::ios::beg); file.read(out.data(), file_size); @@ -30,7 +27,6 @@ bool lava::read_file(std::vector<char>& out, name filename) { } bool lava::write_file(name filename, char const* data, size_t data_size) { - std::ofstream file(filename, std::ofstream::binary); assert(file.is_open()); @@ -43,7 +39,6 @@ bool lava::write_file(name filename, char const* data, size_t data_size) { } bool lava::extension(name file_name, name extension) { - string fn = file_name; string ext = extension; @@ -56,7 +51,6 @@ bool lava::extension(name file_name, name extension) { } bool lava::extension(name filename, names extensions) { - for (auto& ex : extensions) if (extension(filename, ex)) return true; @@ -65,16 +59,13 @@ bool lava::extension(name filename, names extensions) { } lava::string lava::get_filename_from(string_ref path, bool with_extension) { - fs::path target(path); return with_extension ? target.filename().string() : target.stem().string(); } bool lava::remove_existing_path(string& target, string_ref path) { - auto pos = target.find(path); if (pos != std::string::npos) { - target.erase(pos, path.length()); #ifdef _WIN32 @@ -89,290 +80,274 @@ bool lava::remove_existing_path(string& target, string_ref path) { namespace lava { -internal_version file_system::get_version() { + internal_version file_system::get_version() { + PHYSFS_Version result; + PHYSFS_getLinkedVersion(&result); - PHYSFS_Version result; - PHYSFS_getLinkedVersion(&result); + return { result.major, result.minor, result.patch }; + } - return { result.major, result.minor, result.patch }; -} + name file_system::get_base_dir() { + return PHYSFS_getBaseDir(); + } -name file_system::get_base_dir() { return PHYSFS_getBaseDir(); } + string file_system::get_base_dir_str() { + return string(get_base_dir()); + } -string file_system::get_base_dir_str() { return string(get_base_dir()); } + name file_system::get_pref_dir() { + return PHYSFS_getPrefDir(instance().org, instance().app); + } -name file_system::get_pref_dir() { return PHYSFS_getPrefDir(instance().org, instance().app); } + string file_system::get_res_dir() { + string res_dir = get_base_dir(); + res_dir += instance().res_path; + string_ref const_res_dir = res_dir; -string file_system::get_res_dir() { + return fs::path(const_res_dir).lexically_normal().string(); + } - string res_dir = get_base_dir(); - res_dir += instance().res_path; - string_ref const_res_dir = res_dir; + bool file_system::mount(string_ref path) { + return PHYSFS_mount(str(path), nullptr, 1) != 0; + } - return fs::path(const_res_dir).lexically_normal().string(); -} + bool file_system::mount(name base_dir_path) { + return mount(get_base_dir_str() + base_dir_path); + } -bool file_system::mount(string_ref path) { return PHYSFS_mount(str(path), nullptr, 1) != 0; } + bool file_system::exists(name file) { + return PHYSFS_exists(file) != 0; + } -bool file_system::mount(name base_dir_path) { return mount(get_base_dir_str() + base_dir_path); } + name file_system::get_real_dir(name file) { + return PHYSFS_getRealDir(file); + } -bool file_system::exists(name file) { return PHYSFS_exists(file) != 0; } + string_list file_system::enumerate_files(name path) { + string_list result; -name file_system::get_real_dir(name file) { return PHYSFS_getRealDir(file); } + auto rc = PHYSFS_enumerateFiles(path); + for (auto i = rc; *i != nullptr; ++i) + result.push_back(*i); -string_list file_system::enumerate_files(name path) { + PHYSFS_freeList(rc); - string_list result; + return result; + } - auto rc = PHYSFS_enumerateFiles(path); - for (auto i = rc; *i != nullptr; ++i) - result.push_back(*i); + bool file_system::initialize(name argv_0, name o, name a, name e) { + assert(!initialized); // only once + if (initialized) + return initialized; - PHYSFS_freeList(rc); + if (!initialized) { + PHYSFS_init(argv_0); - return result; -} + PHYSFS_setSaneConfig(o, a, e, 0, 0); + initialized = true; -bool file_system::initialize(name argv_0, name o, name a, name e) { + org = o; + app = a; + ext = e; + } - assert(!initialized); // only once - if (initialized) return initialized; - - if (!initialized) { - - PHYSFS_init(argv_0); - - PHYSFS_setSaneConfig(o, a, e, 0, 0); - initialized = true; - - org = o; - app = a; - ext = e; } - return initialized; -} - -void file_system::terminate() { - - if (!initialized) - return; - - PHYSFS_deinit(); -} + void file_system::terminate() { + if (!initialized) + return; -void file_system::mount_res() { + PHYSFS_deinit(); + } + void file_system::mount_res() { #if LIBLAVA_DEBUG -#if _WIN32 - res_path = "../../res/"; -#else - res_path = "../res/"; -#endif +# if _WIN32 + res_path = "../../res/"; +# else + res_path = "../res/"; +# endif #else - res_path = "res/"; + res_path = "res/"; #endif - if (fs::exists(str(get_res_dir()))) - if (file_system::mount(str(res_path))) - log()->debug("mount {}", str(get_res_dir())); - - auto cwd_res_dir = fs::current_path().append("res/").lexically_normal().string(); - - if (fs::exists(cwd_res_dir) && (cwd_res_dir != get_res_dir())) - if (file_system::mount(cwd_res_dir)) - log()->debug("mount {}", str(cwd_res_dir)); - - string archive_file = "res.zip"; - if (fs::exists({ archive_file })) - if (file_system::mount(str(archive_file))) - log()->debug("mount {}", str(archive_file)); -} - -bool file_system::create_data_folder() { - - fs::path data_path = fs::current_path(); - data_path += fs::path::preferred_separator; - data_path += "data"; - - if (!fs::exists(data_path)) - fs::create_directories(data_path); - - return fs::exists(data_path); -} - -file::file(name p, bool write) { open(p, write); } + if (fs::exists(str(get_res_dir()))) + if (file_system::mount(str(res_path))) + log()->debug("mount {}", str(get_res_dir())); -file::~file() { close(); } + auto cwd_res_dir = fs::current_path().append("res/").lexically_normal().string(); -bool file::open(name p, bool write) { + if (fs::exists(cwd_res_dir) && (cwd_res_dir != get_res_dir())) + if (file_system::mount(cwd_res_dir)) + log()->debug("mount {}", str(cwd_res_dir)); - if (!p) - return false; - - path = p; - write_mode = write; - - if (write_mode) - fs_file = PHYSFS_openWrite(path); - else - fs_file = PHYSFS_openRead(path); - - if (fs_file) { - - type = file_type::fs; + string archive_file = "res.zip"; + if (fs::exists({ archive_file })) + if (file_system::mount(str(archive_file))) + log()->debug("mount {}", str(archive_file)); } - else { - if (write) { + bool file_system::create_data_folder() { + fs::path data_path = fs::current_path(); + data_path += fs::path::preferred_separator; + data_path += "data"; - o_stream = std::ofstream(path, std::ofstream::binary); - if (o_stream.is_open()) - type = file_type::f_stream; - } - else { + if (!fs::exists(data_path)) + fs::create_directories(data_path); - i_stream = std::ifstream(path, std::ios::binary | std::ios::ate); - if (i_stream.is_open()) - type = file_type::f_stream; - } + return fs::exists(data_path); } - return opened(); -} + file::file(name p, bool write) { + open(p, write); + } -void file::close() { + file::~file() { + close(); + } - if (type == file_type::fs) { + bool file::open(name p, bool write) { + if (!p) + return false; - PHYSFS_close(fs_file); - } - else if (type == file_type::f_stream) { + path = p; + write_mode = write; if (write_mode) - o_stream.close(); + fs_file = PHYSFS_openWrite(path); else - i_stream.close(); - } -} - -bool file::opened() const { - - if (type == file_type::fs) { + fs_file = PHYSFS_openRead(path); + + if (fs_file) { + type = file_type::fs; + } else { + if (write) { + o_stream = std::ofstream(path, std::ofstream::binary); + if (o_stream.is_open()) + type = file_type::f_stream; + } else { + i_stream = std::ifstream(path, std::ios::binary | std::ios::ate); + if (i_stream.is_open()) + type = file_type::f_stream; + } + } - return fs_file != nullptr; + return opened(); } - else if (type == file_type::f_stream) { - if (write_mode) - return o_stream.is_open(); - else - return i_stream.is_open(); + void file::close() { + if (type == file_type::fs) { + PHYSFS_close(fs_file); + } else if (type == file_type::f_stream) { + if (write_mode) + o_stream.close(); + else + i_stream.close(); + } } - return false; -} + bool file::opened() const { + if (type == file_type::fs) { + return fs_file != nullptr; + } else if (type == file_type::f_stream) { + if (write_mode) + return o_stream.is_open(); + else + return i_stream.is_open(); + } -i64 file::get_size() const { + return false; + } - if (type == file_type::fs) { + i64 file::get_size() const { + if (type == file_type::fs) { + return PHYSFS_fileLength(fs_file); + } else if (type == file_type::f_stream) { + if (write_mode) + return to_i64(o_stream.tellp()); + else + return to_i64(i_stream.tellg()); + } - return PHYSFS_fileLength(fs_file); + return file_error_result; } - else if (type == file_type::f_stream) { + i64 file::read(data_ptr data, ui64 size) { if (write_mode) - return to_i64(o_stream.tellp()); - else - return to_i64(i_stream.tellg()); - } - - return file_error_result; -} - -i64 file::read(data_ptr data, ui64 size) { + return file_error_result; + + if (type == file_type::fs) { + return PHYSFS_readBytes(fs_file, data, size); + } else if (type == file_type::f_stream) { + i_stream.seekg(0, std::ios::beg); + i_stream.read(data, size); + return to_i64(size); + } - if (write_mode) return file_error_result; - - if (type == file_type::fs) { - - return PHYSFS_readBytes(fs_file, data, size); - } - else if (type == file_type::f_stream) { - - i_stream.seekg(0, std::ios::beg); - i_stream.read(data, size); - return to_i64(size); } - return file_error_result; -} + i64 file::write(data_cptr data, ui64 size) { + if (!write_mode) + return file_error_result; -i64 file::write(data_cptr data, ui64 size) { + if (type == file_type::fs) { + return PHYSFS_writeBytes(fs_file, data, size); + } else if (type == file_type::f_stream) { + o_stream.write(data, size); + return to_i64(size); + } - if (!write_mode) return file_error_result; + } - if (type == file_type::fs) { + json_file::json_file(name path) + : path(path) {} - return PHYSFS_writeBytes(fs_file, data, size); + void json_file::add(file_callback* callback) { + callbacks.push_back(callback); } - else if (type == file_type::f_stream) { - o_stream.write(data, size); - return to_i64(size); + void json_file::remove(file_callback* callback) { + lava::remove(callbacks, callback); } - return file_error_result; -} + bool json_file::load() { + scope_data data; + if (!load_file_data(path, data)) + return false; -json_file::json_file(name path) : path(path) {} + auto j = json::parse({ data.ptr, data.size }); -void json_file::add(file_callback* callback) { callbacks.push_back(callback); } + for (auto callback : callbacks) + callback->on_load(j); -void json_file::remove(file_callback* callback) { lava::remove(callbacks, callback); } - -bool json_file::load() { - - scope_data data; - if (!load_file_data(path, data)) - return false; + return true; + } - auto j = json::parse({ data.ptr, data.size }); + bool json_file::save() { + file file(str(path), true); + if (!file.opened()) { + log()->error("save file {}", str(path)); + return false; + } - for (auto callback : callbacks) - callback->on_load(j); + json j; - return true; -} + for (auto callback : callbacks) + callback->on_save(j); -bool json_file::save() { + auto jString = j.dump(4); - file file(str(path), true); - if (!file.opened()) { + file.write(jString.data(), jString.size()); - log()->error("save file {}", str(path)); - return false; + return true; } - json j; - - for (auto callback : callbacks) - callback->on_save(j); - - auto jString = j.dump(4); - - file.write(jString.data(), jString.size()); - - return true; -} - -} // lava +} // namespace lava bool lava::load_file_data(string_ref filename, data& target) { - file file(str(filename)); if (!file.opened()) return false; @@ -382,7 +357,6 @@ bool lava::load_file_data(string_ref filename, data& target) { return false; if (file_error(file.read(target.ptr))) { - log()->error("read file {}", filename); return false; } diff --git a/liblava/util/file.hpp b/liblava/util/file.hpp index a75ed6d5163191495b29a1d5294e00208fc9f3f4..160813244436f9b680af2146705be667e4987c90 100644 --- a/liblava/util/file.hpp +++ b/liblava/util/file.hpp @@ -4,12 +4,10 @@ #pragma once +#include <filesystem> +#include <fstream> #include <liblava/core/data.hpp> #include <liblava/util/log.hpp> - -#include <fstream> -#include <filesystem> - #include <nlohmann/json.hpp> // fwd @@ -17,165 +15,185 @@ struct PHYSFS_File; namespace lava { -constexpr name _zip_ = "zip"; -constexpr name _config_file_ = "config.json"; - -using json = nlohmann::json; + constexpr name _zip_ = "zip"; + constexpr name _config_file_ = "config.json"; -namespace fs = std::filesystem; + using json = nlohmann::json; -bool read_file(std::vector<char>& out, name filename); + namespace fs = std::filesystem; -bool write_file(name filename, char const* data, size_t data_size); + bool read_file(std::vector<char>& out, name filename); -bool extension(name file_name, name extension); + bool write_file(name filename, char const* data, size_t data_size); -bool extension(name filename, names extensions); + bool extension(name file_name, name extension); -string get_filename_from(string_ref path, bool with_extension = false); + bool extension(name filename, names extensions); -bool remove_existing_path(string& target, string_ref path); + string get_filename_from(string_ref path, bool with_extension = false); -struct file_guard : no_copy_no_move { + bool remove_existing_path(string& target, string_ref path); - explicit file_guard(name filename = "") : filename(filename) {} - explicit file_guard(string filename) : filename(filename) {} + struct file_guard : no_copy_no_move { + explicit file_guard(name filename = "") + : filename(filename) {} + explicit file_guard(string filename) + : filename(filename) {} - ~file_guard() { + ~file_guard() { + if (remove) + fs::remove(filename); + } - if (remove) - fs::remove(filename); - } + string filename; + bool remove = true; + }; - string filename; - bool remove = true; -}; + struct file_system : no_copy_no_move { + static file_system& instance() { + static file_system fs; + return fs; + } -struct file_system : no_copy_no_move { + static internal_version get_version(); - static file_system& instance() { + static name get_base_dir(); + static string get_base_dir_str(); + static name get_pref_dir(); + static string get_res_dir(); - static file_system fs; - return fs; - } + static bool mount(string_ref path); + static bool mount(name base_dir_path); + static bool exists(name file); + static name get_real_dir(name file); + static string_list enumerate_files(name path); - static internal_version get_version(); + bool initialize(name argv_0, name org, name app, name ext); + void terminate(); - static name get_base_dir(); - static string get_base_dir_str(); - static name get_pref_dir(); - static string get_res_dir(); + void mount_res(); + bool create_data_folder(); - static bool mount(string_ref path); - static bool mount(name base_dir_path); - static bool exists(name file); - static name get_real_dir(name file); - static string_list enumerate_files(name path); + name get_org() const { + return org; + } + name get_app() const { + return app; + } + name get_ext() const { + return ext; + } - bool initialize(name argv_0, name org, name app, name ext); - void terminate(); + bool ready() const { + return initialized; + } - void mount_res(); - bool create_data_folder(); + private: + file_system() = default; - name get_org() const { return org; } - name get_app() const { return app; } - name get_ext() const { return ext; } + bool initialized = false; - bool ready() const { return initialized; } + name org = nullptr; + name app = nullptr; + name ext = nullptr; -private: - file_system() = default; + string res_path; + }; - bool initialized = false; + enum class file_type : type { - name org = nullptr; - name app = nullptr; - name ext = nullptr; + none = 0, + fs, + f_stream + }; - string res_path; -}; + constexpr i64 const file_error_result = -1; -enum class file_type : type { - - none = 0, - fs, - f_stream -}; - -constexpr i64 const file_error_result = -1; - -inline bool file_error(i64 result) { return result == file_error_result; } - -struct file : no_copy_no_move { - - explicit file(name path = nullptr, bool write = false); - ~file(); - - bool open(name path, bool write = false); - void close(); - - bool opened() const; - i64 get_size() const; + inline bool file_error(i64 result) { + return result == file_error_result; + } - i64 read(data_ptr data) { return read(data, to_ui64(get_size())); } - i64 read(data_ptr data, ui64 size); + struct file : no_copy_no_move { + explicit file(name path = nullptr, bool write = false); + ~file(); - i64 write(data_cptr data, ui64 size); + bool open(name path, bool write = false); + void close(); - bool writable() const { return write_mode; } - file_type get_type() const { return type; } + bool opened() const; + i64 get_size() const; - name get_path() const { return path; } + i64 read(data_ptr data) { + return read(data, to_ui64(get_size())); + } + i64 read(data_ptr data, ui64 size); -private: - file_type type = file_type::none; - bool write_mode = false; + i64 write(data_cptr data, ui64 size); - name path = nullptr; + bool writable() const { + return write_mode; + } + file_type get_type() const { + return type; + } - PHYSFS_File* fs_file = nullptr; - mutable std::ifstream i_stream; - mutable std::ofstream o_stream; -}; + name get_path() const { + return path; + } -bool load_file_data(string_ref filename, data& target); + private: + file_type type = file_type::none; + bool write_mode = false; -struct file_data { + name path = nullptr; - explicit file_data(string_ref filename) { load_file_data(filename, scope_data); } + PHYSFS_File* fs_file = nullptr; + mutable std::ifstream i_stream; + mutable std::ofstream o_stream; + }; - data const& get() const { return scope_data; } + bool load_file_data(string_ref filename, data& target); -private: - lava::scope_data scope_data; -}; + struct file_data { + explicit file_data(string_ref filename) { + load_file_data(filename, scope_data); + } -struct file_callback { + data const& get() const { + return scope_data; + } - using list = std::vector<file_callback*>; + private: + lava::scope_data scope_data; + }; - using func = std::function<void(json&)>; - func on_load; - func on_save; -}; + struct file_callback { + using list = std::vector<file_callback*>; -struct json_file { + using func = std::function<void(json&)>; + func on_load; + func on_save; + }; - explicit json_file(name path = _config_file_); + struct json_file { + explicit json_file(name path = _config_file_); - void add(file_callback* callback); - void remove(file_callback* callback); + void add(file_callback* callback); + void remove(file_callback* callback); - void set(name value) { path = value; } - name get() const { return str(path); } + void set(name value) { + path = value; + } + name get() const { + return str(path); + } - bool load(); - bool save(); + bool load(); + bool save(); -private: - string path; - file_callback::list callbacks; -}; + private: + string path; + file_callback::list callbacks; + }; -} // lava +} // namespace lava diff --git a/liblava/util/log.hpp b/liblava/util/log.hpp index b3c3bab1ab5ffeac2ed1435e2c1abb6e35096e04..ef96dd10db0d14e8573715ef641df3617084029b 100644 --- a/liblava/util/log.hpp +++ b/liblava/util/log.hpp @@ -4,77 +4,72 @@ #pragma once +#include <spdlog/sinks/basic_file_sink.h> +#include <spdlog/sinks/stdout_color_sinks.h> +#include <spdlog/spdlog.h> #include <liblava/core/types.hpp> #include <liblava/core/version.hpp> -#include <spdlog/spdlog.h> -#include <spdlog/sinks/stdout_color_sinks.h> -#include <spdlog/sinks/basic_file_sink.h> - namespace lava { -using logger = std::shared_ptr<spdlog::logger>; - -inline logger log(name name = _lava_) { return spdlog::get(name); } - -inline string to_string(string_ref id, string_ref name) { - - return fmt::format("{} | {}", str(id), str(name)); -} - -inline string to_string(internal_version const& version) { + using logger = std::shared_ptr<spdlog::logger>; - return fmt::format("{}.{}.{}", version.major, version.minor, version.patch); -} + inline logger log(name name = _lava_) { + return spdlog::get(name); + } -inline name to_string(version_stage stage) { + inline string to_string(string_ref id, string_ref name) { + return fmt::format("{} | {}", str(id), str(name)); + } - switch (stage) { + inline string to_string(internal_version const& version) { + return fmt::format("{}.{}.{}", version.major, version.minor, version.patch); + } - case version_stage::preview: return "preview"; - case version_stage::alpha: return "alpha"; - case version_stage::beta: return "beta"; - case version_stage::rc: return "rc"; + inline name to_string(version_stage stage) { + switch (stage) { + case version_stage::preview: + return "preview"; + case version_stage::alpha: + return "alpha"; + case version_stage::beta: + return "beta"; + case version_stage::rc: + return "rc"; default: return ""; + } } -} - -inline string to_string(version const& version) { - - string stage_str = to_string(version.stage); - if ((version.rev > 1) && (version.stage != version_stage::release)) - stage_str += fmt::format(" {}", version.rev); - if (version.release == 0) - return fmt::format("{} {}", version.year, str(stage_str)); - else - return fmt::format("{}.{} {}", version.year, version.release, str(stage_str)); -} + inline string to_string(version const& version) { + string stage_str = to_string(version.stage); + if ((version.rev > 1) && (version.stage != version_stage::release)) + stage_str += fmt::format(" {}", version.rev); -constexpr name _lava_log_file_ = "lava.log"; - -struct log_config { - - name logger = _lava_; - name file = _lava_log_file_; - - i32 level = -1; - bool debug = false; -}; + if (version.release == 0) + return fmt::format("{} {}", version.year, str(stage_str)); + else + return fmt::format("{}.{} {}", version.year, version.release, str(stage_str)); + } -inline void setup_log(log_config config = {}) { + constexpr name _lava_log_file_ = "lava.log"; - if (config.debug) { + struct log_config { + name logger = _lava_; + name file = _lava_log_file_; - auto log = spdlog::stdout_color_mt(config.logger); - log->set_level((config.level < 0) ? spdlog::level::debug : (spdlog::level::level_enum)config.level); - } - else { + i32 level = -1; + bool debug = false; + }; - auto log = spdlog::basic_logger_mt(config.logger, config.file); - log->set_level((config.level < 0) ? spdlog::level::warn : (spdlog::level::level_enum)config.level); + inline void setup_log(log_config config = {}) { + if (config.debug) { + auto log = spdlog::stdout_color_mt(config.logger); + log->set_level((config.level < 0) ? spdlog::level::debug : (spdlog::level::level_enum) config.level); + } else { + auto log = spdlog::basic_logger_mt(config.logger, config.file); + log->set_level((config.level < 0) ? spdlog::level::warn : (spdlog::level::level_enum) config.level); + } } -} -} // lava +} // namespace lava diff --git a/liblava/util/random.hpp b/liblava/util/random.hpp index c9577196cdfe96f4acb28f298b742965f90a720d..3ea2ba2c15407be8a3f0b1737133323a643ee267 100644 --- a/liblava/util/random.hpp +++ b/liblava/util/random.hpp @@ -5,55 +5,57 @@ #pragma once #include <liblava/core/types.hpp> - #include <random> namespace lava { -struct random_generator { - - static random_generator& instance() { - - static random_generator generator; - return generator; - } - - i32 get(i32 low, i32 high) { - - std::uniform_int_distribution<i32> dist(low, high); - return dist(mt); - } - - template <typename T = real> - T get(T low, T high) { - - std::uniform_real_distribution<T> dist(low, high); - return dist(mt); + struct random_generator { + static random_generator& instance() { + static random_generator generator; + return generator; + } + + i32 get(i32 low, i32 high) { + std::uniform_int_distribution<i32> dist(low, high); + return dist(mt); + } + + template<typename T = real> + T get(T low, T high) { + std::uniform_real_distribution<T> dist(low, high); + return dist(mt); + } + + private: + random_generator() { + std::random_device rd; + mt = std::mt19937(rd()); + } + + std::mt19937 mt; + }; + + template<typename T> + inline T random(T low, T high) { + return random_generator::instance().get(low, high); } -private: - random_generator() { - - std::random_device rd; - mt = std::mt19937(rd()); - } - - std::mt19937 mt; -}; - -template <typename T> -inline T random(T low, T high) { return random_generator::instance().get(low, high); } - -struct pseudo_random_generator { - - explicit pseudo_random_generator(ui32 seed) : seed(seed) {} - - void set_seed(ui32 value) { seed = value; } - ui32 get() { return generate_fast() ^ (generate_fast() >> 7); } - -private: - ui32 seed = 0; - ui32 generate_fast() { return seed = (seed * 196314165 + 907633515); } -}; - -} // lava + struct pseudo_random_generator { + explicit pseudo_random_generator(ui32 seed) + : seed(seed) {} + + void set_seed(ui32 value) { + seed = value; + } + ui32 get() { + return generate_fast() ^ (generate_fast() >> 7); + } + + private: + ui32 seed = 0; + ui32 generate_fast() { + return seed = (seed * 196314165 + 907633515); + } + }; + +} // namespace lava diff --git a/liblava/util/telegram.hpp b/liblava/util/telegram.hpp index e5f6e70a6a09c9b73da1e7a7a069a280ba47289f..dbc876cd5fb5e05d4a163d2c26384ebe02e75e21 100644 --- a/liblava/util/telegram.hpp +++ b/liblava/util/telegram.hpp @@ -4,99 +4,91 @@ #pragma once -#include <liblava/util/thread.hpp> - #include <any> #include <cmath> +#include <liblava/util/thread.hpp> #include <set> namespace lava { -constexpr ms const telegram_min_delay{ 250 }; - -using any = std::any; - -struct telegram { - - using ref = telegram const&; - - explicit telegram(id::ref sender, id::ref receiver, type msg, ms dispatch_time = {}, any info = {}) - : sender(sender), receiver(receiver), msg(msg), dispatch_time(dispatch_time), info(std::move(info)) {} - - bool operator==(ref rhs) const { - - return ((dispatch_time - rhs.dispatch_time) < telegram_min_delay) && - (sender == rhs.sender) && (receiver == rhs.receiver) && (msg == rhs.msg); - } - - bool operator<(ref rhs) const { + constexpr ms const telegram_min_delay{ 250 }; - if (*this == rhs) - return false; + using any = std::any; - return (dispatch_time < rhs.dispatch_time); - } + struct telegram { + using ref = telegram const&; - id sender; - id receiver; + explicit telegram(id::ref sender, id::ref receiver, type msg, ms dispatch_time = {}, any info = {}) + : sender(sender), receiver(receiver), msg(msg), dispatch_time(dispatch_time), info(std::move(info)) {} - type msg = no_type; - - ms dispatch_time; - any info; -}; - -struct dispatcher { - - void setup(ui32 threadcount) { pool.setup(threadcount); } + bool operator==(ref rhs) const { + return ((dispatch_time - rhs.dispatch_time) < telegram_min_delay) && (sender == rhs.sender) && (receiver == rhs.receiver) && (msg == rhs.msg); + } - void teardown() { pool.teardown(); } + bool operator<(ref rhs) const { + if (*this == rhs) + return false; - void update(ms current) { + return (dispatch_time < rhs.dispatch_time); + } - current_time = current; - dispatch_delayed_messages(current_time); - } + id sender; + id receiver; - void add_message(id::ref receiver, id::ref sender, type message, ms delay = {}, any const& info = {}) { + type msg = no_type; - telegram msg(sender, receiver, message, current_time, info); + ms dispatch_time; + any info; + }; - if (delay == ms{0}) { + struct dispatcher { + void setup(ui32 threadcount) { + pool.setup(threadcount); + } - discharge(msg); // now - return; + void teardown() { + pool.teardown(); } - msg.dispatch_time += delay; - messages.insert(msg); - } + void update(ms current) { + current_time = current; + dispatch_delayed_messages(current_time); + } - using message_func = std::function<void(telegram::ref, id::ref)>; - message_func on_message; + void add_message(id::ref receiver, id::ref sender, type message, ms delay = {}, any const& info = {}) { + telegram msg(sender, receiver, message, current_time, info); -private: - void discharge(telegram::ref message) { + if (delay == ms{ 0 }) { + discharge(msg); // now + return; + } - pool.enqueue([&, message](id::ref thread) { - if (on_message) - on_message(message, thread); - }); - } + msg.dispatch_time += delay; + messages.insert(msg); + } - void dispatch_delayed_messages(ms time) { + using message_func = std::function<void(telegram::ref, id::ref)>; + message_func on_message; - while (!messages.empty() && (messages.begin()->dispatch_time < time) && (messages.begin()->dispatch_time > ms{})) { + private: + void discharge(telegram::ref message) { + pool.enqueue([&, message](id::ref thread) { + if (on_message) + on_message(message, thread); + }); + } - discharge(*messages.begin()); - messages.erase(messages.begin()); + void dispatch_delayed_messages(ms time) { + while (!messages.empty() && (messages.begin()->dispatch_time < time) && (messages.begin()->dispatch_time > ms{})) { + discharge(*messages.begin()); + messages.erase(messages.begin()); + } } - } - ms current_time; + ms current_time; - thread_pool pool; - std::set<telegram> messages; -}; + thread_pool pool; + std::set<telegram> messages; + }; -} // lava +} // namespace lava diff --git a/liblava/util/thread.hpp b/liblava/util/thread.hpp index b141254e5d28b6a5d6576ae766e2d7516156720d..3abb176d43f5003d72e5988b2f0e4b45ffa52c21 100644 --- a/liblava/util/thread.hpp +++ b/liblava/util/thread.hpp @@ -4,99 +4,90 @@ #pragma once -#include <liblava/core/id.hpp> -#include <liblava/core/time.hpp> - #include <condition_variable> #include <deque> +#include <liblava/core/id.hpp> +#include <liblava/core/time.hpp> #include <mutex> #include <thread> namespace lava { -inline void sleep(ms time) { - - std::this_thread::sleep_for(time); -} - -inline void sleep(seconds time) { - - std::this_thread::sleep_for(time); -} - -struct thread_pool { - - using task = std::function<void(id::ref)>; // thread id - - void setup(ui32 count = 2) { - - for (auto i = 0u; i < count; ++i) - workers.emplace_back(worker(*this)); + inline void sleep(ms time) { + std::this_thread::sleep_for(time); } - void teardown() { + inline void sleep(seconds time) { + std::this_thread::sleep_for(time); + } - stop = true; - condition.notify_all(); + struct thread_pool { + using task = std::function<void(id::ref)>; // thread id - for (auto& worker : workers) - worker.join(); + void setup(ui32 count = 2) { + for (auto i = 0u; i < count; ++i) + workers.emplace_back(worker(*this)); + } - workers.clear(); - } + void teardown() { + stop = true; + condition.notify_all(); - template <typename F> - void enqueue(F f) { + for (auto& worker : workers) + worker.join(); - { - std::unique_lock<std::mutex> lock(queueMutex); - tasks.push_back(task(f)); + workers.clear(); } - condition.notify_one(); - } -private: - struct worker { - - explicit worker(thread_pool& pool) : pool(pool) {} + template<typename F> + void enqueue(F f) { + { + std::unique_lock<std::mutex> lock(queueMutex); + tasks.push_back(task(f)); + } + condition.notify_one(); + } - void operator()() { + private: + struct worker { + explicit worker(thread_pool& pool) + : pool(pool) {} - auto thread_id = ids::next(); + void operator()() { + auto thread_id = ids::next(); - task task; - while (true) { + task task; + while (true) { + { + std::unique_lock<std::mutex> lock(pool.queueMutex); - { - std::unique_lock<std::mutex> lock(pool.queueMutex); + while (!pool.stop && pool.tasks.empty()) + pool.condition.wait(lock); - while (!pool.stop && pool.tasks.empty()) - pool.condition.wait(lock); + if (pool.stop) + break; - if (pool.stop) - break; + task = pool.tasks.front(); + pool.tasks.pop_front(); + } - task = pool.tasks.front(); - pool.tasks.pop_front(); + task(thread_id); } - task(thread_id); + ids::free(thread_id); } - ids::free(thread_id); - } - - private: - thread_pool& pool; - }; + private: + thread_pool& pool; + }; - std::vector<std::thread> workers; - std::deque<task> tasks; + std::vector<std::thread> workers; + std::deque<task> tasks; - std::mutex queueMutex; - std::condition_variable condition; + std::mutex queueMutex; + std::condition_variable condition; - bool stop = false; -}; + bool stop = false; + }; -} // lava +} // namespace lava diff --git a/liblava/util/utility.hpp b/liblava/util/utility.hpp index b6747f43719691241e8e804da9fcab0268a6c9bc..2239d5a4c1c0319088755c610383144a10a0a77a 100644 --- a/liblava/util/utility.hpp +++ b/liblava/util/utility.hpp @@ -4,50 +4,51 @@ #pragma once -#include <liblava/core/types.hpp> - #include <algorithm> #include <cstring> +#include <liblava/core/types.hpp> #include <utility> namespace lava { -inline bool exists(names_ref list, name item) { - - auto itr = std::find_if(list.begin(), list.end(), [&](name entry) { return strcmp(entry, item) == 0; }); - return itr != list.end(); -} - -template <typename T> -inline void remove(std::vector<T>& list, T item) { - - list.erase(std::remove(list.begin(), list.end(), item), list.end()); -} - -template <typename T> -inline bool contains(std::vector<T>& list, T item) { + inline bool exists(names_ref list, name item) { + auto itr = std::find_if(list.begin(), list.end(), [&](name entry) { return strcmp(entry, item) == 0; }); + return itr != list.end(); + } - return std::find(list.begin(), list.end(), item) != list.end(); -} + template<typename T> + inline void remove(std::vector<T>& list, T item) { + list.erase(std::remove(list.begin(), list.end(), item), list.end()); + } -template <typename T> -inline void append(std::vector<T>& list, std::vector<T>& items) { + template<typename T> + inline bool contains(std::vector<T>& list, T item) { + return std::find(list.begin(), list.end(), item) != list.end(); + } - list.insert(list.end(), items.begin(), items.end()); -} + template<typename T> + inline void append(std::vector<T>& list, std::vector<T>& items) { + list.insert(list.end(), items.begin(), items.end()); + } -// reversed iterable + // reversed iterable -template <typename T> -struct reversion_wrapper { T& iterable; }; + template<typename T> + struct reversion_wrapper { T& iterable; }; -template <typename T> -inline auto begin(reversion_wrapper<T> w) { return std::rbegin(w.iterable); } + template<typename T> + inline auto begin(reversion_wrapper<T> w) { + return std::rbegin(w.iterable); + } -template <typename T> -inline auto end(reversion_wrapper<T> w) { return std::rend(w.iterable); } + template<typename T> + inline auto end(reversion_wrapper<T> w) { + return std::rend(w.iterable); + } -template <typename T> -inline reversion_wrapper<T> reverse(T&& iterable) { return { iterable }; } + template<typename T> + inline reversion_wrapper<T> reverse(T&& iterable) { + return { iterable }; + } -} // lava +} // namespace lava diff --git a/tests/driver.cpp b/tests/driver.cpp index f60141eb8b667f49384e23b5ac4cc4bb3655a1b9..aad4574d2cae9e342bbc9a5099d5091c98b3690c 100644 --- a/tests/driver.cpp +++ b/tests/driver.cpp @@ -2,20 +2,17 @@ // copyright : Copyright (c) 2018-present, Lava Block OÜ // license : MIT; see accompanying LICENSE file -#include <tests/driver.hpp> - #include <iostream> +#include <tests/driver.hpp> using namespace lava; int run(int argc, char** argv) { - auto& tests = driver::instance().get(); argh::parser cmd_line(argc, argv); if (cmd_line[{ "-t", "--tests" }]) { - for (auto& t : tests) std::cout << t.first << " - " << t.second->descr << std::endl; @@ -23,17 +20,14 @@ int run(int argc, char** argv) { } if (cmd_line.pos_args().size() > 1) { - char* end_ptr = nullptr; auto selected = std::strtol(str(cmd_line.pos_args().at(1)), &end_ptr, 10); if (*end_ptr != '\0') { - std::cerr << "wrong arguments" << std::endl; return test_result::wrong_arguments; } if (!tests.count(selected)) { - std::cerr << "test " << selected << " not found" << std::endl; return test_result::not_found; } @@ -43,7 +37,6 @@ int run(int argc, char** argv) { } for (auto& t : reverse(tests)) { - std::cout << "test " << t.first << " - " << t.second->descr << std::endl; return t.second->on_func(cmd_line); } @@ -53,15 +46,14 @@ int run(int argc, char** argv) { } int main(int argc, char* argv[]) { - return run(argc, argv); } namespace lava { -test::test(ui32 id, name descr, func func) : id(id), descr(descr), on_func(func) { - - driver::instance().add_test(this); -} + test::test(ui32 id, name descr, func func) + : id(id), descr(descr), on_func(func) { + driver::instance().add_test(this); + } -} // lava +} // namespace lava diff --git a/tests/driver.hpp b/tests/driver.hpp index f21709c856ae3c268d37538d37743f0b4f5341b9..6adac3dce657617f4ac8267a3ca915da2b9cc8d2 100644 --- a/tests/driver.hpp +++ b/tests/driver.hpp @@ -27,55 +27,53 @@ LAVA_TEST(1, "first test") namespace lava { -enum test_result { + enum test_result { - no_tests = -100, - not_found = -101, - wrong_arguments = -102 -}; + no_tests = -100, + not_found = -101, + wrong_arguments = -102 + }; -struct test { + struct test { + using map = std::map<index, test*>; + using func = std::function<i32(argh::parser)>; - using map = std::map<index, test*>; - using func = std::function<i32(argh::parser)>; + explicit test(ui32 id, name descr, func func); - explicit test(ui32 id, name descr, func func); + index id = 0; + string descr; + func on_func; + }; - index id = 0; - string descr; - func on_func; -}; + struct driver { + static driver& instance() { + static driver singleton; + return singleton; + } -struct driver { + void add_test(test* test) { + tests.emplace(test->id, test); + } - static driver& instance() { + test::map const& get() const { + return tests; + } - static driver singleton; - return singleton; - } + private: + driver() = default; - void add_test(test* test) { + test::map tests; + }; - tests.emplace(test->id, test); - } - - test::map const& get() const { return tests; } - -private: - driver() = default; - - test::map tests; -}; - -} // lava +} // namespace lava #define OBJ test_ #define FUNC _test -#define STR_(n,m) n##m -#define STR(n,m) STR_(n,m) +#define STR_(n, m) n##m +#define STR(n, m) STR_(n, m) #define LAVA_TEST(ID, NAME) \ -i32 STR(FUNC,ID)(argh::parser argh); \ -lava::test STR(OBJ,ID)(ID, NAME, ::STR(FUNC,ID)); \ -i32 STR(FUNC,ID)(argh::parser argh) + i32 STR(FUNC, ID)(argh::parser argh); \ + lava::test STR(OBJ, ID)(ID, NAME, ::STR(FUNC, ID)); \ + i32 STR(FUNC, ID)(argh::parser argh) diff --git a/tests/tests.cpp b/tests/tests.cpp index 0dfbc9873c482a2e2ad95f235d655cf62b8dddb3..a55df1584e8eeaf63b2ef390c8c985f8763fb92a 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -6,15 +6,13 @@ using namespace lava; -LAVA_TEST(1, "frame init") -{ +LAVA_TEST(1, "frame init") { frame frame(argh); return frame.ready() ? 0 : error::not_ready; } -LAVA_TEST(2, "run loop") -{ +LAVA_TEST(2, "run loop") { frame frame(argh); if (!frame.ready()) return error::not_ready; @@ -22,7 +20,6 @@ LAVA_TEST(2, "run loop") auto count = 0; frame.add_run([&]() { - sleep(seconds(1)); count++; @@ -37,8 +34,7 @@ LAVA_TEST(2, "run loop") return frame.run(); } -LAVA_TEST(3, "window input") -{ +LAVA_TEST(3, "window input") { frame frame(argh); if (!frame.ready()) return error::not_ready; @@ -51,7 +47,6 @@ LAVA_TEST(3, "window input") window.assign(&input); input.key.listeners.add([&](key_event::ref event) { - if (event.pressed(key::escape)) return frame.shut_down(); @@ -59,7 +54,6 @@ LAVA_TEST(3, "window input") }); frame.add_run([&]() { - input.handle_events(); if (window.close_request()) @@ -71,8 +65,7 @@ LAVA_TEST(3, "window input") return frame.run(); } -LAVA_TEST(4, "clear color") -{ +LAVA_TEST(4, "clear color") { frame frame(argh); if (!frame.ready()) return error::not_ready; @@ -85,7 +78,6 @@ LAVA_TEST(4, "clear color") window.assign(&input); input.key.listeners.add([&](key_event::ref event) { - if (event.pressed(key::escape)) return frame.shut_down(); @@ -110,30 +102,26 @@ LAVA_TEST(4, "clear color") VkCommandBuffers cmd_bufs(frame_count); auto build_cmd_bufs = [&]() { - if (!device->vkCreateCommandPool(device->graphics_queue().family, &cmd_pool)) return false; if (!device->vkAllocateCommandBuffers(cmd_pool, frame_count, cmd_bufs.data())) return false; - VkCommandBufferBeginInfo const begin_info - { + VkCommandBufferBeginInfo const begin_info{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, }; VkClearColorValue const clear_color = { lava::random(0.f, 1.f), lava::random(0.f, 1.f), lava::random(0.f, 1.f), 0.f }; - VkImageSubresourceRange const image_range - { + VkImageSubresourceRange const image_range{ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .levelCount = 1, .layerCount = 1, }; for (auto i = 0u; i < frame_count; ++i) { - auto cmd_buf = cmd_bufs[i]; auto frame_image = render_target->get_image(i); @@ -160,7 +148,6 @@ LAVA_TEST(4, "clear color") }; auto clean_cmd_bufs = [&]() { - device->vkFreeCommandBuffers(cmd_pool, frame_count, cmd_bufs.data()); device->vkDestroyCommandPool(cmd_pool); }; @@ -172,7 +159,6 @@ LAVA_TEST(4, "clear color") render_target->on_swapchain_stop = clean_cmd_bufs; frame.add_run([&]() { - input.handle_events(); if (window.close_request()) @@ -189,7 +175,6 @@ LAVA_TEST(4, "clear color") }); frame.add_run_end([&]() { - clean_cmd_bufs(); plotter.destroy(); @@ -199,8 +184,7 @@ LAVA_TEST(4, "clear color") return frame.run(); } -LAVA_TEST(5, "color block") -{ +LAVA_TEST(5, "color block") { frame frame(argh); if (!frame.ready()) return error::not_ready; @@ -213,7 +197,6 @@ LAVA_TEST(5, "color block") window.assign(&input); input.key.listeners.add([&](key_event::ref event) { - if (event.pressed(key::escape)) return frame.shut_down(); @@ -240,11 +223,9 @@ LAVA_TEST(5, "color block") return error::create_failed; block.add_command([&](VkCommandBuffer cmd_buf) { - VkClearColorValue const clear_color = { lava::random(0.f, 1.f), lava::random(0.f, 1.f), lava::random(0.f, 1.f), 0.f }; - VkImageSubresourceRange const image_range - { + VkImageSubresourceRange const image_range{ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .levelCount = 1, .layerCount = 1, @@ -266,7 +247,6 @@ LAVA_TEST(5, "color block") }); frame.add_run([&]() { - input.handle_events(); if (window.close_request()) @@ -286,7 +266,6 @@ LAVA_TEST(5, "color block") }); frame.add_run_end([&]() { - block.destroy(); plotter.destroy(); @@ -296,8 +275,7 @@ LAVA_TEST(5, "color block") return frame.run(); } -LAVA_TEST(6, "forward shading") -{ +LAVA_TEST(6, "forward shading") { frame frame(argh); if (!frame.ready()) return error::not_ready; @@ -310,7 +288,6 @@ LAVA_TEST(6, "forward shading") window.assign(&input); input.key.listeners.add([&](key_event::ref event) { - if (event.pressed(key::escape)) return frame.shut_down(); @@ -336,7 +313,6 @@ LAVA_TEST(6, "forward shading") return false; block.add_command([&](VkCommandBuffer cmd_buf) { - render_pass->set_clear_color({ lava::random(0.f, 1.f), lava::random(0.f, 1.f), lava::random(0.f, 1.f) }); render_pass->process(cmd_buf, block.get_current_frame()); }); @@ -346,7 +322,6 @@ LAVA_TEST(6, "forward shading") return error::create_failed; frame.add_run([&]() { - input.handle_events(); if (window.close_request()) @@ -356,12 +331,9 @@ LAVA_TEST(6, "forward shading") return window.handle_resize(); if (window.iconified()) { - frame.set_wait_for_events(true); return true; - } - else { - + } else { if (frame.waiting_for_events()) frame.set_wait_for_events(false); } @@ -377,10 +349,9 @@ LAVA_TEST(6, "forward shading") }); frame.add_run_end([&]() { - block.destroy(); shading.destroy(); - + plotter.destroy(); render_target->destroy(); }); @@ -388,14 +359,12 @@ LAVA_TEST(6, "forward shading") return frame.run(); } -LAVA_TEST(7, "gamepad") -{ +LAVA_TEST(7, "gamepad") { frame frame(argh); if (!frame.ready()) return error::not_ready; gamepad_manager::instance().add([&](gamepad pad, bool active) { - auto id = to_ui32(pad.get_id()); if (active) @@ -410,7 +379,6 @@ LAVA_TEST(7, "gamepad") log()->info("gamepad {} - active ({})", to_ui32(pad.get_id()), pad.get_name()); frame.add_run([&]() { - sleep(seconds(1)); return true; @@ -421,14 +389,12 @@ LAVA_TEST(7, "gamepad") #include <imgui.h> -LAVA_TEST(8, "imgui demo") -{ +LAVA_TEST(8, "imgui demo") { app app("demo", argh); if (!app.setup()) return error::not_ready; app.gui.on_draw = []() { - ImGui::ShowDemoWindow(); };