Added shiny mesh to r0, but something seems wrong
This commit is contained in:
parent
7158a15b5b
commit
e49b76fffa
@ -4,17 +4,16 @@
|
||||
#include "../../l1/system/fsmanip.h"
|
||||
#include "../../l1/codegen/util_template_inst.h"
|
||||
|
||||
// todo: generate here eve headers for margaret and for tests (long asset description files in r0)
|
||||
|
||||
void eve_of_l2() {
|
||||
make_dir_nofail("l2/eve");
|
||||
make_dir_nofail("l2/eve/r0");
|
||||
/* Needed in r0_assets.h */
|
||||
generate_eve_span_garden_for_primitive(cstr("l2"), cstr("r0"), cstr("GenericMeshVertex"), true, false);
|
||||
generate_eve_span_garden_for_non_primitive_clonable(cstr("l2"), cstr("r0"), cstr("ModelInSceneTemplate"), true, false);
|
||||
generate_eve_span_garden_for_primitive(cstr("l2"), cstr("r0"), cstr("GenericMeshVertex"), true, true);
|
||||
generate_eve_span_garden_for_non_primitive_clonable(cstr("l2"), cstr("r0"), cstr("GenericMeshInSceneTemplate"), true, false);
|
||||
generate_eve_span_garden_for_primitive(cstr("l2"), cstr("r0"), cstr("GenericMeshInstance"), true, false);
|
||||
generate_eve_span_garden_for_primitive(cstr("l2"), cstr("r0"), cstr("ShinyMeshVertex"), true, false);
|
||||
generate_eve_span_garden_for_primitive(cstr("l2"), cstr("r0"), cstr("ShinyMeshVertex"), true, true);
|
||||
generate_eve_span_garden_for_primitive(cstr("l2"), cstr("r0"), cstr("ShinyMeshInstance"), true, false);
|
||||
generate_eve_span_garden_for_non_primitive_clonable(cstr("l2"), cstr("r0"), cstr("ShinyMeshInSceneTemplate"), true, false);
|
||||
generate_eve_span_garden_for_primitive(cstr("l2"), cstr("r0"), cstr("Pipeline0Spotlight"), true, false);
|
||||
generate_eve_span_garden_for_primitive(cstr("l2"), cstr("r0"), cstr("Pipeline0PointLight"), true, false);
|
||||
generate_eve_span_garden_for_primitive(cstr("l2"), cstr("r0"), cstr("Wimbzle"), true, false);
|
||||
@ -23,11 +22,10 @@ void eve_of_l2() {
|
||||
generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("MarieTriangle"), true, false);
|
||||
generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("MarieTriangleAttr"), true, false);
|
||||
/* Needed in r0_scene.h */
|
||||
generate_eve_span_garden_for_primitive(cstr("l2"), cstr("r0"), cstr("ModelOnScene"), true, false);
|
||||
generate_eve_span_garden_for_non_primitive_clonable(cstr("l2"), cstr("r0"), cstr("UsedModelOnScene"), true, false);
|
||||
generate_eve_span_garden_for_non_primitive_non_clonable(cstr("l2"), cstr("r0"), cstr("UsedGenericModelOnScene"), true, false);
|
||||
generate_eve_span_garden_for_non_primitive_non_clonable(cstr("l2"), cstr("r0"), cstr("UsedShinyModelOnScene"), true, false);
|
||||
/* Needed in margaret/vulkan.h */
|
||||
generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("CSTR"), true, false);
|
||||
// generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("MargaretChosenQueueFamilies"), true, false);
|
||||
generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("VkQueueFamilyProperties"), true, false);
|
||||
generate_eve_span_garden_for_primitive(cstr("l2"), cstr(""), cstr("VkExtensionProperties"), true, false);
|
||||
generate_eve_header(cstr("l2"), cstr(""), cstr("VkSurfaceFormatKHR"),
|
||||
|
||||
@ -94,7 +94,14 @@ VkRenderPass create_render_pass_0(VkDevice logical_device, VkFormat colorbuffer_
|
||||
return render_pass;
|
||||
}
|
||||
|
||||
margaret_prep_buffer_mem_info_of_gpu_vbo_Definition(GenericMeshVertex)
|
||||
MargaretBufferInMemoryInfo GenericMeshVertex_buffer_crinfo_of_gpu_vbo(size_t n) {
|
||||
return (MargaretBufferInMemoryInfo){ .sz = safe_mul_U64(sizeof(GenericMeshVertex), n),
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT };
|
||||
}
|
||||
MargaretBufferInMemoryInfo ShinyMeshVertex_buffer_crinfo_of_gpu_vbo(size_t n) {
|
||||
return (MargaretBufferInMemoryInfo){ .sz = safe_mul_U64(sizeof(ShinyMeshVertex), n),
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT };
|
||||
}
|
||||
|
||||
PipelineHands create_graphics_pipeline_0(
|
||||
VkDevice device, VkRenderPass render_pass, uint32_t subpass
|
||||
@ -133,7 +140,7 @@ PipelineHands create_graphics_pipeline_0(
|
||||
{
|
||||
.location = 1,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT,
|
||||
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
.offset = offsetof(GenericMeshVertex, tex),
|
||||
},
|
||||
|
||||
@ -319,6 +326,229 @@ PipelineHands create_graphics_pipeline_0(
|
||||
return (PipelineHands){.pipeline_layout = pipeline_layout, .pipeline = pipeline, .descriptor_set_layout = my_descriptor_set_layout};
|
||||
}
|
||||
|
||||
PipelineHands create_graphics_pipeline_0_b(
|
||||
VkDevice device, VkRenderPass render_pass, uint32_t subpass
|
||||
) {
|
||||
VecU8 vert_bin_code = read_whole_file_or_abort("shaders/spv/0b/vert.spv");
|
||||
VecU8 frag_bin_code = read_whole_file_or_abort("shaders/spv/0b/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[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 + 6] = {
|
||||
{
|
||||
.location = 0,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
.offset = offsetof(ShinyMeshVertex, pos),
|
||||
},
|
||||
{
|
||||
.location = 1,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
.offset = offsetof(ShinyMeshVertex, normal),
|
||||
},
|
||||
|
||||
/* This is a mat4 datatype, so it will take 4 entire 'locations' */
|
||||
{
|
||||
.location = 2,
|
||||
.binding = 1,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = offsetof(ShinyMeshInstance, model_t) + offsetof(mat4, x)
|
||||
},
|
||||
{
|
||||
.location = 3,
|
||||
.binding = 1,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = offsetof(ShinyMeshInstance, model_t) + offsetof(mat4, y)
|
||||
},
|
||||
{
|
||||
.location = 4,
|
||||
.binding = 1,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = offsetof(ShinyMeshInstance, model_t) + offsetof(mat4, z)
|
||||
},
|
||||
{
|
||||
.location = 5,
|
||||
.binding = 1,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = offsetof(ShinyMeshInstance, model_t) + offsetof(mat4, w)
|
||||
},
|
||||
{
|
||||
.location = 6,
|
||||
.binding = 1,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = offsetof(ShinyMeshInstance, color_off)
|
||||
},
|
||||
{
|
||||
.location = 7,
|
||||
.binding = 1,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = offsetof(ShinyMeshInstance, color_on)
|
||||
},
|
||||
};
|
||||
|
||||
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,
|
||||
.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,
|
||||
};
|
||||
|
||||
VkPipelineDepthStencilStateCreateInfo depth_stencil_state_crinfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
||||
.depthTestEnable = VK_TRUE,
|
||||
.depthWriteEnable = VK_TRUE,
|
||||
.depthCompareOp = VK_COMPARE_OP_LESS
|
||||
};
|
||||
|
||||
// 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 = 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,
|
||||
},
|
||||
};
|
||||
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");
|
||||
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 = &depth_stencil_state_crinfo,
|
||||
.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) {
|
||||
@ -538,11 +768,30 @@ VkFramebuffer create_IT1_framebuffer(VkDevice device, VkImageView IT1_view, VkIm
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
void record_cmd_set_viewport_and_scissors(VkCommandBuffer command_buffer, VkExtent2D image_extent) {
|
||||
VkViewport viewport = {
|
||||
.x = 0.0f,
|
||||
.y = 0.0f,
|
||||
.width = (float)(image_extent.width),
|
||||
.height = (float)(image_extent.height),
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f,
|
||||
};
|
||||
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
|
||||
VkRect2D scissor = {
|
||||
.offset = (VkOffset2D){0, 0},
|
||||
.extent = image_extent,
|
||||
};
|
||||
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
|
||||
}
|
||||
|
||||
void reset_and_record_command_buffer_0(
|
||||
VkCommandBuffer command_buffer, VkRenderPass render_pass_0,
|
||||
const PipelineHands* pipeline_and_layout,
|
||||
VkFramebuffer swapchain_image_framebuffer, VkImage IT1_image, VkExtent2D image_extent,
|
||||
const Scene* scene, VkDescriptorSet my_descriptor_set, mat4 proj_cam_t, vec3 camera_pos
|
||||
const PipelineHands* pipeline_and_layout_0a, const PipelineHands* pipeline_and_layout_0b,
|
||||
VkFramebuffer result_framebuffer, VkExtent2D image_extent,
|
||||
const Scene* scene,
|
||||
VkDescriptorSet descriptor_set_for_pipeline_0a, VkDescriptorSet descriptor_set_for_pipeline_0b,
|
||||
mat4 proj_cam_t, vec3 camera_pos
|
||||
) {
|
||||
if (vkResetCommandBuffer(command_buffer, 0) != VK_SUCCESS)
|
||||
abortf("vkResetCommandBuffer");
|
||||
@ -554,7 +803,7 @@ void reset_and_record_command_buffer_0(
|
||||
VkRenderPassBeginInfo renderpass_begin = {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
.renderPass = render_pass_0,
|
||||
.framebuffer = swapchain_image_framebuffer,
|
||||
.framebuffer = result_framebuffer,
|
||||
.renderArea.offset = (VkOffset2D){0, 0},
|
||||
.renderArea.extent = image_extent,
|
||||
.clearValueCount = ARRAY_SIZE(clear_values),
|
||||
@ -562,39 +811,45 @@ void reset_and_record_command_buffer_0(
|
||||
};
|
||||
|
||||
vkCmdBeginRenderPass(command_buffer, &renderpass_begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout->pipeline);
|
||||
|
||||
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout_0a->pipeline);
|
||||
// We forgot that viewport is not built into our pipeline
|
||||
VkViewport viewport = {
|
||||
.x = 0.0f,
|
||||
.y = 0.0f,
|
||||
.width = (float)(image_extent.width),
|
||||
.height = (float)(image_extent.height),
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f,
|
||||
};
|
||||
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
|
||||
// We forgot that scissors are not built into out pipeline
|
||||
VkRect2D scissor = {
|
||||
.offset = (VkOffset2D){0, 0},
|
||||
.extent = image_extent,
|
||||
};
|
||||
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
|
||||
vkCmdPushConstants(command_buffer, pipeline_and_layout->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT,
|
||||
record_cmd_set_viewport_and_scissors(command_buffer, image_extent);
|
||||
vkCmdPushConstants(command_buffer, pipeline_and_layout_0a->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT,
|
||||
0, sizeof(mat4), &proj_cam_t);
|
||||
vkCmdPushConstants(command_buffer, pipeline_and_layout->pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
vkCmdPushConstants(command_buffer, pipeline_and_layout_0a->pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
sizeof(mat4), sizeof(vec3), &camera_pos);
|
||||
for (size_t i = 0; i < scene->models.len; i++) {
|
||||
const UsedModelOnScene* model = VecUsedModelOnScene_at(&scene->models, i);
|
||||
VkBuffer attached_buffers[2] = { model->model.vbo, model->instance_attr_buf };
|
||||
for (size_t i = 0; i < scene->generic_models.len; i++) {
|
||||
const UsedGenericModelOnScene *model = VecUsedGenericModelOnScene_at(&scene->generic_models, i);
|
||||
VkBuffer attached_buffers[2] = { model->model.vbo, model->model.instance_attr_buf };
|
||||
// We use our whole buffer, no need for offset
|
||||
VkDeviceSize offsets_in_buffers[2] = {0, model->instance_attr_buf_offset};
|
||||
VkDeviceSize offsets_in_buffers[2] = {0, model->model.instance_attr_buf_offset};
|
||||
assert(ARRAY_SIZE(attached_buffers) == 2 && ARRAY_SIZE(offsets_in_buffers) == 2);
|
||||
vkCmdBindVertexBuffers(command_buffer, 0, 2, attached_buffers, offsets_in_buffers);
|
||||
vkCmdBindIndexBuffer(command_buffer, model->model.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);
|
||||
command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout_0a->pipeline_layout, 0,
|
||||
1, &descriptor_set_for_pipeline_0a, 0, NULL);
|
||||
vkCmdDrawIndexed(command_buffer, model->model.indexes, model->instances.len, 0, 0, 0);
|
||||
}
|
||||
|
||||
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout_0b->pipeline);
|
||||
record_cmd_set_viewport_and_scissors(command_buffer, image_extent);
|
||||
vkCmdPushConstants(command_buffer, pipeline_and_layout_0b->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT,
|
||||
0, sizeof(mat4), &proj_cam_t);
|
||||
vkCmdPushConstants(command_buffer, pipeline_and_layout_0b->pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
sizeof(mat4), sizeof(vec3), &camera_pos);
|
||||
for (size_t i = 0; i < scene->shiny_models.len; i++) {
|
||||
const UsedShinyModelOnScene* model = VecUsedShinyModelOnScene_at(&scene->shiny_models, i);
|
||||
VkBuffer attached_buffers[2] = { model->model.vbo, model->model.instance_attr_buf };
|
||||
// We use our whole buffer, no need for offset
|
||||
VkDeviceSize offsets_in_buffers[2] = {0, model->model.instance_attr_buf_offset};
|
||||
assert(ARRAY_SIZE(attached_buffers) == 2 && ARRAY_SIZE(offsets_in_buffers) == 2);
|
||||
vkCmdBindVertexBuffers(command_buffer, 0, 2, attached_buffers, offsets_in_buffers);
|
||||
vkCmdBindIndexBuffer(command_buffer, model->model.ebo, 0, VK_INDEX_TYPE_UINT32);
|
||||
vkCmdBindDescriptorSets(
|
||||
command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout_0b->pipeline_layout, 0,
|
||||
1, &descriptor_set_for_pipeline_0b, 0, NULL);
|
||||
vkCmdDrawIndexed(command_buffer, model->model.indexes, model->instances.len, 0, 0, 0);
|
||||
}
|
||||
|
||||
@ -627,20 +882,7 @@ void reset_and_record_command_buffer_1(
|
||||
vkCmdBeginRenderPass(command_buffer, &renderpass_begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout_1->pipeline);
|
||||
|
||||
VkViewport viewport = {
|
||||
.x = 0.0f,
|
||||
.y = 0.0f,
|
||||
.width = (float)(image_extent.width),
|
||||
.height = (float)(image_extent.height),
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f,
|
||||
};
|
||||
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
|
||||
VkRect2D scissor = {
|
||||
.offset = (VkOffset2D){0, 0},
|
||||
.extent = image_extent,
|
||||
};
|
||||
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
|
||||
record_cmd_set_viewport_and_scissors(command_buffer, image_extent);
|
||||
vkCmdBindDescriptorSets(
|
||||
command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout_1->pipeline_layout, 0,
|
||||
1, &descriptor_set_for_pipeline_1, 0, NULL);
|
||||
@ -666,13 +908,14 @@ void reset_and_record_command_buffer_1(
|
||||
abortf("vkEndCommandBuffer");
|
||||
}
|
||||
|
||||
// todo: kill myself
|
||||
/* First, we copy our scene information to void* host_mem_buffer_mem.
|
||||
* Then, we record a command buffer that would copy these specific regions to corresponding device buffers
|
||||
* It's up to you to submit command_buffer
|
||||
* */
|
||||
void copy_scene_info_to_buffer_and_rerecord_full_copy_command_buffer(
|
||||
VkCommandBuffer command_buffer, VkBuffer host_memory_buffer, char* host_mem_buffer_mem, const Scene* scene,
|
||||
VkBuffer device_lighting_ubo, VkBuffer device_instance_attrs_for_all_generic_meshes
|
||||
VkBuffer device_lighting_ubo, VkBuffer device_instance_attrs_for_models
|
||||
) {
|
||||
|
||||
if (vkResetCommandBuffer(command_buffer, 0) != VK_SUCCESS)
|
||||
@ -681,21 +924,32 @@ void copy_scene_info_to_buffer_and_rerecord_full_copy_command_buffer(
|
||||
if (vkBeginCommandBuffer(command_buffer, &info_begin) != VK_SUCCESS)
|
||||
abortf("vkBeginCommandBuffer");
|
||||
|
||||
// todo: rewrite this entire fucking shit
|
||||
size_t offset_here = 0;
|
||||
{
|
||||
size_t offset_in_mesh_instance_buf = 0;
|
||||
VecVkBufferCopy regions_to_copy_A = VecVkBufferCopy_new();
|
||||
for (size_t mi = 0; mi < scene->models.len; mi++) {
|
||||
const UsedModelOnScene* model = VecUsedModelOnScene_at(&scene->models, mi);
|
||||
assert(model->instances.len <= model->limit_max_instance_count);
|
||||
for (size_t mi = 0; mi < scene->generic_models.len; mi++) {
|
||||
const UsedGenericModelOnScene* model = VecUsedGenericModelOnScene_at(&scene->generic_models, mi);
|
||||
assert(model->instances.len <= model->model.limit_max_instance_count);
|
||||
size_t all = model->instances.len * sizeof(GenericMeshInstance);
|
||||
memcpy(host_mem_buffer_mem + offset_here, model->instances.buf, all);
|
||||
/* Right now we don't combine multiple vkCmdCopyBuffer commands with same src and dst buffers into one, but later we should do it */
|
||||
VecVkBufferCopy_append(®ions_to_copy_A, (VkBufferCopy){.srcOffset = offset_here, .dstOffset = offset_in_mesh_instance_buf, .size = all});
|
||||
offset_here += all;
|
||||
offset_in_mesh_instance_buf += model->limit_max_instance_count * sizeof(GenericMeshInstance);
|
||||
offset_in_mesh_instance_buf += model->model.limit_max_instance_count * sizeof(GenericMeshInstance);
|
||||
}
|
||||
vkCmdCopyBuffer(command_buffer, host_memory_buffer, device_instance_attrs_for_all_generic_meshes, regions_to_copy_A.len, regions_to_copy_A.buf);
|
||||
for (size_t mi = 0; mi < scene->shiny_models.len; mi++) {
|
||||
const UsedShinyModelOnScene* model = VecUsedShinyModelOnScene_at(&scene->shiny_models, mi);
|
||||
assert(model->instances.len <= model->model.limit_max_instance_count);
|
||||
size_t all = model->instances.len * sizeof(ShinyMeshInstance);
|
||||
memcpy(host_mem_buffer_mem + offset_here, model->instances.buf, all);
|
||||
/* Right now we don't combine multiple vkCmdCopyBuffer commands with same src and dst buffers into one, but later we should do it */
|
||||
VecVkBufferCopy_append(®ions_to_copy_A, (VkBufferCopy){.srcOffset = offset_here, .dstOffset = offset_in_mesh_instance_buf, .size = all});
|
||||
offset_here += all;
|
||||
offset_in_mesh_instance_buf += model->model.limit_max_instance_count * sizeof(ShinyMeshInstance);
|
||||
}
|
||||
vkCmdCopyBuffer(command_buffer, host_memory_buffer, device_instance_attrs_for_models, regions_to_copy_A.len, regions_to_copy_A.buf);
|
||||
VecVkBufferCopy_drop(regions_to_copy_A);
|
||||
}
|
||||
{
|
||||
@ -734,7 +988,6 @@ void copy_scene_info_to_buffer_and_rerecord_full_copy_command_buffer(
|
||||
abortf("vkEndCommandBuffer");
|
||||
}
|
||||
|
||||
// todo: generate this structure in l2
|
||||
typedef struct {
|
||||
VkSemaphore in_frame_transfer_complete;
|
||||
VkSemaphore image_available_semaphore;
|
||||
@ -774,7 +1027,8 @@ typedef struct {
|
||||
VkFormat zbuffer_format;
|
||||
VkFormat IT1_format;
|
||||
VkRenderPass render_pass_0;
|
||||
PipelineHands pipeline_hands_0;
|
||||
PipelineHands pipeline_hands_0a;
|
||||
PipelineHands pipeline_hands_0b;
|
||||
VkRenderPass render_pass_1;
|
||||
PipelineHands pipeline_hands_1;
|
||||
Jane_r0 jane;
|
||||
@ -785,9 +1039,12 @@ typedef struct {
|
||||
TextureDataR8G8B8A8 cyl_1_normal_tex;
|
||||
MargaretBufferInMemoryInfo host_mem_buffer;
|
||||
VkDeviceMemory host_mem;
|
||||
VecMargaretBufferInMemoryInfo device_ebo_and_vbo_buffers_for_generic_meshes;
|
||||
VecMargaretBufferInMemoryInfo device_ebo_buffers_for_generic_meshes;
|
||||
VecMargaretBufferInMemoryInfo device_vbo_buffers_for_generic_meshes;
|
||||
VecMargaretBufferInMemoryInfo device_ebo_buffers_for_shiny_meshes;
|
||||
VecMargaretBufferInMemoryInfo device_vbo_buffers_for_shiny_meshes;
|
||||
MargaretBufferInMemoryInfo device_lighting_ubo;
|
||||
MargaretBufferInMemoryInfo device_instance_attrs_for_all_generic_meshes;
|
||||
MargaretBufferInMemoryInfo device_instance_attrs_for_models;
|
||||
MargaretImageInMemoryInfo device_IT1_image;
|
||||
MargaretImageInMemoryInfo device_zbuffer_image;
|
||||
MargaretImageInMemoryInfo device_cyl_1_diffuse_texture;
|
||||
@ -811,7 +1068,8 @@ typedef struct {
|
||||
VkSampler linear_sampler;
|
||||
VkSampler nearest_sampler;
|
||||
VkDescriptorPool descriptor_pool;
|
||||
VkDescriptorSet descriptor_set_for_pipeline_0;
|
||||
VkDescriptorSet descriptor_set_for_pipeline_0a;
|
||||
VkDescriptorSet descriptor_set_for_pipeline_0b;
|
||||
VkDescriptorSet descriptor_set_for_pipeline_1;
|
||||
|
||||
CamControlInfo my_cam_control_info;
|
||||
@ -898,25 +1156,25 @@ void update_state(state_r0* state, uint32_t dur) {
|
||||
|
||||
if (state->first_0x80_keys[XKB_KEY_j]) {
|
||||
state->vk_ctx.Buba_control_info.x -= fl;
|
||||
VecGenericMeshInstance_mat(&VecUsedModelOnScene_mat(&state->vk_ctx.scene.models, 1)->instances, 0)->model_t =
|
||||
VecGenericMeshInstance_mat(&VecUsedGenericModelOnScene_mat(&state->vk_ctx.scene.generic_models, 1)->instances, 0)->model_t =
|
||||
marie_translation_mat4(state->vk_ctx.Buba_control_info);
|
||||
state->vk_ctx.dt_transfer_required = true;
|
||||
}
|
||||
if (state->first_0x80_keys[XKB_KEY_k]) {
|
||||
state->vk_ctx.Buba_control_info.z -= fl;
|
||||
VecGenericMeshInstance_mat(&VecUsedModelOnScene_mat(&state->vk_ctx.scene.models, 1)->instances, 0)->model_t =
|
||||
VecGenericMeshInstance_mat(&VecUsedGenericModelOnScene_mat(&state->vk_ctx.scene.generic_models, 1)->instances, 0)->model_t =
|
||||
marie_translation_mat4(state->vk_ctx.Buba_control_info);
|
||||
state->vk_ctx.dt_transfer_required = true;
|
||||
}
|
||||
if (state->first_0x80_keys[XKB_KEY_l]) {
|
||||
state->vk_ctx.Buba_control_info.z += fl;
|
||||
VecGenericMeshInstance_mat(&VecUsedModelOnScene_mat(&state->vk_ctx.scene.models, 1)->instances, 0)->model_t =
|
||||
VecGenericMeshInstance_mat(&VecUsedGenericModelOnScene_mat(&state->vk_ctx.scene.generic_models, 1)->instances, 0)->model_t =
|
||||
marie_translation_mat4(state->vk_ctx.Buba_control_info);
|
||||
state->vk_ctx.dt_transfer_required = true;
|
||||
}
|
||||
if (state->first_0x80_keys[XKB_KEY_semicolon]) {
|
||||
state->vk_ctx.Buba_control_info.x += fl;
|
||||
VecGenericMeshInstance_mat(&VecUsedModelOnScene_mat(&state->vk_ctx.scene.models, 1)->instances, 0)->model_t =
|
||||
VecGenericMeshInstance_mat(&VecUsedGenericModelOnScene_mat(&state->vk_ctx.scene.generic_models, 1)->instances, 0)->model_t =
|
||||
marie_translation_mat4(state->vk_ctx.Buba_control_info);
|
||||
state->vk_ctx.dt_transfer_required = true;
|
||||
}
|
||||
@ -958,7 +1216,7 @@ void vulkano_frame_drawing(state_r0* state) {
|
||||
copy_scene_info_to_buffer_and_rerecord_full_copy_command_buffer(
|
||||
state->vk_ctx.transfer_command_buffer, state->vk_ctx.host_mem_buffer.buffer,
|
||||
state->vk_ctx.host_mem_buffer_mem, &state->vk_ctx.scene, state->vk_ctx.device_lighting_ubo.buffer,
|
||||
state->vk_ctx.device_instance_attrs_for_all_generic_meshes.buffer);
|
||||
state->vk_ctx.device_instance_attrs_for_models.buffer);
|
||||
VkCommandBuffer command_buffers[1] = { state->vk_ctx.transfer_command_buffer };
|
||||
VkSemaphore signaling_semaphores[1] = { state->vk_ctx.jane.in_frame_transfer_complete };
|
||||
VkSubmitInfo submit_info = {
|
||||
@ -973,10 +1231,12 @@ void vulkano_frame_drawing(state_r0* state) {
|
||||
}
|
||||
|
||||
reset_and_record_command_buffer_0(
|
||||
state->vk_ctx.rendering_command_buffer_0, state->vk_ctx.render_pass_0, &state->vk_ctx.pipeline_hands_0,
|
||||
state->vk_ctx.IT1_framebuffer, state->vk_ctx.device_IT1_image.image, state->vk_ctx.swfb.extent,
|
||||
state->vk_ctx.rendering_command_buffer_0, state->vk_ctx.render_pass_0,
|
||||
&state->vk_ctx.pipeline_hands_0a, &state->vk_ctx.pipeline_hands_0b,
|
||||
state->vk_ctx.IT1_framebuffer, state->vk_ctx.swfb.extent,
|
||||
&state->vk_ctx.scene,
|
||||
state->vk_ctx.descriptor_set_for_pipeline_0, t_mat, state->vk_ctx.my_cam_control_info.pos);
|
||||
state->vk_ctx.descriptor_set_for_pipeline_0a, state->vk_ctx.descriptor_set_for_pipeline_0b,
|
||||
t_mat, state->vk_ctx.my_cam_control_info.pos);
|
||||
|
||||
reset_and_record_command_buffer_1(state->vk_ctx.rendering_command_buffer_1, state->vk_ctx.render_pass_1,
|
||||
&state->vk_ctx.pipeline_hands_1,
|
||||
@ -1390,6 +1650,7 @@ void compile_shader_dir(SpanU8 name) {
|
||||
|
||||
int main() {
|
||||
compile_shader_dir(cstr("0"));
|
||||
compile_shader_dir(cstr("0b"));
|
||||
compile_shader_dir(cstr("1"));
|
||||
|
||||
SpanU8 GPU = cstr("nvidia");
|
||||
@ -1477,7 +1738,8 @@ int main() {
|
||||
state.vk_ctx.IT1_format = IT1_format.some;
|
||||
|
||||
state.vk_ctx.render_pass_0 = create_render_pass_0(state.vk_ctx.device, IT1_format.some, zbuffer_format.some);
|
||||
state.vk_ctx.pipeline_hands_0 = create_graphics_pipeline_0(state.vk_ctx.device, state.vk_ctx.render_pass_0, 0);
|
||||
state.vk_ctx.pipeline_hands_0a = create_graphics_pipeline_0(state.vk_ctx.device, state.vk_ctx.render_pass_0, 0);
|
||||
state.vk_ctx.pipeline_hands_0b = create_graphics_pipeline_0_b(state.vk_ctx.device, state.vk_ctx.render_pass_0, 0);
|
||||
|
||||
state.vk_ctx.render_pass_1 = create_render_pass_1(state.vk_ctx.device, swapchain_details_res.ok.surface_format.format);
|
||||
state.vk_ctx.pipeline_hands_1 = create_graphics_pipeline_1(state.vk_ctx.device, state.vk_ctx.render_pass_1, 0);
|
||||
@ -1486,13 +1748,22 @@ int main() {
|
||||
state.vk_ctx.device, state.vk_ctx.queue_fam, swapchain_details_res.ok,
|
||||
state.vk_ctx.surface, state.vk_ctx.render_pass_1, NULL);
|
||||
|
||||
state.vk_ctx.scene_template = (SceneTemplate){.models = VecModelInSceneTemplate_new(),
|
||||
state.vk_ctx.scene_template = (SceneTemplate){
|
||||
.generic_models = VecGenericMeshInSceneTemplate_new(),
|
||||
.shiny_models = VecShinyMeshInSceneTemplate_new(),
|
||||
.point_lights_max_count = pipeline_0_ubo_point_light_max_count,
|
||||
.spotlights_max_count = pipeline_0_ubo_spotlight_max_count};
|
||||
VecModelInSceneTemplate_append(&state.vk_ctx.scene_template.models,
|
||||
(ModelInSceneTemplate){.topology = generate_one_fourth_of_a_cylinder(10, 2, 6), .max_instance_count = 100});
|
||||
VecModelInSceneTemplate_append(&state.vk_ctx.scene_template.models,
|
||||
(ModelInSceneTemplate){.topology = generate_one_fourth_of_a_cylinder(5, 5, 10), .max_instance_count = 1});
|
||||
VecGenericMeshInSceneTemplate_append(&state.vk_ctx.scene_template.generic_models,
|
||||
(GenericMeshInSceneTemplate){.topology = generate_one_fourth_of_a_cylinder(10, 2, 6), .max_instance_count = 100});
|
||||
VecGenericMeshInSceneTemplate_append(&state.vk_ctx.scene_template.generic_models,
|
||||
(GenericMeshInSceneTemplate){.topology = generate_one_fourth_of_a_cylinder(5, 5, 10), .max_instance_count = 1});
|
||||
VecShinyMeshInSceneTemplate_append(&state.vk_ctx.scene_template.shiny_models, (ShinyMeshInSceneTemplate){
|
||||
.topology = generate_shiny_rhombicuboctahedron(0.5f), .max_instance_count = 5
|
||||
});
|
||||
VecShinyMeshInSceneTemplate_append(&state.vk_ctx.scene_template.shiny_models, (ShinyMeshInSceneTemplate){
|
||||
.topology = generate_shiny_cube(0.5f), .max_instance_count = 5
|
||||
});
|
||||
// todo: generate more cool shiny models
|
||||
|
||||
// todo: learn how to use libpng
|
||||
state.vk_ctx.cyl_1_diffuse_tex = TextureDataR8G8B8A8_read_from_file("textures/log_10_2_6.r8g8b8a8");
|
||||
@ -1516,27 +1787,51 @@ int main() {
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
|
||||
// todo: split this in two (or maybe even better: merge it all into one/two buffer and use offsets
|
||||
state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes = VecMargaretBufferInMemoryInfo_new();
|
||||
for (size_t mi = 0; mi < state.vk_ctx.scene_template.models.len; mi++) {
|
||||
const ModelInSceneTemplate* M = VecModelInSceneTemplate_at(&state.vk_ctx.scene_template.models, mi);
|
||||
VecMargaretBufferInMemoryInfo_append(&state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes,
|
||||
state.vk_ctx.device_ebo_buffers_for_generic_meshes = VecMargaretBufferInMemoryInfo_new();
|
||||
state.vk_ctx.device_vbo_buffers_for_generic_meshes = VecMargaretBufferInMemoryInfo_new();
|
||||
for (size_t mi = 0; mi < state.vk_ctx.scene_template.generic_models.len; mi++) {
|
||||
const GenericMeshInSceneTemplate* M = VecGenericMeshInSceneTemplate_at(&state.vk_ctx.scene_template.generic_models, mi);
|
||||
VecMargaretBufferInMemoryInfo_append(&state.vk_ctx.device_vbo_buffers_for_generic_meshes,
|
||||
GenericMeshVertex_buffer_crinfo_of_gpu_vbo(M->topology.vertices.len));
|
||||
VecMargaretBufferInMemoryInfo_append(&state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes,
|
||||
VecMargaretBufferInMemoryInfo_append(&state.vk_ctx.device_ebo_buffers_for_generic_meshes,
|
||||
margaret_prep_buffer_mem_info_of_gpu_ebo(M->topology.indexes.len));
|
||||
}
|
||||
state.vk_ctx.device_ebo_buffers_for_shiny_meshes = VecMargaretBufferInMemoryInfo_new();
|
||||
state.vk_ctx.device_vbo_buffers_for_shiny_meshes = VecMargaretBufferInMemoryInfo_new();
|
||||
for (size_t mi = 0; mi < state.vk_ctx.scene_template.shiny_models.len; mi++) {
|
||||
const ShinyMeshInSceneTemplate* M = VecShinyMeshInSceneTemplate_at(&state.vk_ctx.scene_template.shiny_models, mi);
|
||||
VecMargaretBufferInMemoryInfo_append(&state.vk_ctx.device_vbo_buffers_for_shiny_meshes,
|
||||
ShinyMeshVertex_buffer_crinfo_of_gpu_vbo(M->topology.vertices.len));
|
||||
VecMargaretBufferInMemoryInfo_append(&state.vk_ctx.device_ebo_buffers_for_shiny_meshes,
|
||||
margaret_prep_buffer_mem_info_of_gpu_ebo(M->topology.indexes.len));
|
||||
}
|
||||
|
||||
state.vk_ctx.device_lighting_ubo = margaret_prep_buffer_mem_info_of_gpu_ubo(sizeof(Pipeline0UBO));
|
||||
state.vk_ctx.device_instance_attrs_for_all_generic_meshes = (MargaretBufferInMemoryInfo){
|
||||
state.vk_ctx.device_instance_attrs_for_models = (MargaretBufferInMemoryInfo){
|
||||
.sz = SceneTemplate_get_space_needed_for_all_instance_attributes(&state.vk_ctx.scene_template),
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
|
||||
};
|
||||
|
||||
VecPtrMargaretBufferInMemoryInfo device_mem_buffers_SPAN = VecPtrMargaretBufferInMemoryInfo_new();
|
||||
for (size_t i = 0; i < state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes.len; i++) {
|
||||
// todo: add iteration macro generation
|
||||
for (size_t i = 0; i < state.vk_ctx.device_ebo_buffers_for_generic_meshes.len; i++) {
|
||||
VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN,
|
||||
VecMargaretBufferInMemoryInfo_mat(&state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes, i));
|
||||
VecMargaretBufferInMemoryInfo_mat(&state.vk_ctx.device_ebo_buffers_for_generic_meshes, i));
|
||||
}
|
||||
for (size_t i = 0; i < state.vk_ctx.device_vbo_buffers_for_generic_meshes.len; i++) {
|
||||
VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN,
|
||||
VecMargaretBufferInMemoryInfo_mat(&state.vk_ctx.device_vbo_buffers_for_generic_meshes, i));
|
||||
}
|
||||
for (size_t i = 0; i < state.vk_ctx.device_ebo_buffers_for_shiny_meshes.len; i++) {
|
||||
VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN,
|
||||
VecMargaretBufferInMemoryInfo_mat(&state.vk_ctx.device_ebo_buffers_for_shiny_meshes, i));
|
||||
}
|
||||
for (size_t i = 0; i < state.vk_ctx.device_vbo_buffers_for_shiny_meshes.len; i++) {
|
||||
VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN,
|
||||
VecMargaretBufferInMemoryInfo_mat(&state.vk_ctx.device_vbo_buffers_for_shiny_meshes, i));
|
||||
}
|
||||
VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &state.vk_ctx.device_lighting_ubo);
|
||||
VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &state.vk_ctx.device_instance_attrs_for_all_generic_meshes);
|
||||
VecPtrMargaretBufferInMemoryInfo_append(&device_mem_buffers_SPAN, &state.vk_ctx.device_instance_attrs_for_models);
|
||||
|
||||
state.vk_ctx.device_IT1_image = margaret_prep_image_mem_info_of_colorbuffer(
|
||||
MAX_WIN_WIDTH, MAX_WIN_HEIGHT, IT1_format.some);
|
||||
@ -1563,37 +1858,67 @@ int main() {
|
||||
state.vk_ctx.rendering_command_buffer_1 = margaret_allocate_command_buffer(state.vk_ctx.device, state.vk_ctx.command_pool);
|
||||
state.vk_ctx.transfer_command_buffer = margaret_allocate_command_buffer(state.vk_ctx.device, state.vk_ctx.command_pool);
|
||||
|
||||
state.vk_ctx.my_cam_control_info = CamControlInfo_new();
|
||||
state.vk_ctx.Buba_control_info = (vec3){0};
|
||||
|
||||
state.vk_ctx.scene = Scene_new();
|
||||
{
|
||||
size_t offset_in_attr_buffer = 0;
|
||||
for (size_t mi = 0; mi < state.vk_ctx.scene_template.models.len; mi++) {
|
||||
const ModelInSceneTemplate* M = VecModelInSceneTemplate_at(&state.vk_ctx.scene_template.models, mi);
|
||||
VecUsedModelOnScene_append(&state.vk_ctx.scene.models, (UsedModelOnScene){
|
||||
.model = (ModelOnScene){
|
||||
.vbo = VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes,
|
||||
2 * mi + 0)->buffer,
|
||||
.ebo = VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes,
|
||||
2 * mi + 1)->buffer,
|
||||
for (size_t mi = 0; mi < state.vk_ctx.scene_template.generic_models.len; mi++) {
|
||||
const GenericMeshInSceneTemplate* M = VecGenericMeshInSceneTemplate_at(&state.vk_ctx.scene_template.generic_models, mi);
|
||||
VecUsedGenericModelOnScene_append(&state.vk_ctx.scene.generic_models, (UsedGenericModelOnScene){
|
||||
.model = (ModelOnSceneMem){
|
||||
.vbo = VecMargaretBufferInMemoryInfo_at(
|
||||
&state.vk_ctx.device_vbo_buffers_for_generic_meshes, mi)->buffer,
|
||||
.ebo = VecMargaretBufferInMemoryInfo_at(
|
||||
&state.vk_ctx.device_ebo_buffers_for_generic_meshes, mi)->buffer,
|
||||
.indexes = M->topology.indexes.len,
|
||||
.instance_attr_buf = state.vk_ctx.device_instance_attrs_for_models.buffer,
|
||||
.instance_attr_buf_offset = offset_in_attr_buffer,
|
||||
.limit_max_instance_count = M->max_instance_count
|
||||
},
|
||||
.instances = VecGenericMeshInstance_new(),
|
||||
.instance_attr_buf = state.vk_ctx.device_instance_attrs_for_all_generic_meshes.buffer,
|
||||
.instance_attr_buf_offset = offset_in_attr_buffer,
|
||||
.limit_max_instance_count = M->max_instance_count
|
||||
});
|
||||
offset_in_attr_buffer += M->max_instance_count * sizeof(GenericMeshInstance);
|
||||
}
|
||||
for (size_t mi = 0; mi < state.vk_ctx.scene_template.shiny_models.len; mi++) {
|
||||
const ShinyMeshInSceneTemplate* M = VecShinyMeshInSceneTemplate_at(&state.vk_ctx.scene_template.shiny_models, mi);
|
||||
VecUsedShinyModelOnScene_append(&state.vk_ctx.scene.shiny_models, (UsedShinyModelOnScene){
|
||||
.model = (ModelOnSceneMem){
|
||||
.vbo = VecMargaretBufferInMemoryInfo_at(
|
||||
&state.vk_ctx.device_vbo_buffers_for_shiny_meshes, mi)->buffer,
|
||||
.ebo = VecMargaretBufferInMemoryInfo_at(
|
||||
&state.vk_ctx.device_ebo_buffers_for_shiny_meshes, mi)->buffer,
|
||||
.indexes = M->topology.indexes.len,
|
||||
.instance_attr_buf = state.vk_ctx.device_instance_attrs_for_models.buffer,
|
||||
.instance_attr_buf_offset = offset_in_attr_buffer,
|
||||
.limit_max_instance_count = M->max_instance_count
|
||||
},
|
||||
.instances = VecShinyMeshInstance_new(),
|
||||
});
|
||||
offset_in_attr_buffer += M->max_instance_count * sizeof(ShinyMeshInstance);
|
||||
}
|
||||
}
|
||||
|
||||
for (int X = 0; X < 10; X++) {
|
||||
for (int Z = 0; Z < 10; Z++) {
|
||||
VecGenericMeshInstance_append(&VecUsedModelOnScene_mat(&state.vk_ctx.scene.models, 0)->instances,
|
||||
VecGenericMeshInstance_append(&VecUsedGenericModelOnScene_mat(&state.vk_ctx.scene.generic_models, 0)->instances,
|
||||
(GenericMeshInstance){ .model_t = marie_translation_mat4((vec3){11.f * (float)X, -6, 4.f * (float)Z}) });
|
||||
}
|
||||
}
|
||||
VecGenericMeshInstance_append(&VecUsedModelOnScene_mat(&state.vk_ctx.scene.models, 1)->instances, (GenericMeshInstance){
|
||||
.model_t = mat4_E
|
||||
VecGenericMeshInstance_append(&VecUsedGenericModelOnScene_mat(&state.vk_ctx.scene.generic_models, 1)->instances,
|
||||
(GenericMeshInstance){ .model_t = marie_translation_mat4(state.vk_ctx.Buba_control_info)
|
||||
});
|
||||
for (U64 i = 0; i < 5; i++) {
|
||||
VecShinyMeshInstance_append(&VecUsedShinyModelOnScene_mat(&state.vk_ctx.scene.shiny_models, 0)->instances,
|
||||
(ShinyMeshInstance){ .model_t = marie_translation_mat4((vec3){
|
||||
(float)((i * i * 10 + i * 4 + 1) % 13) + 2,
|
||||
(float)((i * i * 11 + i * 2 + 2) % 13),
|
||||
(float)((i * i * 9 + i * 1 + 4) % 13) + 3}), .color_off = (vec3){0.6f, 0.2f, 0.2f}});
|
||||
}
|
||||
VecShinyMeshInstance_append(&VecUsedShinyModelOnScene_mat(&state.vk_ctx.scene.shiny_models, 1)->instances,
|
||||
(ShinyMeshInstance){ .model_t = marie_translation_mat4((vec3){-5, 0, 3}), .color_off = (vec3){0.3f, 0.5f, 0.5f}});
|
||||
// todo: synchronize them with my cool light sources)
|
||||
|
||||
if (vkMapMemory(state.vk_ctx.device, state.vk_ctx.host_mem, 0, VK_WHOLE_SIZE, 0, &state.vk_ctx.host_mem_buffer_mem) != VK_SUCCESS)
|
||||
abortf("vkMapMemory");
|
||||
@ -1654,28 +1979,35 @@ int main() {
|
||||
state.vk_ctx.linear_sampler = margaret_create_sampler(state.vk_ctx.physical_device, state.vk_ctx.device, true);
|
||||
state.vk_ctx.nearest_sampler = margaret_create_sampler(state.vk_ctx.physical_device, state.vk_ctx.device, false);
|
||||
|
||||
state.vk_ctx.descriptor_pool = margaret_create_descriptor_set_pool(state.vk_ctx.device, 1, 3, 2);
|
||||
state.vk_ctx.descriptor_set_for_pipeline_0 = margaret_allocate_descriptor_set(
|
||||
state.vk_ctx.device, state.vk_ctx.descriptor_pool, state.vk_ctx.pipeline_hands_0.descriptor_set_layout);
|
||||
state.vk_ctx.descriptor_pool = margaret_create_descriptor_set_pool(state.vk_ctx.device, 2, 3, 3);
|
||||
state.vk_ctx.descriptor_set_for_pipeline_0a = margaret_allocate_descriptor_set(
|
||||
state.vk_ctx.device, state.vk_ctx.descriptor_pool, state.vk_ctx.pipeline_hands_0a.descriptor_set_layout);
|
||||
state.vk_ctx.descriptor_set_for_pipeline_0b = margaret_allocate_descriptor_set(
|
||||
state.vk_ctx.device, state.vk_ctx.descriptor_pool, state.vk_ctx.pipeline_hands_0b.descriptor_set_layout);
|
||||
state.vk_ctx.descriptor_set_for_pipeline_1 = margaret_allocate_descriptor_set(
|
||||
state.vk_ctx.device, state.vk_ctx.descriptor_pool, state.vk_ctx.pipeline_hands_1.descriptor_set_layout);
|
||||
|
||||
// Configuring my descriptor sets, that I just allocated
|
||||
VkDescriptorBufferInfo buffer_info_for_descriptor_0_in_set_0 = {
|
||||
VkDescriptorBufferInfo buffer_info_for_descriptor_0_in_set_0a = {
|
||||
.buffer = state.vk_ctx.device_lighting_ubo.buffer,
|
||||
.offset = 0,
|
||||
.range = sizeof(Pipeline0UBO),
|
||||
};
|
||||
VkDescriptorImageInfo image_info_for_descriptor_1_in_set_0 = {
|
||||
VkDescriptorImageInfo image_info_for_descriptor_1_in_set_0a = {
|
||||
.sampler = state.vk_ctx.linear_sampler,
|
||||
.imageView = state.vk_ctx.cyl_1_diffuse_texture_view,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
};
|
||||
VkDescriptorImageInfo image_info_for_descriptor_2_in_set_0 = {
|
||||
VkDescriptorImageInfo image_info_for_descriptor_2_in_set_0a = {
|
||||
.sampler = state.vk_ctx.nearest_sampler,
|
||||
.imageView = state.vk_ctx.cyl_1_normal_texture_view,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
};
|
||||
VkDescriptorBufferInfo buffer_info_for_descriptor_0_in_set_0b = {
|
||||
.buffer = state.vk_ctx.device_lighting_ubo.buffer,
|
||||
.offset = 0,
|
||||
.range = sizeof(Pipeline0UBO),
|
||||
};
|
||||
VkDescriptorImageInfo image_info_for_descriptor_0_in_set_1 = {
|
||||
.sampler = state.vk_ctx.nearest_sampler,
|
||||
.imageView = state.vk_ctx.IT1_view,
|
||||
@ -1684,30 +2016,40 @@ int main() {
|
||||
VkWriteDescriptorSet writes_in_descriptor_sets[] = {
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = state.vk_ctx.descriptor_set_for_pipeline_0,
|
||||
.dstSet = state.vk_ctx.descriptor_set_for_pipeline_0a,
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.pBufferInfo = &buffer_info_for_descriptor_0_in_set_0,
|
||||
.pBufferInfo = &buffer_info_for_descriptor_0_in_set_0a,
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = state.vk_ctx.descriptor_set_for_pipeline_0,
|
||||
.dstSet = state.vk_ctx.descriptor_set_for_pipeline_0a,
|
||||
.dstBinding = 1,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.pImageInfo = &image_info_for_descriptor_1_in_set_0,
|
||||
.pImageInfo = &image_info_for_descriptor_1_in_set_0a,
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = state.vk_ctx.descriptor_set_for_pipeline_0,
|
||||
.dstSet = state.vk_ctx.descriptor_set_for_pipeline_0a,
|
||||
.dstBinding = 2,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.pImageInfo = &image_info_for_descriptor_2_in_set_0,
|
||||
.pImageInfo = &image_info_for_descriptor_2_in_set_0a,
|
||||
},
|
||||
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = state.vk_ctx.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,
|
||||
},
|
||||
|
||||
{
|
||||
@ -1722,9 +2064,6 @@ int main() {
|
||||
};
|
||||
vkUpdateDescriptorSets(state.vk_ctx.device, ARRAY_SIZE(writes_in_descriptor_sets), writes_in_descriptor_sets, 0, NULL);
|
||||
|
||||
state.vk_ctx.my_cam_control_info = CamControlInfo_new();
|
||||
state.vk_ctx.Buba_control_info = (vec3){0};
|
||||
|
||||
state.vk_ctx.jane = Jane_r0_create(state.vk_ctx.device);
|
||||
|
||||
state.prev_key_frame_time = margaret_clock_gettime_monotonic_raw();
|
||||
@ -1762,12 +2101,34 @@ int main() {
|
||||
vkDestroyImage(state.vk_ctx.device, state.vk_ctx.device_IT1_image.image, NULL);
|
||||
vkDestroyImage(state.vk_ctx.device, state.vk_ctx.device_zbuffer_image.image, NULL);
|
||||
vkDestroyBuffer(state.vk_ctx.device, state.vk_ctx.device_lighting_ubo.buffer, NULL);
|
||||
vkDestroyBuffer(state.vk_ctx.device, state.vk_ctx.device_instance_attrs_for_all_generic_meshes.buffer, NULL);
|
||||
for (size_t i = 0; i < state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes.len; i++)
|
||||
|
||||
vkDestroyBuffer(state.vk_ctx.device, state.vk_ctx.device_instance_attrs_for_models.buffer, NULL);
|
||||
|
||||
for (size_t i = 0; i < state.vk_ctx.device_ebo_buffers_for_generic_meshes.len; i++)
|
||||
vkDestroyBuffer(state.vk_ctx.device,
|
||||
VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes, i)->buffer,
|
||||
VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_ebo_buffers_for_generic_meshes, i)->buffer,
|
||||
NULL);
|
||||
VecMargaretBufferInMemoryInfo_drop(state.vk_ctx.device_ebo_and_vbo_buffers_for_generic_meshes);
|
||||
VecMargaretBufferInMemoryInfo_drop(state.vk_ctx.device_ebo_buffers_for_generic_meshes);
|
||||
|
||||
for (size_t i = 0; i < state.vk_ctx.device_vbo_buffers_for_generic_meshes.len; i++)
|
||||
vkDestroyBuffer(state.vk_ctx.device,
|
||||
VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_vbo_buffers_for_generic_meshes, i)->buffer,
|
||||
NULL);
|
||||
VecMargaretBufferInMemoryInfo_drop(state.vk_ctx.device_vbo_buffers_for_generic_meshes);
|
||||
|
||||
for (size_t i = 0; i < state.vk_ctx.device_ebo_buffers_for_shiny_meshes.len; i++)
|
||||
vkDestroyBuffer(state.vk_ctx.device,
|
||||
VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_ebo_buffers_for_shiny_meshes, i)->buffer,
|
||||
NULL);
|
||||
VecMargaretBufferInMemoryInfo_drop(state.vk_ctx.device_ebo_buffers_for_shiny_meshes);
|
||||
|
||||
for (size_t i = 0; i < state.vk_ctx.device_vbo_buffers_for_shiny_meshes.len; i++)
|
||||
vkDestroyBuffer(state.vk_ctx.device,
|
||||
VecMargaretBufferInMemoryInfo_at(&state.vk_ctx.device_vbo_buffers_for_shiny_meshes, i)->buffer,
|
||||
NULL);
|
||||
VecMargaretBufferInMemoryInfo_drop(state.vk_ctx.device_vbo_buffers_for_shiny_meshes);
|
||||
|
||||
|
||||
|
||||
vkDestroyBuffer(state.vk_ctx.device, state.vk_ctx.host_mem_buffer.buffer, NULL);
|
||||
|
||||
@ -1779,7 +2140,8 @@ int main() {
|
||||
Jane_r0_destroy(state.vk_ctx.device, state.vk_ctx.jane);
|
||||
destroy_graphics_pipeline_hands(state.vk_ctx.device, state.vk_ctx.pipeline_hands_1);
|
||||
vkDestroyRenderPass(state.vk_ctx.device, state.vk_ctx.render_pass_1, NULL);
|
||||
destroy_graphics_pipeline_hands(state.vk_ctx.device, state.vk_ctx.pipeline_hands_0);
|
||||
destroy_graphics_pipeline_hands(state.vk_ctx.device, state.vk_ctx.pipeline_hands_0b);
|
||||
destroy_graphics_pipeline_hands(state.vk_ctx.device, state.vk_ctx.pipeline_hands_0a);
|
||||
vkDestroyRenderPass(state.vk_ctx.device, state.vk_ctx.render_pass_0, NULL);
|
||||
vkDestroyDevice(state.vk_ctx.device, NULL);
|
||||
vkDestroySurfaceKHR(instance, state.vk_ctx.surface, NULL);
|
||||
|
||||
@ -13,59 +13,89 @@ typedef struct {
|
||||
vec3 pos;
|
||||
vec2 tex;
|
||||
} GenericMeshVertex;
|
||||
|
||||
#include "../../../../gen/l2/eve/r0/VecGenericMeshVertex.h"
|
||||
#include "../../../../gen/l2/eve/r0/VecAndSpan_GenericMeshVertex.h"
|
||||
|
||||
typedef struct {
|
||||
VecGenericMeshVertex vertices;
|
||||
VecU32 indexes;
|
||||
} ModelTopology;
|
||||
} GenericMeshTopology;
|
||||
|
||||
void ModelTopology_drop(ModelTopology self) {
|
||||
void GenericMeshTopology_drop(GenericMeshTopology self) {
|
||||
VecGenericMeshVertex_drop(self.vertices);
|
||||
VecU32_drop(self.indexes);
|
||||
}
|
||||
|
||||
ModelTopology ModelTopology_clone(const ModelTopology* self) {
|
||||
return (ModelTopology){.vertices = VecGenericMeshVertex_clone(&self->vertices), .indexes = VecU32_clone(&self->indexes)};
|
||||
GenericMeshTopology GenericMeshTopology_clone(const GenericMeshTopology* self) {
|
||||
return (GenericMeshTopology){.vertices = VecGenericMeshVertex_clone(&self->vertices), .indexes = VecU32_clone(&self->indexes)};
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
ModelTopology topology;
|
||||
GenericMeshTopology topology;
|
||||
U32 max_instance_count;
|
||||
} ModelInSceneTemplate;
|
||||
} GenericMeshInSceneTemplate;
|
||||
|
||||
void ModelInSceneTemplate_drop(ModelInSceneTemplate self) {
|
||||
ModelTopology_drop(self.topology);
|
||||
void GenericMeshInSceneTemplate_drop(GenericMeshInSceneTemplate self) {
|
||||
GenericMeshTopology_drop(self.topology);
|
||||
}
|
||||
|
||||
ModelInSceneTemplate ModelInSceneTemplate_clone(const ModelInSceneTemplate* self) {
|
||||
return (ModelInSceneTemplate){.topology = ModelTopology_clone(&self->topology), .max_instance_count = self->max_instance_count};
|
||||
GenericMeshInSceneTemplate GenericMeshInSceneTemplate_clone(const GenericMeshInSceneTemplate* self) {
|
||||
return (GenericMeshInSceneTemplate){.topology = GenericMeshTopology_clone(&self->topology), .max_instance_count = self->max_instance_count};
|
||||
}
|
||||
|
||||
#include "../../../../gen/l2/eve/r0/VecModelInSceneTemplate.h"
|
||||
#include "../../../../gen/l2/eve/r0/VecGenericMeshInSceneTemplate.h"
|
||||
|
||||
typedef struct {
|
||||
mat4 model_t;
|
||||
} GenericMeshInstance;
|
||||
|
||||
#include "../../../../gen/l2/eve/r0/VecGenericMeshInstance.h"
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
vec3 pos;
|
||||
vec3 normal;
|
||||
} ShinyMeshVertex;
|
||||
#include "../../../../gen/l2/eve/r0/VecAndSpan_ShinyMeshVertex.h"
|
||||
|
||||
#include "../../../../gen/l2/eve/r0/VecShinyMeshVertex.h"
|
||||
typedef struct {
|
||||
VecShinyMeshVertex vertices;
|
||||
VecU32 indexes;
|
||||
} ShinyMeshTopology;
|
||||
|
||||
void ShinyMeshTopology_drop(ShinyMeshTopology self) {
|
||||
VecShinyMeshVertex_drop(self.vertices);
|
||||
VecU32_drop(self.indexes);
|
||||
}
|
||||
|
||||
ShinyMeshTopology ShinyMeshTopology_clone(const ShinyMeshTopology* self) {
|
||||
return (ShinyMeshTopology){.vertices = VecShinyMeshVertex_clone(&self->vertices), VecU32_clone(&self->indexes)};
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
ShinyMeshTopology topology;
|
||||
U32 max_instance_count;
|
||||
} ShinyMeshInSceneTemplate;
|
||||
|
||||
void ShinyMeshInSceneTemplate_drop(ShinyMeshInSceneTemplate self) {
|
||||
ShinyMeshTopology_drop(self.topology);
|
||||
}
|
||||
|
||||
ShinyMeshInSceneTemplate ShinyMeshInSceneTemplate_clone(const ShinyMeshInSceneTemplate* self) {
|
||||
return (ShinyMeshInSceneTemplate){.topology = ShinyMeshTopology_clone(&self->topology),
|
||||
.max_instance_count = self->max_instance_count};
|
||||
}
|
||||
|
||||
#include "../../../../gen/l2/eve/r0/VecShinyMeshInSceneTemplate.h"
|
||||
|
||||
typedef struct {
|
||||
mat4 model_t;
|
||||
vec3 color_off;
|
||||
vec3 color_on;
|
||||
} ShinyMeshInstance;
|
||||
|
||||
#include "../../../../gen/l2/eve/r0/VecShinyMeshInstance.h"
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
vec2 win_scale;
|
||||
} Pipeline1PushRangeVertex;
|
||||
@ -87,7 +117,6 @@ typedef struct {
|
||||
float d;
|
||||
char _padding_3[12];
|
||||
} Pipeline0Spotlight;
|
||||
|
||||
#include "../../../../gen/l2/eve/r0/VecPipeline0Spotlight.h"
|
||||
|
||||
typedef struct {
|
||||
@ -96,25 +125,29 @@ typedef struct {
|
||||
vec3 color;
|
||||
char _padding_1[4];
|
||||
} Pipeline0PointLight;
|
||||
|
||||
#include "../../../../gen/l2/eve/r0/VecPipeline0PointLight.h"
|
||||
|
||||
typedef struct {
|
||||
VecModelInSceneTemplate models;
|
||||
VecGenericMeshInSceneTemplate generic_models;
|
||||
VecShinyMeshInSceneTemplate shiny_models;
|
||||
size_t point_lights_max_count;
|
||||
size_t spotlights_max_count;
|
||||
} SceneTemplate;
|
||||
|
||||
void SceneTemplate_drop(SceneTemplate self) {
|
||||
VecModelInSceneTemplate_drop(self.models);
|
||||
VecGenericMeshInSceneTemplate_drop(self.generic_models);
|
||||
}
|
||||
|
||||
size_t SceneTemplate_get_space_needed_for_all_instance_attributes(const SceneTemplate* self) {
|
||||
size_t s = 0;
|
||||
for (size_t mi = 0; mi < self->models.len; mi++) {
|
||||
const ModelInSceneTemplate* M = VecModelInSceneTemplate_at(&self->models, mi);
|
||||
for (size_t mi = 0; mi < self->generic_models.len; mi++) {
|
||||
const GenericMeshInSceneTemplate* M = VecGenericMeshInSceneTemplate_at(&self->generic_models, mi);
|
||||
s += M->max_instance_count * sizeof(GenericMeshInstance);
|
||||
}
|
||||
for (size_t mi = 0; mi < self->shiny_models.len; mi++) {
|
||||
const ShinyMeshInSceneTemplate* M = VecShinyMeshInSceneTemplate_at(&self->shiny_models, mi);
|
||||
s += M->max_instance_count * sizeof(ShinyMeshInstance);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -127,10 +160,14 @@ size_t SceneTemplate_get_space_needed_for_widest_state_transfer(const SceneTempl
|
||||
|
||||
size_t SceneTemplate_get_space_for_initial_model_topology_transfer(const SceneTemplate* self) {
|
||||
size_t s = 0;
|
||||
for (size_t mi = 0; mi < self->models.len; mi++) {
|
||||
const ModelInSceneTemplate* M = VecModelInSceneTemplate_at(&self->models, mi);
|
||||
for (size_t mi = 0; mi < self->generic_models.len; mi++) {
|
||||
const GenericMeshInSceneTemplate* M = VecGenericMeshInSceneTemplate_at(&self->generic_models, mi);
|
||||
s += M->topology.vertices.len * sizeof(GenericMeshVertex) + M->topology.indexes.len * sizeof(U32);
|
||||
}
|
||||
for (size_t mi = 0; mi < self->shiny_models.len; mi++) {
|
||||
const ShinyMeshInSceneTemplate* M = VecShinyMeshInSceneTemplate_at(&self->shiny_models, mi);
|
||||
s += M->topology.vertices.len * sizeof(ShinyMeshVertex) + M->topology.indexes.len * sizeof(U32);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -145,7 +182,7 @@ typedef struct {
|
||||
Pipeline0Spotlight spotlight_arr[pipeline_0_ubo_spotlight_max_count];
|
||||
} Pipeline0UBO;
|
||||
|
||||
size_t ModelTopology_get_space_needed_for_staging_buffer(const ModelTopology* self) {
|
||||
size_t GenericMeshTopology_get_space_needed_for_staging_buffer(const GenericMeshTopology* self) {
|
||||
return MAX_U64(self->vertices.len * sizeof(GenericMeshVertex), self->indexes.len * sizeof(U32));
|
||||
}
|
||||
|
||||
@ -177,7 +214,7 @@ void TextureDataR8_draw_spot_maxing(TextureDataR8* self, vec2 v, float r_cut, fl
|
||||
}
|
||||
}
|
||||
|
||||
ModelTopology generate_one_fourth_of_a_cylinder(float w, float r, U32 k) {
|
||||
GenericMeshTopology 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 * sinf(M_PI_4f / (float)k);
|
||||
@ -230,7 +267,7 @@ ModelTopology generate_one_fourth_of_a_cylinder(float w, float r, U32 k) {
|
||||
};
|
||||
VecU32_append_span(&indexes, (SpanU32){.data = _span_1, .len = ARRAY_SIZE(_span_1)});
|
||||
}
|
||||
return (ModelTopology){.vertices = vertices, .indexes = indexes};
|
||||
return (GenericMeshTopology){.vertices = vertices, .indexes = indexes};
|
||||
}
|
||||
|
||||
vec2 perimeter_line_get_thorn_on_vertex(Spanvec2 P, size_t i, float thickness) {
|
||||
@ -637,5 +674,117 @@ TextureDataR8G8B8 generate_normal_tex_for_one_fourth_of_a_cylinder(float s_resol
|
||||
return res;
|
||||
}
|
||||
|
||||
U32 quad_to_triangles_conv_arr[6] = {0, 1, 2, 0, 2, 3};
|
||||
|
||||
ShinyMeshTopology generate_shiny_cube(float r) {
|
||||
ShinyMeshVertex vert[24] = {
|
||||
{{+r, +r, +r}, {1, 0, 0}},
|
||||
{{+r, -r, +r}, {1, 0, 0}},
|
||||
{{+r, -r, -r}, {1, 0, 0}},
|
||||
{{+r, +r, -r}, {1, 0, 0}},
|
||||
|
||||
{{-r, -r, -r}, {-1, 0, 0}},
|
||||
{{-r, -r, +r}, {-1, 0, 0}},
|
||||
{{-r, +r, +r}, {-1, 0, 0}},
|
||||
{{-r, +r, -r}, {-1, 0, 0}},
|
||||
|
||||
{{+r, +r, +r}, {0, 1, 0}},
|
||||
{{+r, +r, -r}, {0, 1, 0}},
|
||||
{{-r, +r, -r}, {0, 1, 0}},
|
||||
{{-r, +r, +r}, {0, 1, 0}},
|
||||
|
||||
{{-r, -r, -r}, {0, -1, 0}},
|
||||
{{+r, -r, -r}, {0, -1, 0}},
|
||||
{{+r, -r, +r}, {0, -1, 0}},
|
||||
{{-r, -r, +r}, {0, -1, 0}},
|
||||
|
||||
{{+r, +r, +r}, {0, 0, 1}},
|
||||
{{-r, +r, +r}, {0, 0, 1}},
|
||||
{{-r, -r, +r}, {0, 0, 1}},
|
||||
{{+r, -r, +r}, {0, 0, 1}},
|
||||
|
||||
{{-r, -r, -r}, {0, 0, -1}},
|
||||
{{-r, +r, -r}, {0, 0, -1}},
|
||||
{{+r, +r, -r}, {0, 0, -1}},
|
||||
{{+r, -r, -r}, {0, 0, -1}},
|
||||
};
|
||||
VecShinyMeshVertex vertices_vec = VecShinyMeshVertex_new_zeroinit(24);
|
||||
memcpy(vertices_vec.buf, vert, sizeof(vert));
|
||||
VecU32 indexes_vec = VecU32_new_reserved(36);
|
||||
for (U32 f = 0; f < 6; f++) {
|
||||
for (U32 j = 0; j < 6; j++)
|
||||
VecU32_append(&indexes_vec, f * 4 + quad_to_triangles_conv_arr[j]);
|
||||
}
|
||||
return (ShinyMeshTopology){ .vertices = vertices_vec, .indexes = indexes_vec};
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int face;
|
||||
/* There is a counterclockwise one-to-one correspondence between vertexes of face and edges of face */
|
||||
int vert_on_it;
|
||||
} CubeVertOfFace;
|
||||
|
||||
CubeVertOfFace CubeVertOfFace_jump(CubeVertOfFace vert) {
|
||||
const CubeVertOfFace cube_detour_get_neighbour_face[6][4] = {
|
||||
{{4, 3}, {3, 1}, {5, 2}, {2, 0}},
|
||||
{{3, 3}, {4, 1}, {2, 2}, {5, 0}},
|
||||
{{0, 3}, {5, 1}, {1, 2}, {4, 0}},
|
||||
{{5, 3}, {0, 1}, {4, 2}, {1, 0}},
|
||||
{{2, 3}, {1, 1}, {3, 2}, {0, 0}},
|
||||
{{1, 3}, {2, 1}, {0, 2}, {3, 0}}
|
||||
};
|
||||
return cube_detour_get_neighbour_face[vert.face][vert.vert_on_it];
|
||||
}
|
||||
|
||||
U32 CubeVertOfFace_to_vid(CubeVertOfFace vert) {
|
||||
return 4 * vert.face + vert.vert_on_it;
|
||||
}
|
||||
|
||||
CubeVertOfFace CubeVertOfFace_next(CubeVertOfFace vert) {
|
||||
return (CubeVertOfFace){vert.face, (vert.vert_on_it + 1) % 4};
|
||||
}
|
||||
|
||||
ShinyMeshTopology generate_shiny_rhombicuboctahedron(float r) {
|
||||
ShinyMeshTopology res = generate_shiny_cube(r);
|
||||
for (int f = 0; f < 6; f++) {
|
||||
vec3 growth = vec3_mul_scal((*VecShinyMeshVertex_at(&res.vertices, f * 4)).normal, M_SQRT1_2);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
vec3* pos = &VecShinyMeshVertex_mat(&res.vertices, f * 4 + i)->pos;
|
||||
*pos = vec3_add_vec3(*pos, growth);
|
||||
}
|
||||
}
|
||||
for (int f = 0; f < 6; f++) {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
CubeVertOfFace vof = {f, 2*i+(f%2)};
|
||||
ShinyMeshVertex A = *VecShinyMeshVertex_at(&res.vertices, CubeVertOfFace_to_vid(vof));
|
||||
ShinyMeshVertex B = *VecShinyMeshVertex_at(&res.vertices, CubeVertOfFace_to_vid(CubeVertOfFace_next(CubeVertOfFace_jump(vof))));
|
||||
ShinyMeshVertex C = *VecShinyMeshVertex_at(&res.vertices, CubeVertOfFace_to_vid(CubeVertOfFace_jump(vof)));
|
||||
ShinyMeshVertex D = *VecShinyMeshVertex_at(&res.vertices, CubeVertOfFace_to_vid(CubeVertOfFace_next(vof)));
|
||||
vec3 norm = vec3_normalize(vec3_add_vec3(A.normal, B.normal));
|
||||
ShinyMeshVertex quad_v[4] = {{A.pos, norm}, {B.pos, norm}, {C.pos, norm}, {D.pos, norm}};
|
||||
size_t b = res.vertices.len;
|
||||
VecShinyMeshVertex_append_span(&res.vertices, (SpanShinyMeshVertex){quad_v, ARRAY_SIZE(quad_v)});
|
||||
for (U32 j = 0; j < 6; j++)
|
||||
VecU32_append(&res.indexes, b + quad_to_triangles_conv_arr[j]);
|
||||
}
|
||||
}
|
||||
for (int f = 0; f < 2; f++) {
|
||||
for (int e = 0; e < 4; e++) {
|
||||
CubeVertOfFace vof = {f, e};
|
||||
ShinyMeshVertex A = *VecShinyMeshVertex_at(&res.vertices, CubeVertOfFace_to_vid(CubeVertOfFace_next(vof)));
|
||||
ShinyMeshVertex B = *VecShinyMeshVertex_at(&res.vertices, CubeVertOfFace_to_vid(CubeVertOfFace_jump(vof)));
|
||||
ShinyMeshVertex C = *VecShinyMeshVertex_at(&res.vertices,
|
||||
CubeVertOfFace_to_vid(CubeVertOfFace_next(CubeVertOfFace_jump(CubeVertOfFace_next(vof)))));
|
||||
vec3 norm = vec3_normalize(vec3_add_vec3(A.normal, vec3_add_vec3(B.normal, C.normal)));
|
||||
|
||||
ShinyMeshVertex ang_v[3] = {{A.pos, norm}, {B.pos, norm}, {C.pos, norm}};
|
||||
size_t b = res.vertices.len;
|
||||
VecShinyMeshVertex_append_span(&res.vertices, (SpanShinyMeshVertex){ang_v, ARRAY_SIZE(ang_v)});
|
||||
for (int i = 0; i < 3; i++)
|
||||
VecU32_append(&res.indexes, b + i);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -9,31 +9,34 @@ typedef struct {
|
||||
VkBuffer vbo;
|
||||
VkBuffer ebo;
|
||||
size_t indexes;
|
||||
} ModelOnScene;
|
||||
|
||||
#include "../../../../gen/l2/eve/r0/VecModelOnScene.h"
|
||||
|
||||
/* Contains both data for model instances attributes and buffer (+offset) where it is stored */
|
||||
typedef struct {
|
||||
ModelOnScene model;
|
||||
VecGenericMeshInstance instances;
|
||||
VkBuffer instance_attr_buf;
|
||||
VkDeviceSize instance_attr_buf_offset;
|
||||
U32 limit_max_instance_count;
|
||||
} UsedModelOnScene;
|
||||
} ModelOnSceneMem;
|
||||
|
||||
void UsedModelOnScene_drop(UsedModelOnScene self) {
|
||||
/* Contains both data for model instances attributes and buffer (+offset) where it is stored */
|
||||
/* Also, I made it non-clonable. Thus */
|
||||
typedef struct {
|
||||
ModelOnSceneMem model;
|
||||
VecGenericMeshInstance instances;
|
||||
} UsedGenericModelOnScene;
|
||||
|
||||
void UsedGenericModelOnScene_drop(UsedGenericModelOnScene self) {
|
||||
VecGenericMeshInstance_drop(self.instances);
|
||||
}
|
||||
|
||||
UsedModelOnScene UsedModelOnScene_clone(const UsedModelOnScene* self) {
|
||||
return (UsedModelOnScene){.model = self->model, .instances = VecGenericMeshInstance_clone(&self->instances),
|
||||
.instance_attr_buf = self->instance_attr_buf, .instance_attr_buf_offset = self->instance_attr_buf_offset,
|
||||
.limit_max_instance_count = self->limit_max_instance_count
|
||||
};
|
||||
#include "../../../../gen/l2/eve/r0/VecUsedGenericModelOnScene.h"
|
||||
|
||||
typedef struct {
|
||||
ModelOnSceneMem model;
|
||||
VecShinyMeshInstance instances;
|
||||
} UsedShinyModelOnScene;
|
||||
|
||||
void UsedShinyModelOnScene_drop(UsedShinyModelOnScene self) {
|
||||
VecShinyMeshInstance_drop(self.instances);
|
||||
}
|
||||
|
||||
#include "../../../../gen/l2/eve/r0/VecUsedModelOnScene.h"
|
||||
#include "../../../../gen/l2/eve/r0/VecUsedShinyModelOnScene.h"
|
||||
|
||||
typedef struct {
|
||||
float fov;
|
||||
@ -85,8 +88,10 @@ void CamControlInfo_update_direction(CamControlInfo* self, int win_width, int wi
|
||||
self->cam_basis = marie_simple_camera_rot_m_basis_in_cols(yaw, pitch, 0);
|
||||
}
|
||||
|
||||
/* Non copyable */
|
||||
typedef struct {
|
||||
VecUsedModelOnScene models;
|
||||
VecUsedGenericModelOnScene generic_models;
|
||||
VecUsedShinyModelOnScene shiny_models;
|
||||
VkClearColorValue color;
|
||||
float gamma_correction_factor;
|
||||
float hdr_factor;
|
||||
@ -97,13 +102,16 @@ typedef struct {
|
||||
} Scene;
|
||||
|
||||
Scene Scene_new() {
|
||||
return (Scene){.models = VecUsedModelOnScene_new(), .color = {.float32 = {0, 0, 0, 1}},
|
||||
.gamma_correction_factor = 2.2f, .hdr_factor = 1, .lsd_factor = 0, .anim_time = 0,
|
||||
.spotlights = VecPipeline0Spotlight_new(), .point_lights = VecPipeline0PointLight_new()};
|
||||
return (Scene){.generic_models = VecUsedGenericModelOnScene_new(), .shiny_models = VecUsedShinyModelOnScene_new(),
|
||||
.color = {.float32 = {0, 0, 0, 1}},
|
||||
.gamma_correction_factor = 2.2f, .hdr_factor = 1, .lsd_factor = 0, .anim_time = 0,
|
||||
.spotlights = VecPipeline0Spotlight_new(), .point_lights = VecPipeline0PointLight_new()
|
||||
};
|
||||
}
|
||||
|
||||
void Scene_drop(Scene self) {
|
||||
VecUsedModelOnScene_drop(self.models);
|
||||
VecUsedGenericModelOnScene_drop(self.generic_models);
|
||||
VecUsedShinyModelOnScene_drop(self.shiny_models);
|
||||
VecPipeline0Spotlight_drop(self.spotlights);
|
||||
VecPipeline0PointLight_drop(self.point_lights);
|
||||
}
|
||||
@ -112,7 +120,8 @@ void SceneTemplate_copy_initial_model_topology_and_rerecord_transfer_cmd(
|
||||
const SceneTemplate* scene_template, const Scene* scene, char* host_mem_buffer_mem,
|
||||
VkCommandBuffer command_buffer, VkBuffer host_memory_buffer
|
||||
) {
|
||||
assert(scene_template->models.len == scene->models.len);
|
||||
assert(scene_template->generic_models.len == scene->generic_models.len);
|
||||
assert(scene_template->shiny_models.len == scene->shiny_models.len);
|
||||
|
||||
if (vkResetCommandBuffer(command_buffer, 0) != VK_SUCCESS)
|
||||
abortf("vkResetCommandBuffer");
|
||||
@ -123,19 +132,32 @@ void SceneTemplate_copy_initial_model_topology_and_rerecord_transfer_cmd(
|
||||
size_t offset = 0;
|
||||
// todo: use BufferCopyCmd 2 (to perform all the copying in one command)
|
||||
// todo: ot use one buffer per all the data
|
||||
// VecVkBufferCopy regions_to_copy = VecVkBufferCopy_new_zeroinit(scene_template->models.len * 2);
|
||||
for (size_t mi = 0; mi < scene_template->models.len; mi++) {
|
||||
const ModelInSceneTemplate* mt = VecModelInSceneTemplate_at(&scene_template->models, mi);
|
||||
const UsedModelOnScene* m_buf = VecUsedModelOnScene_at(&scene->models, mi);
|
||||
for (size_t mi = 0; mi < scene_template->generic_models.len; mi++) {
|
||||
const GenericMeshInSceneTemplate* mt = VecGenericMeshInSceneTemplate_at(&scene_template->generic_models, mi);
|
||||
const ModelOnSceneMem *m_buf = &VecUsedGenericModelOnScene_at(&scene->generic_models, mi)->model;
|
||||
size_t vbo_len = mt->topology.vertices.len * sizeof(GenericMeshVertex);
|
||||
memcpy(host_mem_buffer_mem + offset, mt->topology.vertices.buf, vbo_len);
|
||||
VkBufferCopy ra = {.srcOffset = offset, .dstOffset = 0, .size = vbo_len};
|
||||
vkCmdCopyBuffer(command_buffer, host_memory_buffer, m_buf->model.vbo, 1, &ra);
|
||||
vkCmdCopyBuffer(command_buffer, host_memory_buffer, m_buf->vbo, 1, &ra);
|
||||
offset += vbo_len;
|
||||
size_t ebo_len = mt->topology.indexes.len * sizeof(U32);
|
||||
memcpy(host_mem_buffer_mem + offset, mt->topology.indexes.buf, ebo_len);
|
||||
VkBufferCopy rb = {.srcOffset = offset, .dstOffset = 0, .size = ebo_len};
|
||||
vkCmdCopyBuffer(command_buffer, host_memory_buffer, m_buf->model.ebo, 1, &rb);
|
||||
vkCmdCopyBuffer(command_buffer, host_memory_buffer, m_buf->ebo, 1, &rb);
|
||||
offset += ebo_len;
|
||||
}
|
||||
for (size_t mi = 0; mi < scene_template->shiny_models.len; mi++) {
|
||||
const ShinyMeshInSceneTemplate* mt = VecShinyMeshInSceneTemplate_at(&scene_template->shiny_models, mi);
|
||||
const ModelOnSceneMem *m_buf = &VecUsedShinyModelOnScene_at(&scene->shiny_models, mi)->model;
|
||||
size_t vbo_len = mt->topology.vertices.len * sizeof(ShinyMeshVertex);
|
||||
memcpy(host_mem_buffer_mem + offset, mt->topology.vertices.buf, vbo_len);
|
||||
VkBufferCopy ra = {.srcOffset = offset, .dstOffset = 0, .size = vbo_len};
|
||||
vkCmdCopyBuffer(command_buffer, host_memory_buffer, m_buf->vbo, 1, &ra);
|
||||
offset += vbo_len;
|
||||
size_t ebo_len = mt->topology.indexes.len * sizeof(U32);
|
||||
memcpy(host_mem_buffer_mem + offset, mt->topology.indexes.buf, ebo_len);
|
||||
VkBufferCopy rb = {.srcOffset = offset, .dstOffset = 0, .size = ebo_len};
|
||||
vkCmdCopyBuffer(command_buffer, host_memory_buffer, m_buf->ebo, 1, &rb);
|
||||
offset += ebo_len;
|
||||
}
|
||||
|
||||
|
||||
@ -58,4 +58,6 @@ void main(){
|
||||
// todo: add specular map texture
|
||||
vec3 color = natural_color * diffuse_illumination + 0.5 * specular_illumination;
|
||||
fin_color = vec4(color, 1);
|
||||
// fin_color = vec4(length(norm) / 2, 0, 0, 1);
|
||||
fin_color = vec4(fsin_tex, 0, 1);
|
||||
}
|
||||
|
||||
@ -52,4 +52,5 @@ void main(){
|
||||
}
|
||||
vec3 color = color_off * diffuse_illumination + 0.5 * specular_illumination + color_on;
|
||||
fin_color = vec4(color, 1);
|
||||
// fin_color = vec4(length(norm) / 2, 0, 0, 1);
|
||||
}
|
||||
|
||||
@ -320,7 +320,6 @@ int main() {
|
||||
} else {
|
||||
printf("?\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
safe_pthread_join(th);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user