Now my vulkan program works on wayland (r3)

This commit is contained in:
Андреев Григорий 2025-08-29 15:05:06 +03:00
parent a1807a4dfa
commit d4d97ed8c6
6 changed files with 215 additions and 184 deletions

View File

@ -398,9 +398,9 @@ NODISCARD VecU8 generate_OptionT_struct_and_methods(SpanU8 T, bool primitive, bo
"} %s;\n\n", 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("%s Some_%s(%s obj) {\n"
SPACE4 "return (%s){ .variant = Option_Some, .some = obj };\n"
"}\n\n", OptionT, T, T, OptionT));
VecU8_append_vec(&res, VecU8_fmt(
"const %s* %s_expect_ref(const %s* self){\n"

View File

@ -48,6 +48,7 @@ void eve_of_l2() {
generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("VkImage"), true, false);
generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("VkImageView"), true, false);
generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("VkFramebuffer"), true, false);
generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("VkSemaphore"), true, false);
generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("MargaretBufferInMemoryInfo"), true, false);
generate_eve_header(cstr("l2"), cstr(""), cstr("PtrMargaretBufferInMemoryInfo"),
(util_templates_instantiation_options){ .t_primitive = true, .vec = true, .span = true, .mut_span = true,

View File

@ -291,11 +291,11 @@ OptionVkExtent2D margaret_choose_image_extent(const VkSurfaceCapabilitiesKHR* ca
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),
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;
return Some_VkExtent2D(capabilities->currentExtent);
}
uint32_t margaret_choose_swapchain_image_count(const VkSurfaceCapabilitiesKHR* capabilities) {
@ -313,7 +313,9 @@ typedef struct {
} ResultMargaretChosenSwapchainDetailsOrSpanU8;
// Both queries swapchain support details and selects needed formats and presentation modes
ResultMargaretChosenSwapchainDetailsOrSpanU8 margaret_choose_swapchain_details(VkPhysicalDevice physical_device, VkSurfaceKHR surface) {
ResultMargaretChosenSwapchainDetailsOrSpanU8 margaret_choose_swapchain_details(
VkPhysicalDevice physical_device, VkSurfaceKHR surface, VkExtent2D sane_image_extent_limit
) {
/* 1. Getting surface capabilities + formats + presentation modes */
VkSurfaceCapabilitiesKHR surface_capabilities;
if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &surface_capabilities) != VK_SUCCESS)
@ -343,7 +345,11 @@ ResultMargaretChosenSwapchainDetailsOrSpanU8 margaret_choose_swapchain_details(V
return (ResultMargaretChosenSwapchainDetailsOrSpanU8){ .variant = Result_Err,
.err = cstr("No suitable swapchain presentation mode") };
VkExtent2D image_extent = margaret_choose_image_extent(&surface_capabilities);
OptionVkExtent2D image_extent = margaret_choose_image_extent(&surface_capabilities, sane_image_extent_limit);
if (image_extent.variant == Option_None)
return (ResultMargaretChosenSwapchainDetailsOrSpanU8){ .variant = Result_Err,
.err = cstr("Can't choose sane image extent")};
uint32_t image_count = margaret_choose_swapchain_image_count(&surface_capabilities);
OptionVkCompositeAlphaFlagBitsKHR chosen_composite_alpha = margaret_choose_composite_alpha(
@ -357,7 +363,7 @@ ResultMargaretChosenSwapchainDetailsOrSpanU8 margaret_choose_swapchain_details(V
return (ResultMargaretChosenSwapchainDetailsOrSpanU8){ .variant = Result_Ok,\
.ok = (MargaretChosenSwapchainDetails){
.surface_format = chosen_surface_format.some, .presentation_mode = chosen_present_mode.some,
.image_extent = image_extent, .image_count = image_count,
.image_extent = image_extent.some, .image_count = image_count,
.surface_pre_transform = surface_capabilities.currentTransform,
.composite_alpha = chosen_composite_alpha.some
}
@ -421,7 +427,8 @@ typedef struct {
} MargaretScoredPhysicalDevice;
MargaretScoredPhysicalDevice margaret_score_physical_device(
VkPhysicalDevice dev, VkSurfaceKHR surface, SpanU8 favourite_word, SpanU8 forbidden_word
VkPhysicalDevice dev, VkSurfaceKHR surface, SpanU8 favourite_word, SpanU8 forbidden_word,
VkExtent2D sane_image_extent_limit
) {
VkPhysicalDeviceProperties properties;
vkGetPhysicalDeviceProperties(dev, &properties);
@ -463,7 +470,7 @@ MargaretScoredPhysicalDevice margaret_score_physical_device(
}
VecVecU8_drop(dev_extensions);
// Extension VK_KHR_swapchain is present, now we can call query_swap_chain_support
ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details = margaret_choose_swapchain_details(dev, surface);
ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details = margaret_choose_swapchain_details(dev, surface, sane_image_extent_limit);
if (swapchain_details.variant == Result_Err) {
return (MargaretScoredPhysicalDevice){dev, -1, cstr("Physical device lacks nice swapchain support")};
}
@ -485,7 +492,7 @@ MargaretScoredPhysicalDevice margaret_score_physical_device(
VecMargaretScoredPhysicalDevice margaret_get_physical_devices_scored(
VkInstance instance, VkSurfaceKHR surface,
SpanU8 favourite_word, SpanU8 forbidden_word
SpanU8 favourite_word, SpanU8 forbidden_word, VkExtent2D sane_image_extent_limit
) {
uint32_t physical_device_count = 0;
if (vkEnumeratePhysicalDevices(instance, &physical_device_count, NULL) != VK_SUCCESS)
@ -496,7 +503,8 @@ VecMargaretScoredPhysicalDevice margaret_get_physical_devices_scored(
VecMargaretScoredPhysicalDevice scored_devices = VecMargaretScoredPhysicalDevice_new_zeroinit(physical_device_count);
for (uint32_t i = 0; i < physical_device_count; i++) {
*VecMargaretScoredPhysicalDevice_mat(&scored_devices, i) = margaret_score_physical_device(
*VecVkPhysicalDevice_at(&physical_devices, i), surface, favourite_word, forbidden_word
*VecVkPhysicalDevice_at(&physical_devices, i), surface,
favourite_word, forbidden_word, sane_image_extent_limit
);
}
MutSpanMargaretScoredPhysicalDevice_sort(VecMargaretScoredPhysicalDevice_to_mspan(&scored_devices));
@ -505,9 +513,10 @@ VecMargaretScoredPhysicalDevice margaret_get_physical_devices_scored(
VkPhysicalDevice margaret_select_one_physical_device(
VkInstance instance, VkSurfaceKHR surface,
SpanU8 favourite_word, SpanU8 forbidden_word
SpanU8 favourite_word, SpanU8 forbidden_word, VkExtent2D sane_image_extent_limit
) {
VecMargaretScoredPhysicalDevice scored_devices = margaret_get_physical_devices_scored(instance, surface, favourite_word, forbidden_word);
VecMargaretScoredPhysicalDevice scored_devices = margaret_get_physical_devices_scored(instance, surface,
favourite_word, forbidden_word, sane_image_extent_limit);
printf("Physical devices (with scores):\n");
for (size_t i = 0; i < scored_devices.len; i++) {
const MargaretScoredPhysicalDevice* dev = VecMargaretScoredPhysicalDevice_at(&scored_devices, i);
@ -571,6 +580,7 @@ VkSwapchainKHR margaret_create_swapchain (
#include "../../../gen/l2/eve/VecVkImage.h"
#include "../../../gen/l2/eve/VecVkImageView.h"
#include "../../../gen/l2/eve/VecVkFramebuffer.h"
#include "../../../gen/l2/eve/VecVkSemaphore.h"
VecVkImageView margaret_create_swapchain_image_views(
VkDevice device, VkSwapchainKHR swapchain,
@ -653,6 +663,7 @@ typedef struct {
VecVkImageView image_views;
VecVkFramebuffer framebuffers;
VkExtent2D extent;
VecVkSemaphore rendering_finished_here_semaphores;
} MargaretSwapchainBundle;
MargaretSwapchainBundle MargaretSwapchainBundle_new(
@ -662,12 +673,18 @@ MargaretSwapchainBundle MargaretSwapchainBundle_new(
VkSwapchainKHR swapchain = margaret_create_swapchain(device, queue_families, swapchain_details, surface, old_swapchain);
VecVkImageView image_views = margaret_create_swapchain_image_views(device, swapchain, swapchain_details.surface_format.format);
VecVkFramebuffer framebuffers = margaret_create_swapchain_framebuffers(device, &image_views, render_pass, swapchain_details.image_extent);
VecVkSemaphore rendering_finished_semaphores = VecVkSemaphore_new_zeroinit(framebuffers.len);
for (size_t i = 0; i < framebuffers.len; i++)
*VecVkSemaphore_mat(&rendering_finished_semaphores, i) = margaret_create_semaphore(device);
return (MargaretSwapchainBundle){ .swapchain = swapchain, .image_views = image_views,
.framebuffers = framebuffers, .extent = swapchain_details.image_extent,
.rendering_finished_here_semaphores = rendering_finished_semaphores
};
}
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);
for (size_t i = 0; i < swfb.framebuffers.len; i++) {
vkDestroyFramebuffer(device, *VecVkFramebuffer_at(&swfb.framebuffers, i), NULL);
}

View File

@ -936,23 +936,20 @@ typedef struct {
VkSemaphore in_frame_transfer_complete;
VkSemaphore image_available_semaphore;
VkSemaphore rendered_to_IT1_semaphore;
VkSemaphore render_finished_semaphore;
VkFence in_flight_fence;
} Jane;
} Jane_r0;
NODISCARD Jane Jane_create(VkDevice device) {
return (Jane){
NODISCARD Jane_r0 Jane_r0_create(VkDevice device) {
return (Jane_r0){
.in_frame_transfer_complete = margaret_create_semaphore(device),
.image_available_semaphore = margaret_create_semaphore(device),
.rendered_to_IT1_semaphore = margaret_create_semaphore(device),
.render_finished_semaphore = margaret_create_semaphore(device),
.in_flight_fence = margaret_create_fence(device, true)
};
}
void Jane_destroy(VkDevice device, Jane jane) {
void Jane_r0_destroy(VkDevice device, Jane_r0 jane) {
vkDestroyFence(device, jane.in_flight_fence, NULL);
vkDestroySemaphore(device, jane.render_finished_semaphore, NULL);
vkDestroySemaphore(device, jane.rendered_to_IT1_semaphore, NULL);
vkDestroySemaphore(device, jane.image_available_semaphore, NULL);
vkDestroySemaphore(device, jane.in_frame_transfer_complete, NULL);
@ -960,14 +957,15 @@ void Jane_destroy(VkDevice device, Jane jane) {
void recreate_swapchain(
VkPhysicalDevice physical_device, VkDevice device, MargaretChosenQueueFamilies queue_fam, VkSurfaceKHR surface,
VkRenderPass render_pass, MargaretSwapchainBundle* swfb, Jane* jane) {
VkRenderPass render_pass, MargaretSwapchainBundle* swfb, Jane_r0* jane, VkExtent2D sane_image_extent_limit) {
// We are about stop program and rebuild our sem+sem+fence synchronization mechanism
vkDeviceWaitIdle(device);
Jane_destroy(device, *jane);
*jane = Jane_create(device);
Jane_r0_destroy(device, *jane);
*jane = Jane_r0_create(device);
VkSwapchainKHR old_swapchain = MargaretSwapchainBundle_pop_swapchain_drop_rest(device, *swfb);
// old swfb is 83% dropped
ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details(physical_device, surface);
ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details(
physical_device, surface, sane_image_extent_limit);
if (swapchain_details_res.variant != Result_Ok)
abortf("swapchain_details_res.variant != Result_Ok");
MargaretChosenSwapchainDetails swapchain_details = swapchain_details_res.ok;
@ -1002,6 +1000,7 @@ int main() {
bool ENABLE_VALIDATION_LAYERS = true;
const U32 MAX_WIN_WIDTH = 1920;
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);
@ -1015,7 +1014,8 @@ int main() {
VkSurfaceKHR surface = margaret_create_surface_x_dunk(instance, &x);
VkPhysicalDevice physical_device = margaret_select_one_physical_device(instance, surface, GPU, bugged_GPU);
VkPhysicalDevice physical_device = margaret_select_one_physical_device(
instance, surface, GPU, bugged_GPU, sane_image_extent_limit);
// print_physical_device_available_extensions(physical_device);
@ -1031,7 +1031,8 @@ int main() {
VkQueue presentation_queue;
vkGetDeviceQueue(device, queue_fam.for_presentation, 0, &presentation_queue);
ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details(physical_device, surface);
ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details(
physical_device, surface, sane_image_extent_limit);
if (swapchain_details_res.variant != Result_Ok)
abortf("swapchain_details_res.variant != Result_Ok");
@ -1283,7 +1284,7 @@ int main() {
CamControlInfo my_cam_control_info = CamControlInfo_new();
vec3 Buba_control_info = {0};
Jane jane = Jane_create(device);
Jane_r0 jane = Jane_r0_create(device);
// Mainloop
margaret_ns_time start = margaret_clock_gettime_monotonic_raw();
@ -1383,11 +1384,11 @@ int main() {
);
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);
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);
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");
@ -1475,7 +1476,9 @@ int main() {
};
assert(ARRAY_SIZE(waiting_for_semaphores) == ARRAY_SIZE(waiting_stages));
VkCommandBuffer command_buffers[1] = { rendering_command_buffer_1 };
VkSemaphore signaling_semaphores[1] = { jane.render_finished_semaphore };
VkSemaphore signaling_semaphores[1] = {
*VecVkSemaphore_at(&swfb.rendering_finished_here_semaphores, ij)
};
VkSubmitInfo cmd_submit_info = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
@ -1495,7 +1498,9 @@ int main() {
}
{
VkSemaphore waiting_for_semaphores[] = { jane.render_finished_semaphore };
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) );
@ -1515,11 +1520,11 @@ int main() {
// 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);
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);
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");
@ -1567,7 +1572,7 @@ int main() {
vkFreeMemory(device, host_mem, NULL);
vkDestroyCommandPool(device, command_pool, NULL);
MargaretSwapchainBundle_drop_with_device(device, swfb);
Jane_destroy(device, jane);
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);

View File

@ -217,16 +217,19 @@ void try_drawing_frame(state_t *state){
/* Draw checkerboxed background */
uint32_t* data = state->swapchain.data + ij * MAX_BUFFER_WIDTH * MAX_BUFFER_HEIGHT;
draw_frame(state, data, width, height);
printf("Attached\n");
wl_surface_attach(state->wl_surface, state->swapchain.used_buffers[ij], 0, 0);
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 void main_h_xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial){
state_t *state = data;
printf("XDG surface configured!\n");
printf("Acknowledged surface configure\n");
xdg_surface_ack_configure(xdg_surface, serial);
// todo: synchronize with frame event
state->swapchain.want_to_draw = true;
try_drawing_frame(state);
}
@ -476,7 +479,7 @@ 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
printf("AAA!!! CALLBACK!!!\n");
state->wl_callback = wl_surface_frame(state->wl_surface);
if (!state->wl_callback)
abortf("wl_surface_frame\n");
@ -551,6 +554,7 @@ int main() {
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, "r1");
printf("Commited\n");
wl_surface_commit(state.wl_surface);
state.wl_callback = wl_surface_frame(state.wl_surface);

View File

@ -11,9 +11,6 @@
#include "../../margaret/vulkan.h"
#include <poll.h>
#define MAX_BUFFER_WIDTH 1000
#define MAX_BUFFER_HEIGHT 800
// todo: generate this function in l2
VkRenderPass create_render_pass_0(VkDevice logical_device, VkFormat colorbuffer_format) {
@ -26,7 +23,7 @@ VkRenderPass create_render_pass_0(VkDevice logical_device, VkFormat colorbuffer_
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
.finalLayout = VK_IMAGE_L AYOUT_PRESENT_SRC_KHR,
}
};
@ -99,26 +96,25 @@ void reset_and_record_command_buffer_0(
typedef struct {
VkSemaphore image_available_semaphore;
VkSemaphore render_finished_semaphore;
VkFence in_flight_fence;
} Jane_r3;
NODISCARD Jane_r3 Jane_r3_create(VkDevice device) {
return (Jane_r3){
.image_available_semaphore = margaret_create_semaphore(device),
.render_finished_semaphore = margaret_create_semaphore(device),
.in_flight_fence = margaret_create_fence(device, true)
};
}
void Jane_r3_destroy(VkDevice device, Jane_r3 jane) {
vkDestroyFence(device, jane.in_flight_fence, NULL);
vkDestroySemaphore(device, jane.render_finished_semaphore, NULL);
vkDestroySemaphore(device, jane.image_available_semaphore, NULL);
}
typedef struct {
/* Memory settings */
VkExtent2D sane_image_extent_limit;
/* Globals */
struct wl_display *wl_display;
struct wl_registry *wl_registry;
@ -162,36 +158,140 @@ typedef struct {
margaret_ns_time prev_key_frame_time;
} state_t;
void draw_frame(state_t* state, uint32_t* data, int32_t width, int32_t height) {
}
void update_state(state_t* state, uint32_t fl) {
const float width = (float)(state->width < MAX_BUFFER_WIDTH ? state->width : MAX_BUFFER_WIDTH);
const float height = (float)(state->height < MAX_BUFFER_HEIGHT ? state->height : MAX_BUFFER_HEIGHT);
float dur = (float)fl / 1000;
state->ht += dur;
}
// void try_drawing_frame(state_t *state){
// if (!state->swapchain.want_to_draw)
// return;
// const int32_t width = state->width < MAX_BUFFER_WIDTH ? state->width : MAX_BUFFER_WIDTH;
// const int32_t height = state->height < MAX_BUFFER_HEIGHT ? state->height : MAX_BUFFER_HEIGHT;
/* Draw checkerboxed background */
// uint32_t* data = state->swapchain.data + ij * MAX_BUFFER_WIDTH * MAX_BUFFER_HEIGHT;
// draw_frame(state, data, width, height);
// wl_surface_attach(state->wl_surface, state->swapchain.used_buffers[ij], 0, 0);
// wl_surface_damage_buffer(state->wl_surface, 0, 0, INT32_MAX, INT32_MAX);
// wl_surface_commit(state->wl_surface);
// }
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, state->sane_image_extent_limit);
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);
// printf("Dozhdalisya!\n");
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");
}
// printf("Image acquired\n");
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);
{
VkSemaphore waiting_for_semaphores[1] = {state->jane.image_available_semaphore};
VkPipelineStageFlags waiting_stages[1] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkCommandBuffer command_buffers[1] = {state->rendering_command_buffer_0};
VkSemaphore signaling_semaphores[1] = {
*VecVkSemaphore_at(&state->swfb.rendering_finished_here_semaphores, ij)
};
VkSubmitInfo submit_info = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.waitSemaphoreCount = 1,
.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->graphics_queue, 1, &submit_info, state->jane.in_flight_fence) != VK_SUCCESS)
abortf("vkQueueSubmit");
}
{
VkSemaphore waiting_for_semaphores[] = {
*VecVkSemaphore_at(&state->swfb.rendering_finished_here_semaphores, ij)
};
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,
};
// printf("Now I will present it\n");
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_xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial){
state_t *state = data;
printf("XDG surface configured!\n");
printf("XDG surface configured! (%d %d)\n", state->width, state->height);
printf("Acknowledged surface configure\n");
xdg_surface_ack_configure(xdg_surface, serial);
// state->swapchain.want_to_draw = true;
// try_drawing_frame(state);
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 = {
@ -202,8 +302,12 @@ 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_t *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)
if (width <= 0 || height <= 0)
return;
state->width = width;
state->height = height;
@ -412,118 +516,9 @@ static const struct wl_registry_listener main_h_wl_registry_listener = {
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");
@ -533,6 +528,10 @@ 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,7 +541,7 @@ static const struct wl_callback_listener main_h_wl_surface_frame_listener = {
int main() {
state_t state = { .width = 800, .height = 480 };
state_t state = { .sane_image_extent_limit = {1000, 700}, .width = 800, .height = 480 };
state.wl_display = wl_display_connect(NULL);
if (!state.wl_display)
@ -572,18 +571,23 @@ int main() {
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.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);
// 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);
state.physical_device = margaret_select_one_physical_device(vk_instance, state.vk_surface,
cstr("nvidia"), cstr("NOT SPECIFIED"));
cstr("nvidia"), cstr("NOT SPECIFIED"), state.sane_image_extent_limit);
ResultMargaretChosenQueueFamiliesOrSpanU8 queue_fam_res = margaret_choose_good_queue_families(
state.physical_device, state.vk_surface);
if (queue_fam_res.variant != Result_Ok)
@ -591,10 +595,9 @@ int main() {
state.queue_fam = queue_fam_res.ok;
state.device = margaret_create_logical_device(state.physical_device, state.queue_fam);
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);
vkGetDeviceQueue(state.device, state.queue_fam.for_presentation, 0, &state.presentation_queue);
ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details(
state.physical_device, state.vk_surface);
state.physical_device, state.vk_surface, state.sane_image_extent_limit);
if (swapchain_details_res.variant != Result_Ok)
abortf("swapchain_details_res.variant != Result_Ok");
MargaretChosenSwapchainDetails swapchain_details = swapchain_details_res.ok;
@ -610,10 +613,11 @@ int main() {
// 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)) {
while (wl_display_dispatch(state.wl_display) >= 0) {
if (state.closed)
break;
}
printf("Finished!\n");
vkDeviceWaitIdle(state.device);
// todo: destroy instance and all the shit