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 = &param.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 = &param.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 &target; }
-
-    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 &target;
+        }
+
+        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();
     };