diff options
| author | Anna (navi) Figueiredo Gomes <navi@vlhl.dev> | 2024-01-05 00:37:18 +0100 | 
|---|---|---|
| committer | Anna (navi) Figueiredo Gomes <navi@vlhl.dev> | 2024-01-05 00:40:06 +0100 | 
| commit | 45cbbfde7c7da36c1969f62190413323894c3be5 (patch) | |
| tree | 068b787ec73b45eeaeaabb8c5622633363318648 | |
| parent | 81be424535d5c3671f42d8347b1a50e9205af3e2 (diff) | |
| download | vlkn-45cbbfde7c7da36c1969f62190413323894c3be5.tar.xz | |
mips levels
Signed-off-by: Anna (navi) Figueiredo Gomes <navi@vlhl.dev>
| -rw-r--r-- | main.c | 143 | 
1 files changed, 109 insertions, 34 deletions
| @@ -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; | 
