From 284b0b711b8c43d8dcb1ba50fdb5fe6943151693 Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Thu, 1 Jan 2026 15:29:05 +0300 Subject: [PATCH] Found a serious flaw in Lucy design. A very very serious flaw. Gonna rewrite everything --- src/l2/lucy/glyph_cache.h | 13 ++++- src/l2/lucy/glyph_render.h | 99 +++++++++++++++++++++++--------------- src/l3/r4/R4.hs | 11 +++-- src/l3/r4/r4.c | 50 +++++++++++++------ 4 files changed, 115 insertions(+), 58 deletions(-) diff --git a/src/l2/lucy/glyph_cache.h b/src/l2/lucy/glyph_cache.h index 134561e..01f7345 100644 --- a/src/l2/lucy/glyph_cache.h +++ b/src/l2/lucy/glyph_cache.h @@ -80,6 +80,10 @@ struct LucyGlyphCache { VecRefListNodeLucyImage to_be_copied_to_device_next_cycle; /* deletion will be performed last */ VecRefListNodeLucyImage to_be_deleted; + /* This filed is actually used in later stages of 'another_frame' sequence. It is used by font renderer + * to know if sus stuff had occurred. At the beginning of my _another_frame method it gets turned false + * automatically, but during my _another_frame it can get raised true to indicate reshuffling of images */ + bool changes_happened; }; @@ -98,7 +102,10 @@ LucyGlyphCache LucyGlyphCache_new(MargaretEngineReference ve){ VkDescriptorSet descriptor_set = margaret_allocate_descriptor_set(ve.device, ve.descriptor_pool, my_desc_set_layout); return (LucyGlyphCache){.ve = ve, .images = ListLucyImage_new(), - .descriptor_set_layout = my_desc_set_layout, .descriptor_set = descriptor_set}; + .descriptor_set_layout = my_desc_set_layout, .descriptor_set = descriptor_set, + .to_be_freed_of_old_staging_next_cycle = VecRefListNodeLucyImage_new(), + .to_be_copied_to_device_next_cycle = VecRefListNodeLucyImage_new(), + .to_be_deleted = VecRefListNodeLucyImage_new(), .changes_happened = false}; } void LucyFaceFixedSize_get_rid_of_myself(LucyFaceFixedSize* self){ @@ -302,7 +309,10 @@ void LucyGlyphCache_drop(LucyGlyphCache self){ VecRefListNodeLucyImage_drop(self.to_be_deleted); } +void + void LucyGlyphCache_another_frame(LucyGlyphCache* self){ + self->changes_happened = false; for (size_t i = 0; i < self->to_be_freed_of_old_staging_next_cycle.len; i++) { LucyImage* img = &self->to_be_freed_of_old_staging_next_cycle.buf[i]->el; assert(img->staging_buffer.len != 0); @@ -355,6 +365,7 @@ void LucyGlyphCache_another_frame(LucyGlyphCache* self){ .pImageInfo = desc_elements.buf }, 0, NULL); VecVkDescriptorImageInfo_drop(desc_elements); + self->changes_happened = true; } self->to_be_freed_of_old_staging_next_cycle.len = 0; self->to_be_copied_to_device_next_cycle.len = 0; diff --git a/src/l2/lucy/glyph_render.h b/src/l2/lucy/glyph_render.h index fc34018..e8bea21 100644 --- a/src/l2/lucy/glyph_render.h +++ b/src/l2/lucy/glyph_render.h @@ -13,13 +13,32 @@ typedef struct{ U32 tex_ind; } LucyVertex; +typedef struct { + ListNodeLucyImage* img; + vec4 color; + ivec2 positioned; + uvec2 pos_on_atlas; + U32 w; + U32 h; +} LucyRenderedGlyphRecord; + +#include "../../../gen/l1/eve/lucy/VecLucyRenderedGlyphRecord.h" + +typedef struct { + vec4 color; + vec2 lt_pos; + vec2 br_pos; + vec2 lt_tex; + vec2 br_tex; +} LucyGlyphInstance; + typedef struct { MargaretEngineReference ve; LucyGlyphCache* cache; VkPipelineLayout pipeline_layout; VkPipeline pipeline; - U64 vertex_count; + VecLucyRenderedGlyphRecord rendered_glyphs; MargaretSubbuf staging_vbo; MargaretSubbuf vbo; bool need_to_transfer; @@ -67,7 +86,7 @@ LucyRenderer LucyRenderer_new( }); return (LucyRenderer){.ve = ve, .cache = cache, .pipeline_layout = pipeline_layout, .pipeline = pipeline, - .vertex_count = 0, .staging_vbo = MargaretBufAllocator_alloc(ve.staging_buffers, 67), + .rendered_glyphs = VecLucyRenderedGlyphRecord_new(), .staging_vbo = MargaretBufAllocator_alloc(ve.staging_buffers, 67), .vbo = MargaretBufAllocator_alloc(ve.dev_local_buffers, 67) }; } @@ -76,14 +95,7 @@ LucyRenderer LucyRenderer_new( * before LucyRenderer_another_frame */ void LucyRenderer_clear(LucyRenderer* self){ - self->vertex_count = 0; -} - -void LucyRenderer__append_vertex_to_vao(LucyRenderer* self, LucyVertex vert_data){ - self->vertex_count++; - assert(self->vertex_count * sizeof(LucyVertex) <= self->staging_vbo.len); - LucyVertex* staging = (LucyVertex*)MargaretSubbuf_get_mapped(&self->staging_vbo); - staging[self->vertex_count - 1] = vert_data; + self->rendered_glyphs.len = 0; } /* When another_frame starts, you are safe to call this function, but you also have to call it @@ -113,10 +125,40 @@ void LucyRenderer_add_text( assert(map_it > 0 && map_it < glyphs->tree.len); LucyStoredGlyph* glyph = &glyphs->el.buf[map_it - 1].value; if (glyph->w > 0 && glyph->h > 0) { + VecLucyRenderedGlyphRecord_append(&self->rendered_glyphs, (LucyRenderedGlyphRecord){ + .color = color, .img = glyph->img, + .positioned = ivec2_add_ivec2(pos, glyph->bearing), + .pos_on_atlas = glyph->pos_on_atlas, .w = glyph->w, .h = glyph->h + }); + } + pos.x += (S32)glyph->advance_x; + } +} + +/* It only records transfer commands (transfer command buffer is passed in MargaretEngineReference object) */ +void LucyRenderer_another_frame(LucyRenderer* self){ + U64 needed_vbo_length = self->rendered_glyphs.len * 6 * sizeof(LucyVertex); + if (self->staging_vbo.len < needed_vbo_length) { + printf("LucyRenderer Staging Buffer: Gotta replace %lu with %lu\n", + self->staging_vbo.len, needed_vbo_length); + MargaretBufAllocator_expand_or_move_old_host_visible( + self->ve.staging_buffers, &self->staging_vbo, needed_vbo_length); + } + if (self->vbo.len < needed_vbo_length) { + MargaretBufAllocator_expand_or_free_old(self->ve.dev_local_buffers, &self->vbo, needed_vbo_length); + } + size_t vertex_id = 0; // todo: rewrite using instances + LucyVertex* vbo_data = (LucyVertex*)MargaretSubbuf_get_mapped(&self->staging_vbo); + if ((self->cache->changes_happened || self->need_to_transfer) && self->rendered_glyphs.len > 0) { + printf("LucyRenderer: we are doing copying\n"); + + for (size_t i = 0; i < self->rendered_glyphs.len; i++) { + LucyRenderedGlyphRecord* glyph = &self->rendered_glyphs.buf[i]; float atlas_w = (float)glyph->img->el.img.width; float atlas_h = (float)glyph->img->el.img.height; U32 desc_elem_id = glyph->img->el.pos_in_desc_array; - ivec2 positioned = ivec2_add_ivec2(pos, glyph->bearing); + vec4 color = glyph->color; + ivec2 positioned = glyph->positioned; LucyVertex v0 = { .color = color, .pos = (vec2){(float)positioned.x, (float)positioned.y}, .tex_cord = (vec2){ @@ -145,36 +187,17 @@ void LucyRenderer_add_text( (float)(glyph->pos_on_atlas.y + glyph->h) / atlas_h }, .tex_ind = desc_elem_id }; - /* What if we run out of space? */ - U64 needed_vbo_length = (self->vertex_count + 6) * sizeof(LucyVertex); - if (self->staging_vbo.len < needed_vbo_length) { - printf("LucyRenderer Staging Buffer: Gotta replace %lu with %lu\n", - self->staging_vbo.len, needed_vbo_length); - MargaretBufAllocator_expand_or_move_old_host_visible( - self->ve.staging_buffers, &self->staging_vbo, needed_vbo_length); - } - LucyRenderer__append_vertex_to_vao(self, v1); - LucyRenderer__append_vertex_to_vao(self, v0); - LucyRenderer__append_vertex_to_vao(self, v2); - LucyRenderer__append_vertex_to_vao(self, v1); - LucyRenderer__append_vertex_to_vao(self, v2); - LucyRenderer__append_vertex_to_vao(self, v3); - + vbo_data[vertex_id++] = v1; + vbo_data[vertex_id++] = v0; + vbo_data[vertex_id++] = v2; + vbo_data[vertex_id++] = v1; + vbo_data[vertex_id++] = v2; + vbo_data[vertex_id++] = v3; } - pos.x += (S32)glyph->advance_x; - } -} -/* It only records transfer commands (transfer command buffer is passed in MargaretEngineReference object) */ -void LucyRenderer_another_frame(LucyRenderer* self){ - if (self->vbo.len < self->vertex_count * sizeof(LucyVertex)) { - MargaretBufAllocator_expand_or_free_old(self->ve.dev_local_buffers, &self->vbo, - self->vertex_count * sizeof(LucyVertex)); - } - if (self->need_to_transfer && self->vertex_count > 0) { self->need_to_transfer = false; margaret_rec_cmd_copy_buffer_one_to_one_part(self->ve.transfer_cmd_buffer, - &self->staging_vbo, &self->vbo, 0, self->vertex_count * sizeof(LucyVertex)); + &self->staging_vbo, &self->vbo, 0, needed_vbo_length); } } @@ -189,7 +212,7 @@ void LucyRenderer_another_frame_rec_drawing( (VkBuffer[]){MargaretSubbuf_get_buffer(&self->vbo)}, (VkDeviceSize[]){self->vbo.start}); vkCmdBindDescriptorSets(drawing_cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, self->pipeline_layout, 0, 1, (VkDescriptorSet[]){self->cache->descriptor_set}, 0, NULL); - vkCmdDraw(drawing_cmd_buf, self->vertex_count, 1, 0, 0); + vkCmdDraw(drawing_cmd_buf, self->rendered_glyphs.len * 6, 1, 0, 0); } #endif \ No newline at end of file diff --git a/src/l3/r4/R4.hs b/src/l3/r4/R4.hs index 94ef4c2..28eb866 100644 --- a/src/l3/r4/R4.hs +++ b/src/l3/r4/R4.hs @@ -6,9 +6,9 @@ import Data.IORef (newIORef, readIORef, writeIORef, modifyIORef) import Data.Word(Word32, Word64) lucyFaceAddGlyphRange :: LucyFaceFixedSize -> Char -> Char -> IO () -lucyFaceAddGlyphRange ffs a b = lucyFaceAddGlyphs ffs A (B - A + 1) where - A = ((fromIntegral $ ord a) :: Word32) - B = ((fromIntegral $ ord b) :: Word32) +lucyFaceAddGlyphRange ffs a b = lucyFaceAddGlyphs ffs aInt (bInt - aInt + 1) + where aInt = ((fromIntegral $ ord a) :: Word32) + bInt = ((fromIntegral $ ord b) :: Word32) -- Game configurable @@ -40,8 +40,9 @@ main = do aliceSetCamPos alice (Vec3 0 heroHeight 0) face <- aliceNewLucyFace alice "src/l3/fonts/DMSerifText-Regular.ttf" faceOf40 <- aliceLucyFaceOfSize face 40 - lucyFaceAddGlyphs faceOf40 32 (126 - 32 + 1) - lucyFaceAddGlyphs faceOf40 (fromIntegral) (126 - 32 + 1) + lucyFaceAddGlyphRange faceOf40 ' ' '~' + lucyFaceAddGlyphRange faceOf40 'а' 'я' + lucyFaceAddGlyphRange faceOf40 'А' 'Я' aliceAddText alice faceOf40 (Vec4 1 1 0 1) "Privet" 100 200 weirdStructure <- aliceAddGenericMeshHand alice "gen/l2/models/log_10_2_6.AliceGenericMesh" diff --git a/src/l3/r4/r4.c b/src/l3/r4/r4.c index 1b464af..6835e90 100644 --- a/src/l3/r4/r4.c +++ b/src/l3/r4/r4.c @@ -18,33 +18,55 @@ AliceGenericMeshPath AliceGenericMeshPath_for_puck(){ }; } -void main_h_on_wayland_keyboard_key(void* data, U32 keysym, U32 act){ +typedef struct{ + Alice* alice; + LucyFace* font_face; + RBTreeNodeLucyFaceFixedSize* font_face_of_size_40; +} R4AlphaStuff; +void main_h_on_wayland_keyboard_key(void* data, U32 keysym, U32 act){ } void main_h_on_another_frame(void* data, float fl){ - + R4AlphaStuff *st = data; + Alice* alice = st->alice; + margaret_ns_time TIME = margaret_clock_gettime_monotonic_raw(); + printf("Updating text\n"); + LucyRenderer_clear(&alice->lucy_renderer); + VecU8 text = VecU8_fmt("Time is %u.%u\nHave a good day sir\n", (U64)TIME.tv_sec, (U64)TIME.tv_nsec); + LucyRenderer_add_text(&alice->lucy_renderer, st->font_face_of_size_40, (vec4){0.1f, 0.2f, 0, 1}, 0, + VecU8_to_span(&text), (ivec2){100, 100}); } int main(){ + R4AlphaStuff st; Alice* alice = Alice_new(); + st.alice = alice; + st.alice->guest = &st; - LucyFace* font_face = LucyFace_new(alice->ft_library, &alice->lucy_cache, + st.font_face = LucyFace_new(st.alice->ft_library, &st.alice->lucy_cache, VecU8_fmt("%s/src/l3/fonts/DMSerifText-Regular.ttf", cstr("."))); - RBTreeNodeLucyFaceFixedSize* font_face_of_size_40 = LucyFace_of_size(font_face, 40); + st.font_face_of_size_40 = LucyFace_of_size(st.font_face, 13); VecLucyGlyphCachingRequest lucy_requests = VecLucyGlyphCachingRequest_new(); VecU32Segment ranges_needed = VecU32Segment_new(); VecU32Segment_append(&ranges_needed, (U32Segment){.start = 32, .len = 126 - 32 + 1}); VecLucyGlyphCachingRequest_append(&lucy_requests, (LucyGlyphCachingRequest){ - .sized_face = font_face_of_size_40, .codepoint_ranges = ranges_needed, + .sized_face = st.font_face_of_size_40, .codepoint_ranges = ranges_needed, }); LucyGlyphCache_add_glyphs(lucy_requests); + lucy_requests = VecLucyGlyphCachingRequest_new(); + ranges_needed = VecU32Segment_new(); + VecU32Segment_append(&ranges_needed, (U32Segment){.start = 0x430, .len = 0x44f - 0x430 + 1}); + VecLucyGlyphCachingRequest_append(&lucy_requests, (LucyGlyphCachingRequest){ + .sized_face = st.font_face_of_size_40, .codepoint_ranges = ranges_needed, + }); - LucyRenderer_add_text(&alice->lucy_renderer, font_face_of_size_40, (vec4){1, 0, 0, 1}, 0, + LucyGlyphCache_add_glyphs(lucy_requests); + LucyRenderer_add_text(&st.alice->lucy_renderer, st.font_face_of_size_40, (vec4){1, 0, 0, 1}, 0, cstr("Bebra budet\notnyahana"), (ivec2){10, 10}); - ListNodeAliceGenericMeshHand* model_gen = Alice_add_generic_mesh(alice, AliceGenericMeshPath_for_log(cstr("."), 10, 2, 6)); - AliceGenericMeshHand_resize_instance_arr(alice, &model_gen->el, 1); + ListNodeAliceGenericMeshHand* model_gen = Alice_add_generic_mesh(st.alice, AliceGenericMeshPath_for_log(cstr("."), 10, 2, 6)); + AliceGenericMeshHand_resize_instance_arr(st.alice, &model_gen->el, 1); for (int X = 0; X < 1; X++) { for (int Z = 0; Z < 1; Z++) { @@ -54,8 +76,8 @@ int main(){ } } - // ListNodeAliceShinyMeshHand *model_sh = Alice_add_shiny_mesh(alice, vcstr("./gen/l2/models/cube.AliceShinyMesh")); - // AliceShinyMeshHand_resize_instance_arr(alice, &model_sh->el, 100); + // ListNodeAliceShinyMeshHand *model_sh = Alice_add_shiny_mesh(st->alice, vcstr("./gen/l2/models/cube.AliceShinyMesh")); + // AliceShinyMeshHand_resize_instance_arr(st->alice, &model_sh->el, 100); // for (int X = 0; X < 10; X++) { // for (int Z = 0; Z < 10; Z++) { @@ -66,7 +88,7 @@ int main(){ // } // } - // Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_ubo.staging); + // Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&st->alice->pipeline0_ubo.staging); // assert(pipeline_0_ubo_point_light_max_count >= 100); // ubo->point_light_count = 100; // ubo->spotlight_count = 0; @@ -81,8 +103,8 @@ int main(){ // ubo->point_light_arr[0].color = (vec3){100, 100, 100}; - // ListNodeAliceGenericMeshHand* model_puck = Alice_add_generic_mesh(alice, AliceGenericMeshPath_for_puck()); - // AliceGenericMeshHand_resize_instance_arr(alice, &model_puck->el, 100); + // ListNodeAliceGenericMeshHand* model_puck = Alice_add_generic_mesh(st->alice, AliceGenericMeshPath_for_puck()); + // AliceGenericMeshHand_resize_instance_arr(st->alice, &model_puck->el, 100); // for (int X = 0; X < 10; X++) { // for (int Z = 0; Z < 10; Z++) { // AliceGenericMeshHand_set_inst(&model_puck->el, X * 10 + Z, (GenericMeshInstanceInc){ @@ -90,7 +112,7 @@ int main(){ // }); // } // } - Alice_mainloop(alice, &(AliceCallbacks){ + Alice_mainloop(st.alice, &(AliceCallbacks){ .on_wl_keyboard_key = main_h_on_wayland_keyboard_key, .on_another_frame = main_h_on_another_frame, });