Stashing progress... Don't take this commit seriously

This commit is contained in:
Андреев Григорий 2026-02-12 17:54:11 +03:00
parent 4f06ecb7ac
commit 71f73964cf
6 changed files with 343 additions and 199 deletions

View File

@ -10,6 +10,11 @@ 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,6 +3,7 @@
#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 {
@ -12,9 +13,6 @@ 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 */
@ -23,28 +21,21 @@ 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;
MargaretSubbuf staging_diffuse_tex_buf;
MargaretSubbuf staging_normal_tex_buf;
MargaretSubbuf staging_specular_tex_buf;
AliceBufferUplOnce* vbo;
AliceBufferUplOnce* ebo;
AliceTextureUplOnce* diffuse_texture;
AliceTextureUplOnce* normal_texture;
AliceTextureUplOnce* specular_texture;
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;
@ -55,11 +46,8 @@ typedef struct {
typedef struct {
size_t indexes;
MargaretSubbuf staging_vbo;
MargaretSubbuf staging_ebo;
MargaretSubbuf vbo;
MargaretSubbuf ebo;
AliceBufferUplOnce* vbo;
AliceBufferUplOnce* ebo;
PatriciaBuf instance_attr;
bool scheduled_for_deletion;
@ -736,17 +724,12 @@ 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(),
};
}
@ -757,16 +740,12 @@ 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(),
};
}
@ -806,6 +785,9 @@ 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;
@ -829,7 +811,8 @@ 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;
@ -838,11 +821,6 @@ 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));
@ -851,38 +829,36 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const Generic
VecU8_drop(t_paths.normal_texture_path);
VecU8_drop(t_paths.specular_texture_path);
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->vbo = AliceBufferUplOnce_new(topology->vertices.len * sizeof(GenericMeshVertex),
&alice->staging_buffers, &alice->dev_local_buffers);
mm->ebo = AliceBufferUplOnce_new(topology->indexes.len * sizeof(U32),
&alice->staging_buffers, &alice->dev_local_buffers);
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,
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,
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,
VK_FORMAT_R8_UNORM,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
mm->diffuse_texture = AliceTextureUplOnce_new(mm->pixels_diffuse.width, mm->pixels_diffuse.height,
VK_FORMAT_R8G8B8A8_SRGB, sizeof(cvec4),
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
&alice->staging_buffers, &alice->dev_local_images);
mm->normal_texture = AliceTextureUplOnce_new(mm->pixels_normal.width, mm->pixels_normal.height,
VK_FORMAT_R8G8B8A8_SRGB, sizeof(cvec4),
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
&alice->staging_buffers, &alice->dev_local_images);
mm->specular_texture = AliceTextureUplOnce_new(mm->pixels_specular.width, mm->pixels_specular.height,
VK_FORMAT_R8_SRGB, sizeof(U8),
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
&alice->staging_buffers, &alice->dev_local_images);
AliceAllSingleUploadBuffers_register(&alice->single_upload_buffers, mm->vbo);
AliceAllSingleUploadBuffers_register(&alice->single_upload_buffers, mm->ebo);
AliceAllSingleUploadTextures_register(&alice->single_upload_textures, mm->diffuse_texture);
AliceAllSingleUploadTextures_register(&alice->single_upload_textures, mm->normal_texture);
AliceAllSingleUploadTextures_register(&alice->single_upload_textures, mm->specular_texture);
mm->scheduled_for_deletion = false;
/* We allocated enough memory, but now it's time to actually fill staging buffers */
/* 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);
/* 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);
for (U64 i = 0; i < topology->vertices.len; i++) {
staging_vbo[i].base = topology->vertices.buf[i];
}
@ -912,53 +888,47 @@ 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.len >= ebo_len);
U32* staging_ebo = (U32*)MargaretSubbuf_get_mapped(&mm->staging_ebo);
assert(mm->ebo->staging.len >= ebo_len);
U32* staging_ebo = (U32*)AliceBufferUplOnce_get_mapped_staging(mm->ebo);
memcpy(staging_ebo, topology->indexes.buf, ebo_len);
/* Filling staging textures from memory pixel data */
/* todo: do it immediately ON THE READ */
memcpy(MargaretSubbuf_get_mapped(&mm->staging_diffuse_tex_buf), mm->pixels_diffuse.pixels.buf,
memcpy(AliceTextureUplOnce_get_mapped_staging(mm->diffuse_texture), mm->pixels_diffuse.pixels.buf,
TextureDataR8G8B8A8_get_size_in_bytes(&mm->pixels_diffuse));
memcpy(MargaretSubbuf_get_mapped(&mm->staging_normal_tex_buf), mm->pixels_normal.pixels.buf,
memcpy(AliceTextureUplOnce_get_mapped_staging(mm->normal_texture), mm->pixels_normal.pixels.buf,
TextureDataR8G8B8A8_get_size_in_bytes(&mm->pixels_normal));
memcpy(MargaretSubbuf_get_mapped(&mm->staging_specular_tex_buf), mm->pixels_specular.pixels.buf,
memcpy(AliceTextureUplOnce_get_mapped_staging(mm->specular_texture), 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 */
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;
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;
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 = P.diffuse_view,
.sampler = alice->linear_sampler, .imageView = mm->diffuse_texture->view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
};
VkDescriptorImageInfo image_info_for_descriptor_2_in_set_0a = {
.sampler = alice->nearest_sampler, .imageView = P.normal_view,
.sampler = alice->nearest_sampler, .imageView = mm->normal_texture->view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
};
VkDescriptorImageInfo image_info_for_descriptor_3_in_set_0a = {
.sampler = alice->nearest_sampler, .imageView = P.specular_view,
.sampler = alice->nearest_sampler, .imageView = mm->specular_texture->view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
};
VkWriteDescriptorSet writes_in_descriptor_set[] = {
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = P.p_0a_set_0,
.dstSet = P,
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
@ -967,7 +937,7 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const Generic
},
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = P.p_0a_set_0,
.dstSet = P,
.dstBinding = 1,
.dstArrayElement = 0,
.descriptorCount = 1,
@ -976,7 +946,7 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const Generic
},
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = P.p_0a_set_0,
.dstSet = P,
.dstBinding = 2,
.dstArrayElement = 0,
.descriptorCount = 1,
@ -985,7 +955,7 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const Generic
},
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = P.p_0a_set_0,
.dstSet = P,
.dstBinding = 3,
.dstArrayElement = 0,
.descriptorCount = 1,
@ -996,12 +966,10 @@ 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;
@ -1011,23 +979,20 @@ 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->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));
mm->vbo = AliceBufferUplOnce_new(topology->vertices.len * sizeof(ShinyMeshVertex),
&alice->staging_buffers, &alice->dev_local_buffers);
mm->ebo = AliceBufferUplOnce_new(topology->indexes.len * sizeof(U32),
&alice->staging_buffers, &alice->dev_local_buffers);
ListAliceShinyMeshHand_insert_node(&alice->shiny_models.hands, mm_node);
VecRefListNodeAliceShinyMeshHand_append(&alice->shiny_models.to_be_copied_to_device_next_cycle, mm_node);
AliceAllSingleUploadBuffers_register(&alice->single_upload_buffers, mm->vbo);
AliceAllSingleUploadBuffers_register(&alice->single_upload_buffers, mm->ebo);
/* We allocated enough memory, now it's time to actually fill staging buffers */
/* And we start by filling staging 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);
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);
for (U64 i = 0; i < topology->vertices.len; i++) {
staging_vbo[i].base = topology->vertices.buf[i];
}
@ -1042,21 +1007,41 @@ 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 */
/* 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.len >= ebo_len);
U32* staging_ebo = (U32*)MargaretSubbuf_get_mapped(&mm->staging_ebo);
assert(mm->ebo->staging.len >= ebo_len);
U32* staging_ebo = (U32*)AliceBufferUplOnce_get_mapped_staging(mm->ebo);
memcpy(staging_ebo, topology->indexes.buf, ebo_len);
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->staging_vbo.len, needed_length);
self->instance_attr.staging.len, needed_length);
MargaretBufAllocator_expand_or_move_old_host_visible(
&alice->staging_buffers, &self->instance_attr.staging, needed_length);
}
@ -1094,108 +1079,34 @@ 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_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);
}
void AliceAllMeshesGeneric__resolve_on_another_frame(Alice* alice, AliceAllMeshesGeneric* self){
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);
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);
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);
// 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_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);
}
void AliceAllMeshesShiny__resolve_on_another_frame(Alice* alice, AliceAllMeshesShiny* self){
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);
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);
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);
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;
}
@ -1206,8 +1117,8 @@ void AliceAllMeshesShiny__resolve_mesh_creation(Alice* alice, AliceAllMeshesShin
* 3) As mentioned before, Pipeline0UBO also gets copied
*/
void AliceScene__another_frame(Alice* alice) {
AliceAllMeshesGeneric__resolve_mesh_creation(alice, &alice->generic_models);
AliceAllMeshesShiny__resolve_mesh_creation(alice, &alice->shiny_models);
AliceAllMeshesGeneric__resolve_on_another_frame(alice, &alice->generic_models);
AliceAllMeshesShiny__resolve_on_another_frame(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;
@ -1291,9 +1202,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;
const MargaretSubbuf* dev_local_vbo = &model->vbo->device_buf;
const MargaretSubbuf* dev_local_inst_attr = &model->instance_attr.device_local;
const MargaretSubbuf* dev_local_ebo = &model->ebo;
const MargaretSubbuf* dev_local_ebo = &model->ebo->device_buf;
// const
vkCmdBindVertexBuffers(alice->rendering_command_buf_0, 0,
2, (VkBuffer[]){
@ -1319,9 +1230,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;
const MargaretSubbuf* dev_local_vbo = &model->vbo->device_buf;
const MargaretSubbuf* dev_local_inst_attr = &model->instance_attr.device_local;
const MargaretSubbuf* dev_local_ebo = &model->ebo;
const MargaretSubbuf* dev_local_ebo = &model->ebo->device_buf;
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 });
@ -1483,6 +1394,13 @@ 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);
@ -1961,8 +1879,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,
@ -1974,6 +1892,9 @@ 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));

View File

@ -0,0 +1,186 @@
#pragma once
#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);
}
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);
}
void AliceAllSingleUploadTextures_delete(AliceAllSingleUploadTextures* self, AliceTextureUplOnce* obj) {
assert(obj);
obj->scheduled_for_deletion = true;
VecRefAliceTextureUplOnce_append(&self->to_be_deleted, obj);
}

View File

@ -13,8 +13,6 @@
#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 */

View File

@ -1246,3 +1246,35 @@ 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,6 +96,8 @@ 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 */