@@ -195,6 +195,25 @@ MaybeError SwapChain::Initialize(SwapChainBase* previousSwapChain) {
195195 createInfo.clipped = VK_FALSE ;
196196 createInfo.oldSwapchain = previousVkSwapChain;
197197
198+ // Create the swapchain images with VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT so they can be
199+ // reinterpreted to the configuration's viewFormats. VK_KHR_swapchain_mutable_format requires
200+ // the full list of formats to be provided, including the image format itself.
201+ VkImageFormatListCreateInfo imageFormatListInfo;
202+ std::vector<VkFormat> viewFormats;
203+ if (!mConfig .wgpuViewFormats .empty ()) {
204+ DAWN_ASSERT (device->GetDeviceInfo ().HasExt (DeviceExt::SwapchainMutableFormat));
205+ createInfo.flags |= VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR ;
206+ viewFormats.push_back (mConfig .format );
207+ for (wgpu::TextureFormat viewFormat : mConfig .wgpuViewFormats ) {
208+ viewFormats.push_back (VulkanImageFormat (device, viewFormat));
209+ }
210+ imageFormatListInfo.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO ;
211+ imageFormatListInfo.pNext = nullptr ;
212+ imageFormatListInfo.viewFormatCount = static_cast <uint32_t >(viewFormats.size ());
213+ imageFormatListInfo.pViewFormats = viewFormats.data ();
214+ createInfo.pNext = &imageFormatListInfo;
215+ }
216+
198217 DAWN_TRY (CheckVkSuccess (
199218 device->fn .CreateSwapchainKHR (device->GetVkDevice (), &createInfo, nullptr , &*mSwapChain ),
200219 " CreateSwapChain" ));
@@ -272,14 +291,20 @@ ResultOrError<SwapChain::Config> SwapChain::ChooseConfig(
272291 VkImageUsageFlags targetUsages =
273292 VulkanImageUsage (GetDevice (), GetUsage (), GetDevice ()->GetValidInternalFormat (GetFormat ()));
274293 VkImageUsageFlags supportedUsages = surfaceInfo.capabilities .supportedUsageFlags ;
275- // The swapchain images are also unable to satisfy viewFormats: they are
276- // created without VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, so they cannot be
277- // reinterpreted. The blit texture is a regular texture and can.
278- if (!IsSubset (targetUsages, supportedUsages) || !GetViewFormats ().empty ()) {
279- config.needsBlit = true ;
280- } else {
294+ // The swapchain images support the configuration's viewFormats only if they are created
295+ // with VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, which requires VK_KHR_swapchain_mutable_format.
296+ // Otherwise the blit texture, a regular texture, is used to support them.
297+ const bool viewFormatsSupported =
298+ GetViewFormats ().empty () ||
299+ ToBackend (GetDevice ())->GetDeviceInfo ().HasExt (DeviceExt::SwapchainMutableFormat);
300+ if (IsSubset (targetUsages, supportedUsages) && viewFormatsSupported) {
281301 config.usage = targetUsages;
282302 config.wgpuUsage = GetUsage ();
303+ // The swapchain will be created with VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR so the
304+ // images can be reinterpreted to these formats.
305+ config.wgpuViewFormats = GetViewFormats ();
306+ } else {
307+ config.needsBlit = true ;
283308 }
284309
285310 // Only support BGRA8Unorm (and RGBA8Unorm on android) with SRGB color space for now.
@@ -548,12 +573,13 @@ ResultOrError<SwapChainTextureInfo> SwapChain::GetCurrentTextureInternal(bool is
548573 }
549574 lastImage.lastAcquireDoneFence = std::move (acquireFence);
550575
551- // Wait on the previous fence and destroy it .
576+ // Wrap the swapchain texture .
552577 TextureDescriptor textureDesc;
553578 textureDesc.size .width = mConfig .extent .width ;
554579 textureDesc.size .height = mConfig .extent .height ;
555580 textureDesc.format = mConfig .wgpuFormat ;
556581 textureDesc.usage = mConfig .wgpuUsage ;
582+ textureDesc.viewFormats = mConfig .wgpuViewFormats ;
557583
558584 mTexture = SwapChainTexture::Create (device, Unpack (&textureDesc), lastImage.image );
559585
@@ -563,8 +589,9 @@ ResultOrError<SwapChainTextureInfo> SwapChain::GetCurrentTextureInternal(bool is
563589 return swapChainTextureInfo;
564590 }
565591
566- // The blit texture always perfectly matches what the user requested for the swapchain.
567- // We need to add the Vulkan TRANSFER_SRC flag for the vkCmdBlitImage call.
592+ // The blit texture always perfectly matches what the user requested for the swapchain,
593+ // including the viewFormats which GetSwapChainBaseTextureDescriptor() carries over. We need
594+ // to add the Vulkan TRANSFER_SRC flag for the vkCmdBlitImage call.
568595 TextureDescriptor desc = GetSwapChainBaseTextureDescriptor (this );
569596 DAWN_TRY_ASSIGN (mBlitTexture , InternalTexture::Create (device, Unpack (&desc),
570597 VK_IMAGE_USAGE_TRANSFER_SRC_BIT ));
0 commit comments