summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c143
1 files changed, 109 insertions, 34 deletions
diff --git a/main.c b/main.c
index d606747..e3393a3 100644
--- a/main.c
+++ b/main.c
@@ -96,6 +96,7 @@ static VkBuffer vertex_buffer;
static VkDeviceMemory vertex_buffer_memory;
static VkBuffer index_buffer;
static VkDeviceMemory index_buffer_memory;
+static uint32_t mip_levels;
static VkImage texture_image;
static VkDeviceMemory texture_image_memory;
static VkImageView texture_view;
@@ -510,7 +511,7 @@ void create_swapchain() {
}
-VkImageView create_image_view(VkImage image, VkFormat format, VkImageAspectFlags aspect_flags) {
+VkImageView create_image_view(VkImage image, VkFormat format, VkImageAspectFlags aspect_flags, uint32_t mip_level) {
VkImageViewCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.image = image,
@@ -525,7 +526,7 @@ VkImageView create_image_view(VkImage image, VkFormat format, VkImageAspectFlags
.subresourceRange = {
.aspectMask = aspect_flags,
.baseMipLevel = 0,
- .levelCount = 1,
+ .levelCount = mip_level,
.baseArrayLayer = 0,
.layerCount = 1
}
@@ -547,7 +548,7 @@ void create_image_views() {
swapchain_image_views->len = swapchain_images->len;
for (size_t i = 0; i < swapchain_images->len; i++) {
- swapchain_image_views->data[i] = create_image_view(swapchain_images->data[i], swapchain_format, VK_IMAGE_ASPECT_COLOR_BIT);
+ swapchain_image_views->data[i] = create_image_view(swapchain_images->data[i], swapchain_format, VK_IMAGE_ASPECT_COLOR_BIT, 1);
}
}
@@ -1223,7 +1224,7 @@ void create_descriptor_sets() {
}
}
-void create_image(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,
+void create_image(uint32_t width, uint32_t height, uint32_t mip_level, VkFormat format, VkImageTiling tiling,
VkImageUsageFlags usage, VkMemoryPropertyFlags props, VkImage *img, VkDeviceMemory *memory) {
VkImageCreateInfo image_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
@@ -1233,7 +1234,7 @@ void create_image(uint32_t width, uint32_t height, VkFormat format, VkImageTilin
.height = height,
.depth = 1
},
- .mipLevels = 1,
+ .mipLevels = mip_level,
.arrayLayers = 1,
.format = format,
.tiling = tiling,
@@ -1267,7 +1268,7 @@ void create_image(uint32_t width, uint32_t height, VkFormat format, VkImageTilin
vkBindImageMemory(gpu, *img, *memory, 0);
}
-void transition_image_layout(VkImage image, VkFormat format, VkImageLayout old_layout, VkImageLayout new_layout) {
+void transition_image_layout(VkImage image, VkFormat format, VkImageLayout old_layout, VkImageLayout new_layout, uint32_t mip_level) {
VkCommandBuffer command_buffer = being_single_command();
VkImageMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
@@ -1279,7 +1280,7 @@ void transition_image_layout(VkImage image, VkFormat format, VkImageLayout old_l
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
- .levelCount = 1,
+ .levelCount = mip_level,
.baseArrayLayer = 0,
.layerCount = 1
},
@@ -1312,6 +1313,93 @@ void transition_image_layout(VkImage image, VkFormat format, VkImageLayout old_l
end_single_command(command_buffer);
}
+void generate_mipmaps(VkImage image, VkFormat image_format, int32_t width, int32_t height, uint32_t mip_levels) {
+ VkFormatProperties format_props;
+ vkGetPhysicalDeviceFormatProperties(phy_gpu, image_format, &format_props);
+ if (!(format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
+ fputs("texture image format does not support linear blitting", stderr);
+ exit(-1);
+ }
+ VkCommandBuffer command_buffer = being_single_command();
+
+ VkImageMemoryBarrier barrier = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ .image = image,
+ .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+ .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+ .subresourceRange = {
+ .layerCount = 1,
+ .levelCount = 1,
+ .baseArrayLayer = 0,
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT
+ },
+ };
+
+ int32_t mip_width = width, mip_height = height;
+
+ for (size_t i = 1; i < mip_levels; i++) {
+ barrier.subresourceRange.baseMipLevel = i - 1;
+ barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+ barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
+ barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+
+ vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &barrier);
+ VkImageBlit blit = {
+ .srcOffsets = {
+ { 0, 0, 0 },
+ { mip_width, mip_height, 1 }
+ },
+ .srcSubresource = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .mipLevel = i - 1,
+ .baseArrayLayer = 0,
+ .layerCount = 1
+ },
+ .dstOffsets = {
+ { 0, 0, 0 },
+ { mip_width > 1 ? mip_width / 2 : 1, mip_height > 1 ? mip_height / 2 : 1, 1 },
+ },
+ .dstSubresource = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .mipLevel = i,
+ .baseArrayLayer = 0,
+ .layerCount = 1
+ }
+ };
+
+ vkCmdBlitImage(command_buffer,
+ image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ 1, &blit, VK_FILTER_LINEAR);
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ barrier.newLayout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL;
+ barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+ barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+
+ vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &barrier);
+
+ if (mip_width > 1)
+ mip_width /= 2;
+ if (mip_height > 1)
+ mip_height /= 2;
+ }
+
+ barrier.subresourceRange.baseMipLevel = mip_levels - 1;
+ barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ barrier.newLayout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL;
+ barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+ barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+
+ vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &barrier);
+
+ end_single_command(command_buffer);
+}
+
void create_texture_image() {
int32_t width, height, channels;
@@ -1321,6 +1409,8 @@ void create_texture_image() {
exit(-1);
}
+ mip_levels = floor(log2(width > height ? width : height)) + 1;
+
VkDeviceSize image_size = width * height * 4;
VkBuffer tmp_buffer;
@@ -1336,23 +1426,26 @@ void create_texture_image() {
stbi_image_free(pixels);
- create_image(width, height, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL,
- VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &texture_image, &texture_image_memory);
+ create_image(width, height, mip_levels, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
+ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &texture_image, &texture_image_memory);
transition_image_layout(texture_image, VK_FORMAT_R8G8B8A8_SRGB,
- VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, mip_levels);
copy_buffer_to_image(tmp_buffer, texture_image, width, height);
- transition_image_layout(texture_image, VK_FORMAT_R8G8B8A8_SRGB,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+// transition_image_layout(texture_image, VK_FORMAT_R8G8B8A8_SRGB,
+// VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, mip_levels);
+
+ generate_mipmaps(texture_image, VK_FORMAT_R8G8B8A8_SRGB, width, height, mip_levels);
vkDestroyBuffer(gpu, tmp_buffer, NULL);
vkFreeMemory(gpu, tmp_mem, NULL);
}
void create_texture_view() {
- texture_view = create_image_view(texture_image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT);
+ texture_view = create_image_view(texture_image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT, mip_levels);
}
void create_texture_sampler() {
@@ -1374,7 +1467,7 @@ void create_texture_sampler() {
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
.mipLodBias = 0.0f,
.minLod = 0.0f,
- .maxLod = 0.0f
+ .maxLod = VK_LOD_CLAMP_NONE
};
VkResult res = vkCreateSampler(gpu, &sampler_info, NULL, &texture_sampler);
@@ -1386,10 +1479,10 @@ void create_texture_sampler() {
void create_depth_resources() {
VkFormat depth_format = VK_FORMAT_D32_SFLOAT;
- create_image(swapchain_extent.width, swapchain_extent.height, VK_FORMAT_D32_SFLOAT, VK_IMAGE_TILING_OPTIMAL,
+ create_image(swapchain_extent.width, swapchain_extent.height, 1, VK_FORMAT_D32_SFLOAT, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &depth_image, &depth_memory);
- depth_image_view = create_image_view(depth_image, VK_FORMAT_D32_SFLOAT, VK_IMAGE_ASPECT_DEPTH_BIT);
+ depth_image_view = create_image_view(depth_image, VK_FORMAT_D32_SFLOAT, VK_IMAGE_ASPECT_DEPTH_BIT, 1);
}
void recreate_swapchain() {
@@ -1411,24 +1504,6 @@ void recreate_swapchain() {
create_framebuffers();
}
-void get_data(void *ctx, const char *filename, const int is_mtl, const char *obj_filename, char **data, size_t *len) {
- (void) ctx;
- if (!filename) {
- fputs("null filename", stderr);
- *data = NULL;
- *len = 0;
- return;
- }
-
- FILE *fp = fopen(filename, "rb");
- fseek(fp, 0, SEEK_END);
- *len = ftell(fp);
- rewind(fp);
- *data = calloc(*len, 1);
- fread(*data, 1, *len + 1, fp);
- fclose(fp);
-}
-
void load_model() {
vertices = calloc(1, sizeof(*vertices) + sizeof(*vertices->data) * 65535);
vertices->cap = 65535;