Compare commits

..

No commits in common. "5b8ecd80207b59eabe831b0a07fed4dbd9685e3f" and "1fbd4f041371ce2a49c106c745675b025b584c37" have entirely different histories.

10 changed files with 255 additions and 401 deletions

View File

@ -9,7 +9,7 @@ HEADERS_src_l1_5 = $(HEADERS_gen_l1) $(call find_headers,l1_5)
#HEADERS_gen_l1_5 := $(HEADERS_src_l1_5) gen/l1_5/dorothy.txt
HEADERS_gen_l1_5 := gen/l1_5/dorothy.txt
ASSETS_src_l_adele = $(call find_assets,l_adele)
ASSETS_src_l_adele = $($call find_assets,l_adele)
ASSETS_gen_l_adele = gen/l_adele/dorothy.txt
HEADERS_src_l2 := $(HEADERS_gen_l1_5) $(call find_headers,l2)

View File

@ -10,11 +10,6 @@ void generate_code_for_alice_on_l1(){
generate_eve_span_company_for_primitive(l, ns, cstr("GenericMeshVertexInc"), true, true);
generate_eve_span_company_for_primitive(l, ns, cstr("ShinyMeshVertexInc"), true, true);
/* Helpful utils for sticking your butt into rendering mainloop (transferring stuff to device local
* memory at the right time) */
generate_eve_span_company_for_primitive(l, ns, cstr("RefAliceBufferUplOnce"), true, false);
generate_eve_span_company_for_primitive(l, ns, cstr("RefAliceTextureUplOnce"), true, false);
/* Engine stuff */
// todo: yes, maybe right now it is not primitive but I surely will make it primitive someday. Right now I don't care
generate_List_templ_inst_eve_header(l, ns, (list_instantiation_op){

View File

@ -3,7 +3,6 @@
#include "model_file.h"
#include "../../l1/marie/geom_alg_utils.h"
#include "../margaret/vulkan_utils.h"
#include "transfer_in_mainloop.h"
#include "../lucy/glyph_render.h"
typedef struct {
@ -13,6 +12,9 @@ typedef struct {
} PatriciaBuf;
typedef struct {
VkImageView diffuse_view;
VkImageView normal_view;
VkImageView specular_view;
/* Each generic model has its own descriptor set
* It's because it has its own textures. But it also has copies of references to light UBO
* Because I am to lazy to create two set layouts for generic model pipeline */
@ -21,21 +23,28 @@ typedef struct {
typedef struct {
size_t indexes;
// Option<MargaretSubbuf>
MargaretSubbuf staging_vbo;
// Option<MargaretSubbuf>
MargaretSubbuf staging_ebo;
// todo: replace TextureDataXXX with MargaretPngPromises
TextureDataR8G8B8A8 pixels_diffuse;
TextureDataR8G8B8A8 pixels_normal;
TextureDataR8 pixels_specular;
AliceBufferUplOnce* vbo;
AliceBufferUplOnce* ebo;
AliceTextureUplOnce* diffuse_texture;
AliceTextureUplOnce* normal_texture;
AliceTextureUplOnce* specular_texture;
MargaretSubbuf staging_diffuse_tex_buf;
MargaretSubbuf staging_normal_tex_buf;
MargaretSubbuf staging_specular_tex_buf;
MargaretSubbuf vbo;
MargaretSubbuf ebo;
PatriciaBuf instance_attr;
MargaretImg diffuse_texture;
MargaretImg normal_texture;
MargaretImg specular_texture;
AliceGenericMeshMemDependantVkObj mem_dependant_vk_obj;
bool scheduled_for_deletion;
@ -46,8 +55,11 @@ typedef struct {
typedef struct {
size_t indexes;
AliceBufferUplOnce* vbo;
AliceBufferUplOnce* ebo;
MargaretSubbuf staging_vbo;
MargaretSubbuf staging_ebo;
MargaretSubbuf vbo;
MargaretSubbuf ebo;
PatriciaBuf instance_attr;
bool scheduled_for_deletion;
@ -724,12 +736,17 @@ typedef struct ListNodeAliceGenericMeshHand* RefListNodeAliceGenericMeshHand;
typedef struct {
ListAliceGenericMeshHand hands;
/* Familiar pattern. Todo: move familiar pattern to l1 codegen. 2 matches so far */
VecRefListNodeAliceGenericMeshHand to_be_freed_of_old_staging_next_cycle;
VecRefListNodeAliceGenericMeshHand to_be_copied_to_device_next_cycle;
VecRefListNodeAliceGenericMeshHand to_be_deleted;
} AliceAllMeshesGeneric;
AliceAllMeshesGeneric AliceAllMeshesGeneric_new(){
return (AliceAllMeshesGeneric){
.hands = ListAliceGenericMeshHand_new(),
.to_be_freed_of_old_staging_next_cycle = VecRefListNodeAliceGenericMeshHand_new(),
.to_be_copied_to_device_next_cycle = VecRefListNodeAliceGenericMeshHand_new(),
.to_be_deleted = VecRefListNodeAliceGenericMeshHand_new(),
};
}
@ -740,12 +757,16 @@ typedef struct ListNodeAliceShinyMeshHand* RefListNodeAliceShinyMeshHand;
typedef struct {
ListAliceShinyMeshHand hands;
/* Ah */
VecRefListNodeAliceShinyMeshHand to_be_freed_of_old_staging_next_cycle;
VecRefListNodeAliceShinyMeshHand to_be_copied_to_device_next_cycle;
VecRefListNodeAliceShinyMeshHand to_be_deleted;
} AliceAllMeshesShiny;
AliceAllMeshesShiny AliceAllMeshesShiny_new(){
return (AliceAllMeshesShiny){
.hands = ListAliceShinyMeshHand_new(),
.to_be_freed_of_old_staging_next_cycle = VecRefListNodeAliceShinyMeshHand_new(),
.to_be_copied_to_device_next_cycle = VecRefListNodeAliceShinyMeshHand_new(),
.to_be_deleted = VecRefListNodeAliceShinyMeshHand_new(),
};
}
@ -785,9 +806,6 @@ struct Alice {
Jane_alice jane; // todo: figure out my own design
MargaretSwapchainBundle swfb;
AliceAllSingleUploadBuffers single_upload_buffers;
AliceAllSingleUploadTextures single_upload_textures;
AlicePipeline0UBO pipeline0_ubo;
AliceAllMeshesGeneric generic_models;
AliceAllMeshesShiny shiny_models;
@ -811,8 +829,7 @@ struct Alice {
};
ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const GenericMeshTopology* topology,
AliceGenericMeshTexturePaths t_paths
){
AliceGenericMeshTexturePaths t_paths){
ListNodeAliceGenericMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceGenericMeshHand));
AliceGenericMeshHand* mm = &mm_node->el;
@ -821,6 +838,11 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const Generic
mm->instance_attr.staging = MargaretBufAllocator_alloc(&alice->staging_buffers, 200);
mm->instance_attr.device_local = MargaretBufAllocator_alloc(&alice->dev_local_buffers, 200);
mm->staging_vbo = MargaretBufAllocator_alloc(&alice->staging_buffers,
topology->vertices.len * sizeof(GenericMeshVertex));
mm->staging_ebo = MargaretBufAllocator_alloc(&alice->staging_buffers,
topology->indexes.len * sizeof(U32));
// todo: change this, I don't like this at all :(
mm->pixels_diffuse = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&t_paths.diffuse_texture_path));
mm->pixels_normal = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&t_paths.normal_texture_path));
@ -829,36 +851,38 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const Generic
VecU8_drop(t_paths.normal_texture_path);
VecU8_drop(t_paths.specular_texture_path);
mm->vbo = AliceAllSingleUploadBuffers_register_new(&alice->single_upload_buffers,
topology->vertices.len * sizeof(GenericMeshVertex),
&alice->staging_buffers, &alice->dev_local_buffers);
mm->ebo = AliceAllSingleUploadBuffers_register_new(&alice->single_upload_buffers,
topology->indexes.len * sizeof(U32),
&alice->staging_buffers, &alice->dev_local_buffers);
mm->staging_diffuse_tex_buf = MargaretBufAllocator_alloc(&alice->staging_buffers,
mm->pixels_diffuse.pixels.len * sizeof(cvec4));
mm->staging_normal_tex_buf = MargaretBufAllocator_alloc(&alice->staging_buffers,
mm->pixels_normal.pixels.len * sizeof(cvec4));
mm->staging_specular_tex_buf = MargaretBufAllocator_alloc(&alice->staging_buffers,
mm->pixels_specular.pixels.len * sizeof(U8));
mm->diffuse_texture = AliceAllSingleUploadTextures_register_new(&alice->single_upload_textures,
mm->vbo = MargaretBufAllocator_alloc(&alice->dev_local_buffers,
topology->vertices.len * sizeof(GenericMeshVertex));
mm->ebo = MargaretBufAllocator_alloc(&alice->dev_local_buffers,
topology->indexes.len * sizeof(U32));
mm->diffuse_texture = MargaretImgAllocator_alloc(&alice->dev_local_images,
mm->pixels_diffuse.width, mm->pixels_diffuse.height,
sizeof(cvec4), VK_FORMAT_R8G8B8A8_SRGB,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
&alice->staging_buffers, &alice->dev_local_images);
mm->normal_texture = AliceAllSingleUploadTextures_register_new(&alice->single_upload_textures,
VK_FORMAT_R8G8B8A8_SRGB,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
mm->normal_texture = MargaretImgAllocator_alloc(&alice->dev_local_images,
mm->pixels_normal.width, mm->pixels_normal.height,
sizeof(cvec4), VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
&alice->staging_buffers, &alice->dev_local_images);
mm->specular_texture = AliceAllSingleUploadTextures_register_new(&alice->single_upload_textures,
VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
mm->specular_texture = MargaretImgAllocator_alloc(&alice->dev_local_images,
mm->pixels_specular.width, mm->pixels_specular.height,
sizeof(U8), VK_FORMAT_R8_UNORM,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
&alice->staging_buffers, &alice->dev_local_images);
VK_FORMAT_R8_UNORM,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
mm->scheduled_for_deletion = false;
/* We allocated enough memory, but now it's time to actually fill staging buffers */
/* Filling staging VBO */
assert(mm->vbo->staging.len >= topology->vertices.len * sizeof(GenericMeshVertex));
assert(mm->vbo->device_buf.len >= topology->vertices.len * sizeof(GenericMeshVertex));
GenericMeshVertex* staging_vbo = (GenericMeshVertex*)AliceBufferUplOnce_get_mapped_staging(mm->vbo);
/* Filleing staging VBO */
assert(mm->staging_vbo.len >= topology->vertices.len * sizeof(GenericMeshVertex));
assert(mm->vbo.len >= topology->vertices.len * sizeof(GenericMeshVertex));
GenericMeshVertex* staging_vbo = (GenericMeshVertex*)MargaretSubbuf_get_mapped(&mm->staging_vbo);
for (U64 i = 0; i < topology->vertices.len; i++) {
staging_vbo[i].base = topology->vertices.buf[i];
}
@ -888,47 +912,53 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const Generic
/* Filling EBO is easy */
assert(topology->indexes.len == mm->indexes);
size_t ebo_len = topology->indexes.len * sizeof(U32);
assert(mm->ebo->staging.len >= ebo_len);
U32* staging_ebo = (U32*)AliceBufferUplOnce_get_mapped_staging(mm->ebo);
assert(mm->ebo.len >= ebo_len);
U32* staging_ebo = (U32*)MargaretSubbuf_get_mapped(&mm->staging_ebo);
memcpy(staging_ebo, topology->indexes.buf, ebo_len);
/* Filling staging textures from memory pixel data */
/* todo: do it immediately ON THE READ */
memcpy(AliceTextureUplOnce_get_mapped_staging(mm->diffuse_texture), mm->pixels_diffuse.pixels.buf,
memcpy(MargaretSubbuf_get_mapped(&mm->staging_diffuse_tex_buf), mm->pixels_diffuse.pixels.buf,
TextureDataR8G8B8A8_get_size_in_bytes(&mm->pixels_diffuse));
memcpy(AliceTextureUplOnce_get_mapped_staging(mm->normal_texture), mm->pixels_normal.pixels.buf,
memcpy(MargaretSubbuf_get_mapped(&mm->staging_normal_tex_buf), mm->pixels_normal.pixels.buf,
TextureDataR8G8B8A8_get_size_in_bytes(&mm->pixels_normal));
memcpy(AliceTextureUplOnce_get_mapped_staging(mm->specular_texture), mm->pixels_specular.pixels.buf,
memcpy(MargaretSubbuf_get_mapped(&mm->staging_specular_tex_buf), mm->pixels_specular.pixels.buf,
TextureDataR8_get_size_in_bytes(&mm->pixels_specular));
// todo: that is about time when we can delete mm->pixels_* buffers. They are still wasting space out there
// todo: BUt I won't do it, because I chose inplace texture reading (from png)
/* But now we are filling AliceGenericMeshMemDependantVkObj. If we ever gonna do defragmentation,
* this step would have to be repeated */
VkDescriptorSet P = margaret_allocate_descriptor_set(alice->device,
alice->descriptor_pool, alice->pipeline_hands_0a.descriptor_set_layout);
mm->mem_dependant_vk_obj.p_0a_set_0 = P;
AliceGenericMeshMemDependantVkObj P = (AliceGenericMeshMemDependantVkObj){
.diffuse_view = margaret_create_view_for_image(alice->device, mm->diffuse_texture.a.image,
VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT),
.normal_view = margaret_create_view_for_image(alice->device, mm->normal_texture.a.image,
VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT),
.specular_view = margaret_create_view_for_image(alice->device, mm->specular_texture.a.image,
VK_FORMAT_R8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT),
.p_0a_set_0 = margaret_allocate_descriptor_set(alice->device,
alice->descriptor_pool, alice->pipeline_hands_0a.descriptor_set_layout),
};
mm->mem_dependant_vk_obj = P;
VkDescriptorBufferInfo buffer_info_for_descriptor_0_in_set_0a = {
.buffer = MargaretSubbuf_get_buffer(&alice->pipeline0_ubo.device_local),
.offset = alice->pipeline0_ubo.device_local.start, .range = sizeof(Pipeline0UBO),
};
VkDescriptorImageInfo image_info_for_descriptor_1_in_set_0a = {
.sampler = alice->linear_sampler, .imageView = mm->diffuse_texture->view,
.sampler = alice->linear_sampler, .imageView = P.diffuse_view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
};
VkDescriptorImageInfo image_info_for_descriptor_2_in_set_0a = {
.sampler = alice->nearest_sampler, .imageView = mm->normal_texture->view,
.sampler = alice->nearest_sampler, .imageView = P.normal_view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
};
VkDescriptorImageInfo image_info_for_descriptor_3_in_set_0a = {
.sampler = alice->nearest_sampler, .imageView = mm->specular_texture->view,
.sampler = alice->nearest_sampler, .imageView = P.specular_view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
};
VkWriteDescriptorSet writes_in_descriptor_set[] = {
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = P,
.dstSet = P.p_0a_set_0,
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
@ -937,7 +967,7 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const Generic
},
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = P,
.dstSet = P.p_0a_set_0,
.dstBinding = 1,
.dstArrayElement = 0,
.descriptorCount = 1,
@ -946,7 +976,7 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const Generic
},
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = P,
.dstSet = P.p_0a_set_0,
.dstBinding = 2,
.dstArrayElement = 0,
.descriptorCount = 1,
@ -955,7 +985,7 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const Generic
},
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = P,
.dstSet = P.p_0a_set_0,
.dstBinding = 3,
.dstArrayElement = 0,
.descriptorCount = 1,
@ -966,10 +996,12 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const Generic
vkUpdateDescriptorSets(alice->device, ARRAY_SIZE(writes_in_descriptor_set), writes_in_descriptor_set, 0, NULL);
ListAliceGenericMeshHand_insert_node(&alice->generic_models.hands, mm_node);
VecRefListNodeAliceGenericMeshHand_append(&alice->generic_models.to_be_copied_to_device_next_cycle, mm_node);
return mm_node;
}
ListNodeAliceShinyMeshHand* Alice_add_shiny_mesh(Alice* alice, const ShinyMeshTopology* topology){
ListNodeAliceShinyMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceShinyMeshHand));
AliceShinyMeshHand* mm = &mm_node->el;
@ -979,18 +1011,23 @@ ListNodeAliceShinyMeshHand* Alice_add_shiny_mesh(Alice* alice, const ShinyMeshTo
mm->instance_attr.staging = MargaretBufAllocator_alloc(&alice->staging_buffers, 128);
mm->instance_attr.device_local = MargaretBufAllocator_alloc(&alice->dev_local_buffers, 128);
mm->vbo = AliceAllSingleUploadBuffers_register_new(&alice->single_upload_buffers,
topology->vertices.len * sizeof(ShinyMeshVertex),
&alice->staging_buffers, &alice->dev_local_buffers);
mm->ebo = AliceAllSingleUploadBuffers_register_new(&alice->single_upload_buffers,
topology->indexes.len * sizeof(U32),
&alice->staging_buffers, &alice->dev_local_buffers);
mm->staging_vbo = MargaretBufAllocator_alloc(&alice->staging_buffers,
topology->vertices.len * sizeof(ShinyMeshVertex));
mm->staging_ebo = MargaretBufAllocator_alloc(&alice->staging_buffers,
topology->indexes.len * sizeof(U32));
mm->vbo = MargaretBufAllocator_alloc(&alice->dev_local_buffers,
topology->vertices.len * sizeof(ShinyMeshVertex));
mm->ebo = MargaretBufAllocator_alloc(&alice->dev_local_buffers,
topology->indexes.len * sizeof(U32));
ListAliceShinyMeshHand_insert_node(&alice->shiny_models.hands, mm_node);
VecRefListNodeAliceShinyMeshHand_append(&alice->shiny_models.to_be_copied_to_device_next_cycle, mm_node);
/* We allocated enough memory, now it's time to actually fill staging buffers */
/* And we start by filling staging VBO */
assert(mm->vbo->staging.len >= topology->vertices.len * sizeof(ShinyMeshVertex));
assert(mm->vbo->device_buf.len >= topology->vertices.len * sizeof(ShinyMeshVertex));
ShinyMeshVertex* staging_vbo = (ShinyMeshVertex*)AliceBufferUplOnce_get_mapped_staging(mm->vbo);
assert(mm->staging_vbo.len >= topology->vertices.len * sizeof(ShinyMeshVertex));
assert(mm->vbo.len >= topology->vertices.len * sizeof(ShinyMeshVertex));
ShinyMeshVertex* staging_vbo = (ShinyMeshVertex*)MargaretSubbuf_get_mapped(&mm->staging_vbo);
for (U64 i = 0; i < topology->vertices.len; i++) {
staging_vbo[i].base = topology->vertices.buf[i];
}
@ -1005,43 +1042,21 @@ ListNodeAliceShinyMeshHand* Alice_add_shiny_mesh(Alice* alice, const ShinyMeshTo
vec3 norm = vec3_normalize(vec3_cross(vec3_minus_vec3(p1, p0), vec3_minus_vec3(p2, p0)));
staging_vbo[v0].normal = staging_vbo[v1].normal = staging_vbo[v2].normal = norm;
}
/* Filling staging EBO is super-duper easy */
assert(topology->indexes.len == mm->indexes);
size_t ebo_len = topology->indexes.len * sizeof(U32);
assert(mm->ebo->staging.len >= ebo_len);
U32* staging_ebo = (U32*)AliceBufferUplOnce_get_mapped_staging(mm->ebo);
assert(mm->ebo.len >= ebo_len);
U32* staging_ebo = (U32*)MargaretSubbuf_get_mapped(&mm->staging_ebo);
memcpy(staging_ebo, topology->indexes.buf, ebo_len);
ListAliceShinyMeshHand_insert_node(&alice->shiny_models.hands, mm_node);
return mm_node;
}
void Alice_delete_generic_mesh(Alice* alice, ListNodeAliceGenericMeshHand* hand) {
AliceAllSingleUploadBuffers_delete(&alice->single_upload_buffers, hand->el.vbo);
AliceAllSingleUploadBuffers_delete(&alice->single_upload_buffers, hand->el.ebo);
AliceAllSingleUploadTextures_delete(&alice->single_upload_textures, hand->el.diffuse_texture);
AliceAllSingleUploadTextures_delete(&alice->single_upload_textures, hand->el.normal_texture);
AliceAllSingleUploadTextures_delete(&alice->single_upload_textures, hand->el.specular_texture);
hand->el.normal_texture = hand->el.normal_texture = hand->el.specular_texture = NULL;
hand->el.vbo = hand->el.ebo = NULL;
VecRefListNodeAliceGenericMeshHand_append(&alice->generic_models.to_be_deleted, hand);
}
void Alice_delete_shiny_mesh(Alice* alice, ListNodeAliceShinyMeshHand* hand) {
AliceAllSingleUploadBuffers_delete(&alice->single_upload_buffers, hand->el.vbo);
AliceAllSingleUploadBuffers_delete(&alice->single_upload_buffers, hand->el.ebo);
hand->el.vbo = hand->el.ebo = NULL;
VecRefListNodeAliceShinyMeshHand_append(&alice->shiny_models.to_be_deleted, hand);
}
void AliceGenericMeshHand_resize_instance_arr(Alice* alice, AliceGenericMeshHand* self, U64 new_count){
U64 needed_length = new_count * sizeof(GenericMeshInstance);
if (self->instance_attr.staging.len < needed_length) {
printf("Alice generic model instance staging Buffer: Gotta replace %lu with %lu\n",
self->instance_attr.staging.len, needed_length);
self->staging_vbo.len, needed_length);
MargaretBufAllocator_expand_or_move_old_host_visible(
&alice->staging_buffers, &self->instance_attr.staging, needed_length);
}
@ -1079,34 +1094,108 @@ void AliceShinyMeshHand_set_inst(AliceShinyMeshHand* self, size_t instance, Shin
tr_inv.x.z, tr_inv.y.z, tr_inv.z.z );
}
void AliceAllMeshesGeneric__resolve_on_another_frame(Alice* alice, AliceAllMeshesGeneric* self){
void AliceAllMeshesGeneric__resolve_mesh_creation(Alice* alice, AliceAllMeshesGeneric* self){
for (size_t i = 0; i < self->to_be_freed_of_old_staging_next_cycle.len; i++) {
AliceGenericMeshHand* mm = &self->to_be_freed_of_old_staging_next_cycle.buf[i]->el;
assert(mm->staging_vbo.len != 0);
assert(mm->staging_ebo.len != 0);
MargaretBufAllocator_free(&alice->staging_buffers, mm->staging_vbo);
MargaretBufAllocator_free(&alice->staging_buffers, mm->staging_ebo);
mm->staging_vbo.len = 0;
mm->staging_ebo.len = 0;
}
for (size_t i = 0; i < self->to_be_copied_to_device_next_cycle.len; i++) {
ListNodeAliceGenericMeshHand* mm_node = self->to_be_copied_to_device_next_cycle.buf[i];
AliceGenericMeshHand* mm = &mm_node->el;
assert(mm->staging_vbo.len != 0);
assert(mm->staging_ebo.len != 0);
if (mm->scheduled_for_deletion)
continue;
margaret_rec_cmd_copy_buffer_one_to_one(alice->transfer_command_buf, &mm->staging_vbo, &mm->vbo);
margaret_rec_cmd_copy_buffer_one_to_one(alice->transfer_command_buf, &mm->staging_ebo, &mm->ebo);
margaret_rec_cmd_copy_buffer_to_image_one_to_one_color_aspect(alice->transfer_command_buf,
&mm->staging_diffuse_tex_buf, &mm->diffuse_texture, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);
margaret_rec_cmd_copy_buffer_to_image_one_to_one_color_aspect(alice->transfer_command_buf,
&mm->staging_normal_tex_buf, &mm->normal_texture, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);
margaret_rec_cmd_copy_buffer_to_image_one_to_one_color_aspect(alice->transfer_command_buf,
&mm->staging_specular_tex_buf, &mm->specular_texture, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);
VecRefListNodeAliceGenericMeshHand_append(&self->to_be_freed_of_old_staging_next_cycle, mm_node);
}
for (size_t i = 0; i < self->to_be_deleted.len; i++) {
ListNodeAliceGenericMeshHand* mm_node = self->to_be_deleted.buf[i];
AliceGenericMeshHand* mm = &mm_node->el;
assert(mm->scheduled_for_deletion);
assert(mm->vbo == NULL);
assert(mm->ebo == NULL);
MargaretBufAllocator_free(&alice->staging_buffers, mm->instance_attr.staging);
MargaretBufAllocator_free(&alice->dev_local_buffers, mm->instance_attr.device_local);
if (mm->staging_vbo.len != 0)
MargaretBufAllocator_free(&alice->staging_buffers, mm->staging_vbo);
if (mm->staging_ebo.len != 0)
MargaretBufAllocator_free(&alice->staging_buffers, mm->staging_ebo);
if (mm->staging_diffuse_tex_buf.len != 0)
MargaretBufAllocator_free(&alice->staging_buffers, mm->staging_diffuse_tex_buf);
if (mm->staging_normal_tex_buf.len != 0)
MargaretBufAllocator_free(&alice->staging_buffers, mm->staging_normal_tex_buf);
if (mm->staging_specular_tex_buf.len != 0)
MargaretBufAllocator_free(&alice->staging_buffers, mm->staging_specular_tex_buf);
MargaretBufAllocator_free(&alice->dev_local_buffers, mm->vbo);
MargaretBufAllocator_free(&alice->dev_local_buffers, mm->ebo);
MargaretImgAllocator_free(&alice->dev_local_images, mm->diffuse_texture.a);
MargaretImgAllocator_free(&alice->dev_local_images, mm->normal_texture.a);
MargaretImgAllocator_free(&alice->dev_local_images, mm->specular_texture.a);
// todo: the problem is, here we don't free some memory stored in AliceGenericMeshHand to store texture.
// todo: but the truth is: I am gonna get rid of pixels_{,,} fields very soon, so AliceGenericMeshHand would
// todo: be primitive again, without stupid crap
ListAliceGenericMeshHand_erase_by_it(&self->hands, mm_node);
}
self->to_be_freed_of_old_staging_next_cycle.len = 0;
self->to_be_copied_to_device_next_cycle.len = 0;
self->to_be_deleted.len = 0;
}
void AliceAllMeshesShiny__resolve_on_another_frame(Alice* alice, AliceAllMeshesShiny* self){
void AliceAllMeshesShiny__resolve_mesh_creation(Alice* alice, AliceAllMeshesShiny* self){
for (size_t i = 0; i < self->to_be_freed_of_old_staging_next_cycle.len; i++) {
AliceShinyMeshHand* mm = &self->to_be_freed_of_old_staging_next_cycle.buf[i]->el;
assert(mm->staging_vbo.len != 0);
assert(mm->staging_ebo.len != 0);
MargaretBufAllocator_free(&alice->staging_buffers, mm->staging_vbo);
MargaretBufAllocator_free(&alice->staging_buffers, mm->staging_ebo);
mm->staging_vbo.len = 0;
mm->staging_ebo.len = 0;
}
for (size_t i = 0; i < self->to_be_copied_to_device_next_cycle.len; i++) {
ListNodeAliceShinyMeshHand* mm_node = self->to_be_copied_to_device_next_cycle.buf[i];
AliceShinyMeshHand* mm = &mm_node->el;
assert(mm->staging_vbo.len != 0);
assert(mm->staging_ebo.len != 0);
if (mm->scheduled_for_deletion)
continue;
margaret_rec_cmd_copy_buffer_one_to_one(alice->transfer_command_buf, &mm->staging_vbo, &mm->vbo);
margaret_rec_cmd_copy_buffer_one_to_one(alice->transfer_command_buf, &mm->staging_ebo, &mm->ebo);
VecRefListNodeAliceShinyMeshHand_append(&self->to_be_freed_of_old_staging_next_cycle, mm_node);
}
for (size_t i = 0; i < self->to_be_deleted.len; i++) {
ListNodeAliceShinyMeshHand* mm_node = self->to_be_deleted.buf[i];
AliceShinyMeshHand* mm = &mm_node->el;
assert(mm->scheduled_for_deletion);
assert(mm->vbo == NULL);
assert(mm->ebo == NULL);
MargaretBufAllocator_free(&alice->staging_buffers, mm->instance_attr.staging);
MargaretBufAllocator_free(&alice->dev_local_buffers, mm->instance_attr.device_local);
if (mm->staging_vbo.len != 0)
MargaretBufAllocator_free(&alice->staging_buffers, mm->staging_vbo);
if (mm->staging_ebo.len != 0)
MargaretBufAllocator_free(&alice->staging_buffers, mm->staging_ebo);
MargaretBufAllocator_free(&alice->dev_local_buffers, mm->vbo);
MargaretBufAllocator_free(&alice->dev_local_buffers, mm->ebo);
ListAliceShinyMeshHand_erase_by_it(&self->hands, mm_node);
}
self->to_be_freed_of_old_staging_next_cycle.len = 0;
self->to_be_copied_to_device_next_cycle.len = 0;
self->to_be_deleted.len = 0;
}
@ -1117,8 +1206,8 @@ void AliceAllMeshesShiny__resolve_on_another_frame(Alice* alice, AliceAllMeshesS
* 3) As mentioned before, Pipeline0UBO also gets copied
*/
void AliceScene__another_frame(Alice* alice) {
AliceAllMeshesGeneric__resolve_on_another_frame(alice, &alice->generic_models);
AliceAllMeshesShiny__resolve_on_another_frame(alice, &alice->shiny_models);
AliceAllMeshesGeneric__resolve_mesh_creation(alice, &alice->generic_models);
AliceAllMeshesShiny__resolve_mesh_creation(alice, &alice->shiny_models);
for (ListNodeAliceGenericMeshHand* mm_node = alice->generic_models.hands.first; mm_node; mm_node = mm_node->next) {
AliceGenericMeshHand* mm = &mm_node->el;
@ -1202,9 +1291,9 @@ void alice_reset_and_record_command_buffer_0(Alice* alice, mat4 proj_cam_t) {
AliceGenericMeshHand* model = &mm_node->el;
VkDescriptorSet model_indiv_descriptor_set_0 = model->mem_dependant_vk_obj.p_0a_set_0;
const MargaretSubbuf* dev_local_vbo = &model->vbo->device_buf;
const MargaretSubbuf* dev_local_vbo = &model->vbo;
const MargaretSubbuf* dev_local_inst_attr = &model->instance_attr.device_local;
const MargaretSubbuf* dev_local_ebo = &model->ebo->device_buf;
const MargaretSubbuf* dev_local_ebo = &model->ebo;
// const
vkCmdBindVertexBuffers(alice->rendering_command_buf_0, 0,
2, (VkBuffer[]){
@ -1230,9 +1319,9 @@ void alice_reset_and_record_command_buffer_0(Alice* alice, mat4 proj_cam_t) {
1, &alice->descriptor_set_for_pipeline_0b, 0, NULL);
for (ListNodeAliceShinyMeshHand* mm_node = alice->shiny_models.hands.first; mm_node; mm_node = mm_node->next) {
const AliceShinyMeshHand* model = &mm_node->el;
const MargaretSubbuf* dev_local_vbo = &model->vbo->device_buf;
const MargaretSubbuf* dev_local_vbo = &model->vbo;
const MargaretSubbuf* dev_local_inst_attr = &model->instance_attr.device_local;
const MargaretSubbuf* dev_local_ebo = &model->ebo->device_buf;
const MargaretSubbuf* dev_local_ebo = &model->ebo;
vkCmdBindVertexBuffers(alice->rendering_command_buf_0, 0, 2, (VkBuffer[]){
MargaretSubbuf_get_buffer(dev_local_vbo), MargaretSubbuf_get_buffer(dev_local_inst_attr)
}, (VkDeviceSize[]){ dev_local_vbo->start, dev_local_inst_attr->start });
@ -1394,13 +1483,6 @@ void alice_frame_drawing(Alice* alice) {
alice->callbacks.on_another_frame(alice->guest, (float)(alice->wl.cur_frame_time - alice->wl.last_frame_time) / 1000);
margaret_reset_and_begin_command_buffer(alice->transfer_command_buf);
/* Literally everything, including lucy cache, depends on these two steps */
AliceAllSingleUploadBuffers__resolve_on_another_frame(&alice->single_upload_buffers,
&alice->staging_buffers, &alice->dev_local_buffers, alice->transfer_command_buf);
AliceAllSingleUploadTextures__resolve_on_another_frame(&alice->single_upload_textures,
&alice->staging_buffers, &alice->dev_local_images, alice->transfer_command_buf);
AliceScene__another_frame(alice);
LucyGlyphCache_another_frame(&alice->lucy_cache);
LucyRenderer_another_frame(&alice->lucy_renderer);
@ -1879,8 +1961,8 @@ Alice* Alice_new(){
// todo: inquire about the uniform buffer alignment and storage buffer alignment
alice->dev_local_buffers = MargaretBufAllocator_new(alice->device, alice->physical_device,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT ,
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
/* | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT */,
mem_type_id_device_local, 6, false, 10000);
alice->dev_local_images = MargaretImgAllocator_new(alice->device, alice->physical_device,
@ -1892,9 +1974,6 @@ Alice* Alice_new(){
alice->device, alice->queue_fam, swapchain_details_res.ok,
alice->surface, alice->render_pass_1, NULL);
alice->single_upload_buffers = AliceAllSingleUploadBuffers_new();
alice->single_upload_textures = AliceAllSingleUploadTextures_new();
alice->generic_models = AliceAllMeshesGeneric_new();
alice->shiny_models = AliceAllMeshesShiny_new();
alice->pipeline0_ubo.staging = MargaretBufAllocator_alloc(&alice->staging_buffers, sizeof(Pipeline0UBO));
@ -1921,7 +2000,7 @@ Alice* Alice_new(){
if (ft_init_err)
abortf("Can't init free type library\n");
alice->lucy_cache = LucyGlyphCache_new(engine_reference, &alice->single_upload_textures);
alice->lucy_cache = LucyGlyphCache_new(engine_reference);
alice->lucy_renderer = LucyRenderer_new(engine_reference, &alice->lucy_cache, root_dir, alice->render_pass_1, 0);

View File

@ -1,209 +0,0 @@
#pragma once
/* I sometimes call this sub-namespace of Alice namespace Abigail. Though I hadn't renamed it to Abigail yet.
* Abigail does not depend on Alice Engine. It only depends on margaret. So systems like Lucy can use it
* without creating any sus circular dependepncies.
*/
#include "../margaret/vulkan_utils.h"
/* Handler of a read-only buffer that can be uploaded and deleted at any time with it's staging buffer automatically
* deleted (Similar to what AliceTextureUploadedOnce does to textures) */
typedef struct {
MargaretSubbuf staging;
MargaretSubbuf device_buf;
bool scheduled_for_deletion;
} AliceBufferUplOnce;
typedef AliceBufferUplOnce* RefAliceBufferUplOnce;
#include "../../../gen/l1/eve/alice/VecRefAliceBufferUplOnce.h"
/* Handler of a texture that can be uploaded and deleted at any time with it's staging buffer automatically deleted.
* Stores VkImageView as a bonus */
typedef struct {
MargaretSubbuf staging;
MargaretImg img;
VkImageView view;
bool scheduled_for_deletion;
} AliceTextureUplOnce;
typedef AliceTextureUplOnce* RefAliceTextureUplOnce;
#include "../../../gen/l1/eve/alice/VecRefAliceTextureUplOnce.h"
typedef struct {
VecRefAliceBufferUplOnce to_be_freed_of_old_staging_next_cycle;
VecRefAliceBufferUplOnce to_be_copied_to_device_next_cycle;
VecRefAliceBufferUplOnce to_be_deleted;
} AliceAllSingleUploadBuffers;
AliceAllSingleUploadBuffers AliceAllSingleUploadBuffers_new() {
return (AliceAllSingleUploadBuffers){
.to_be_freed_of_old_staging_next_cycle = VecRefAliceBufferUplOnce_new(),
.to_be_copied_to_device_next_cycle = VecRefAliceBufferUplOnce_new(),
.to_be_deleted = VecRefAliceBufferUplOnce_new(),
};
}
typedef struct {
VecRefAliceTextureUplOnce to_be_freed_of_old_staging_next_cycle;
VecRefAliceTextureUplOnce to_be_copied_to_device_next_cycle;
VecRefAliceTextureUplOnce to_be_deleted;
} AliceAllSingleUploadTextures;
AliceAllSingleUploadTextures AliceAllSingleUploadTextures_new(){
return (AliceAllSingleUploadTextures){
.to_be_freed_of_old_staging_next_cycle = VecRefAliceTextureUplOnce_new(),
.to_be_copied_to_device_next_cycle = VecRefAliceTextureUplOnce_new(),
.to_be_deleted = VecRefAliceTextureUplOnce_new(),
};
}
void AliceAllSingleUploadBuffers__resolve_on_another_frame(AliceAllSingleUploadBuffers* self,
MargaretBufAllocator* staging_buffers, MargaretBufAllocator* dev_local_buffers, VkCommandBuffer transfer_cmd_buffer
) {
for (size_t i = 0; i < self->to_be_freed_of_old_staging_next_cycle.len; i++) {
AliceBufferUplOnce* mm = self->to_be_freed_of_old_staging_next_cycle.buf[i];
assert(mm->staging.len != 0);
MargaretBufAllocator_free(staging_buffers, mm->staging);
mm->staging.len = 0;
}
for (size_t i = 0; i < self->to_be_copied_to_device_next_cycle.len; i++) {
AliceBufferUplOnce* mm = self->to_be_copied_to_device_next_cycle.buf[i];
assert(mm->staging.len != 0);
if (mm->scheduled_for_deletion)
continue;
margaret_rec_cmd_copy_buffer_one_to_one(transfer_cmd_buffer, &mm->staging, &mm->device_buf);
VecRefAliceBufferUplOnce_append(&self->to_be_freed_of_old_staging_next_cycle, mm);
}
for (size_t i = 0; i < self->to_be_deleted.len; i++) {
AliceBufferUplOnce* mm = self->to_be_deleted.buf[i];
assert(mm->scheduled_for_deletion);
if (mm->staging.len != 0)
MargaretBufAllocator_free(staging_buffers, mm->staging);
MargaretBufAllocator_free(dev_local_buffers, mm->device_buf);
free(mm);
}
self->to_be_freed_of_old_staging_next_cycle.len = 0;
self->to_be_copied_to_device_next_cycle.len = 0;
self->to_be_deleted.len = 0;
}
void AliceAllSingleUploadTextures__resolve_on_another_frame(AliceAllSingleUploadTextures* self,
MargaretBufAllocator* staging_buffers, MargaretImgAllocator* dev_local_images, VkCommandBuffer transfer_cmd_buffer
) {
for (size_t i = 0; i < self->to_be_freed_of_old_staging_next_cycle.len; i++) {
AliceTextureUplOnce* mm = self->to_be_freed_of_old_staging_next_cycle.buf[i];
assert(mm->staging.len != 0);
MargaretBufAllocator_free(staging_buffers, mm->staging);
mm->staging.len = 0;
}
for (size_t i = 0; i < self->to_be_copied_to_device_next_cycle.len; i++) {
AliceTextureUplOnce* mm = self->to_be_copied_to_device_next_cycle.buf[i];
assert(mm->staging.len != 0);
if (mm->scheduled_for_deletion)
continue;
margaret_rec_cmd_copy_buffer_to_image_one_to_one_color_aspect(transfer_cmd_buffer,
&mm->staging, &mm->img, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);
VecRefAliceTextureUplOnce_append(&self->to_be_freed_of_old_staging_next_cycle, mm);
}
for (size_t i = 0; i < self->to_be_deleted.len; i++) {
AliceTextureUplOnce* mm = self->to_be_deleted.buf[i];
assert(mm->scheduled_for_deletion);
if (mm->staging.len != 0)
MargaretBufAllocator_free(staging_buffers, mm->staging);
MargaretImgAllocator_free(dev_local_images, mm->img.a);
vkDestroyImageView(dev_local_images->device, mm->view, NULL);
free(mm);
}
self->to_be_freed_of_old_staging_next_cycle.len = 0;
self->to_be_copied_to_device_next_cycle.len = 0;
self->to_be_deleted.len = 0;
}
/* Doesn't get automatically added to `to_be_copied_to_device_next_cycle` */
AliceBufferUplOnce* AliceBufferUplOnce_new(size_t len,
MargaretBufAllocator* staging_buffers, MargaretBufAllocator* dev_local_buffers
) {
AliceBufferUplOnce* res = (AliceBufferUplOnce*)safe_malloc(sizeof(AliceBufferUplOnce));
res->staging = MargaretBufAllocator_alloc(staging_buffers, len);
res->device_buf = MargaretBufAllocator_alloc(dev_local_buffers, len);
res->scheduled_for_deletion = false;
return res;
}
void* AliceBufferUplOnce_get_mapped_staging(AliceBufferUplOnce* self) {
return MargaretSubbuf_get_mapped(&self->staging);
}
void AliceAllSingleUploadBuffers_register(AliceAllSingleUploadBuffers* self, AliceBufferUplOnce* obj) {
assert(obj->staging.len > 0);
assert(!obj->scheduled_for_deletion);
VecRefAliceBufferUplOnce_append(&self->to_be_copied_to_device_next_cycle, obj);
}
AliceBufferUplOnce* AliceAllSingleUploadBuffers_register_new(AliceAllSingleUploadBuffers* self, size_t len,
MargaretBufAllocator* staging_buffers, MargaretBufAllocator* dev_local_buffers
) {
AliceBufferUplOnce* res = AliceBufferUplOnce_new(len, staging_buffers, dev_local_buffers);
AliceAllSingleUploadBuffers_register(self, res);
return res;
}
void AliceAllSingleUploadBuffers_delete(AliceAllSingleUploadBuffers* self, AliceBufferUplOnce* obj) {
assert(obj);
obj->scheduled_for_deletion = true;
VecRefAliceBufferUplOnce_append(&self->to_be_deleted, obj);
}
/* Doesn't get automatically added to `to_be_copied_to_device_next_cycle`
* Only works for VK_IMAGE_ASPECT_COLOR_BIT images */
AliceTextureUplOnce* AliceTextureUplOnce_new(U64 width, U64 height, U64 pixel_sz, VkFormat format,
VkImageUsageFlags usage, MargaretBufAllocator* staging_buffers, MargaretImgAllocator* dev_local_images
) {
assert(pixel_sz == margaret_singleplane_format_to_sizeof_type(format));
AliceTextureUplOnce* res = (AliceTextureUplOnce*)safe_malloc(sizeof(AliceTextureUplOnce));
res->staging = MargaretBufAllocator_alloc(staging_buffers, width * height * pixel_sz);
res->img = MargaretImgAllocator_alloc(dev_local_images, width, height, format, usage);
res->view = margaret_create_view_for_image(dev_local_images->device, res->img.a.image,
format, VK_IMAGE_ASPECT_COLOR_BIT);
res->scheduled_for_deletion = false;
return res;
}
void* AliceTextureUplOnce_get_mapped_staging(AliceTextureUplOnce* self) {
return MargaretSubbuf_get_mapped(&self->staging);
}
void AliceAllSingleUploadTextures_register(AliceAllSingleUploadTextures* self, AliceTextureUplOnce* obj) {
assert(obj->staging.len > 0);
assert(!obj->scheduled_for_deletion);
VecRefAliceTextureUplOnce_append(&self->to_be_copied_to_device_next_cycle, obj);
}
AliceTextureUplOnce* AliceAllSingleUploadTextures_register_new(AliceAllSingleUploadTextures* self,
U64 width, U64 height, U64 pixel_sz, VkFormat format,
VkImageUsageFlags usage, MargaretBufAllocator* staging_buffers, MargaretImgAllocator* dev_local_images
) {
AliceTextureUplOnce* res = AliceTextureUplOnce_new(width, height, pixel_sz, format, usage,
staging_buffers, dev_local_images);
AliceAllSingleUploadTextures_register(self, res);
return res;
}
void AliceAllSingleUploadTextures_delete(AliceAllSingleUploadTextures* self, AliceTextureUplOnce* obj) {
assert(obj);
obj->scheduled_for_deletion = true;
VecRefAliceTextureUplOnce_append(&self->to_be_deleted, obj);
}

View File

@ -1,23 +1,30 @@
#pragma once
#include "../margaret/vulkan_utils.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#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"
#include "../alice/transfer_in_mainloop.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#define LUCY_MAX_DESCRIPTOR_COUNT 100
typedef U32 lucy_image_index_t;
typedef struct {
AliceTextureUplOnce* tex;
/* This value is actually Option<MargaretSubbuf>. If staging_buffer is already deleted (after it is no longer used),
* staging_buffer.len will be 0 */
MargaretSubbuf staging_buffer;
MargaretImg img;
VkImageView img_view;
U64 usage;
/* Is this image scheduled for deletion on th next cycle. */
bool scheduled_for_deletion;
/* 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/OptionLucyImage.h"
@ -64,19 +71,19 @@ struct LucyFace {
struct LucyGlyphCache {
MargaretEngineReference ve;
AliceAllSingleUploadTextures* single_upload_textures;
VecOptionLucyImage image_slots;
VkDescriptorSetLayout descriptor_set_layout;
VkDescriptorSet descriptor_set;
/* We can delete images and link images to descriptor set only when frame isn't in flight */
VecU32 to_be_written_to_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;
/* deletion will be performed last */
VecU32 to_be_deleted;
};
LucyGlyphCache LucyGlyphCache_new(MargaretEngineReference ve, AliceAllSingleUploadTextures* single_upload_textures){
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,
@ -101,9 +108,10 @@ LucyGlyphCache LucyGlyphCache_new(MargaretEngineReference ve, AliceAllSingleUplo
image_slots.buf[i].variant = Option_None;
}
return (LucyGlyphCache){
.ve = ve, .single_upload_textures = single_upload_textures, .image_slots = image_slots,
.ve = ve, .image_slots = image_slots,
.descriptor_set_layout = my_desc_set_layout, .descriptor_set = descriptor_set,
.to_be_written_to_descriptor_set = VecU32_new(),
.to_be_freed_of_old_staging_next_cycle = VecU32_new(),
.to_be_copied_to_device_next_cycle = VecU32_new(),
.to_be_deleted = VecU32_new()};
}
@ -118,9 +126,7 @@ void LucyFaceFixedSize_get_rid_of_myself(LucyFaceFixedSize* self){
assert(img->usage > 0);
if (--img->usage) {
assert(!img->scheduled_for_deletion);
img->scheduled_for_deletion = true;
AliceAllSingleUploadTextures_delete(cache->single_upload_textures, img->tex);
img->tex = NULL;
img->scheduled_for_deletion = 1;
VecU32_append(&cache->to_be_deleted, slot_id);
}
}
@ -186,12 +192,12 @@ void LucyGlyphCache_add_glyphs__close_img(
assert(!img->scheduled_for_deletion);
img_width = MAX_U32(img_width, 10); // Just a precaution. empty buffers aren't supported by Margaret
img_height = MAX_U32(img_height, 10);
img->tex = AliceAllSingleUploadTextures_register_new(cache->single_upload_textures,
img_width, img_height, sizeof(U8), VK_FORMAT_R8_UNORM,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
cache->ve.staging_buffers, cache->ve.dev_local_images);
VecU32_append(&cache->to_be_written_to_descriptor_set, img_slot_id);
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,
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,
VK_FORMAT_R8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
}
void LucyGlyphCache_add_glyphs(VecLucyGlyphCachingRequest requests_for_faces){
@ -263,6 +269,7 @@ void LucyGlyphCache_add_glyphs(VecLucyGlyphCachingRequest requests_for_faces){
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;
@ -312,8 +319,8 @@ void LucyGlyphCache_add_glyphs(VecLucyGlyphCachingRequest requests_for_faces){
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->tex->img.width;
U8* staging = (U8*)AliceTextureUplOnce_get_mapped_staging(image->tex);
U64 staging_width = image->img.width;
U8* staging = (U8*)MargaretSubbuf_get_mapped(&image->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++) {
@ -332,18 +339,31 @@ 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_written_to_descriptor_set);
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);
}
void LucyGlyphCache_another_frame(LucyGlyphCache* self){
for (size_t i = 0; i < self->to_be_written_to_descriptor_set.len; i++) {
U32 slot_id = self->to_be_written_to_descriptor_set.buf[i];
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;
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;
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,
@ -351,7 +371,7 @@ void LucyGlyphCache_another_frame(LucyGlyphCache* self){
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.pImageInfo = &(VkDescriptorImageInfo){
.sampler = self->ve.nearest_sampler, .imageView = img->tex->view,
.sampler = self->ve.nearest_sampler, .imageView = img->img_view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
}
}, 0, NULL);
@ -359,16 +379,19 @@ void LucyGlyphCache_another_frame(LucyGlyphCache* self){
/* 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_deleted.buf[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;
assert(img->scheduled_for_deletion);
assert(img->usage == 0);
assert(img->tex == NULL);
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;
}
self->to_be_written_to_descriptor_set.len = 0;
self->to_be_freed_of_old_staging_next_cycle.len = 0;
self->to_be_copied_to_device_next_cycle.len = 0;
self->to_be_deleted.len = 0;
}

View File

@ -97,8 +97,8 @@ void LucyRenderer_draw_char_glyph(LucyRenderer* self, vec4 color, ivec2 pos, Luc
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->tex->img.width;
float atlas_h = (float)img->tex->img.height;
float atlas_w = (float)img->img.width;
float atlas_h = (float)img->img.height;
ivec2 positioned = ivec2_add_ivec2(pos, glyph->bearing);
U64 needed_vbo_length = (self->glyphs_count + 1) * sizeof(LucyRenderInstance);

View File

@ -1120,7 +1120,7 @@ VkPipeline margaret_create_triangle_pipeline_one_attachment(
.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
.colorBlendOp = VK_BLEND_OP_ADD,
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
.alphaBlendOp = VK_BLEND_OP_ADD,
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
@ -1246,35 +1246,3 @@ void margaret_rec_cmd_copy_buffer_to_image_one_to_one_color_aspect(
});
dst->current_layout = dst_new_layout;
}
U64 margaret_singleplane_format_to_sizeof_type(VkFormat type){
switch (type) {
case VK_FORMAT_R32G32B32A32_SFLOAT: return 16;
case VK_FORMAT_R32G32B32_SFLOAT: return 12;
case VK_FORMAT_R32G32_SFLOAT: return 8;
case VK_FORMAT_R32_SFLOAT: return 4;
case VK_FORMAT_R16_SFLOAT: return 2;
case VK_FORMAT_R16G16_SFLOAT: return 4;
case VK_FORMAT_R16G16B16_SFLOAT: return 6;
case VK_FORMAT_R16G16B16A16_SFLOAT: return 8;
case VK_FORMAT_R16_UNORM: return 2;
case VK_FORMAT_R16G16_UNORM: return 4;
case VK_FORMAT_R16G16B16_UNORM: return 6;
case VK_FORMAT_R16G16B16A16_UNORM: return 8;
case VK_FORMAT_R8G8B8A8_UNORM: return 4;
case VK_FORMAT_R8G8B8_UNORM: return 3;
case VK_FORMAT_R8G8_UNORM: return 2;
case VK_FORMAT_R8_UNORM: return 1;
case VK_FORMAT_R32_UINT: return 4;
case VK_FORMAT_R32G32_UINT: return 8;
case VK_FORMAT_R32G32B32_UINT: return 12;
case VK_FORMAT_R32G32B32A32_UINT: return 16;
case VK_FORMAT_R8G8B8A8_SRGB: return 4;
default:
abortf("Jokes on you\n");
}
}

View File

@ -96,8 +96,6 @@ typedef struct{
U64 misses_count;
U64 hits_count;
Vecvec3 bullets_stuck_on_ROA;
MargaretSubbuf sb;
} R4BetaState;
/* We are surrounded by a giant cubic mesh of light sources */

View File

@ -13,4 +13,5 @@ layout (binding=0) uniform sampler2D images[];
void main(){
float I = texture(images[nonuniformEXT(tex_ind)], tex_cord).r;
fin_color = vec4(color.rgb, color.a * I);
//fin_color = vec4(0, 0, 0, 1);
}

View File

@ -38,5 +38,4 @@ void main(){
vsout_tex_ind = tex_ind;
vec2 pos = all_v_pos[gl_VertexIndex % 6];
gl_Position = vec4(deng(width, pos.x), deng(height, pos.y), 0, 1);
}