From 7158a15b5bd1ba02ca31594c5e8ddfb9f2f35992 Mon Sep 17 00:00:00 2001 From: Andreev Gregory Date: Sat, 30 Aug 2025 16:14:15 +0300 Subject: [PATCH] Got rid of Xorg completely! Plus fixed some bugs. Yay!!! --- CMakeLists.txt | 4 +- Makefile | 5 +- src/l1/core/util.h | 2 + src/l2/codegen/codegen.c | 3 +- src/l2/margaret/vulkan.h | 14 +- src/l2/tests/r0/r0.c | 1498 ++++++++++------- src/l2/tests/r0/r0_assets.h | 4 + src/l2/tests/r0/r0_scene.h | 2 + .../{test_shaders => shaders}/glsl/0/0.frag | 0 .../{test_shaders => shaders}/glsl/0/0.vert | 0 .../{test_shaders => shaders}/glsl/0b/0b.frag | 0 .../{test_shaders => shaders}/glsl/0b/0b.vert | 0 .../{test_shaders => shaders}/glsl/1/1.frag | 0 .../{test_shaders => shaders}/glsl/1/1.vert | 0 src/l2/tests/r0/test_shader_compile.sh | 15 - .../bitmap_converter.py | 0 .../log_10_2_6.png | Bin .../r0/{test_textures => textures}/test.png | Bin src/l2/tests/r3/r3.c | 15 +- src/l2/tests/r3/shader_compile.sh | 12 - 20 files changed, 886 insertions(+), 688 deletions(-) rename src/l2/tests/r0/{test_shaders => shaders}/glsl/0/0.frag (100%) rename src/l2/tests/r0/{test_shaders => shaders}/glsl/0/0.vert (100%) rename src/l2/tests/r0/{test_shaders => shaders}/glsl/0b/0b.frag (100%) rename src/l2/tests/r0/{test_shaders => shaders}/glsl/0b/0b.vert (100%) rename src/l2/tests/r0/{test_shaders => shaders}/glsl/1/1.frag (100%) rename src/l2/tests/r0/{test_shaders => shaders}/glsl/1/1.vert (100%) delete mode 100755 src/l2/tests/r0/test_shader_compile.sh rename src/l2/tests/r0/{test_textures => textures}/bitmap_converter.py (100%) rename src/l2/tests/r0/{test_textures => textures}/log_10_2_6.png (100%) rename src/l2/tests/r0/{test_textures => textures}/test.png (100%) delete mode 100644 src/l2/tests/r3/shader_compile.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 958789f..0b84844 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,8 +34,8 @@ add_executable(1_test src/l1/tests/t1.c) add_executable(codegen_l2 src/l2/codegen/codegen.c) -add_executable(0_render_test src/l2/tests/r0/r0.c) -target_link_libraries(0_render_test -lvulkan -lX11 -lm) +add_executable(0_render_test src/l2/tests/r0/r0.c gen/l_wl_protocols/xdg-shell-private.c) +target_link_libraries(0_render_test -lvulkan -lwayland-client -lm -lxkbcommon) add_executable(0_render_test_tex_init_prep src/l2/tests/r0/r0_tex_init_prep.c) target_link_libraries(0_render_test_tex_init_prep -lm) diff --git a/Makefile b/Makefile index 5d3a75e..387906c 100644 --- a/Makefile +++ b/Makefile @@ -53,9 +53,10 @@ gen/l_wl_protocols/xdg-shell-private.c: $(wl_protocols)/stable/xdg-shell/xdg-she l_wl_protocols := gen/l_wl_protocols/xdg-shell-client.h gen/l_wl_protocols/xdg-shell-private.c -out/l2/r0: src/l2/tests/r0/r0.c $(HEADERS_gen_l2) $(HEADERS_src_l2) $(HEADERS_gen_l1) $(HEADERS_src_l1) +out/l2/r0: src/l2/tests/r0/r0.c $(HEADERS_gen_l2) $(HEADERS_src_l2) $(HEADERS_gen_l1) $(HEADERS_src_l1) \ + $(l_wl_protocols) mkdir -p out/l2 - $(cc) $(cflags) -o $@ $< -lvulkan -lX11 -lm + $(cc) $(cflags) -o $@ $< gen/l_wl_protocols/xdg-shell-private.c -lvulkan -lm -lxkbcommon -lwayland-client out/l2/r1: src/l2/tests/r1/r1.c $(HEADERS_gen_l2) $(HEADERS_src_l2) $(HEADERS_gen_l1) $(HEADERS_src_l1) \ $(l_wl_protocols) diff --git a/src/l1/core/util.h b/src/l1/core/util.h index 00186b1..6e546e5 100644 --- a/src/l1/core/util.h +++ b/src/l1/core/util.h @@ -15,6 +15,8 @@ #define NORETURN [[noreturn]] #define NODISCARD [[nodiscard]] +typedef const char* CSTR; + typedef enum { Option_Some, Option_None } Option_variant; diff --git a/src/l2/codegen/codegen.c b/src/l2/codegen/codegen.c index ce77f49..e527a81 100644 --- a/src/l2/codegen/codegen.c +++ b/src/l2/codegen/codegen.c @@ -24,9 +24,8 @@ void eve_of_l2() { generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("MarieTriangleAttr"), true, false); /* Needed in r0_scene.h */ generate_eve_span_garden_for_primitive(cstr("l2"), cstr("r0"), cstr("ModelOnScene"), true, false); - generate_eve_span_garden_for_primitive(cstr("l2"), cstr("r0"), cstr("UsedModelOnScene"), true, false); + generate_eve_span_garden_for_non_primitive_clonable(cstr("l2"), cstr("r0"), cstr("UsedModelOnScene"), true, false); /* Needed in margaret/vulkan.h */ - generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("Xlib_Event"), true, false); // todo: get rid of this crap generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("CSTR"), true, false); // generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("MargaretChosenQueueFamilies"), true, false); generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("VkQueueFamilyProperties"), true, false); diff --git a/src/l2/margaret/vulkan.h b/src/l2/margaret/vulkan.h index 70599e1..ef9b8dc 100644 --- a/src/l2/margaret/vulkan.h +++ b/src/l2/margaret/vulkan.h @@ -44,8 +44,6 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL margaret_static_debug_callback( return VK_FALSE; } -typedef const char* CSTR; - #include "../../../gen/l2/eve/VecCSTR.h" typedef struct { @@ -114,7 +112,8 @@ NODISCARD MargaretInstanceAndItsDebug MargaretInstanceAndItsDebug_new(bool enabl }; margaret_create_debug_utils_messenger_EXT(instance, &debug_messenger_crinfo, NULL, &debug_messenger); } - + VecCSTR_drop(needed_layers); /* needed_layers invalidated */ + VecCSTR_drop(needed_extensions); /* needed_extensions invalidated */ return (MargaretInstanceAndItsDebug){.instance = instance, .debug_messenger = debug_messenger}; } @@ -508,6 +507,7 @@ VecMargaretScoredPhysicalDevice margaret_get_physical_devices_scored( ); } MutSpanMargaretScoredPhysicalDevice_sort(VecMargaretScoredPhysicalDevice_to_mspan(&scored_devices)); + VecVkPhysicalDevice_drop(physical_devices); return scored_devices; } @@ -535,7 +535,9 @@ VkPhysicalDevice margaret_select_one_physical_device( const MargaretScoredPhysicalDevice* best_dev = VecMargaretScoredPhysicalDevice_at(&scored_devices, scored_devices.len - 1); if (best_dev->score < 0) abortf("No suitable vulkan devices"); - return best_dev->physical_device; + VkPhysicalDevice result = best_dev->physical_device; + VecMargaretScoredPhysicalDevice_drop(scored_devices); /* best_dev, scored_devices invalidated */ + return result; } VkSwapchainKHR margaret_create_swapchain ( @@ -613,6 +615,7 @@ VecVkImageView margaret_create_swapchain_image_views( if (vkCreateImageView(device, &imageview_crinfo, NULL, VecVkImageView_mat(&swapchain_image_views, i)) != VK_SUCCESS) abortf("vkCreateImageView"); } + VecVkImage_drop(swapchain_images); return swapchain_image_views; } @@ -685,12 +688,15 @@ MargaretSwapchainBundle MargaretSwapchainBundle_new( VkSwapchainKHR MargaretSwapchainBundle_pop_swapchain_drop_rest(VkDevice device, MargaretSwapchainBundle swfb) { for (size_t i = 0; i < swfb.rendering_finished_here_semaphores.len; i++) vkDestroySemaphore(device, *VecVkSemaphore_at(&swfb.rendering_finished_here_semaphores, i), NULL); + VecVkSemaphore_drop(swfb.rendering_finished_here_semaphores); for (size_t i = 0; i < swfb.framebuffers.len; i++) { vkDestroyFramebuffer(device, *VecVkFramebuffer_at(&swfb.framebuffers, i), NULL); } + VecVkFramebuffer_drop(swfb.framebuffers); for (size_t i = 0; i < swfb.image_views.len; i++) { vkDestroyImageView(device, *VecVkImageView_at(&swfb.image_views, i), NULL); } + VecVkImageView_drop(swfb.image_views); // Old swapchain bundle is 83% dropped return swfb.swapchain; } diff --git a/src/l2/tests/r0/r0.c b/src/l2/tests/r0/r0.c index 4f9a807..c7df585 100644 --- a/src/l2/tests/r0/r0.c +++ b/src/l2/tests/r0/r0.c @@ -1,213 +1,16 @@ #include "../../margaret/vulkan.h" #include "../../../../gen/l2/geom.h" #include +#include #include "../../../l1/system/fileio.h" #include #include "r0_scene.h" -#include // Only for linux +#include +#include "../../../l1/system/fsmanip.h" +#include "../../../../gen/l_wl_protocols/xdg-shell-client.h" +#include -/* I temporarily moved all the Xlib crap here, away from margaret. todo: remove crap from here too */ -// todo: rewrite this crap to wayland (fom now on wayland is my best friend in all situations) -#include -#include -#include -// todo: rewrite margaret to use libwayland-client, and get rid of this fucking crap -typedef XEvent Xlib_Event; - -#include "../../../../gen/l2/eve/VecXlib_Event.h" - -// todo: AAAAAAAAAAAAA I HATE XLIB SO FUCKINGG MNJUHC AAAASAAAAA AAAAAAA -typedef Display Xlib_Display; -typedef Window Xlib_Window; -typedef Atom Xlib_Atom; - -// todo: AAAAAAAAAAAAAAAA AAASASDASDASDASDAGAHGFKJG AAAAAAAAAAA FUCK XLIB FUCK XORG FUCK THIS SHIT -NODISCARD VecXlib_Event margaret_read_x_events(Xlib_Display* dpy) { - int evh = XEventsQueued(dpy, QueuedAfterReading); - VecXlib_Event result = VecXlib_Event_new_zeroinit(evh); - for (int i = 0; i < evh; i++) { - XNextEvent(dpy, VecXlib_Event_mat(&result, i)); - } - return result; -} - -void margaret_win_init_set_properties(Xlib_Display* dpy, Xlib_Window win) { - const char* strings[] = { - "WM_PROTOCOLS", - "ATOM", - "WM_DELETE_WINDOW" - }; - Atom atoms[3]; - int status; - status = XInternAtoms(dpy, (char**)(strings), 3, False, atoms); - if (status == 0) - abortf("XInternAtoms"); - status = XChangeProperty(dpy, win, atoms[0], atoms[1], 32, PropModeReplace, (unsigned char *)&atoms[2], 1); - if (status == 0) - abortf("XChangeProperty"); -} - -// todo: delete this crap -typedef struct { - Xlib_Atom A_WM_windel; - Xlib_Atom A_WM_protocols; - int width; - int height; - bool should_stop; - Xlib_Window win; -} Margaret_WEP; - -// todo: delete this crap -Margaret_WEP Margaret_WEP_new(Xlib_Display* dpy, Xlib_Window win) { - return (Margaret_WEP){ - .A_WM_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False), - .A_WM_windel = XInternAtom(dpy, "WM_DELETE_WINDOW", False), - .should_stop = false, - .win = win, - }; -} - -// todo: delete this crap -void Margaret_WEP_update_with_new_event(Margaret_WEP* self, const Xlib_Event* ev) { - if (ev->xany.window != self->win) - return; - if (ev->type == ConfigureNotify) { - printf("That was ConfigureNotify\n"); - self->width = ev->xconfigure.width; - self->height = ev->xconfigure.height; - } else if (ev->type == ClientMessage) { - printf("That was ClientMessage\n"); - if (ev->xclient.message_type == self->A_WM_protocols && - ev->xclient.format == 32 && ev->xclient.data.l[0] == self->A_WM_windel - ){ - printf("WM_DELETE_WINDOW\n"); - self->should_stop = true; - } - } else if (ev->type == DestroyNotify) { - printf("That was DestroyNotify\n"); - self->should_stop = true; - } -} - - -// todo: delete this crap -MargaretInstanceAndItsDebug MargaretInstanceAndItsDebug_new_xlib_flavour(bool enable_validation_layers) { - // InstanceAndDebugHands res{}; - VkApplicationInfo app_info = { - .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, - .pApplicationName = "Kto prochital tot zdohnet", - .applicationVersion = VK_MAKE_VERSION(1, 0, 0), - .pEngineName = "Margaret", - .engineVersion = VK_MAKE_VERSION(1, 0, 0), - .apiVersion = VK_API_VERSION_1_2, - }; - - VecCSTR needed_extensions = VecCSTR_new(); - VecCSTR_append(&needed_extensions, "VK_KHR_xlib_surface"); - VecCSTR_append(&needed_extensions, "VK_KHR_surface"); - VecCSTR needed_layers = VecCSTR_new(); - if (enable_validation_layers) { - VecCSTR_append(&needed_extensions, "VK_EXT_debug_utils"); - VecCSTR_append(&needed_layers, "VK_LAYER_KHRONOS_validation"); - } - - VkInstanceCreateInfo instance_crinfo = { - .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - // .pNext may be set to `for-instance-creation-only` Debug Messanger crinfo later - .pApplicationInfo = &app_info, - .enabledLayerCount = needed_layers.len, - .ppEnabledLayerNames = needed_layers.buf, - .enabledExtensionCount = needed_extensions.len, - .ppEnabledExtensionNames = needed_extensions.buf, - }; - - if (enable_validation_layers) { - VkDebugUtilsMessengerCreateInfoEXT debug_messenger_2_crinfo = { - .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, - .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | - 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 = margaret_static_debug_callback, - .pUserData = NULL, - }; - instance_crinfo.pNext = &debug_messenger_2_crinfo; - } - VkInstance instance; - if (vkCreateInstance(&instance_crinfo, NULL, &instance) != VK_SUCCESS) - abortf("Failed to create Vulkan instance"); - VkDebugUtilsMessengerEXT debug_messenger = NULL; - if (enable_validation_layers) { - VkDebugUtilsMessengerCreateInfoEXT debug_messenger_crinfo = { - .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, - .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | - 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 = margaret_static_debug_callback, - .pUserData = NULL, - }; - margaret_create_debug_utils_messenger_EXT(instance, &debug_messenger_crinfo, NULL, &debug_messenger); - } - - return (MargaretInstanceAndItsDebug){.instance = instance, .debug_messenger = debug_messenger}; -} - -// todo: remove this dumb crap -typedef struct { - Xlib_Display* dpy; - Xlib_Window win; -} MargaretSingleWindowSetup_XlibFlavour; - -// todo: delte this garbage -MargaretSingleWindowSetup_XlibFlavour MargaretSingleWindowSetup_XlibFlavour_new() { - Display *dpy = XOpenDisplay(NULL); - if (!dpy) - abortf("Unable to open X display"); - - int screen = DefaultScreen(dpy); - Window root = RootWindow(dpy, screen); - - unsigned long black = BlackPixel(dpy, screen); - unsigned long white = WhitePixel(dpy, screen); - int win_x = 50, win_y = 50; - unsigned int win_w = 400, win_h = 300; - Window win = XCreateSimpleWindow( - dpy, root, - win_x, win_y, win_w, win_h, - 1, black, white - ); - margaret_win_init_set_properties(dpy, win); - - /* 3) Select for ConfigureNotify and Expose events */ - XSelectInput(dpy, win, StructureNotifyMask | ExposureMask | PointerMotionMask | KeyPressMask | KeyReleaseMask); - return (MargaretSingleWindowSetup_XlibFlavour){ .dpy = dpy, .win = win }; -} - -// todo: ahfadlhja kjdelete this crap -void MargaretSingleWindowSetup_XlibFlavour_drop(MargaretSingleWindowSetup_XlibFlavour x) { - XDestroyWindow(x.dpy, x.win); - XCloseDisplay(x.dpy); -} - -// todo: delete this crap. We are gonna use libwayland -VkSurfaceKHR margaret_create_surface_x_dunk(VkInstance instance, const MargaretSingleWindowSetup_XlibFlavour* x) { - VkXlibSurfaceCreateInfoKHR surface_crinfo = { - .sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, .dpy = x->dpy, .window = x->win, - }; - VkSurfaceKHR surface; - if (vkCreateXlibSurfaceKHR(instance, &surface_crinfo, NULL, &surface) != VK_SUCCESS) - abortf("Failed to create Vulkan surface"); - return surface; -} - - - -// todo: generate this class in l2 +// todo: generate this structure in l2 typedef struct { VkPipelineLayout pipeline_layout; VkPipeline pipeline; @@ -296,8 +99,8 @@ margaret_prep_buffer_mem_info_of_gpu_vbo_Definition(GenericMeshVertex) PipelineHands create_graphics_pipeline_0( VkDevice device, VkRenderPass render_pass, uint32_t subpass ) { - VecU8 vert_bin_code = read_whole_file_or_abort("test_shaders/spv/0/vert.spv"); - VecU8 frag_bin_code = read_whole_file_or_abort("test_shaders/spv/0/frag.spv"); + VecU8 vert_bin_code = read_whole_file_or_abort("shaders/spv/0/vert.spv"); + VecU8 frag_bin_code = read_whole_file_or_abort("shaders/spv/0/frag.spv"); VkShaderModule vert_module = margaret_VkShaderModule_new(device, vert_bin_code); VkShaderModule frag_module = margaret_VkShaderModule_new(device, frag_bin_code); VecU8_drop(vert_bin_code); @@ -574,8 +377,8 @@ VkRenderPass create_render_pass_1(VkDevice logical_device, VkFormat image_format PipelineHands create_graphics_pipeline_1( VkDevice device, VkRenderPass render_pass, uint32_t subpass ) { - VecU8 vert_bin_code = read_whole_file_or_abort("test_shaders/spv/1/vert.spv"); - VecU8 frag_bin_code = read_whole_file_or_abort("test_shaders/spv/1/frag.spv"); + VecU8 vert_bin_code = read_whole_file_or_abort("shaders/spv/1/vert.spv"); + VecU8 frag_bin_code = read_whole_file_or_abort("shaders/spv/1/frag.spv"); VkShaderModule vert_module = margaret_VkShaderModule_new(device, vert_bin_code); VkShaderModule frag_module = margaret_VkShaderModule_new(device, frag_bin_code); VecU8_drop(vert_bin_code); @@ -955,45 +758,639 @@ void Jane_r0_destroy(VkDevice device, Jane_r0 jane) { vkDestroySemaphore(device, jane.in_frame_transfer_complete, NULL); } -void recreate_swapchain( - VkPhysicalDevice physical_device, VkDevice device, MargaretChosenQueueFamilies queue_fam, VkSurfaceKHR surface, - VkRenderPass render_pass, MargaretSwapchainBundle* swfb, Jane_r0* jane, VkExtent2D sane_image_extent_limit) { +// todo: handle case where presentation and graphics are from the same family +typedef struct { + VkQueue graphics_queue; + VkQueue presentation_queue; +} UsedVulkanQueues; + +typedef struct { + MargaretInstanceAndItsDebug instance_and_debug; + VkSurfaceKHR surface; + VkPhysicalDevice physical_device; + MargaretChosenQueueFamilies queue_fam; + VkDevice device; + UsedVulkanQueues queues; + VkFormat zbuffer_format; + VkFormat IT1_format; + VkRenderPass render_pass_0; + PipelineHands pipeline_hands_0; + VkRenderPass render_pass_1; + PipelineHands pipeline_hands_1; + Jane_r0 jane; + MargaretSwapchainBundle swfb; + + SceneTemplate scene_template; + TextureDataR8G8B8A8 cyl_1_diffuse_tex; + TextureDataR8G8B8A8 cyl_1_normal_tex; + MargaretBufferInMemoryInfo host_mem_buffer; + VkDeviceMemory host_mem; + VecMargaretBufferInMemoryInfo device_ebo_and_vbo_buffers_for_generic_meshes; + MargaretBufferInMemoryInfo device_lighting_ubo; + MargaretBufferInMemoryInfo device_instance_attrs_for_all_generic_meshes; + MargaretImageInMemoryInfo device_IT1_image; + MargaretImageInMemoryInfo device_zbuffer_image; + MargaretImageInMemoryInfo device_cyl_1_diffuse_texture; + MargaretImageInMemoryInfo device_cyl_1_normal_texture; + VkDeviceMemory device_mem; + + VkCommandPool command_pool; + VkCommandBuffer rendering_command_buffer_0; + VkCommandBuffer rendering_command_buffer_1; + VkCommandBuffer transfer_command_buffer; + + Scene scene; + + void* host_mem_buffer_mem; + + VkImageView zbuffer_view; + VkImageView IT1_view; + VkFramebuffer IT1_framebuffer; + VkImageView cyl_1_diffuse_texture_view; + VkImageView cyl_1_normal_texture_view; + VkSampler linear_sampler; + VkSampler nearest_sampler; + VkDescriptorPool descriptor_pool; + VkDescriptorSet descriptor_set_for_pipeline_0; + VkDescriptorSet descriptor_set_for_pipeline_1; + + CamControlInfo my_cam_control_info; + vec3 Buba_control_info; + + bool dt_transfer_required; +} vulkan_ctx_r0; + +typedef struct { + /* Memory settings */ + VkExtent2D sane_image_extent_limit; + /* Globals */ + struct wl_display *wl_display; + struct wl_registry *wl_registry; + struct wl_compositor *wl_compositor; + struct xdg_wm_base *xdg_wm_base; + struct wl_seat *wl_seat; + /* Objects */ + struct wl_surface *wl_surface; + struct wl_callback* wl_callback; + struct xdg_surface *xdg_surface; + struct xdg_toplevel *xdg_toplevel; + /* vulkan objects */ + vulkan_ctx_r0 vk_ctx; + /* inputs */ + struct wl_pointer* pointer; + struct wl_keyboard* keyboard; + /* xkb */ + struct xkb_state* xkb_state; + struct xkb_context* xkb_context; + struct xkb_keymap* xkb_keymap; + /* app state */ + uint32_t last_frame_time; + int32_t width_heard; + int32_t height_heard; + int32_t width_confirmed; + int32_t height_confirmed; + bool closed; + bool first_0x80_keys[0x80]; + /* framerate counting */ + U32 frame_count_since_key; + margaret_ns_time prev_key_frame_time; +} state_r0; + +void recreate_swapchain(state_r0 *state) { // We are about stop program and rebuild our sem+sem+fence synchronization mechanism - vkDeviceWaitIdle(device); - Jane_r0_destroy(device, *jane); - *jane = Jane_r0_create(device); - VkSwapchainKHR old_swapchain = MargaretSwapchainBundle_pop_swapchain_drop_rest(device, *swfb); + vkDeviceWaitIdle(state->vk_ctx.device); + Jane_r0_destroy(state->vk_ctx.device, state->vk_ctx.jane); + state->vk_ctx.jane = Jane_r0_create(state->vk_ctx.device); + VkSwapchainKHR old_swapchain = MargaretSwapchainBundle_pop_swapchain_drop_rest( + state->vk_ctx.device, state->vk_ctx.swfb); // old swfb is 83% dropped + VkExtent2D extent = state->width_confirmed <= 0 || state->height_confirmed <= 0 ? + state->sane_image_extent_limit : (VkExtent2D){ state->width_confirmed, state->height_confirmed }; + ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details( - physical_device, surface, sane_image_extent_limit); + state->vk_ctx.physical_device, state->vk_ctx.surface, extent); if (swapchain_details_res.variant != Result_Ok) abortf("swapchain_details_res.variant != Result_Ok"); MargaretChosenSwapchainDetails swapchain_details = swapchain_details_res.ok; - MargaretSwapchainBundle new_swfb = MargaretSwapchainBundle_new(device, queue_fam, swapchain_details, surface, - render_pass, swfb->swapchain); - vkDestroySwapchainKHR(device, old_swapchain, NULL); + MargaretSwapchainBundle new_swfb = MargaretSwapchainBundle_new(state->vk_ctx.device, state->vk_ctx.queue_fam, + swapchain_details, state->vk_ctx.surface, state->vk_ctx.render_pass_1, state->vk_ctx.swfb.swapchain); + vkDestroySwapchainKHR(state->vk_ctx.device, old_swapchain, NULL); // Now old swfb is 100% dropped - *swfb = new_swfb; + state->vk_ctx.swfb = new_swfb; } +void update_state(state_r0* state, uint32_t dur) { + float fl = (float)dur / 1000; -void prepare_shaders() { - int ret = system("./test_shader_compile.sh"); - if (ret == -1) { - abortf("system() failed\n"); - } else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) { - abortf("Error: script exited with code %d\n", WEXITSTATUS(ret)); - } else if (!WIFEXITED(ret)) { - abortf("Error: script terminated abnormally\n"); + state->vk_ctx.scene.anim_time += fl; + if (state->first_0x80_keys[XKB_KEY_w]) + CamControlInfo_forward(&state->vk_ctx.my_cam_control_info, fl); + if (state->first_0x80_keys[XKB_KEY_s]) + CamControlInfo_backward(&state->vk_ctx.my_cam_control_info, fl); + if (state->first_0x80_keys[XKB_KEY_a]) + CamControlInfo_left(&state->vk_ctx.my_cam_control_info, fl); + if (state->first_0x80_keys[XKB_KEY_d]) + CamControlInfo_right(&state->vk_ctx.my_cam_control_info, fl); + if (state->first_0x80_keys[XKB_KEY_q]) + CamControlInfo_down(&state->vk_ctx.my_cam_control_info, fl); + if (state->first_0x80_keys[XKB_KEY_e]) + CamControlInfo_up(&state->vk_ctx.my_cam_control_info, fl); + + if (state->first_0x80_keys[XKB_KEY_j]) { + state->vk_ctx.Buba_control_info.x -= fl; + VecGenericMeshInstance_mat(&VecUsedModelOnScene_mat(&state->vk_ctx.scene.models, 1)->instances, 0)->model_t = + marie_translation_mat4(state->vk_ctx.Buba_control_info); + state->vk_ctx.dt_transfer_required = true; + } + if (state->first_0x80_keys[XKB_KEY_k]) { + state->vk_ctx.Buba_control_info.z -= fl; + VecGenericMeshInstance_mat(&VecUsedModelOnScene_mat(&state->vk_ctx.scene.models, 1)->instances, 0)->model_t = + marie_translation_mat4(state->vk_ctx.Buba_control_info); + state->vk_ctx.dt_transfer_required = true; + } + if (state->first_0x80_keys[XKB_KEY_l]) { + state->vk_ctx.Buba_control_info.z += fl; + VecGenericMeshInstance_mat(&VecUsedModelOnScene_mat(&state->vk_ctx.scene.models, 1)->instances, 0)->model_t = + marie_translation_mat4(state->vk_ctx.Buba_control_info); + state->vk_ctx.dt_transfer_required = true; + } + if (state->first_0x80_keys[XKB_KEY_semicolon]) { + state->vk_ctx.Buba_control_info.x += fl; + VecGenericMeshInstance_mat(&VecUsedModelOnScene_mat(&state->vk_ctx.scene.models, 1)->instances, 0)->model_t = + marie_translation_mat4(state->vk_ctx.Buba_control_info); + state->vk_ctx.dt_transfer_required = true; } } -typedef struct { - U8 r; U8 g; U8 b; U8 a; -} color8rgba; +void vulkano_frame_drawing(state_r0* state) { + and_again: + vkWaitForFences(state->vk_ctx.device, 1, &state->vk_ctx.jane.in_flight_fence, VK_TRUE, UINT64_MAX); + uint32_t ij; + VkResult aq_ret = vkAcquireNextImageKHR( + state->vk_ctx.device, state->vk_ctx.swfb.swapchain, + UINT64_MAX, state->vk_ctx.jane.image_available_semaphore, VK_NULL_HANDLE, &ij + ); + if (aq_ret == VK_ERROR_OUT_OF_DATE_KHR) { + fprintf(stderr, "vkAcquireNextImageKHR: VK_ERROR_OUT_OF_DATE_KHR\n"); + recreate_swapchain(state); + goto and_again; + } else if (aq_ret == VK_SUBOPTIMAL_KHR) { + fprintf(stderr, "vkAcquireNextImageKHR: VK_SUBOPTIMAL_KHR\n"); + recreate_swapchain(state); + goto and_again; + } else if (aq_ret != VK_SUCCESS) { + abortf("vkAcquireNextImageKHR"); + } + + vkResetFences(state->vk_ctx.device, 1, &state->vk_ctx.jane.in_flight_fence); + + state->vk_ctx.scene.color = (VkClearColorValue){{0, 0.5f, 0.9f, 1}}; + mat4 projection_matrix = marie_perspective_projection_fov_mat4( + (float)state->width_confirmed, (float)state->height_confirmed, + state->vk_ctx.my_cam_control_info.fov, 0.01f, 1000); + mat4 camera_rotation_matrix = marie_mat3_to_mat4_transposed(state->vk_ctx.my_cam_control_info.cam_basis); + mat4 camera_translation_matrix = marie_translation_mat4(vec3_minus(state->vk_ctx.my_cam_control_info.pos)); + mat4 t_mat = mat4_mul_mat4(projection_matrix, mat4_mul_mat4(camera_rotation_matrix, camera_translation_matrix)); + + if (state->vk_ctx.dt_transfer_required){ + assert(state->vk_ctx.scene.spotlights.len < pipeline_0_ubo_spotlight_max_count); + assert(state->vk_ctx.scene.point_lights.len < pipeline_0_ubo_point_light_max_count); + copy_scene_info_to_buffer_and_rerecord_full_copy_command_buffer( + state->vk_ctx.transfer_command_buffer, state->vk_ctx.host_mem_buffer.buffer, + state->vk_ctx.host_mem_buffer_mem, &state->vk_ctx.scene, state->vk_ctx.device_lighting_ubo.buffer, + state->vk_ctx.device_instance_attrs_for_all_generic_meshes.buffer); + VkCommandBuffer command_buffers[1] = { state->vk_ctx.transfer_command_buffer }; + VkSemaphore signaling_semaphores[1] = { state->vk_ctx.jane.in_frame_transfer_complete }; + VkSubmitInfo submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .commandBufferCount = ARRAY_SIZE(command_buffers), + .pCommandBuffers = command_buffers, + .signalSemaphoreCount = ARRAY_SIZE(signaling_semaphores), + .pSignalSemaphores = signaling_semaphores, + }; + if (vkQueueSubmit(state->vk_ctx.queues.graphics_queue, 1, &submit_info, NULL) != VK_SUCCESS) + abortf("vkQueueSubmit\n"); + } + + reset_and_record_command_buffer_0( + state->vk_ctx.rendering_command_buffer_0, state->vk_ctx.render_pass_0, &state->vk_ctx.pipeline_hands_0, + state->vk_ctx.IT1_framebuffer, state->vk_ctx.device_IT1_image.image, state->vk_ctx.swfb.extent, + &state->vk_ctx.scene, + state->vk_ctx.descriptor_set_for_pipeline_0, t_mat, state->vk_ctx.my_cam_control_info.pos); + + reset_and_record_command_buffer_1(state->vk_ctx.rendering_command_buffer_1, state->vk_ctx.render_pass_1, + &state->vk_ctx.pipeline_hands_1, + *VecVkFramebuffer_at(&state->vk_ctx.swfb.framebuffers, ij), + state->vk_ctx.swfb.extent, + state->sane_image_extent_limit, &state->vk_ctx.scene, state->vk_ctx.descriptor_set_for_pipeline_1); + + { + VkSemaphore waiting_for_semaphores_if_dt_transfer_required[1] = { + state->vk_ctx.jane.in_frame_transfer_complete + }; + VkPipelineStageFlags waiting_stages_if_dt_transfer_required[1] = { + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT + }; + assert(ARRAY_SIZE(waiting_for_semaphores_if_dt_transfer_required) == + ARRAY_SIZE(waiting_stages_if_dt_transfer_required)); + VkCommandBuffer command_buffers[1] = {state->vk_ctx.rendering_command_buffer_0}; + VkSemaphore signaling_semaphores[1] = { state->vk_ctx.jane.rendered_to_IT1_semaphore }; + VkSubmitInfo submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + + // We wait for `waiting_for_semaphores` before THESE stages + // waitSemaphoreCount specifies size for both pWaitSemaphores and pWaitDstStageMask + .waitSemaphoreCount = state->vk_ctx.dt_transfer_required ? + ARRAY_SIZE(waiting_for_semaphores_if_dt_transfer_required) : 0, + .pWaitSemaphores = state->vk_ctx.dt_transfer_required ? + waiting_for_semaphores_if_dt_transfer_required : NULL, + .pWaitDstStageMask = state->vk_ctx.dt_transfer_required ? + waiting_stages_if_dt_transfer_required : NULL, + + .commandBufferCount = ARRAY_SIZE(command_buffers), + .pCommandBuffers = command_buffers, + + .signalSemaphoreCount = ARRAY_SIZE(signaling_semaphores), + .pSignalSemaphores = signaling_semaphores, + }; + if (vkQueueSubmit(state->vk_ctx.queues.graphics_queue, 1, &submit_info, NULL) != VK_SUCCESS) + abortf("vkQueueSubmit"); + } + { + VkSemaphore waiting_for_semaphores[2] = { + state->vk_ctx.jane.image_available_semaphore, + state->vk_ctx.jane.rendered_to_IT1_semaphore }; + VkPipelineStageFlags waiting_stages[2] = { + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + // VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT + }; + assert(ARRAY_SIZE(waiting_for_semaphores) == ARRAY_SIZE(waiting_stages)); + VkCommandBuffer command_buffers[1] = { state->vk_ctx.rendering_command_buffer_1 }; + VkSemaphore signaling_semaphores[1] = { + *VecVkSemaphore_at(&state->vk_ctx.swfb.rendering_finished_here_semaphores, ij) + }; + VkSubmitInfo cmd_submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + + .waitSemaphoreCount = ARRAY_SIZE(waiting_for_semaphores), + .pWaitSemaphores = waiting_for_semaphores, + .pWaitDstStageMask = waiting_stages, + + .commandBufferCount = ARRAY_SIZE(command_buffers), + .pCommandBuffers = command_buffers, + + .signalSemaphoreCount = ARRAY_SIZE(signaling_semaphores), + .pSignalSemaphores = signaling_semaphores, + }; + + if (vkQueueSubmit(state->vk_ctx.queues.graphics_queue, 1, &cmd_submit_info, state->vk_ctx.jane.in_flight_fence) != VK_SUCCESS) + abortf("vkQueueSubmit"); + } + + { + VkSemaphore waiting_for_semaphores[] = { + *VecVkSemaphore_at(&state->vk_ctx.swfb.rendering_finished_here_semaphores, ij) + }; + VkSwapchainKHR swapchains[] = { state->vk_ctx.swfb.swapchain }; + uint32_t image_indices[] = { ij }; + assert( ARRAY_SIZE(swapchains) == ARRAY_SIZE(image_indices) ); + + VkPresentInfoKHR present_info = { + .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, + .waitSemaphoreCount = ARRAY_SIZE(waiting_for_semaphores), + .pWaitSemaphores = waiting_for_semaphores, + + .swapchainCount = ARRAY_SIZE(swapchains), + .pSwapchains = swapchains, + .pImageIndices = image_indices, + .pResults = NULL, + }; + + VkResult pres_ret = vkQueuePresentKHR(state->vk_ctx.queues.presentation_queue, &present_info); + // todo: ponder more over this + if (pres_ret == VK_ERROR_OUT_OF_DATE_KHR) { + fprintf(stderr, "vkQueuePresentKHR: VK_ERROR_OUT_OF_DATE_KHR\n"); + recreate_swapchain(state); + goto and_again; + } else if (pres_ret == VK_SUBOPTIMAL_KHR) { + fprintf(stderr, "vkQueuePresentKHR: VK_SUBOPTIMAL_KHR\n"); + recreate_swapchain(state); + goto and_again; + } else if (pres_ret != VK_SUCCESS) { + abortf("vkQueuePresentKHR"); + } + } + state->vk_ctx.dt_transfer_required = false; + margaret_ns_time frame_B0 = margaret_clock_gettime_monotonic_raw(); + state->frame_count_since_key++; + if (margaret_ns_time_sec_diff(state->prev_key_frame_time, frame_B0) > 1.0) { + float fps = (float)state->frame_count_since_key / margaret_ns_time_sec_diff(state->prev_key_frame_time, frame_B0); + printf("FPS: %0.1lf\n", fps); + state->frame_count_since_key = 0; + state->prev_key_frame_time = frame_B0; + } +} + + +static void main_h_xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial){ + state_r0 *state = data; + printf("XDG surface configured! (%d %d)\n", state->width_heard, state->height_heard); + state->width_confirmed = state->width_heard; + state->height_confirmed = state->height_heard; + xdg_surface_ack_configure(xdg_surface, serial); + recreate_swapchain(state); + vulkano_frame_drawing(state); +} + +static const struct xdg_surface_listener xdg_surface_listener = { + .configure = main_h_xdg_surface_configure, +}; + +static void main_h_xdg_toplevel_configure( + void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states + ){ + state_r0 *state = data; + uint32_t *conf_state; + wl_array_for_each(conf_state, states) { + printf("A state of xdg toplevel: %u\n", *conf_state); + } + printf("XDG toplevel configured to (%d %d)\n", width, height); + if (width <= 0 || height <= 0) + return; + state->width_heard = width; + state->height_heard = height; +} + +static void main_h_xdg_toplevel_close(void *data, struct xdg_toplevel *toplevel){ + state_r0 *state = data; + state->closed = true; +} + +static const struct xdg_toplevel_listener main_h_xdg_toplevel_listener = { + .configure = main_h_xdg_toplevel_configure, + .close = main_h_xdg_toplevel_close, +}; + +static void main_h_xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial){ + xdg_wm_base_pong(xdg_wm_base, serial); +} + +static const struct xdg_wm_base_listener main_h_xdg_wm_base_listener = { + .ping = main_h_xdg_wm_base_ping, +}; + + + +static void main_h_wl_keyboard_keymap( + void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size + ) { + state_r0* state = data; + if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) + abortf("O_o"); + char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (map_shm == MAP_FAILED) + abortf("Couldn't mmap new keymap ha-ha\n"); + + xkb_keymap_unref(state->xkb_keymap); + xkb_state_unref(state->xkb_state); + state->xkb_keymap = xkb_keymap_new_from_string( + state->xkb_context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); + munmap(map_shm, size); + close(fd); + state->xkb_state = xkb_state_new(state->xkb_keymap); + printf("Keymap changed!\n"); + memset(&state->first_0x80_keys, 0, sizeof(state->first_0x80_keys)); +} + +static void main_h_wl_keyboard_enter( + void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys + ) { + state_r0* state = data; + printf("keyboard enter; keys pressed are:\n"); + uint32_t *key; + wl_array_for_each(key, keys) { + uint32_t actual_key = *key + 8; + xkb_keysym_t sym = xkb_state_key_get_one_sym(state->xkb_state, actual_key); + if (sym < 0x80) + state->first_0x80_keys[sym] = true; + } +} + +static void main_h_wl_keyboard_leave( + void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface + ) { + state_r0* state = data; + memset(&state->first_0x80_keys, 0, sizeof(state->first_0x80_keys)); +} + +static void main_h_wl_keyboard_key( + void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t key_action + ) { + state_r0* state = data; + uint32_t actual_key = key + 8; + /* It actually could be nokey keysym. You never know without checking */ + xkb_keysym_t keysym = xkb_state_key_get_one_sym(state->xkb_state, actual_key); + if (keysym < 0x80 && key_action == WL_KEYBOARD_KEY_STATE_RELEASED) { + state->first_0x80_keys[keysym] = false; + } else if (keysym < 0x80 && key_action == WL_KEYBOARD_KEY_STATE_PRESSED) { + state->first_0x80_keys[keysym] = true; + } + if (key_action == WL_KEYBOARD_KEY_STATE_RELEASED) { + if (keysym == XKB_KEY_1) { + vec3 p = state->vk_ctx.my_cam_control_info.pos; + VecPipeline0PointLight_mat(&state->vk_ctx.scene.point_lights, 0)->pos = p; + printf("Point light source pos set to %f %f %f\n", p.x, p.y, p.z); + state->vk_ctx.dt_transfer_required = true; + } else if (keysym == XKB_KEY_2) { + state->vk_ctx.scene.hdr_factor /= 1.05f; + printf("hdr factor decreased to %f\n", state->vk_ctx.scene.hdr_factor); + } else if (keysym == XKB_KEY_3) { + state->vk_ctx.scene.hdr_factor *= 1.05f; + printf("hdr factor increased to %f\n", state->vk_ctx.scene.hdr_factor); + } + } +} + +static void main_h_wl_keyboard_modifiers( + void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, + uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group + ) { + state_r0* state = data; + xkb_state_update_mask(state->xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group); +} + +static void main_h_wl_keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, int32_t rate, int32_t delay){ + printf("Repeat timings changed: rate = %d, delay = %d\n", rate, delay); +} + +static const struct wl_keyboard_listener main_h_wl_keyboard_listener = { + .keymap = main_h_wl_keyboard_keymap, + .enter = main_h_wl_keyboard_enter, + .leave = main_h_wl_keyboard_leave, + .key = main_h_wl_keyboard_key, + .modifiers = main_h_wl_keyboard_modifiers, + .repeat_info = main_h_wl_keyboard_repeat_info, +}; + + +static void main_h_wl_pointer_enter( + void *data, struct wl_pointer *wl_pointer, uint32_t serial, + struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y + ) { + state_r0 *state = data; +} + +static void main_h_wl_pointer_leave( + void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface + ) { + state_r0 *state = data; +} + +static void main_h_wl_pointer_motion( + void *data,struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y + ) { + state_r0 *state = data; + CamControlInfo_update_direction(&state->vk_ctx.my_cam_control_info, + state->width_confirmed, state->height_confirmed, + (float)surface_x / 256.f, (float)surface_y / 256.f); +} + +static void main_h_wl_pointer_button( + void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t btn_action + ) { + state_r0 *state = data; +} + +static void main_h_wl_pointer_axis( + void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value + ) { + state_r0 *state = data; +} + +static void main_h_wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { + state_r0 *state = data; +} + +const struct wl_pointer_listener main_h_wl_pointer_listener = { + .enter = main_h_wl_pointer_enter, + .leave = main_h_wl_pointer_leave, + .motion = main_h_wl_pointer_motion, + .button = main_h_wl_pointer_button, + .axis = main_h_wl_pointer_axis, + .frame = main_h_wl_pointer_frame +}; + +static void main_h_wl_seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) { + state_r0* state = data; + if (capabilities & WL_SEAT_CAPABILITY_POINTER) { + state->pointer = wl_seat_get_pointer(wl_seat); + if (!state->pointer) + abortf("wl_seat_get_pointer\n"); + wl_pointer_add_listener(state->pointer, &main_h_wl_pointer_listener, state); + } + if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { + state->keyboard = wl_seat_get_keyboard(wl_seat); + if (!state->keyboard) + abortf("wl_seat_get_keyboard\n"); + wl_keyboard_add_listener(state->keyboard, &main_h_wl_keyboard_listener, state); + } +} + +static void main_h_wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) { + printf("Our seat name: %s\n", name); +} + +static const struct wl_seat_listener main_h_wl_seat_listener = { + .capabilities = main_h_wl_seat_capabilities, + .name = main_h_wl_seat_name, +}; + +static void main_h_wl_registry_global( + void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, uint32_t version + ) { + state_r0 *state = data; + if (strcmp(interface, wl_compositor_interface.name) == 0) { + state->wl_compositor = wl_registry_bind(wl_registry, name, &wl_compositor_interface, 4); + if (!state->wl_compositor) + abortf("wl_registry_bind\n"); + } else if (strcmp(interface, xdg_wm_base_interface.name) == 0) { + state->xdg_wm_base = wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1); + if (!state->xdg_wm_base) + abortf("wl_registry_bind\n"); + xdg_wm_base_add_listener(state->xdg_wm_base, &main_h_xdg_wm_base_listener, state); + } else if (strcmp(interface, wl_seat_interface.name) == 0) { + if (state->wl_seat) { + printf("We got second seat, but we only need one\n"); + return; + } + state->wl_seat = wl_registry_bind(wl_registry, name, &wl_seat_interface, 4); + if (!state->wl_seat) + abortf("wl_registry_bind\n"); + wl_seat_add_listener(state->wl_seat, &main_h_wl_seat_listener, state); + } +} + +static void main_h_wl_registry_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name){ + +} + +static const struct wl_registry_listener main_h_wl_registry_listener = { + .global = main_h_wl_registry_global, + .global_remove = main_h_wl_registry_global_remove, +}; + +static const struct wl_callback_listener main_h_wl_surface_frame_listener; + +static void main_h_wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time){ + state_r0 *state = data; + wl_callback_destroy(cb); + state->wl_callback = wl_surface_frame(state->wl_surface); + if (!state->wl_callback) + abortf("wl_surface_frame\n"); + wl_callback_add_listener(state->wl_callback, &main_h_wl_surface_frame_listener, state); + + if (state->last_frame_time != 0) { + update_state(state, time - state->last_frame_time); + } + vulkano_frame_drawing(state); + state->last_frame_time = time; +} + +static const struct wl_callback_listener main_h_wl_surface_frame_listener = { + .done = main_h_wl_surface_frame_done, +}; + + + +void calling_system_func(const char* command) { + int ret = system(command); + if (ret == -1) { + abortf("system() failed\n"); + } else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) { + abortf("Error: command exited with code %d\n", WEXITSTATUS(ret)); + } else if (!WIFEXITED(ret)) { + abortf("Error: command terminated abnormally\n"); + } +} + +void compile_shader_dir(SpanU8 name) { + make_dir_nofail("shaders/spv"); + VecU8 spv_shader_dir_name = VecU8_fmt("shaders/spv/%s%c", name, 0); + make_dir_nofail((CSTR)spv_shader_dir_name.buf); + VecU8_drop(spv_shader_dir_name); + VecU8 vert_cmd = VecU8_fmt("glslc -o shaders/spv/%s/vert.spv shaders/glsl/%s/%s.vert%c", name, name, name, 0); + calling_system_func((CSTR)vert_cmd.buf); + VecU8_drop(vert_cmd); + VecU8 frag_cmd = VecU8_fmt("glslc -o shaders/spv/%s/frag.spv shaders/glsl/%s/%s.frag%c", name, name, name, 0); + calling_system_func((CSTR)frag_cmd.buf); + VecU8_drop(frag_cmd); +} + int main() { - prepare_shaders(); + compile_shader_dir(cstr("0")); + compile_shader_dir(cstr("1")); SpanU8 GPU = cstr("nvidia"); SpanU8 bugged_GPU = cstr("nothere"); @@ -1002,147 +1399,185 @@ int main() { const U32 MAX_WIN_HEIGHT = 1080; VkExtent2D sane_image_extent_limit = {MAX_WIN_WIDTH, MAX_WIN_HEIGHT}; - MargaretSingleWindowSetup_XlibFlavour x = MargaretSingleWindowSetup_XlibFlavour_new(); - Margaret_WEP wep = Margaret_WEP_new(x.dpy, x.win); - XMapWindow(x.dpy, x.win); + state_r0 state = {0}; + state.sane_image_extent_limit = (VkExtent2D){1000, 700}; - MargaretInstanceAndItsDebug inst_hands = MargaretInstanceAndItsDebug_new_xlib_flavour(ENABLE_VALIDATION_LAYERS); - VkInstance instance = inst_hands.instance; + state.wl_display = wl_display_connect(NULL); + if (!state.wl_display) + abortf("Could not connect"); + state.wl_registry = wl_display_get_registry(state.wl_display); + if (!state.wl_registry) + abortf("wl_display_get_registry"); + wl_registry_add_listener(state.wl_registry, &main_h_wl_registry_listener, &state); + wl_display_roundtrip(state.wl_display); + if (!state.wl_compositor) + abortf("No wl_compositor"); + if (!state.xdg_wm_base) + abortf("No xdg_wm_base"); + state.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!state.xkb_context) + abortf("xkb_context_new\n"); + state.wl_surface = wl_compositor_create_surface(state.wl_compositor); + if (!state.wl_surface) + abortf("wl_compositor_create_surface\n"); + state.xdg_surface = xdg_wm_base_get_xdg_surface( + state.xdg_wm_base, state.wl_surface); + if (!state.xdg_surface) + abortf("xdg_wm_base_get_xdg_surface\n"); + xdg_surface_add_listener(state.xdg_surface, &xdg_surface_listener, &state); + state.xdg_toplevel = xdg_surface_get_toplevel(state.xdg_surface); + if (!state.xdg_toplevel) + abortf("xdg_surface_get_toplevel\n"); + xdg_toplevel_add_listener(state.xdg_toplevel, &main_h_xdg_toplevel_listener, &state); + xdg_toplevel_set_title(state.xdg_toplevel, "r3"); + xdg_toplevel_set_app_id(state.xdg_toplevel, "r3"); + wl_surface_commit(state.wl_surface); + + state.wl_callback = wl_surface_frame(state.wl_surface); + if (!state.wl_callback) + abortf("wl_surface_frame\n"); + wl_callback_add_listener(state.wl_callback, &main_h_wl_surface_frame_listener, &state); + + state.vk_ctx.instance_and_debug = MargaretInstanceAndItsDebug_new(ENABLE_VALIDATION_LAYERS); + VkInstance instance = state.vk_ctx.instance_and_debug.instance; // print_instance_available_extensions(instance); // print_instance_available_layers(instance); - VkSurfaceKHR surface = margaret_create_surface_x_dunk(instance, &x); + state.vk_ctx.surface = margaret_create_surface(instance, state.wl_display, state.wl_surface); - VkPhysicalDevice physical_device = margaret_select_one_physical_device( - instance, surface, GPU, bugged_GPU, sane_image_extent_limit); + state.vk_ctx.physical_device = margaret_select_one_physical_device( + instance, state.vk_ctx.surface, GPU, bugged_GPU, sane_image_extent_limit); // print_physical_device_available_extensions(physical_device); - ResultMargaretChosenQueueFamiliesOrSpanU8 queue_fam_res = margaret_choose_good_queue_families(physical_device, surface); + ResultMargaretChosenQueueFamiliesOrSpanU8 queue_fam_res = margaret_choose_good_queue_families( + state.vk_ctx.physical_device, state.vk_ctx.surface); if (queue_fam_res.variant != Result_Ok) abortf("queue_fam_res.variant != Result_Ok"); - MargaretChosenQueueFamilies queue_fam = queue_fam_res.ok; + state.vk_ctx.queue_fam = queue_fam_res.ok; - VkDevice device = margaret_create_logical_device(physical_device, queue_fam); + state.vk_ctx.device = margaret_create_logical_device(state.vk_ctx.physical_device, state.vk_ctx.queue_fam); - VkQueue graphics_queue; - vkGetDeviceQueue(device, queue_fam.for_graphics, 0, &graphics_queue); - VkQueue presentation_queue; - vkGetDeviceQueue(device, queue_fam.for_presentation, 0, &presentation_queue); + vkGetDeviceQueue(state.vk_ctx.device, state.vk_ctx.queue_fam.for_graphics, 0, &state.vk_ctx.queues.graphics_queue); + vkGetDeviceQueue(state.vk_ctx.device, state.vk_ctx.queue_fam.for_presentation, 0, &state.vk_ctx.queues.presentation_queue); ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details( - physical_device, surface, sane_image_extent_limit); + state.vk_ctx.physical_device, state.vk_ctx.surface, sane_image_extent_limit); if (swapchain_details_res.variant != Result_Ok) abortf("swapchain_details_res.variant != Result_Ok"); - // We hope that the image format won't be changed even when window gets resized - // (swapchain_details.surface_format.format) - OptionVkFormat zbuffer_format = margaret_find_supported_zbuffer_format(physical_device); + OptionVkFormat zbuffer_format = margaret_find_supported_zbuffer_format(state.vk_ctx.physical_device); if (zbuffer_format.variant != Option_Some) abortf("Could not find supported zbuffer format\n"); - OptionVkFormat IT1_format = margaret_find_supported_hdr_buffer_format(physical_device); + state.vk_ctx.zbuffer_format = zbuffer_format.some; + OptionVkFormat IT1_format = margaret_find_supported_hdr_buffer_format(state.vk_ctx.physical_device); if (IT1_format.variant != Option_Some) abortf("Could not find supported hdr buffer format\n"); + state.vk_ctx.IT1_format = IT1_format.some; - VkRenderPass render_pass_0 = create_render_pass_0(device, IT1_format.some, zbuffer_format.some); - PipelineHands pipeline_hands_0 = create_graphics_pipeline_0(device, render_pass_0, 0); + state.vk_ctx.render_pass_0 = create_render_pass_0(state.vk_ctx.device, IT1_format.some, zbuffer_format.some); + state.vk_ctx.pipeline_hands_0 = create_graphics_pipeline_0(state.vk_ctx.device, state.vk_ctx.render_pass_0, 0); - VkRenderPass render_pass_1 = create_render_pass_1(device, swapchain_details_res.ok.surface_format.format); - PipelineHands pipeline_hands_1 = create_graphics_pipeline_1(device, render_pass_1, 0); + state.vk_ctx.render_pass_1 = create_render_pass_1(state.vk_ctx.device, swapchain_details_res.ok.surface_format.format); + state.vk_ctx.pipeline_hands_1 = create_graphics_pipeline_1(state.vk_ctx.device, state.vk_ctx.render_pass_1, 0); - MargaretSwapchainBundle swfb = MargaretSwapchainBundle_new(device, queue_fam, swapchain_details_res.ok, surface, render_pass_1, NULL); + state.vk_ctx.swfb = MargaretSwapchainBundle_new( + state.vk_ctx.device, state.vk_ctx.queue_fam, swapchain_details_res.ok, + state.vk_ctx.surface, state.vk_ctx.render_pass_1, NULL); - SceneTemplate scene_template = {.models = VecModelInSceneTemplate_new(), + state.vk_ctx.scene_template = (SceneTemplate){.models = VecModelInSceneTemplate_new(), .point_lights_max_count = pipeline_0_ubo_point_light_max_count, .spotlights_max_count = pipeline_0_ubo_spotlight_max_count}; - VecModelInSceneTemplate_append(&scene_template.models, + VecModelInSceneTemplate_append(&state.vk_ctx.scene_template.models, (ModelInSceneTemplate){.topology = generate_one_fourth_of_a_cylinder(10, 2, 6), .max_instance_count = 100}); - VecModelInSceneTemplate_append(&scene_template.models, + VecModelInSceneTemplate_append(&state.vk_ctx.scene_template.models, (ModelInSceneTemplate){.topology = generate_one_fourth_of_a_cylinder(5, 5, 10), .max_instance_count = 1}); - // TextureDataR8G8B8A8 wood_texture_data = generate_texture_for_one_fourth_of_a_cylinder(20, 10, 2, 6); // todo: learn how to use libpng - TextureDataR8G8B8A8 cyl_1_diffuse_tex = TextureDataR8G8B8A8_read_from_file("test_textures/log_10_2_6.r8g8b8a8"); + state.vk_ctx.cyl_1_diffuse_tex = TextureDataR8G8B8A8_read_from_file("textures/log_10_2_6.r8g8b8a8"); // todo: learn how to write texture immediately from file to mapped host memory buffer // todo: and at the same time I need to add methods to convert between these formats - TextureDataR8G8B8A8 cyl_1_normal_tex = TextureDataR8G8B8A8_read_from_file("test_textures/log_10_2_6_NORMAL.r8g8b8a8"); + state.vk_ctx.cyl_1_normal_tex = TextureDataR8G8B8A8_read_from_file("textures/log_10_2_6_NORMAL.r8g8b8a8"); - // todo: kill myself + // todo: kill myself (update: still WiP) // We have only one staging buffer in host memory (because we don't really need more) - MargaretBufferInMemoryInfo host_mem_buffer = (MargaretBufferInMemoryInfo){ .sz = - MAX_U64(SceneTemplate_get_space_for_initial_model_topology_transfer(&scene_template), - MAX_U64(SceneTemplate_get_space_needed_for_widest_state_transfer(&scene_template), - MAX_U64(TextureDataR8G8B8A8_get_size_in_bytes(&cyl_1_diffuse_tex), - MAX_U64(TextureDataR8G8B8A8_get_size_in_bytes(&cyl_1_normal_tex), 0)))) + state.vk_ctx.host_mem_buffer = (MargaretBufferInMemoryInfo){ .sz = + MAX_U64(SceneTemplate_get_space_for_initial_model_topology_transfer(&state.vk_ctx.scene_template), + MAX_U64(SceneTemplate_get_space_needed_for_widest_state_transfer(&state.vk_ctx.scene_template), + MAX_U64(TextureDataR8G8B8A8_get_size_in_bytes(&state.vk_ctx.cyl_1_diffuse_tex), + MAX_U64(TextureDataR8G8B8A8_get_size_in_bytes(&state.vk_ctx.cyl_1_normal_tex), 0)))) , .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT }; - PtrMargaretBufferInMemoryInfo host_mem_buffer_SPAN[1] = {&host_mem_buffer}; - VkDeviceMemory host_mem = margaret_initialize_buffers_and_images(physical_device, device, + PtrMargaretBufferInMemoryInfo host_mem_buffer_SPAN[1] = {&state.vk_ctx.host_mem_buffer}; + state.vk_ctx.host_mem = margaret_initialize_buffers_and_images(state.vk_ctx.physical_device, state.vk_ctx.device, (MutSpanPtrMargaretBufferInMemoryInfo){.data = host_mem_buffer_SPAN, .len = 1}, (MutSpanPtrMargaretImageInMemoryInfo){ 0 }, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); // todo: split this in two (or maybe even better: merge it all into one/two buffer and use offsets - VecMargaretBufferInMemoryInfo device_ebo_and_vbo_buffers_for_generic_meshes = VecMargaretBufferInMemoryInfo_new(); - for (size_t mi = 0; mi < scene_template.models.len; mi++) { - const ModelInSceneTemplate* M = VecModelInSceneTemplate_at(&scene_template.models, mi); - VecMargaretBufferInMemoryInfo_append(&device_ebo_and_vbo_buffers_for_generic_meshes, + state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes = VecMargaretBufferInMemoryInfo_new(); + for (size_t mi = 0; mi < state.vk_ctx.scene_template.models.len; mi++) { + const ModelInSceneTemplate* M = VecModelInSceneTemplate_at(&state.vk_ctx.scene_template.models, mi); + VecMargaretBufferInMemoryInfo_append(&state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes, GenericMeshVertex_buffer_crinfo_of_gpu_vbo(M->topology.vertices.len)); - VecMargaretBufferInMemoryInfo_append(&device_ebo_and_vbo_buffers_for_generic_meshes, + VecMargaretBufferInMemoryInfo_append(&state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes, margaret_prep_buffer_mem_info_of_gpu_ebo(M->topology.indexes.len)); } - MargaretBufferInMemoryInfo device_lighting_ubo = margaret_prep_buffer_mem_info_of_gpu_ubo(sizeof(Pipeline0UBO)); - MargaretBufferInMemoryInfo device_instance_attrs_for_all_generic_meshes = (MargaretBufferInMemoryInfo){ - .sz = SceneTemplate_get_space_needed_for_all_instance_attributes(&scene_template), + state.vk_ctx.device_lighting_ubo = margaret_prep_buffer_mem_info_of_gpu_ubo(sizeof(Pipeline0UBO)); + state.vk_ctx.device_instance_attrs_for_all_generic_meshes = (MargaretBufferInMemoryInfo){ + .sz = SceneTemplate_get_space_needed_for_all_instance_attributes(&state.vk_ctx.scene_template), .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT }; VecPtrMargaretBufferInMemoryInfo device_mem_buffers_SPAN = VecPtrMargaretBufferInMemoryInfo_new(); - for (size_t i = 0; i < device_ebo_and_vbo_buffers_for_generic_meshes.len; i++) { + for (size_t i = 0; i < state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes.len; i++) { VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, - VecMargaretBufferInMemoryInfo_mat(&device_ebo_and_vbo_buffers_for_generic_meshes, i)); + VecMargaretBufferInMemoryInfo_mat(&state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes, i)); } - VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &device_lighting_ubo); - VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &device_instance_attrs_for_all_generic_meshes); - printf("Buffers: %lu\n", device_mem_buffers_SPAN.len); + VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &state.vk_ctx.device_lighting_ubo); + VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &state.vk_ctx.device_instance_attrs_for_all_generic_meshes); - MargaretImageInMemoryInfo device_IT1_image = margaret_prep_image_mem_info_of_colorbuffer(MAX_WIN_WIDTH, MAX_WIN_HEIGHT, IT1_format.some); - MargaretImageInMemoryInfo device_zbuffer_image = margaret_prep_image_mem_info_of_zbuffer(MAX_WIN_WIDTH, MAX_WIN_HEIGHT, zbuffer_format.some); - MargaretImageInMemoryInfo device_cyl_1_diffuse_texture = margaret_prep_image_mem_info_of_gpu_texture_srgba(cyl_1_diffuse_tex.width, - TextureDataR8G8B8A8_get_height(&cyl_1_diffuse_tex)); - MargaretImageInMemoryInfo device_cyl_1_normal_texture = margaret_prep_image_mem_info_of_gpu_texture_srgba(cyl_1_normal_tex.width, - TextureDataR8G8B8A8_get_height(&cyl_1_normal_tex)); + state.vk_ctx.device_IT1_image = margaret_prep_image_mem_info_of_colorbuffer( + MAX_WIN_WIDTH, MAX_WIN_HEIGHT, IT1_format.some); + state.vk_ctx.device_zbuffer_image = margaret_prep_image_mem_info_of_zbuffer( + MAX_WIN_WIDTH, MAX_WIN_HEIGHT, zbuffer_format.some); + state.vk_ctx.device_cyl_1_diffuse_texture = margaret_prep_image_mem_info_of_gpu_texture_srgba( + state.vk_ctx.cyl_1_diffuse_tex.width, TextureDataR8G8B8A8_get_height(&state.vk_ctx.cyl_1_diffuse_tex)); + state.vk_ctx.device_cyl_1_normal_texture = margaret_prep_image_mem_info_of_gpu_texture_srgba( + state.vk_ctx.cyl_1_normal_tex.width, TextureDataR8G8B8A8_get_height(&state.vk_ctx.cyl_1_normal_tex)); PtrMargaretImageInMemoryInfo device_mem_images_SPAN[] = { - &device_IT1_image, &device_zbuffer_image, &device_cyl_1_diffuse_texture, &device_cyl_1_normal_texture + &state.vk_ctx.device_IT1_image, &state.vk_ctx.device_zbuffer_image, &state.vk_ctx.device_cyl_1_diffuse_texture, + &state.vk_ctx.device_cyl_1_normal_texture }; - VkDeviceMemory device_mem = margaret_initialize_buffers_and_images(physical_device, device, + state.vk_ctx.device_mem = margaret_initialize_buffers_and_images(state.vk_ctx.physical_device, state.vk_ctx.device, VecPtrMargaretBufferInMemoryInfo_to_mspan(&device_mem_buffers_SPAN), (MutSpanPtrMargaretImageInMemoryInfo){ .data = device_mem_images_SPAN, .len = ARRAY_SIZE(device_mem_images_SPAN) }, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + /* device_mem_buffers_SPAN invalidated */ + VecPtrMargaretBufferInMemoryInfo_drop(device_mem_buffers_SPAN); - VkCommandPool command_pool = margaret_create_resettable_command_pool(device, queue_fam.for_graphics); - VkCommandBuffer rendering_command_buffer_0 = margaret_allocate_command_buffer(device, command_pool); - VkCommandBuffer rendering_command_buffer_1 = margaret_allocate_command_buffer(device, command_pool); - VkCommandBuffer transfer_command_buffer = margaret_allocate_command_buffer(device, command_pool); + state.vk_ctx.command_pool = margaret_create_resettable_command_pool(state.vk_ctx.device, state.vk_ctx.queue_fam.for_graphics); + state.vk_ctx.rendering_command_buffer_0 = margaret_allocate_command_buffer(state.vk_ctx.device, state.vk_ctx.command_pool); + state.vk_ctx.rendering_command_buffer_1 = margaret_allocate_command_buffer(state.vk_ctx.device, state.vk_ctx.command_pool); + state.vk_ctx.transfer_command_buffer = margaret_allocate_command_buffer(state.vk_ctx.device, state.vk_ctx.command_pool); - Scene scene = Scene_new(); + state.vk_ctx.scene = Scene_new(); { size_t offset_in_attr_buffer = 0; - for (size_t mi = 0; mi < scene_template.models.len; mi++) { - // UsedModelOnScene* ptb = VecUsedModelOnScene_cat() - const ModelInSceneTemplate* M = VecModelInSceneTemplate_at(&scene_template.models, mi); - VecUsedModelOnScene_append(&scene.models, (UsedModelOnScene){ + for (size_t mi = 0; mi < state.vk_ctx.scene_template.models.len; mi++) { + const ModelInSceneTemplate* M = VecModelInSceneTemplate_at(&state.vk_ctx.scene_template.models, mi); + VecUsedModelOnScene_append(&state.vk_ctx.scene.models, (UsedModelOnScene){ .model = (ModelOnScene){ - .vbo = VecMargaretBufferInMemoryInfo_at(&device_ebo_and_vbo_buffers_for_generic_meshes, + .vbo = VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes, 2 * mi + 0)->buffer, - .ebo = VecMargaretBufferInMemoryInfo_at(&device_ebo_and_vbo_buffers_for_generic_meshes, + .ebo = VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes, 2 * mi + 1)->buffer, .indexes = M->topology.indexes.len, }, .instances = VecGenericMeshInstance_new(), - .instance_attr_buf = device_instance_attrs_for_all_generic_meshes.buffer, + .instance_attr_buf = state.vk_ctx.device_instance_attrs_for_all_generic_meshes.buffer, .instance_attr_buf_offset = offset_in_attr_buffer, .limit_max_instance_count = M->max_instance_count }); @@ -1152,98 +1587,104 @@ int main() { for (int X = 0; X < 10; X++) { for (int Z = 0; Z < 10; Z++) { - VecGenericMeshInstance_append(&VecUsedModelOnScene_mat(&scene.models, 0)->instances, + VecGenericMeshInstance_append(&VecUsedModelOnScene_mat(&state.vk_ctx.scene.models, 0)->instances, (GenericMeshInstance){ .model_t = marie_translation_mat4((vec3){11.f * (float)X, -6, 4.f * (float)Z}) }); } } - VecGenericMeshInstance_append(&VecUsedModelOnScene_mat(&scene.models, 1)->instances, (GenericMeshInstance){ + VecGenericMeshInstance_append(&VecUsedModelOnScene_mat(&state.vk_ctx.scene.models, 1)->instances, (GenericMeshInstance){ .model_t = mat4_E }); - void* host_mem_buffer_mem; - if (vkMapMemory(device, host_mem, 0, VK_WHOLE_SIZE, 0, &host_mem_buffer_mem) != VK_SUCCESS) + if (vkMapMemory(state.vk_ctx.device, state.vk_ctx.host_mem, 0, VK_WHOLE_SIZE, 0, &state.vk_ctx.host_mem_buffer_mem) != VK_SUCCESS) abortf("vkMapMemory"); - SceneTemplate_copy_initial_model_topology_and_rerecord_transfer_cmd(&scene_template, &scene, host_mem_buffer_mem, transfer_command_buffer, host_mem_buffer.buffer); + SceneTemplate_copy_initial_model_topology_and_rerecord_transfer_cmd( + &state.vk_ctx.scene_template, &state.vk_ctx.scene, state.vk_ctx.host_mem_buffer_mem, + state.vk_ctx.transfer_command_buffer, state.vk_ctx.host_mem_buffer.buffer); { - VkCommandBuffer command_buffers[1] = { transfer_command_buffer }; - // VkSemaphore signaling_semaphores[1] = { swfb.in_frame_transfer_complete }; + VkCommandBuffer command_buffers[1] = { state.vk_ctx.transfer_command_buffer }; VkSubmitInfo submit_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .commandBufferCount = ARRAY_SIZE(command_buffers), .pCommandBuffers = command_buffers, - // .signalSemaphoreCount = ARRAY_SIZE(signaling_semaphores), - // .pSignalSemaphores = signaling_semaphores, }; - if (vkQueueSubmit(graphics_queue, 1, &submit_info, NULL) != VK_SUCCESS) + if (vkQueueSubmit(state.vk_ctx.queues.graphics_queue, 1, &submit_info, NULL) != VK_SUCCESS) abortf("vkQueueSubmit\n"); } - vkDeviceWaitIdle(device); + vkDeviceWaitIdle(state.vk_ctx.device); { - memcpy(host_mem_buffer_mem, cyl_1_diffuse_tex.pixels.buf, - TextureDataR8G8B8A8_get_size_in_bytes(&cyl_1_diffuse_tex)); - margaret_copy_buffer_to_texture_for_frag_shader_imm(device, command_pool, graphics_queue, - &device_cyl_1_diffuse_texture, host_mem_buffer.buffer); + memcpy(state.vk_ctx.host_mem_buffer_mem, state.vk_ctx.cyl_1_diffuse_tex.pixels.buf, + TextureDataR8G8B8A8_get_size_in_bytes(&state.vk_ctx.cyl_1_diffuse_tex)); + margaret_copy_buffer_to_texture_for_frag_shader_imm( + state.vk_ctx.device, state.vk_ctx.command_pool, state.vk_ctx.queues.graphics_queue, + &state.vk_ctx.device_cyl_1_diffuse_texture, state.vk_ctx.host_mem_buffer.buffer); } - vkDeviceWaitIdle(device); + vkDeviceWaitIdle(state.vk_ctx.device); { - memcpy(host_mem_buffer_mem, cyl_1_normal_tex.pixels.buf, TextureDataR8G8B8A8_get_size_in_bytes(&cyl_1_normal_tex)); - margaret_copy_buffer_to_texture_for_frag_shader_imm(device, command_pool, graphics_queue, - &device_cyl_1_normal_texture, host_mem_buffer.buffer); + memcpy(state.vk_ctx.host_mem_buffer_mem, state.vk_ctx.cyl_1_normal_tex.pixels.buf, + TextureDataR8G8B8A8_get_size_in_bytes(&state.vk_ctx.cyl_1_normal_tex)); + margaret_copy_buffer_to_texture_for_frag_shader_imm( + state.vk_ctx.device, state.vk_ctx.command_pool, state.vk_ctx.queues.graphics_queue, + &state.vk_ctx.device_cyl_1_normal_texture, state.vk_ctx.host_mem_buffer.buffer); } - vkDeviceWaitIdle(device); - + vkDeviceWaitIdle(state.vk_ctx.device); // We sent everything we needed. but host_mem_buffer_mem may be used later // My zbuffer also needs a view - VkImageView zbuffer_view = margaret_create_view_for_image(device, &device_zbuffer_image, VK_IMAGE_ASPECT_DEPTH_BIT); + state.vk_ctx.zbuffer_view = margaret_create_view_for_image(state.vk_ctx.device, + &state.vk_ctx.device_zbuffer_image, VK_IMAGE_ASPECT_DEPTH_BIT); /* Here we create an image view into a temporary IT1 texture and a framebuffer for scene rendering */ - VkImageView IT1_view = margaret_create_view_for_image(device, &device_IT1_image, VK_IMAGE_ASPECT_COLOR_BIT); - VkFramebuffer IT1_framebuffer = create_IT1_framebuffer(device, IT1_view, zbuffer_view, render_pass_0, - MAX_WIN_WIDTH, MAX_WIN_HEIGHT); + state.vk_ctx.IT1_view = margaret_create_view_for_image(state.vk_ctx.device, + &state.vk_ctx.device_IT1_image, VK_IMAGE_ASPECT_COLOR_BIT); + state.vk_ctx.IT1_framebuffer = create_IT1_framebuffer(state.vk_ctx.device, + state.vk_ctx.IT1_view, state.vk_ctx.zbuffer_view, state.vk_ctx.render_pass_0, MAX_WIN_WIDTH, MAX_WIN_HEIGHT); // My cylinder 1 texture needs VkImageView - VkImageView cyl_1_diffuse_texture_view = margaret_create_view_for_image(device, &device_cyl_1_diffuse_texture, VK_IMAGE_ASPECT_COLOR_BIT); + state.vk_ctx.cyl_1_diffuse_texture_view = margaret_create_view_for_image( + state.vk_ctx.device, &state.vk_ctx.device_cyl_1_diffuse_texture, VK_IMAGE_ASPECT_COLOR_BIT); // My cylinder 1 normal texture also needs NkImageView - VkImageView cyl_1_normal_texture_view = margaret_create_view_for_image(device, &device_cyl_1_normal_texture, VK_IMAGE_ASPECT_COLOR_BIT); + state.vk_ctx.cyl_1_normal_texture_view = margaret_create_view_for_image( + state.vk_ctx.device, &state.vk_ctx.device_cyl_1_normal_texture, VK_IMAGE_ASPECT_COLOR_BIT); // Right now I only have one light source - VecPipeline0PointLight_append(&scene.point_lights, (Pipeline0PointLight){.pos = {0}, .color = {100, 100, 100}}); + VecPipeline0PointLight_append(&state.vk_ctx.scene.point_lights, (Pipeline0PointLight){.pos = {0}, .color = {100, 100, 100}}); // These samplers are global for a lot of my future textures - VkSampler linear_sampler = margaret_create_sampler(physical_device, device, true); - VkSampler nearest_sampler = margaret_create_sampler(physical_device, device, false); + state.vk_ctx.linear_sampler = margaret_create_sampler(state.vk_ctx.physical_device, state.vk_ctx.device, true); + state.vk_ctx.nearest_sampler = margaret_create_sampler(state.vk_ctx.physical_device, state.vk_ctx.device, false); - VkDescriptorPool descriptor_pool = margaret_create_descriptor_set_pool(device, 1, 3, 2); - VkDescriptorSet descriptor_set_for_pipeline_0 = margaret_allocate_descriptor_set(device, descriptor_pool, pipeline_hands_0.descriptor_set_layout); - VkDescriptorSet descriptor_set_for_pipeline_1 = margaret_allocate_descriptor_set(device, descriptor_pool, pipeline_hands_1.descriptor_set_layout); + state.vk_ctx.descriptor_pool = margaret_create_descriptor_set_pool(state.vk_ctx.device, 1, 3, 2); + state.vk_ctx.descriptor_set_for_pipeline_0 = margaret_allocate_descriptor_set( + state.vk_ctx.device, state.vk_ctx.descriptor_pool, state.vk_ctx.pipeline_hands_0.descriptor_set_layout); + state.vk_ctx.descriptor_set_for_pipeline_1 = margaret_allocate_descriptor_set( + state.vk_ctx.device, state.vk_ctx.descriptor_pool, state.vk_ctx.pipeline_hands_1.descriptor_set_layout); // Configuring my descriptor sets, that I just allocated VkDescriptorBufferInfo buffer_info_for_descriptor_0_in_set_0 = { - .buffer = device_lighting_ubo.buffer, + .buffer = state.vk_ctx.device_lighting_ubo.buffer, .offset = 0, .range = sizeof(Pipeline0UBO), }; VkDescriptorImageInfo image_info_for_descriptor_1_in_set_0 = { - .sampler = linear_sampler, - .imageView = cyl_1_diffuse_texture_view, + .sampler = state.vk_ctx.linear_sampler, + .imageView = state.vk_ctx.cyl_1_diffuse_texture_view, .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; VkDescriptorImageInfo image_info_for_descriptor_2_in_set_0 = { - .sampler = nearest_sampler, - .imageView = cyl_1_normal_texture_view, + .sampler = state.vk_ctx.nearest_sampler, + .imageView = state.vk_ctx.cyl_1_normal_texture_view, .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; VkDescriptorImageInfo image_info_for_descriptor_0_in_set_1 = { - .sampler = nearest_sampler, - .imageView = IT1_view, + .sampler = state.vk_ctx.nearest_sampler, + .imageView = state.vk_ctx.IT1_view, .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; VkWriteDescriptorSet writes_in_descriptor_sets[] = { { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = descriptor_set_for_pipeline_0, + .dstSet = state.vk_ctx.descriptor_set_for_pipeline_0, .dstBinding = 0, .dstArrayElement = 0, .descriptorCount = 1, @@ -1252,7 +1693,7 @@ int main() { }, { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = descriptor_set_for_pipeline_0, + .dstSet = state.vk_ctx.descriptor_set_for_pipeline_0, .dstBinding = 1, .dstArrayElement = 0, .descriptorCount = 1, @@ -1261,7 +1702,7 @@ int main() { }, { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = descriptor_set_for_pipeline_0, + .dstSet = state.vk_ctx.descriptor_set_for_pipeline_0, .dstBinding = 2, .dstArrayElement = 0, .descriptorCount = 1, @@ -1271,7 +1712,7 @@ int main() { { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = descriptor_set_for_pipeline_1, + .dstSet = state.vk_ctx.descriptor_set_for_pipeline_1, .dstBinding = 0, .dstArrayElement = 0, .descriptorCount = 1, @@ -1279,306 +1720,87 @@ int main() { .pImageInfo = &image_info_for_descriptor_0_in_set_1, }, }; - vkUpdateDescriptorSets(device, ARRAY_SIZE(writes_in_descriptor_sets), writes_in_descriptor_sets, 0, NULL); + vkUpdateDescriptorSets(state.vk_ctx.device, ARRAY_SIZE(writes_in_descriptor_sets), writes_in_descriptor_sets, 0, NULL); - CamControlInfo my_cam_control_info = CamControlInfo_new(); - vec3 Buba_control_info = {0}; + state.vk_ctx.my_cam_control_info = CamControlInfo_new(); + state.vk_ctx.Buba_control_info = (vec3){0}; - Jane_r0 jane = Jane_r0_create(device); - - // Mainloop - margaret_ns_time start = margaret_clock_gettime_monotonic_raw(); - margaret_ns_time prev_key_frame_time = start; - int frame_count_since_key = 0; - margaret_ns_time prev_frame_timestamp = start; + state.vk_ctx.jane = Jane_r0_create(state.vk_ctx.device); + state.prev_key_frame_time = margaret_clock_gettime_monotonic_raw(); + state.frame_count_since_key = 0; /* Will happen mid-frame */ - bool dt_transfer_required = true; + state.vk_ctx.dt_transfer_required = true; - bool pressed_first_0x80[0x80] = {0}; - while (true) { - margaret_ns_time frame_A0 = margaret_clock_gettime_monotonic_raw(); - float fl = margaret_ns_time_sec_diff(prev_frame_timestamp, frame_A0); - prev_frame_timestamp = frame_A0; - - VecXlib_Event events = margaret_read_x_events(x.dpy); - if (wep.should_stop) + while (wl_display_dispatch(state.wl_display) >= 0) { + if (state.closed) break; - for (size_t i = 0; i < events.len; i++) { - Xlib_Event* ev = VecXlib_Event_mat(&events, i); - if (ev->xany.window != wep.win) - continue; - Margaret_WEP_update_with_new_event(&wep, ev); - if (ev->xany.type == MotionNotify) { - CamControlInfo_update_direction(&my_cam_control_info, wep.width, wep.height, ev->xmotion.x, ev->xmotion.y); - } - if (ev->xany.type == KeyPress) { - KeySym keysym = XLookupKeysym(&ev->xkey, 0); - if (keysym < 0x80) - pressed_first_0x80[keysym] = true; - } - if (ev->xany.type == KeyRelease) { - KeySym keysym = XLookupKeysym(&ev->xkey, 0); - if (keysym < 0x80) - pressed_first_0x80[keysym] = false; - if (keysym == XK_1) { - vec3 p = my_cam_control_info.pos; - VecPipeline0PointLight_mat(&scene.point_lights, 0)->pos = p; - printf("Point light source pos set to %f %f %f\n", p.x, p.y, p.z); - dt_transfer_required = true; - } else if (keysym == XK_2) { - scene.hdr_factor /= 1.05f; - printf("hdr factor decreased to %f\n", scene.hdr_factor); - } else if (keysym == XK_3) { - scene.hdr_factor *= 1.05f; - printf("hdr factor increased to %f\n", scene.hdr_factor); - } - } - } - if (pressed_first_0x80[XK_w]) - CamControlInfo_forward(&my_cam_control_info, fl); - if (pressed_first_0x80[XK_s]) - CamControlInfo_backward(&my_cam_control_info, fl); - if (pressed_first_0x80[XK_a]) - CamControlInfo_left(&my_cam_control_info, fl); - if (pressed_first_0x80[XK_d]) - CamControlInfo_right(&my_cam_control_info, fl); - if (pressed_first_0x80[XK_q]) - CamControlInfo_down(&my_cam_control_info, fl); - if (pressed_first_0x80[XK_e]) - CamControlInfo_up(&my_cam_control_info, fl); - - if (pressed_first_0x80[XK_j]) {\ - Buba_control_info.x -= fl; - VecGenericMeshInstance_mat(&VecUsedModelOnScene_mat(&scene.models, 1)->instances, 0)->model_t = - marie_translation_mat4(Buba_control_info); - dt_transfer_required = true; - } - if (pressed_first_0x80[XK_k]) {\ - Buba_control_info.z -= fl; - VecGenericMeshInstance_mat(&VecUsedModelOnScene_mat(&scene.models, 1)->instances, 0)->model_t = - marie_translation_mat4(Buba_control_info); - dt_transfer_required = true; - } - if (pressed_first_0x80[XK_l]) {\ - Buba_control_info.z += fl; - VecGenericMeshInstance_mat(&VecUsedModelOnScene_mat(&scene.models, 1)->instances, 0)->model_t = - marie_translation_mat4(Buba_control_info); - dt_transfer_required = true; - } - if (pressed_first_0x80[XK_semicolon]) {\ - Buba_control_info.x += fl; - VecGenericMeshInstance_mat(&VecUsedModelOnScene_mat(&scene.models, 1)->instances, 0)->model_t = - marie_translation_mat4(Buba_control_info); - dt_transfer_required = true; - } - - - - // Rendering - vkWaitForFences(device, 1, &jane.in_flight_fence, VK_TRUE, UINT64_MAX); - uint32_t ij; - VkResult aq_ret = vkAcquireNextImageKHR( - device, swfb.swapchain, - UINT64_MAX, jane.image_available_semaphore, VK_NULL_HANDLE, &ij - ); - if (aq_ret == VK_ERROR_OUT_OF_DATE_KHR) { - fprintf(stderr, "vkAcquireNextImageKHR: VK_ERROR_OUT_OF_DATE_KHR\n"); - recreate_swapchain(physical_device, device, queue_fam, surface, render_pass_1, &swfb, &jane, sane_image_extent_limit); - continue; - } else if (aq_ret == VK_SUBOPTIMAL_KHR) { - fprintf(stderr, "vkAcquireNextImageKHR: VK_SUBOPTIMAL_KHR\n"); - recreate_swapchain(physical_device, device, queue_fam, surface, render_pass_1, &swfb, &jane, sane_image_extent_limit); - continue; - } else if (aq_ret != VK_SUCCESS) { - abortf("vkAcquireNextImageKHR"); - } - - vkResetFences(device, 1, &jane.in_flight_fence); - - float ae = margaret_ns_time_sec_diff(start, frame_A0); - scene.anim_time = ae; - scene.color = (VkClearColorValue){{0, 0, 0, 1}}; - mat4 projection_matrix = marie_perspective_projection_fov_mat4((float)wep.width, (float)wep.height, - my_cam_control_info.fov, 0.01f, 1000); - mat4 camera_rotation_matrix = marie_mat3_to_mat4_transposed(my_cam_control_info.cam_basis); - mat4 camera_translation_matrix = marie_translation_mat4(vec3_minus(my_cam_control_info.pos)); - mat4 t_mat = mat4_mul_mat4(projection_matrix, mat4_mul_mat4(camera_rotation_matrix, camera_translation_matrix)); - - if (dt_transfer_required){ - assert(scene.spotlights.len < pipeline_0_ubo_spotlight_max_count); - assert(scene.point_lights.len < pipeline_0_ubo_point_light_max_count); - copy_scene_info_to_buffer_and_rerecord_full_copy_command_buffer( - transfer_command_buffer, host_mem_buffer.buffer, host_mem_buffer_mem, &scene, device_lighting_ubo.buffer, - device_instance_attrs_for_all_generic_meshes.buffer); - VkCommandBuffer command_buffers[1] = { transfer_command_buffer }; - VkSemaphore signaling_semaphores[1] = { jane.in_frame_transfer_complete }; - VkSubmitInfo submit_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .commandBufferCount = ARRAY_SIZE(command_buffers), - .pCommandBuffers = command_buffers, - .signalSemaphoreCount = ARRAY_SIZE(signaling_semaphores), - .pSignalSemaphores = signaling_semaphores, - }; - if (vkQueueSubmit(graphics_queue, 1, &submit_info, NULL) != VK_SUCCESS) - abortf("vkQueueSubmit\n"); - } - - reset_and_record_command_buffer_0( - rendering_command_buffer_0, render_pass_0, &pipeline_hands_0, - IT1_framebuffer, device_IT1_image.image, swfb.extent, &scene, - descriptor_set_for_pipeline_0, t_mat, my_cam_control_info.pos); - - reset_and_record_command_buffer_1(rendering_command_buffer_1, render_pass_1, &pipeline_hands_1, - *VecVkFramebuffer_at(&swfb.framebuffers, ij), - swfb.extent, (VkExtent2D){.width = MAX_WIN_WIDTH, .height = MAX_WIN_HEIGHT}, &scene, descriptor_set_for_pipeline_1); - - { - VkSemaphore waiting_for_semaphores_if_dt_transfer_required[1] = { - jane.in_frame_transfer_complete - }; - VkPipelineStageFlags waiting_stages_if_dt_transfer_required[1] = { - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT - }; - assert(ARRAY_SIZE(waiting_for_semaphores_if_dt_transfer_required) == - ARRAY_SIZE(waiting_stages_if_dt_transfer_required)); - VkCommandBuffer command_buffers[1] = {rendering_command_buffer_0}; - VkSemaphore signaling_semaphores[1] = { jane.rendered_to_IT1_semaphore }; - VkSubmitInfo submit_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - - // We wait for `waiting_for_semaphores` before THESE stages - // waitSemaphoreCount specifies size for both pWaitSemaphores and pWaitDstStageMask - .waitSemaphoreCount = dt_transfer_required ? - ARRAY_SIZE(waiting_for_semaphores_if_dt_transfer_required) : 0, - .pWaitSemaphores = dt_transfer_required ? - waiting_for_semaphores_if_dt_transfer_required : NULL, - .pWaitDstStageMask = dt_transfer_required ? - waiting_stages_if_dt_transfer_required : NULL, - - .commandBufferCount = ARRAY_SIZE(command_buffers), - .pCommandBuffers = command_buffers, - - .signalSemaphoreCount = ARRAY_SIZE(signaling_semaphores), - .pSignalSemaphores = signaling_semaphores, - }; - if (vkQueueSubmit(graphics_queue, 1, &submit_info, NULL) != VK_SUCCESS) - abortf("vkQueueSubmit"); - } - { - VkSemaphore waiting_for_semaphores[2] = { - jane.image_available_semaphore, - jane.rendered_to_IT1_semaphore }; - VkPipelineStageFlags waiting_stages[2] = { - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - // VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT - }; - assert(ARRAY_SIZE(waiting_for_semaphores) == ARRAY_SIZE(waiting_stages)); - VkCommandBuffer command_buffers[1] = { rendering_command_buffer_1 }; - VkSemaphore signaling_semaphores[1] = { - *VecVkSemaphore_at(&swfb.rendering_finished_here_semaphores, ij) - }; - VkSubmitInfo cmd_submit_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - - .waitSemaphoreCount = ARRAY_SIZE(waiting_for_semaphores), - .pWaitSemaphores = waiting_for_semaphores, - .pWaitDstStageMask = waiting_stages, - - .commandBufferCount = ARRAY_SIZE(command_buffers), - .pCommandBuffers = command_buffers, - - .signalSemaphoreCount = ARRAY_SIZE(signaling_semaphores), - .pSignalSemaphores = signaling_semaphores, - }; - - if (vkQueueSubmit(graphics_queue, 1, &cmd_submit_info, jane.in_flight_fence) != VK_SUCCESS) - abortf("vkQueueSubmit"); - } - - { - VkSemaphore waiting_for_semaphores[] = { - *VecVkSemaphore_at(&swfb.rendering_finished_here_semaphores, ij) - }; - VkSwapchainKHR swapchains[] = { swfb.swapchain }; - uint32_t image_indices[] = { ij }; - assert( ARRAY_SIZE(swapchains) == ARRAY_SIZE(image_indices) ); - - VkPresentInfoKHR present_info = { - .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, - .waitSemaphoreCount = ARRAY_SIZE(waiting_for_semaphores), - .pWaitSemaphores = waiting_for_semaphores, - - .swapchainCount = ARRAY_SIZE(swapchains), - .pSwapchains = swapchains, - .pImageIndices = image_indices, - .pResults = NULL, - }; - - VkResult pres_ret = vkQueuePresentKHR(presentation_queue, &present_info); - // todo: ponder more over this - if (pres_ret == VK_ERROR_OUT_OF_DATE_KHR) { - fprintf(stderr, "vkQueuePresentKHR: VK_ERROR_OUT_OF_DATE_KHR\n"); - recreate_swapchain(physical_device, device, queue_fam, surface, render_pass_1, &swfb, &jane, sane_image_extent_limit); - continue; - } else if (pres_ret == VK_SUBOPTIMAL_KHR) { - fprintf(stderr, "vkQueuePresentKHR: VK_SUBOPTIMAL_KHR\n"); - recreate_swapchain(physical_device, device, queue_fam, surface, render_pass_1, &swfb, &jane, sane_image_extent_limit); - continue; - } else if (pres_ret != VK_SUCCESS) { - abortf("vkQueuePresentKHR"); - } - } - dt_transfer_required = false; - margaret_ns_time frame_B0 = margaret_clock_gettime_monotonic_raw(); - if (margaret_ns_time_sec_diff(frame_A0, frame_B0) > 0.3) { - fprintf(stderr, "]]] Profiling frame scheduling:\n" - "total: %.6lf\n" - "]]]", - margaret_ns_time_sec_diff(frame_A0, frame_B0)); - } - frame_count_since_key++; - if (margaret_ns_time_sec_diff(prev_key_frame_time, frame_B0) > 1.0) { - float fps = (float)frame_count_since_key / margaret_ns_time_sec_diff(prev_key_frame_time, frame_B0); - printf("FPS: %0.1lf\n", fps); - frame_count_since_key = 0; - prev_key_frame_time = frame_B0; - } } - vkDeviceWaitIdle(device); + vkDeviceWaitIdle(state.vk_ctx.device); // The End - // dropping scene - Scene_drop(scene); - // todo: destroy objects that hold scene and model topology - // destroying vulkan objects - vkDestroyDescriptorPool(device, descriptor_pool, NULL); - vkDestroySampler(device, linear_sampler, NULL); - vkDestroySampler(device, nearest_sampler, NULL); - vkDestroyImageView(device, cyl_1_diffuse_texture_view, NULL); - vkDestroyImageView(device, cyl_1_normal_texture_view, NULL); + vkDestroyDescriptorPool(state.vk_ctx.device, state.vk_ctx.descriptor_pool, NULL); + vkDestroySampler(state.vk_ctx.device, state.vk_ctx.linear_sampler, NULL); + vkDestroySampler(state.vk_ctx.device, state.vk_ctx.nearest_sampler, NULL); - // todo: destroy buffers for model topology - vkDestroyBuffer(device, device_lighting_ubo.buffer, NULL); - vkDestroyImage(device, device_cyl_1_diffuse_texture.image, NULL); - vkDestroyImage(device, device_cyl_1_normal_texture.image, NULL); - vkDestroyImage(device, device_IT1_image.image, NULL); - vkDestroyImage(device, device_zbuffer_image.image, NULL); - vkDestroyBuffer(device, host_mem_buffer.buffer, NULL); + vkDestroyImageView(state.vk_ctx.device, state.vk_ctx.cyl_1_normal_texture_view, NULL); + vkDestroyImageView(state.vk_ctx.device, state.vk_ctx.cyl_1_diffuse_texture_view, NULL); + vkDestroyFramebuffer(state.vk_ctx.device, state.vk_ctx.IT1_framebuffer, NULL); + vkDestroyImageView(state.vk_ctx.device, state.vk_ctx.IT1_view, NULL); + vkDestroyImageView(state.vk_ctx.device, state.vk_ctx.zbuffer_view, NULL); - vkFreeMemory(device, device_mem, NULL); - vkUnmapMemory(device, host_mem); - vkFreeMemory(device, host_mem, NULL); - vkDestroyCommandPool(device, command_pool, NULL); - MargaretSwapchainBundle_drop_with_device(device, swfb); - Jane_r0_destroy(device, jane); - destroy_graphics_pipeline_hands(device, pipeline_hands_1); - vkDestroyRenderPass(device, render_pass_1, NULL); - destroy_graphics_pipeline_hands(device, pipeline_hands_0); - vkDestroyRenderPass(device, render_pass_0, NULL); - vkDestroyDevice(device, NULL); - vkDestroySurfaceKHR(instance, surface, NULL); - MargaretInstanceAndItsDebug_drop(inst_hands); - MargaretSingleWindowSetup_XlibFlavour_drop(x); + Scene_drop(state.vk_ctx.scene); + + vkDestroyCommandPool(state.vk_ctx.device, state.vk_ctx.command_pool, NULL); + + vkUnmapMemory(state.vk_ctx.device, state.vk_ctx.host_mem); + vkFreeMemory(state.vk_ctx.device, state.vk_ctx.host_mem, NULL); + vkFreeMemory(state.vk_ctx.device, state.vk_ctx.device_mem, NULL); + + vkDestroyImage(state.vk_ctx.device, state.vk_ctx.device_cyl_1_diffuse_texture.image, NULL); + vkDestroyImage(state.vk_ctx.device, state.vk_ctx.device_cyl_1_normal_texture.image, NULL); + vkDestroyImage(state.vk_ctx.device, state.vk_ctx.device_IT1_image.image, NULL); + vkDestroyImage(state.vk_ctx.device, state.vk_ctx.device_zbuffer_image.image, NULL); + vkDestroyBuffer(state.vk_ctx.device, state.vk_ctx.device_lighting_ubo.buffer, NULL); + vkDestroyBuffer(state.vk_ctx.device, state.vk_ctx.device_instance_attrs_for_all_generic_meshes.buffer, NULL); + for (size_t i = 0; i < state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes.len; i++) + vkDestroyBuffer(state.vk_ctx.device, + VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes, i)->buffer, + NULL); + VecMargaretBufferInMemoryInfo_drop(state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes); + + vkDestroyBuffer(state.vk_ctx.device, state.vk_ctx.host_mem_buffer.buffer, NULL); + + TextureDataR8G8B8A8_drop(state.vk_ctx.cyl_1_normal_tex); + TextureDataR8G8B8A8_drop(state.vk_ctx.cyl_1_diffuse_tex); + SceneTemplate_drop(state.vk_ctx.scene_template); + + MargaretSwapchainBundle_drop_with_device(state.vk_ctx.device, state.vk_ctx.swfb); + Jane_r0_destroy(state.vk_ctx.device, state.vk_ctx.jane); + destroy_graphics_pipeline_hands(state.vk_ctx.device, state.vk_ctx.pipeline_hands_1); + vkDestroyRenderPass(state.vk_ctx.device, state.vk_ctx.render_pass_1, NULL); + destroy_graphics_pipeline_hands(state.vk_ctx.device, state.vk_ctx.pipeline_hands_0); + vkDestroyRenderPass(state.vk_ctx.device, state.vk_ctx.render_pass_0, NULL); + vkDestroyDevice(state.vk_ctx.device, NULL); + vkDestroySurfaceKHR(instance, state.vk_ctx.surface, NULL); + MargaretInstanceAndItsDebug_drop(state.vk_ctx.instance_and_debug); + + if (state.wl_callback) + wl_callback_destroy(state.wl_callback); + xdg_toplevel_destroy(state.xdg_toplevel); + xdg_surface_destroy(state.xdg_surface); + xdg_wm_base_destroy(state.xdg_wm_base); + wl_surface_destroy(state.wl_surface); + wl_compositor_destroy(state.wl_compositor); + if (state.pointer) + wl_pointer_destroy(state.pointer); + xkb_context_unref(state.xkb_context); + xkb_keymap_unref(state.xkb_keymap); + xkb_state_unref(state.xkb_state); + if (state.keyboard) + wl_keyboard_destroy(state.keyboard); + if (state.wl_seat) + wl_seat_destroy(state.wl_seat); + wl_registry_destroy(state.wl_registry); + wl_display_disconnect(state.wl_display); } diff --git a/src/l2/tests/r0/r0_assets.h b/src/l2/tests/r0/r0_assets.h index 51c034d..166d0b0 100644 --- a/src/l2/tests/r0/r0_assets.h +++ b/src/l2/tests/r0/r0_assets.h @@ -105,6 +105,10 @@ typedef struct { size_t spotlights_max_count; } SceneTemplate; +void SceneTemplate_drop(SceneTemplate self) { + VecModelInSceneTemplate_drop(self.models); +} + size_t SceneTemplate_get_space_needed_for_all_instance_attributes(const SceneTemplate* self) { size_t s = 0; for (size_t mi = 0; mi < self->models.len; mi++) { diff --git a/src/l2/tests/r0/r0_scene.h b/src/l2/tests/r0/r0_scene.h index 838d5ee..68d35c9 100644 --- a/src/l2/tests/r0/r0_scene.h +++ b/src/l2/tests/r0/r0_scene.h @@ -104,6 +104,8 @@ Scene Scene_new() { void Scene_drop(Scene self) { VecUsedModelOnScene_drop(self.models); + VecPipeline0Spotlight_drop(self.spotlights); + VecPipeline0PointLight_drop(self.point_lights); } void SceneTemplate_copy_initial_model_topology_and_rerecord_transfer_cmd( diff --git a/src/l2/tests/r0/test_shaders/glsl/0/0.frag b/src/l2/tests/r0/shaders/glsl/0/0.frag similarity index 100% rename from src/l2/tests/r0/test_shaders/glsl/0/0.frag rename to src/l2/tests/r0/shaders/glsl/0/0.frag diff --git a/src/l2/tests/r0/test_shaders/glsl/0/0.vert b/src/l2/tests/r0/shaders/glsl/0/0.vert similarity index 100% rename from src/l2/tests/r0/test_shaders/glsl/0/0.vert rename to src/l2/tests/r0/shaders/glsl/0/0.vert diff --git a/src/l2/tests/r0/test_shaders/glsl/0b/0b.frag b/src/l2/tests/r0/shaders/glsl/0b/0b.frag similarity index 100% rename from src/l2/tests/r0/test_shaders/glsl/0b/0b.frag rename to src/l2/tests/r0/shaders/glsl/0b/0b.frag diff --git a/src/l2/tests/r0/test_shaders/glsl/0b/0b.vert b/src/l2/tests/r0/shaders/glsl/0b/0b.vert similarity index 100% rename from src/l2/tests/r0/test_shaders/glsl/0b/0b.vert rename to src/l2/tests/r0/shaders/glsl/0b/0b.vert diff --git a/src/l2/tests/r0/test_shaders/glsl/1/1.frag b/src/l2/tests/r0/shaders/glsl/1/1.frag similarity index 100% rename from src/l2/tests/r0/test_shaders/glsl/1/1.frag rename to src/l2/tests/r0/shaders/glsl/1/1.frag diff --git a/src/l2/tests/r0/test_shaders/glsl/1/1.vert b/src/l2/tests/r0/shaders/glsl/1/1.vert similarity index 100% rename from src/l2/tests/r0/test_shaders/glsl/1/1.vert rename to src/l2/tests/r0/shaders/glsl/1/1.vert diff --git a/src/l2/tests/r0/test_shader_compile.sh b/src/l2/tests/r0/test_shader_compile.sh deleted file mode 100755 index 4487522..0000000 --- a/src/l2/tests/r0/test_shader_compile.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -set +x -cd test_shaders - -function compile(){ - mkdir -p "spv/$1" - glslc -o "spv/$1/vert.spv" "glsl/$1/$1.vert" - glslc -o "spv/$1/frag.spv" "glsl/$1/$1.frag" -} - -compile 0 -compile 1 -compile 0b - diff --git a/src/l2/tests/r0/test_textures/bitmap_converter.py b/src/l2/tests/r0/textures/bitmap_converter.py similarity index 100% rename from src/l2/tests/r0/test_textures/bitmap_converter.py rename to src/l2/tests/r0/textures/bitmap_converter.py diff --git a/src/l2/tests/r0/test_textures/log_10_2_6.png b/src/l2/tests/r0/textures/log_10_2_6.png similarity index 100% rename from src/l2/tests/r0/test_textures/log_10_2_6.png rename to src/l2/tests/r0/textures/log_10_2_6.png diff --git a/src/l2/tests/r0/test_textures/test.png b/src/l2/tests/r0/textures/test.png similarity index 100% rename from src/l2/tests/r0/test_textures/test.png rename to src/l2/tests/r0/textures/test.png diff --git a/src/l2/tests/r3/r3.c b/src/l2/tests/r3/r3.c index 00428d2..e1cccc9 100644 --- a/src/l2/tests/r3/r3.c +++ b/src/l2/tests/r3/r3.c @@ -288,10 +288,6 @@ static void main_h_xdg_surface_configure(void *data, struct xdg_surface *xdg_sur xdg_surface_ack_configure(xdg_surface, serial); vulkano_frame_drawing(state); - // printf("Damaged\n"); - // wl_surface_damage_buffer(state->wl_surface, 0, 0, INT32_MAX, INT32_MAX); - // printf("Commited\n"); - // wl_surface_commit(state->wl_surface); } static const struct xdg_surface_listener xdg_surface_listener = { @@ -528,10 +524,7 @@ static void main_h_wl_surface_frame_done(void *data, struct wl_callback *cb, uin update_state(state, time - state->last_frame_time); } vulkano_frame_drawing(state); - // printf("Damaged\n"); - // wl_surface_damage(state->wl_surface, 0, 0, state->width, state->height); - // printf("Commited\n"); - // wl_surface_commit(state->wl_surface); + state->last_frame_time = time; } @@ -542,8 +535,8 @@ static const struct wl_callback_listener main_h_wl_surface_frame_listener = { int main() { state_t state = { .sane_image_extent_limit = {1000, 700}, .width = 800, .height = 480 }; - state.wl_display = wl_display_connect(NULL); + state.wl_display = wl_display_connect(NULL); if (!state.wl_display) abortf("Could not connect"); state.wl_registry = wl_display_get_registry(state.wl_display); @@ -579,10 +572,6 @@ int main() { abortf("wl_surface_frame\n"); wl_callback_add_listener(state.wl_callback, &main_h_wl_surface_frame_listener, &state); - // wl_surface_commit(state.wl_surface); - // wl_display_roundtrip(state.wl_display); - // wl_surface_commit(state.wl_surface); - state.vk_instance_and_debug = MargaretInstanceAndItsDebug_new(true); VkInstance vk_instance = state.vk_instance_and_debug.instance; state.vk_surface = margaret_create_surface(vk_instance, state.wl_display, state.wl_surface); diff --git a/src/l2/tests/r3/shader_compile.sh b/src/l2/tests/r3/shader_compile.sh deleted file mode 100644 index 6d4e89d..0000000 --- a/src/l2/tests/r3/shader_compile.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -set +x -cd test_shaders - -function compile(){ - mkdir -p "spv/$1" - glslc -o "spv/$1/vert.spv" "glsl/$1/$1.vert" - glslc -o "spv/$1/frag.spv" "glsl/$1/$1.frag" -} - -compile 0