I just managed to draw pure shit

This commit is contained in:
Андреев Григорий 2025-08-02 17:02:58 +03:00
parent af94aeeef7
commit 09a64f4965
7 changed files with 596 additions and 228 deletions

View File

@ -994,8 +994,24 @@ typedef struct {
VkBuffer buffer;
} MargaretBufferInMemoryInfo;
SpanT_struct_Definition(MargaretBufferInMemoryInfo)
SpanT_method_Definition(MargaretBufferInMemoryInfo)
#define MargaretBufferInMemoryInfo_drop(self) {}
#define MargaretBufferInMemoryInfo_clone(self) (*(self))
VecT_trivmove_struct_Definition(MargaretBufferInMemoryInfo);
VecT_trivmove_method_Definition(MargaretBufferInMemoryInfo);
VecT_primitive_zeroinit_method_Definition(MargaretBufferInMemoryInfo);
typedef MargaretBufferInMemoryInfo* MargaretBufferInMemoryInfo_Ptr;
#define MargaretBufferInMemoryInfo_Ptr_drop(self) {}
#define MargaretBufferInMemoryInfo_Ptr_clone(self) (*(self))
VecT_trivmove_struct_Definition(MargaretBufferInMemoryInfo_Ptr);
VecT_trivmove_method_Definition(MargaretBufferInMemoryInfo_Ptr);
VecT_primitive_zeroinit_method_Definition(MargaretBufferInMemoryInfo_Ptr);
SpanT_struct_Definition(MargaretBufferInMemoryInfo_Ptr)
SpanT_method_Definition(MargaretBufferInMemoryInfo_Ptr)
SpanT_VecT_method_Definition(MargaretBufferInMemoryInfo_Ptr)
// Used in autogenerated code
typedef struct {
@ -1009,19 +1025,35 @@ typedef struct {
VkImage image;
} MargaretImageInMemoryInfo;
SpanT_struct_Definition(MargaretImageInMemoryInfo)
SpanT_method_Definition(MargaretImageInMemoryInfo)
#define MargaretImageInMemoryInfo_drop(self) {}
#define MargaretImageInMemoryInfo_clone(self) (*(self))
VecT_trivmove_struct_Definition(MargaretImageInMemoryInfo);
VecT_trivmove_method_Definition(MargaretImageInMemoryInfo);
VecT_primitive_zeroinit_method_Definition(MargaretImageInMemoryInfo);
typedef MargaretImageInMemoryInfo* MargaretImageInMemoryInfo_Ptr;
#define MargaretImageInMemoryInfo_Ptr_drop(self) {}
#define MargaretImageInMemoryInfo_Ptr_clone(self) (*(self))
VecT_trivmove_struct_Definition(MargaretImageInMemoryInfo_Ptr);
VecT_trivmove_method_Definition(MargaretImageInMemoryInfo_Ptr);
VecT_primitive_zeroinit_method_Definition(MargaretImageInMemoryInfo_Ptr);
SpanT_struct_Definition(MargaretImageInMemoryInfo_Ptr)
SpanT_method_Definition(MargaretImageInMemoryInfo_Ptr)
SpanT_VecT_method_Definition(MargaretImageInMemoryInfo_Ptr)
// A handy function to initialize buffers and images (attaching them to allocated memory)
VkDeviceMemory margaret_initialize_buffers_and_images(
VkPhysicalDevice physical_device, VkDevice device,
SpanMargaretBufferInMemoryInfo buffer_hands, SpanMargaretImageInMemoryInfo image_hands,
SpanMargaretBufferInMemoryInfo_Ptr buffer_hands, SpanMargaretImageInMemoryInfo_Ptr image_hands,
VkMemoryPropertyFlags properties
) {
uint32_t memory_types_allowed = -1;
VkDeviceSize offset = 0;
for (size_t i = 0; i < buffer_hands.len; i++) {
MargaretBufferInMemoryInfo* buf_hand = SpanMargaretBufferInMemoryInfo_at(buffer_hands, i);
MargaretBufferInMemoryInfo* buf_hand = *SpanMargaretBufferInMemoryInfo_Ptr_at(buffer_hands, i);
VkBufferCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = buf_hand->sz,
@ -1041,7 +1073,7 @@ VkDeviceMemory margaret_initialize_buffers_and_images(
}
for (size_t i = 0; i < image_hands.len; i++) {
MargaretImageInMemoryInfo* img_hand = SpanMargaretImageInMemoryInfo_at(image_hands, i);
MargaretImageInMemoryInfo* img_hand = *SpanMargaretImageInMemoryInfo_Ptr_at(image_hands, i);
VkImageCreateInfo crinfo = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = VK_IMAGE_TYPE_2D,
@ -1082,13 +1114,13 @@ VkDeviceMemory margaret_initialize_buffers_and_images(
}
for (size_t i = 0; i < buffer_hands.len; i++) {
MargaretBufferInMemoryInfo* buf_hand = SpanMargaretBufferInMemoryInfo_at(buffer_hands, i);
MargaretBufferInMemoryInfo* buf_hand = *SpanMargaretBufferInMemoryInfo_Ptr_at(buffer_hands, i);
if (vkBindBufferMemory(device, buf_hand->buffer, memory, buf_hand->offset) != VK_SUCCESS)
abortf("vkBindBufferMemory");
}
for (size_t i = 0; i < image_hands.len; i++) {
MargaretImageInMemoryInfo* img_hand = SpanMargaretImageInMemoryInfo_at(image_hands, i);
MargaretImageInMemoryInfo* img_hand = *SpanMargaretImageInMemoryInfo_Ptr_at(image_hands, i);
if (vkBindImageMemory(device, img_hand->image, memory, img_hand->offset) != VK_SUCCESS)
abortf("vkBindImageMemory");
}
@ -1371,18 +1403,18 @@ VkDescriptorPool margaret_create_descriptor_set_pool(VkDevice device,
return descriptor_pool;
}
void margaret_record_buf_copying_command_buf(
VkDevice device, VkCommandBuffer command_buffer,
VkBuffer dest_buffer, VkBuffer src_buffer, VkDeviceSize buffer_size
) {
VkCommandBufferBeginInfo beginfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, };
if (vkBeginCommandBuffer(command_buffer, &beginfo) != VK_SUCCESS)
abortf("vkBeginCommandBuffer");
VkBufferCopy regions_to_copy[1] = {(VkBufferCopy){.srcOffset = 0, .dstOffset = 0, .size = buffer_size}};
vkCmdCopyBuffer(command_buffer, src_buffer, dest_buffer, ARRAY_SIZE(regions_to_copy), regions_to_copy);
if (vkEndCommandBuffer(command_buffer) != VK_SUCCESS)
abortf("vkEndCommandBuffer");
}
/* Won't actually use this function, it's too underpowered */
// void margaret_record_buf_copying_command_buf(VkCommandBuffer command_buffer,
// VkBuffer dest_buffer, VkBuffer src_buffer, VkDeviceSize buffer_size
// ) {
// VkCommandBufferBeginInfo beginfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, };
// if (vkBeginCommandBuffer(command_buffer, &beginfo) != VK_SUCCESS)
// abortf("vkBeginCommandBuffer");
// VkBufferCopy regions_to_copy[1] = {(VkBufferCopy){.srcOffset = 0, .dstOffset = 0, .size = buffer_size}};
// vkCmdCopyBuffer(command_buffer, src_buffer, dest_buffer, ARRAY_SIZE(regions_to_copy), regions_to_copy);
// if (vkEndCommandBuffer(command_buffer) != VK_SUCCESS)
// abortf("vkEndCommandBuffer");
// }
VkDescriptorSet margaret_allocate_descriptor_set(VkDevice device, VkDescriptorPool descriptor_pool, VkDescriptorSetLayout layout) {
VkDescriptorSetAllocateInfo alloc_info = {
@ -1397,4 +1429,11 @@ VkDescriptorSet margaret_allocate_descriptor_set(VkDevice device, VkDescriptorPo
return descriptor_set;
}
#define VkBufferCopy_drop(x) {}
#define VkBufferCopy_clone(xp) (*(xp))
VecT_trivmove_struct_Definition(VkBufferCopy)
VecT_trivmove_method_Definition(VkBufferCopy)
VecT_primitive_zeroinit_method_Definition(VkBufferCopy)
#endif

View File

@ -90,7 +90,7 @@ VkRenderPass create_render_pass_0(VkDevice logical_device, VkFormat colorbuffer_
return render_pass;
}
margaret_prep_buffer_mem_info_of_gpu_vbo_Definition(Vertex)
margaret_prep_buffer_mem_info_of_gpu_vbo_Definition(GenericMeshVertex)
PipelineHands create_graphics_pipeline_0(
VkDevice device, VkRenderPass render_pass, uint32_t subpass
@ -107,23 +107,56 @@ PipelineHands create_graphics_pipeline_0(
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] = {
VkVertexInputBindingDescription vertex_bindings[2] = {
{
.binding = 0,
.stride = sizeof(GenericMeshVertex),
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
},
{
.binding = 1,
.stride = sizeof(GenericMeshInstance),
.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE,
}
};
VkVertexInputAttributeDescription vertex_attributes[2 + 4] = {
{
.location = 0,
.binding = 0,
.format = VK_FORMAT_R32G32B32_SFLOAT,
.offset = offsetof(Vertex, pos),
.offset = offsetof(GenericMeshVertex, pos),
},
{
.location = 1,
.binding = 0,
.format = VK_FORMAT_R32G32_SFLOAT,
.offset = offsetof(Vertex, tex),
.offset = offsetof(GenericMeshVertex, tex),
},
/* This is a mat4 datatype, so it will take 4 entire 'locations' */
{
.location = 2,
.binding = 1,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = offsetof(GenericMeshInstance, model_trans) + offsetof(mat4, x)
},
{
.location = 3,
.binding = 1,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = offsetof(GenericMeshInstance, model_trans) + offsetof(mat4, y)
},
{
.location = 4,
.binding = 1,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = offsetof(GenericMeshInstance, model_trans) + offsetof(mat4, z)
},
{
.location = 5,
.binding = 1,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = offsetof(GenericMeshInstance, model_trans) + offsetof(mat4, w)
},
};
@ -153,8 +186,8 @@ PipelineHands create_graphics_pipeline_0(
.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,
// .cullMode = VK_CULL_MODE_BACK_BIT,
.cullMode = VK_CULL_MODE_NONE,
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
.depthBiasEnable = VK_FALSE,
.depthBiasConstantFactor = 0.0f,
@ -237,7 +270,13 @@ PipelineHands create_graphics_pipeline_0(
{
.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,
@ -498,8 +537,8 @@ VkFramebuffer create_IT1_framebuffer(VkDevice device, VkImageView IT1_view, VkIm
void reset_and_record_command_buffer_0(
VkCommandBuffer command_buffer, VkRenderPass render_pass_0,
const PipelineHands* pipeline_and_layout,
VkFramebuffer swapchain_image_framebuffer, VkExtent2D image_extent,
const Scene* scene, VkDescriptorSet my_descriptor_set, mat4 t_mat
VkFramebuffer swapchain_image_framebuffer, VkImage IT1_image, VkExtent2D image_extent,
const Scene* scene, VkDescriptorSet my_descriptor_set, mat4 proj_cam_t, vec3 camera_pos
) {
if (vkResetCommandBuffer(command_buffer, 0) != VK_SUCCESS)
abortf("vkResetCommandBuffer");
@ -537,23 +576,50 @@ void reset_and_record_command_buffer_0(
.extent = image_extent,
};
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
vkCmdPushConstants(command_buffer, pipeline_and_layout->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,
sizeof(mat4), sizeof(vec3), &camera_pos);
for (size_t i = 0; i < scene->models.len; i++) {
const UsedModelOnScene* model = VecUsedModelOnScene_cat(&scene->models, i);
VkBuffer attached_buffers[1] = { model->model.vbo };
VkBuffer attached_buffers[2] = { model->model.vbo, model->instance_attr_buf };
// 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);
VkDeviceSize offsets_in_buffers[2] = {0, 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);
mat4 tt = mat4_mul_mat4(t_mat, model->model_t);
vkCmdPushConstants(command_buffer, pipeline_and_layout->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT,
0, sizeof(mat4), &tt);
vkCmdBindDescriptorSets(
command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout->pipeline_layout, 0,
1, &my_descriptor_set, 0, NULL);
vkCmdDrawIndexed(command_buffer, model->model.indexes, 1, 0, 0, 0);
vkCmdDrawIndexed(command_buffer, model->model.indexes, model->instances.len, 0, 0, 0);
}
vkCmdEndRenderPass(command_buffer);
// VkImageMemoryBarrier barrier = {
// .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
// .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
// .dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
// .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
// .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
// .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
// .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
// .image = IT1_image,
// .subresourceRange = (VkImageSubresourceRange){
// .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
// .baseMipLevel = 0,
// .levelCount = 1,
// .baseArrayLayer = 0,
// .layerCount = 1,
// },
// };
// vkCmdPipelineBarrier(command_buffer,
// VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
// VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
// 0,
// 0, NULL,
// 0, NULL,
// 1, &barrier);
if (vkEndCommandBuffer(command_buffer) != VK_SUCCESS)
abortf("vkEndCommandBuffer");
}
@ -621,6 +687,74 @@ void reset_and_record_command_buffer_1(
abortf("vkEndCommandBuffer");
}
/* 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
) {
if (vkResetCommandBuffer(command_buffer, 0) != VK_SUCCESS)
abortf("vkResetCommandBuffer");
VkCommandBufferBeginInfo info_begin = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
if (vkBeginCommandBuffer(command_buffer, &info_begin) != VK_SUCCESS)
abortf("vkBeginCommandBuffer");
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_cat(&scene->models, mi);
assert(model->instances.len <= 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(&regions_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);
}
vkCmdCopyBuffer(command_buffer, host_memory_buffer, device_instance_attrs_for_all_generic_meshes, regions_to_copy_A.len, regions_to_copy_A.buf);
VecVkBufferCopy_drop(regions_to_copy_A);
}
{
assert(scene->point_lights.len <= pipeline_0_ubo_point_light_max_count);
assert(scene->spotlights.len <= pipeline_0_ubo_spotlight_max_count);
int point_lights = (int)scene->point_lights.len;
int spotlights = (int)scene->spotlights.len;
memcpy(host_mem_buffer_mem + offset_here, &point_lights, sizeof(int));
memcpy(host_mem_buffer_mem + offset_here + sizeof(int), &spotlights, sizeof(int));
memcpy(host_mem_buffer_mem + offset_here + sizeof(int) * 2, scene->point_lights.buf, sizeof(Pipeline0PointLight) * point_lights);
memcpy(host_mem_buffer_mem + offset_here + sizeof(int) * 2 + sizeof(Pipeline0PointLight) * point_lights,
scene->spotlights.buf, sizeof(Pipeline0Spotlight) * spotlights);
VkBufferCopy regions_to_copy_B[] = {
{
.srcOffset = offset_here, .dstOffset = offsetof(Pipeline0UBO, point_light_count),
.size = sizeof(int),
},
{
.srcOffset = offset_here + sizeof(int), .dstOffset = offsetof(Pipeline0UBO, spotlight_count),
.size = sizeof(int),
},
{
.srcOffset = offset_here + 2 * sizeof(int), .dstOffset = offsetof(Pipeline0UBO, point_light_arr),
.size = sizeof(Pipeline0PointLight) * point_lights,
},
{
.srcOffset = offset_here + 2 * sizeof(int) + sizeof(Pipeline0PointLight) * point_lights,
.dstOffset = offsetof(Pipeline0UBO, spotlight_arr),
.size = sizeof(Pipeline0Spotlight) * spotlights,
},
};
vkCmdCopyBuffer(command_buffer, host_memory_buffer, device_lighting_ubo, ARRAY_SIZE(regions_to_copy_B), regions_to_copy_B);
}
if (vkEndCommandBuffer(command_buffer) != VK_SUCCESS)
abortf("vkEndCommandBuffer");
}
// todo: add here deletion and recreation of several synchronization primitives
void recreate_swapchain(
@ -660,11 +794,11 @@ typedef struct {
int main() {
prepare_shaders();
ConstSpanU8 GPU = cstr("amd");
ConstSpanU8 bugged_GPU = cstr("nvidia");
ConstSpanU8 GPU = cstr("nvidia");
ConstSpanU8 bugged_GPU = cstr("nothere");
bool ENABLE_VALIDATION_LAYERS = true;
U32 MAX_WIN_WIDTH = 1920;
U32 MAX_WIN_HEIGHT = 1080;
const U32 MAX_WIN_WIDTH = 1920;
const U32 MAX_WIN_HEIGHT = 1080;
MargaretSingleWindowSetup x = MargaretSingleWindowSetup_new();
Margaret_WEP wep = Margaret_WEP_new(x.dpy, x.win);
@ -716,9 +850,14 @@ int main() {
MargaretSwapchainBundle swfb = MargaretSwapchainBundle_new(device, queue_fam, swapchain_details, surface, render_pass_1, NULL);
// Filling scene info
ModelTopology cylinder_1 = generate_one_fourth_of_a_cylinder(10, 2, 6);
ModelTopology cylinder_2 = generate_one_fourth_of_a_cylinder(5, 5, 10);
SceneTemplate scene_template = {.models = VecModelInSceneTemplate_new(),
.point_lights_max_count = pipeline_0_ubo_point_light_max_count,
.spotlights_max_count = pipeline_0_ubo_spotlight_max_count};
VecModelInSceneTemplate_append(&scene_template.models,
(ModelInSceneTemplate){.topology = generate_one_fourth_of_a_cylinder(10, 2, 6), .max_instance_count = 100});
VecModelInSceneTemplate_append(&scene_template.models,
(ModelInSceneTemplate){.topology = generate_one_fourth_of_a_cylinder(5, 5, 10), .max_instance_count = 1});
// TextureDataR8G8B8A8 wood_texture_data = generate_texture_for_one_fourth_of_a_cylinder(20, 10, 2, 6);
// todo: learn how to use libpng
TextureDataR8G8B8A8 cyl_1_diffuse_tex = TextureDataR8G8B8A8_read_from_file("test_textures/log_10_2_6.r8g8b8a8");
@ -726,95 +865,130 @@ int main() {
// todo: and at the same time I need to add methods to convert between these formats
TextureDataR8G8B8A8 cyl_1_normal_tex = TextureDataR8G8B8A8_read_from_file("test_textures/log_10_2_6_NORMAL.r8g8b8a8");
// todo: kill myself
// We have only one staging buffer in host memory (because we don't really need more)
MargaretBufferInMemoryInfo host_mem_buffer = (MargaretBufferInMemoryInfo){ .sz =
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(SceneTemplate_get_space_for_initial_model_topology_transfer(&scene_template),
MAX_U64(SceneTemplate_get_space_needed_for_widest_state_transfer(&scene_template),
MAX_U64(TextureDataR8G8B8A8_get_size_in_bytes(&cyl_1_diffuse_tex),
MAX_U64(TextureDataR8G8B8A8_get_size_in_bytes(&cyl_1_normal_tex), 0)))))
MAX_U64(TextureDataR8G8B8A8_get_size_in_bytes(&cyl_1_normal_tex), 0))))
, .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT };
MargaretBufferInMemoryInfo_Ptr host_mem_buffer_SPAN[1] = {&host_mem_buffer};
VkDeviceMemory host_mem = margaret_initialize_buffers_and_images(physical_device, device,
(SpanMargaretBufferInMemoryInfo){.data = &host_mem_buffer, .len = 1}, (SpanMargaretImageInMemoryInfo){ 0 },
(SpanMargaretBufferInMemoryInfo_Ptr){.data = host_mem_buffer_SPAN, .len = 1},
(SpanMargaretImageInMemoryInfo_Ptr){ 0 },
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
MargaretBufferInMemoryInfo device_mem_buffers[] = {
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)),
// todo: split this in two (or maybe even better: merge it all into one/two buffer and use offsets
VecMargaretBufferInMemoryInfo device_ebo_and_vbo_buffers_for_generic_meshes = VecMargaretBufferInMemoryInfo_new();
for (size_t mi = 0; mi < scene_template.models.len; mi++) {
const ModelInSceneTemplate* M = VecModelInSceneTemplate_cat(&scene_template.models, mi);
VecMargaretBufferInMemoryInfo_append(&device_ebo_and_vbo_buffers_for_generic_meshes,
GenericMeshVertex_buffer_crinfo_of_gpu_vbo(M->topology.vertices.len));
VecMargaretBufferInMemoryInfo_append(&device_ebo_and_vbo_buffers_for_generic_meshes,
margaret_prep_buffer_mem_info_of_gpu_ebo(M->topology.indexes.len));
}
MargaretBufferInMemoryInfo device_lighting_ubo = margaret_prep_buffer_mem_info_of_gpu_ubo(sizeof(Pipeline0UBO));
MargaretBufferInMemoryInfo device_instance_attrs_for_all_generic_meshes = (MargaretBufferInMemoryInfo){
.sz = SceneTemplate_get_space_needed_for_all_instance_attributes(&scene_template),
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
};
MargaretImageInMemoryInfo device_mem_images[] = {
margaret_prep_image_mem_info_of_colorbuffer(MAX_WIN_WIDTH, MAX_WIN_HEIGHT, IT1_format.some),
margaret_prep_image_mem_info_of_zbuffer(MAX_WIN_WIDTH, MAX_WIN_HEIGHT, zbuffer_format.some),
margaret_prep_image_mem_info_of_gpu_texture_srgba(cyl_1_diffuse_tex.width,
TextureDataR8G8B8A8_get_height(&cyl_1_diffuse_tex)),
margaret_prep_image_mem_info_of_gpu_texture_srgba(cyl_1_normal_tex.width,
TextureDataR8G8B8A8_get_height(&cyl_1_normal_tex)),
VecMargaretBufferInMemoryInfo_Ptr device_mem_buffers_SPAN = VecMargaretBufferInMemoryInfo_Ptr_new();
for (size_t i = 0; i < device_ebo_and_vbo_buffers_for_generic_meshes.len; i++) {
VecMargaretBufferInMemoryInfo_Ptr_append(&device_mem_buffers_SPAN,
VecMargaretBufferInMemoryInfo_at(&device_ebo_and_vbo_buffers_for_generic_meshes, i));
}
VecMargaretBufferInMemoryInfo_Ptr_append(&device_mem_buffers_SPAN, &device_lighting_ubo);
VecMargaretBufferInMemoryInfo_Ptr_append(&device_mem_buffers_SPAN, &device_instance_attrs_for_all_generic_meshes);
printf("Buffers: %lu\n", device_mem_buffers_SPAN.len);
MargaretImageInMemoryInfo device_IT1_image = margaret_prep_image_mem_info_of_colorbuffer(MAX_WIN_WIDTH, MAX_WIN_HEIGHT, IT1_format.some);
MargaretImageInMemoryInfo device_zbuffer_image = margaret_prep_image_mem_info_of_zbuffer(MAX_WIN_WIDTH, MAX_WIN_HEIGHT, zbuffer_format.some);
MargaretImageInMemoryInfo device_cyl_1_diffuse_texture = margaret_prep_image_mem_info_of_gpu_texture_srgba(cyl_1_diffuse_tex.width,
TextureDataR8G8B8A8_get_height(&cyl_1_diffuse_tex));
MargaretImageInMemoryInfo device_cyl_1_normal_texture = margaret_prep_image_mem_info_of_gpu_texture_srgba(cyl_1_normal_tex.width,
TextureDataR8G8B8A8_get_height(&cyl_1_normal_tex));
MargaretImageInMemoryInfo_Ptr device_mem_images_SPAN[] = {
&device_IT1_image, &device_zbuffer_image, &device_cyl_1_diffuse_texture, &device_cyl_1_normal_texture
};
// todo: replace this ugly garbage with pointer spans. Seriously, this is fucking digusting
VkDeviceMemory device_mem = margaret_initialize_buffers_and_images(physical_device, device,
(SpanMargaretBufferInMemoryInfo){ .data = device_mem_buffers, .len = ARRAY_SIZE(device_mem_buffers)},
(SpanMargaretImageInMemoryInfo){ .data = device_mem_images, .len = ARRAY_SIZE(device_mem_images) },
VecMargaretBufferInMemoryInfo_Ptr_to_SpanMargaretBufferInMemoryInfo_Ptr(&device_mem_buffers_SPAN),
(SpanMargaretImageInMemoryInfo_Ptr){ .data = device_mem_images_SPAN, .len = ARRAY_SIZE(device_mem_images_SPAN) },
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
MargaretBufferInMemoryInfo device_vbo_1_buffer = device_mem_buffers[0];
MargaretBufferInMemoryInfo device_ebo_1_buffer = device_mem_buffers[1];
MargaretBufferInMemoryInfo device_vbo_2_buffer = device_mem_buffers[2];
MargaretBufferInMemoryInfo device_ebo_2_buffer = device_mem_buffers[3];
MargaretBufferInMemoryInfo device_ubo_my_buffer = device_mem_buffers[4];
MargaretImageInMemoryInfo device_IT1_image = device_mem_images[0];
MargaretImageInMemoryInfo device_zbuffer_image = device_mem_images[1];
MargaretImageInMemoryInfo device_cyl_1_diffuse_texture = device_mem_images[2];
MargaretImageInMemoryInfo device_cyl_1_normal_texture = device_mem_images[3];
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);
VkCommandBuffer rendering_command_buffer_1 = margaret_allocate_command_buffer(device, command_pool);
VkCommandBuffer transfer_command_buffer = margaret_allocate_command_buffer(device, command_pool);
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(Pipeline0UBO));
Scene scene = Scene_new();
{
size_t offset_in_attr_buffer = 0;
for (size_t mi = 0; mi < scene_template.models.len; mi++) {
// UsedModelOnScene* ptb = VecUsedModelOnScene_cat()
const ModelInSceneTemplate* M = VecModelInSceneTemplate_cat(&scene_template.models, mi);
VecUsedModelOnScene_append(&scene.models, (UsedModelOnScene){
.model = (ModelOnScene){
.vbo = VecMargaretBufferInMemoryInfo_cat(&device_ebo_and_vbo_buffers_for_generic_meshes,
2 * mi + 0)->buffer,
.ebo = VecMargaretBufferInMemoryInfo_cat(&device_ebo_and_vbo_buffers_for_generic_meshes,
2 * mi + 1)->buffer,
.indexes = M->topology.indexes.len,
},
.instances = VecGenericMeshInstance_new(),
.instance_attr_buf = 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 (int X = 0; X < 10; X++) {
for (int Z = 0; Z < 10; Z++) {
VecGenericMeshInstance_append(&VecUsedModelOnScene_at(&scene.models, 0)->instances,
(GenericMeshInstance){ .model_trans = marie_translation_mat4((vec3){11.f * (float)X, -6, 4.f * (float)Z}) });
}
}
VecGenericMeshInstance_append(&VecUsedModelOnScene_at(&scene.models, 1)->instances, (GenericMeshInstance){
.model_trans = mat4_E
});
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
SceneTemplate_copy_initial_model_topology_and_rerecord_transfer_cmd(&scene_template, &scene, host_mem_buffer_mem, transfer_command_buffer, host_mem_buffer.buffer);
{
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);
VkCommandBuffer command_buffers[1] = { transfer_command_buffer };
// VkSemaphore signaling_semaphores[1] = { swfb.in_frame_transfer_complete };
VkSubmitInfo submit_info = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.commandBufferCount = ARRAY_SIZE(command_buffers),
.pCommandBuffers = command_buffers,
// .signalSemaphoreCount = ARRAY_SIZE(signaling_semaphores),
// .pSignalSemaphores = signaling_semaphores,
};
if (vkQueueSubmit(graphics_queue, 1, &submit_info, NULL) != VK_SUCCESS)
abortf("vkQueueSubmit\n");
}
vkDeviceWaitIdle(device);
{
memcpy(host_mem_buffer_mem, cyl_1_diffuse_tex.pixels.buf,
TextureDataR8G8B8A8_get_size_in_bytes(&cyl_1_diffuse_tex));
margaret_copy_buffer_to_texture_for_frag_shader_imm(device, command_pool, graphics_queue,
&device_cyl_1_diffuse_texture, host_mem_buffer.buffer);
}
vkDeviceWaitIdle(device);
{
memcpy(host_mem_buffer_mem, cyl_1_normal_tex.pixels.buf, TextureDataR8G8B8A8_get_size_in_bytes(&cyl_1_normal_tex));
margaret_copy_buffer_to_texture_for_frag_shader_imm(device, command_pool, graphics_queue,
&device_cyl_1_normal_texture, host_mem_buffer.buffer);
}
vkDeviceWaitIdle(device);
// We sent everything we needed. but host_mem_buffer_mem may be used later
@ -830,25 +1004,21 @@ int main() {
// My cylinder 1 normal texture also needs NkImageView
VkImageView cyl_1_normal_texture_view = margaret_create_view_for_image(device, &device_cyl_1_normal_texture, VK_IMAGE_ASPECT_COLOR_BIT);
Scene scene = Scene_new();
VecUsedModelOnScene_append(&scene.models, (UsedModelOnScene){.model = {
.vbo = device_vbo_1_buffer.buffer, .ebo = device_ebo_1_buffer.buffer, .indexes = cylinder_1.indexes.len
}, .model_t = marie_translation_mat4((vec3){1, -1, 5}) });
VecUsedModelOnScene_append(&scene.models, (UsedModelOnScene){.model = {
.vbo = device_vbo_2_buffer.buffer, .ebo = device_ebo_2_buffer.buffer, .indexes = cylinder_2.indexes.len
}, .model_t = marie_translation_mat4((vec3){6, -3, 16}) });
// Right now I only have one light source
VecPipeline0PointLight_append(&scene.point_lights, (Pipeline0PointLight){.pos = {0}, .color = {100, 100, 100}});
// These samplers are global for a lot of my future textures
VkSampler linear_sampler = margaret_create_sampler(physical_device, device, true);
VkSampler nearest_sampler = margaret_create_sampler(physical_device, device, false);
VkDescriptorPool descriptor_pool = margaret_create_descriptor_set_pool(device, 1, 3, 2);
VkDescriptorPool descriptor_pool = margaret_create_descriptor_set_pool(device, 1, 3, 2);
VkDescriptorSet descriptor_set_for_pipeline_0 = margaret_allocate_descriptor_set(device, descriptor_pool, pipeline_hands_0.descriptor_set_layout);
VkDescriptorSet descriptor_set_for_pipeline_1 = margaret_allocate_descriptor_set(device, descriptor_pool, pipeline_hands_1.descriptor_set_layout);
// Configuring my descriptor sets, that I just allocated
VkDescriptorBufferInfo buffer_info_for_descriptor_0_in_set_0 = {
.buffer = device_ubo_my_buffer.buffer,
.buffer = device_lighting_ubo.buffer,
.offset = 0,
.range = sizeof(Pipeline0UBO),
};
@ -909,6 +1079,7 @@ int main() {
vkUpdateDescriptorSets(device, ARRAY_SIZE(writes_in_descriptor_sets), writes_in_descriptor_sets, 0, NULL);
CamControlInfo my_cam_control_info = CamControlInfo_new();
vec3 Buba_control_info = {0};
// Mainloop
margaret_ns_time start = margaret_clock_gettime_monotonic_raw();
@ -916,6 +1087,9 @@ int main() {
int frame_count_since_key = 0;
margaret_ns_time prev_frame_timestamp = start;
/* Will happen mid-frame */
bool dt_transfer_required = true;
bool pressed_first_0x80[0x80] = {0};
while (true) {
margaret_ns_time frame_A0 = margaret_clock_gettime_monotonic_raw();
@ -942,6 +1116,18 @@ int main() {
KeySym keysym = XLookupKeysym(&ev->xkey, 0);
if (keysym < 0x80)
pressed_first_0x80[keysym] = false;
if (keysym == XK_1) {
vec3 p = my_cam_control_info.pos;
VecPipeline0PointLight_at(&scene.point_lights, 0)->pos = p;
printf("Point light source pos set to %f %f %f\n", p.x, p.y, p.z);
dt_transfer_required = true;
} else if (keysym == XK_2) {
scene.hdr_factor /= 1.05f;
printf("hdr factor decreased to %f\n", scene.hdr_factor);
} else if (keysym == XK_3) {
scene.hdr_factor *= 1.05f;
printf("hdr factor increased to %f\n", scene.hdr_factor);
}
}
}
if (pressed_first_0x80[XK_w])
@ -957,6 +1143,33 @@ int main() {
if (pressed_first_0x80[XK_e])
CamControlInfo_up(&my_cam_control_info, fl);
if (pressed_first_0x80[XK_j]) {\
Buba_control_info.x -= fl;
VecGenericMeshInstance_at(&VecUsedModelOnScene_at(&scene.models, 1)->instances, 0)->model_trans =
marie_translation_mat4(Buba_control_info);
dt_transfer_required = true;
}
if (pressed_first_0x80[XK_k]) {\
Buba_control_info.z -= fl;
VecGenericMeshInstance_at(&VecUsedModelOnScene_at(&scene.models, 1)->instances, 0)->model_trans =
marie_translation_mat4(Buba_control_info);
dt_transfer_required = true;
}
if (pressed_first_0x80[XK_l]) {\
Buba_control_info.z += fl;
VecGenericMeshInstance_at(&VecUsedModelOnScene_at(&scene.models, 1)->instances, 0)->model_trans =
marie_translation_mat4(Buba_control_info);
dt_transfer_required = true;
}
if (pressed_first_0x80[XK_semicolon]) {\
Buba_control_info.x += fl;
VecGenericMeshInstance_at(&VecUsedModelOnScene_at(&scene.models, 1)->instances, 0)->model_trans =
marie_translation_mat4(Buba_control_info);
dt_transfer_required = true;
}
// Rendering
vkWaitForFences(device, 1, &swfb.in_flight_fence, VK_TRUE, UINT64_MAX);
uint32_t ij;
@ -980,62 +1193,63 @@ int main() {
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}};
scene.color = (VkClearColorValue){{0, 0, 0, 1}};
mat4 projection_matrix = marie_perspective_projection_fov_mat4((float)wep.width, (float)wep.height,
my_cam_control_info.fov, 0.01f, 1000);
mat4 camera_rotation_matrix = marie_mat3_to_mat4_transposed(my_cam_control_info.cam_basis);
mat4 camera_translation_matrix = marie_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));
{
if (dt_transfer_required){
assert(scene.spotlights.len < pipeline_0_ubo_spotlight_max_count);
assert(scene.point_lights.len < pipeline_0_ubo_point_light_max_count);
Pipeline0UBO* subo = (Pipeline0UBO*)host_mem_buffer_mem;
// todo: speed it up a little
subo->spotlight_count = (int)scene.spotlights.len;
memcpy(&subo->spotlight_arr, scene.spotlights.buf, scene.spotlights.len * sizeof(Pipeline0Spotlight));
subo->point_light_count = (int)scene.point_lights.len;
memcpy(&subo->point_light_arr, scene.point_lights.buf, scene.point_lights.len * sizeof(Pipeline0PointLight));
VkCommandBuffer command_buffers[1] = { uniform_transfer_command_buffer };
copy_scene_info_to_buffer_and_rerecord_full_copy_command_buffer(
transfer_command_buffer, host_mem_buffer.buffer, host_mem_buffer_mem, &scene, device_lighting_ubo.buffer,
device_instance_attrs_for_all_generic_meshes.buffer);
VkCommandBuffer command_buffers[1] = { transfer_command_buffer };
VkSemaphore signaling_semaphores[1] = { swfb.in_frame_transfer_complete };
VkSubmitInfo ubo_copying_cmd_buffer_submit = {
VkSubmitInfo submit_info = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.commandBufferCount = ARRAY_SIZE(command_buffers),
.pCommandBuffers = command_buffers,
.signalSemaphoreCount = ARRAY_SIZE(signaling_semaphores),
.pSignalSemaphores = signaling_semaphores,
};
vkQueueSubmit(graphics_queue, 1, &ubo_copying_cmd_buffer_submit, NULL);
if (vkQueueSubmit(graphics_queue, 1, &submit_info, NULL) != VK_SUCCESS)
abortf("vkQueueSubmit\n");
}
reset_and_record_command_buffer_0(rendering_command_buffer_0, render_pass_0, &pipeline_hands_0,
IT1_framebuffer, swfb.extent, &scene, descriptor_set_for_pipeline_0, t_mat);
reset_and_record_command_buffer_0(
rendering_command_buffer_0, render_pass_0, &pipeline_hands_0,
IT1_framebuffer, device_IT1_image.image, swfb.extent, &scene,
descriptor_set_for_pipeline_0, t_mat, my_cam_control_info.pos);
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}, &scene, descriptor_set_for_pipeline_1);
{
VkSemaphore waiting_for_semaphores[2] = {
swfb.image_available_semaphore, swfb.in_frame_transfer_complete
VkSemaphore waiting_for_semaphores_if_dt_transfer_required[1] = {
swfb.in_frame_transfer_complete
};
VkPipelineStageFlags waiting_stages[2] = {
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
VkPipelineStageFlags waiting_stages_if_dt_transfer_required[1] = {
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
};
assert(ARRAY_SIZE(waiting_for_semaphores) == ARRAY_SIZE(waiting_stages));
// VkCommandBuffer command_buffers[1] = {*VecVkCommandBuffer_cat(&rendering_command_buffers, ij)};
assert(ARRAY_SIZE(waiting_for_semaphores_if_dt_transfer_required) ==
ARRAY_SIZE(waiting_stages_if_dt_transfer_required));
VkCommandBuffer command_buffers[1] = {rendering_command_buffer_0};
VkSemaphore signaling_semaphores[1] = { swfb.rendered_to_IT1_semaphore };
VkSubmitInfo cmd_submit_info = {
VkSubmitInfo submit_info = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
// We wait for `waiting_for_semaphores` before THESE stages
// waitSemaphoreCount specifies size for both pWaitSemaphores and pWaitDstStageMask
.waitSemaphoreCount = ARRAY_SIZE(waiting_for_semaphores),
.pWaitSemaphores = waiting_for_semaphores,
.pWaitDstStageMask = waiting_stages,
.waitSemaphoreCount = dt_transfer_required ?
ARRAY_SIZE(waiting_for_semaphores_if_dt_transfer_required) : 0,
.pWaitSemaphores = dt_transfer_required ?
waiting_for_semaphores_if_dt_transfer_required : NULL,
.pWaitDstStageMask = dt_transfer_required ?
waiting_stages_if_dt_transfer_required : NULL,
.commandBufferCount = ARRAY_SIZE(command_buffers),
.pCommandBuffers = command_buffers,
@ -1043,13 +1257,18 @@ int main() {
.signalSemaphoreCount = ARRAY_SIZE(signaling_semaphores),
.pSignalSemaphores = signaling_semaphores,
};
if (vkQueueSubmit(graphics_queue, 1, &cmd_submit_info, NULL) != VK_SUCCESS)
if (vkQueueSubmit(graphics_queue, 1, &submit_info, NULL) != VK_SUCCESS)
abortf("vkQueueSubmit");
}
{
VkSemaphore waiting_for_semaphores[1] = { swfb.rendered_to_IT1_semaphore };
VkPipelineStageFlags waiting_stages[1] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
VkSemaphore waiting_for_semaphores[2] = {
swfb.image_available_semaphore,
swfb.rendered_to_IT1_semaphore };
VkPipelineStageFlags waiting_stages[2] = {
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
// VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
};
assert(ARRAY_SIZE(waiting_for_semaphores) == ARRAY_SIZE(waiting_stages));
VkCommandBuffer command_buffers[1] = { rendering_command_buffer_1 };
VkSemaphore signaling_semaphores[1] = { swfb.render_finished_semaphore };
@ -1102,6 +1321,7 @@ int main() {
abortf("vkQueuePresentKHR");
}
}
dt_transfer_required = false;
margaret_ns_time frame_B0 = margaret_clock_gettime_monotonic_raw();
if (margaret_ns_time_sec_diff(frame_A0, frame_B0) > 0.3) {
fprintf(stderr, "]]] Profiling frame scheduling:\n"
@ -1118,11 +1338,11 @@ int main() {
}
}
vkDeviceWaitIdle(device);
// The End
// dropping scene
Scene_drop(scene);
ModelTopology_drop(cylinder_1);
ModelTopology_drop(cylinder_2);
// todo: destroy objects that hold scene and model topology
// destroying vulkan objects
vkDestroyDescriptorPool(device, descriptor_pool, NULL);
vkDestroySampler(device, linear_sampler, NULL);
@ -1130,11 +1350,8 @@ int main() {
vkDestroyImageView(device, cyl_1_diffuse_texture_view, NULL);
vkDestroyImageView(device, cyl_1_normal_texture_view, NULL);
vkDestroyBuffer(device, device_vbo_1_buffer.buffer, NULL);
vkDestroyBuffer(device, device_ebo_1_buffer.buffer, NULL);
vkDestroyBuffer(device, device_vbo_2_buffer.buffer, NULL);
vkDestroyBuffer(device, device_ebo_2_buffer.buffer, NULL);
vkDestroyBuffer(device, device_ubo_my_buffer.buffer, NULL);
// todo: destroy buffers for model topology
vkDestroyBuffer(device, device_lighting_ubo.buffer, NULL);
vkDestroyImage(device, device_cyl_1_diffuse_texture.image, NULL);
vkDestroyImage(device, device_cyl_1_normal_texture.image, NULL);
vkDestroyImage(device, device_IT1_image.image, NULL);

View File

@ -12,28 +12,49 @@
typedef struct {
vec3 pos;
vec2 tex;
} Vertex;
} GenericMeshVertex;
#define Vertex_drop(vp) {}
#define Vertex_clone(vp) (*(vp))
#define GenericMeshVertex_drop(vp) {}
#define GenericMeshVertex_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)
VecT_trivmove_struct_Definition(GenericMeshVertex)
VecT_trivmove_method_Definition(GenericMeshVertex)
VecT_primitive_zeroinit_method_Definition(GenericMeshVertex)
SpanT_struct_Definition(GenericMeshVertex)
SpanT_method_Definition(GenericMeshVertex)
SpanT_VecT_method_Definition(GenericMeshVertex)
typedef struct {
VecVertex vertices;
VecGenericMeshVertex vertices;
VecU32 indexes;
} ModelTopology;
void ModelTopology_drop(ModelTopology self) {
VecVertex_drop(self.vertices);
VecGenericMeshVertex_drop(self.vertices);
VecU32_drop(self.indexes);
}
ModelTopology ModelTopology_clone(const ModelTopology* self) {
return (ModelTopology){.vertices = VecGenericMeshVertex_new(&self->vertices), .indexes = VecU32_clone(&self->indexes)};
}
typedef struct {
ModelTopology topology;
U32 max_instance_count;
} ModelInSceneTemplate;
void ModelInSceneTemplate_drop(ModelInSceneTemplate self) {
ModelTopology_drop(self.topology);
}
ModelInSceneTemplate ModelInSceneTemplate_clone(const ModelInSceneTemplate* self) {
return (ModelInSceneTemplate){.topology = ModelTopology_clone(&self->topology), .max_instance_count = self->max_instance_count};
}
VecT_trivmove_struct_Definition(ModelInSceneTemplate)
VecT_trivmove_method_Definition(ModelInSceneTemplate)
VecT_primitive_zeroinit_method_Definition(ModelInSceneTemplate)
typedef struct {
vec2 win_scale;
} Pipeline1PushRangeVertex;
@ -77,19 +98,62 @@ VecT_trivmove_struct_Definition(Pipeline0PointLight)
VecT_trivmove_method_Definition(Pipeline0PointLight)
VecT_primitive_zeroinit_method_Definition(Pipeline0PointLight)
typedef struct {
mat4 model_trans;
} GenericMeshInstance;
#define GenericMeshInstance_drop(vp) {}
#define GenericMeshInstance_clone(vp) (*(vp))
VecT_trivmove_struct_Definition(GenericMeshInstance)
VecT_trivmove_method_Definition(GenericMeshInstance)
VecT_primitive_zeroinit_method_Definition(GenericMeshInstance)
typedef struct {
VecModelInSceneTemplate models;
size_t point_lights_max_count;
size_t spotlights_max_count;
} SceneTemplate;
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_cat(&self->models, mi);
s += M->max_instance_count * sizeof(GenericMeshInstance);
}
return s;
}
size_t SceneTemplate_get_space_needed_for_widest_state_transfer(const SceneTemplate* self) {
return self->point_lights_max_count * sizeof(Pipeline0PointLight) +
self->spotlights_max_count * sizeof(Pipeline0Spotlight) +
SceneTemplate_get_space_needed_for_all_instance_attributes(self);
}
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_cat(&self->models, mi);
s += M->topology.vertices.len * sizeof(GenericMeshVertex) + M->topology.indexes.len * sizeof(U32);
}
return s;
}
#define pipeline_0_ubo_point_light_max_count 20
#define pipeline_0_ubo_spotlight_max_count 120
typedef struct {
int spotlight_count;
int point_light_count;
int spotlight_count;
char _padding_1[8];
Pipeline0PointLight point_light_arr[pipeline_0_ubo_point_light_max_count];
Pipeline0Spotlight spotlight_arr[pipeline_0_ubo_spotlight_max_count];
} Pipeline0UBO;
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));
return MAX_U64(self->vertices.len * sizeof(GenericMeshVertex), self->indexes.len * sizeof(U32));
}
void TextureDataR8_pixel_maxing(TextureDataR8* self, S32 x, S32 y, U8 val) {
@ -205,33 +269,6 @@ void TextureDataR8_draw_one_segment_maxing(TextureDataR8* self,
TextureDataR8_draw_inner_line_maxing(self, v1, v2, r_cut, r_decay);
}
// 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;
// }
ModelTopology generate_one_fourth_of_a_cylinder(float w, float r, U32 k) {
assert(k >= 1);
const float a = M_PI_2f / (float)k;
@ -240,33 +277,33 @@ ModelTopology generate_one_fourth_of_a_cylinder(float w, float r, U32 k) {
const vec2 v1tex = {(r + w) / (2 * r + w), r / (2 * r + k * l)};
const vec2 v2tex = {r / (2 * r + w), 2 * r / (2 * r + k * l)};
const vec2 v3tex = {(r + w) / (2 * r + w), 2 * r / (2 * r + 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}});
VecGenericMeshVertex vertices = VecGenericMeshVertex_new(); // todo: reserve 4 * k + 6
VecGenericMeshVertex_append(&vertices, (GenericMeshVertex){.pos = {0, 0, 0}, .tex = v0tex});
VecGenericMeshVertex_append(&vertices, (GenericMeshVertex){.pos = {w, 0, 0}, .tex = v1tex});
VecGenericMeshVertex_append(&vertices, (GenericMeshVertex){.pos = {0, r, 0}, .tex = v2tex});
VecGenericMeshVertex_append(&vertices, (GenericMeshVertex){.pos = {w, r, 0}, .tex = v3tex});
VecGenericMeshVertex_append(&vertices, (GenericMeshVertex){.pos = {0, 0, -r}, .tex = {r / (2 * r + w), 0}});
VecGenericMeshVertex_append(&vertices, (GenericMeshVertex){.pos = {w, 0, -r}, .tex = {(r + w) / (2 * r + w), 0}});
for (U32 i = 1; i <= k; i++) {
VecVertex_append(&vertices, (Vertex){
VecGenericMeshVertex_append(&vertices, (GenericMeshVertex){
.pos = {0, cosf(a * i) * r, -sinf(a * i) * r},
.tex = vec2_add_vec2(v0tex, (vec2){r / (2 * r + w) * -sinf(a * i), r / (2 * r + k * l) * cos(a * i)})
});
}
for (U32 i = 1; i <= k; i++) {
VecVertex_append(&vertices, (Vertex){
VecGenericMeshVertex_append(&vertices, (GenericMeshVertex){
.pos = {w, cosf(a * i) * r, -sinf(a * i) * r},
.tex = vec2_add_vec2(v1tex, (vec2){r / (2 * r + w) * sinf(a * i), r / (2*r + k * l) * cos(a * i)})
});
}
for (U32 i = 1; i <= k; i++) {
VecVertex_append(&vertices, (Vertex){
VecGenericMeshVertex_append(&vertices, (GenericMeshVertex){
.pos = {0, cosf(a * i) * r, -sinf(a * i) * r},
.tex = {v2tex.x, v2tex.y + i * l / (2*r + k * l)}
});
}
for (U32 i = 1; i <= k; i++) {
VecVertex_append(&vertices, (Vertex){
VecGenericMeshVertex_append(&vertices, (GenericMeshVertex){
.pos = {w, cosf(a * i) * r, -sinf(a * i) * r},
.tex = {v3tex.x, v3tex.y + i * l / (2*r + k * l)}
});

View File

@ -3,7 +3,8 @@
#include "r0_assets.h"
/* No offset yet */
/* No offset yet.
* Contains references to vulkan handlers for buffers */
typedef struct {
VkBuffer vbo;
VkBuffer ebo;
@ -17,13 +18,25 @@ VecT_trivmove_struct_Definition(ModelOnScene)
VecT_trivmove_method_Definition(ModelOnScene)
VecT_primitive_zeroinit_method_Definition(ModelOnScene)
/* Contains both data for model instances attributes and buffer (+offset) where it is stored */
typedef struct {
ModelOnScene model;
mat4 model_t;
VecGenericMeshInstance instances;
VkBuffer instance_attr_buf;
VkDeviceSize instance_attr_buf_offset;
U32 limit_max_instance_count;
} UsedModelOnScene;
#define UsedModelOnScene_drop(vp) {}
#define UsedModelOnScene_clone(vp) (*(vp))
void UsedModelOnScene_drop(UsedModelOnScene 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
};
}
VecT_trivmove_struct_Definition(UsedModelOnScene)
VecT_trivmove_method_Definition(UsedModelOnScene)
@ -96,7 +109,7 @@ typedef struct {
} Scene;
Scene Scene_new() {
return (Scene){.models = VecUsedModelOnScene_new(), .color = {.float32 = {1, 0.5, 0.7}},
return (Scene){.models = VecUsedModelOnScene_new(), .color = {.float32 = {0, 0, 0, 1}},
.gamma_correction_factor = 2.2, .hdr_factor = 1, .lsd_factor = 0, .anim_time = 0,
.spotlights = VecPipeline0Spotlight_new(), .point_lights = VecPipeline0PointLight_new()};
}
@ -105,5 +118,39 @@ void Scene_drop(Scene self) {
VecUsedModelOnScene_drop(self.models);
}
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);
if (vkResetCommandBuffer(command_buffer, 0) != VK_SUCCESS)
abortf("vkResetCommandBuffer");
VkCommandBufferBeginInfo info_begin = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
if (vkBeginCommandBuffer(command_buffer, &info_begin) != VK_SUCCESS)
abortf("vkBeginCommandBuffer");
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_cat(&scene_template->models, mi);
const UsedModelOnScene* m_buf = VecUsedModelOnScene_cat(&scene->models, mi);
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);
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);
offset += ebo_len;
}
if (vkEndCommandBuffer(command_buffer) != VK_SUCCESS)
abortf("vkEndCommandBuffer");
}
#endif

View File

@ -1,6 +1,7 @@
#version 450
layout(location = 0) in vec2 fsin_tex;
layout(location = 1) in vec3 fsin_pos;
layout(location = 0) out vec4 fin_color;
@ -8,29 +9,54 @@ layout(binding = 1) uniform sampler2D color_tex;
layout(binding = 2) uniform sampler2D normal_map;
struct Pipeline0Spotlight
{
vec3 pos;
vec3 dir;
vec3 colour;
layout(push_constant, std430) uniform pc {
layout(offset = 64) vec3 camera_pos;
};
struct Pipeline0Spotlight {
vec3 pos;
vec3 dir;
vec3 color;
float range;
};
struct Pipeline0PointLight
{
struct Pipeline0PointLight {
vec3 pos;
vec3 colour;
vec3 color;
};
layout(std140, binding = 0) uniform Pipeline0UBO
{
int spotlight_count;
int point_light_count;
layout(std140, binding = 0) uniform Pipeline0UBO {
int point_light_count;
int spotlight_count;
Pipeline0PointLight point_light_arr[20];
Pipeline0Spotlight spotlight_arr [120];
Pipeline0Spotlight spotlight_arr [120];
};
float get_intensity(float dist){
return 1 / pow(dist + 1, 2);
}
void main(){
fin_color = texture(normal_map, fsin_tex);
vec3 compressed_normal = texture(normal_map, fsin_tex).xyz;
vec3 norm = compressed_normal * 2 - 1;
vec3 diffuse_illumination = vec3(0);
vec3 specular_illumination = vec3(0);
for (int i = 0; i < point_light_count; i++) {
Pipeline0PointLight lamp = point_light_arr[i];
vec3 to_light = -fsin_pos + lamp.pos;
float dist = length(to_light);
vec3 U = to_light / dist;
diffuse_illumination += get_intensity(dist) * max(0.02, dot(U, norm)) * lamp.color;
vec3 A = reflect(-U, norm);
vec3 B = normalize(-fsin_pos+camera_pos);
specular_illumination += get_intensity(dist) * pow(max(0, dot(A, B)), 32) * lamp.color;
}
for (int i = 0; i < spotlight_count; i++) {
Pipeline0Spotlight lamp = spotlight_arr[i];
}
vec3 natural_color = texture(color_tex, fsin_tex).xyz;
// todo: add specular texture
// vec3 color = natural_color * (diffuse_illumination + specular_illumination);
vec3 color = natural_color * ( specular_illumination);
fin_color = vec4(color, 1);
}

View File

@ -2,18 +2,19 @@
layout(location = 0) in vec3 pos;
layout(location = 1) in vec2 tex;
layout(location = 2) in mat4 model_t;
/* 2 <- 3, 4, 5 */
layout(location = 0) out vec2 vsout_tex;
layout(location = 1) out vec3 vsout_pos;
layout(push_constant, std430) uniform pc {
/* Individual transformation for a model. Fits in push constant range
Includes global perspective matrix and camera matrix, but for each model there is a distinct
transformation matrix. Right now I only have one instance for each model,
otherwise I would use per-instance vertex attribute */
mat4 t;
mat4 proj_cam_t;
};
void main(){
vsout_tex = tex;
gl_Position = t * vec4(pos, 1);
vec4 real_pos = model_t * vec4(pos, 1);
vsout_pos = real_pos.xyz;
gl_Position = proj_cam_t * real_pos;
}

View File

@ -14,5 +14,6 @@ layout(push_constant, std430) uniform pc {
void main() {
vec2 tex_offset = 1.0 / textureSize(prev, 0);
fin_color = texture(prev, gl_FragCoord.xy * tex_offset);
vec4 hdr_color = texture(prev, gl_FragCoord.xy * tex_offset);
fin_color = vec4(vec3(1) - exp(-hdr_factor * hdr_color.xyz), 1);
}