Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c941fc4

Browse files
committed
Add explanation to mipmapping chapter about checking for linear blit support and alternatives
1 parent ec0cef1 commit c941fc4

2 files changed

Lines changed: 53 additions & 2 deletions

File tree

09_Generating_Mipmaps.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,49 @@ generateMipmaps(textureImage, texWidth, texHeight, mipLevels);
234234

235235
Our texture image's mipmaps are now completely filled.
236236

237+
## Linear filtering support
238+
239+
It is very convenient to use a built-in function like `vkCmdBlitImage` to generate all the mip levels, but unfortunately it is not guaranteed to be supported on all platforms. It requires the texture image format we use to support linear filtering, which can be checked with the `vkGetPhysicalDeviceFormatProperties` function. We will add a check to the `generateMipmaps` function for this.
240+
241+
First add an additional parameter that specifies the image format:
242+
243+
```c++
244+
void createTextureImage() {
245+
...
246+
247+
generateMipmaps(textureImage, VK_FORMAT_R8G8B8A8_UNORM, texWidth, texHeight, mipLevels);
248+
}
249+
250+
void generateMipmaps(VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, uint32_t mipLevels) {
251+
252+
...
253+
}
254+
```
255+
256+
In the `generateMipmaps` function, use `vkGetPhysicalDeviceFormatProperties` to request the properties of the texture image format:
257+
258+
```c++
259+
void generateMipmaps(VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, uint32_t mipLevels) {
260+
261+
// Check if image format supports linear blitting
262+
VkFormatProperties formatProperties;
263+
vkGetPhysicalDeviceFormatProperties(physicalDevice, imageFormat, &formatProperties);
264+
265+
...
266+
```
267+
268+
The `VkFormatProperties` struct has three fields named `linearTilingFeatures`, `optimalTilingFeatures` and `bufferFeatures` that each describe how the format can be used depending on the way it is used. We create a texture image with the optimal tiling format, so we need to check `optimalTilingFeatures`. Support for the linear filtering feature can be checked with the `VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT`:
269+
270+
```c++
271+
if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
272+
throw std::runtime_error("texture image format does not support linear blitting!");
273+
}
274+
```
275+
276+
There are two alternatives in this case. You could implement a function that searches common texture image formats for one that *does* support linear blitting, or you could implement the mipmap generation in software with a library like [stb_image_resize](https://github.com/nothings/stb/blob/master/stb_image_resize.h). Each mip level can then be loaded into the image in the same way that you loaded the original image.
277+
278+
It should be noted that it is uncommon in practice to generate the mipmap levels at runtime anyway. Usually they are pregenerated and stored in the texture file alongside the base level to improve loading speed. Implementing resizing in software and loading multiple levels from a file is left as an exercise to the reader.
279+
237280
## Sampler
238281

239282
While the `VkImage` holds the mipmap data, `VkSampler` controls how that data is read while rendering. Vulkan allows us to specify `minLod`, `maxLod`, `mipLodBias`, and `mipmapMode` ("Lod" means "Level of Detail"). When a texture is sampled, the sampler selects a mip level according to the following pseudocode:

code/28_mipmapping.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -820,10 +820,18 @@ class HelloTriangleApplication {
820820
vkDestroyBuffer(device, stagingBuffer, nullptr);
821821
vkFreeMemory(device, stagingBufferMemory, nullptr);
822822

823-
generateMipmaps(textureImage, texWidth, texHeight, mipLevels);
823+
generateMipmaps(textureImage, VK_FORMAT_R8G8B8A8_UNORM, texWidth, texHeight, mipLevels);
824824
}
825825

826-
void generateMipmaps(VkImage image, int32_t texWidth, int32_t texHeight, uint32_t mipLevels) {
826+
void generateMipmaps(VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, uint32_t mipLevels) {
827+
// Check if image format supports linear blitting
828+
VkFormatProperties formatProperties;
829+
vkGetPhysicalDeviceFormatProperties(physicalDevice, imageFormat, &formatProperties);
830+
831+
if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
832+
throw std::runtime_error("texture image format does not support linear blitting!");
833+
}
834+
827835
VkCommandBuffer commandBuffer = beginSingleTimeCommands();
828836

829837
VkImageMemoryBarrier barrier = {};

0 commit comments

Comments
 (0)