Compare commits

..

No commits in common. "9a9a5b1b0fb286e95d5ca37a8a92cbf8752eeeb5" and "dd2d3c6575b1a0ff2a9eb01e9ba901167b1c987e" have entirely different histories.

11 changed files with 137 additions and 234 deletions

View File

@ -1,4 +0,0 @@
Fonts used:
DM Serif Text made by Colophon Foundry
Roboto made by Christian Robertson, Paratype, Font Bureau
Great Vibes made by Robert Leuschke

View File

@ -7,13 +7,14 @@
void generate_l1_lucy_headers(){
SpanU8 l = cstr("l1"), ns = cstr("lucy");
mkdir_nofail("l1/eve/lucy");
generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
.T = cstr("LucyImage"), .t_primitive = true});
generate_eve_span_company_for_primitive(l, ns, cstr("OptionLucyImage"), true, false);
generate_List_templ_inst_eve_header(l, ns, (list_instantiation_op){
.T = cstr("LucyImage"), .t_primitive = true}, true);
generate_eve_span_company_for_primitive(l, ns, cstr("KVPU32ToLucyStoredGlyph"), true, false);
generate_eve_span_company_for_primitive(l, ns, cstr("KVPU32ToLucyFaceFixedSize"), true, false);
generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("LucyGlyphCachingRequest"), true, true);
/* Vector of iterators */
generate_eve_span_company_for_primitive(l, ns, cstr("RefListNodeLucyImage"), true, false);
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("LucyPositionedStagingGlyph"), .vec = true, .sort = true,

View File

@ -235,7 +235,7 @@ U32 SpanU8_decode_as_utf8(SpanU8* rem){
if (rem->len < (size_t)sz)
return 0;
U32 res = first & (b - 1);
for (int i = 1; i <= sz; i++) {
for (int i = 1; i < sz; i++) {
U8 th = rem->data[0];
if ((th & 0b11000000) != 0b10000000)
return 0;

View File

@ -660,6 +660,7 @@ void Jane_alice_destroy(VkDevice device, Jane_alice jane) {
vkDestroyFence(device, jane.roxy, NULL);
}
// todo: handle case where presentation and graphics are from the same family
typedef struct {
VkQueue graphics_queue;
VkQueue presentation_queue;
@ -1896,13 +1897,8 @@ Alice* Alice_new(){
alice->device = margaret_create_logical_device(alice->physical_device, alice->queue_fam);
if (alice->queue_fam.for_graphics == alice->queue_fam.for_presentation) {
vkGetDeviceQueue(alice->device, alice->queue_fam.for_graphics, 0, &alice->queues.graphics_queue);
alice->queues.presentation_queue = alice->queues.graphics_queue;
} else {
vkGetDeviceQueue(alice->device, alice->queue_fam.for_graphics, 0, &alice->queues.graphics_queue);
vkGetDeviceQueue(alice->device, alice->queue_fam.for_presentation, 0, &alice->queues.presentation_queue);
}
vkGetDeviceQueue(alice->device, alice->queue_fam.for_graphics, 0, &alice->queues.graphics_queue);
vkGetDeviceQueue(alice->device, alice->queue_fam.for_presentation, 0, &alice->queues.presentation_queue);
ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details(
alice->physical_device, alice->surface, alice->wl.sane_image_extent_limit);

View File

@ -7,15 +7,12 @@
#include "../../../gen/l1/VecAndSpan_U32Segment.h"
#include "../../../gen/l1/vulkan/VecVkDescriptorImageInfo.h"
#include "../../../gen/l1/pixel_masses.h"
#include "../../../gen/l1/VecAndSpan_U32.h"
#include "../../l1_5/core/buff_rb_tree_node.h"
#include "../../l1_5/core/rb_tree_node.h"
#define LUCY_MAX_DESCRIPTOR_COUNT 100
typedef U32 lucy_image_index_t;
typedef struct {
/* This value is actually Option<MargaretSubbuf>. If staging_buffer is already deleted (after it is no longer used),
* staging_buffer.len will be 0 */
@ -23,16 +20,18 @@ typedef struct {
MargaretImg img;
VkImageView img_view;
U64 usage;
U64 pos_in_desc_array;
/* 0 if this image isn't scheduled for deletion on th next cycle.
* 1 if it is */
int scheduled_for_deletion;
} LucyImage;
#include "../../../gen/l1/eve/lucy/ListLucyImage.h"
#include "../../../gen/l1/eve/lucy/OptionLucyImage.h"
#include "../../../gen/l1/eve/lucy/VecOptionLucyImage.h"
typedef ListNodeLucyImage* RefListNodeLucyImage;
#include "../../../gen/l1/eve/lucy/VecRefListNodeLucyImage.h"
typedef struct {
U32 img_slot_id;
ListNodeLucyImage* img;
U32 w, h;
U32 advance_x;
ivec2 bearing;
@ -72,28 +71,22 @@ struct LucyFace {
struct LucyGlyphCache {
MargaretEngineReference ve;
VecOptionLucyImage image_slots;
ListLucyImage images;
VkDescriptorSetLayout descriptor_set_layout;
VkDescriptorSet descriptor_set;
/* to_be_freed_of_old_staging_next_cycle never intersect with to_be_copied_to_device_next_cycle */
VecU32 to_be_freed_of_old_staging_next_cycle;
VecU32 to_be_copied_to_device_next_cycle;
VecRefListNodeLucyImage to_be_freed_of_old_staging_next_cycle;
VecRefListNodeLucyImage to_be_copied_to_device_next_cycle;
/* deletion will be performed last */
VecU32 to_be_deleted;
VecRefListNodeLucyImage to_be_deleted;
};
LucyGlyphCache LucyGlyphCache_new(MargaretEngineReference ve){
VkDescriptorSetLayout my_desc_set_layout;
VkDescriptorSetLayoutBindingFlagsCreateInfo set_layout_crinfo_flags = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
.bindingCount = 1,
.pBindingFlags = (VkDescriptorBindingFlags[]){ VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT }
};
check(vkCreateDescriptorSetLayout(ve.device, &(VkDescriptorSetLayoutCreateInfo){
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.pNext = &set_layout_crinfo_flags,
.bindingCount = 1,
.pBindings = (VkDescriptorSetLayoutBinding[]){{
.binding = 0,
@ -104,31 +97,20 @@ LucyGlyphCache LucyGlyphCache_new(MargaretEngineReference ve){
}, NULL, &my_desc_set_layout) == VK_SUCCESS);
VkDescriptorSet descriptor_set = margaret_allocate_descriptor_set(ve.device, ve.descriptor_pool,
my_desc_set_layout);
VecOptionLucyImage image_slots = VecOptionLucyImage_new_zeroinit(LUCY_MAX_DESCRIPTOR_COUNT);
for (size_t i = 0; i < LUCY_MAX_DESCRIPTOR_COUNT; i++) {
image_slots.buf[i].variant = Option_None;
}
return (LucyGlyphCache){
.ve = ve, .image_slots = image_slots,
.descriptor_set_layout = my_desc_set_layout, .descriptor_set = descriptor_set,
.to_be_freed_of_old_staging_next_cycle = VecU32_new(),
.to_be_copied_to_device_next_cycle = VecU32_new(),
.to_be_deleted = VecU32_new()};
return (LucyGlyphCache){.ve = ve, .images = ListLucyImage_new(),
.descriptor_set_layout = my_desc_set_layout, .descriptor_set = descriptor_set};
}
void LucyFaceFixedSize_get_rid_of_myself(LucyFaceFixedSize* self){
LucyGlyphCache* cache = self->p->p;
BufRBTree_MapU32ToLucyStoredGlyph* glyphs = &self->glyphs;
for (size_t gid = 0; gid < glyphs->el.len; gid++) {
U32 slot_id = glyphs->el.buf[gid].value.img_slot_id;
OptionLucyImage* img_slot = VecOptionLucyImage_mat(&cache->image_slots, slot_id);
assert(img_slot->variant == Option_Some);
LucyImage* img = &img_slot->some;
assert(img->usage > 0);
if (--img->usage) {
assert(!img->scheduled_for_deletion);
img->scheduled_for_deletion = 1;
VecU32_append(&cache->to_be_deleted, slot_id);
ListNodeLucyImage* img = glyphs->el.buf[gid].value.img;
assert(img->el.usage > 0);
if (--img->el.usage) {
assert(!img->el.scheduled_for_deletion);
img->el.scheduled_for_deletion = 1;
VecRefListNodeLucyImage_append(&cache->to_be_deleted, img);
}
}
BufRBTree_MapU32ToLucyStoredGlyph_sink(glyphs);
@ -152,7 +134,7 @@ typedef struct {
TextureDataR8 bitmap;
/* Will be determined in the next phase */
uvec2 pos;
U32 img_slot_id;
ListNodeLucyImage* img;
} LucyPositionedStagingGlyph;
bool LucyPositionedStagingGlyph_less_LucyPositionedStagingGlyph(
@ -167,37 +149,18 @@ void LucyPositionedStagingGlyph_drop(LucyPositionedStagingGlyph self){
/* Instantiation for helper type */
#include "../../../gen/l1/eve/lucy/VecLucyPositionedStagingGlyph.h"
/* Helper function */
U32 LucyGlyphCache_add_glyphs__find_image_slot(LucyGlyphCache* cache){
for (U32 i = 0; i < cache->image_slots.len; i++) {
OptionLucyImage* slot = &cache->image_slots.buf[i];
if (slot->variant == Option_None) {
slot->variant = Option_Some;
slot->some.scheduled_for_deletion = 0;
slot->some.usage = 0;
return i;
}
}
abortf("LucyCache run out of image descriptor in a descriptor set (dictated by layout).\n"
"You better add up on them\n");
}
/* Helper function */
void LucyGlyphCache_add_glyphs__close_img(
LucyGlyphCache* cache, U32 img_slot_id, U32 img_width, U32 img_height
LucyGlyphCache* cache, ListNodeLucyImage* img, U32 img_width, U32 img_height
){
OptionLucyImage* img_slot = VecOptionLucyImage_mat(&cache->image_slots, img_slot_id);
assert(img_slot->variant == Option_Some);
LucyImage* img = &img_slot->some;
assert(img->usage > 0);
assert(!img->scheduled_for_deletion);
assert(img->el.usage > 0);
img_width = MAX_U32(img_width, 10); // Just a precaution. empty buffers aren't supported by Margaret
img_height = MAX_U32(img_height, 10);
VecU32_append(&cache->to_be_copied_to_device_next_cycle, img_slot_id);
img->staging_buffer = MargaretBufAllocator_alloc(cache->ve.staging_buffers, img_width * img_height * 1);
img->img = MargaretImgAllocator_alloc(cache->ve.dev_local_images, img_width, img_height, VK_FORMAT_R8_UNORM,
VecRefListNodeLucyImage_append(&cache->to_be_copied_to_device_next_cycle, img);
img->el.staging_buffer = MargaretBufAllocator_alloc(cache->ve.staging_buffers, img_width * img_height * 1);
img->el.img = MargaretImgAllocator_alloc(cache->ve.dev_local_images, img_width, img_height, VK_FORMAT_R8_UNORM,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
img->img_view = margaret_create_view_for_image(cache->ve.device, img->img.a.image,
img->el.img_view = margaret_create_view_for_image(cache->ve.device, img->el.img.a.image,
VK_FORMAT_R8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
}
@ -265,14 +228,11 @@ void LucyGlyphCache_add_glyphs(VecLucyGlyphCachingRequest requests_for_faces){
U32 starting_x = 0;
VecU32 landscape = VecU32_new_reserved(200);
U32 img_width = 0, img_height = 0;
U32 img_slot_id = LucyGlyphCache_add_glyphs__find_image_slot(cache);
ListNodeLucyImage* img = ListLucyImage_insert(&cache->images, (LucyImage){0});
for (size_t j = 0; j < ready.len; j++) {
LucyPositionedStagingGlyph* p_glyph;
one_more_chance:
{}
int s = 23123;
p_glyph = &ready.buf[j];
LucyImage* img = &VecOptionLucyImage_mat(&cache->image_slots, img_slot_id)->some;
U64 new_width_required = p_glyph->bitmap.width + starting_x;
if (new_width_required > max_dim) {
/* Resetting row */
@ -290,12 +250,12 @@ void LucyGlyphCache_add_glyphs(VecLucyGlyphCachingRequest requests_for_faces){
U64 new_height_required = height_here + p_glyph->bitmap.height;
if (new_height_required > max_dim) {
/* Resetting image */
LucyGlyphCache_add_glyphs__close_img(cache, img_slot_id, img_width, img_height);
LucyGlyphCache_add_glyphs__close_img(cache, img, img_width, img_height);
starting_x = 0;
landscape.len = 0;
img_width = 0;
img_height = 0;
img_slot_id = LucyGlyphCache_add_glyphs__find_image_slot(cache);
img = ListLucyImage_insert(&cache->images, (LucyImage){0});
goto one_more_chance;
}
/* Success */
@ -303,25 +263,24 @@ void LucyGlyphCache_add_glyphs(VecLucyGlyphCachingRequest requests_for_faces){
*VecU32_mat(&landscape, starting_x + x) = new_height_required;
}
img_height = MAX_U64(img_height, new_height_required);
p_glyph->img_slot_id = img_slot_id;
p_glyph->img = img;
p_glyph->pos = (uvec2){starting_x, height_here};
img->usage++; /* p_glyph uses it, that's a rock fact */
img->el.usage++; /* p_glyph uses it, that's a rock fact */
BufRBTree_MapU32ToLucyStoredGlyph *glyphs = &p_glyph->sized_face->glyphs;
U64 map_it = BufRBTree_MapU32ToLucyStoredGlyph_find(glyphs, p_glyph->codepoint);
assert(map_it > 0 && map_it < glyphs->tree.len);
LucyStoredGlyph* actual_glyph = &glyphs->el.buf[map_it - 1].value;
actual_glyph->pos_on_atlas = (uvec2){starting_x, height_here};
actual_glyph->img_slot_id = img_slot_id;
actual_glyph->img = img;
starting_x += p_glyph->bitmap.width;
}
LucyGlyphCache_add_glyphs__close_img(cache, img_slot_id, img_width, img_height);
LucyGlyphCache_add_glyphs__close_img(cache, img, img_width, img_height);
/* Phase 3. We have all the data. Now what?
* Now we fill staging buffers with glyphs bitsets from `ready` vector */
for (size_t j = 0; j < ready.len; j++) {
LucyPositionedStagingGlyph* p_glyph = &ready.buf[j];
LucyImage* image = &VecOptionLucyImage_mat(&cache->image_slots, p_glyph->img_slot_id)->some;
U64 staging_width = image->img.width;
U8* staging = (U8*)MargaretSubbuf_get_mapped(&image->staging_buffer);
U64 staging_width = p_glyph->img->el.img.width;
U8* staging = (U8*)MargaretSubbuf_get_mapped(&p_glyph->img->el.staging_buffer);
for (U64 y = 0; y < p_glyph->bitmap.height; y++) {
U64 Y = y + p_glyph->pos.y;
for (U64 x = 0; x < p_glyph->bitmap.width; x++) {
@ -337,59 +296,65 @@ void LucyGlyphCache_add_glyphs(VecLucyGlyphCachingRequest requests_for_faces){
/* This must not happen before all the LucyFaceFixedSizes are destroyed */
void LucyGlyphCache_drop(LucyGlyphCache self){
for (size_t i = 0; i < self.image_slots.len; i++) {
assert(self.image_slots.buf[i].variant == Option_None);
}
VecU32_drop(self.to_be_freed_of_old_staging_next_cycle);
VecU32_drop(self.to_be_copied_to_device_next_cycle);
VecU32_drop(self.to_be_deleted);
assert(self.images.first == NULL);
VecRefListNodeLucyImage_drop(self.to_be_freed_of_old_staging_next_cycle);
VecRefListNodeLucyImage_drop(self.to_be_copied_to_device_next_cycle);
VecRefListNodeLucyImage_drop(self.to_be_deleted);
}
void LucyGlyphCache_another_frame(LucyGlyphCache* self){
for (size_t i = 0; i < self->to_be_freed_of_old_staging_next_cycle.len; i++) {
U32 slot_id = self->to_be_freed_of_old_staging_next_cycle.buf[i];
LucyImage* img = &self->image_slots.buf[slot_id].some;
LucyImage* img = &self->to_be_freed_of_old_staging_next_cycle.buf[i]->el;
assert(img->staging_buffer.len != 0);
MargaretBufAllocator_free(self->ve.staging_buffers, img->staging_buffer);
img->staging_buffer.len = 0;
}
for (size_t i = 0; i < self->to_be_copied_to_device_next_cycle.len; i++) {
U32 slot_id = self->to_be_copied_to_device_next_cycle.buf[i];
OptionLucyImage* img_slot = &self->image_slots.buf[slot_id];
assert(img_slot->variant == Option_Some);
LucyImage* img = &img_slot->some;
ListNodeLucyImage* img_node = self->to_be_copied_to_device_next_cycle.buf[i];
LucyImage* img = &img_node->el;
assert(img->staging_buffer.len != 0);
if (img->scheduled_for_deletion)
continue;
margaret_rec_cmd_copy_buffer_to_image_one_to_one_color_aspect(self->ve.transfer_cmd_buffer,
&img->staging_buffer, &img->img, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);
VecU32_append(&self->to_be_freed_of_old_staging_next_cycle, slot_id);
vkUpdateDescriptorSets(self->ve.device, 1, &(VkWriteDescriptorSet){
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = self->descriptor_set, .dstBinding = 0, .dstArrayElement = slot_id,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.pImageInfo = &(VkDescriptorImageInfo){
.sampler = self->ve.nearest_sampler, .imageView = img->img_view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
}
}, 0, NULL);
VecRefListNodeLucyImage_append(&self->to_be_freed_of_old_staging_next_cycle, img_node);
}
/* We technically could carry out each deletion request in O(1) and each img creation request in O(1),
* but who cares, it's no problem going over the entire descriptor set when something get's added or deleted */
for (size_t i = 0; i < self->to_be_deleted.len; i++) {
U32 slot_id = self->to_be_copied_to_device_next_cycle.buf[i];
OptionLucyImage* img_slot = &self->image_slots.buf[slot_id];
assert(img_slot->variant == Option_Some);
LucyImage* img = &img_slot->some;
ListNodeLucyImage* img_node = self->to_be_deleted.buf[i];
LucyImage* img = &img_node->el;
assert(img->scheduled_for_deletion);
assert(img->usage == 0);
if (img->staging_buffer.len != 0)
MargaretBufAllocator_free(self->ve.staging_buffers, img->staging_buffer);
MargaretImgAllocator_free(self->ve.dev_local_images, img->img.a);
img_slot->variant = Option_None;
ListLucyImage_erase_by_it(&self->images, img_node);
}
if ((self->to_be_copied_to_device_next_cycle.len > 0) || (self->to_be_deleted.len > 0)) {
U32 descriptor_i = 0;
VecVkDescriptorImageInfo desc_elements = VecVkDescriptorImageInfo_new();
for (ListNodeLucyImage* list_node = self->images.first; list_node; list_node = list_node->next) {
if (descriptor_i == LUCY_MAX_DESCRIPTOR_COUNT) {
abortf("Today you are out of luck\n");
}
LucyImage* img = &list_node->el;
img->pos_in_desc_array = descriptor_i;
VecVkDescriptorImageInfo_append(&desc_elements, (VkDescriptorImageInfo){
.sampler = self->ve.nearest_sampler, .imageView = img->img_view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
});
descriptor_i++;
}
vkUpdateDescriptorSets(self->ve.device, 1, &(VkWriteDescriptorSet){
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = self->descriptor_set, .dstBinding = 0, .dstArrayElement = 0,
.descriptorCount = desc_elements.len,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.pImageInfo = desc_elements.buf
}, 0, NULL);
VecVkDescriptorImageInfo_drop(desc_elements);
}
self->to_be_freed_of_old_staging_next_cycle.len = 0;
self->to_be_copied_to_device_next_cycle.len = 0;

View File

@ -13,22 +13,13 @@ typedef struct{
U32 tex_ind;
} LucyVertex;
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 glyphs_count;
U64 vertex_count;
MargaretSubbuf staging_vbo;
MargaretSubbuf vbo;
bool need_to_transfer;
@ -76,7 +67,7 @@ LucyRenderer LucyRenderer_new(
});
return (LucyRenderer){.ve = ve, .cache = cache, .pipeline_layout = pipeline_layout, .pipeline = pipeline,
.glyphs_count = 0, .staging_vbo = MargaretBufAllocator_alloc(ve.staging_buffers, 67),
.vertex_count = 0, .staging_vbo = MargaretBufAllocator_alloc(ve.staging_buffers, 67),
.vbo = MargaretBufAllocator_alloc(ve.dev_local_buffers, 67)
};
}
@ -85,7 +76,14 @@ LucyRenderer LucyRenderer_new(
* before LucyRenderer_another_frame
*/
void LucyRenderer_clear(LucyRenderer* self){
self->glyphs_count = 0;
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;
}
/* When another_frame starts, you are safe to call this function, but you also have to call it
@ -115,25 +113,10 @@ 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) {
OptionLucyImage* img_slot = VecOptionLucyImage_mat(&self->cache->image_slots, glyph->img_slot_id);
assert(img_slot->variant == Option_Some);
LucyImage* img = &img_slot->some;
float atlas_w = (float)img->img.width;
float atlas_h = (float)img->img.height;
U32 desc_elem_id = glyph->img_slot_id;
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);
U64 needed_vbo_length = (self->glyphs_count + 1) * 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);
}
LucyVertex* vbo_data = (LucyVertex*)MargaretSubbuf_get_mapped(&self->staging_vbo);
vbo_data += self->glyphs_count * 6;
LucyVertex v0 = {
.color = color, .pos = (vec2){(float)positioned.x, (float)positioned.y},
.tex_cord = (vec2){
@ -162,14 +145,21 @@ void LucyRenderer_add_text(
(float)(glyph->pos_on_atlas.y + glyph->h) / atlas_h
}, .tex_ind = desc_elem_id
};
*(vbo_data++) = v1;
*(vbo_data++) = v0;
*(vbo_data++) = v2;
*(vbo_data++) = v1;
*(vbo_data++) = v2;
*(vbo_data++) = v3;
/* 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);
self->glyphs_count++;
}
pos.x += (S32)glyph->advance_x;
}
@ -177,16 +167,14 @@ void LucyRenderer_add_text(
/* It only records transfer commands (transfer command buffer is passed in MargaretEngineReference object) */
void LucyRenderer_another_frame(LucyRenderer* self){
U64 needed_vbo_length = self->glyphs_count * 6 * sizeof(LucyVertex);
if (self->vbo.len < needed_vbo_length) {
MargaretBufAllocator_expand_or_free_old(self->ve.dev_local_buffers, &self->vbo, needed_vbo_length);
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->glyphs_count > 0) {
printf("LucyRenderer: we are doing copying\n");
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, needed_vbo_length);
&self->staging_vbo, &self->vbo, 0, self->vertex_count * sizeof(LucyVertex));
}
}
@ -201,7 +189,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->glyphs_count * 6, 1, 0, 0);
vkCmdDraw(drawing_cmd_buf, self->vertex_count, 1, 0, 0);
}
#endif

View File

@ -309,27 +309,20 @@ NODISCARD VecU8 margaret_stringify_device_memory_properties_2(VkPhysicalDevice p
VkDevice margaret_create_logical_device(VkPhysicalDevice physical_device, MargaretChosenQueueFamilies queue_fam) {
VkPhysicalDeviceFeatures physical_features;
vkGetPhysicalDeviceFeatures(physical_device, &physical_features);
float qfam_queue_priorities[1] = {1.f};
VkDeviceQueueCreateInfo queue_crinfo[2] = { 0 };
int queue_c = 0;
if (queue_fam.for_graphics == queue_fam.for_presentation) {
queue_c = 1;
queue_crinfo[0].queueFamilyIndex = queue_fam.for_graphics;
} else {
queue_c = 2;
queue_crinfo[0].queueFamilyIndex = queue_fam.for_graphics;
queue_crinfo[1].queueFamilyIndex = queue_fam.for_presentation;
}
for (int i = 0; i < queue_c; i++) {
queue_crinfo[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queue_crinfo[i].queueCount = 1;
queue_crinfo[i].pQueuePriorities = qfam_queue_priorities;
// todo: handle case of `two in one`
float qfam_instance_priorities[1] = {1.f};
VkDeviceQueueCreateInfo logical_device_queue_crinfo[2] = { 0 };
for (int i = 0; i < 2; i++) {
logical_device_queue_crinfo[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
logical_device_queue_crinfo[i].queueCount = 1;
logical_device_queue_crinfo[i].pQueuePriorities = qfam_instance_priorities;
}
logical_device_queue_crinfo[0].queueFamilyIndex = queue_fam.for_graphics;
logical_device_queue_crinfo[1].queueFamilyIndex = queue_fam.for_presentation;
VkPhysicalDeviceVulkan12Features used_vk12_features = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
.runtimeDescriptorArray = true,
.descriptorBindingPartiallyBound = true,
.shaderSampledImageArrayNonUniformIndexing = true,
};
// We DEMAND synchronization2
@ -352,8 +345,8 @@ VkDevice margaret_create_logical_device(VkPhysicalDevice physical_device, Margar
VkDeviceCreateInfo device_crinfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = (const void*)&used_features2,
.queueCreateInfoCount = queue_c,
.pQueueCreateInfos = queue_crinfo,
.queueCreateInfoCount = ARRAY_SIZE(logical_device_queue_crinfo),
.pQueueCreateInfos = logical_device_queue_crinfo,
.enabledExtensionCount = ARRAY_SIZE(needed_extensions),
.ppEnabledExtensionNames = needed_extensions,
// We leave that filed because we have specified features2 in `.pNext`
@ -590,8 +583,6 @@ MargaretScoredPhysicalDevice margaret_score_physical_device(
return (MargaretScoredPhysicalDevice){dev, -1, cstr("No shaderSampledImageArrayNonUniformIndexing")};
if (!vk12_features.runtimeDescriptorArray)
return (MargaretScoredPhysicalDevice){dev, -1, cstr("No runtimeDescriptorArray")};
if (!vk12_features.descriptorBindingPartiallyBound)
return (MargaretScoredPhysicalDevice){dev, -1, cstr("No descriptorBindingPartiallyBound")};
ResultMargaretChosenQueueFamiliesOrSpanU8 queue_families = margaret_choose_good_queue_families(dev, surface);
if (queue_families.variant == Result_Err)
return (MargaretScoredPhysicalDevice){dev, -1, queue_families.err};

Binary file not shown.

View File

@ -3,14 +3,7 @@ import Geom
import Control.Monad (forM_, when)
import Data.Char (ord)
import Data.IORef (newIORef, readIORef, writeIORef, modifyIORef)
import Data.Word(Word32, Word64)
lucyFaceAddGlyphRange :: LucyFaceFixedSize -> Char -> Char -> IO ()
lucyFaceAddGlyphRange ffs a b = lucyFaceAddGlyphs ffs aInt (bInt - aInt + 1)
where aInt = ((fromIntegral $ ord a) :: Word32)
bInt = ((fromIntegral $ ord b) :: Word32)
-- Game configurable
goodColorOfCube :: (Integral a) => a -> Vec3
goodColorOfCube i = ((Vec3 100 0 0) ^*^ t) ^+^ ((Vec3 0 50 90) ^*^ (1 - t)) where t = ((fromIntegral i :: Float) / 4)
@ -40,9 +33,7 @@ main = do
aliceSetCamPos alice (Vec3 0 heroHeight 0)
face <- aliceNewLucyFace alice "src/l3/fonts/DMSerifText-Regular.ttf"
faceOf40 <- aliceLucyFaceOfSize face 40
lucyFaceAddGlyphRange faceOf40 ' ' '~'
lucyFaceAddGlyphRange faceOf40 'а' 'я'
lucyFaceAddGlyphRange faceOf40 'А' 'Я'
lucyFaceAddGlyphs faceOf40 32 (126 - 32 + 1)
aliceAddText alice faceOf40 (Vec4 1 1 0 1) "Privet" 100 200
weirdStructure <- aliceAddGenericMeshHand alice "gen/l2/models/log_10_2_6.AliceGenericMesh"
@ -76,7 +67,6 @@ main = do
heroPos <- newIORef (Vec2 0 0)
puckRotation <- newIORef (0 :: Float)
-- Create the Callbacks structure.
let callbacks = Callbacks myonKeyboardKey myonAnotherFrame where
myonKeyboardKey keysym keyAction = do

View File

@ -18,57 +18,33 @@ AliceGenericMeshPath AliceGenericMeshPath_for_puck(){
};
}
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;
// st.font_face = LucyFace_new(st.alice->ft_library, &st.alice->lucy_cache,
// VecU8_fmt("%s/src/l3/fonts/DMSerifText-Regular.ttf", cstr(".")));
st.font_face = LucyFace_new(st.alice->ft_library, &st.alice->lucy_cache,
VecU8_fmt("%s/src/l3/fonts/GreatVibes-Regular.ttf", cstr(".")));
st.font_face_of_size_40 = LucyFace_of_size(st.font_face, 40);
LucyFace* font_face = LucyFace_new(alice->ft_library, &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);
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 = st.font_face_of_size_40, .codepoint_ranges = ranges_needed,
.sized_face = 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,
});
LucyGlyphCache_add_glyphs(lucy_requests);
LucyRenderer_add_text(&st.alice->lucy_renderer, st.font_face_of_size_40, (vec4){0, 0, 0, 1}, 0,
cstr("Bebra budet\nотнюхана\n"), (ivec2){10, 10});
LucyRenderer_add_text(&alice->lucy_renderer, 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(st.alice, AliceGenericMeshPath_for_log(cstr("."), 10, 2, 6));
AliceGenericMeshHand_resize_instance_arr(st.alice, &model_gen->el, 1);
ListNodeAliceGenericMeshHand* model_gen = Alice_add_generic_mesh(alice, AliceGenericMeshPath_for_log(cstr("."), 10, 2, 6));
AliceGenericMeshHand_resize_instance_arr(alice, &model_gen->el, 1);
for (int X = 0; X < 1; X++) {
for (int Z = 0; Z < 1; Z++) {
@ -78,8 +54,8 @@ int main(){
}
}
// 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);
// ListNodeAliceShinyMeshHand *model_sh = Alice_add_shiny_mesh(alice, vcstr("./gen/l2/models/cube.AliceShinyMesh"));
// AliceShinyMeshHand_resize_instance_arr(alice, &model_sh->el, 100);
// for (int X = 0; X < 10; X++) {
// for (int Z = 0; Z < 10; Z++) {
@ -90,7 +66,7 @@ int main(){
// }
// }
// Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&st->alice->pipeline0_ubo.staging);
// Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_ubo.staging);
// assert(pipeline_0_ubo_point_light_max_count >= 100);
// ubo->point_light_count = 100;
// ubo->spotlight_count = 0;
@ -105,8 +81,8 @@ int main(){
// ubo->point_light_arr[0].color = (vec3){100, 100, 100};
// ListNodeAliceGenericMeshHand* model_puck = Alice_add_generic_mesh(st->alice, AliceGenericMeshPath_for_puck());
// AliceGenericMeshHand_resize_instance_arr(st->alice, &model_puck->el, 100);
// ListNodeAliceGenericMeshHand* model_puck = Alice_add_generic_mesh(alice, AliceGenericMeshPath_for_puck());
// AliceGenericMeshHand_resize_instance_arr(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){
@ -114,7 +90,7 @@ int main(){
// });
// }
// }
Alice_mainloop(st.alice, &(AliceCallbacks){
Alice_mainloop(alice, &(AliceCallbacks){
.on_wl_keyboard_key = main_h_on_wayland_keyboard_key,
.on_another_frame = main_h_on_another_frame,
});