diff --git a/src/dawn/native/vulkan/AdapterVk.cpp b/src/dawn/native/vulkan/AdapterVk.cpp index ee5c15f863..1d7822c3dc 100644 --- a/src/dawn/native/vulkan/AdapterVk.cpp +++ b/src/dawn/native/vulkan/AdapterVk.cpp @@ -240,16 +240,23 @@ void Adapter::InitializeSupportedFeaturesImpl() { mSupportedFeatures.EnableFeature(Feature::DepthClipControl); } - VkFormatProperties properties; + VkFormatProperties rg11b10Properties; mVulkanInstance->GetFunctions().GetPhysicalDeviceFormatProperties( - mPhysicalDevice, VK_FORMAT_B10G11R11_UFLOAT_PACK32, &properties); + mPhysicalDevice, VK_FORMAT_B10G11R11_UFLOAT_PACK32, &rg11b10Properties); if (IsSubset(static_cast(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT), - properties.optimalTilingFeatures)) { + rg11b10Properties.optimalTilingFeatures)) { mSupportedFeatures.EnableFeature(Feature::RG11B10UfloatRenderable); } + VkFormatProperties bgra8unormProperties; + mVulkanInstance->GetFunctions().GetPhysicalDeviceFormatProperties( + mPhysicalDevice, VK_FORMAT_B8G8R8A8_UNORM, &bgra8unormProperties); + if (bgra8unormProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) { + mSupportedFeatures.EnableFeature(Feature::BGRA8UnormStorage); + } + #if defined(DAWN_USE_SYNC_FDS) // TODO(chromium:1258986): Precisely enable the feature by querying the device's format // features. diff --git a/src/dawn/native/vulkan/BindGroupVk.cpp b/src/dawn/native/vulkan/BindGroupVk.cpp index 0eafbdb0a7..e4547fc287 100644 --- a/src/dawn/native/vulkan/BindGroupVk.cpp +++ b/src/dawn/native/vulkan/BindGroupVk.cpp @@ -113,7 +113,12 @@ BindGroup::BindGroup(Device* device, case BindingInfoType::StorageTexture: { TextureView* view = ToBackend(GetBindingAsTextureView(bindingIndex)); - VkImageView handle = view->GetHandle(); + VkImageView handle = VK_NULL_HANDLE; + if (view->GetTexture()->GetFormat().format == wgpu::TextureFormat::BGRA8Unorm) { + handle = view->GetHandleForBGRA8UnormStorage(); + } else { + handle = view->GetHandle(); + } if (handle == VK_NULL_HANDLE) { // The Texture was destroyed before the TextureView was created. // Skip this descriptor write since it would be diff --git a/src/dawn/native/vulkan/TextureVk.cpp b/src/dawn/native/vulkan/TextureVk.cpp index 6bec0a979d..13e0b28f6f 100644 --- a/src/dawn/native/vulkan/TextureVk.cpp +++ b/src/dawn/native/vulkan/TextureVk.cpp @@ -684,7 +684,17 @@ MaybeError Texture::InitializeAsInternalTexture(VkImageUsageFlags extraUsages) { VkImageFormatListCreateInfo imageFormatListInfo = {}; std::vector viewFormats; - if (GetViewFormats().any()) { + bool requiresCreateMutableFormatBit = GetViewFormats().any(); + // As current SPIR-V SPEC doesn't support 'bgra8' as a valid image format, to support the + // STORAGE usage of BGRA8Unorm we have to create an RGBA8Unorm image view on the BGRA8Unorm + // storage texture and polyfill it as RGBA8Unorm in Tint. See http://crbug.com/dawn/1641 for + // more details. + if (createInfo.format == VK_FORMAT_B8G8R8A8_UNORM && + createInfo.usage & VK_IMAGE_USAGE_STORAGE_BIT) { + viewFormats.push_back(VK_FORMAT_R8G8B8A8_UNORM); + requiresCreateMutableFormatBit = true; + } + if (requiresCreateMutableFormatBit) { createInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; if (device->GetDeviceInfo().HasExt(DeviceExt::ImageFormatList)) { createInfoChain.Add(&imageFormatListInfo, @@ -1423,6 +1433,16 @@ MaybeError TextureView::Initialize(const TextureViewDescriptor* descriptor) { device->fn.CreateImageView(device->GetVkDevice(), &createInfo, nullptr, &*mHandle), "CreateImageView")); + // We should create an image view with format RGBA8Unorm on the BGRA8Unorm texture when the + // texture is used as storage texture. See http://crbug.com/dawn/1641 for more details. + if (createInfo.format == VK_FORMAT_B8G8R8A8_UNORM && + (GetTexture()->GetInternalUsage() & wgpu::TextureUsage::StorageBinding)) { + createInfo.format = VK_FORMAT_R8G8B8A8_UNORM; + DAWN_TRY(CheckVkSuccess(device->fn.CreateImageView(device->GetVkDevice(), &createInfo, + nullptr, &*mHandleForBGRA8UnormStorage), + "CreateImageView for BGRA8Unorm storage")); + } + SetLabelImpl(); return {}; @@ -1437,12 +1457,21 @@ void TextureView::DestroyImpl() { device->GetFencedDeleter()->DeleteWhenUnused(mHandle); mHandle = VK_NULL_HANDLE; } + + if (mHandleForBGRA8UnormStorage != VK_NULL_HANDLE) { + device->GetFencedDeleter()->DeleteWhenUnused(mHandleForBGRA8UnormStorage); + mHandleForBGRA8UnormStorage = VK_NULL_HANDLE; + } } VkImageView TextureView::GetHandle() const { return mHandle; } +VkImageView TextureView::GetHandleForBGRA8UnormStorage() const { + return mHandleForBGRA8UnormStorage; +} + void TextureView::SetLabelImpl() { SetDebugName(ToBackend(GetDevice()), mHandle, "Dawn_TextureView", GetLabel()); } diff --git a/src/dawn/native/vulkan/TextureVk.h b/src/dawn/native/vulkan/TextureVk.h index b0a2c00fa3..48017bf953 100644 --- a/src/dawn/native/vulkan/TextureVk.h +++ b/src/dawn/native/vulkan/TextureVk.h @@ -193,6 +193,7 @@ class TextureView final : public TextureViewBase { static ResultOrError> Create(TextureBase* texture, const TextureViewDescriptor* descriptor); VkImageView GetHandle() const; + VkImageView GetHandleForBGRA8UnormStorage() const; private: ~TextureView() override; @@ -204,6 +205,7 @@ class TextureView final : public TextureViewBase { void SetLabelImpl() override; VkImageView mHandle = VK_NULL_HANDLE; + VkImageView mHandleForBGRA8UnormStorage = VK_NULL_HANDLE; }; } // namespace dawn::native::vulkan