2016-06-12 53 views
3

我試圖使用vkCmdBlitImage生成mipmaps運行時(實現glGenerateMipmap()功能),但不理解該過程。這是我的代碼到目前爲止:在Vulkan中生成mipmap

VkImageCreateInfo imageCreateInfo = {}; 
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 
imageCreateInfo.pNext = nullptr; 
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; 
imageCreateInfo.format = format; 
imageCreateInfo.mipLevels = mipLevels; 
imageCreateInfo.arrayLayers = 1; 
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; 
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; 
imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; 
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; 
imageCreateInfo.extent = { static_cast<std::uint32_t>(width), static_cast<std::uint32_t>(height), 1 }; 
imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; 

err = vkCreateImage(GfxDeviceGlobal::device, &imageCreateInfo, nullptr, &image); 

... 

    for (int i = 1; i < mipLevels; ++i) 
    { 
     const std::int32_t mipWidth = width >> i; 
     const std::int32_t mipHeight = height >> i; 

     VkImageBlit imageBlit = {}; 
     imageBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 
     imageBlit.srcSubresource.baseArrayLayer = 0; 
     imageBlit.srcSubresource.layerCount = 1; 
     imageBlit.srcSubresource.mipLevel = 0; 
     imageBlit.srcOffsets[ 0 ] = { 0, 0, 0 }; 
     imageBlit.srcOffsets[ 1 ] = { width, height, 1 }; 

     imageBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 
     imageBlit.dstSubresource.baseArrayLayer = 0; 
     imageBlit.dstSubresource.layerCount = 1; 
     imageBlit.dstSubresource.mipLevel = i; 
     imageBlit.dstOffsets[ 0 ] = { 0, 0, 0 }; 
     imageBlit.dstOffsets[ 1 ] = { mipWidth, mipHeight, 1 }; 

     vkCmdBlitImage(texCmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 
         image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 
         1, &imageBlit, VK_FILTER_LINEAR); 
    } 

是否每個mip級別都需要它自己的圖像?他們應該如何初始化?什麼時候在使用紋理數據的暫存緩衝區時應該生成mipmap?

編輯:我修改了代碼,只使用一個圖像的建議,它似乎現在工作(我可以在RenderDoc紋理查看器中看到正確的mip級別的圖像,我沒有得到任何驗證錯誤)。

+1

src和dst圖像可以相同。爲此甚至應該。 ;每個圖像至少有1個mip級別([0]是基礎「紋理」)。把'i'弄糊塗到'i'是很奇怪的。 – krOoze

回答

3

每個mip級別都需要自己的圖像嗎?

不,您不需要爲每個mip級別提供單獨的圖像。如果您爲紋理創建圖像,則只需設置VkImageCreateInfo的mipLevels。

它們應該如何初始化?什麼時候在使用紋理數據的暫存緩衝區時應該生成mipmap?

這很大程度上取決於您想要餵食您的mips。你只是想從紋理文件(靜態mip級別)加載它們,還是需要在運行時生成它們?

如果您只想從文件加載它們,請不要blit。創建一個臨時緩衝區(不是圖像),將紋理數據加載到該緩衝區中,並從該緩衝區對圖像執行vkCmdCopyBufferToImage。

但你能否請添加一些更多的細節。我沒有看到任何圖像佈局轉換,這些轉換可能至關重要,具體取決於您正在執行的操作,圖像創建信息(例如標誌)沒有任何信息,並且您沒有說明代碼是否實際工作。

有一件事可能是錯誤的(很難說沒有更多的代碼)是你blit源代碼中的mipLevel。你真的有一個完整的MIP鏈和mip複製mip的來源嗎?

+0

謝謝,我在問題中添加了一些細節。我沒有寫過渡,因爲我不確定我的整個過程。 – SurvivalMachine

+1

@SurvivalMachine通過我的真棒搜索技巧,找到你正在嘗試做什麼的例子。要搭載這個答案:https://skia.googlesource.com/skia.git/+/master/src/gpu/vk/GrVkGpu.cpp#779 – krOoze