УУУПС X)

This commit is contained in:
Андреев Григорий 2025-08-28 18:10:27 +03:00
parent fc7884a9ed
commit a1807a4dfa
5 changed files with 391 additions and 242 deletions

View File

@ -397,10 +397,10 @@ NODISCARD VecU8 generate_OptionT_struct_and_methods(SpanU8 T, bool primitive, bo
SPACE4 "%s some;\n"
"} %s;\n\n", T, OptionT);
VecU8_append_vec(&res, VecU8_fmt(
"#define None_%s() (%s){ .variant = Option_None }\n"
"#define Some_%s(expr) (%s){ .variant = Option_Some, .some = (expr) }\n\n",
T, OptionT, T, OptionT));
VecU8_append_vec(&res, VecU8_fmt("#define None_%s() (%s){ .variant = Option_None }\n\n", T, OptionT));
VecU8_append_vec(&res, VecU8_fmt("%s Some_%s(obj) {\n"
SPACE4 "(%s){ .variant = Option_Some, .some = obj };\n"
"}\n\n", OptionT, T, OptionT));
VecU8_append_vec(&res, VecU8_fmt(
"const %s* %s_expect_ref(const %s* self){\n"

View File

@ -26,7 +26,7 @@ void eve_of_l2() {
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);
/* Needed in margaret/vulkan.h */
generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("Xlib_Event"), true, false);
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);
@ -35,6 +35,10 @@ void eve_of_l2() {
(util_templates_instantiation_options){ .t_primitive = true, .vec = true, .option = true });
generate_eve_header(cstr("l2"), cstr(""), cstr("VkPresentModeKHR"),
(util_templates_instantiation_options){ .t_primitive = true, .vec = true, .option = true });
generate_eve_header(cstr("l2"), cstr(""), cstr("VkCompositeAlphaFlagBitsKHR"),
(util_templates_instantiation_options){ .t_primitive = true, .option = true });
generate_eve_header(cstr("l2"), cstr(""), cstr("VkExtent2D"),
(util_templates_instantiation_options){ .t_primitive = true, .option = true });
generate_eve_header(cstr("l2"), cstr(""), cstr("VkFormat"),
(util_templates_instantiation_options){ .t_primitive = true, .span = true, .option = true });
generate_eve_header(cstr("l2"), cstr(""), cstr("MargaretScoredPhysicalDevice"),

View File

@ -3,94 +3,13 @@
#include "../../../gen/l1/Option_int_primitives.h"
#include "../../../gen/l1/VecAndSpan_Vec_int_primitives.h"
// todo: rewrite this crap to wayland (fom now on wayland is my best friend in all situations)
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_xlib.h>
#include <vulkan/vulkan_wayland.h>
#include "../core/stringop.h"
#include "../../l1/system/fileio.h"
#include "time.h"
#include <wayland-client.h>
// 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;
}
}
void margaret_create_debug_utils_messenger_EXT(
VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
@ -134,73 +53,6 @@ typedef struct {
VkDebugUtilsMessengerEXT debug_messenger;
} MargaretInstanceAndItsDebug;
// 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};
}
NODISCARD MargaretInstanceAndItsDebug MargaretInstanceAndItsDebug_new(bool enable_validation_layers) {
VkApplicationInfo app_info = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
@ -387,8 +239,10 @@ VkDevice margaret_create_logical_device(VkPhysicalDevice physical_device, Margar
return device;
}
#include "../../../gen/l2/eve/OptionVkExtent2D.h"
#include "../../../gen/l2/eve/VecAndOption_VkSurfaceFormatKHR.h"
#include "../../../gen/l2/eve/VecAndOption_VkPresentModeKHR.h"
#include "../../../gen/l2/eve/OptionVkCompositeAlphaFlagBitsKHR.h"
/* These variables are in some way enforced by VkSurfaceCapabilitiesKHR (but not completely determined) */
typedef struct {
@ -397,6 +251,7 @@ typedef struct {
VkExtent2D image_extent;
uint32_t image_count;
VkSurfaceTransformFlagBitsKHR surface_pre_transform;
VkCompositeAlphaFlagBitsKHR composite_alpha;
} MargaretChosenSwapchainDetails;
OptionVkSurfaceFormatKHR margaret_choose_surface_format(const VecVkSurfaceFormatKHR* surface_formats) {
@ -423,11 +278,24 @@ OptionVkPresentModeKHR margaret_choose_presentation_mode(const VecVkPresentModeK
return res;
}
VkExtent2D margaret_choose_image_extent(const VkSurfaceCapabilitiesKHR* capabilities) {
OptionVkCompositeAlphaFlagBitsKHR margaret_choose_composite_alpha(VkCompositeAlphaFlagBitsKHR bits) {
if (bits & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)
return Some_VkCompositeAlphaFlagBitsKHR(VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR);
if (bits & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)
return Some_VkCompositeAlphaFlagBitsKHR(VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR);
return None_VkCompositeAlphaFlagBitsKHR();
}
OptionVkExtent2D margaret_choose_image_extent(const VkSurfaceCapabilitiesKHR* capabilities, VkExtent2D sane_limits) {
if (capabilities->currentExtent.width == UINT32_MAX) {
return (VkExtent2D){ capabilities->maxImageExtent.width, capabilities->maxImageExtent.height,};
} else
return capabilities->currentExtent;
if (capabilities->minImageExtent.width > sane_limits.width ||
capabilities->minImageExtent.height > sane_limits.height)
return None_VkExtent2D();
return Some_VkExtent2D ((VkExtent2D) { MIN_U32(sane_limits.width, sane_limits.width),
MIN_U32(sane_limits.height, sane_limits.height) });
}
/* May be bigger, than a sane limit */
return capabilities->currentExtent;
}
uint32_t margaret_choose_swapchain_image_count(const VkSurfaceCapabilitiesKHR* capabilities) {
@ -478,6 +346,11 @@ ResultMargaretChosenSwapchainDetailsOrSpanU8 margaret_choose_swapchain_details(V
VkExtent2D image_extent = margaret_choose_image_extent(&surface_capabilities);
uint32_t image_count = margaret_choose_swapchain_image_count(&surface_capabilities);
OptionVkCompositeAlphaFlagBitsKHR chosen_composite_alpha = margaret_choose_composite_alpha(
surface_capabilities.supportedCompositeAlpha);
if (chosen_composite_alpha.variant == Option_None)
return (ResultMargaretChosenSwapchainDetailsOrSpanU8){.variant = Result_Err, .err = cstr("No composite alpha")};
VecVkSurfaceFormatKHR_drop(surface_formats);
VecVkPresentModeKHR_drop(pres_modes);
@ -485,7 +358,8 @@ ResultMargaretChosenSwapchainDetailsOrSpanU8 margaret_choose_swapchain_details(V
.ok = (MargaretChosenSwapchainDetails){
.surface_format = chosen_surface_format.some, .presentation_mode = chosen_present_mode.some,
.image_extent = image_extent, .image_count = image_count,
.surface_pre_transform = surface_capabilities.currentTransform
.surface_pre_transform = surface_capabilities.currentTransform,
.composite_alpha = chosen_composite_alpha.some
}
};
}
@ -673,7 +547,7 @@ VkSwapchainKHR margaret_create_swapchain (
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
// Filling imageSharingMode and queueFamilyIndexes later
.preTransform = swapchain_details.surface_pre_transform,
.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
.compositeAlpha = swapchain_details.composite_alpha,
.presentMode = swapchain_details.presentation_mode,
.clipped = VK_TRUE,
.oldSwapchain = old_swapchain,
@ -867,53 +741,6 @@ VkCommandBuffer margaret_allocate_command_buffer(VkDevice device, VkCommandPool
return res;
}
// 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;
}
VkSurfaceKHR margaret_create_surface(VkInstance instance, struct wl_display* wl_display, struct wl_surface* wl_surface) {
VkWaylandSurfaceCreateInfoKHR crinfo = {

View File

@ -6,6 +6,207 @@
#include "r0_scene.h"
#include <sys/wait.h> // Only for linux
/* 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 <X11/Xlib.h>
#include <X11/Xutil.h>
#include <vulkan/vulkan_xlib.h>
// 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
typedef struct {
VkPipelineLayout pipeline_layout;

View File

@ -80,7 +80,7 @@ void reset_and_record_command_buffer_0(
if (vkBeginCommandBuffer(command_buffer, &info_begin) != VK_SUCCESS)
abortf("vkBeginCommandBuffer");
VkClearValue clear_values[1] = {{.color = {.float32={0, fabsf(sinf(ht)), 0, 1}}},};
VkClearValue clear_values[1] = {{.color = {.float32={1, fabsf(sinf(ht)), 0, 1}}},};
VkRenderPassBeginInfo renderpass_begin = {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.renderPass = render_pass_0,
@ -138,7 +138,11 @@ typedef struct {
VkSurfaceKHR vk_surface;
VkQueue graphics_queue;
VkQueue presentation_queue;
VkRenderPass render_pass_0;
MargaretSwapchainBundle swfb;
VkCommandPool command_pool;
VkCommandBuffer rendering_command_buffer_0;
Jane_r3 jane;
/* inputs */
struct wl_pointer* pointer;
struct wl_keyboard* keyboard;
@ -153,6 +157,9 @@ typedef struct {
int32_t height;
bool closed;
bool first_0x80_keys[0x80];
/* framerate counting */
U32 frame_count_since_key;
margaret_ns_time prev_key_frame_time;
} state_t;
void draw_frame(state_t* state, uint32_t* data, int32_t width, int32_t height) {
@ -403,30 +410,135 @@ static const struct wl_registry_listener main_h_wl_registry_listener = {
.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_t *state = data;
// wl_callback_destroy(cb);
// // todo: when I add multiple surfaces, gonna need to think of something smarter
// 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);
// }
//
// state->swapchain.want_to_draw = true;
// try_drawing_frame(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,
// };
static const struct wl_callback_listener main_h_wl_surface_frame_listener;
void recreate_swapchain(state_t* state) {
// We are about stop program and rebuild our sem+sem+fence synchronization mechanism
vkDeviceWaitIdle(state->device);
Jane_r3_destroy(state->device, state->jane);
state->jane = Jane_r3_create(state->device);
VkSwapchainKHR old_swapchain = MargaretSwapchainBundle_pop_swapchain_drop_rest(state->device, state->swfb);
// old swfb is 83% dropped
ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details(
state->physical_device, state->vk_surface);
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(
state->device, state->queue_fam, swapchain_details, state->vk_surface,
state->render_pass_0, state->swfb.swapchain);
vkDestroySwapchainKHR(state->device, old_swapchain, NULL);
// Now old swfb is 100% dropped
state->swfb = new_swfb;
}
void vulkano_frame_drawing(state_t* state) {
// Rendering
and_try_again:
vkWaitForFences(state->device, 1, &state->jane.in_flight_fence, VK_TRUE, UINT64_MAX);
uint32_t ij;
VkResult aq_ret = vkAcquireNextImageKHR(
state->device, state->swfb.swapchain,
UINT64_MAX, state->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_try_again;
} else if (aq_ret == VK_SUBOPTIMAL_KHR) {
fprintf(stderr, "vkAcquireNextImageKHR: VK_SUBOPTIMAL_KHR\n");
recreate_swapchain(state);
goto and_try_again;
} else if (aq_ret != VK_SUCCESS) {
abortf("vkAcquireNextImageKHR");
}
vkResetFences(state->device, 1, &state->jane.in_flight_fence);
reset_and_record_command_buffer_0(state->rendering_command_buffer_0, state->render_pass_0,
*VecVkFramebuffer_at(&state->swfb.framebuffers, ij), state->swfb.extent, state->ht);
{
VkCommandBuffer command_buffers[1] = {state->rendering_command_buffer_0};
VkSemaphore signaling_semaphores[1] = { state->jane.render_finished_semaphore };
VkSubmitInfo submit_info = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.waitSemaphoreCount = 0,
.pWaitSemaphores = NULL,
.pWaitDstStageMask = NULL,
.commandBufferCount = ARRAY_SIZE(command_buffers),
.pCommandBuffers = command_buffers,
.signalSemaphoreCount = ARRAY_SIZE(signaling_semaphores),
.pSignalSemaphores = signaling_semaphores,
};
if (vkQueueSubmit(state->graphics_queue, 1, &submit_info, NULL) != VK_SUCCESS)
abortf("vkQueueSubmit");
}
{
VkSemaphore waiting_for_semaphores[] = { state->jane.render_finished_semaphore };
VkSwapchainKHR swapchains[] = { state->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->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_try_again;
} else if (pres_ret == VK_SUBOPTIMAL_KHR) {
fprintf(stderr, "vkQueuePresentKHR: VK_SUBOPTIMAL_KHR\n");
recreate_swapchain(state);
goto and_try_again;
} else if (pres_ret != VK_SUCCESS) {
abortf("vkQueuePresentKHR");
}
}
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.1f\n", fps);
state->frame_count_since_key = 0;
state->prev_key_frame_time = frame_B0;
}
}
static void main_h_wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time){
state_t *state = data;
wl_callback_destroy(cb);
// todo: when I add multiple surfaces, gonna need to think of something smarter
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,
};
int main() {
@ -481,28 +593,33 @@ int main() {
vkGetDeviceQueue(state.device, state.queue_fam.for_graphics, 0, &state.graphics_queue);
VkQueue presentation_queue;
vkGetDeviceQueue(state.device, state.queue_fam.for_presentation, 0, &presentation_queue);
ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details(physical_device, vk_surface);
ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details(
state.physical_device, state.vk_surface);
if (swapchain_details_res.variant != Result_Ok)
abortf("swapchain_details_res.variant != Result_Ok");
MargaretChosenSwapchainDetails swapchain_details = swapchain_details_res.ok;
VkRenderPass render_pass_0 = create_render_pass_0(device, swapchain_details.surface_format.format);
state.render_pass_0 = create_render_pass_0(state.device, swapchain_details.surface_format.format);
// PipelineHands pipeline_hands_0 = create_graphics_pipeline_0(device, render_pass_0, 0);
MargaretSwapchainBundle swfb = MargaretSwapchainBundle_new(device, queue_fam, swapchain_details_res.ok, vk_surface, render_pass_0, NULL);
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);
state.swfb = MargaretSwapchainBundle_new(state.device, state.queue_fam,
swapchain_details_res.ok, state.vk_surface, state.render_pass_0, NULL);
state.command_pool = margaret_create_resettable_command_pool(state.device, state.queue_fam.for_graphics);
state.rendering_command_buffer_0 = margaret_allocate_command_buffer(state.device, state.command_pool);
Jane_r3 jane = Jane_r3_create(device);
state.jane = Jane_r3_create(state.device);
// todo: write what I need to write
int wl_display_loop_fd = wl_display_get_fd(state.wl_display);
struct pollfd mainloop_fds[1] = {(struct pollfd){}};
// int wl_display_loop_fd = wl_display_get_fd(state.wl_display);
// struct pollfd mainloop_fds[1] = {(struct pollfd){}};
while (wl_display_dispatch(state.wl_display)) {
if (state.closed)
break;
}
// if (state.wl_callback)
// wl_callback_destroy(state.wl_callback);
vkDeviceWaitIdle(state.device);
// todo: destroy instance and all the shit
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);