|
| 1 | +diff --git a/src/main.cpp b/src/main.cpp |
| 2 | +index 6dabfb1..89a0f11 100644 |
| 3 | +--- a/src/main.cpp |
| 4 | ++++ b/src/main.cpp |
| 5 | +@@ -85,6 +85,7 @@ private: |
| 6 | + std::vector<vk::raii::Buffer> m_uniformBuffers; |
| 7 | + std::vector<void*> m_uniformBuffersMapped; |
| 8 | + vk::raii::DeviceMemory m_textureImageMemory{ nullptr }; |
| 9 | ++ uint32_t m_mipLevels; |
| 10 | + vk::raii::Image m_textureImage{ nullptr }; |
| 11 | + vk::raii::ImageView m_textureImageView{ nullptr }; |
| 12 | + vk::raii::Sampler m_textureSampler{ nullptr }; |
| 13 | +@@ -492,7 +493,12 @@ private: |
| 14 | + m_swapChainImageViews.reserve( m_swapChainImages.size() ); |
| 15 | + for (size_t i = 0; i < m_swapChainImages.size(); ++i) { |
| 16 | + m_swapChainImageViews.emplace_back( |
| 17 | +- createImageView(m_swapChainImages[i], m_swapChainImageFormat, vk::ImageAspectFlagBits::eColor) |
| 18 | ++ createImageView( |
| 19 | ++ m_swapChainImages[i], |
| 20 | ++ m_swapChainImageFormat, |
| 21 | ++ vk::ImageAspectFlagBits::eColor, |
| 22 | ++ 1 |
| 23 | ++ ) |
| 24 | + ); |
| 25 | + } |
| 26 | + } |
| 27 | +@@ -1185,6 +1191,7 @@ private: |
| 28 | + void createImage( |
| 29 | + uint32_t width, |
| 30 | + uint32_t height, |
| 31 | ++ uint32_t mipLevels, |
| 32 | + vk::Format format, |
| 33 | + vk::ImageTiling tilling, |
| 34 | + vk::ImageUsageFlags usage, |
| 35 | +@@ -1197,7 +1204,7 @@ private: |
| 36 | + imageInfo.extent.width = width; |
| 37 | + imageInfo.extent.height = height; |
| 38 | + imageInfo.extent.depth = 1; |
| 39 | +- imageInfo.mipLevels = 1; |
| 40 | ++ imageInfo.mipLevels = mipLevels; |
| 41 | + imageInfo.arrayLayers = 1; |
| 42 | + imageInfo.format = format; |
| 43 | + imageInfo.tiling = tilling; |
| 44 | +@@ -1221,7 +1228,8 @@ private: |
| 45 | + vk::raii::Image& image, |
| 46 | + vk::Format format, |
| 47 | + vk::ImageLayout oldLayout, |
| 48 | +- vk::ImageLayout newLayout |
| 49 | ++ vk::ImageLayout newLayout, |
| 50 | ++ uint32_t mipLevels |
| 51 | + ) { |
| 52 | + vk::raii::CommandBuffer commandBuffer = beginSingleTimeCommands(); |
| 53 | + |
| 54 | +@@ -1233,7 +1241,7 @@ private: |
| 55 | + barrier.image = image; |
| 56 | + // barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; |
| 57 | + barrier.subresourceRange.baseMipLevel = 0; |
| 58 | +- barrier.subresourceRange.levelCount = 1; |
| 59 | ++ barrier.subresourceRange.levelCount = mipLevels; |
| 60 | + barrier.subresourceRange.baseArrayLayer = 0; |
| 61 | + barrier.subresourceRange.layerCount = 1; |
| 62 | + |
| 63 | +@@ -1324,6 +1332,7 @@ private: |
| 64 | + throw std::runtime_error("failed to load texture image!"); |
| 65 | + } |
| 66 | + vk::DeviceSize imageSize = texWidth * texHeight * 4; |
| 67 | ++ m_mipLevels = static_cast<uint32_t>(std::floor(std::log2(std::max(texWidth, texHeight)))) + 1; |
| 68 | + |
| 69 | + vk::raii::DeviceMemory stagingBufferMemory{ nullptr }; |
| 70 | + vk::raii::Buffer stagingBuffer{ nullptr }; |
| 71 | +@@ -1346,8 +1355,10 @@ private: |
| 72 | + createImage( |
| 73 | + texWidth, |
| 74 | + texHeight, |
| 75 | ++ m_mipLevels, |
| 76 | + vk::Format::eR8G8B8A8Srgb, |
| 77 | + vk::ImageTiling::eOptimal, |
| 78 | ++ vk::ImageUsageFlagBits::eTransferSrc | |
| 79 | + vk::ImageUsageFlagBits::eTransferDst | |
| 80 | + vk::ImageUsageFlagBits::eSampled, |
| 81 | + vk::MemoryPropertyFlagBits::eDeviceLocal, |
| 82 | +@@ -1359,7 +1370,8 @@ private: |
| 83 | + m_textureImage, |
| 84 | + vk::Format::eR8G8B8A8Srgb, |
| 85 | + vk::ImageLayout::eUndefined, |
| 86 | +- vk::ImageLayout::eTransferDstOptimal |
| 87 | ++ vk::ImageLayout::eTransferDstOptimal, |
| 88 | ++ m_mipLevels |
| 89 | + ); |
| 90 | + |
| 91 | + copyBufferToImage( |
| 92 | +@@ -1369,33 +1381,52 @@ private: |
| 93 | + static_cast<uint32_t>(texHeight) |
| 94 | + ); |
| 95 | + |
| 96 | +- transitionImageLayout( |
| 97 | ++ generateMipmaps( |
| 98 | + m_textureImage, |
| 99 | + vk::Format::eR8G8B8A8Srgb, |
| 100 | +- vk::ImageLayout::eTransferDstOptimal, |
| 101 | +- vk::ImageLayout::eShaderReadOnlyOptimal |
| 102 | ++ texWidth, |
| 103 | ++ texHeight, |
| 104 | ++ m_mipLevels |
| 105 | + ); |
| 106 | ++ |
| 107 | ++ // transitionImageLayout( |
| 108 | ++ // m_textureImage, |
| 109 | ++ // vk::Format::eR8G8B8A8Srgb, |
| 110 | ++ // vk::ImageLayout::eTransferDstOptimal, |
| 111 | ++ // vk::ImageLayout::eShaderReadOnlyOptimal, |
| 112 | ++ // m_mipLevels |
| 113 | ++ // ); |
| 114 | + |
| 115 | + } |
| 116 | + ///////////////////////////////////////////////////////////////// |
| 117 | + |
| 118 | + ///////////////////////////////////////////////////////////////// |
| 119 | + /// image view and sampler |
| 120 | +- vk::raii::ImageView createImageView(vk::Image image, vk::Format format, vk::ImageAspectFlags aspectFlags) { |
| 121 | ++ vk::raii::ImageView createImageView( |
| 122 | ++ vk::Image image, |
| 123 | ++ vk::Format format, |
| 124 | ++ vk::ImageAspectFlags aspectFlags, |
| 125 | ++ uint32_t mipLevels |
| 126 | ++ ) { |
| 127 | + vk::ImageViewCreateInfo viewInfo; |
| 128 | + viewInfo.image = image; |
| 129 | + viewInfo.viewType = vk::ImageViewType::e2D; |
| 130 | + viewInfo.format = format; |
| 131 | + viewInfo.subresourceRange.aspectMask = aspectFlags; |
| 132 | + viewInfo.subresourceRange.baseMipLevel = 0; |
| 133 | +- viewInfo.subresourceRange.levelCount = 1; |
| 134 | ++ viewInfo.subresourceRange.levelCount = mipLevels; |
| 135 | + viewInfo.subresourceRange.baseArrayLayer = 0; |
| 136 | + viewInfo.subresourceRange.layerCount = 1; |
| 137 | + |
| 138 | + return m_device.createImageView(viewInfo); |
| 139 | + } |
| 140 | + void createTextureImageView() { |
| 141 | +- m_textureImageView = createImageView(m_textureImage, vk::Format::eR8G8B8A8Srgb, vk::ImageAspectFlagBits::eColor); |
| 142 | ++ m_textureImageView = createImageView( |
| 143 | ++ m_textureImage, |
| 144 | ++ vk::Format::eR8G8B8A8Srgb, |
| 145 | ++ vk::ImageAspectFlagBits::eColor, |
| 146 | ++ m_mipLevels |
| 147 | ++ ); |
| 148 | + } |
| 149 | + void createTextureSampler() { |
| 150 | + vk::SamplerCreateInfo samplerInfo; |
| 151 | +@@ -1420,7 +1451,9 @@ private: |
| 152 | + samplerInfo.mipmapMode = vk::SamplerMipmapMode::eLinear; |
| 153 | + samplerInfo.mipLodBias = 0.0f; |
| 154 | + samplerInfo.minLod = 0.0f; |
| 155 | +- samplerInfo.maxLod = 0.0f; |
| 156 | ++ samplerInfo.maxLod = static_cast<float>(m_mipLevels); |
| 157 | ++ |
| 158 | ++ // samplerInfo.minLod = static_cast<float>(m_mipLevels / 2); |
| 159 | + |
| 160 | + m_textureSampler = m_device.createSampler(samplerInfo); |
| 161 | + } |
| 162 | +@@ -1466,6 +1499,7 @@ private: |
| 163 | + createImage( |
| 164 | + m_swapChainExtent.width, |
| 165 | + m_swapChainExtent.height, |
| 166 | ++ 1, |
| 167 | + depthFormat, |
| 168 | + vk::ImageTiling::eOptimal, |
| 169 | + vk::ImageUsageFlagBits::eDepthStencilAttachment, |
| 170 | +@@ -1474,13 +1508,19 @@ private: |
| 171 | + m_depthImageMemory |
| 172 | + ); |
| 173 | + |
| 174 | +- m_depthImageView = createImageView(m_depthImage, depthFormat, vk::ImageAspectFlagBits::eDepth); |
| 175 | ++ m_depthImageView = createImageView( |
| 176 | ++ m_depthImage, |
| 177 | ++ depthFormat, |
| 178 | ++ vk::ImageAspectFlagBits::eDepth, |
| 179 | ++ 1 |
| 180 | ++ ); |
| 181 | + |
| 182 | + // transitionImageLayout( |
| 183 | + // m_depthImage, |
| 184 | + // depthFormat, |
| 185 | + // vk::ImageLayout::eUndefined, |
| 186 | +- // vk::ImageLayout::eDepthStencilAttachmentOptimal |
| 187 | ++ // vk::ImageLayout::eDepthStencilAttachmentOptimal, |
| 188 | ++ // 1 |
| 189 | + // ); |
| 190 | + } |
| 191 | + ///////////////////////////////////////////////////////////////// |
| 192 | +@@ -1538,6 +1578,114 @@ private: |
| 193 | + } |
| 194 | + } |
| 195 | + ///////////////////////////////////////////////////////////////// |
| 196 | ++ |
| 197 | ++ ///////////////////////////////////////////////////////////////// |
| 198 | ++ /// mipmaps |
| 199 | ++ void generateMipmaps( |
| 200 | ++ vk::raii::Image& image, |
| 201 | ++ vk::Format imageFormat, |
| 202 | ++ int32_t texWidth, |
| 203 | ++ int32_t texHeight, |
| 204 | ++ uint32_t mipLevels |
| 205 | ++ ) { |
| 206 | ++ // vk::FormatProperties |
| 207 | ++ auto formatProperties = m_physicalDevice.getFormatProperties(imageFormat); |
| 208 | ++ |
| 209 | ++ if(!(formatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eSampledImageFilterLinear)){ |
| 210 | ++ throw std::runtime_error("texture image format does not support linear blitting!"); |
| 211 | ++ } |
| 212 | ++ |
| 213 | ++ |
| 214 | ++ auto commandBuffer = beginSingleTimeCommands(); |
| 215 | ++ |
| 216 | ++ vk::ImageMemoryBarrier barrier; |
| 217 | ++ barrier.image = image; |
| 218 | ++ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 219 | ++ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 220 | ++ barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; |
| 221 | ++ barrier.subresourceRange.baseArrayLayer = 0; |
| 222 | ++ barrier.subresourceRange.layerCount = 1; |
| 223 | ++ barrier.subresourceRange.levelCount = 1; |
| 224 | ++ |
| 225 | ++ int32_t mipWidth = texWidth; |
| 226 | ++ int32_t mipHeight = texHeight; |
| 227 | ++ |
| 228 | ++ for (uint32_t i = 1; i < mipLevels; ++i) { |
| 229 | ++ barrier.subresourceRange.baseMipLevel = i - 1; |
| 230 | ++ barrier.oldLayout = vk::ImageLayout::eTransferDstOptimal; |
| 231 | ++ barrier.newLayout = vk::ImageLayout::eTransferSrcOptimal; |
| 232 | ++ barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite; |
| 233 | ++ barrier.dstAccessMask = vk::AccessFlagBits::eTransferRead; |
| 234 | ++ commandBuffer.pipelineBarrier( |
| 235 | ++ vk::PipelineStageFlagBits::eTransfer, |
| 236 | ++ vk::PipelineStageFlagBits::eTransfer, |
| 237 | ++ {}, |
| 238 | ++ nullptr, |
| 239 | ++ nullptr, |
| 240 | ++ barrier |
| 241 | ++ ); |
| 242 | ++ |
| 243 | ++ vk::ImageBlit blit; |
| 244 | ++ blit.srcOffsets[0] = vk::Offset3D{ 0, 0, 0 }; |
| 245 | ++ blit.srcOffsets[1] = vk::Offset3D{ mipWidth, mipHeight, 1 }; |
| 246 | ++ blit.srcSubresource.aspectMask = vk::ImageAspectFlagBits::eColor; |
| 247 | ++ blit.srcSubresource.mipLevel = i - 1; |
| 248 | ++ blit.srcSubresource.baseArrayLayer = 0; |
| 249 | ++ blit.srcSubresource.layerCount = 1; |
| 250 | ++ blit.dstOffsets[0] = vk::Offset3D{ 0, 0, 0 }; |
| 251 | ++ blit.dstOffsets[1] = vk::Offset3D{ |
| 252 | ++ mipWidth > 1 ? mipWidth / 2 : 1, |
| 253 | ++ mipHeight > 1 ? mipHeight / 2 : 1, |
| 254 | ++ 1 |
| 255 | ++ }; |
| 256 | ++ blit.dstSubresource.aspectMask = vk::ImageAspectFlagBits::eColor; |
| 257 | ++ blit.dstSubresource.mipLevel = i; |
| 258 | ++ blit.dstSubresource.baseArrayLayer = 0; |
| 259 | ++ blit.dstSubresource.layerCount = 1; |
| 260 | ++ commandBuffer.blitImage( |
| 261 | ++ image, vk::ImageLayout::eTransferSrcOptimal, |
| 262 | ++ image, vk::ImageLayout::eTransferDstOptimal, |
| 263 | ++ blit, |
| 264 | ++ vk::Filter::eLinear |
| 265 | ++ ); |
| 266 | ++ |
| 267 | ++ barrier.oldLayout = vk::ImageLayout::eTransferSrcOptimal; |
| 268 | ++ barrier.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal; |
| 269 | ++ barrier.srcAccessMask = vk::AccessFlagBits::eTransferRead; |
| 270 | ++ barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead; |
| 271 | ++ commandBuffer.pipelineBarrier( |
| 272 | ++ vk::PipelineStageFlagBits::eTransfer, |
| 273 | ++ vk::PipelineStageFlagBits::eFragmentShader, |
| 274 | ++ {}, |
| 275 | ++ nullptr, |
| 276 | ++ nullptr, |
| 277 | ++ barrier |
| 278 | ++ ); |
| 279 | ++ |
| 280 | ++ if (mipWidth > 1) mipWidth /= 2; |
| 281 | ++ if (mipHeight > 1) mipHeight /= 2; |
| 282 | ++ } |
| 283 | ++ |
| 284 | ++ barrier.subresourceRange.baseMipLevel = mipLevels - 1; |
| 285 | ++ barrier.oldLayout = vk::ImageLayout::eTransferDstOptimal; |
| 286 | ++ barrier.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal; |
| 287 | ++ barrier.srcAccessMask = vk::AccessFlagBits::eTransferRead; |
| 288 | ++ barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead; |
| 289 | ++ commandBuffer.pipelineBarrier( |
| 290 | ++ vk::PipelineStageFlagBits::eTransfer, |
| 291 | ++ vk::PipelineStageFlagBits::eFragmentShader, |
| 292 | ++ {}, |
| 293 | ++ nullptr, |
| 294 | ++ nullptr, |
| 295 | ++ barrier |
| 296 | ++ ); |
| 297 | ++ |
| 298 | ++ if (mipWidth > 1) mipWidth /= 2; |
| 299 | ++ if (mipHeight > 1) mipHeight /= 2; |
| 300 | ++ |
| 301 | ++ endSingleTimeCommands( std::move(commandBuffer) ); |
| 302 | ++ } |
| 303 | ++ ///////////////////////////////////////////////////////////////// |
| 304 | + }; |
| 305 | + |
| 306 | + |
0 commit comments