diff --git a/CMakeLists.txt b/CMakeLists.txt index 130440e..1ea6104 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,8 @@ project(splitter_draft C) #include_directories(${CMAKE_SOURCE_DIR}) set(CMAKE_C_FLAGS "-Wall -Wextra -Werror=implicit-function-declaration -Werror=return-type --std=c99 -g -ggdb -O0") -add_compile_definitions(_POSIX_C_SOURCE=200112L ) +add_compile_definitions(_POSIX_C_SOURCE=200112L) +add_compile_definitions(_GNU_SOURCE) add_executable(main src/l1/main.c) diff --git a/src/l1/main.c b/src/l1/main.c index 2dbcb7b..e7e633c 100644 --- a/src/l1/main.c +++ b/src/l1/main.c @@ -52,7 +52,6 @@ NODISCARD VecU8 generate_xvecy_struct_definition(ConstSpanU8 xvec, ConstSpanU8 m return res; } -// todo: replace all these number operations with function forms NODISCARD VecU8 generate_xvecy_method_add_xvecy(ConstSpanU8 xvec, ConstSpanU8 member, int cc) { VecU8 res = VecU8_new(); string_append_xvecy(&res, xvec, cc); @@ -559,7 +558,9 @@ NODISCARD VecU8 generate_xmat234x234_structs_and_methods(ConstSpanU8 xmat, Const void generate_geometry_header() { VecU8 res = begin_header(cstr("PROTOTYPE1_GEN_GEOM")); + VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("cvec"), cstr("U8"))); VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("ivec"), cstr("S32"))); + VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("vec"), cstr("float"))); VecU8_append_vec(&res, generate_xvec234_structs_and_methods(cstr("dvec"), cstr("double"))); VecU8_append_vec(&res, generate_xmat234x234_structs_and_methods(cstr("mat"), cstr("vec"), cstr("float"), sizeof(float))); diff --git a/src/l2/margaret/graphics_geom.h b/src/l2/margaret/graphics_geom.h index 0d76da2..82b174f 100644 --- a/src/l2/margaret/graphics_geom.h +++ b/src/l2/margaret/graphics_geom.h @@ -2,7 +2,77 @@ #define PROTOTYPE1_SRC_L2_MARGARET_GRAPHICS_GEOM_H #include "../../../gen/geom.h" +#include "math.h" +mat4 margaret_translation_mat4(vec3 vec) { + return mat4_new( + 1, 0, 0, vec.x, + 0, 1, 0, vec.y, + 0, 0, 1, vec.z, + 0, 0, 0, 1 + ); +} + +mat3 margaret_3d_rot_mat3(vec3 r, float a) { + float cosa = cosf(a); + float sina = sinf(a); + return mat3_new( + r.x * r.x * (1 - cosa) + cosa, r.x * r.y * (1 - cosa) - sina * r.z, r.x * r.z * (1 - cosa) + sina * r.y, + r.x * r.y * (1 - cosa) + sina * r.z, r.y * r.y * (1 - cosa) + cosa, r.y * r.z * (1 - cosa) - sina * r.x, + r.x * r.z * (1 - cosa) - sina * r.y, r.y * r.z * (1 - cosa) + sina * r.x, r.z * r.z * (1 - cosa) + cosa + ); +} + +mat4 margaret_mat3_to_mat4(mat3 A) { + return mat4_new( + A.x.x, A.y.x, A.z.x, 0, + A.x.y, A.y.y, A.z.y, 0, + A.x.z, A.y.z, A.z.z, 0, + 0, 0, 0, 1); +} + +mat4 margaret_mat3_to_mat4_transposed(mat3 A) { + return mat4_new( + A.x.x, A.x.y, A.x.z, 0, + A.y.x, A.y.y, A.y.z, 0, + A.z.x, A.z.y, A.z.z, 0, + 0, 0, 0, 1); +} + +mat4 margaret_3d_rot_mat4(vec3 r, double a) { + return margaret_mat3_to_mat4(margaret_3d_rot_mat3(r, a)); +} + + +mat4 margaret_perspective_projection_mat4(float right, float top, float near, float far) { + return mat4_new( + near/right, 0, 0, 0, + 0, -near/top, 0, 0, + 0, 0, (far + near) / (near - far), 2 * far * near / (near - far), + 0, 0, -1, 0 ); +} + +mat4 margaret_perspective_projection_fov_mat4(float win_width, float win_height, float fov, + float spat_frustum_near, float spat_frustum_far) { + float right = tanf(fov / 2) * spat_frustum_near; + float top = win_height * right / win_width; + return margaret_perspective_projection_mat4(right, top, spat_frustum_near, spat_frustum_far); +} + + +mat3 margaret_simple_camera_rot_m_basis_in_cols(float yaw, float pitch, float roll) { + float cos_ya = cosf(yaw); + float sin_ya = sinf(yaw); + float cos_pi = cosf(pitch); + float sin_pi = sinf(pitch); + float cos_ro = cosf(roll); + float sin_ro = sinf(roll); + return (mat3){ + .x = (vec3){cos_ro * cos_ya + sin_ro * sin_pi * sin_ya, sin_ro * cos_pi, -cos_ro * sin_ya + sin_ro * sin_pi * cos_ya}, + .y = (vec3){-sin_ro * cos_ya + cos_ro * sin_pi * sin_ya, cos_ro * cos_pi, sin_ro * sin_ya + cos_ro * sin_pi * cos_ya}, + .z = (vec3){cos_pi * sin_ya, -sin_pi, cos_pi * cos_ya} + }; +} #endif diff --git a/src/l2/margaret/margaret.h b/src/l2/margaret/margaret.h index dcf102c..1c71f50 100644 --- a/src/l2/margaret/margaret.h +++ b/src/l2/margaret/margaret.h @@ -871,7 +871,7 @@ MargaretSingleWindowSetup MargaretSingleWindowSetup_new() { margaret_win_init_set_properties(dpy, win); /* 3) Select for ConfigureNotify and Expose events */ - XSelectInput(dpy, win, StructureNotifyMask | ExposureMask); + XSelectInput(dpy, win, StructureNotifyMask | ExposureMask | PointerMotionMask | KeyPressMask | KeyReleaseMask); return (MargaretSingleWindowSetup){ .dpy = dpy, .win = win }; } diff --git a/src/l2/margaret/stringop.h b/src/l2/margaret/stringop.h index 6f42ca9..ec40af6 100644 --- a/src/l2/margaret/stringop.h +++ b/src/l2/margaret/stringop.h @@ -3,6 +3,8 @@ #include "../../l1/core/VecSpan_int_primitives.h" +// todo: move this out of margaret (may still keep it in l2) + U8 U8_to_lowercase(U8 ch) { if ('A' <= ch && ch <= 'Z') return ch - 'A' + 'a'; diff --git a/src/l2/tests/r0.c b/src/l2/tests/r0.c index c02aeb7..7773066 100644 --- a/src/l2/tests/r0.c +++ b/src/l2/tests/r0.c @@ -3,88 +3,22 @@ #include #include "../../l1/system/fileio.h" #include +#include "r0_assets.h" // Only for linux #include +// todo: generate this class in l2 typedef struct { - vec3 pos; - vec2 tex; -} OA_Vertex; + VkPipelineLayout pipeline_layout; + VkPipeline pipeline; + VkDescriptorSetLayout descriptor_set_layout; +} PipelineHands; -typedef struct { - vec3 s; - float _0; -} MyUbo; -typedef struct { - VkBuffer vbo; - VkBuffer ebo; - // If topology is triangle list,then this is trice the amount of triangles - size_t indices; -} OA_ObjectOnScene; - -#define OA_ObjectOnScene_drop(vp) {} -#define OA_ObjectOnScene_clone(vp) (*(vp)) - -VecT_trivmove_struct_Definition(OA_ObjectOnScene) -VecT_trivmove_method_Definition(OA_ObjectOnScene) -VecT_primitive_zeroinit_method_Definition(OA_ObjectOnScene) - -typedef struct { - VecOA_ObjectOnScene oa_objects; - VkClearColorValue color; -} Scene; - -// todo: generate this function in l2 -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; +void destroy_graphics_pipeline_hands(VkDevice device, PipelineHands hands) { + vkDestroyPipeline(device, hands.pipeline, NULL); + vkDestroyPipelineLayout(device, hands.pipeline_layout, NULL); + vkDestroyDescriptorSetLayout(device, hands.descriptor_set_layout, NULL); } // todo: generate this function in l2 @@ -139,19 +73,228 @@ VkRenderPass create_render_pass_0(VkDevice logical_device, VkFormat image_format return render_pass; } -// todo: generate this class in l2 -typedef struct { - VkPipelineLayout pipeline_layout; - VkPipeline pipeline; - VkDescriptorSetLayout descriptor_set_layout; -} PipelineHands; +margaret_prep_buffer_mem_info_of_gpu_vbo_Definition(Vertex) -void destroy_graphics_pipeline_hands(VkDevice device, PipelineHands hands) { - vkDestroyPipeline(device, hands.pipeline, NULL); - vkDestroyPipelineLayout(device, hands.pipeline_layout, NULL); - vkDestroyDescriptorSetLayout(device, hands.descriptor_set_layout, NULL); +PipelineHands create_graphics_pipeline_0( + VkDevice device, VkRenderPass render_pass, uint32_t subpass + ) { + VecU8 vert_bin_code = read_whole_file_or_abort("test_shaders/spv/0/vert.spv"); + VecU8 frag_bin_code = read_whole_file_or_abort("test_shaders/spv/0/frag.spv"); + VkShaderModule vert_module = margaret_VkShaderModule_new(device, vert_bin_code); + VkShaderModule frag_module = margaret_VkShaderModule_new(device, frag_bin_code); + VecU8_drop(vert_bin_code); + VecU8_drop(frag_bin_code); + + VkPipelineShaderStageCreateInfo shader_stages_crinfo[2] = { + margaret_shader_stage_vertex_crinfo(vert_module), + margaret_shader_stage_fragment_crinfo(frag_module) + }; + + VkVertexInputBindingDescription vertex_bindings[1] = { { + .binding = 0, + .stride = sizeof(Vertex), + .inputRate = VK_VERTEX_INPUT_RATE_VERTEX, + } }; + VkVertexInputAttributeDescription vertex_attributes[2] = { + { + .location = 0, + .binding = 0, + .format = VK_FORMAT_R32G32B32_SFLOAT, + .offset = offsetof(Vertex, pos), + }, + { + .location = 1, + .binding = 0, + .format = VK_FORMAT_R32G32_SFLOAT, + .offset = offsetof(Vertex, tex), + }, + }; + + VkPipelineVertexInputStateCreateInfo vertex_input_crinfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + .vertexBindingDescriptionCount = ARRAY_SIZE(vertex_bindings), + .pVertexBindingDescriptions = vertex_bindings, + .vertexAttributeDescriptionCount = ARRAY_SIZE(vertex_attributes), + .pVertexAttributeDescriptions = vertex_attributes, + }; + + VkPipelineInputAssemblyStateCreateInfo input_assembly_crinfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + .primitiveRestartEnable = VK_FALSE, + }; + + VkPipelineViewportStateCreateInfo viewport_state = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + // We are using dynamic viewport and scissors, that is why we do not attach viewport/scissor values + // when creating a rendering pipeline. We will do that later + .viewportCount = 1, + .scissorCount = 1, + }; + + VkPipelineRasterizationStateCreateInfo rasterizer_crinfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + .depthClampEnable = VK_FALSE, + .polygonMode = VK_POLYGON_MODE_FILL, + // .cullMode = VK_CULL_MODE_BACK_BIT, + .cullMode = VK_CULL_MODE_NONE, + .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, + .depthBiasEnable = VK_FALSE, + .depthBiasConstantFactor = 0.0f, + .depthBiasClamp = 0.0f, + .depthBiasSlopeFactor = 0.0f, + .lineWidth = 1.0f, + }; + + VkPipelineMultisampleStateCreateInfo multisampling_crinfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + .sampleShadingEnable = VK_FALSE, + .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, + .minSampleShading = 1.0f, + .pSampleMask = NULL, + .alphaToCoverageEnable = VK_FALSE, + .alphaToOneEnable = VK_FALSE, + }; + + // For one framebuffer + VkPipelineColorBlendAttachmentState color_blend_attachments[1] = {(VkPipelineColorBlendAttachmentState){ + .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, + .blendEnable = VK_FALSE, + }}; + + // For the entire pipeline + VkPipelineColorBlendStateCreateInfo color_blending_crinfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + .logicOpEnable = VK_FALSE, + .logicOp = VK_LOGIC_OP_COPY, + .attachmentCount = ARRAY_SIZE(color_blend_attachments), + .pAttachments = color_blend_attachments, + // Blend constants specified heres + }; + + VkDynamicState dynamic_states[2] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; + VkPipelineDynamicStateCreateInfo dynamic_state_crinfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + .dynamicStateCount = ARRAY_SIZE(dynamic_states), + .pDynamicStates = dynamic_states, + }; + + VkDescriptorSetLayoutBinding bindings_for_my_descr_set_layout[] = { + { + // Binding in shader + .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_VERTEX_BIT, + }, + { + .binding = 1, + .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"); + + VkPipelineLayoutCreateInfo layout_crinfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = 1, + .pSetLayouts = &my_descriptor_set_layout, + .pushConstantRangeCount = 0, + .pPushConstantRanges = NULL, + }; + VkPipelineLayout pipeline_layout; + if (vkCreatePipelineLayout(device, &layout_crinfo, NULL, &pipeline_layout) != VK_SUCCESS) + abortf("vkCreatePipelineLayout"); + VkGraphicsPipelineCreateInfo pipeline_crinfo = { + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .stageCount = ARRAY_SIZE(shader_stages_crinfo), + .pStages = shader_stages_crinfo, + .pVertexInputState = &vertex_input_crinfo, + .pInputAssemblyState = &input_assembly_crinfo, + .pViewportState = &viewport_state, + .pRasterizationState = &rasterizer_crinfo, + .pMultisampleState = &multisampling_crinfo, + .pDepthStencilState = NULL, + .pColorBlendState = &color_blending_crinfo, + .pDynamicState = &dynamic_state_crinfo, + .layout = pipeline_layout, + .renderPass = render_pass, + .subpass = subpass, + .basePipelineHandle = VK_NULL_HANDLE, + }; + + VkPipeline pipeline; + if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_crinfo, NULL, &pipeline) != VK_SUCCESS) + abortf("vkCreateGraphicsPipelines"); + + vkDestroyShaderModule(device, frag_module, NULL); + vkDestroyShaderModule(device, vert_module, NULL); + return (PipelineHands){.pipeline_layout = pipeline_layout, .pipeline = pipeline, .descriptor_set_layout = my_descriptor_set_layout}; } + +// todo: generate this function in l2 +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; +} + + // todo: generate this function in l2 PipelineHands create_graphics_pipeline_1( VkDevice device, VkRenderPass render_pass, uint32_t subpass @@ -226,7 +369,7 @@ PipelineHands create_graphics_pipeline_1( .logicOp = VK_LOGIC_OP_COPY, .attachmentCount = ARRAY_SIZE(color_blend_attachments), .pAttachments = color_blend_attachments, - // Blend constants specified heres + // Blend constants specified here }; VkDynamicState dynamic_states[2] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; @@ -253,22 +396,24 @@ PipelineHands create_graphics_pipeline_1( if (vkCreateDescriptorSetLayout(device, &descriptor_set_layout_crinfo, NULL, &my_descriptor_set_layout) != VK_SUCCESS) abortf("vkCreateDescriptorSetLayout"); - VkPushConstantRange used_region_sz_push_const = { - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, - .offset = 0, .size = sizeof(vec2) + 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) }, }; VkPipelineLayoutCreateInfo layout_crinfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .setLayoutCount = 1, .pSetLayouts = &my_descriptor_set_layout, - .pushConstantRangeCount = 1, - .pPushConstantRanges = &used_region_sz_push_const, + .pushConstantRangeCount = ARRAY_SIZE(used_region_sz_push_const), + .pPushConstantRanges = used_region_sz_push_const, }; VkPipelineLayout pipeline_layout; if (vkCreatePipelineLayout(device, &layout_crinfo, NULL, &pipeline_layout) != VK_SUCCESS) abortf("vkCreatePipelineLayout"); - // todo: kill myself (update: still todo (update: still not done )) update: work in progress + // todo: kill myself (update: still todo (update: still not done )) update: work in progress (update: medium priority) VkGraphicsPipelineCreateInfo pipeline_crinfo = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .stageCount = ARRAY_SIZE(shader_stages_crinfo), @@ -296,173 +441,6 @@ PipelineHands create_graphics_pipeline_1( return (PipelineHands){.pipeline_layout = pipeline_layout, .pipeline = pipeline, .descriptor_set_layout = my_descriptor_set_layout}; } -PipelineHands create_graphics_pipeline_0( - VkDevice device, VkRenderPass render_pass, uint32_t subpass - ) { - VecU8 vert_bin_code = read_whole_file_or_abort("test_shaders/spv/0/vert.spv"); - VecU8 frag_bin_code = read_whole_file_or_abort("test_shaders/spv/0/frag.spv"); - VkShaderModule vert_module = margaret_VkShaderModule_new(device, vert_bin_code); - VkShaderModule frag_module = margaret_VkShaderModule_new(device, frag_bin_code); - VecU8_drop(vert_bin_code); - VecU8_drop(frag_bin_code); - - VkPipelineShaderStageCreateInfo shader_stages_crinfo[2] = { - margaret_shader_stage_vertex_crinfo(vert_module), - margaret_shader_stage_fragment_crinfo(frag_module) - }; - - VkVertexInputBindingDescription vertex_bindings[1] = { { - .binding = 0, - .stride = sizeof(OA_Vertex), - .inputRate = VK_VERTEX_INPUT_RATE_VERTEX, - } }; - VkVertexInputAttributeDescription vertex_attributes[2] = { - { - .location = 0, - .binding = 0, - .format = VK_FORMAT_R32G32B32_SFLOAT, - .offset = offsetof(OA_Vertex, pos), - }, - { - .location = 1, - .binding = 0, - .format = VK_FORMAT_R32G32_SFLOAT, - .offset = offsetof(OA_Vertex, tex), - }, - }; - - VkPipelineVertexInputStateCreateInfo vertex_input_crinfo = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .vertexBindingDescriptionCount = ARRAY_SIZE(vertex_bindings), - .pVertexBindingDescriptions = vertex_bindings, - .vertexAttributeDescriptionCount = ARRAY_SIZE(vertex_attributes), - .pVertexAttributeDescriptions = vertex_attributes, - }; - - VkPipelineInputAssemblyStateCreateInfo input_assembly_crinfo = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, - .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, - .primitiveRestartEnable = VK_FALSE, - }; - - VkPipelineViewportStateCreateInfo viewport_state = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, - // We are using dynamic viewport and scissors, that is why we do not attach viewport/scissor values - // when creating a rendering pipeline. We will do that later - .viewportCount = 1, - .scissorCount = 1, - }; - - VkPipelineRasterizationStateCreateInfo rasterizer_crinfo = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - .depthClampEnable = VK_FALSE, - .polygonMode = VK_POLYGON_MODE_FILL, - .cullMode = VK_CULL_MODE_BACK_BIT, - .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, - .depthBiasEnable = VK_FALSE, - .depthBiasConstantFactor = 0.0f, - .depthBiasClamp = 0.0f, - .depthBiasSlopeFactor = 0.0f, - .lineWidth = 1.0f, - }; - - VkPipelineMultisampleStateCreateInfo multisampling_crinfo = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - .sampleShadingEnable = VK_FALSE, - .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, - .minSampleShading = 1.0f, - .pSampleMask = NULL, - .alphaToCoverageEnable = VK_FALSE, - .alphaToOneEnable = VK_FALSE, - }; - - // For one framebuffer - VkPipelineColorBlendAttachmentState color_blend_attachments[1] = {(VkPipelineColorBlendAttachmentState){ - .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, - .blendEnable = VK_FALSE, - }}; - - // For the entire pipeline - VkPipelineColorBlendStateCreateInfo color_blending_crinfo = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, - .logicOpEnable = VK_FALSE, - .logicOp = VK_LOGIC_OP_COPY, - .attachmentCount = ARRAY_SIZE(color_blend_attachments), - .pAttachments = color_blend_attachments, - // Blend constants specified heres - }; - - VkDynamicState dynamic_states[2] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamic_state_crinfo = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, - .dynamicStateCount = ARRAY_SIZE(dynamic_states), - .pDynamicStates = dynamic_states, - }; - - VkDescriptorSetLayoutBinding bindings_for_my_descr_set_layout[] = { - { - // Binding in shader - .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, - }, - }; - 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"); - - VkPipelineLayoutCreateInfo layout_crinfo = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .setLayoutCount = 1, - .pSetLayouts = &my_descriptor_set_layout, - .pushConstantRangeCount = 0, - .pPushConstantRanges = NULL, - }; - VkPipelineLayout pipeline_layout; - if (vkCreatePipelineLayout(device, &layout_crinfo, NULL, &pipeline_layout) != VK_SUCCESS) - abortf("vkCreatePipelineLayout"); - VkGraphicsPipelineCreateInfo pipeline_crinfo = { - .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .stageCount = ARRAY_SIZE(shader_stages_crinfo), - .pStages = shader_stages_crinfo, - .pVertexInputState = &vertex_input_crinfo, - .pInputAssemblyState = &input_assembly_crinfo, - .pViewportState = &viewport_state, - .pRasterizationState = &rasterizer_crinfo, - .pMultisampleState = &multisampling_crinfo, - .pDepthStencilState = NULL, - .pColorBlendState = &color_blending_crinfo, - .pDynamicState = &dynamic_state_crinfo, - .layout = pipeline_layout, - .renderPass = render_pass, - .subpass = subpass, - .basePipelineHandle = VK_NULL_HANDLE, - }; - - // todo: actually use this function - - VkPipeline pipeline; - if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_crinfo, NULL, &pipeline) != VK_SUCCESS) - abortf("vkCreateGraphicsPipelines"); - - vkDestroyShaderModule(device, frag_module, NULL); - vkDestroyShaderModule(device, vert_module, NULL); - return (PipelineHands){.pipeline_layout = pipeline_layout, .pipeline = pipeline, .descriptor_set_layout = my_descriptor_set_layout}; -} - VkFramebuffer create_IT1_framebuffer(VkDevice device, VkImageView IT1_view, VkRenderPass render_pass_0, VkExtent2D MAX_WIN_SIZE) { VkImageView attachments[1] = {IT1_view}; @@ -523,17 +501,17 @@ void reset_and_record_command_buffer_0( .extent = image_extent, }; vkCmdSetScissor(command_buffer, 0, 1, &scissor); - for (size_t i = 0; i < scene->oa_objects.len; i++) { - const OA_ObjectOnScene* obj = VecOA_ObjectOnScene_cat(&scene->oa_objects, i); - VkBuffer attached_buffers[1] = { obj->vbo }; + for (size_t i = 0; i < scene->models.len; i++) { + const ModelOnScene* models = VecModelOnScene_cat(&scene->models, i); + VkBuffer attached_buffers[1] = { models->vbo }; // We use our whole buffer, no need for offset VkDeviceSize offsets_in_buffers[1] = {0}; vkCmdBindVertexBuffers(command_buffer, 0, 1, attached_buffers, offsets_in_buffers); - vkCmdBindIndexBuffer(command_buffer, obj->ebo, 0, VK_INDEX_TYPE_UINT32); + vkCmdBindIndexBuffer(command_buffer, models->ebo, 0, VK_INDEX_TYPE_UINT32); vkCmdBindDescriptorSets( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout->pipeline_layout, 0, 1, &my_descriptor_set, 0, NULL); - vkCmdDrawIndexed(command_buffer, obj->indices, 1, 0, 0, 0); + vkCmdDrawIndexed(command_buffer, models->indexes, 1, 0, 0, 0); } vkCmdEndRenderPass(command_buffer); @@ -545,7 +523,7 @@ void reset_and_record_command_buffer_1( VkCommandBuffer command_buffer, VkRenderPass render_pass_1, const PipelineHands* pipeline_and_layout_1, VkFramebuffer swapchain_image_framebuffer, VkExtent2D image_extent, - VkExtent2D max_win_size, + VkExtent2D max_win_size, const Scene* scene, VkDescriptorSet descriptor_set_for_pipeline_1 ) { if (vkResetCommandBuffer(command_buffer, 0) != VK_SUCCESS) @@ -554,15 +532,12 @@ void reset_and_record_command_buffer_1( if (vkBeginCommandBuffer(command_buffer, &info_begin) != VK_SUCCESS) abortf("vkBeginCommandBuffer"); - // VkClearValue clear_color[1] = {{.color = scene->color}}; VkRenderPassBeginInfo renderpass_begin = { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, .renderPass = render_pass_1, .framebuffer = swapchain_image_framebuffer, .renderArea.offset = (VkOffset2D){0, 0}, .renderArea.extent = image_extent, - .clearValueCount = 0, - .pClearValues = NULL, }; vkCmdBeginRenderPass(command_buffer, &renderpass_begin, VK_SUBPASS_CONTENTS_INLINE); @@ -586,10 +561,20 @@ void reset_and_record_command_buffer_1( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout_1->pipeline_layout, 0, 1, &descriptor_set_for_pipeline_1, 0, NULL); - vec2 region_tex_scale = {(float)image_extent.width / (float)max_win_size.width, - (float)image_extent.height / (float)max_win_size.height}; - vkCmdPushConstants(command_buffer, pipeline_and_layout_1->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vec2), ®ion_tex_scale); - + Pipeline1PushRangeVertex reg_and_params_vertex = {.win_scale = { + (float)image_extent.width / (float)max_win_size.width, + (float)image_extent.height / (float)max_win_size.height}, + }; + Pipeline1PushRangeFragment reg_and_params_fragment = { + .gamma_correction_factor = scene->gamma_correction_factor, + .hdr_factor = scene->hdr_factor, + .lsd_factor = scene->lsd_factor, + .anim_time = scene->anim_time + }; + vkCmdPushConstants(command_buffer, pipeline_and_layout_1->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, + 0, sizeof(Pipeline1PushRangeVertex), ®_and_params_vertex); + vkCmdPushConstants(command_buffer, pipeline_and_layout_1->pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, + sizeof(Pipeline1PushRangeVertex), sizeof(Pipeline1PushRangeFragment), ®_and_params_fragment); vkCmdDraw(command_buffer, 3, 1, 0, 0); vkCmdEndRenderPass(command_buffer); @@ -598,6 +583,7 @@ void reset_and_record_command_buffer_1( } +// todo: add here deletion and recreation of several synchronization primitives void recreate_swapchain( VkPhysicalDevice physical_device, VkDevice device, MargaretChosenQueueFamilies queue_fam, VkSurfaceKHR surface, VkRenderPass render_pass, MargaretSwapchainBundle* swfb) { @@ -616,7 +602,6 @@ void recreate_swapchain( *swfb = new_swfb; } -margaret_prep_buffer_mem_info_of_gpu_vbo_Definition(OA_Vertex) void prepare_shaders() { int ret = system("./test_shader_compile.sh"); @@ -687,65 +672,31 @@ int main() { MargaretSwapchainBundle swfb = MargaretSwapchainBundle_new(device, queue_fam, swapchain_details, surface, render_pass_1, NULL); // Filling scene info - const OA_Vertex obj1_vertexes[] = { - (OA_Vertex){ .pos = {-1, -0.5f, 0}, .tex = {0, 1} }, - (OA_Vertex){ .pos = {0.3f, -0.5f, 0}, .tex = {1, 1} }, - (OA_Vertex){ .pos = {-3.f, 3.f, 0}, .tex = {1, 0} }, - (OA_Vertex){ .pos = {-0.5f, .4f, 0}, .tex = {0, 0} }, - }; - const uint32_t obj1_indices[] = { 0, 2, 1, 0, 3, 2 }; - const OA_Vertex obj2_vertexes[] = { - (OA_Vertex){ .pos = {0.9f, 0.9f}, .tex = {1.f, 0} }, - (OA_Vertex){ .pos = {0.4f, -0.9f, 0}, .tex = {0, 1.f} }, - (OA_Vertex){ .pos = {-0.2f, 1.f}, .tex = {0, 0} }, - }; - const uint32_t obj2_indices[] = {0, 1, 2}; - - const U32 wood_texture_width = 100; - const U32 wood_texture_height = 100; - color8rgba wood_texture_data[wood_texture_height][wood_texture_width]; - for (U32 y = 0; y < wood_texture_height; y++) { - for (U32 col = 0; col < wood_texture_width; col++) { - wood_texture_data[y][col] = (color8rgba){150, 30, 50, 255}; - } - } - for (U32 i = 0; i < 10; i++) { - for (U32 y = 0; y < wood_texture_height; y++) { - U32 col = 3 + i * 10 + ((30 < y + 3 * i && y - i < 60) ? 1 : 0); - wood_texture_data[y][col] = (color8rgba){130, 25, 40, 255}; - wood_texture_data[y][col + 1] = (color8rgba){80, 10, 15, 255}; - wood_texture_data[y][col + 2] = (color8rgba){70, 11, 12, 255}; - wood_texture_data[y][col + 3] = (color8rgba){125, 20, 20, 255}; - } - } - for (U32 y = 0; y < 10; y++) { - for (U32 col = 0; col < 10; col++) { - wood_texture_data[13 + y][4 + col] = (color8rgba){140, 50, 20, 255}; - } - } + ModelTopology cylinder_1 = generate_one_fourth_of_a_cylinder(10, 2, 6); + ModelTopology cylinder_2 = generate_one_fourth_of_a_cylinder(5, 5, 10); + TextureDataR8G8B8A8 wood_texture_data = generate_wood_texture(); // We have only one staging buffer in host memory (because we don't really need more) MargaretBufferInMemoryInfo host_mem_buffer = (MargaretBufferInMemoryInfo){ .sz = - MAX_U64(sizeof(obj1_vertexes), - MAX_U64(sizeof(obj1_indices), - MAX_U64(sizeof(obj2_vertexes), - MAX_U64(sizeof(obj2_indices), - MAX_U64(sizeof(MyUbo), - MAX_U64(sizeof(wood_texture_data), 0)))))) + MAX_U64(ModelTopology_get_space_needed_for_staging_buffer(&cylinder_1), + MAX_U64(ModelTopology_get_space_needed_for_staging_buffer(&cylinder_2), + MAX_U64(sizeof(Pipeline0UBO), + MAX_U64(TextureDataR8G8B8A8_get_space_needed_for_staging_buffer(&wood_texture_data), 0)))) , .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT }; VkDeviceMemory host_mem = margaret_initialize_buffers_and_images(physical_device, device, (SpanMargaretBufferInMemoryInfo){.data = &host_mem_buffer, .len = 1}, (SpanMargaretImageInMemoryInfo){ 0 }, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); MargaretBufferInMemoryInfo device_mem_buffers[] = { - OA_Vertex_buffer_crinfo_of_gpu_vbo(ARRAY_SIZE(obj1_vertexes)), - margaret_prep_buffer_mem_info_of_gpu_ebo(ARRAY_SIZE(obj1_indices)), - OA_Vertex_buffer_crinfo_of_gpu_vbo(ARRAY_SIZE(obj2_vertexes)), - margaret_prep_buffer_mem_info_of_gpu_ebo(ARRAY_SIZE(obj2_indices)), - margaret_prep_buffer_mem_info_of_gpu_ubo(sizeof(MyUbo)), + Vertex_buffer_crinfo_of_gpu_vbo(cylinder_1.vertices.len), + margaret_prep_buffer_mem_info_of_gpu_ebo(cylinder_1.indexes.len), + Vertex_buffer_crinfo_of_gpu_vbo(cylinder_2.vertices.len), + margaret_prep_buffer_mem_info_of_gpu_ebo(cylinder_2.indexes.len), + margaret_prep_buffer_mem_info_of_gpu_ubo(sizeof(Pipeline0UBO)), }; MargaretImageInMemoryInfo device_mem_images[] = { - margaret_prep_image_mem_info_of_gpu_texture_rgba(wood_texture_width, wood_texture_height), + margaret_prep_image_mem_info_of_gpu_texture_rgba(wood_texture_data.width, + TextureDataR8G8B8A8_get_height(&wood_texture_data)), margaret_prep_image_mem_info_of_colorbuffer(MAX_WIN_WIDTH, MAX_WIN_HEIGHT, swapchain_details.surface_format.format), }; VkDeviceMemory device_mem = margaret_initialize_buffers_and_images(physical_device, device, @@ -758,7 +709,7 @@ int main() { MargaretBufferInMemoryInfo device_ebo_2_buffer = device_mem_buffers[3]; MargaretBufferInMemoryInfo device_ubo_my_buffer = device_mem_buffers[4]; MargaretImageInMemoryInfo device_wood_texture = device_mem_images[0]; - MargaretImageInMemoryInfo device_IT1_image = device_mem_images[1]; // todo: use it in my shenanigans + MargaretImageInMemoryInfo device_IT1_image = device_mem_images[1]; VkCommandPool command_pool = margaret_create_resettable_command_pool(device, queue_fam.for_graphics); VkCommandBuffer rendering_command_buffer_0 = margaret_allocate_command_buffer(device, command_pool); @@ -766,25 +717,38 @@ int main() { VkCommandBuffer uniform_transfer_command_buffer = margaret_allocate_command_buffer(device, command_pool); margaret_record_buf_copying_command_buf(device, uniform_transfer_command_buffer, - device_ubo_my_buffer.buffer, host_mem_buffer.buffer, sizeof(MyUbo)); + device_ubo_my_buffer.buffer, host_mem_buffer.buffer, sizeof(Pipeline0UBO)); void* host_mem_buffer_mem; if (vkMapMemory(device, host_mem, 0, VK_WHOLE_SIZE, 0, &host_mem_buffer_mem) != VK_SUCCESS) abortf("vkMapMemory"); // Now this is what we will do for each buffer: we first memcpy it into mapped region, then we submit a copying command - memcpy(host_mem_buffer_mem, obj1_vertexes, sizeof(obj1_vertexes)); - margaret_copy_buffer_imm(device, command_pool, graphics_queue, - device_vbo_1_buffer.buffer, host_mem_buffer.buffer, sizeof(obj1_vertexes)); - memcpy(host_mem_buffer_mem, obj1_indices, sizeof(obj1_indices)); - margaret_copy_buffer_imm(device, command_pool, graphics_queue, - device_ebo_1_buffer.buffer, host_mem_buffer.buffer, sizeof(obj1_indices)); - memcpy(host_mem_buffer_mem, obj2_vertexes, sizeof(obj2_vertexes)); - margaret_copy_buffer_imm(device, command_pool, graphics_queue, - device_vbo_2_buffer.buffer, host_mem_buffer.buffer, sizeof(obj2_vertexes)); - memcpy(host_mem_buffer_mem, obj2_indices, sizeof(obj2_indices)); - margaret_copy_buffer_imm(device, command_pool, graphics_queue, - device_ebo_2_buffer.buffer, host_mem_buffer.buffer, sizeof(obj2_indices)); - memcpy(host_mem_buffer_mem, wood_texture_data, sizeof(wood_texture_data)); + { + size_t size = cylinder_1.vertices.len * sizeof(Vertex); + memcpy(host_mem_buffer_mem, cylinder_1.vertices.buf, size); + margaret_copy_buffer_imm(device, command_pool, graphics_queue, + device_vbo_1_buffer.buffer, host_mem_buffer.buffer, size); + } + { + size_t size = cylinder_1.indexes.len * sizeof(U32); + memcpy(host_mem_buffer_mem, cylinder_1.indexes.buf, size); + margaret_copy_buffer_imm(device, command_pool, graphics_queue, + device_ebo_1_buffer.buffer, host_mem_buffer.buffer, size); + } + { + size_t size = cylinder_2.vertices.len * sizeof(Vertex); + memcpy(host_mem_buffer_mem, cylinder_2.vertices.buf, size); + margaret_copy_buffer_imm(device, command_pool, graphics_queue, + device_vbo_2_buffer.buffer, host_mem_buffer.buffer, size); + } + { + size_t size = cylinder_2.indexes.len * sizeof(U32); + memcpy(host_mem_buffer_mem, cylinder_2.indexes.buf, size); + margaret_copy_buffer_imm(device, command_pool, graphics_queue, + device_ebo_2_buffer.buffer, host_mem_buffer.buffer, size); + } + memcpy(host_mem_buffer_mem, wood_texture_data.pixels.buf, + TextureDataR8G8B8A8_get_space_needed_for_staging_buffer(&wood_texture_data)); margaret_copy_buffer_to_texture_for_frag_shader_imm(device, command_pool, graphics_queue, &device_wood_texture, host_mem_buffer.buffer); // We sent everything we needed. but host_mem_buffer_mem may be used later @@ -794,17 +758,15 @@ int main() { /* Here we create an image view into a temporary IT1 texture and a framebuffer for scene rendering */ VkImageView IT1_view = margaret_create_view_for_image(device, &device_IT1_image, VK_IMAGE_ASPECT_COLOR_BIT); - // todo: I will get back here soon VkFramebuffer IT1_framebuffer = create_IT1_framebuffer(device, IT1_view, render_pass_0, (VkExtent2D){.width = MAX_WIN_WIDTH, .height = MAX_WIN_HEIGHT}); Scene scene; - scene.oa_objects = VecOA_ObjectOnScene_new_zeroinit(2); - *VecOA_ObjectOnScene_at(&scene.oa_objects, 0) = (OA_ObjectOnScene){ - .vbo = device_vbo_1_buffer.buffer, .ebo = device_ebo_1_buffer.buffer, .indices = ARRAY_SIZE(obj1_indices) }; - *VecOA_ObjectOnScene_at(&scene.oa_objects, 1) = (OA_ObjectOnScene){ - .vbo = device_vbo_2_buffer.buffer, .ebo = device_ebo_2_buffer.buffer, .indices = ARRAY_SIZE(obj2_indices) }; - // device_vbo/ebo_1/2_buffer won't be used only intrinsically by vulkan, not by us + scene.models = VecModelOnScene_new_zeroinit(2); + *VecModelOnScene_at(&scene.models, 0) = (ModelOnScene){ + .vbo = device_vbo_1_buffer.buffer, .ebo = device_ebo_1_buffer.buffer, .indexes = cylinder_1.indexes.len }; + // *VecModelOnScene_at(&scene.models, 1) = (ModelOnScene){ + // .vbo = device_vbo_2_buffer.buffer, .ebo = device_ebo_2_buffer.buffer, .indexes = cylinder_2.indexes.len }; // Sampler is global for a lot of my future textures VkSampler my_texture_sampler = margaret_create_sampler(physical_device, device); @@ -817,7 +779,7 @@ int main() { VkDescriptorBufferInfo buffer_info_for_descriptor_0_in_set_0 = { .buffer = device_ubo_my_buffer.buffer, .offset = 0, - .range = sizeof(MyUbo), + .range = sizeof(Pipeline0UBO), }; VkDescriptorImageInfo image_info_for_descriptor_1_in_set_0 = { .sampler = my_texture_sampler, @@ -849,7 +811,6 @@ int main() { .pImageInfo = &image_info_for_descriptor_1_in_set_0, }, - { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .dstSet = descriptor_set_for_pipeline_1, @@ -862,18 +823,56 @@ int main() { }; vkUpdateDescriptorSets(device, ARRAY_SIZE(writes_in_descriptor_sets), writes_in_descriptor_sets, 0, NULL); + CamControlInfo my_cam_control_info = CamControlInfo_new(); + // Mainloop margaret_ns_time start = margaret_clock_gettime_monotonic_raw(); margaret_ns_time prev_key_frame_time = start; int frame_count_since_key = 0; + margaret_ns_time prev_frame_timestamp = start; + bool pressed_first_0x80[0x80] = {0}; while (true) { margaret_ns_time frame_A0 = margaret_clock_gettime_monotonic_raw(); + float fl = margaret_ns_time_sec_diff(prev_frame_timestamp, frame_A0); + prev_frame_timestamp = frame_A0; + VecXlib_Event events = margaret_read_x_events(x.dpy); - for (size_t i = 0; i < events.len; i++) - Margaret_WEP_update_with_new_event(&wep, VecXlib_Event_cat(&events, i)); if (wep.should_stop) break; + for (size_t i = 0; i < events.len; i++) { + Xlib_Event* ev = VecXlib_Event_at(&events, i); + // printf("%lu %lu\n", ev->xany.window, wep.win); + if (ev->xany.window != wep.win) + continue; + Margaret_WEP_update_with_new_event(&wep, ev); + if (ev->xany.type == MotionNotify) { + CamControlInfo_update_direction(&my_cam_control_info, wep.width, wep.height, ev->xmotion.x, ev->xmotion.y); + } + if (ev->xany.type == KeyPress) { + KeySym keysym = XLookupKeysym(&ev->xkey, 0); + if (keysym < 0x80) + pressed_first_0x80[keysym] = true; + } + if (ev->xany.type == KeyRelease) { + KeySym keysym = XLookupKeysym(&ev->xkey, 0); + if (keysym < 0x80) + pressed_first_0x80[keysym] = false; + } + } + if (pressed_first_0x80[XK_w]) + CamControlInfo_forward(&my_cam_control_info, fl); + if (pressed_first_0x80[XK_s]) + CamControlInfo_backward(&my_cam_control_info, fl); + if (pressed_first_0x80[XK_a]) + CamControlInfo_left(&my_cam_control_info, fl); + if (pressed_first_0x80[XK_d]) + CamControlInfo_right(&my_cam_control_info, fl); + if (pressed_first_0x80[XK_q]) + CamControlInfo_down(&my_cam_control_info, fl); + if (pressed_first_0x80[XK_e]) + CamControlInfo_up(&my_cam_control_info, fl); + // Rendering vkWaitForFences(device, 1, &swfb.in_flight_fence, VK_TRUE, UINT64_MAX); uint32_t ij; @@ -895,12 +894,17 @@ int main() { vkResetFences(device, 1, &swfb.in_flight_fence); - float ae = sinf(margaret_ns_time_sec_diff(start, frame_A0)); - scene.color = (VkClearColorValue){{0.5f, fabsf(ae), .3f, 1.0f}}; - vec3 SS = {ae * ae, 0.5f + 0.5f * ae, 0}; - + float ae = margaret_ns_time_sec_diff(start, frame_A0); + scene.anim_time = ae; + scene.color = (VkClearColorValue){{0.5f, fabsf(sinf(ae)), .3f, 1.0f}}; + mat4 projection_matrix = margaret_perspective_projection_fov_mat4((float)wep.width, (float)wep.height, + my_cam_control_info.fov, 0.01f, 1000); + mat4 camera_rotation_matrix = margaret_mat3_to_mat4_transposed(my_cam_control_info.cam_basis); + mat4 camera_translation_matrix = margaret_translation_mat4(vec3_minus(my_cam_control_info.pos)); + mat4 t_mat = mat4_mul_mat4(projection_matrix, mat4_mul_mat4(camera_rotation_matrix, camera_translation_matrix)); + // mat4 t_mat = mat4_mul_mat4(camera_rotation_matrix, camera_translation_matrix); { - *(MyUbo *)host_mem_buffer_mem = (MyUbo){ .s = SS }; + *(Pipeline0UBO*)host_mem_buffer_mem = (Pipeline0UBO){.t = t_mat}; VkCommandBuffer command_buffers[1] = { uniform_transfer_command_buffer }; VkSemaphore signaling_semaphores[1] = { swfb.in_frame_transfer_complete }; VkSubmitInfo ubo_copying_cmd_buffer_submit = { @@ -918,7 +922,7 @@ int main() { reset_and_record_command_buffer_1(rendering_command_buffer_1, render_pass_1, &pipeline_hands_1, *VecVkFramebuffer_cat(&swfb.framebuffers, ij), - swfb.extent, (VkExtent2D){.width = MAX_WIN_WIDTH, .height = MAX_WIN_HEIGHT}, descriptor_set_for_pipeline_1); + swfb.extent, (VkExtent2D){.width = MAX_WIN_WIDTH, .height = MAX_WIN_HEIGHT}, &scene, descriptor_set_for_pipeline_1); { VkSemaphore waiting_for_semaphores[2] = { @@ -1025,7 +1029,9 @@ int main() { vkDeviceWaitIdle(device); // The End // dropping scene - VecOA_ObjectOnScene_drop(scene.oa_objects); + Scene_drop(scene); + ModelTopology_drop(cylinder_1); + ModelTopology_drop(cylinder_2); // destroying vulkan objects vkDestroyDescriptorPool(device, descriptor_pool, NULL); vkDestroySampler(device, my_texture_sampler, NULL); diff --git a/src/l2/tests/r0_assets.h b/src/l2/tests/r0_assets.h new file mode 100644 index 0000000..825010c --- /dev/null +++ b/src/l2/tests/r0_assets.h @@ -0,0 +1,256 @@ +#ifndef SPLITTER_DRAFT_SRC_L2_TESTS_R0_ASSETS_H +#define SPLITTER_DRAFT_SRC_L2_TESTS_R0_ASSETS_H + +#include "../margaret/graphics_geom.h" +#include "../../l1/core/util.h" +#include + +typedef struct { + vec3 pos; + vec2 tex; +} Vertex; + +/* No offset yet */ +typedef struct { + VkBuffer vbo; + VkBuffer ebo; + size_t indexes; +} ModelOnScene; + +#define ModelOnScene_drop(vp) {} +#define ModelOnScene_clone(vp) (*(vp)) + +VecT_trivmove_struct_Definition(ModelOnScene) +VecT_trivmove_method_Definition(ModelOnScene) +VecT_primitive_zeroinit_method_Definition(ModelOnScene) + +#define Vertex_drop(vp) {} +#define Vertex_clone(vp) (*(vp)) + +VecT_trivmove_struct_Definition(Vertex) +VecT_trivmove_method_Definition(Vertex) +VecT_primitive_zeroinit_method_Definition(Vertex) +SpanT_struct_Definition(Vertex) +SpanT_method_Definition(Vertex) +SpanT_VecT_method_Definition(Vertex) + +typedef struct { + VecVertex vertices; + VecU32 indexes; +} ModelTopology; + +void ModelTopology_drop(ModelTopology self) { + VecVertex_drop(self.vertices); + VecU32_drop(self.indexes); +} + +ModelTopology generate_one_fourth_of_a_cylinder(float w, float r, U32 k) { + assert(k >= 1); + const float a = M_PI_2f / (float)k; + const float l = 2 * r * sin(M_PI_4f / (float)k); + const vec2 v0tex = {r / (2 * r + w), 1 / (2 + k * l)}; + const vec2 v1tex = {(r + w) / (2 * r + w), 1 / (2 + k * l)}; + const vec2 v2tex = {r / (2 * r + w), 2 / (2 + k * l)}; + const vec2 v3tex = {(r + w) / (2 * r + w), 2 / (2 + k * l)}; + VecVertex vertices = VecVertex_new(); // todo: reserve 4 * k + 6 + VecVertex_append(&vertices, (Vertex){.pos = {0, 0, 0}, .tex = v0tex}); + VecVertex_append(&vertices, (Vertex){.pos = {w, 0, 0}, .tex = v1tex}); + VecVertex_append(&vertices, (Vertex){.pos = {0, r, 0}, .tex = v2tex}); + VecVertex_append(&vertices, (Vertex){.pos = {w, r, 0}, .tex = v3tex}); + VecVertex_append(&vertices, (Vertex){.pos = {0, 0, r}, .tex = {r / (2 * r + w), 0}}); + VecVertex_append(&vertices, (Vertex){.pos = {w, 0, r}, .tex = {(r + w) / (2 * r + w), 0}}); + for (U32 i = 1; i <= k; i++) { + VecVertex_append(&vertices, (Vertex){ + .pos = {0, cosf(a * i) * r, sinf(a * i) * r}, + .tex = vec2_add_vec2(v0tex, (vec2){r / (2 * r + w) * -sinf(a * i), 1 / (2 + k * l) * cos(a * i)}) + }); + } + for (U32 i = 1; i <= k; i++) { + VecVertex_append(&vertices, (Vertex){ + .pos = {w, cosf(a * i) * r, sinf(a * i) * r}, + .tex = vec2_add_vec2(v1tex, (vec2){r / (2 * r + w) * sinf(a * i), 1 / (2 + k * l) * cos(a * i)}) + }); + } + for (U32 i = 1; i <= k; i++) { + VecVertex_append(&vertices, (Vertex){ + .pos = {0, cosf(a * i) * r, sinf(a * i) * r}, + .tex = {v2tex.x, v2tex.y + i * l / (2 + k * l)} + }); + } + for (U32 i = 1; i <= k; i++) { + VecVertex_append(&vertices, (Vertex){ + .pos = {w, cosf(a * i) * r, sinf(a * i) * r}, + .tex = {v3tex.x, v3tex.y + i * l / (2 + k * l)} + }); + } + VecU32 indexes = VecU32_new(); // todo: reserve 3 * (2+2+2*k+2*k)< + { + U32 _span_0[] = { 5, 0, 1, 5, 4, 0, 1, 0, 3, 3, 0, 2 }; + VecU32_append_span(&indexes, (ConstSpanU32){.data = _span_0, .len = ARRAY_SIZE(_span_0)}); + } + for (U32 i = 1; i <= k; i++) { + U32 _span_1[] = { + 0, 5 + i, i > 1 ? 5 + i - 1 : 2, + 1, i > 1 ? 5 + k + i - 1 : 3, 5 + k + i, + i > 1 ? 5 + 2 * k + i - 1 : 2, 5 + 2 * k + i, i > 1 ? 5 + 3 * k + i - 1 : 3, + 5 + 3 * k + i, i > 1 ? 5 + 3 * k + i - 1 : 3, 5 + 2 * k + i + }; + VecU32_append_span(&indexes, (ConstSpanU32){.data = _span_1, .len = ARRAY_SIZE(_span_1)}); + } + return (ModelTopology){.vertices = vertices, .indexes = indexes}; +} + +typedef struct { + vec2 win_scale; +} Pipeline1PushRangeVertex; + +typedef struct { + float gamma_correction_factor; + float hdr_factor; + float lsd_factor; + float anim_time; +} Pipeline1PushRangeFragment; + +typedef struct { + mat4 t; +} Pipeline0UBO; + +#define cvec4_drop(vp) {} +#define cvec4_clone(vp) (*(vp)) + +VecT_trivmove_struct_Definition(cvec4) +VecT_trivmove_method_Definition(cvec4) +VecT_primitive_zeroinit_method_Definition(cvec4) + +typedef struct { + // I hate this so much uuuh. Capacity is not actually useful here... + Veccvec4 pixels; + size_t width; +} TextureDataR8G8B8A8; + +TextureDataR8G8B8A8 TextureDataR8G8B8A8_new(size_t width, size_t height) { + return (TextureDataR8G8B8A8){.pixels = Veccvec4_new_zeroinit(width * height), .width = width}; +} + +size_t TextureDataR8G8B8A8_get_height(const TextureDataR8G8B8A8* self) { + return self->pixels.len / self->width; +} + +void TextureDataR8G8B8A8_drop(TextureDataR8G8B8A8 self) { + Veccvec4_drop(self.pixels); +} + +cvec4* TextureDataR8G8B8A8_at(TextureDataR8G8B8A8* self, size_t x, size_t y) { + assert(x < self->width); + return Veccvec4_at(&self->pixels, x + y * self->width); +} + +TextureDataR8G8B8A8 generate_wood_texture() { + const U32 width = 100; + const U32 height = 100; + TextureDataR8G8B8A8 res = TextureDataR8G8B8A8_new(width, height); + for (U32 y = 0; y < width; y++) { + for (U32 col = 0; col < height; col++) { + *TextureDataR8G8B8A8_at(&res, col, y) = (cvec4){150, 30, 50, 255}; + } + } + for (U32 i = 0; i < 10; i++) { + for (U32 y = 0; y < height; y++) { + U32 col = 3 + i * 10 + ((30 < y + 3 * i && y - i < 60) ? 1 : 0); + + *TextureDataR8G8B8A8_at(&res, col, y) = (cvec4){130, 25, 40, 255}; + *TextureDataR8G8B8A8_at(&res, col + 1, y) = (cvec4){80, 10, 15, 255}; + *TextureDataR8G8B8A8_at(&res, col + 2, y) = (cvec4){70, 11, 12, 255}; + *TextureDataR8G8B8A8_at(&res, col + 3, y) = (cvec4){125, 20, 20, 255}; + } + } + for (U32 y = 0; y < 10; y++) { + for (U32 col = 0; col < 10; col++) { + *TextureDataR8G8B8A8_at(&res, col + 4, y + 13) = (cvec4){60, 8, 6, 255}; + } + } + return res; +} + +size_t ModelTopology_get_space_needed_for_staging_buffer(const ModelTopology* self) { + return MAX_U64(self->vertices.len * sizeof(Vertex), self->indexes.len * sizeof(U32)); +} + +size_t TextureDataR8G8B8A8_get_space_needed_for_staging_buffer(const TextureDataR8G8B8A8* self) { + return self->pixels.len * sizeof(cvec4); +} + +typedef struct { + float fov; + mat3 cam_basis; + vec3 pos; + + float speed; + float sensitivity; + float pitch_cap; +} CamControlInfo; + +void CamControlInfo_forward(CamControlInfo* self, float fl) { + self->pos = vec3_add_vec3(self->pos, vec3_mul_scal(self->cam_basis.z, -self->speed * fl)); +} + +void CamControlInfo_backward(CamControlInfo* self, float fl) { + self->pos = vec3_add_vec3(self->pos, vec3_mul_scal(self->cam_basis.z, self->speed * fl)); +} + +void CamControlInfo_left(CamControlInfo* self, float fl) { + self->pos = vec3_add_vec3(self->pos, vec3_mul_scal(self->cam_basis.x, -self->speed * fl)); +} + +void CamControlInfo_right(CamControlInfo* self, float fl) { + self->pos = vec3_add_vec3(self->pos, vec3_mul_scal(self->cam_basis.x, self->speed * fl)); +} + +void CamControlInfo_down(CamControlInfo* self, float fl) { + self->pos = vec3_add_vec3(self->pos, vec3_mul_scal((vec3){0, -1, 0}, self->speed * fl)); +} + +void CamControlInfo_up(CamControlInfo* self, float fl) { + self->pos = vec3_add_vec3(self->pos, vec3_mul_scal((vec3){0, 1, 0}, self->speed * fl)); +} + +CamControlInfo CamControlInfo_new() { + return (CamControlInfo){ + .fov = 1.5, .cam_basis = margaret_simple_camera_rot_m_basis_in_cols(0, 0, 0), .pos = {0, 0, 0}, + .speed = 2.7, .sensitivity = 0.5f * M_PIf / 180, .pitch_cap = M_PI * 0.49 + }; +} + +float clamp_float(float a, float l, float r) { + return (a < l) ? l : ((a <= r) ? a : r); +} + +void CamControlInfo_update_direction(CamControlInfo* self, int win_width, int win_height, int pointer_x, int pointer_y) { + float yaw = (float)(win_width / 2 - pointer_x) * self->sensitivity; + float pitch = clamp_float( + (float)(win_height / 2 - pointer_y) * self->sensitivity, + -self->pitch_cap, self->pitch_cap + ); + self->cam_basis = margaret_simple_camera_rot_m_basis_in_cols(yaw, pitch, 0); +} + +typedef struct { + VecModelOnScene models; + VkClearColorValue color; + float gamma_correction_factor; + float hdr_factor; + float lsd_factor; + float anim_time; // A timer, passed to functions that push push constants +} Scene; + +Scene Scene_new() { + return (Scene){.models = VecModelOnScene_new(), .color = {.float32 = {1, 0.5, 0.7}}, + .gamma_correction_factor = 2.2, .hdr_factor = 1, .lsd_factor = 0, .anim_time = 0}; +} + +void Scene_drop(Scene self) { + VecModelOnScene_drop(self.models); +} + + +#endif diff --git a/src/l2/tests/test_shaders/glsl/0/0.frag b/src/l2/tests/test_shaders/glsl/0/0.frag index a1dbad1..d75e8d2 100644 --- a/src/l2/tests/test_shaders/glsl/0/0.frag +++ b/src/l2/tests/test_shaders/glsl/0/0.frag @@ -4,6 +4,8 @@ layout(location = 0) in vec2 fsin_tex; layout(location = 0) out vec4 fin_color; +layout(binding = 1) uniform sampler2D color_tex; + void main(){ - fin_color = vec4(fsin_tex, 0, 1); + fin_color = texture(color_tex, fsin_tex); } \ No newline at end of file diff --git a/src/l2/tests/test_shaders/glsl/0/0.vert b/src/l2/tests/test_shaders/glsl/0/0.vert index d77ba17..5f93605 100644 --- a/src/l2/tests/test_shaders/glsl/0/0.vert +++ b/src/l2/tests/test_shaders/glsl/0/0.vert @@ -5,10 +5,13 @@ layout(location = 1) in vec2 tex; layout(location = 0) out vec2 vsout_tex; +layout(binding = 0) uniform ubo { + mat4 t; +}; // todo: add my ubo (location = 0) into the mix // todo: add my woiod_texture (location = 1) into the mix void main(){ vsout_tex = tex; - gl_Position = vec4(pos, 1); + gl_Position = t * vec4(pos, 1); } \ No newline at end of file diff --git a/src/l2/tests/test_shaders/glsl/1/1.frag b/src/l2/tests/test_shaders/glsl/1/1.frag index a6749a9..410676e 100644 --- a/src/l2/tests/test_shaders/glsl/1/1.frag +++ b/src/l2/tests/test_shaders/glsl/1/1.frag @@ -5,11 +5,14 @@ layout(location = 0) out vec4 fin_color; layout(binding = 0) uniform sampler2D prev; +layout(push_constant, std430) uniform pc { + layout(offset = 8) float gamma_correction_factor; + float hdr_factor; + float lsd_factor; + float anim_time; +}; + void main() { vec2 tex_offset = 1.0 / textureSize(prev, 0); -// fin_color = texture(wood_texture, gl_FragCoord.xy * tex_offset); - - fin_color = (texture(prev, fsin_tex + tex_offset * vec2(1, 0)) + texture(prev, fsin_tex + tex_offset * vec2(-1, 0)) + - texture(prev, fsin_tex + tex_offset * vec2(0, 1)) + texture(prev, fsin_tex + tex_offset * vec2(0, -1)) - 4 * - texture(prev, fsin_tex + tex_offset * vec2(0, 0))) / 8; + fin_color = texture(prev, gl_FragCoord.xy * tex_offset); }