diff --git a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp index 81c0d203d..19081bd8d 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp @@ -1951,6 +1951,53 @@ bool WrappedVulkan::Serialise_vkCreateImage(SerialiserType &ser, VkDevice device } } + rdcarray patchedFormatList; + + // similarly for the image format list for MSAA textures, add the UINT cast format we will need + if(CreateInfo.samples != VK_SAMPLE_COUNT_1_BIT) + { + VkImageFormatListCreateInfo *formatListInfo = (VkImageFormatListCreateInfo *)FindNextStruct( + &CreateInfo, VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO); + + if(formatListInfo) + { + uint32_t bs = GetByteSize(1, 1, 1, CreateInfo.format, 0); + + VkFormat msaaCopyFormat = VK_FORMAT_UNDEFINED; + if(bs == 1) + msaaCopyFormat = VK_FORMAT_R8_UINT; + else if(bs == 2) + msaaCopyFormat = VK_FORMAT_R16_UINT; + else if(bs == 4) + msaaCopyFormat = VK_FORMAT_R32_UINT; + else if(bs == 8) + msaaCopyFormat = VK_FORMAT_R32G32_UINT; + else if(bs == 16) + msaaCopyFormat = VK_FORMAT_R32G32B32A32_UINT; + + patchedFormatList.resize(formatListInfo->viewFormatCount + 1); + + const VkFormat *oldFmts = formatListInfo->pViewFormats; + VkFormat *newFmts = patchedFormatList.data(); + formatListInfo->pViewFormats = newFmts; + + bool needAdded = true; + uint32_t i = 0; + for(; i < formatListInfo->viewFormatCount; i++) + { + newFmts[i] = oldFmts[i]; + if(newFmts[i] == msaaCopyFormat) + needAdded = false; + } + + if(needAdded) + { + newFmts[i] = msaaCopyFormat; + formatListInfo->viewFormatCount++; + } + } + } + VkImageCreateInfo patched = CreateInfo; byte *tempMem = GetTempMemory(GetNextPatchSize(patched.pNext)); @@ -2066,7 +2113,19 @@ VkResult WrappedVulkan::vkCreateImage(VkDevice device, const VkImageCreateInfo * // create non-subsampled image to be able to copy its content createInfo_adjusted.flags &= ~VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT; - byte *tempMem = GetTempMemory(GetNextPatchSize(createInfo_adjusted.pNext)); + size_t tempMemSize = GetNextPatchSize(createInfo_adjusted.pNext); + + // reserve space for a patched view format list if necessary + if(createInfo_adjusted.samples != VK_SAMPLE_COUNT_1_BIT) + { + VkImageFormatListCreateInfo *formatListInfo = (VkImageFormatListCreateInfo *)FindNextStruct( + &createInfo_adjusted, VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO); + + if(formatListInfo) + tempMemSize += sizeof(VkFormat) * (formatListInfo->viewFormatCount + 1); + } + + byte *tempMem = GetTempMemory(tempMemSize); UnwrapNextChain(m_State, "VkImageCreateInfo", tempMem, (VkBaseInStructure *)&createInfo_adjusted); @@ -2091,6 +2150,49 @@ VkResult WrappedVulkan::vkCreateImage(VkDevice device, const VkImageCreateInfo * } } + // similarly for the image format list for MSAA textures, add the UINT cast format we will need + if(createInfo_adjusted.samples != VK_SAMPLE_COUNT_1_BIT) + { + VkImageFormatListCreateInfo *formatListInfo = (VkImageFormatListCreateInfo *)FindNextStruct( + &createInfo_adjusted, VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO); + + if(formatListInfo) + { + uint32_t bs = GetByteSize(1, 1, 1, createInfo_adjusted.format, 0); + + VkFormat msaaCopyFormat = VK_FORMAT_UNDEFINED; + if(bs == 1) + msaaCopyFormat = VK_FORMAT_R8_UINT; + else if(bs == 2) + msaaCopyFormat = VK_FORMAT_R16_UINT; + else if(bs == 4) + msaaCopyFormat = VK_FORMAT_R32_UINT; + else if(bs == 8) + msaaCopyFormat = VK_FORMAT_R32G32_UINT; + else if(bs == 16) + msaaCopyFormat = VK_FORMAT_R32G32B32A32_UINT; + + const VkFormat *oldFmts = formatListInfo->pViewFormats; + VkFormat *newFmts = (VkFormat *)tempMem; + formatListInfo->pViewFormats = newFmts; + + bool needAdded = true; + uint32_t i = 0; + for(; i < formatListInfo->viewFormatCount; i++) + { + newFmts[i] = oldFmts[i]; + if(newFmts[i] == msaaCopyFormat) + needAdded = false; + } + + if(needAdded) + { + newFmts[i] = msaaCopyFormat; + formatListInfo->viewFormatCount++; + } + } + } + VkResult ret; SERIALISE_TIME_CALL( ret = ObjDisp(device)->CreateImage(Unwrap(device), &createInfo_adjusted, pAllocator, pImage)); diff --git a/util/test/demos/vk/vk_helpers.h b/util/test/demos/vk/vk_helpers.h index bf34b4af8..a9717fcc3 100644 --- a/util/test/demos/vk/vk_helpers.h +++ b/util/test/demos/vk/vk_helpers.h @@ -516,6 +516,12 @@ struct ImageCreateInfo : public VkImageCreateInfo imageType = VK_IMAGE_TYPE_1D; } + VkImageCreateInfo &next(const void *next) + { + this->pNext = next; + return *this; + } + operator const VkImageCreateInfo *() const { return this; } }; diff --git a/util/test/demos/vk/vk_texture_zoo.cpp b/util/test/demos/vk/vk_texture_zoo.cpp index cd77f6ec4..5433c0ff7 100644 --- a/util/test/demos/vk/vk_texture_zoo.cpp +++ b/util/test/demos/vk/vk_texture_zoo.cpp @@ -464,11 +464,17 @@ void main() viewAspect = VK_IMAGE_ASPECT_DEPTH_BIT; } + VkImageFormatListCreateInfoKHR formatList = {VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR}; + formatList.viewFormatCount = 2; + VkFormat fmts[] = {test.fmt.texFmt, test.fmt.viewFmt}; + formatList.pViewFormats = fmts; + test.res = AllocatedImage( this, vkh::ImageCreateInfo( w, h, d, test.fmt.texFmt, usage, test.isMSAA ? 1 : texMips, test.isArray ? texSlices : 1, - test.isMSAA ? VkSampleCountFlagBits(texSamples) : VK_SAMPLE_COUNT_1_BIT, flags), + test.isMSAA ? VkSampleCountFlagBits(texSamples) : VK_SAMPLE_COUNT_1_BIT, flags) + .next(hasExt(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME) ? &formatList : NULL), VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY})); test.view = createImageView(vkh::ImageViewCreateInfo( test.res.image, test.viewType, test.fmt.viewFmt, {}, vkh::ImageSubresourceRange(viewAspect))); @@ -619,6 +625,7 @@ void main() void Prepare(int argc, char **argv) { devExts.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); + optDevExts.push_back(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME); features.sampleRateShading = true;