diff --git a/src/l1/core/VecU8_as_str.h b/src/l1/core/VecU8_as_str.h index 9e89880..c7f9a1d 100644 --- a/src/l1/core/VecU8_as_str.h +++ b/src/l1/core/VecU8_as_str.h @@ -35,6 +35,12 @@ void SpanU8_fprint(SpanU8 str, FILE* stream) { putc((int)*SpanU8_at(str, i), stream); } +/* Not thread safe */ +void VecU8_print(VecU8 self){ + SpanU8_print(VecU8_to_span(&self)); + VecU8_drop(self); +} + NODISCARD VecU8 VecU8_format(const char *fmt, ...) { assert(fmt); diff --git a/src/l1_5/core/parsing_string.h b/src/l1_5/core/parsing_string.h index 568e9ef..d0eee90 100644 --- a/src/l1_5/core/parsing_string.h +++ b/src/l1_5/core/parsing_string.h @@ -83,7 +83,7 @@ int SpanU8_read_U64(SpanU8* rem_ret, U64* res_ret){ } /* Returns positive on error, 0 on success, rem_ret is untouched on error */ -int SpanU8_read_S64(SpanU8* rem_ret, S64* ret){ +int SpanU8_read_S64(SpanU8* rem_ret, S64* ret, bool allow_leading_zero){ SpanU8 rem = *rem_ret; U64 x = 0; bool saw_minus = false; @@ -92,7 +92,7 @@ int SpanU8_read_S64(SpanU8* rem_ret, S64* ret){ U8 ch = *rem.data; if ('0' <= ch && ch <= '9') { U64 d = (U64)(ch - '0'); - if (x == 0 && rem_ret->len - rem.len > (U64)saw_minus) { + if (!allow_leading_zero && x == 0 && rem_ret->len - rem.len > (U64)saw_minus) { return 1; } if (x > 9223372036854775808UL / 10) { @@ -193,7 +193,7 @@ int SpanU8_read_float(SpanU8* rem_ret, float* res_ret){ if (SpanU8_parsing_is_char_ahead(rem, '+')) SpanU8_parsing_skip_char(&rem); S64 exp; - int ret = SpanU8_read_S64(&rem, &exp); + int ret = SpanU8_read_S64(&rem, &exp, true); if (ret) return ret; if (res == 0.f) diff --git a/src/l2/alice/engine.h b/src/l2/alice/engine.h new file mode 100644 index 0000000..d28203d --- /dev/null +++ b/src/l2/alice/engine.h @@ -0,0 +1,2086 @@ +#ifndef prototype1_src_l2_alice_engine_h +#define prototype1_src_l2_alice_engine_h + +#include "model_file.h" +#include "../../l1/marie/geom_alg_utils.h" +#include "../margaret/vulkan_utils.h" +#include "../lucy/glyph_render.h" + +typedef struct { + U64 count; + MargaretSubbuf staging; + MargaretSubbuf device_local; +} 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 */ + VkDescriptorSet p_0a_set_0; +} AliceGenericMeshMemDependantVkObj; + +typedef struct { + size_t indexes; + // Option + MargaretSubbuf staging_vbo; + // Option + 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; + + 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; +} AliceGenericMeshHand; + +#include "../../../gen/l1/eve/alice/ListAliceGenericMeshHand.h" + +typedef struct { + size_t indexes; + + MargaretSubbuf staging_vbo; + MargaretSubbuf staging_ebo; + + MargaretSubbuf vbo; + MargaretSubbuf ebo; + PatriciaBuf instance_attr; + + bool scheduled_for_deletion; +} AliceShinyMeshHand; + +#include "../../../gen/l1/eve/alice/ListAliceShinyMeshHand.h" + +typedef struct { + float fov; + mat3 cam_basis; + vec3 pos; +} AliceCam; + +typedef struct{ + AliceCam cam; + float sensitivity; + float pitch_cap; +} AliceCamVerticalControl; + +AliceCamVerticalControl AliceCamVerticalControl_new() { + return (AliceCamVerticalControl){ + .cam.fov = 1.5f, .cam.cam_basis = marie_simple_camera_rot_m_basis_in_cols(0, 0, 0), .cam.pos = {0, 0, 0}, + .sensitivity = 0.5f * M_PIf / 180, .pitch_cap = M_PIf * 0.49f + }; +} + +void AliceCamVerticalControl_update_direction( + AliceCamVerticalControl* self, int win_width, int win_height, float pointer_x, float pointer_y) { + float yaw = ((float)win_width / 2 - pointer_x) * self->sensitivity; + float pitch = marie_clamp_float( + ((float)win_height / 2 - pointer_y) * self->sensitivity, + -self->pitch_cap, self->pitch_cap + ); + self->cam.cam_basis = marie_simple_camera_rot_m_basis_in_cols(yaw, pitch, 0); +} + +typedef struct { + MargaretSubbuf staging; + MargaretSubbuf device_local; +} AlicePipeline0UBO; + +typedef struct{ + vec4 clear_color; + float gamma_correction_factor; + float hdr_factor; + float lsd_factor; +} AliceRenderConfig; + +AliceRenderConfig AliceRenderConfig_new(){ + return (AliceRenderConfig){ + .clear_color = {0, 0.5f, 0.9f, 1}, + .gamma_correction_factor = 2.2f, .hdr_factor = 1, .lsd_factor = 0}; +} + +/* Here ends the old r0_scene.h file + * And begins old r0.c file */ + +#include +#include "../../../gen/l1/margaret/png_pixel_masses.h" +#include "../lucy/glyph_cache.h" +#include +//#include "../../l1/system/fileio.h" +#include +#include +#include "../../../gen/l_wl_protocols/xdg-shell-client.h" + + +VkRenderPass create_render_pass_0(VkDevice logical_device, VkFormat colorbuffer_format, VkFormat zbuffer_format) { + VkAttachmentDescription all_attachments[2] = { + { + .format = colorbuffer_format, + .samples = VK_SAMPLE_COUNT_1_BIT, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }, + { + .format = zbuffer_format, + .samples = VK_SAMPLE_COUNT_1_BIT, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, + .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + } + }; + + // For our one single render subpass + VkAttachmentReference color_attachments_refs[1] = { + { + .attachment = 0, + .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + } }; + + VkAttachmentReference depth_attachment_ref = { + .attachment = 1, + .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + }; + + VkSubpassDescription subpasses_descr[1] = { (VkSubpassDescription){ + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .colorAttachmentCount = ARRAY_SIZE(color_attachments_refs), + .pColorAttachments = color_attachments_refs, + .pDepthStencilAttachment = &depth_attachment_ref, + } }; + + VkSubpassDependency subpass_dependencies[1] = { + // subpass_0_external + (VkSubpassDependency) { + .srcSubpass = VK_SUBPASS_EXTERNAL, + .dstSubpass = 0, + .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + }}; + + VkRenderPassCreateInfo render_pass_crinfo = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + .attachmentCount = ARRAY_SIZE(all_attachments), + .pAttachments = all_attachments, + .subpassCount = ARRAY_SIZE(subpasses_descr), + .pSubpasses = subpasses_descr, + .dependencyCount = ARRAY_SIZE(subpass_dependencies), + .pDependencies = subpass_dependencies, + }; + VkRenderPass render_pass; + if (vkCreateRenderPass(logical_device, &render_pass_crinfo, NULL, &render_pass) != VK_SUCCESS) + abortf("vkCreateRenderPass"); + return render_pass; +} + +typedef struct { + VkPipelineLayout pipeline_layout; + VkPipeline pipeline; + VkDescriptorSetLayout descriptor_set_layout; +} AlicePipeline0a; + +void AlicePipeline0a_destroy(VkDevice device, AlicePipeline0a hands) { + vkDestroyPipeline(device, hands.pipeline, NULL); + vkDestroyPipelineLayout(device, hands.pipeline_layout, NULL); + vkDestroyDescriptorSetLayout(device, hands.descriptor_set_layout, NULL); +} + +AlicePipeline0a create_graphics_pipeline_0( + VkDevice device, SpanU8 root_dir, VkRenderPass render_pass, uint32_t subpass + ) { + VkDescriptorSetLayoutBinding bindings_for_my_descr_set_layout[] = { + { + .binding = 0, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + // our shader variable is not an array of descriptors, so this stays 1 + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + }, + { + .binding = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + }, + { + .binding = 2, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + }, + { + .binding = 3, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + }, + }; + VkDescriptorSetLayoutCreateInfo descriptor_set_layout_crinfo = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .bindingCount = ARRAY_SIZE(bindings_for_my_descr_set_layout), + .pBindings = bindings_for_my_descr_set_layout, + }; + VkDescriptorSetLayout my_descriptor_set_layout; + if (vkCreateDescriptorSetLayout(device, &descriptor_set_layout_crinfo, NULL, &my_descriptor_set_layout) != VK_SUCCESS) + abortf("vkCreateDescriptorSetLayout"); + + VkPushConstantRange pc_ranges[] = { + { + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, + .offset = 0, .size = sizeof(mat4) + }, + { + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + .offset = sizeof(mat4), .size = sizeof(vec3) + }, + + }; + + VkPipelineLayoutCreateInfo layout_crinfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = 1, + .pSetLayouts = &my_descriptor_set_layout, + .pushConstantRangeCount = ARRAY_SIZE(pc_ranges), + .pPushConstantRanges = pc_ranges, + }; + VkPipelineLayout pipeline_layout; + if (vkCreatePipelineLayout(device, &layout_crinfo, NULL, &pipeline_layout) != VK_SUCCESS) + abortf("vkCreatePipelineLayout"); + + + VecU8 vert_bin_code = read_file_by_path(VecU8_fmt("%s/gen/l_adele/alice/0gen/vert.spv", root_dir)); + VecU8 frag_bin_code = read_file_by_path(VecU8_fmt("%s/gen/l_adele/alice/0gen/frag.spv", root_dir)); + + VkVertexInputBindingDescription vertex_bindings[2] = { + { + .binding = 0, + .stride = sizeof(GenericMeshVertex), + .inputRate = VK_VERTEX_INPUT_RATE_VERTEX, + }, + { + .binding = 1, + .stride = sizeof(GenericMeshInstance), + .inputRate = VK_VERTEX_INPUT_RATE_INSTANCE, + } + }; + VkVertexInputAttributeDescription vertex_attributes[2 + 3 + 4 + 3] = { + { + .location = 0, .binding = 0, + .format = VK_FORMAT_R32G32B32_SFLOAT, + .offset = offsetof(GenericMeshVertexInc, pos), + }, + { + .location = 1, .binding = 0, + .format = VK_FORMAT_R32G32_SFLOAT, + .offset = offsetof(GenericMeshVertexInc, tex), + }, + { + .location = 2, .binding = 0, + .format = VK_FORMAT_R32G32B32_SFLOAT, + .offset = offsetof(GenericMeshVertex, norm), + }, + { + .location = 3, .binding = 0, + .format = VK_FORMAT_R32G32B32_SFLOAT, + .offset = offsetof(GenericMeshVertex, tang_U), + }, + { + .location = 4, .binding = 0, + .format = VK_FORMAT_R32G32B32_SFLOAT, + .offset = offsetof(GenericMeshVertex, tang_V), + }, + + /* This is a mat4 datatype, so it will take 4 entire 'locations' */ + { + .location = 5, .binding = 1, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = offsetof(GenericMeshInstanceInc, model_t) + offsetof(mat4, x) + }, + { + .location = 6, .binding = 1, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = offsetof(GenericMeshInstanceInc, model_t) + offsetof(mat4, y) + }, + { + .location = 7, .binding = 1, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = offsetof(GenericMeshInstanceInc, model_t) + offsetof(mat4, z) + }, + { + .location = 8, .binding = 1, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = offsetof(GenericMeshInstanceInc, model_t) + offsetof(mat4, w) + }, + { + .location = 9, .binding = 1, + .format = VK_FORMAT_R32G32B32_SFLOAT, + .offset = offsetof(GenericMeshInstance, normal_t) + offsetof(mat3, x) + }, + { + .location = 10, .binding = 1, + .format = VK_FORMAT_R32G32B32_SFLOAT, + .offset = offsetof(GenericMeshInstance, normal_t) + offsetof(mat3, y) + }, + { + .location = 11, .binding = 1, + .format = VK_FORMAT_R32G32B32_SFLOAT, + .offset = offsetof(GenericMeshInstance, normal_t) + offsetof(mat3, z) + }, + }; + + VkPipeline pipeline = margaret_create_triangle_pipeline_one_attachment(device, render_pass, subpass, + (MargaretMostImportantPipelineOptions){ + .pipeline_layout = pipeline_layout, + .vertex_shader_code = vert_bin_code, .fragment_shader_code = frag_bin_code, + .vertexBindingDescriptionCount = ARRAY_SIZE(vertex_bindings), vertex_bindings, + .vertexAttributeDescriptionCount = ARRAY_SIZE(vertex_attributes), vertex_attributes, + .depthTestEnable = true, .depthWriteEnable = true, .blendEnable = false + }); + return (AlicePipeline0a){.pipeline_layout = pipeline_layout, .pipeline = pipeline, .descriptor_set_layout = my_descriptor_set_layout}; +} + +typedef struct { + VkPipelineLayout pipeline_layout; + VkPipeline pipeline; + VkDescriptorSetLayout descriptor_set_layout; +} AlicePipeline0b; + +void AlicePipeline0b_destroy(VkDevice device, AlicePipeline0b hands) { + vkDestroyPipeline(device, hands.pipeline, NULL); + vkDestroyPipelineLayout(device, hands.pipeline_layout, NULL); + vkDestroyDescriptorSetLayout(device, hands.descriptor_set_layout, NULL); +} + +AlicePipeline0b create_graphics_pipeline_0_b( + VkDevice device, SpanU8 root_dir, VkRenderPass render_pass, uint32_t subpass + ) { + VkDescriptorSetLayout my_descriptor_set_layout; + check(vkCreateDescriptorSetLayout(device, &(VkDescriptorSetLayoutCreateInfo){ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .bindingCount = 1, + .pBindings = (VkDescriptorSetLayoutBinding[]){{ + .binding = 0, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + }}, + }, NULL, &my_descriptor_set_layout) == VK_SUCCESS); + + VkPushConstantRange pc_ranges[] = { + { + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, + .offset = 0, .size = sizeof(mat4) + }, + { + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + .offset = sizeof(mat4), .size = sizeof(vec3) + }}; + + VkPipelineLayout pipeline_layout; + check(vkCreatePipelineLayout(device, &(VkPipelineLayoutCreateInfo){ + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = 1, + .pSetLayouts = (VkDescriptorSetLayout[]){my_descriptor_set_layout}, + .pushConstantRangeCount = ARRAY_SIZE(pc_ranges), + .pPushConstantRanges = pc_ranges, + }, NULL, &pipeline_layout) == VK_SUCCESS); + + + VecU8 vert_bin_code = read_file_by_path(VecU8_fmt("%s/gen/l_adele/alice/0sh/vert.spv", root_dir)); + VecU8 frag_bin_code = read_file_by_path(VecU8_fmt("%s/gen/l_adele/alice/0sh/frag.spv", root_dir)); + + VkVertexInputBindingDescription vertex_bindings[2] = { + { + .binding = 0, + .stride = sizeof(ShinyMeshVertex), + .inputRate = VK_VERTEX_INPUT_RATE_VERTEX, + }, + { + .binding = 1, + .stride = sizeof(ShinyMeshInstance), + .inputRate = VK_VERTEX_INPUT_RATE_INSTANCE, + } + }; + VkVertexInputAttributeDescription vertex_attributes[2 + 4 + 2 + 3] = { + { + .location = 0, .binding = 0, + .format = VK_FORMAT_R32G32B32_SFLOAT, + .offset = offsetof(ShinyMeshVertexInc, pos), + }, + { + .location = 1, .binding = 0, + .format = VK_FORMAT_R32G32B32_SFLOAT, + .offset = offsetof(ShinyMeshVertexInc, color), + }, + { + .location = 2, .binding = 0, + .format = VK_FORMAT_R32G32B32_SFLOAT, + .offset = offsetof(ShinyMeshVertex, normal), + }, + + /* This is a mat4 datatype, so it will take 4 entire 'locations' */ + { + .location = 3, .binding = 1, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = offsetof(ShinyMeshInstanceInc, model_t) + offsetof(mat4, x) + }, + { + .location = 4, .binding = 1, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = offsetof(ShinyMeshInstanceInc, model_t) + offsetof(mat4, y) + }, + { + .location = 5, .binding = 1, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = offsetof(ShinyMeshInstanceInc, model_t) + offsetof(mat4, z) + }, + { + .location = 6, .binding = 1, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = offsetof(ShinyMeshInstanceInc, model_t) + offsetof(mat4, w) + }, + { + .location = 7, .binding = 1, + .format = VK_FORMAT_R32G32B32_SFLOAT, + .offset = offsetof(ShinyMeshInstanceInc, color_on) + }, + { + .location = 8, .binding = 1, + .format = VK_FORMAT_R32G32B32_SFLOAT, + .offset = offsetof(ShinyMeshInstance, normal_t) + offsetof(mat3, x) + }, + { + .location = 9, .binding = 1, + .format = VK_FORMAT_R32G32B32_SFLOAT, + .offset = offsetof(ShinyMeshInstance, normal_t) + offsetof(mat3, y) + }, + { + .location = 10, .binding = 1, + .format = VK_FORMAT_R32G32B32_SFLOAT, + .offset = offsetof(ShinyMeshInstance, normal_t) + offsetof(mat3, z) + }, + }; + + VkPipeline pipeline = margaret_create_triangle_pipeline_one_attachment(device, render_pass, subpass, + (MargaretMostImportantPipelineOptions){ + .pipeline_layout = pipeline_layout, + .vertex_shader_code = vert_bin_code, .fragment_shader_code = frag_bin_code, + .vertexBindingDescriptionCount = ARRAY_SIZE(vertex_bindings), vertex_bindings, + .vertexAttributeDescriptionCount = ARRAY_SIZE(vertex_attributes), vertex_attributes, + .depthTestEnable = true, .depthWriteEnable = true, .blendEnable = false + }); + + return (AlicePipeline0b){.pipeline_layout = pipeline_layout, .pipeline = pipeline, .descriptor_set_layout = my_descriptor_set_layout}; +} + +VkRenderPass create_render_pass_1(VkDevice logical_device, VkFormat image_format) { + // Color attachments array for our render pass + VkAttachmentDescription all_attachments[1] = { (VkAttachmentDescription){ + .format = image_format, + .samples = VK_SAMPLE_COUNT_1_BIT, + .loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + } }; + + // For our one single render subpass + VkAttachmentReference color_attachment_refs[1] = { (VkAttachmentReference){ + .attachment = 0, + .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + } }; + + VkSubpassDescription subpasses_descr[1] = { (VkSubpassDescription){ + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .colorAttachmentCount = ARRAY_SIZE(color_attachment_refs), + .pColorAttachments = color_attachment_refs, + } }; + + VkSubpassDependency subpass_dependencies[1] = { + // subpass_0_external + (VkSubpassDependency) { + .srcSubpass = VK_SUBPASS_EXTERNAL, + .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .srcAccessMask = 0, + .dstSubpass = 0, + .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + }}; + + VkRenderPassCreateInfo render_pass_crinfo = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + .attachmentCount = ARRAY_SIZE(all_attachments), + .pAttachments = all_attachments, + .subpassCount = ARRAY_SIZE(subpasses_descr), + .pSubpasses = subpasses_descr, + .dependencyCount = ARRAY_SIZE(subpass_dependencies), + .pDependencies = subpass_dependencies, + }; + VkRenderPass render_pass; + if (vkCreateRenderPass(logical_device, &render_pass_crinfo, NULL, &render_pass) != VK_SUCCESS) + abortf("vkCreateRenderPass"); + return render_pass; +} + +typedef struct { + VkPipelineLayout pipeline_layout; + VkPipeline pipeline; + VkDescriptorSetLayout descriptor_set_layout; +} AlicePipeline1; + +void AlicePipeline1_destroy(VkDevice device, AlicePipeline1 hands) { + vkDestroyPipeline(device, hands.pipeline, NULL); + vkDestroyPipelineLayout(device, hands.pipeline_layout, NULL); + vkDestroyDescriptorSetLayout(device, hands.descriptor_set_layout, NULL); +} + +AlicePipeline1 create_graphics_pipeline_1( + VkDevice device, SpanU8 root_dir, VkRenderPass render_pass, uint32_t subpass + ) { + + VkDescriptorSetLayoutBinding bindings_for_my_descr_set_layout[] = { + { + .binding = 0, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + }, + }; + VkDescriptorSetLayout my_descriptor_set_layout; + check(vkCreateDescriptorSetLayout(device, &(VkDescriptorSetLayoutCreateInfo){ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .bindingCount = ARRAY_SIZE(bindings_for_my_descr_set_layout), + .pBindings = bindings_for_my_descr_set_layout, + }, NULL, &my_descriptor_set_layout) == VK_SUCCESS); + + VkPushConstantRange used_region_sz_push_const[2] = { + { .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, + .offset = 0, .size = sizeof(Pipeline1PushRangeVertex) }, + { .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + .offset = sizeof(Pipeline1PushRangeVertex), .size = sizeof(Pipeline1PushRangeFragment) }, + }; + + VkPipelineLayout pipeline_layout; + check(vkCreatePipelineLayout(device, &(VkPipelineLayoutCreateInfo){ + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = 1, + .pSetLayouts = &my_descriptor_set_layout, + .pushConstantRangeCount = ARRAY_SIZE(used_region_sz_push_const), + .pPushConstantRanges = used_region_sz_push_const, + }, NULL, &pipeline_layout) == VK_SUCCESS); + + + VecU8 vert_bin_code = read_file_by_path(VecU8_fmt("%s/gen/l_adele/alice/1/vert.spv", root_dir)); + VecU8 frag_bin_code = read_file_by_path(VecU8_fmt("%s/gen/l_adele/alice/1/frag.spv", root_dir)); + + VkPipeline pipeline = margaret_create_triangle_pipeline_one_attachment(device, render_pass, subpass, + (MargaretMostImportantPipelineOptions){ + .pipeline_layout = pipeline_layout, + .vertex_shader_code = vert_bin_code, .fragment_shader_code = frag_bin_code, + .vertexBindingDescriptionCount = 0, .pVertexBindingDescriptions = NULL, + .vertexAttributeDescriptionCount = 0, .pVertexAttributeDescriptions = NULL, + }); + return (AlicePipeline1){.pipeline_layout = pipeline_layout, .pipeline = pipeline, .descriptor_set_layout = my_descriptor_set_layout}; +} + +VkFramebuffer create_IT1_framebuffer(VkDevice device, VkImageView IT1_view, VkImageView zbuffer_view, VkRenderPass render_pass_0, + U32 MAX_WIN_WIDTH, U32 MAX_WIN_HEIGHT) { + VkImageView attachments[2] = {IT1_view, zbuffer_view}; + VkFramebufferCreateInfo framebuffer_crinfo = { + .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + .renderPass = render_pass_0, + .attachmentCount = ARRAY_SIZE(attachments), + .pAttachments = attachments, + .width = MAX_WIN_WIDTH, + .height = MAX_WIN_HEIGHT, + .layers = 1 + }; + VkFramebuffer framebuffer; + if (vkCreateFramebuffer(device, &framebuffer_crinfo, NULL, &framebuffer) != VK_SUCCESS) + abortf("vkCreateFramebuffer"); + return framebuffer; +} + +void record_cmd_set_viewport_and_scissors(VkCommandBuffer command_buffer, VkExtent2D image_extent) { + vkCmdSetViewport(command_buffer, 0, 1, &(VkViewport){ + .x = 0.0f, .y = 0.0f, + .width = (float)(image_extent.width), .height = (float)(image_extent.height), + .minDepth = 0.0f, .maxDepth = 1.0f, + }); + vkCmdSetScissor(command_buffer, 0, 1, &(VkRect2D){ .offset = (VkOffset2D){0, 0}, .extent = image_extent}); +} + +typedef struct { + VkSemaphore in_frame_transfer_complete; + VkSemaphore image_available_semaphore; + VkSemaphore rendered_to_IT1_semaphore; + VkFence in_flight_fence; + // For miscellaneous uses (for init) + VkFence roxy; +} Jane_alice; + +NODISCARD Jane_alice Jane_alice_create(VkDevice device) { + return (Jane_alice){ + .in_frame_transfer_complete = margaret_create_semaphore(device), + .image_available_semaphore = margaret_create_semaphore(device), + .rendered_to_IT1_semaphore = margaret_create_semaphore(device), + .in_flight_fence = margaret_create_fence(device, true), + .roxy = margaret_create_fence(device, false), + }; +} + +void Jane_alice_destroy(VkDevice device, Jane_alice jane) { + vkDestroySemaphore(device, jane.rendered_to_IT1_semaphore, NULL); + vkDestroySemaphore(device, jane.image_available_semaphore, NULL); + vkDestroySemaphore(device, jane.in_frame_transfer_complete, NULL); + vkDestroyFence(device, jane.in_flight_fence, NULL); + vkDestroyFence(device, jane.roxy, NULL); +} + +typedef struct { + VkQueue graphics_queue; + VkQueue presentation_queue; +} UsedVulkanQueues; + + +void alice_default_callback_on_wl_keyboard_key(void* d, U32 keysym, U32 key_action){} + +void alice_default_callback_on_another_frame(void* d, float fl){} + +typedef struct Alice Alice; + +typedef struct{ + /* guest data, keysym, key action (wl_keyboard_key_state) */ + void (*on_wl_keyboard_key)(void*, U32, U32); + void (*on_another_frame)(void*, float); +} AliceCallbacks; + +void AliceCallbacks_set_default(AliceCallbacks* self){ + self->on_another_frame = alice_default_callback_on_another_frame; + self->on_wl_keyboard_key = alice_default_callback_on_wl_keyboard_key; +} + +typedef struct { + /* Memory settings */ + VkExtent2D sane_image_extent_limit; + /* Globals */ + struct wl_display *wl_display; + struct wl_registry *wl_registry; + struct wl_compositor *wl_compositor; + struct xdg_wm_base *xdg_wm_base; + struct wl_seat *wl_seat; + /* Objects */ + struct wl_surface *wl_surface; + struct wl_callback* wl_callback; + struct xdg_surface *xdg_surface; + struct xdg_toplevel *xdg_toplevel; + /* inputs */ + struct wl_pointer* pointer; + struct wl_keyboard* keyboard; + /* xkb */ + struct xkb_state* xkb_state; + struct xkb_context* xkb_context; + struct xkb_keymap* xkb_keymap; + /* app state */ + uint32_t last_frame_time; + uint32_t cur_frame_time; + int32_t width_heard; + int32_t height_heard; + int32_t width_confirmed; + int32_t height_confirmed; + bool closed; + bool first_0x80_keys[0x80]; + /* framerate counting */ + U32 frame_count_since_key; + margaret_ns_time prev_key_frame_time; +} AliceWaylandApp; + +float AliceWaylandApp_get_elapsed_time(const AliceWaylandApp* self){ + return (float)(self->cur_frame_time - self->last_frame_time) / 1000; +} + +/* They are actually MutRef, but who cares lol, we won't have such distinction here anytime soon, so we shorten + * it to Ref (whil keeping in kind that it is actually MutRef) + */ +typedef struct ListNodeAliceGenericMeshHand* RefListNodeAliceGenericMeshHand; +#include "../../../gen/l1/eve/alice/VecRefListNodeAliceGenericMeshHand.h" + +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(), + }; +} + +typedef struct ListNodeAliceShinyMeshHand* RefListNodeAliceShinyMeshHand; +#include "../../../gen/l1/eve/alice/VecRefListNodeAliceShinyMeshHand.h" + +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(), + }; +} + + +struct Alice { + AliceCallbacks callbacks; + void* guest; + AliceWaylandApp wl; + + MargaretInstanceAndItsDebug instance_and_debug; + VkSurfaceKHR surface; + VkPhysicalDevice physical_device; + MargaretChosenQueueFamilies queue_fam; + VkDevice device; + UsedVulkanQueues queues; + VkFormat zbuffer_format; + VkFormat IT1_format; + VkRenderPass render_pass_0; + AlicePipeline0a pipeline_hands_0a; + AlicePipeline0b pipeline_hands_0b; + VkRenderPass render_pass_1; + AlicePipeline1 pipeline_hands_1; + VkSampler linear_sampler; + VkSampler nearest_sampler; + VkCommandPool command_pool; + VkCommandBuffer rendering_command_buf_0; + VkCommandBuffer rendering_command_buf_1; + VkCommandBuffer transfer_command_buf; + VkCommandBuffer device_local_mem_mv_command_buf; + VkDescriptorPool descriptor_pool; // todo: write dynamic allocator wrapper for descriptor pools + + MargaretImgAllocator dev_local_images; + MargaretBufAllocator dev_local_buffers; + MargaretBufAllocator staging_buffers; + + Jane_alice jane; // todo: figure out my own design + MargaretSwapchainBundle swfb; + + AlicePipeline0UBO pipeline0_ubo; + AliceAllMeshesGeneric generic_models; + AliceAllMeshesShiny shiny_models; + AliceCamVerticalControl cam_info; + /* stuff like background color, hdr factor and + * postprocessing kernel. Mostly related to renderpass 1 */ + AliceRenderConfig rendering_config; + + MargaretImg IT1_image; + MargaretImg zbuffer_image; + + FT_Library ft_library; + LucyGlyphCache lucy_cache; + LucyRenderer lucy_renderer; + + VkImageView zbuffer_view; + VkImageView IT1_view; + VkFramebuffer IT1_framebuffer; + VkDescriptorSet descriptor_set_for_pipeline_0b; + VkDescriptorSet descriptor_set_for_pipeline_1; +}; + +ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, AliceGenericMeshPath paths){ + GenericMeshTopology topology; + if (SpanU8_is_postfix(cstr(".AliceGenericMesh"), VecU8_to_span(&paths.topology_path) )) { + topology = alice_expect_read_generic_mesh_from_file(paths.topology_path); + } else if (SpanU8_is_postfix(cstr(".obj"), VecU8_to_span(&paths.topology_path) )) { + topology = alice_expect_read_generic_mesh_from_obj_file(paths.topology_path); + } else { + abortf("Иди своей дорогой\n"); + } + + ListNodeAliceGenericMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceGenericMeshHand)); + AliceGenericMeshHand* mm = &mm_node->el; + mm->indexes = topology.indexes.len; + mm->instance_attr.count = 0; + 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(&paths.diffuse_texture_path)); + mm->pixels_normal = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&paths.normal_texture_path)); + mm->pixels_specular = TextureDataR8_read_from_png_nofail(VecU8_to_span(&paths.specular_texture_path)); + VecU8_drop(paths.diffuse_texture_path); + VecU8_drop(paths.normal_texture_path); + VecU8_drop(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 = 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->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); + for (U64 i = 0; i < topology.vertices.len; i++) { + staging_vbo[i].base = topology.vertices.buf[i]; + } + assert(topology.indexes.len % 3 == 0); + for (size_t ti = 0; ti * 3 < topology.indexes.len; ti++) { + U32 v0 = topology.indexes.buf[ti * 3 + 0]; + U32 v1 = topology.indexes.buf[ti * 3 + 1]; + U32 v2 = topology.indexes.buf[ti * 3 + 2]; + const GenericMeshVertexInc* A0 = VecGenericMeshVertexInc_at(&topology.vertices, v0); + const GenericMeshVertexInc* A1 = VecGenericMeshVertexInc_at(&topology.vertices, v1); + const GenericMeshVertexInc* A2 = VecGenericMeshVertexInc_at(&topology.vertices, v2); + vec3 dp1 = vec3_minus_vec3(A1->pos, A0->pos); + vec3 dp2 = vec3_minus_vec3(A2->pos, A0->pos); + float du1 = A1->tex.x - A0->tex.x; + float dv1 = A1->tex.y - A0->tex.y; + float du2 = A2->tex.x - A0->tex.x; + float dv2 = A2->tex.y - A0->tex.y; + vec3 norm = vec3_normalize(vec3_cross(dp1, dp2)); + mat2x3 tang_U_V = mat3x2_transpose(mat2_mul_mat3x2( + mat2_inverse(mat2_new(du1, dv1, du2, dv2)), + mat2x3_transpose((mat2x3){.x = dp1, .y = dp2}) + )); + staging_vbo[v0].norm = staging_vbo[v1].norm = staging_vbo[v2].norm = norm; + staging_vbo[v0].tang_U = staging_vbo[v1].tang_U = staging_vbo[v2].tang_U = tang_U_V.x; + staging_vbo[v0].tang_V = staging_vbo[v1].tang_V = staging_vbo[v2].tang_V = tang_U_V.y; + } + /* 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); + 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, + TextureDataR8G8B8A8_get_size_in_bytes(&mm->pixels_diffuse)); + memcpy(MargaretSubbuf_get_mapped(&mm->staging_normal_tex_buf), 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, + 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; + + 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, + .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, + .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, + .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, + .dstBinding = 0, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .pBufferInfo = &buffer_info_for_descriptor_0_in_set_0a, + }, + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = P.p_0a_set_0, + .dstBinding = 1, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = &image_info_for_descriptor_1_in_set_0a, + }, + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = P.p_0a_set_0, + .dstBinding = 2, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = &image_info_for_descriptor_2_in_set_0a, + }, + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = P.p_0a_set_0, + .dstBinding = 3, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = &image_info_for_descriptor_3_in_set_0a, + }, + }; + 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, VecU8 path){ + ShinyMeshTopology topology = alice_expect_read_shiny_mesh_from_file(path); + + ListNodeAliceShinyMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceShinyMeshHand)); + AliceShinyMeshHand* mm = &mm_node->el; + + mm->indexes = topology.indexes.len; + + mm->instance_attr.count = 0; + 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)); + + 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->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]; + } + assert(topology.indexes.len % 3 == 0); + for (size_t ti = 0; ti * 3 < topology.indexes.len; ti++) { + U32 v0 = topology.indexes.buf[ti * 3 + 0]; + U32 v1 = topology.indexes.buf[ti * 3 + 1]; + U32 v2 = topology.indexes.buf[ti * 3 + 2]; + vec3 p0 = VecShinyMeshVertexInc_at(&topology.vertices, v0)->pos; + vec3 p1 = VecShinyMeshVertexInc_at(&topology.vertices, v1)->pos; + vec3 p2 = VecShinyMeshVertexInc_at(&topology.vertices, v2)->pos; + 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.len >= ebo_len); + U32* staging_ebo = (U32*)MargaretSubbuf_get_mapped(&mm->staging_ebo); + memcpy(staging_ebo, topology.indexes.buf, ebo_len); + return mm_node; +} + +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); + MargaretBufAllocator_expand_or_move_old_host_visible( + &alice->staging_buffers, &self->instance_attr.staging, needed_length); + } + self->instance_attr.count = new_count; +} + +void AliceShinyMeshHand_resize_instance_arr(Alice* alice, AliceShinyMeshHand* self, U64 new_count){ + U64 needed_length = new_count * sizeof(ShinyMeshInstance); + if (self->instance_attr.staging.len < needed_length) { + MargaretBufAllocator_expand_or_move_old_host_visible( + &alice->staging_buffers, &self->instance_attr.staging, needed_length); + } + self->instance_attr.count = new_count; +} + +void AliceGenericMeshHand_set_inst(AliceGenericMeshHand* self, size_t instance, GenericMeshInstanceInc uncomp){ + assert(instance < self->instance_attr.count); + GenericMeshInstance* staging = (GenericMeshInstance*)MargaretSubbuf_get_mapped(&self->instance_attr.staging); + staging[instance].base = uncomp; + mat4 tr_inv = mat4_transpose(mat4_inverse(uncomp.model_t)); + staging[instance].normal_t = mat3_new( + tr_inv.x.x, tr_inv.y.x, tr_inv.z.x, + tr_inv.x.y, tr_inv.y.y, tr_inv.z.y, + tr_inv.x.z, tr_inv.y.z, tr_inv.z.z ); +} + +void AliceShinyMeshHand_set_inst(AliceShinyMeshHand* self, size_t instance, ShinyMeshInstanceInc uncomp){ + assert(instance < self->instance_attr.count); + ShinyMeshInstance* staging = (ShinyMeshInstance*)MargaretSubbuf_get_mapped(&self->instance_attr.staging); + staging[instance].base = uncomp; + mat4 tr_inv = mat4_transpose(mat4_inverse(uncomp.model_t)); + staging[instance].normal_t = mat3_new( + tr_inv.x.x, tr_inv.y.x, tr_inv.z.x, + tr_inv.x.y, tr_inv.y.y, tr_inv.z.y, + 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); + } + 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); + + // 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); + } + 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); + + 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; +} + +/* No buffer rerecording, no buffer beginning, no buffer ending, + * 1) It copies initial generic model and shiny model topology. Textures of generic models included + * 2) For all models and for all light sources it copies EVERYTHING. + * You won't normally need to copy every single thing, but here you have the most bold solution. + * 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); + + for (ListNodeAliceGenericMeshHand* mm_node = alice->generic_models.hands.first; mm_node; mm_node = mm_node->next) { + AliceGenericMeshHand* mm = &mm_node->el; + assert(mm->instance_attr.count * sizeof(GenericMeshInstance) <= mm->instance_attr.staging.len); + if (mm->instance_attr.count * sizeof(GenericMeshInstance) > mm->instance_attr.device_local.len) { + MargaretBufAllocator_expand_or_free_old(&alice->dev_local_buffers, &mm->instance_attr.device_local, + mm->instance_attr.count * sizeof(GenericMeshInstance)); + } + assert(mm->instance_attr.count * sizeof(GenericMeshInstance) <= mm->instance_attr.device_local.len); + if (mm->instance_attr.count) { + margaret_rec_cmd_copy_buffer_one_to_one_part(alice->transfer_command_buf, + &mm->instance_attr.staging, &mm->instance_attr.device_local, 0, + mm->instance_attr.count * sizeof(GenericMeshInstance)); + } + } + for (ListNodeAliceShinyMeshHand* mm_node = alice->shiny_models.hands.first; mm_node; mm_node = mm_node->next) { + AliceShinyMeshHand* mm = &mm_node->el; + assert(mm->instance_attr.count * sizeof(ShinyMeshInstance) <= mm->instance_attr.staging.len); + if (mm->instance_attr.count * sizeof(ShinyMeshInstance) > mm->instance_attr.device_local.len) { + MargaretBufAllocator_expand_or_free_old(&alice->dev_local_buffers, &mm->instance_attr.device_local, + mm->instance_attr.count * sizeof(ShinyMeshInstance)); + } + assert(mm->instance_attr.count * sizeof(ShinyMeshInstance) <= mm->instance_attr.device_local.len); + if (mm->instance_attr.count) { + margaret_rec_cmd_copy_buffer_one_to_one_part(alice->transfer_command_buf, + &mm->instance_attr.staging, &mm->instance_attr.device_local, 0, + mm->instance_attr.count * sizeof(ShinyMeshInstance)); + } + } + Pipeline0UBO* mem = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_ubo.staging); + assert(mem->point_light_count <= pipeline_0_ubo_point_light_max_count); + assert(mem->spotlight_count <= pipeline_0_ubo_spotlight_max_count); + + // todo: I will probably replace pipeline0ubo with ubo for length + two readonly storage buffers for light sources + // all of this is basically useless + + const MargaretSubbuf* ubo_staging = &alice->pipeline0_ubo.staging; + const MargaretSubbuf* ubo_device_local = &alice->pipeline0_ubo.device_local; + + margaret_rec_cmd_copy_buffer_one_to_one_part(alice->transfer_command_buf, ubo_staging, ubo_device_local, + offsetof(Pipeline0UBO, point_light_count), sizeof(int)); + margaret_rec_cmd_copy_buffer_one_to_one_part(alice->transfer_command_buf, ubo_staging, ubo_device_local, + offsetof(Pipeline0UBO, spotlight_count), sizeof(int)); + if (mem->point_light_count) { + margaret_rec_cmd_copy_buffer_one_to_one_part(alice->transfer_command_buf, ubo_staging, ubo_device_local, + offsetof(Pipeline0UBO, point_light_arr), sizeof(Pipeline0PointLight) * mem->point_light_count); + } + if (mem->spotlight_count) { + margaret_rec_cmd_copy_buffer_one_to_one_part(alice->transfer_command_buf, ubo_staging, ubo_device_local, + offsetof(Pipeline0UBO, spotlight_arr), sizeof(Pipeline0Spotlight) * mem->spotlight_count); + } +} + + +void alice_reset_and_record_command_buffer_0(Alice* alice, mat4 proj_cam_t) { + margaret_reset_and_begin_command_buffer(alice->rendering_command_buf_0); + + vec4 clear_color = alice->rendering_config.clear_color; + VkExtent2D image_extent = alice->swfb.extent; + vkCmdBeginRenderPass(alice->rendering_command_buf_0, &(VkRenderPassBeginInfo){ + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderPass = alice->render_pass_0, + .framebuffer = alice->IT1_framebuffer, + .renderArea.offset = (VkOffset2D){0, 0}, + .renderArea.extent = image_extent, + .clearValueCount = 2, + .pClearValues = (VkClearValue[]){ + {.color.float32 = {clear_color.x, clear_color.y, clear_color.z, clear_color.w}}, + {.depthStencil = {.depth = 1, .stencil = 0}} + }, + }, VK_SUBPASS_CONTENTS_INLINE); + + vkCmdBindPipeline(alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0a.pipeline); + record_cmd_set_viewport_and_scissors(alice->rendering_command_buf_0, image_extent); + vkCmdPushConstants(alice->rendering_command_buf_0, alice->pipeline_hands_0a.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, + 0, sizeof(mat4), &proj_cam_t); + vkCmdPushConstants(alice->rendering_command_buf_0, alice->pipeline_hands_0a.pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, + sizeof(mat4), sizeof(vec3), &alice->cam_info.cam.pos); + + for (ListNodeAliceGenericMeshHand* mm_node = alice->generic_models.hands.first; mm_node; mm_node = mm_node->next) { + 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_inst_attr = &model->instance_attr.device_local; + const MargaretSubbuf* dev_local_ebo = &model->ebo; + // const + 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 }); + vkCmdBindIndexBuffer(alice->rendering_command_buf_0, MargaretSubbuf_get_buffer(dev_local_ebo), dev_local_ebo->start, + VK_INDEX_TYPE_UINT32); + vkCmdBindDescriptorSets( + alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0a.pipeline_layout, 0, + 1, &model_indiv_descriptor_set_0, 0, NULL); + vkCmdDrawIndexed(alice->rendering_command_buf_0, model->indexes, model->instance_attr.count, 0, 0, 0); + } + + vkCmdBindPipeline(alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0b.pipeline); + record_cmd_set_viewport_and_scissors(alice->rendering_command_buf_0, image_extent); + vkCmdPushConstants(alice->rendering_command_buf_0, alice->pipeline_hands_0b.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, + 0, sizeof(mat4), &proj_cam_t); + vkCmdPushConstants(alice->rendering_command_buf_0, alice->pipeline_hands_0b.pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, + sizeof(mat4), sizeof(vec3), &alice->cam_info.cam.pos); + vkCmdBindDescriptorSets( + alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0b.pipeline_layout, 0, + 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_inst_attr = &model->instance_attr.device_local; + 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 }); + vkCmdBindIndexBuffer(alice->rendering_command_buf_0, MargaretSubbuf_get_buffer(dev_local_ebo), dev_local_ebo->start, + VK_INDEX_TYPE_UINT32); + vkCmdDrawIndexed(alice->rendering_command_buf_0, model->indexes, model->instance_attr.count, 0, 0, 0); + } + + vkCmdEndRenderPass(alice->rendering_command_buf_0); + margaret_end_command_buffer(alice->rendering_command_buf_0); +} + +void alice_reset_and_record_command_buffer_1( + Alice* alice, VkFramebuffer swapchain_image_framebuffer + ) { + margaret_reset_and_begin_command_buffer(alice->rendering_command_buf_1); + + VkExtent2D image_extent = alice->swfb.extent; + vkCmdBeginRenderPass(alice->rendering_command_buf_1, &(VkRenderPassBeginInfo){ + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderPass = alice->render_pass_1, + .framebuffer = swapchain_image_framebuffer, + .renderArea.offset = (VkOffset2D){0, 0}, + .renderArea.extent = image_extent, + }, VK_SUBPASS_CONTENTS_INLINE); + vkCmdBindPipeline(alice->rendering_command_buf_1, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_1.pipeline); + + record_cmd_set_viewport_and_scissors(alice->rendering_command_buf_1, image_extent); + vkCmdBindDescriptorSets( + alice->rendering_command_buf_1, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_1.pipeline_layout, 0, + 1, &alice->descriptor_set_for_pipeline_1, 0, NULL); + + Pipeline1PushRangeVertex reg_and_params_vertex = {.win_scale = { + (float)image_extent.width / (float)alice->wl.sane_image_extent_limit.width, + (float)image_extent.height / (float)alice->wl.sane_image_extent_limit.height}, + }; + Pipeline1PushRangeFragment reg_and_params_fragment = { + .gamma_correction_factor = alice->rendering_config.gamma_correction_factor, + .hdr_factor = alice->rendering_config.hdr_factor, + .lsd_factor = alice->rendering_config.lsd_factor, + .anim_time = 0 /* Not used */ + }; + vkCmdPushConstants(alice->rendering_command_buf_1, alice->pipeline_hands_1.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, + 0, sizeof(Pipeline1PushRangeVertex), ®_and_params_vertex); + vkCmdPushConstants(alice->rendering_command_buf_1, alice->pipeline_hands_1.pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, + sizeof(Pipeline1PushRangeVertex), sizeof(Pipeline1PushRangeFragment), ®_and_params_fragment); + vkCmdDraw(alice->rendering_command_buf_1, 3, 1, 0, 0); + + LucyRenderer_another_frame_rec_drawing(&alice->lucy_renderer, alice->rendering_command_buf_1, image_extent); + + vkCmdEndRenderPass(alice->rendering_command_buf_1); + margaret_end_command_buffer(alice->rendering_command_buf_1); +} + +void recreate_swapchain(Alice *alice) { + // We are stopping program and rebuilding our sem+sem+fence synchronization mechanism + vkDeviceWaitIdle(alice->device); // todo: AAAAAAAAAAAAAAA this is all so so wrong AAAAAAAA + Jane_alice_destroy(alice->device, alice->jane); + alice->jane = Jane_alice_create(alice->device); + VkSwapchainKHR old_swapchain = MargaretSwapchainBundle_pop_swapchain_drop_rest( + alice->device, alice->swfb); + // old swfb is 83% dropped + VkExtent2D extent = alice->wl.width_confirmed <= 0 || alice->wl.height_confirmed <= 0 ? + alice->wl.sane_image_extent_limit : (VkExtent2D){ alice->wl.width_confirmed, alice->wl.height_confirmed }; + + ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details( + alice->physical_device, alice->surface, extent); + if (swapchain_details_res.variant != Result_Ok) + abortf("swapchain_details_res.variant != Result_Ok"); + MargaretChosenSwapchainDetails swapchain_details = swapchain_details_res.ok; + MargaretSwapchainBundle new_swfb = MargaretSwapchainBundle_new(alice->device, alice->queue_fam, + swapchain_details, alice->surface, alice->render_pass_1, alice->swfb.swapchain); + vkDestroySwapchainKHR(alice->device, old_swapchain, NULL); + // Now old swfb is 100% dropped + alice->swfb = new_swfb; +} + +/* It creates image views, descriptor sets, framebuffers. But not for generic models. + * If we ever gonna do defragmentation, this step would have to be repeated */ +void alice_create_mem_dependant_vk_obj(Alice* alice){ + alice->zbuffer_view = margaret_create_view_for_image(alice->device, alice->zbuffer_image.a.image, + alice->zbuffer_format, VK_IMAGE_ASPECT_DEPTH_BIT); + alice->IT1_view = margaret_create_view_for_image(alice->device, alice->IT1_image.a.image, + alice->IT1_format, VK_IMAGE_ASPECT_COLOR_BIT); + alice->IT1_framebuffer = create_IT1_framebuffer(alice->device, + alice->IT1_view, alice->zbuffer_view, alice->render_pass_0, + alice->wl.sane_image_extent_limit.width, alice->wl.sane_image_extent_limit.height); + + alice->descriptor_set_for_pipeline_0b = margaret_allocate_descriptor_set( + alice->device, alice->descriptor_pool, alice->pipeline_hands_0b.descriptor_set_layout); + alice->descriptor_set_for_pipeline_1 = margaret_allocate_descriptor_set( + alice->device, alice->descriptor_pool, alice->pipeline_hands_1.descriptor_set_layout); + + // todo: separate set0 and set 1 + VkDescriptorBufferInfo buffer_info_for_descriptor_0_in_set_0b = { + .buffer = MargaretSubbuf_get_buffer(&alice->pipeline0_ubo.device_local), + .offset = alice->pipeline0_ubo.device_local.start, .range = sizeof(Pipeline0UBO), + }; + VkDescriptorImageInfo image_info_for_descriptor_0_in_set_1 = { + .sampler = alice->nearest_sampler, .imageView = alice->IT1_view, + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + VkWriteDescriptorSet writes_in_descriptor_sets[] = { + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = alice->descriptor_set_for_pipeline_0b, + .dstBinding = 0, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .pBufferInfo = &buffer_info_for_descriptor_0_in_set_0b, + }, + + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = alice->descriptor_set_for_pipeline_1, + .dstBinding = 0, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = &image_info_for_descriptor_0_in_set_1, + }, + }; + vkUpdateDescriptorSets(alice->device, ARRAY_SIZE(writes_in_descriptor_sets), writes_in_descriptor_sets, 0, NULL); +} + +/* Needed for defragmentation of memory */ +void destroy_vulkan_reference_objects(Alice* alice){ + abortf("Please don't\n"); + // todo: vkdestro all the views all the framebuffers + // todo: drop everything, +} + +void alice_frame_drawing(Alice* alice) { + check(vkWaitForFences(alice->device, 1, &alice->jane.in_flight_fence, VK_TRUE, UINT64_MAX) == VK_SUCCESS); + check(vkResetFences(alice->device, 1, &alice->jane.in_flight_fence) == VK_SUCCESS); + uint32_t ij; + VkResult aq_ret; + and_again: + aq_ret = vkAcquireNextImageKHR( + alice->device, alice->swfb.swapchain, + UINT64_MAX, alice->jane.image_available_semaphore, VK_NULL_HANDLE, &ij + ); + if (aq_ret == VK_ERROR_OUT_OF_DATE_KHR || aq_ret == VK_SUBOPTIMAL_KHR) { + fprintf(stderr, "vkAcquireNextImageKHR in { VK_ERROR_OUT_OF_DATE_KHR, VK_SUBOPTIMAL_KHR }\n"); + recreate_swapchain(alice); + goto and_again; + } else if (aq_ret != VK_SUCCESS) { + abortf("vkAcquireNextImageKHR"); + } + + mat4 projection_matrix = marie_perspective_projection_fov_mat4( + (float)alice->wl.width_confirmed, (float)alice->wl.height_confirmed, + alice->cam_info.cam.fov, 0.01f, 1000); + mat4 camera_rotation_matrix = marie_mat3_to_mat4_transposed(alice->cam_info.cam.cam_basis); + mat4 camera_translation_matrix = marie_translation_mat4(vec3_minus(alice->cam_info.cam.pos)); + mat4 t_mat = mat4_mul_mat4(projection_matrix, mat4_mul_mat4(camera_rotation_matrix, camera_translation_matrix)); + + 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); + AliceScene__another_frame(alice); + LucyGlyphCache_another_frame(&alice->lucy_cache); + LucyRenderer_another_frame(&alice->lucy_renderer); + margaret_end_command_buffer(alice->transfer_command_buf); + alice_reset_and_record_command_buffer_0(alice, t_mat); + alice_reset_and_record_command_buffer_1(alice, *VecVkFramebuffer_at(&alice->swfb.framebuffers, ij)); + + check(vkQueueSubmit(alice->queues.graphics_queue, 1, &(VkSubmitInfo){ + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .commandBufferCount = 1, + .pCommandBuffers = (VkCommandBuffer[]){ alice->transfer_command_buf }, + .signalSemaphoreCount = 1, + .pSignalSemaphores = (VkSemaphore[]){ alice->jane.in_frame_transfer_complete }, + }, NULL) == VK_SUCCESS); + + check(vkQueueSubmit(alice->queues.graphics_queue, 1, &(VkSubmitInfo){ + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + + .waitSemaphoreCount = 1, + .pWaitSemaphores = (VkSemaphore[]){alice->jane.in_frame_transfer_complete}, + .pWaitDstStageMask = (VkPipelineStageFlags[]){ + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT + }, + + .commandBufferCount = 1, + .pCommandBuffers = (VkCommandBuffer[]){ alice->rendering_command_buf_0 }, + + .signalSemaphoreCount = 1, + .pSignalSemaphores = (VkSemaphore[]){ alice->jane.rendered_to_IT1_semaphore }, + }, NULL) == VK_SUCCESS); + + check(vkQueueSubmit(alice->queues.graphics_queue, 1, &(VkSubmitInfo){ + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .waitSemaphoreCount = 2, + .pWaitSemaphores = (VkSemaphore[]){ + alice->jane.image_available_semaphore, alice->jane.rendered_to_IT1_semaphore }, + .pWaitDstStageMask = (VkPipelineStageFlags[]){ + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT }, + .commandBufferCount = 1, + .pCommandBuffers = (VkCommandBuffer[]){ alice->rendering_command_buf_1 }, + .signalSemaphoreCount = 1, + .pSignalSemaphores = (VkSemaphore[]){ + *VecVkSemaphore_at(&alice->swfb.rendering_finished_here_semaphores, ij) }, + }, alice->jane.in_flight_fence) == VK_SUCCESS); + + VkPresentInfoKHR present_info = { + .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, + .waitSemaphoreCount = 1, + .pWaitSemaphores = (VkSemaphore[]){ + *VecVkSemaphore_at(&alice->swfb.rendering_finished_here_semaphores, ij) }, + .swapchainCount = 1, + .pSwapchains = (VkSwapchainKHR[]){ alice->swfb.swapchain }, + .pImageIndices = (U32[]){ ij }, + .pResults = NULL, + }; + VkResult present_ret = vkQueuePresentKHR(alice->queues.presentation_queue, &present_info); + if (present_ret == VK_ERROR_OUT_OF_DATE_KHR || present_ret == VK_SUBOPTIMAL_KHR) { + fprintf(stderr, "vkQueuePresentKHR: VK_ERROR_OUT_OF_DATE_KHR or \n"); + check(vkWaitForFences(alice->device, 1, &alice->jane.in_flight_fence, VK_TRUE, UINT64_MAX) == VK_SUCCESS); + check(vkResetFences(alice->device, 1, &alice->jane.in_flight_fence) == VK_SUCCESS); + recreate_swapchain(alice); + goto and_again; + } else if (present_ret != VK_SUCCESS) { + abortf("vkQueuePresentKHR"); + } + + margaret_ns_time frame_B0 = margaret_clock_gettime_monotonic_raw(); + alice->wl.frame_count_since_key++; + if (margaret_ns_time_sec_diff(alice->wl.prev_key_frame_time, frame_B0) > 1.0) { + float fps = (float)alice->wl.frame_count_since_key / margaret_ns_time_sec_diff(alice->wl.prev_key_frame_time, frame_B0); + printf("FPS: %0.1lf\n", fps); + alice->wl.frame_count_since_key = 0; + alice->wl.prev_key_frame_time = frame_B0; + } +} + +static void alice_mainloop_h_xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial){ + Alice* alice = data; + printf("XDG surface configured! (%d %d)\n", alice->wl.width_heard, alice->wl.height_heard); + alice->wl.width_confirmed = alice->wl.width_heard; + alice->wl.height_confirmed = alice->wl.height_heard; + xdg_surface_ack_configure(xdg_surface, serial); + // todo: omg, I need to fix this crap for real, like, this is all so wrong + recreate_swapchain(alice); + alice_frame_drawing(alice); +} + +static const struct xdg_surface_listener xdg_surface_listener = { + .configure = alice_mainloop_h_xdg_surface_configure, +}; + +static void alice_mainloop_h_xdg_toplevel_configure( + void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states + ){ + Alice* alice = data; + uint32_t *conf_state; + wl_array_for_each(conf_state, states) { + printf("A state of xdg toplevel: %u\n", *conf_state); + } + printf("XDG toplevel configured to (%d %d)\n", width, height); + if (width <= 0 || height <= 0) + return; + alice->wl.width_heard = width; + alice->wl.height_heard = height; +} + +static void alice_mainloop_h_xdg_toplevel_close(void *data, struct xdg_toplevel *toplevel){ + Alice* alice = data; + alice->wl.closed = true; +} + +static const struct xdg_toplevel_listener alice_mainloop_h_xdg_toplevel_listener = { + .configure = alice_mainloop_h_xdg_toplevel_configure, + .close = alice_mainloop_h_xdg_toplevel_close, +}; + +static void alice_mainloop_h_xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial){ + xdg_wm_base_pong(xdg_wm_base, serial); +} + +static const struct xdg_wm_base_listener alice_mainloop_h_xdg_wm_base_listener = { + .ping = alice_mainloop_h_xdg_wm_base_ping, +}; + +static void alice_mainloop_h_wl_keyboard_keymap( + void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size + ) { + Alice* alice = data; + if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) + abortf("O_o"); + char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (map_shm == MAP_FAILED) + abortf("Couldn't mmap new keymap ha-ha\n"); + + xkb_keymap_unref(alice->wl.xkb_keymap); + xkb_state_unref(alice->wl.xkb_state); + alice->wl.xkb_keymap = xkb_keymap_new_from_string( + alice->wl.xkb_context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); + munmap(map_shm, size); + close(fd); + alice->wl.xkb_state = xkb_state_new(alice->wl.xkb_keymap); + printf("Keymap changed!\n"); + memset(&alice->wl.first_0x80_keys, 0, sizeof(alice->wl.first_0x80_keys)); +} + +static void alice_mainloop_h_wl_keyboard_enter( + void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys + ) { + Alice* alice = data; + printf("keyboard enter; keys pressed are:\n"); + uint32_t *key; + wl_array_for_each(key, keys) { + uint32_t actual_key = *key + 8; + xkb_keysym_t sym = xkb_state_key_get_one_sym(alice->wl.xkb_state, actual_key); + if (sym < 0x80) + alice->wl.first_0x80_keys[sym] = true; + } +} + +static void alice_mainloop_h_wl_keyboard_leave( + void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface + ) { + Alice* alice = data; + memset(&alice->wl.first_0x80_keys, 0, sizeof(alice->wl.first_0x80_keys)); +} + +static void alice_mainloop_h_wl_keyboard_key( + void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t key_action + ) { + Alice* alice = data; + uint32_t actual_key = key + 8; + /* It actually could be nokey keysym. You never know without checking */ + xkb_keysym_t keysym = xkb_state_key_get_one_sym(alice->wl.xkb_state, actual_key); + if (keysym < 0x80 && key_action == WL_KEYBOARD_KEY_STATE_RELEASED) { + alice->wl.first_0x80_keys[keysym] = false; + } else if (keysym < 0x80 && key_action == WL_KEYBOARD_KEY_STATE_PRESSED) { + alice->wl.first_0x80_keys[keysym] = true; + } + alice->callbacks.on_wl_keyboard_key(alice->guest, keysym, key_action); + if (key_action == WL_KEYBOARD_KEY_STATE_RELEASED) { + if (keysym == XKB_KEY_1) { + } else if (keysym == XKB_KEY_2) { + alice->rendering_config.hdr_factor /= 1.05f; + printf("hdr factor decreased to %f\n", alice->rendering_config.hdr_factor); + } else if (keysym == XKB_KEY_3) { + alice->rendering_config.hdr_factor *= 1.05f; + printf("hdr factor increased to %f\n", alice->rendering_config.hdr_factor); + } + } +} + +static void alice_mainloop_h_wl_keyboard_modifiers( + void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, + uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group + ) { + Alice* alice = data; + xkb_state_update_mask(alice->wl.xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group); +} + +static void alice_mainloop_h_wl_keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, int32_t rate, int32_t delay){ + printf("Repeat timings changed: rate = %d, delay = %d\n", rate, delay); +} + +static const struct wl_keyboard_listener alice_mainloop_h_wl_keyboard_listener = { + .keymap = alice_mainloop_h_wl_keyboard_keymap, + .enter = alice_mainloop_h_wl_keyboard_enter, + .leave = alice_mainloop_h_wl_keyboard_leave, + .key = alice_mainloop_h_wl_keyboard_key, + .modifiers = alice_mainloop_h_wl_keyboard_modifiers, + .repeat_info = alice_mainloop_h_wl_keyboard_repeat_info, +}; + + +static void alice_mainloop_h_wl_pointer_enter( + void *data, struct wl_pointer *wl_pointer, uint32_t serial, + struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y + ) { +} + +static void alice_mainloop_h_wl_pointer_leave( + void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface + ) { +} + +static void alice_mainloop_h_wl_pointer_motion( + void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y + ) { + Alice* alice = data; + AliceCamVerticalControl_update_direction(&alice->cam_info, + alice->wl.width_confirmed, alice->wl.height_confirmed, + (float)surface_x / 256.f, (float)surface_y / 256.f); +} + +static void alice_mainloop_h_wl_pointer_button( + void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t btn_action + ) { + Alice* alice = data; +} + +static void alice_mainloop_h_wl_pointer_axis( + void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value + ) { + Alice* alice = data; +} + +static void alice_mainloop_h_wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { + Alice* alice = data; +} + +const struct wl_pointer_listener alice_mainloop_h_wl_pointer_listener = { + .enter = alice_mainloop_h_wl_pointer_enter, + .leave = alice_mainloop_h_wl_pointer_leave, + .motion = alice_mainloop_h_wl_pointer_motion, + .button = alice_mainloop_h_wl_pointer_button, + .axis = alice_mainloop_h_wl_pointer_axis, + .frame = alice_mainloop_h_wl_pointer_frame +}; + +static void alice_mainloop_h_wl_seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) { + Alice* alice = data; + if (capabilities & WL_SEAT_CAPABILITY_POINTER) { + alice->wl.pointer = wl_seat_get_pointer(wl_seat); + if (!alice->wl.pointer) + abortf("wl_seat_get_pointer\n"); + wl_pointer_add_listener(alice->wl.pointer, &alice_mainloop_h_wl_pointer_listener, alice); + } + if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { + alice->wl.keyboard = wl_seat_get_keyboard(wl_seat); + if (!alice->wl.keyboard) + abortf("wl_seat_get_keyboard\n"); + wl_keyboard_add_listener(alice->wl.keyboard, &alice_mainloop_h_wl_keyboard_listener, alice); + } +} + +static void alice_mainloop_h_wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) { + printf("Our seat name: %s\n", name); +} + +static const struct wl_seat_listener alice_mainloop_h_wl_seat_listener = { + .capabilities = alice_mainloop_h_wl_seat_capabilities, + .name = alice_mainloop_h_wl_seat_name, +}; + +static void alice_mainloop_h_wl_registry_global( + void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, uint32_t version + ) { + Alice* alice = data; + if (strcmp(interface, wl_compositor_interface.name) == 0) { + alice->wl.wl_compositor = wl_registry_bind(wl_registry, name, &wl_compositor_interface, 4); + if (!alice->wl.wl_compositor) + abortf("wl_registry_bind\n"); + } else if (strcmp(interface, xdg_wm_base_interface.name) == 0) { + alice->wl.xdg_wm_base = wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1); + if (!alice->wl.xdg_wm_base) + abortf("wl_registry_bind\n"); + xdg_wm_base_add_listener(alice->wl.xdg_wm_base, &alice_mainloop_h_xdg_wm_base_listener, alice); + } else if (strcmp(interface, wl_seat_interface.name) == 0) { + if (alice->wl.wl_seat) { + printf("We got second seat, but we only need one\n"); + return; + } + alice->wl.wl_seat = wl_registry_bind(wl_registry, name, &wl_seat_interface, 4); + if (!alice->wl.wl_seat) + abortf("wl_registry_bind\n"); + wl_seat_add_listener(alice->wl.wl_seat, &alice_mainloop_h_wl_seat_listener, alice); + } +} + +static void alice_mainloop_h_wl_registry_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name){ + +} + +static const struct wl_registry_listener alice_mainloop_h_wl_registry_listener = { + .global = alice_mainloop_h_wl_registry_global, + .global_remove = alice_mainloop_h_wl_registry_global_remove, +}; + +static const struct wl_callback_listener alice_mainloop_h_wl_surface_frame_listener; + +static void alice_mainloop_h_wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time){ + Alice* alice = data; + wl_callback_destroy(cb); + alice->wl.wl_callback = wl_surface_frame(alice->wl.wl_surface); + if (!alice->wl.wl_callback) + abortf("wl_surface_frame\n"); + wl_callback_add_listener(alice->wl.wl_callback, &alice_mainloop_h_wl_surface_frame_listener, alice); + + alice->wl.cur_frame_time = time; + alice_frame_drawing(alice); + alice->wl.last_frame_time = time; +} + +static const struct wl_callback_listener alice_mainloop_h_wl_surface_frame_listener = { + .done = alice_mainloop_h_wl_surface_frame_done, +}; + +Alice* Alice_new(){ + Alice* alice = safe_malloc(sizeof(Alice)); + SpanU8 root_dir = cstr("."); + SpanU8 GPU = cstr("nvidia"); + SpanU8 bugged_GPU = cstr("nothere"); + bool ENABLE_VALIDATION_LAYERS = true; + const U32 MAX_WIN_WIDTH = 1920; + const U32 MAX_WIN_HEIGHT = 1080; + AliceCallbacks_set_default(&alice->callbacks); + + alice->wl.sane_image_extent_limit = (VkExtent2D){MAX_WIN_WIDTH, MAX_WIN_HEIGHT}; + + alice->wl.wl_display = wl_display_connect(NULL); + if (!alice->wl.wl_display) + abortf("Could not connect"); + alice->wl.wl_registry = wl_display_get_registry(alice->wl.wl_display); + if (!alice->wl.wl_registry) + abortf("wl_display_get_registry"); + wl_registry_add_listener(alice->wl.wl_registry, &alice_mainloop_h_wl_registry_listener, alice); + wl_display_roundtrip(alice->wl.wl_display); + if (!alice->wl.wl_compositor) + abortf("No wl_compositor"); + if (!alice->wl.xdg_wm_base) + abortf("No xdg_wm_base"); + alice->wl.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!alice->wl.xkb_context) + abortf("xkb_context_new\n"); + alice->wl.wl_surface = wl_compositor_create_surface(alice->wl.wl_compositor); + if (!alice->wl.wl_surface) + abortf("wl_compositor_create_surface\n"); + alice->wl.xdg_surface = xdg_wm_base_get_xdg_surface( + alice->wl.xdg_wm_base, alice->wl.wl_surface); + if (!alice->wl.xdg_surface) + abortf("xdg_wm_base_get_xdg_surface\n"); + xdg_surface_add_listener(alice->wl.xdg_surface, &xdg_surface_listener, alice); + alice->wl.xdg_toplevel = xdg_surface_get_toplevel(alice->wl.xdg_surface); + if (!alice->wl.xdg_toplevel) + abortf("xdg_surface_get_toplevel\n"); + xdg_toplevel_add_listener(alice->wl.xdg_toplevel, &alice_mainloop_h_xdg_toplevel_listener, alice); + xdg_toplevel_set_title(alice->wl.xdg_toplevel, "r3"); + xdg_toplevel_set_app_id(alice->wl.xdg_toplevel, "r3"); + wl_surface_commit(alice->wl.wl_surface); + + alice->wl.wl_callback = wl_surface_frame(alice->wl.wl_surface); + if (!alice->wl.wl_callback) + abortf("wl_surface_frame\n"); + wl_callback_add_listener(alice->wl.wl_callback, &alice_mainloop_h_wl_surface_frame_listener, alice); + alice->wl.cur_frame_time = alice->wl.last_frame_time = 0; + + alice->instance_and_debug = MargaretInstanceAndItsDebug_new(ENABLE_VALIDATION_LAYERS); + VkInstance instance = alice->instance_and_debug.instance; + + // print_instance_available_extensions(instance); + // print_instance_available_layers(instance); + + alice->surface = margaret_create_surface(instance, alice->wl.wl_display, alice->wl.wl_surface); + + alice->physical_device = margaret_select_one_physical_device( + instance, alice->surface, GPU, bugged_GPU, alice->wl.sane_image_extent_limit); + + // print_physical_device_available_extensions(physical_device); + + ResultMargaretChosenQueueFamiliesOrSpanU8 queue_fam_res = margaret_choose_good_queue_families( + alice->physical_device, alice->surface); + if (queue_fam_res.variant != Result_Ok) + abortf("queue_fam_res.variant != Result_Ok"); + alice->queue_fam = queue_fam_res.ok; + + 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); + } + + ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details( + alice->physical_device, alice->surface, alice->wl.sane_image_extent_limit); + if (swapchain_details_res.variant != Result_Ok) + abortf("swapchain_details_res.variant != Result_Ok"); + + OptionVkFormat zbuffer_format_found = margaret_find_supported_zbuffer_format(alice->physical_device); + alice->zbuffer_format = OptionVkFormat_expect(zbuffer_format_found); + OptionVkFormat IT1_format_found = margaret_find_supported_hdr_buffer_format(alice->physical_device); + alice->IT1_format = OptionVkFormat_expect(IT1_format_found); + + alice->render_pass_0 = create_render_pass_0(alice->device, alice->IT1_format, alice->zbuffer_format); + alice->pipeline_hands_0a = create_graphics_pipeline_0(alice->device, root_dir, alice->render_pass_0, 0); + alice->pipeline_hands_0b = create_graphics_pipeline_0_b(alice->device, root_dir, alice->render_pass_0, 0); + + alice->render_pass_1 = create_render_pass_1(alice->device, swapchain_details_res.ok.surface_format.format); + alice->pipeline_hands_1 = create_graphics_pipeline_1(alice->device, root_dir, alice->render_pass_1, 0); + + // These samplers are global for a lot of my future textures + alice->linear_sampler = margaret_create_sampler(alice->physical_device, alice->device, true); + alice->nearest_sampler = margaret_create_sampler(alice->physical_device, alice->device, false); + + alice->command_pool = margaret_create_resettable_command_pool(alice->device, alice->queue_fam.for_graphics); + alice->rendering_command_buf_0 = margaret_allocate_command_buffer(alice->device, alice->command_pool); + alice->rendering_command_buf_1 = margaret_allocate_command_buffer(alice->device, alice->command_pool); + alice->transfer_command_buf = margaret_allocate_command_buffer(alice->device, alice->command_pool); + alice->device_local_mem_mv_command_buf = margaret_allocate_command_buffer(alice->device, alice->command_pool); + + // todo: write a descriptor set allocator (in Margaret) that manages dynamic descript or pool allocatrinonsasdasdasd + alice->descriptor_pool = margaret_create_descriptor_set_pool(alice->device, 100, 100, 100); + + /* Here we search physical device memory types for the one with host-visible flag and the other with device-local flag */ + VkPhysicalDeviceMemoryProperties mem_properties; + vkGetPhysicalDeviceMemoryProperties(alice->physical_device, &mem_properties); + const VkMemoryPropertyFlags host_visible_coherent = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + const VkMemoryPropertyFlags device_local = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + int mem_type_id_host_visible_coherent = -1; + for (int i = 0; i < (int)mem_properties.memoryTypeCount; i++) { + if ((mem_properties.memoryTypes[i].propertyFlags & host_visible_coherent) == host_visible_coherent) { + mem_type_id_host_visible_coherent = i; + break; + } + } + if (mem_type_id_host_visible_coherent == -1) { + abortf("Can't find host visible + host coherent memory\n"); + } + int mem_type_id_device_local = -1; + for (int i = 0; i < (int)mem_properties.memoryTypeCount; i++) { + if ((mem_properties.memoryTypes[i].propertyFlags & device_local) == device_local) { + mem_type_id_device_local = i; + break; + } + } + if (mem_type_id_device_local == -1) { + abortf("Can't find device local memory\n"); + } + + alice->staging_buffers = MargaretBufAllocator_new(alice->device, alice->physical_device, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + mem_type_id_host_visible_coherent, 3, true, 16); + + // 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 */, + mem_type_id_device_local, 6, false, 10000); + + alice->dev_local_images = MargaretImgAllocator_new(alice->device, alice->physical_device, + mem_type_id_device_local, 16000000); + + alice->jane = Jane_alice_create(alice->device); + /* Luckily, swapchain image allocation is not managed by me */ + alice->swfb = MargaretSwapchainBundle_new( + alice->device, alice->queue_fam, swapchain_details_res.ok, + alice->surface, alice->render_pass_1, NULL); + + alice->generic_models = AliceAllMeshesGeneric_new(); + alice->shiny_models = AliceAllMeshesShiny_new(); + alice->pipeline0_ubo.staging = MargaretBufAllocator_alloc(&alice->staging_buffers, sizeof(Pipeline0UBO)); + alice->pipeline0_ubo.device_local = MargaretBufAllocator_alloc(&alice->dev_local_buffers, sizeof(Pipeline0UBO)); + Pipeline0UBO* ubo0 = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_ubo.staging); + ubo0->point_light_count = ubo0->spotlight_count = 0; + + alice->cam_info = AliceCamVerticalControl_new(); + alice->rendering_config = AliceRenderConfig_new(); + + alice->IT1_image = MargaretImgAllocator_alloc(&alice->dev_local_images, + MAX_WIN_WIDTH, MAX_WIN_HEIGHT, alice->IT1_format, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + alice->zbuffer_image = MargaretImgAllocator_alloc(&alice->dev_local_images, + MAX_WIN_WIDTH, MAX_WIN_HEIGHT, alice->zbuffer_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + + MargaretEngineReference engine_reference = { + .device = alice->device, .physical_device = alice->physical_device, .transfer_cmd_buffer = alice->transfer_command_buf, + .dev_local_images = &alice->dev_local_images, .dev_local_buffers = &alice->dev_local_buffers, + .staging_buffers = &alice->staging_buffers, .descriptor_pool = alice->descriptor_pool, + .linear_sampler = alice->linear_sampler, .nearest_sampler = alice->nearest_sampler + }; + + FT_Error ft_init_err = FT_Init_FreeType(&alice->ft_library); + if (ft_init_err) + abortf("Can't init free type library\n"); + + alice->lucy_cache = LucyGlyphCache_new(engine_reference); + + alice->lucy_renderer = LucyRenderer_new(engine_reference, &alice->lucy_cache, root_dir, alice->render_pass_1, 0); + + // Creating framebuffer for IT1, image views for IT1 and zbuffer + // Creating descriptor set for pipeline 0b and for pipeline 1 (containing IT1 sampler) + alice_create_mem_dependant_vk_obj(alice); + + alice->wl.prev_key_frame_time = margaret_clock_gettime_monotonic_raw(); + alice->wl.frame_count_since_key = 0; + /* Alice initialization complete */ + return alice; +} + +void Alice_set_point_light_count(Alice* alice, int new_count){ + Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_ubo.staging); + assert(new_count <= pipeline_0_ubo_point_light_max_count); + ubo->point_light_count = new_count; +} + +void Alice_set_point_light(Alice* alice, int index, Pipeline0PointLight data){ + Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_ubo.staging); + assert(index < pipeline_0_ubo_point_light_max_count); + ubo->point_light_arr[index] = data; +} + +/* This function actually consumes alice handler. Alice must not be used after */ +void Alice_mainloop(Alice* alice, const AliceCallbacks* callbacks) { + alice->callbacks.on_wl_keyboard_key = callbacks->on_wl_keyboard_key; + alice->callbacks.on_another_frame = callbacks->on_another_frame; + printf("ENTERING WAYLAND MAINLOOP\n"); + while (wl_display_dispatch(alice->wl.wl_display) >= 0) { + if (alice->wl.closed) + break; + } + vkDeviceWaitIdle(alice->device); + + // The End + // vkDestroyDescriptorPool(vk->device, vk->descriptor_pool, NULL); + // vkDestroySampler(vk->device, vk->linear_sampler, NULL); + // vkDestroySampler(vk->device, vk->nearest_sampler, NULL); + // + // + // Scene_drop(vk->scene); + // + // vkDestroyCommandPool(vk->device, vk->command_pool, NULL); + // + // + // MargaretSwapchainBundle_drop_with_device(vk->device, vk->swfb); + // Jane_alice_destroy(vk->device, vk->jane); + // destroy_graphics_pipeline_hands(vk->device, vk->pipeline_hands_1); + // vkDestroyRenderPass(vk->device, vk->render_pass_1, NULL); + // destroy_graphics_pipeline_hands(vk->device, vk->pipeline_hands_0b); + // destroy_graphics_pipeline_hands(vk->device, vk->pipeline_hands_0a); + // vkDestroyRenderPass(vk->device, vk->render_pass_0, NULL); + // vkDestroyDevice(vk->device, NULL); + // vkDestroySurfaceKHR(instance, vk->surface, NULL); + // MargaretInstanceAndItsDebug_drop(vk->instance_and_debug); + // + // if (alice->wl.wl_callback) + // wl_callback_destroy(alice->wl.wl_callback); + // xdg_toplevel_destroy(alice->wl.xdg_toplevel); + // xdg_surface_destroy(alice->wl.xdg_surface); + // xdg_wm_base_destroy(alice->wl.xdg_wm_base); + // wl_surface_destroy(alice->wl.wl_surface); + // wl_compositor_destroy(alice->wl.wl_compositor); + // if (alice->wl.pointer) + // wl_pointer_destroy(alice->wl.pointer); + // xkb_context_unref(alice->wl.xkb_context); + // xkb_keymap_unref(alice->wl.xkb_keymap); + // xkb_state_unref(alice->wl.xkb_state); + // if (alice->wl.keyboard) + // wl_keyboard_destroy(alice->wl.keyboard); + // if (alice->wl.wl_seat) + // wl_seat_destroy(alice->wl.wl_seat); + // wl_registry_destroy(alice->wl.wl_registry); + wl_display_disconnect(alice->wl.wl_display); +} + +#endif \ No newline at end of file diff --git a/src/l2/allie/allie.c b/src/l2/allie/allie.c index 93a2964..e4bb8cf 100644 --- a/src/l2/allie/allie.c +++ b/src/l2/allie/allie.c @@ -1,2084 +1,4 @@ -#include "../alice/model_file.h" -#include "../../l1/marie/geom_alg_utils.h" -#include "../margaret/vulkan_utils.h" -#include "../lucy/glyph_render.h" - -typedef struct { - U64 count; - MargaretSubbuf staging; - MargaretSubbuf device_local; -} 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 */ - VkDescriptorSet p_0a_set_0; -} AliceGenericMeshMemDependantVkObj; - -typedef struct { - size_t indexes; - // Option - MargaretSubbuf staging_vbo; - // Option - 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; - - 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; -} AliceGenericMeshHand; - -#include "../../../gen/l1/eve/alice/ListAliceGenericMeshHand.h" - -typedef struct { - size_t indexes; - - MargaretSubbuf staging_vbo; - MargaretSubbuf staging_ebo; - - MargaretSubbuf vbo; - MargaretSubbuf ebo; - PatriciaBuf instance_attr; - - bool scheduled_for_deletion; -} AliceShinyMeshHand; - -#include "../../../gen/l1/eve/alice/ListAliceShinyMeshHand.h" - -typedef struct { - float fov; - mat3 cam_basis; - vec3 pos; -} AliceCam; - -typedef struct{ - AliceCam cam; - float sensitivity; - float pitch_cap; -} AliceCamVerticalControl; - -AliceCamVerticalControl AliceCamVerticalControl_new() { - return (AliceCamVerticalControl){ - .cam.fov = 1.5f, .cam.cam_basis = marie_simple_camera_rot_m_basis_in_cols(0, 0, 0), .cam.pos = {0, 0, 0}, - .sensitivity = 0.5f * M_PIf / 180, .pitch_cap = M_PIf * 0.49f - }; -} - -void AliceCamVerticalControl_update_direction( - AliceCamVerticalControl* self, int win_width, int win_height, float pointer_x, float pointer_y) { - float yaw = ((float)win_width / 2 - pointer_x) * self->sensitivity; - float pitch = marie_clamp_float( - ((float)win_height / 2 - pointer_y) * self->sensitivity, - -self->pitch_cap, self->pitch_cap - ); - self->cam.cam_basis = marie_simple_camera_rot_m_basis_in_cols(yaw, pitch, 0); -} - -typedef struct { - MargaretSubbuf staging; - MargaretSubbuf device_local; -} AlicePipeline0UBO; - -typedef struct{ - vec4 clear_color; - float gamma_correction_factor; - float hdr_factor; - float lsd_factor; -} AliceRenderConfig; - -AliceRenderConfig AliceRenderConfig_new(){ - return (AliceRenderConfig){ - .clear_color = {0, 0.5f, 0.9f, 1}, - .gamma_correction_factor = 2.2f, .hdr_factor = 1, .lsd_factor = 0}; -} - -/* Here ends the old r0_scene.h file - * And begins old r0.c file */ - -#include -#include "../../../gen/l1/margaret/png_pixel_masses.h" -#include "../lucy/glyph_cache.h" -#include -//#include "../../l1/system/fileio.h" -#include -#include -#include "../../../gen/l_wl_protocols/xdg-shell-client.h" - - -VkRenderPass create_render_pass_0(VkDevice logical_device, VkFormat colorbuffer_format, VkFormat zbuffer_format) { - VkAttachmentDescription all_attachments[2] = { - { - .format = colorbuffer_format, - .samples = VK_SAMPLE_COUNT_1_BIT, - .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, - .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - }, - { - .format = zbuffer_format, - .samples = VK_SAMPLE_COUNT_1_BIT, - .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, - .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, - .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, - .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - } - }; - - // For our one single render subpass - VkAttachmentReference color_attachments_refs[1] = { - { - .attachment = 0, - .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - } }; - - VkAttachmentReference depth_attachment_ref = { - .attachment = 1, - .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - }; - - VkSubpassDescription subpasses_descr[1] = { (VkSubpassDescription){ - .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, - .colorAttachmentCount = ARRAY_SIZE(color_attachments_refs), - .pColorAttachments = color_attachments_refs, - .pDepthStencilAttachment = &depth_attachment_ref, - } }; - - VkSubpassDependency subpass_dependencies[1] = { - // subpass_0_external - (VkSubpassDependency) { - .srcSubpass = VK_SUBPASS_EXTERNAL, - .dstSubpass = 0, - .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, - .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, - .srcAccessMask = 0, - .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - }}; - - VkRenderPassCreateInfo render_pass_crinfo = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .attachmentCount = ARRAY_SIZE(all_attachments), - .pAttachments = all_attachments, - .subpassCount = ARRAY_SIZE(subpasses_descr), - .pSubpasses = subpasses_descr, - .dependencyCount = ARRAY_SIZE(subpass_dependencies), - .pDependencies = subpass_dependencies, - }; - VkRenderPass render_pass; - if (vkCreateRenderPass(logical_device, &render_pass_crinfo, NULL, &render_pass) != VK_SUCCESS) - abortf("vkCreateRenderPass"); - return render_pass; -} - -typedef struct { - VkPipelineLayout pipeline_layout; - VkPipeline pipeline; - VkDescriptorSetLayout descriptor_set_layout; -} AlicePipeline0a; - -void AlicePipeline0a_destroy(VkDevice device, AlicePipeline0a hands) { - vkDestroyPipeline(device, hands.pipeline, NULL); - vkDestroyPipelineLayout(device, hands.pipeline_layout, NULL); - vkDestroyDescriptorSetLayout(device, hands.descriptor_set_layout, NULL); -} - -AlicePipeline0a create_graphics_pipeline_0( - VkDevice device, SpanU8 root_dir, VkRenderPass render_pass, uint32_t subpass - ) { - VkDescriptorSetLayoutBinding bindings_for_my_descr_set_layout[] = { - { - .binding = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - // our shader variable is not an array of descriptors, so this stays 1 - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - }, - { - .binding = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - }, - { - .binding = 2, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - }, - { - .binding = 3, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - }, - }; - VkDescriptorSetLayoutCreateInfo descriptor_set_layout_crinfo = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .bindingCount = ARRAY_SIZE(bindings_for_my_descr_set_layout), - .pBindings = bindings_for_my_descr_set_layout, - }; - VkDescriptorSetLayout my_descriptor_set_layout; - if (vkCreateDescriptorSetLayout(device, &descriptor_set_layout_crinfo, NULL, &my_descriptor_set_layout) != VK_SUCCESS) - abortf("vkCreateDescriptorSetLayout"); - - VkPushConstantRange pc_ranges[] = { - { - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, - .offset = 0, .size = sizeof(mat4) - }, - { - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - .offset = sizeof(mat4), .size = sizeof(vec3) - }, - - }; - - VkPipelineLayoutCreateInfo layout_crinfo = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .setLayoutCount = 1, - .pSetLayouts = &my_descriptor_set_layout, - .pushConstantRangeCount = ARRAY_SIZE(pc_ranges), - .pPushConstantRanges = pc_ranges, - }; - VkPipelineLayout pipeline_layout; - if (vkCreatePipelineLayout(device, &layout_crinfo, NULL, &pipeline_layout) != VK_SUCCESS) - abortf("vkCreatePipelineLayout"); - - - VecU8 vert_bin_code = read_file_by_path(VecU8_fmt("%s/gen/l_adele/alice/0gen/vert.spv", root_dir)); - VecU8 frag_bin_code = read_file_by_path(VecU8_fmt("%s/gen/l_adele/alice/0gen/frag.spv", root_dir)); - - VkVertexInputBindingDescription vertex_bindings[2] = { - { - .binding = 0, - .stride = sizeof(GenericMeshVertex), - .inputRate = VK_VERTEX_INPUT_RATE_VERTEX, - }, - { - .binding = 1, - .stride = sizeof(GenericMeshInstance), - .inputRate = VK_VERTEX_INPUT_RATE_INSTANCE, - } - }; - VkVertexInputAttributeDescription vertex_attributes[2 + 3 + 4 + 3] = { - { - .location = 0, .binding = 0, - .format = VK_FORMAT_R32G32B32_SFLOAT, - .offset = offsetof(GenericMeshVertexInc, pos), - }, - { - .location = 1, .binding = 0, - .format = VK_FORMAT_R32G32_SFLOAT, - .offset = offsetof(GenericMeshVertexInc, tex), - }, - { - .location = 2, .binding = 0, - .format = VK_FORMAT_R32G32B32_SFLOAT, - .offset = offsetof(GenericMeshVertex, norm), - }, - { - .location = 3, .binding = 0, - .format = VK_FORMAT_R32G32B32_SFLOAT, - .offset = offsetof(GenericMeshVertex, tang_U), - }, - { - .location = 4, .binding = 0, - .format = VK_FORMAT_R32G32B32_SFLOAT, - .offset = offsetof(GenericMeshVertex, tang_V), - }, - - /* This is a mat4 datatype, so it will take 4 entire 'locations' */ - { - .location = 5, .binding = 1, - .format = VK_FORMAT_R32G32B32A32_SFLOAT, - .offset = offsetof(GenericMeshInstanceInc, model_t) + offsetof(mat4, x) - }, - { - .location = 6, .binding = 1, - .format = VK_FORMAT_R32G32B32A32_SFLOAT, - .offset = offsetof(GenericMeshInstanceInc, model_t) + offsetof(mat4, y) - }, - { - .location = 7, .binding = 1, - .format = VK_FORMAT_R32G32B32A32_SFLOAT, - .offset = offsetof(GenericMeshInstanceInc, model_t) + offsetof(mat4, z) - }, - { - .location = 8, .binding = 1, - .format = VK_FORMAT_R32G32B32A32_SFLOAT, - .offset = offsetof(GenericMeshInstanceInc, model_t) + offsetof(mat4, w) - }, - { - .location = 9, .binding = 1, - .format = VK_FORMAT_R32G32B32_SFLOAT, - .offset = offsetof(GenericMeshInstance, normal_t) + offsetof(mat3, x) - }, - { - .location = 10, .binding = 1, - .format = VK_FORMAT_R32G32B32_SFLOAT, - .offset = offsetof(GenericMeshInstance, normal_t) + offsetof(mat3, y) - }, - { - .location = 11, .binding = 1, - .format = VK_FORMAT_R32G32B32_SFLOAT, - .offset = offsetof(GenericMeshInstance, normal_t) + offsetof(mat3, z) - }, - }; - - VkPipeline pipeline = margaret_create_triangle_pipeline_one_attachment(device, render_pass, subpass, - (MargaretMostImportantPipelineOptions){ - .pipeline_layout = pipeline_layout, - .vertex_shader_code = vert_bin_code, .fragment_shader_code = frag_bin_code, - .vertexBindingDescriptionCount = ARRAY_SIZE(vertex_bindings), vertex_bindings, - .vertexAttributeDescriptionCount = ARRAY_SIZE(vertex_attributes), vertex_attributes, - .depthTestEnable = true, .depthWriteEnable = true, .blendEnable = false - }); - return (AlicePipeline0a){.pipeline_layout = pipeline_layout, .pipeline = pipeline, .descriptor_set_layout = my_descriptor_set_layout}; -} - -typedef struct { - VkPipelineLayout pipeline_layout; - VkPipeline pipeline; - VkDescriptorSetLayout descriptor_set_layout; -} AlicePipeline0b; - -void AlicePipeline0b_destroy(VkDevice device, AlicePipeline0b hands) { - vkDestroyPipeline(device, hands.pipeline, NULL); - vkDestroyPipelineLayout(device, hands.pipeline_layout, NULL); - vkDestroyDescriptorSetLayout(device, hands.descriptor_set_layout, NULL); -} - -AlicePipeline0b create_graphics_pipeline_0_b( - VkDevice device, SpanU8 root_dir, VkRenderPass render_pass, uint32_t subpass - ) { - VkDescriptorSetLayout my_descriptor_set_layout; - check(vkCreateDescriptorSetLayout(device, &(VkDescriptorSetLayoutCreateInfo){ - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .bindingCount = 1, - .pBindings = (VkDescriptorSetLayoutBinding[]){{ - .binding = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - }}, - }, NULL, &my_descriptor_set_layout) == VK_SUCCESS); - - VkPushConstantRange pc_ranges[] = { - { - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, - .offset = 0, .size = sizeof(mat4) - }, - { - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - .offset = sizeof(mat4), .size = sizeof(vec3) - }}; - - VkPipelineLayout pipeline_layout; - check(vkCreatePipelineLayout(device, &(VkPipelineLayoutCreateInfo){ - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .setLayoutCount = 1, - .pSetLayouts = (VkDescriptorSetLayout[]){my_descriptor_set_layout}, - .pushConstantRangeCount = ARRAY_SIZE(pc_ranges), - .pPushConstantRanges = pc_ranges, - }, NULL, &pipeline_layout) == VK_SUCCESS); - - - VecU8 vert_bin_code = read_file_by_path(VecU8_fmt("%s/gen/l_adele/alice/0sh/vert.spv", root_dir)); - VecU8 frag_bin_code = read_file_by_path(VecU8_fmt("%s/gen/l_adele/alice/0sh/frag.spv", root_dir)); - - VkVertexInputBindingDescription vertex_bindings[2] = { - { - .binding = 0, - .stride = sizeof(ShinyMeshVertex), - .inputRate = VK_VERTEX_INPUT_RATE_VERTEX, - }, - { - .binding = 1, - .stride = sizeof(ShinyMeshInstance), - .inputRate = VK_VERTEX_INPUT_RATE_INSTANCE, - } - }; - VkVertexInputAttributeDescription vertex_attributes[2 + 4 + 2 + 3] = { - { - .location = 0, .binding = 0, - .format = VK_FORMAT_R32G32B32_SFLOAT, - .offset = offsetof(ShinyMeshVertexInc, pos), - }, - { - .location = 1, .binding = 0, - .format = VK_FORMAT_R32G32B32_SFLOAT, - .offset = offsetof(ShinyMeshVertexInc, color), - }, - { - .location = 2, .binding = 0, - .format = VK_FORMAT_R32G32B32_SFLOAT, - .offset = offsetof(ShinyMeshVertex, normal), - }, - - /* This is a mat4 datatype, so it will take 4 entire 'locations' */ - { - .location = 3, .binding = 1, - .format = VK_FORMAT_R32G32B32A32_SFLOAT, - .offset = offsetof(ShinyMeshInstanceInc, model_t) + offsetof(mat4, x) - }, - { - .location = 4, .binding = 1, - .format = VK_FORMAT_R32G32B32A32_SFLOAT, - .offset = offsetof(ShinyMeshInstanceInc, model_t) + offsetof(mat4, y) - }, - { - .location = 5, .binding = 1, - .format = VK_FORMAT_R32G32B32A32_SFLOAT, - .offset = offsetof(ShinyMeshInstanceInc, model_t) + offsetof(mat4, z) - }, - { - .location = 6, .binding = 1, - .format = VK_FORMAT_R32G32B32A32_SFLOAT, - .offset = offsetof(ShinyMeshInstanceInc, model_t) + offsetof(mat4, w) - }, - { - .location = 7, .binding = 1, - .format = VK_FORMAT_R32G32B32_SFLOAT, - .offset = offsetof(ShinyMeshInstanceInc, color_on) - }, - { - .location = 8, .binding = 1, - .format = VK_FORMAT_R32G32B32_SFLOAT, - .offset = offsetof(ShinyMeshInstance, normal_t) + offsetof(mat3, x) - }, - { - .location = 9, .binding = 1, - .format = VK_FORMAT_R32G32B32_SFLOAT, - .offset = offsetof(ShinyMeshInstance, normal_t) + offsetof(mat3, y) - }, - { - .location = 10, .binding = 1, - .format = VK_FORMAT_R32G32B32_SFLOAT, - .offset = offsetof(ShinyMeshInstance, normal_t) + offsetof(mat3, z) - }, - }; - - VkPipeline pipeline = margaret_create_triangle_pipeline_one_attachment(device, render_pass, subpass, - (MargaretMostImportantPipelineOptions){ - .pipeline_layout = pipeline_layout, - .vertex_shader_code = vert_bin_code, .fragment_shader_code = frag_bin_code, - .vertexBindingDescriptionCount = ARRAY_SIZE(vertex_bindings), vertex_bindings, - .vertexAttributeDescriptionCount = ARRAY_SIZE(vertex_attributes), vertex_attributes, - .depthTestEnable = true, .depthWriteEnable = true, .blendEnable = false - }); - - return (AlicePipeline0b){.pipeline_layout = pipeline_layout, .pipeline = pipeline, .descriptor_set_layout = my_descriptor_set_layout}; -} - -VkRenderPass create_render_pass_1(VkDevice logical_device, VkFormat image_format) { - // Color attachments array for our render pass - VkAttachmentDescription all_attachments[1] = { (VkAttachmentDescription){ - .format = image_format, - .samples = VK_SAMPLE_COUNT_1_BIT, - .loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, - .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - } }; - - // For our one single render subpass - VkAttachmentReference color_attachment_refs[1] = { (VkAttachmentReference){ - .attachment = 0, - .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - } }; - - VkSubpassDescription subpasses_descr[1] = { (VkSubpassDescription){ - .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, - .colorAttachmentCount = ARRAY_SIZE(color_attachment_refs), - .pColorAttachments = color_attachment_refs, - } }; - - VkSubpassDependency subpass_dependencies[1] = { - // subpass_0_external - (VkSubpassDependency) { - .srcSubpass = VK_SUBPASS_EXTERNAL, - .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - .srcAccessMask = 0, - .dstSubpass = 0, - .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - }}; - - VkRenderPassCreateInfo render_pass_crinfo = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .attachmentCount = ARRAY_SIZE(all_attachments), - .pAttachments = all_attachments, - .subpassCount = ARRAY_SIZE(subpasses_descr), - .pSubpasses = subpasses_descr, - .dependencyCount = ARRAY_SIZE(subpass_dependencies), - .pDependencies = subpass_dependencies, - }; - VkRenderPass render_pass; - if (vkCreateRenderPass(logical_device, &render_pass_crinfo, NULL, &render_pass) != VK_SUCCESS) - abortf("vkCreateRenderPass"); - return render_pass; -} - -typedef struct { - VkPipelineLayout pipeline_layout; - VkPipeline pipeline; - VkDescriptorSetLayout descriptor_set_layout; -} AlicePipeline1; - -void AlicePipeline1_destroy(VkDevice device, AlicePipeline1 hands) { - vkDestroyPipeline(device, hands.pipeline, NULL); - vkDestroyPipelineLayout(device, hands.pipeline_layout, NULL); - vkDestroyDescriptorSetLayout(device, hands.descriptor_set_layout, NULL); -} - -AlicePipeline1 create_graphics_pipeline_1( - VkDevice device, SpanU8 root_dir, VkRenderPass render_pass, uint32_t subpass - ) { - - VkDescriptorSetLayoutBinding bindings_for_my_descr_set_layout[] = { - { - .binding = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - }, - }; - VkDescriptorSetLayout my_descriptor_set_layout; - check(vkCreateDescriptorSetLayout(device, &(VkDescriptorSetLayoutCreateInfo){ - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .bindingCount = ARRAY_SIZE(bindings_for_my_descr_set_layout), - .pBindings = bindings_for_my_descr_set_layout, - }, NULL, &my_descriptor_set_layout) == VK_SUCCESS); - - VkPushConstantRange used_region_sz_push_const[2] = { - { .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, - .offset = 0, .size = sizeof(Pipeline1PushRangeVertex) }, - { .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - .offset = sizeof(Pipeline1PushRangeVertex), .size = sizeof(Pipeline1PushRangeFragment) }, - }; - - VkPipelineLayout pipeline_layout; - check(vkCreatePipelineLayout(device, &(VkPipelineLayoutCreateInfo){ - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .setLayoutCount = 1, - .pSetLayouts = &my_descriptor_set_layout, - .pushConstantRangeCount = ARRAY_SIZE(used_region_sz_push_const), - .pPushConstantRanges = used_region_sz_push_const, - }, NULL, &pipeline_layout) == VK_SUCCESS); - - - VecU8 vert_bin_code = read_file_by_path(VecU8_fmt("%s/gen/l_adele/alice/1/vert.spv", root_dir)); - VecU8 frag_bin_code = read_file_by_path(VecU8_fmt("%s/gen/l_adele/alice/1/frag.spv", root_dir)); - - VkPipeline pipeline = margaret_create_triangle_pipeline_one_attachment(device, render_pass, subpass, - (MargaretMostImportantPipelineOptions){ - .pipeline_layout = pipeline_layout, - .vertex_shader_code = vert_bin_code, .fragment_shader_code = frag_bin_code, - .vertexBindingDescriptionCount = 0, .pVertexBindingDescriptions = NULL, - .vertexAttributeDescriptionCount = 0, .pVertexAttributeDescriptions = NULL, - }); - return (AlicePipeline1){.pipeline_layout = pipeline_layout, .pipeline = pipeline, .descriptor_set_layout = my_descriptor_set_layout}; -} - -VkFramebuffer create_IT1_framebuffer(VkDevice device, VkImageView IT1_view, VkImageView zbuffer_view, VkRenderPass render_pass_0, - U32 MAX_WIN_WIDTH, U32 MAX_WIN_HEIGHT) { - VkImageView attachments[2] = {IT1_view, zbuffer_view}; - VkFramebufferCreateInfo framebuffer_crinfo = { - .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - .renderPass = render_pass_0, - .attachmentCount = ARRAY_SIZE(attachments), - .pAttachments = attachments, - .width = MAX_WIN_WIDTH, - .height = MAX_WIN_HEIGHT, - .layers = 1 - }; - VkFramebuffer framebuffer; - if (vkCreateFramebuffer(device, &framebuffer_crinfo, NULL, &framebuffer) != VK_SUCCESS) - abortf("vkCreateFramebuffer"); - return framebuffer; -} - -void record_cmd_set_viewport_and_scissors(VkCommandBuffer command_buffer, VkExtent2D image_extent) { - vkCmdSetViewport(command_buffer, 0, 1, &(VkViewport){ - .x = 0.0f, .y = 0.0f, - .width = (float)(image_extent.width), .height = (float)(image_extent.height), - .minDepth = 0.0f, .maxDepth = 1.0f, - }); - vkCmdSetScissor(command_buffer, 0, 1, &(VkRect2D){ .offset = (VkOffset2D){0, 0}, .extent = image_extent}); -} - -typedef struct { - VkSemaphore in_frame_transfer_complete; - VkSemaphore image_available_semaphore; - VkSemaphore rendered_to_IT1_semaphore; - VkFence in_flight_fence; - // For miscellaneous uses (for init) - VkFence roxy; -} Jane_alice; - -NODISCARD Jane_alice Jane_alice_create(VkDevice device) { - return (Jane_alice){ - .in_frame_transfer_complete = margaret_create_semaphore(device), - .image_available_semaphore = margaret_create_semaphore(device), - .rendered_to_IT1_semaphore = margaret_create_semaphore(device), - .in_flight_fence = margaret_create_fence(device, true), - .roxy = margaret_create_fence(device, false), - }; -} - -void Jane_alice_destroy(VkDevice device, Jane_alice jane) { - vkDestroySemaphore(device, jane.rendered_to_IT1_semaphore, NULL); - vkDestroySemaphore(device, jane.image_available_semaphore, NULL); - vkDestroySemaphore(device, jane.in_frame_transfer_complete, NULL); - vkDestroyFence(device, jane.in_flight_fence, NULL); - vkDestroyFence(device, jane.roxy, NULL); -} - -typedef struct { - VkQueue graphics_queue; - VkQueue presentation_queue; -} UsedVulkanQueues; - - -void alice_default_callback_on_wl_keyboard_key(void* d, U32 keysym, U32 key_action){} - -void alice_default_callback_on_another_frame(void* d, float fl){} - -typedef struct Alice Alice; - -typedef struct{ - /* guest data, keysym, key action (wl_keyboard_key_state) */ - void (*on_wl_keyboard_key)(void*, U32, U32); - void (*on_another_frame)(void*, float); -} AliceCallbacks; - -void AliceCallbacks_set_default(AliceCallbacks* self){ - self->on_another_frame = alice_default_callback_on_another_frame; - self->on_wl_keyboard_key = alice_default_callback_on_wl_keyboard_key; -} - -typedef struct { - /* Memory settings */ - VkExtent2D sane_image_extent_limit; - /* Globals */ - struct wl_display *wl_display; - struct wl_registry *wl_registry; - struct wl_compositor *wl_compositor; - struct xdg_wm_base *xdg_wm_base; - struct wl_seat *wl_seat; - /* Objects */ - struct wl_surface *wl_surface; - struct wl_callback* wl_callback; - struct xdg_surface *xdg_surface; - struct xdg_toplevel *xdg_toplevel; - /* inputs */ - struct wl_pointer* pointer; - struct wl_keyboard* keyboard; - /* xkb */ - struct xkb_state* xkb_state; - struct xkb_context* xkb_context; - struct xkb_keymap* xkb_keymap; - /* app state */ - uint32_t last_frame_time; - uint32_t cur_frame_time; - int32_t width_heard; - int32_t height_heard; - int32_t width_confirmed; - int32_t height_confirmed; - bool closed; - bool first_0x80_keys[0x80]; - /* framerate counting */ - U32 frame_count_since_key; - margaret_ns_time prev_key_frame_time; -} AliceWaylandApp; - -float AliceWaylandApp_get_elapsed_time(const AliceWaylandApp* self){ - return (float)(self->cur_frame_time - self->last_frame_time) / 1000; -} - -/* They are actually MutRef, but who cares lol, we won't have such distinction here anytime soon, so we shorten - * it to Ref (whil keeping in kind that it is actually MutRef) - */ -typedef struct ListNodeAliceGenericMeshHand* RefListNodeAliceGenericMeshHand; -#include "../../../gen/l1/eve/alice/VecRefListNodeAliceGenericMeshHand.h" - -typedef struct { - ListAliceGenericMeshHand hands; - /* Familiar pattern. Todo: move familiar pattern to l1 codegen. 3 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(), - }; -} - -typedef struct ListNodeAliceShinyMeshHand* RefListNodeAliceShinyMeshHand; -#include "../../../gen/l1/eve/alice/VecRefListNodeAliceShinyMeshHand.h" - -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(), - }; -} - - -struct Alice { - AliceCallbacks callbacks; - void* guest; - AliceWaylandApp wl; - - MargaretInstanceAndItsDebug instance_and_debug; - VkSurfaceKHR surface; - VkPhysicalDevice physical_device; - MargaretChosenQueueFamilies queue_fam; - VkDevice device; - UsedVulkanQueues queues; - VkFormat zbuffer_format; - VkFormat IT1_format; - VkRenderPass render_pass_0; - AlicePipeline0a pipeline_hands_0a; - AlicePipeline0b pipeline_hands_0b; - VkRenderPass render_pass_1; - AlicePipeline1 pipeline_hands_1; - VkSampler linear_sampler; - VkSampler nearest_sampler; - VkCommandPool command_pool; - VkCommandBuffer rendering_command_buf_0; - VkCommandBuffer rendering_command_buf_1; - VkCommandBuffer transfer_command_buf; - VkCommandBuffer device_local_mem_mv_command_buf; - VkDescriptorPool descriptor_pool; // todo: write dynamic allocator wrapper for descriptor pools - - MargaretImgAllocator dev_local_images; - MargaretBufAllocator dev_local_buffers; - MargaretBufAllocator staging_buffers; - - Jane_alice jane; // todo: figure out my own design - MargaretSwapchainBundle swfb; - - AlicePipeline0UBO pipeline0_ubo; - AliceAllMeshesGeneric generic_models; - AliceAllMeshesShiny shiny_models; - AliceCamVerticalControl cam_info; - /* stuff like background color, hdr factor and - * postprocessing kernel. Mostly related to renderpass 1 */ - AliceRenderConfig rendering_config; - - MargaretImg IT1_image; - MargaretImg zbuffer_image; - - FT_Library ft_library; - LucyGlyphCache lucy_cache; - LucyRenderer lucy_renderer; - - VkImageView zbuffer_view; - VkImageView IT1_view; - VkFramebuffer IT1_framebuffer; - VkDescriptorSet descriptor_set_for_pipeline_0b; - VkDescriptorSet descriptor_set_for_pipeline_1; -}; - -ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, AliceGenericMeshPath paths){ - GenericMeshTopology topology; - if (SpanU8_is_postfix(cstr(".AliceGenericMesh"), VecU8_to_span(&paths.topology_path) )) { - topology = alice_expect_read_generic_mesh_from_file(paths.topology_path); - } else if (SpanU8_is_postfix(cstr(".obj"), VecU8_to_span(&paths.topology_path) )) { - topology = alice_expect_read_generic_mesh_from_obj_file(paths.topology_path); - } else { - abortf("Иди своей дорогой\n"); - } - - ListNodeAliceGenericMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceGenericMeshHand)); - AliceGenericMeshHand* mm = &mm_node->el; - mm->indexes = topology.indexes.len; - mm->instance_attr.count = 0; - 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(&paths.diffuse_texture_path)); - mm->pixels_normal = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&paths.normal_texture_path)); - mm->pixels_specular = TextureDataR8_read_from_png_nofail(VecU8_to_span(&paths.specular_texture_path)); - VecU8_drop(paths.diffuse_texture_path); - VecU8_drop(paths.normal_texture_path); - VecU8_drop(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 = 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->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); - for (U64 i = 0; i < topology.vertices.len; i++) { - staging_vbo[i].base = topology.vertices.buf[i]; - } - assert(topology.indexes.len % 3 == 0); - for (size_t ti = 0; ti * 3 < topology.indexes.len; ti++) { - U32 v0 = topology.indexes.buf[ti * 3 + 0]; - U32 v1 = topology.indexes.buf[ti * 3 + 1]; - U32 v2 = topology.indexes.buf[ti * 3 + 2]; - const GenericMeshVertexInc* A0 = VecGenericMeshVertexInc_at(&topology.vertices, v0); - const GenericMeshVertexInc* A1 = VecGenericMeshVertexInc_at(&topology.vertices, v1); - const GenericMeshVertexInc* A2 = VecGenericMeshVertexInc_at(&topology.vertices, v2); - vec3 dp1 = vec3_minus_vec3(A1->pos, A0->pos); - vec3 dp2 = vec3_minus_vec3(A2->pos, A0->pos); - float du1 = A1->tex.x - A0->tex.x; - float dv1 = A1->tex.y - A0->tex.y; - float du2 = A2->tex.x - A0->tex.x; - float dv2 = A2->tex.y - A0->tex.y; - vec3 norm = vec3_normalize(vec3_cross(dp1, dp2)); - mat2x3 tang_U_V = mat3x2_transpose(mat2_mul_mat3x2( - mat2_inverse(mat2_new(du1, dv1, du2, dv2)), - mat2x3_transpose((mat2x3){.x = dp1, .y = dp2}) - )); - staging_vbo[v0].norm = staging_vbo[v1].norm = staging_vbo[v2].norm = norm; - staging_vbo[v0].tang_U = staging_vbo[v1].tang_U = staging_vbo[v2].tang_U = tang_U_V.x; - staging_vbo[v0].tang_V = staging_vbo[v1].tang_V = staging_vbo[v2].tang_V = tang_U_V.y; - } - /* 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); - 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, - TextureDataR8G8B8A8_get_size_in_bytes(&mm->pixels_diffuse)); - memcpy(MargaretSubbuf_get_mapped(&mm->staging_normal_tex_buf), 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, - 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; - - 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, - .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, - .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, - .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, - .dstBinding = 0, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .pBufferInfo = &buffer_info_for_descriptor_0_in_set_0a, - }, - { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = P.p_0a_set_0, - .dstBinding = 1, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .pImageInfo = &image_info_for_descriptor_1_in_set_0a, - }, - { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = P.p_0a_set_0, - .dstBinding = 2, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .pImageInfo = &image_info_for_descriptor_2_in_set_0a, - }, - { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = P.p_0a_set_0, - .dstBinding = 3, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .pImageInfo = &image_info_for_descriptor_3_in_set_0a, - }, - }; - 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, VecU8 path){ - ShinyMeshTopology topology = alice_expect_read_shiny_mesh_from_file(path); - - ListNodeAliceShinyMeshHand* mm_node = safe_calloc(1, sizeof(ListNodeAliceShinyMeshHand)); - AliceShinyMeshHand* mm = &mm_node->el; - - mm->indexes = topology.indexes.len; - - mm->instance_attr.count = 0; - 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)); - - 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->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]; - } - assert(topology.indexes.len % 3 == 0); - for (size_t ti = 0; ti * 3 < topology.indexes.len; ti++) { - U32 v0 = topology.indexes.buf[ti * 3 + 0]; - U32 v1 = topology.indexes.buf[ti * 3 + 1]; - U32 v2 = topology.indexes.buf[ti * 3 + 2]; - vec3 p0 = VecShinyMeshVertexInc_at(&topology.vertices, v0)->pos; - vec3 p1 = VecShinyMeshVertexInc_at(&topology.vertices, v1)->pos; - vec3 p2 = VecShinyMeshVertexInc_at(&topology.vertices, v2)->pos; - 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.len >= ebo_len); - U32* staging_ebo = (U32*)MargaretSubbuf_get_mapped(&mm->staging_ebo); - memcpy(staging_ebo, topology.indexes.buf, ebo_len); - return mm_node; -} - -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); - MargaretBufAllocator_expand_or_move_old_host_visible( - &alice->staging_buffers, &self->instance_attr.staging, needed_length); - } - self->instance_attr.count = new_count; -} - -void AliceShinyMeshHand_resize_instance_arr(Alice* alice, AliceShinyMeshHand* self, U64 new_count){ - U64 needed_length = new_count * sizeof(ShinyMeshInstance); - if (self->instance_attr.staging.len < needed_length) { - MargaretBufAllocator_expand_or_move_old_host_visible( - &alice->staging_buffers, &self->instance_attr.staging, needed_length); - } - self->instance_attr.count = new_count; -} - -void AliceGenericMeshHand_set_inst(AliceGenericMeshHand* self, size_t instance, GenericMeshInstanceInc uncomp){ - assert(instance < self->instance_attr.count); - GenericMeshInstance* staging = (GenericMeshInstance*)MargaretSubbuf_get_mapped(&self->instance_attr.staging); - staging[instance].base = uncomp; - mat4 tr_inv = mat4_transpose(mat4_inverse(uncomp.model_t)); - staging[instance].normal_t = mat3_new( - tr_inv.x.x, tr_inv.y.x, tr_inv.z.x, - tr_inv.x.y, tr_inv.y.y, tr_inv.z.y, - tr_inv.x.z, tr_inv.y.z, tr_inv.z.z ); -} - -void AliceShinyMeshHand_set_inst(AliceShinyMeshHand* self, size_t instance, ShinyMeshInstanceInc uncomp){ - assert(instance < self->instance_attr.count); - ShinyMeshInstance* staging = (ShinyMeshInstance*)MargaretSubbuf_get_mapped(&self->instance_attr.staging); - staging[instance].base = uncomp; - mat4 tr_inv = mat4_transpose(mat4_inverse(uncomp.model_t)); - staging[instance].normal_t = mat3_new( - tr_inv.x.x, tr_inv.y.x, tr_inv.z.x, - tr_inv.x.y, tr_inv.y.y, tr_inv.z.y, - 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); - } - 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); - - // 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); - } - 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); - - 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; -} - -/* No buffer rerecording, no buffer beginning, no buffer ending, - * 1) It copies initial generic model and shiny model topology. Textures of generic models included - * 2) For all models and for all light sources it copies EVERYTHING. - * You won't normally need to copy every single thing, but here you have the most bold solution. - * 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); - - for (ListNodeAliceGenericMeshHand* mm_node = alice->generic_models.hands.first; mm_node; mm_node = mm_node->next) { - AliceGenericMeshHand* mm = &mm_node->el; - assert(mm->instance_attr.count * sizeof(GenericMeshInstance) <= mm->instance_attr.staging.len); - if (mm->instance_attr.count * sizeof(GenericMeshInstance) > mm->instance_attr.device_local.len) { - MargaretBufAllocator_expand_or_free_old(&alice->dev_local_buffers, &mm->instance_attr.device_local, - mm->instance_attr.count * sizeof(GenericMeshInstance)); - } - assert(mm->instance_attr.count * sizeof(GenericMeshInstance) <= mm->instance_attr.device_local.len); - if (mm->instance_attr.count) { - margaret_rec_cmd_copy_buffer_one_to_one_part(alice->transfer_command_buf, - &mm->instance_attr.staging, &mm->instance_attr.device_local, 0, - mm->instance_attr.count * sizeof(GenericMeshInstance)); - } - } - for (ListNodeAliceShinyMeshHand* mm_node = alice->shiny_models.hands.first; mm_node; mm_node = mm_node->next) { - AliceShinyMeshHand* mm = &mm_node->el; - assert(mm->instance_attr.count * sizeof(ShinyMeshInstance) <= mm->instance_attr.staging.len); - if (mm->instance_attr.count * sizeof(ShinyMeshInstance) > mm->instance_attr.device_local.len) { - MargaretBufAllocator_expand_or_free_old(&alice->dev_local_buffers, &mm->instance_attr.device_local, - mm->instance_attr.count * sizeof(ShinyMeshInstance)); - } - assert(mm->instance_attr.count * sizeof(ShinyMeshInstance) <= mm->instance_attr.device_local.len); - if (mm->instance_attr.count) { - margaret_rec_cmd_copy_buffer_one_to_one_part(alice->transfer_command_buf, - &mm->instance_attr.staging, &mm->instance_attr.device_local, 0, - mm->instance_attr.count * sizeof(ShinyMeshInstance)); - } - } - Pipeline0UBO* mem = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_ubo.staging); - assert(mem->point_light_count <= pipeline_0_ubo_point_light_max_count); - assert(mem->spotlight_count <= pipeline_0_ubo_spotlight_max_count); - - // todo: I will probably replace pipeline0ubo with ubo for length + two readonly storage buffers for light sources - // all of this is basically useless - - const MargaretSubbuf* ubo_staging = &alice->pipeline0_ubo.staging; - const MargaretSubbuf* ubo_device_local = &alice->pipeline0_ubo.device_local; - - margaret_rec_cmd_copy_buffer_one_to_one_part(alice->transfer_command_buf, ubo_staging, ubo_device_local, - offsetof(Pipeline0UBO, point_light_count), sizeof(int)); - margaret_rec_cmd_copy_buffer_one_to_one_part(alice->transfer_command_buf, ubo_staging, ubo_device_local, - offsetof(Pipeline0UBO, spotlight_count), sizeof(int)); - if (mem->point_light_count) { - margaret_rec_cmd_copy_buffer_one_to_one_part(alice->transfer_command_buf, ubo_staging, ubo_device_local, - offsetof(Pipeline0UBO, point_light_arr), sizeof(Pipeline0PointLight) * mem->point_light_count); - } - if (mem->spotlight_count) { - margaret_rec_cmd_copy_buffer_one_to_one_part(alice->transfer_command_buf, ubo_staging, ubo_device_local, - offsetof(Pipeline0UBO, spotlight_arr), sizeof(Pipeline0Spotlight) * mem->spotlight_count); - } -} - - -void alice_reset_and_record_command_buffer_0(Alice* alice, mat4 proj_cam_t) { - margaret_reset_and_begin_command_buffer(alice->rendering_command_buf_0); - - vec4 clear_color = alice->rendering_config.clear_color; - VkExtent2D image_extent = alice->swfb.extent; - vkCmdBeginRenderPass(alice->rendering_command_buf_0, &(VkRenderPassBeginInfo){ - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderPass = alice->render_pass_0, - .framebuffer = alice->IT1_framebuffer, - .renderArea.offset = (VkOffset2D){0, 0}, - .renderArea.extent = image_extent, - .clearValueCount = 2, - .pClearValues = (VkClearValue[]){ - {.color.float32 = {clear_color.x, clear_color.y, clear_color.z, clear_color.w}}, - {.depthStencil = {.depth = 1, .stencil = 0}} - }, - }, VK_SUBPASS_CONTENTS_INLINE); - - vkCmdBindPipeline(alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0a.pipeline); - record_cmd_set_viewport_and_scissors(alice->rendering_command_buf_0, image_extent); - vkCmdPushConstants(alice->rendering_command_buf_0, alice->pipeline_hands_0a.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, - 0, sizeof(mat4), &proj_cam_t); - vkCmdPushConstants(alice->rendering_command_buf_0, alice->pipeline_hands_0a.pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, - sizeof(mat4), sizeof(vec3), &alice->cam_info.cam.pos); - - for (ListNodeAliceGenericMeshHand* mm_node = alice->generic_models.hands.first; mm_node; mm_node = mm_node->next) { - 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_inst_attr = &model->instance_attr.device_local; - const MargaretSubbuf* dev_local_ebo = &model->ebo; - // const - 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 }); - vkCmdBindIndexBuffer(alice->rendering_command_buf_0, MargaretSubbuf_get_buffer(dev_local_ebo), dev_local_ebo->start, - VK_INDEX_TYPE_UINT32); - vkCmdBindDescriptorSets( - alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0a.pipeline_layout, 0, - 1, &model_indiv_descriptor_set_0, 0, NULL); - vkCmdDrawIndexed(alice->rendering_command_buf_0, model->indexes, model->instance_attr.count, 0, 0, 0); - } - - vkCmdBindPipeline(alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0b.pipeline); - record_cmd_set_viewport_and_scissors(alice->rendering_command_buf_0, image_extent); - vkCmdPushConstants(alice->rendering_command_buf_0, alice->pipeline_hands_0b.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, - 0, sizeof(mat4), &proj_cam_t); - vkCmdPushConstants(alice->rendering_command_buf_0, alice->pipeline_hands_0b.pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, - sizeof(mat4), sizeof(vec3), &alice->cam_info.cam.pos); - vkCmdBindDescriptorSets( - alice->rendering_command_buf_0, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_0b.pipeline_layout, 0, - 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_inst_attr = &model->instance_attr.device_local; - 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 }); - vkCmdBindIndexBuffer(alice->rendering_command_buf_0, MargaretSubbuf_get_buffer(dev_local_ebo), dev_local_ebo->start, - VK_INDEX_TYPE_UINT32); - vkCmdDrawIndexed(alice->rendering_command_buf_0, model->indexes, model->instance_attr.count, 0, 0, 0); - } - - vkCmdEndRenderPass(alice->rendering_command_buf_0); - margaret_end_command_buffer(alice->rendering_command_buf_0); -} - -void alice_reset_and_record_command_buffer_1( - Alice* alice, VkFramebuffer swapchain_image_framebuffer - ) { - margaret_reset_and_begin_command_buffer(alice->rendering_command_buf_1); - - VkExtent2D image_extent = alice->swfb.extent; - vkCmdBeginRenderPass(alice->rendering_command_buf_1, &(VkRenderPassBeginInfo){ - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderPass = alice->render_pass_1, - .framebuffer = swapchain_image_framebuffer, - .renderArea.offset = (VkOffset2D){0, 0}, - .renderArea.extent = image_extent, - }, VK_SUBPASS_CONTENTS_INLINE); - vkCmdBindPipeline(alice->rendering_command_buf_1, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_1.pipeline); - - record_cmd_set_viewport_and_scissors(alice->rendering_command_buf_1, image_extent); - vkCmdBindDescriptorSets( - alice->rendering_command_buf_1, VK_PIPELINE_BIND_POINT_GRAPHICS, alice->pipeline_hands_1.pipeline_layout, 0, - 1, &alice->descriptor_set_for_pipeline_1, 0, NULL); - - Pipeline1PushRangeVertex reg_and_params_vertex = {.win_scale = { - (float)image_extent.width / (float)alice->wl.sane_image_extent_limit.width, - (float)image_extent.height / (float)alice->wl.sane_image_extent_limit.height}, - }; - Pipeline1PushRangeFragment reg_and_params_fragment = { - .gamma_correction_factor = alice->rendering_config.gamma_correction_factor, - .hdr_factor = alice->rendering_config.hdr_factor, - .lsd_factor = alice->rendering_config.lsd_factor, - .anim_time = 0 /* Not used */ - }; - vkCmdPushConstants(alice->rendering_command_buf_1, alice->pipeline_hands_1.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, - 0, sizeof(Pipeline1PushRangeVertex), ®_and_params_vertex); - vkCmdPushConstants(alice->rendering_command_buf_1, alice->pipeline_hands_1.pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, - sizeof(Pipeline1PushRangeVertex), sizeof(Pipeline1PushRangeFragment), ®_and_params_fragment); - vkCmdDraw(alice->rendering_command_buf_1, 3, 1, 0, 0); - - LucyRenderer_another_frame_rec_drawing(&alice->lucy_renderer, alice->rendering_command_buf_1, image_extent); - - vkCmdEndRenderPass(alice->rendering_command_buf_1); - margaret_end_command_buffer(alice->rendering_command_buf_1); -} - -void recreate_swapchain(Alice *alice) { - // We are stopping program and rebuilding our sem+sem+fence synchronization mechanism - vkDeviceWaitIdle(alice->device); // todo: AAAAAAAAAAAAAAA this is all so so wrong AAAAAAAA - Jane_alice_destroy(alice->device, alice->jane); - alice->jane = Jane_alice_create(alice->device); - VkSwapchainKHR old_swapchain = MargaretSwapchainBundle_pop_swapchain_drop_rest( - alice->device, alice->swfb); - // old swfb is 83% dropped - VkExtent2D extent = alice->wl.width_confirmed <= 0 || alice->wl.height_confirmed <= 0 ? - alice->wl.sane_image_extent_limit : (VkExtent2D){ alice->wl.width_confirmed, alice->wl.height_confirmed }; - - ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details( - alice->physical_device, alice->surface, extent); - if (swapchain_details_res.variant != Result_Ok) - abortf("swapchain_details_res.variant != Result_Ok"); - MargaretChosenSwapchainDetails swapchain_details = swapchain_details_res.ok; - MargaretSwapchainBundle new_swfb = MargaretSwapchainBundle_new(alice->device, alice->queue_fam, - swapchain_details, alice->surface, alice->render_pass_1, alice->swfb.swapchain); - vkDestroySwapchainKHR(alice->device, old_swapchain, NULL); - // Now old swfb is 100% dropped - alice->swfb = new_swfb; -} - -/* It creates image views, descriptor sets, framebuffers. But not for generic models. - * If we ever gonna do defragmentation, this step would have to be repeated */ -void alice_create_mem_dependant_vk_obj(Alice* alice){ - alice->zbuffer_view = margaret_create_view_for_image(alice->device, alice->zbuffer_image.a.image, - alice->zbuffer_format, VK_IMAGE_ASPECT_DEPTH_BIT); - alice->IT1_view = margaret_create_view_for_image(alice->device, alice->IT1_image.a.image, - alice->IT1_format, VK_IMAGE_ASPECT_COLOR_BIT); - alice->IT1_framebuffer = create_IT1_framebuffer(alice->device, - alice->IT1_view, alice->zbuffer_view, alice->render_pass_0, - alice->wl.sane_image_extent_limit.width, alice->wl.sane_image_extent_limit.height); - - alice->descriptor_set_for_pipeline_0b = margaret_allocate_descriptor_set( - alice->device, alice->descriptor_pool, alice->pipeline_hands_0b.descriptor_set_layout); - alice->descriptor_set_for_pipeline_1 = margaret_allocate_descriptor_set( - alice->device, alice->descriptor_pool, alice->pipeline_hands_1.descriptor_set_layout); - - // todo: separate set0 and set 1 - VkDescriptorBufferInfo buffer_info_for_descriptor_0_in_set_0b = { - .buffer = MargaretSubbuf_get_buffer(&alice->pipeline0_ubo.device_local), - .offset = alice->pipeline0_ubo.device_local.start, .range = sizeof(Pipeline0UBO), - }; - VkDescriptorImageInfo image_info_for_descriptor_0_in_set_1 = { - .sampler = alice->nearest_sampler, .imageView = alice->IT1_view, - .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - }; - VkWriteDescriptorSet writes_in_descriptor_sets[] = { - { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = alice->descriptor_set_for_pipeline_0b, - .dstBinding = 0, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .pBufferInfo = &buffer_info_for_descriptor_0_in_set_0b, - }, - - { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = alice->descriptor_set_for_pipeline_1, - .dstBinding = 0, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .pImageInfo = &image_info_for_descriptor_0_in_set_1, - }, - }; - vkUpdateDescriptorSets(alice->device, ARRAY_SIZE(writes_in_descriptor_sets), writes_in_descriptor_sets, 0, NULL); -} - -/* Needed for defragmentation of memory */ -void destroy_vulkan_reference_objects(Alice* alice){ - abortf("Please don't\n"); - // todo: vkdestro all the views all the framebuffers - // todo: drop everything, -} - -void alice_frame_drawing(Alice* alice) { - check(vkWaitForFences(alice->device, 1, &alice->jane.in_flight_fence, VK_TRUE, UINT64_MAX) == VK_SUCCESS); - check(vkResetFences(alice->device, 1, &alice->jane.in_flight_fence) == VK_SUCCESS); - uint32_t ij; - VkResult aq_ret; - and_again: - aq_ret = vkAcquireNextImageKHR( - alice->device, alice->swfb.swapchain, - UINT64_MAX, alice->jane.image_available_semaphore, VK_NULL_HANDLE, &ij - ); - if (aq_ret == VK_ERROR_OUT_OF_DATE_KHR || aq_ret == VK_SUBOPTIMAL_KHR) { - fprintf(stderr, "vkAcquireNextImageKHR in { VK_ERROR_OUT_OF_DATE_KHR, VK_SUBOPTIMAL_KHR }\n"); - recreate_swapchain(alice); - goto and_again; - } else if (aq_ret != VK_SUCCESS) { - abortf("vkAcquireNextImageKHR"); - } - - mat4 projection_matrix = marie_perspective_projection_fov_mat4( - (float)alice->wl.width_confirmed, (float)alice->wl.height_confirmed, - alice->cam_info.cam.fov, 0.01f, 1000); - mat4 camera_rotation_matrix = marie_mat3_to_mat4_transposed(alice->cam_info.cam.cam_basis); - mat4 camera_translation_matrix = marie_translation_mat4(vec3_minus(alice->cam_info.cam.pos)); - mat4 t_mat = mat4_mul_mat4(projection_matrix, mat4_mul_mat4(camera_rotation_matrix, camera_translation_matrix)); - - 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); - AliceScene__another_frame(alice); - LucyGlyphCache_another_frame(&alice->lucy_cache); - LucyRenderer_another_frame(&alice->lucy_renderer); - margaret_end_command_buffer(alice->transfer_command_buf); - alice_reset_and_record_command_buffer_0(alice, t_mat); - alice_reset_and_record_command_buffer_1(alice, *VecVkFramebuffer_at(&alice->swfb.framebuffers, ij)); - - check(vkQueueSubmit(alice->queues.graphics_queue, 1, &(VkSubmitInfo){ - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .commandBufferCount = 1, - .pCommandBuffers = (VkCommandBuffer[]){ alice->transfer_command_buf }, - .signalSemaphoreCount = 1, - .pSignalSemaphores = (VkSemaphore[]){ alice->jane.in_frame_transfer_complete }, - }, NULL) == VK_SUCCESS); - - check(vkQueueSubmit(alice->queues.graphics_queue, 1, &(VkSubmitInfo){ - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - - .waitSemaphoreCount = 1, - .pWaitSemaphores = (VkSemaphore[]){alice->jane.in_frame_transfer_complete}, - .pWaitDstStageMask = (VkPipelineStageFlags[]){ - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT - }, - - .commandBufferCount = 1, - .pCommandBuffers = (VkCommandBuffer[]){ alice->rendering_command_buf_0 }, - - .signalSemaphoreCount = 1, - .pSignalSemaphores = (VkSemaphore[]){ alice->jane.rendered_to_IT1_semaphore }, - }, NULL) == VK_SUCCESS); - - check(vkQueueSubmit(alice->queues.graphics_queue, 1, &(VkSubmitInfo){ - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .waitSemaphoreCount = 2, - .pWaitSemaphores = (VkSemaphore[]){ - alice->jane.image_available_semaphore, alice->jane.rendered_to_IT1_semaphore }, - .pWaitDstStageMask = (VkPipelineStageFlags[]){ - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT }, - .commandBufferCount = 1, - .pCommandBuffers = (VkCommandBuffer[]){ alice->rendering_command_buf_1 }, - .signalSemaphoreCount = 1, - .pSignalSemaphores = (VkSemaphore[]){ - *VecVkSemaphore_at(&alice->swfb.rendering_finished_here_semaphores, ij) }, - }, alice->jane.in_flight_fence) == VK_SUCCESS); - - VkPresentInfoKHR present_info = { - .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, - .waitSemaphoreCount = 1, - .pWaitSemaphores = (VkSemaphore[]){ - *VecVkSemaphore_at(&alice->swfb.rendering_finished_here_semaphores, ij) }, - .swapchainCount = 1, - .pSwapchains = (VkSwapchainKHR[]){ alice->swfb.swapchain }, - .pImageIndices = (U32[]){ ij }, - .pResults = NULL, - }; - VkResult present_ret = vkQueuePresentKHR(alice->queues.presentation_queue, &present_info); - if (present_ret == VK_ERROR_OUT_OF_DATE_KHR || present_ret == VK_SUBOPTIMAL_KHR) { - fprintf(stderr, "vkQueuePresentKHR: VK_ERROR_OUT_OF_DATE_KHR or \n"); - check(vkWaitForFences(alice->device, 1, &alice->jane.in_flight_fence, VK_TRUE, UINT64_MAX) == VK_SUCCESS); - check(vkResetFences(alice->device, 1, &alice->jane.in_flight_fence) == VK_SUCCESS); - recreate_swapchain(alice); - goto and_again; - } else if (present_ret != VK_SUCCESS) { - abortf("vkQueuePresentKHR"); - } - - margaret_ns_time frame_B0 = margaret_clock_gettime_monotonic_raw(); - alice->wl.frame_count_since_key++; - if (margaret_ns_time_sec_diff(alice->wl.prev_key_frame_time, frame_B0) > 1.0) { - float fps = (float)alice->wl.frame_count_since_key / margaret_ns_time_sec_diff(alice->wl.prev_key_frame_time, frame_B0); - printf("FPS: %0.1lf\n", fps); - alice->wl.frame_count_since_key = 0; - alice->wl.prev_key_frame_time = frame_B0; - } -} - -static void alice_mainloop_h_xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial){ - Alice* alice = data; - printf("XDG surface configured! (%d %d)\n", alice->wl.width_heard, alice->wl.height_heard); - alice->wl.width_confirmed = alice->wl.width_heard; - alice->wl.height_confirmed = alice->wl.height_heard; - xdg_surface_ack_configure(xdg_surface, serial); - // todo: omg, I need to fix this crap for real, like, this is all so wrong - recreate_swapchain(alice); - alice_frame_drawing(alice); -} - -static const struct xdg_surface_listener xdg_surface_listener = { - .configure = alice_mainloop_h_xdg_surface_configure, -}; - -static void alice_mainloop_h_xdg_toplevel_configure( - void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states - ){ - Alice* alice = data; - uint32_t *conf_state; - wl_array_for_each(conf_state, states) { - printf("A state of xdg toplevel: %u\n", *conf_state); - } - printf("XDG toplevel configured to (%d %d)\n", width, height); - if (width <= 0 || height <= 0) - return; - alice->wl.width_heard = width; - alice->wl.height_heard = height; -} - -static void alice_mainloop_h_xdg_toplevel_close(void *data, struct xdg_toplevel *toplevel){ - Alice* alice = data; - alice->wl.closed = true; -} - -static const struct xdg_toplevel_listener alice_mainloop_h_xdg_toplevel_listener = { - .configure = alice_mainloop_h_xdg_toplevel_configure, - .close = alice_mainloop_h_xdg_toplevel_close, -}; - -static void alice_mainloop_h_xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial){ - xdg_wm_base_pong(xdg_wm_base, serial); -} - -static const struct xdg_wm_base_listener alice_mainloop_h_xdg_wm_base_listener = { - .ping = alice_mainloop_h_xdg_wm_base_ping, -}; - -static void alice_mainloop_h_wl_keyboard_keymap( - void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size - ) { - Alice* alice = data; - if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) - abortf("O_o"); - char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); - if (map_shm == MAP_FAILED) - abortf("Couldn't mmap new keymap ha-ha\n"); - - xkb_keymap_unref(alice->wl.xkb_keymap); - xkb_state_unref(alice->wl.xkb_state); - alice->wl.xkb_keymap = xkb_keymap_new_from_string( - alice->wl.xkb_context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); - munmap(map_shm, size); - close(fd); - alice->wl.xkb_state = xkb_state_new(alice->wl.xkb_keymap); - printf("Keymap changed!\n"); - memset(&alice->wl.first_0x80_keys, 0, sizeof(alice->wl.first_0x80_keys)); -} - -static void alice_mainloop_h_wl_keyboard_enter( - void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys - ) { - Alice* alice = data; - printf("keyboard enter; keys pressed are:\n"); - uint32_t *key; - wl_array_for_each(key, keys) { - uint32_t actual_key = *key + 8; - xkb_keysym_t sym = xkb_state_key_get_one_sym(alice->wl.xkb_state, actual_key); - if (sym < 0x80) - alice->wl.first_0x80_keys[sym] = true; - } -} - -static void alice_mainloop_h_wl_keyboard_leave( - void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface - ) { - Alice* alice = data; - memset(&alice->wl.first_0x80_keys, 0, sizeof(alice->wl.first_0x80_keys)); -} - -static void alice_mainloop_h_wl_keyboard_key( - void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t key_action - ) { - Alice* alice = data; - uint32_t actual_key = key + 8; - /* It actually could be nokey keysym. You never know without checking */ - xkb_keysym_t keysym = xkb_state_key_get_one_sym(alice->wl.xkb_state, actual_key); - if (keysym < 0x80 && key_action == WL_KEYBOARD_KEY_STATE_RELEASED) { - alice->wl.first_0x80_keys[keysym] = false; - } else if (keysym < 0x80 && key_action == WL_KEYBOARD_KEY_STATE_PRESSED) { - alice->wl.first_0x80_keys[keysym] = true; - } - alice->callbacks.on_wl_keyboard_key(alice->guest, keysym, key_action); - if (key_action == WL_KEYBOARD_KEY_STATE_RELEASED) { - if (keysym == XKB_KEY_1) { - } else if (keysym == XKB_KEY_2) { - alice->rendering_config.hdr_factor /= 1.05f; - printf("hdr factor decreased to %f\n", alice->rendering_config.hdr_factor); - } else if (keysym == XKB_KEY_3) { - alice->rendering_config.hdr_factor *= 1.05f; - printf("hdr factor increased to %f\n", alice->rendering_config.hdr_factor); - } - } -} - -static void alice_mainloop_h_wl_keyboard_modifiers( - void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, - uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group - ) { - Alice* alice = data; - xkb_state_update_mask(alice->wl.xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group); -} - -static void alice_mainloop_h_wl_keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, int32_t rate, int32_t delay){ - printf("Repeat timings changed: rate = %d, delay = %d\n", rate, delay); -} - -static const struct wl_keyboard_listener alice_mainloop_h_wl_keyboard_listener = { - .keymap = alice_mainloop_h_wl_keyboard_keymap, - .enter = alice_mainloop_h_wl_keyboard_enter, - .leave = alice_mainloop_h_wl_keyboard_leave, - .key = alice_mainloop_h_wl_keyboard_key, - .modifiers = alice_mainloop_h_wl_keyboard_modifiers, - .repeat_info = alice_mainloop_h_wl_keyboard_repeat_info, -}; - - -static void alice_mainloop_h_wl_pointer_enter( - void *data, struct wl_pointer *wl_pointer, uint32_t serial, - struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y - ) { -} - -static void alice_mainloop_h_wl_pointer_leave( - void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface - ) { -} - -static void alice_mainloop_h_wl_pointer_motion( - void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y - ) { - Alice* alice = data; - AliceCamVerticalControl_update_direction(&alice->cam_info, - alice->wl.width_confirmed, alice->wl.height_confirmed, - (float)surface_x / 256.f, (float)surface_y / 256.f); -} - -static void alice_mainloop_h_wl_pointer_button( - void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t btn_action - ) { - Alice* alice = data; -} - -static void alice_mainloop_h_wl_pointer_axis( - void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value - ) { - Alice* alice = data; -} - -static void alice_mainloop_h_wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { - Alice* alice = data; -} - -const struct wl_pointer_listener alice_mainloop_h_wl_pointer_listener = { - .enter = alice_mainloop_h_wl_pointer_enter, - .leave = alice_mainloop_h_wl_pointer_leave, - .motion = alice_mainloop_h_wl_pointer_motion, - .button = alice_mainloop_h_wl_pointer_button, - .axis = alice_mainloop_h_wl_pointer_axis, - .frame = alice_mainloop_h_wl_pointer_frame -}; - -static void alice_mainloop_h_wl_seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) { - Alice* alice = data; - if (capabilities & WL_SEAT_CAPABILITY_POINTER) { - alice->wl.pointer = wl_seat_get_pointer(wl_seat); - if (!alice->wl.pointer) - abortf("wl_seat_get_pointer\n"); - wl_pointer_add_listener(alice->wl.pointer, &alice_mainloop_h_wl_pointer_listener, alice); - } - if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { - alice->wl.keyboard = wl_seat_get_keyboard(wl_seat); - if (!alice->wl.keyboard) - abortf("wl_seat_get_keyboard\n"); - wl_keyboard_add_listener(alice->wl.keyboard, &alice_mainloop_h_wl_keyboard_listener, alice); - } -} - -static void alice_mainloop_h_wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) { - printf("Our seat name: %s\n", name); -} - -static const struct wl_seat_listener alice_mainloop_h_wl_seat_listener = { - .capabilities = alice_mainloop_h_wl_seat_capabilities, - .name = alice_mainloop_h_wl_seat_name, -}; - -static void alice_mainloop_h_wl_registry_global( - void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, uint32_t version - ) { - Alice* alice = data; - if (strcmp(interface, wl_compositor_interface.name) == 0) { - alice->wl.wl_compositor = wl_registry_bind(wl_registry, name, &wl_compositor_interface, 4); - if (!alice->wl.wl_compositor) - abortf("wl_registry_bind\n"); - } else if (strcmp(interface, xdg_wm_base_interface.name) == 0) { - alice->wl.xdg_wm_base = wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1); - if (!alice->wl.xdg_wm_base) - abortf("wl_registry_bind\n"); - xdg_wm_base_add_listener(alice->wl.xdg_wm_base, &alice_mainloop_h_xdg_wm_base_listener, alice); - } else if (strcmp(interface, wl_seat_interface.name) == 0) { - if (alice->wl.wl_seat) { - printf("We got second seat, but we only need one\n"); - return; - } - alice->wl.wl_seat = wl_registry_bind(wl_registry, name, &wl_seat_interface, 4); - if (!alice->wl.wl_seat) - abortf("wl_registry_bind\n"); - wl_seat_add_listener(alice->wl.wl_seat, &alice_mainloop_h_wl_seat_listener, alice); - } -} - -static void alice_mainloop_h_wl_registry_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name){ - -} - -static const struct wl_registry_listener alice_mainloop_h_wl_registry_listener = { - .global = alice_mainloop_h_wl_registry_global, - .global_remove = alice_mainloop_h_wl_registry_global_remove, -}; - -static const struct wl_callback_listener alice_mainloop_h_wl_surface_frame_listener; - -static void alice_mainloop_h_wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time){ - Alice* alice = data; - wl_callback_destroy(cb); - alice->wl.wl_callback = wl_surface_frame(alice->wl.wl_surface); - if (!alice->wl.wl_callback) - abortf("wl_surface_frame\n"); - wl_callback_add_listener(alice->wl.wl_callback, &alice_mainloop_h_wl_surface_frame_listener, alice); - - alice->wl.cur_frame_time = time; - alice_frame_drawing(alice); - alice->wl.last_frame_time = time; -} - -static const struct wl_callback_listener alice_mainloop_h_wl_surface_frame_listener = { - .done = alice_mainloop_h_wl_surface_frame_done, -}; - -Alice* Alice_new(){ - Alice* alice = safe_malloc(sizeof(Alice)); - SpanU8 root_dir = cstr("."); - SpanU8 GPU = cstr("nvidia"); - SpanU8 bugged_GPU = cstr("nothere"); - bool ENABLE_VALIDATION_LAYERS = true; - const U32 MAX_WIN_WIDTH = 1920; - const U32 MAX_WIN_HEIGHT = 1080; - AliceCallbacks_set_default(&alice->callbacks); - - alice->wl.sane_image_extent_limit = (VkExtent2D){MAX_WIN_WIDTH, MAX_WIN_HEIGHT}; - - alice->wl.wl_display = wl_display_connect(NULL); - if (!alice->wl.wl_display) - abortf("Could not connect"); - alice->wl.wl_registry = wl_display_get_registry(alice->wl.wl_display); - if (!alice->wl.wl_registry) - abortf("wl_display_get_registry"); - wl_registry_add_listener(alice->wl.wl_registry, &alice_mainloop_h_wl_registry_listener, alice); - wl_display_roundtrip(alice->wl.wl_display); - if (!alice->wl.wl_compositor) - abortf("No wl_compositor"); - if (!alice->wl.xdg_wm_base) - abortf("No xdg_wm_base"); - alice->wl.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - if (!alice->wl.xkb_context) - abortf("xkb_context_new\n"); - alice->wl.wl_surface = wl_compositor_create_surface(alice->wl.wl_compositor); - if (!alice->wl.wl_surface) - abortf("wl_compositor_create_surface\n"); - alice->wl.xdg_surface = xdg_wm_base_get_xdg_surface( - alice->wl.xdg_wm_base, alice->wl.wl_surface); - if (!alice->wl.xdg_surface) - abortf("xdg_wm_base_get_xdg_surface\n"); - xdg_surface_add_listener(alice->wl.xdg_surface, &xdg_surface_listener, alice); - alice->wl.xdg_toplevel = xdg_surface_get_toplevel(alice->wl.xdg_surface); - if (!alice->wl.xdg_toplevel) - abortf("xdg_surface_get_toplevel\n"); - xdg_toplevel_add_listener(alice->wl.xdg_toplevel, &alice_mainloop_h_xdg_toplevel_listener, alice); - xdg_toplevel_set_title(alice->wl.xdg_toplevel, "r3"); - xdg_toplevel_set_app_id(alice->wl.xdg_toplevel, "r3"); - wl_surface_commit(alice->wl.wl_surface); - - alice->wl.wl_callback = wl_surface_frame(alice->wl.wl_surface); - if (!alice->wl.wl_callback) - abortf("wl_surface_frame\n"); - wl_callback_add_listener(alice->wl.wl_callback, &alice_mainloop_h_wl_surface_frame_listener, alice); - alice->wl.cur_frame_time = alice->wl.last_frame_time = 0; - - alice->instance_and_debug = MargaretInstanceAndItsDebug_new(ENABLE_VALIDATION_LAYERS); - VkInstance instance = alice->instance_and_debug.instance; - - // print_instance_available_extensions(instance); - // print_instance_available_layers(instance); - - alice->surface = margaret_create_surface(instance, alice->wl.wl_display, alice->wl.wl_surface); - - alice->physical_device = margaret_select_one_physical_device( - instance, alice->surface, GPU, bugged_GPU, alice->wl.sane_image_extent_limit); - - // print_physical_device_available_extensions(physical_device); - - ResultMargaretChosenQueueFamiliesOrSpanU8 queue_fam_res = margaret_choose_good_queue_families( - alice->physical_device, alice->surface); - if (queue_fam_res.variant != Result_Ok) - abortf("queue_fam_res.variant != Result_Ok"); - alice->queue_fam = queue_fam_res.ok; - - 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); - } - - ResultMargaretChosenSwapchainDetailsOrSpanU8 swapchain_details_res = margaret_choose_swapchain_details( - alice->physical_device, alice->surface, alice->wl.sane_image_extent_limit); - if (swapchain_details_res.variant != Result_Ok) - abortf("swapchain_details_res.variant != Result_Ok"); - - OptionVkFormat zbuffer_format_found = margaret_find_supported_zbuffer_format(alice->physical_device); - alice->zbuffer_format = OptionVkFormat_expect(zbuffer_format_found); - OptionVkFormat IT1_format_found = margaret_find_supported_hdr_buffer_format(alice->physical_device); - alice->IT1_format = OptionVkFormat_expect(IT1_format_found); - - alice->render_pass_0 = create_render_pass_0(alice->device, alice->IT1_format, alice->zbuffer_format); - alice->pipeline_hands_0a = create_graphics_pipeline_0(alice->device, root_dir, alice->render_pass_0, 0); - alice->pipeline_hands_0b = create_graphics_pipeline_0_b(alice->device, root_dir, alice->render_pass_0, 0); - - alice->render_pass_1 = create_render_pass_1(alice->device, swapchain_details_res.ok.surface_format.format); - alice->pipeline_hands_1 = create_graphics_pipeline_1(alice->device, root_dir, alice->render_pass_1, 0); - - // These samplers are global for a lot of my future textures - alice->linear_sampler = margaret_create_sampler(alice->physical_device, alice->device, true); - alice->nearest_sampler = margaret_create_sampler(alice->physical_device, alice->device, false); - - alice->command_pool = margaret_create_resettable_command_pool(alice->device, alice->queue_fam.for_graphics); - alice->rendering_command_buf_0 = margaret_allocate_command_buffer(alice->device, alice->command_pool); - alice->rendering_command_buf_1 = margaret_allocate_command_buffer(alice->device, alice->command_pool); - alice->transfer_command_buf = margaret_allocate_command_buffer(alice->device, alice->command_pool); - alice->device_local_mem_mv_command_buf = margaret_allocate_command_buffer(alice->device, alice->command_pool); - - // todo: write a descriptor set allocator (in Margaret) that manages dynamic descript or pool allocatrinonsasdasdasd - alice->descriptor_pool = margaret_create_descriptor_set_pool(alice->device, 100, 100, 100); - - /* Here we search physical device memory types for the one with host-visible flag and the other with device-local flag */ - VkPhysicalDeviceMemoryProperties mem_properties; - vkGetPhysicalDeviceMemoryProperties(alice->physical_device, &mem_properties); - const VkMemoryPropertyFlags host_visible_coherent = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - const VkMemoryPropertyFlags device_local = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - int mem_type_id_host_visible_coherent = -1; - for (int i = 0; i < (int)mem_properties.memoryTypeCount; i++) { - if ((mem_properties.memoryTypes[i].propertyFlags & host_visible_coherent) == host_visible_coherent) { - mem_type_id_host_visible_coherent = i; - break; - } - } - if (mem_type_id_host_visible_coherent == -1) { - abortf("Can't find host visible + host coherent memory\n"); - } - int mem_type_id_device_local = -1; - for (int i = 0; i < (int)mem_properties.memoryTypeCount; i++) { - if ((mem_properties.memoryTypes[i].propertyFlags & device_local) == device_local) { - mem_type_id_device_local = i; - break; - } - } - if (mem_type_id_device_local == -1) { - abortf("Can't find device local memory\n"); - } - - alice->staging_buffers = MargaretBufAllocator_new(alice->device, alice->physical_device, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - mem_type_id_host_visible_coherent, 3, true, 16); - - // 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 */, - mem_type_id_device_local, 6, false, 10000); - - alice->dev_local_images = MargaretImgAllocator_new(alice->device, alice->physical_device, - mem_type_id_device_local, 16000000); - - alice->jane = Jane_alice_create(alice->device); - /* Luckily, swapchain image allocation is not managed by me */ - alice->swfb = MargaretSwapchainBundle_new( - alice->device, alice->queue_fam, swapchain_details_res.ok, - alice->surface, alice->render_pass_1, NULL); - - alice->generic_models = AliceAllMeshesGeneric_new(); - alice->shiny_models = AliceAllMeshesShiny_new(); - alice->pipeline0_ubo.staging = MargaretBufAllocator_alloc(&alice->staging_buffers, sizeof(Pipeline0UBO)); - alice->pipeline0_ubo.device_local = MargaretBufAllocator_alloc(&alice->dev_local_buffers, sizeof(Pipeline0UBO)); - Pipeline0UBO* ubo0 = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_ubo.staging); - ubo0->point_light_count = ubo0->spotlight_count = 0; - - alice->cam_info = AliceCamVerticalControl_new(); - alice->rendering_config = AliceRenderConfig_new(); - - alice->IT1_image = MargaretImgAllocator_alloc(&alice->dev_local_images, - MAX_WIN_WIDTH, MAX_WIN_HEIGHT, alice->IT1_format, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); - alice->zbuffer_image = MargaretImgAllocator_alloc(&alice->dev_local_images, - MAX_WIN_WIDTH, MAX_WIN_HEIGHT, alice->zbuffer_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); - - MargaretEngineReference engine_reference = { - .device = alice->device, .physical_device = alice->physical_device, .transfer_cmd_buffer = alice->transfer_command_buf, - .dev_local_images = &alice->dev_local_images, .dev_local_buffers = &alice->dev_local_buffers, - .staging_buffers = &alice->staging_buffers, .descriptor_pool = alice->descriptor_pool, - .linear_sampler = alice->linear_sampler, .nearest_sampler = alice->nearest_sampler - }; - - FT_Error ft_init_err = FT_Init_FreeType(&alice->ft_library); - if (ft_init_err) - abortf("Can't init free type library\n"); - - alice->lucy_cache = LucyGlyphCache_new(engine_reference); - - alice->lucy_renderer = LucyRenderer_new(engine_reference, &alice->lucy_cache, root_dir, alice->render_pass_1, 0); - - // Creating framebuffer for IT1, image views for IT1 and zbuffer - // Creating descriptor set for pipeline 0b and for pipeline 1 (containing IT1 sampler) - alice_create_mem_dependant_vk_obj(alice); - - alice->wl.prev_key_frame_time = margaret_clock_gettime_monotonic_raw(); - alice->wl.frame_count_since_key = 0; - /* Alice initialization complete */ - return alice; -} - -void Alice_set_point_light_count(Alice* alice, int new_count){ - Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_ubo.staging); - assert(new_count <= pipeline_0_ubo_point_light_max_count); - ubo->point_light_count = new_count; -} - -void Alice_set_point_light(Alice* alice, int index, Pipeline0PointLight data){ - Pipeline0UBO* ubo = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_ubo.staging); - assert(index < pipeline_0_ubo_point_light_max_count); - ubo->point_light_arr[index] = data; -} - -/* This function actually consumes alice handler. Alice must not be used after */ -void Alice_mainloop(Alice* alice, const AliceCallbacks* callbacks) { - alice->callbacks.on_wl_keyboard_key = callbacks->on_wl_keyboard_key; - alice->callbacks.on_another_frame = callbacks->on_another_frame; - printf("ENTERING WAYLAND MAINLOOP\n"); - while (wl_display_dispatch(alice->wl.wl_display) >= 0) { - if (alice->wl.closed) - break; - } - vkDeviceWaitIdle(alice->device); - - // The End - // vkDestroyDescriptorPool(vk->device, vk->descriptor_pool, NULL); - // vkDestroySampler(vk->device, vk->linear_sampler, NULL); - // vkDestroySampler(vk->device, vk->nearest_sampler, NULL); - // - // - // Scene_drop(vk->scene); - // - // vkDestroyCommandPool(vk->device, vk->command_pool, NULL); - // - // - // MargaretSwapchainBundle_drop_with_device(vk->device, vk->swfb); - // Jane_alice_destroy(vk->device, vk->jane); - // destroy_graphics_pipeline_hands(vk->device, vk->pipeline_hands_1); - // vkDestroyRenderPass(vk->device, vk->render_pass_1, NULL); - // destroy_graphics_pipeline_hands(vk->device, vk->pipeline_hands_0b); - // destroy_graphics_pipeline_hands(vk->device, vk->pipeline_hands_0a); - // vkDestroyRenderPass(vk->device, vk->render_pass_0, NULL); - // vkDestroyDevice(vk->device, NULL); - // vkDestroySurfaceKHR(instance, vk->surface, NULL); - // MargaretInstanceAndItsDebug_drop(vk->instance_and_debug); - // - // if (alice->wl.wl_callback) - // wl_callback_destroy(alice->wl.wl_callback); - // xdg_toplevel_destroy(alice->wl.xdg_toplevel); - // xdg_surface_destroy(alice->wl.xdg_surface); - // xdg_wm_base_destroy(alice->wl.xdg_wm_base); - // wl_surface_destroy(alice->wl.wl_surface); - // wl_compositor_destroy(alice->wl.wl_compositor); - // if (alice->wl.pointer) - // wl_pointer_destroy(alice->wl.pointer); - // xkb_context_unref(alice->wl.xkb_context); - // xkb_keymap_unref(alice->wl.xkb_keymap); - // xkb_state_unref(alice->wl.xkb_state); - // if (alice->wl.keyboard) - // wl_keyboard_destroy(alice->wl.keyboard); - // if (alice->wl.wl_seat) - // wl_seat_destroy(alice->wl.wl_seat); - // wl_registry_destroy(alice->wl.wl_registry); - wl_display_disconnect(alice->wl.wl_display); -} +#include "../alice/engine.h" void allie_alice_set_sky_color(Alice* alice, float x, float y, float z, float w){ alice->rendering_config.clear_color = (vec4){x, y, z, w}; diff --git a/src/l2/core/glb_file.h b/src/l2/core/glb_file.h index f4dd274..b0f4f36 100644 --- a/src/l2/core/glb_file.h +++ b/src/l2/core/glb_file.h @@ -62,6 +62,8 @@ int glb_file_get_segments(SpanU8 file, GLBFileSegments* ret){ /* Illegal, no json segment */ return 8; } + SpanU8_print(json_segment); + printf("\n"); OptionJson parsed_json = json_decode(json_segment, 15); if (parsed_json.variant == Option_None) { return 9; diff --git a/src/l2/core/json_encoded.h b/src/l2/core/json_encoded.h index 97e340e..108041e 100644 --- a/src/l2/core/json_encoded.h +++ b/src/l2/core/json_encoded.h @@ -173,15 +173,20 @@ OptionJson json_decoding_h_no_spaces(SpanU8* rem, U32 depth_rem){ if (depth_rem == 0) { return None_Json(); } - S64 int_value; - int int_code = SpanU8_read_S64(rem, &int_value); - if (int_code == 0) - return Some_Json(Json_from_int(int_value)); float fl_value; + SpanU8 was = *rem; int fl_code = SpanU8_read_float(rem, &fl_value); - if (fl_code == 0) - return Some_Json(Json_from_float(fl_value)); + if (fl_code == 0) { + S64 int_value; + int int_code = SpanU8_read_S64(&was, &int_value, false); + if (was.data == rem->data) { + assert(int_code == 0); + return Some_Json(Json_from_int(int_value)); + } else { + return Some_Json(Json_from_float(fl_value)); + } + } bool false_code = SpanU8_parsing_try_read_prefix(rem, cstr("false")); if (false_code) diff --git a/src/l2/tests/t_parsing.c b/src/l2/tests/t_parsing.c index f799375..536f336 100644 --- a/src/l2/tests/t_parsing.c +++ b/src/l2/tests/t_parsing.c @@ -126,7 +126,7 @@ void tt13(){ void test_s64_reading_with_ill_formed_inp(SpanU8 str){ SpanU8 rem = str; S64 val; - int c = SpanU8_read_S64(&rem, &val); + int c = SpanU8_read_S64(&rem, &val, false); check(c > 0); check(SpanU8_equal(str, rem)); } @@ -149,7 +149,7 @@ void tt14(){ void test_s64_reading_with_good_inp(SpanU8 str, S64 right_val, U64 leftovers){ SpanU8 rem = str; S64 val; - int c = SpanU8_read_S64(&rem, &val); + int c = SpanU8_read_S64(&rem, &val, false); check(c == 0); check(rem.data == str.data + str.len - leftovers && rem.len == leftovers); check(val == right_val); @@ -193,6 +193,8 @@ void tt16(){ test_float_reading_with_good_inp(cstr("-1e-50"), -1e-50f, 0.00001f, 0); test_float_reading_with_good_inp(cstr("-1e50"), -1e50f, 0.00001f, 0); test_float_reading_with_good_inp(cstr("-15e+4"), -150000, 0.00001f, 0); + test_float_reading_with_good_inp(cstr("0.012307405471801758"), 0.012307405471801758f, 0.1f, 0); + test_float_reading_with_good_inp(cstr("-0.012307405471801758"), -0.012307405471801758f, 0.1f, 0); } void test_float_reading_with_ill_formed_inp(SpanU8 str){ @@ -369,6 +371,7 @@ void tt27(){ test_json_decoding_ok(" { } ", Json_from_MapVecU8ToJson(RBTree_MapVecU8ToJson_new())); test_json_decoding_ok(" \"7\" ", Json_from_SpanU8(cstr("7"))); test_json_decoding_ok(" \"XXX\" ", Json_from_SpanU8(cstr("XXX"))); + test_json_decoding_ok(" -0.012307405471801758", Json_from_float(-0.012307405471801758f)); { VecJson x = VecJson_new(); VecJson_append(&x, Json_from_int(12)); diff --git a/src/l3/models/skeleton.glb b/src/l3/models/skeleton.glb new file mode 100644 index 0000000..631cbc7 Binary files /dev/null and b/src/l3/models/skeleton.glb differ diff --git a/src/l3/r4/r4.c b/src/l3/r4/r4.c index bbc6d5e..b4750d5 100644 --- a/src/l3/r4/r4.c +++ b/src/l3/r4/r4.c @@ -1,5 +1,5 @@ -#include "../../l2/core/json.h" -#include "../../l2/allie/allie.c" +#include "../../l2/core/glb_file.h" +#include "../../l2/alice/engine.h" AliceGenericMeshPath AliceGenericMeshPath_for_log(SpanU8 root_dir, U64 w, U64 r, U64 k) { return (AliceGenericMeshPath){ @@ -59,7 +59,7 @@ void main_h_on_another_frame(void* data, float fl){ // VecU8_to_span(&text), (ivec2){100, 100}); } -int main(){ +void run_app(){ R4AlphaStuff st; st.hero_pos = (vec3){0, 0.81f, 0}; Alice* alice = Alice_new(); @@ -168,5 +168,18 @@ int main(){ .on_wl_keyboard_key = main_h_on_wayland_keyboard_key, .on_another_frame = main_h_on_another_frame, }); - return 0; -} \ No newline at end of file +} + +int main(){ + run_app(); + VecU8 file = read_file_by_path(vcstr("./src/l3/models/skeleton.glb")); + GLBFileSegments data; + int c = glb_file_get_segments(VecU8_to_span(&file), &data); + if (c > 0) { + abortf("Incorrect glb ==> %d\n", c); + } + VecU8 json_text = json_encode(&data.gltf); + VecU8_print(json_text); + GLBFileSegments_drop(data); + VecU8_drop(file); +} diff --git a/src/l_adele/alice/0simp/0simp.frag b/src/l_adele/alice/0simp/0simp.frag new file mode 100644 index 0000000..2d1180d --- /dev/null +++ b/src/l_adele/alice/0simp/0simp.frag @@ -0,0 +1,62 @@ +#version 450 + +layout(location = 1) in vec2 tex; +layout(location = 2) in vec3 pos; +layout(location = 3) in vec3 norm; + +/* Right now all in set 0 */ +layout(location = 0) out vec4 fin_color; +/* Yes, even these guys */ +layout(binding = 1) uniform sampler2D color_tex; + +layout(push_constant, std430) uniform pc { + layout(offset = 64) vec3 camera_pos; +}; + +struct Pipeline0PointLight { + vec3 pos; + vec3 color; +}; + +struct Pipeline0Spotlight { + vec3 pos; + vec3 dir; + vec3 color; + float range; +}; + +layout(std140, binding = 0) uniform Pipeline0UBO { + int point_light_count; + int spotlight_count; + Pipeline0PointLight point_light_arr[120]; + Pipeline0Spotlight spotlight_arr [20]; +}; + +float get_intensity(float dist){ + return 1 / (dist * dist * 1.8 + dist * 0.7 + 1); +} + +void main(){ + vec3 norm = normalize(mat3(tang_U, tang_norm, tang_V) * correct_norm_on_tang); + vec3 diffuse_illumination = vec3(0); + vec3 specular_illumination = vec3(0); + for (int i = 0; i < point_light_count; i++) { + Pipeline0PointLight lamp = point_light_arr[i]; + vec3 to_light = -pos + lamp.pos; + float dist = length(to_light); + vec3 U = to_light / dist; + diffuse_illumination += get_intensity(dist) * max(0, dot(U, norm)) * lamp.color; + vec3 A = reflect(-U, norm); + vec3 to_cam = -pos+camera_pos; + float dist_to_cam = length(to_cam); + vec3 B = to_cam / dist_to_cam; + specular_illumination += get_intensity(dist) * pow(max(0, dot(A, B)), 32) * lamp.color; + } + for (int i = 0; i < spotlight_count; i++) { + Pipeline0Spotlight lamp = spotlight_arr[i]; + } + vec3 natural_color = texture(color_tex, tex).xyz; + float specular_c = 0.1; + vec3 color = natural_color * diffuse_illumination + specular_c * specular_illumination+; + fin_color = vec4(color, 1); +} diff --git a/src/l_adele/alice/0simp/0simp.vert b/src/l_adele/alice/0simp/0simp.vert new file mode 100644 index 0000000..508fcfc --- /dev/null +++ b/src/l_adele/alice/0simp/0simp.vert @@ -0,0 +1,27 @@ +#version 450 + +layout(location = 0) in vec3 pos; +layout(location = 1) in vec2 tex; + +layout(location = 5) in mat4 model_t; +/* 5 <- 6, 7, 8 */ +layout(location = 9) in mat3 normal_t; +/* 9 <- 10, 11 */ + +layout(location = 0) out vec3 out_norm; +layout(location = 1) out vec3 out_tang_U; +layout(location = 2) out vec3 out_tang_V; +layout(location = 3) out vec2 out_tex; +layout(location = 4) out vec3 out_pos; + +layout(push_constant, std430) uniform pc { + mat4 proj_cam_t; +}; + +void main(){ + out_norm = normalize(normal_t * norm); + out_tex = tex; + vec4 real_pos = model_t * vec4(pos, 1); + out_pos = real_pos.xyz; + gl_Position = proj_cam_t * real_pos; +} \ No newline at end of file