Improving Vulkan backend validation messages.

Improves validation messages in various Vulkan backend files:

 - vulkan/DeviceVk.cpp
 - vulkan/ShaderModuleVk.cpp
 - vulkan/SwapChainVk.cpp
 - vulkan/TextureVk.cpp
 - vulkan/external_memory/MemoryServiceDmaBuf.cpp
 - vulkan/external_memory/MemoryServiceOpaqueFD.cpp
 - vulkan/external_memory/MemoryServiceZirconHandle.cpp
 - vulkan/external_semaphore/SemaphoreServiceFD.cpp
 - vulkan/external_semaphore/SemaphoreServiceZirconHandle.cpp

Bug: dawn:563
Change-Id: I521fecc29e7919413aa6210eff050848689296a1
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/67122
Commit-Queue: Brandon Jones <bajones@chromium.org>
Auto-Submit: Brandon Jones <bajones@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/src/dawn_native/Surface.cpp b/src/dawn_native/Surface.cpp
index 56027a9..505fc60 100644
--- a/src/dawn_native/Surface.cpp
+++ b/src/dawn_native/Surface.cpp
@@ -30,6 +30,30 @@
 
 namespace dawn_native {
 
+    absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
+        Surface::Type value,
+        const absl::FormatConversionSpec& spec,
+        absl::FormatSink* s) {
+        switch (value) {
+            case Surface::Type::MetalLayer:
+                s->Append("MetalLayer");
+                break;
+            case Surface::Type::WindowsHWND:
+                s->Append("WindowsHWND");
+                break;
+            case Surface::Type::WindowsCoreWindow:
+                s->Append("WindowsCoreWindow");
+                break;
+            case Surface::Type::WindowsSwapChainPanel:
+                s->Append("WindowsSwapChainPanel");
+                break;
+            case Surface::Type::Xlib:
+                s->Append("Xlib");
+                break;
+        }
+        return {true};
+    }
+
 #if defined(DAWN_ENABLE_BACKEND_METAL)
     bool InheritsFromCAMetalLayer(void* obj);
 #endif  // defined(DAWN_ENABLE_BACKEND_METAL)
diff --git a/src/dawn_native/Surface.h b/src/dawn_native/Surface.h
index a137736..d3b3b69 100644
--- a/src/dawn_native/Surface.h
+++ b/src/dawn_native/Surface.h
@@ -100,6 +100,11 @@
         uint32_t mXWindow = 0;
     };
 
+    absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
+        Surface::Type value,
+        const absl::FormatConversionSpec& spec,
+        absl::FormatSink* s);
+
     // For the benefit of template generation.
     using SurfaceBase = Surface;
 
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index 1360d3c..48a8b19 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -745,16 +745,16 @@
         }
 
         // Check services support this combination of handle type / image info
-        if (!mExternalSemaphoreService->Supported()) {
-            return DAWN_VALIDATION_ERROR("External semaphore usage not supported");
-        }
-        if (!mExternalMemoryService->SupportsImportMemory(
+        DAWN_INVALID_IF(!mExternalSemaphoreService->Supported(),
+                        "External semaphore usage not supported");
+
+        DAWN_INVALID_IF(
+            !mExternalMemoryService->SupportsImportMemory(
                 VulkanImageFormat(this, textureDescriptor->format), VK_IMAGE_TYPE_2D,
                 VK_IMAGE_TILING_OPTIMAL,
                 VulkanImageUsage(usage, GetValidInternalFormat(textureDescriptor->format)),
-                VK_IMAGE_CREATE_ALIAS_BIT_KHR)) {
-            return DAWN_VALIDATION_ERROR("External memory usage not supported");
-        }
+                VK_IMAGE_CREATE_ALIAS_BIT_KHR),
+            "External memory usage not supported");
 
         // Create an external semaphore to signal when the texture is done being used
         DAWN_TRY_ASSIGN(*outSignalSemaphore,
@@ -815,7 +815,9 @@
         if (ConsumedError(ValidateTextureDescriptor(this, textureDescriptor))) {
             return nullptr;
         }
-        if (ConsumedError(ValidateVulkanImageCanBeWrapped(this, textureDescriptor))) {
+        if (ConsumedError(ValidateVulkanImageCanBeWrapped(this, textureDescriptor),
+                          "validating that a Vulkan image can be wrapped with %s.",
+                          textureDescriptor)) {
             return nullptr;
         }
 
diff --git a/src/dawn_native/vulkan/ShaderModuleVk.cpp b/src/dawn_native/vulkan/ShaderModuleVk.cpp
index 9cad708..b8b7475 100644
--- a/src/dawn_native/vulkan/ShaderModuleVk.cpp
+++ b/src/dawn_native/vulkan/ShaderModuleVk.cpp
@@ -112,8 +112,6 @@
         }
 
         // Creation of VkShaderModule is deferred to this point when using tint generator
-        std::ostringstream errorStream;
-        errorStream << "Tint SPIR-V writer failure:" << std::endl;
 
         // Remap BindingNumber to BindingIndex in WGSL shader
         using BindingRemapper = tint::transform::BindingRemapper;
@@ -159,10 +157,8 @@
         options.emit_vertex_point_size = true;
         options.disable_workgroup_init = GetDevice()->IsToggleEnabled(Toggle::DisableWorkgroupInit);
         auto result = tint::writer::spirv::Generate(&program, options);
-        if (!result.success) {
-            errorStream << "Generator: " << result.error << std::endl;
-            return DAWN_VALIDATION_ERROR(errorStream.str().c_str());
-        }
+        DAWN_INVALID_IF(!result.success, "An error occured while generating SPIR-V: %s.",
+                        result.error);
 
         std::vector<uint32_t> spirv = std::move(result.spirv);
         DAWN_TRY(
diff --git a/src/dawn_native/vulkan/SwapChainVk.cpp b/src/dawn_native/vulkan/SwapChainVk.cpp
index c0f856f..95ba482 100644
--- a/src/dawn_native/vulkan/SwapChainVk.cpp
+++ b/src/dawn_native/vulkan/SwapChainVk.cpp
@@ -182,7 +182,8 @@
                     break;
             }
 
-            return DAWN_VALIDATION_ERROR("Unsupported surface type for Vulkan");
+            return DAWN_FORMAT_VALIDATION_ERROR("Unsupported surface type (%s) for Vulkan.",
+                                                surface->GetType());
         }
 
         VkPresentModeKHR ToVulkanPresentMode(wgpu::PresentMode mode) {
@@ -241,9 +242,10 @@
             // TODO(crbug.com/dawn/269): figure out what should happen when surfaces are used by
             // multiple backends one after the other. It probably needs to block until the backend
             // and GPU are completely finished with the previous swapchain.
-            if (previousSwapChain->GetBackendType() != wgpu::BackendType::Vulkan) {
-                return DAWN_VALIDATION_ERROR("vulkan::SwapChain cannot switch between APIs");
-            }
+            DAWN_INVALID_IF(previousSwapChain->GetBackendType() != wgpu::BackendType::Vulkan,
+                            "Vulkan SwapChain cannot switch backend types from %s to %s.",
+                            previousSwapChain->GetBackendType(), wgpu::BackendType::Vulkan);
+
             // TODO(crbug.com/dawn/269): use ToBackend once OldSwapChainBase is removed.
             SwapChain* previousVulkanSwapChain = static_cast<SwapChain*>(previousSwapChain);
 
@@ -251,9 +253,8 @@
             // Vulkan devices on different VkInstances. Probably needs to block too!
             VkInstance previousInstance =
                 ToBackend(previousSwapChain->GetDevice())->GetVkInstance();
-            if (previousInstance != ToBackend(GetDevice())->GetVkInstance()) {
-                return DAWN_VALIDATION_ERROR("vulkan::SwapChain cannot switch between instances");
-            }
+            DAWN_INVALID_IF(previousInstance != ToBackend(GetDevice())->GetVkInstance(),
+                            "Vulkan SwapChain cannot switch between Vulkan instances.");
 
             // The previous swapchain is a dawn_native::vulkan::SwapChain so we can reuse its
             // VkSurfaceKHR provided since they are on the same instance.
@@ -389,23 +390,23 @@
         }
         if (!hasBGRA8Unorm) {
             return DAWN_INTERNAL_ERROR(
-                "Vulkan swapchain must support BGRA8Unorm with SRGB colorspace");
+                "Vulkan SwapChain must support BGRA8Unorm with sRGB colorspace.");
         }
         config.format = VK_FORMAT_B8G8R8A8_UNORM;
         config.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
         config.wgpuFormat = wgpu::TextureFormat::BGRA8Unorm;
 
         // Only the identity transform with opaque alpha is supported for now.
-        if ((surfaceInfo.capabilities.supportedTransforms &
-             VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) == 0) {
-            return DAWN_VALIDATION_ERROR("Vulkan swapchain must support the identity transform");
-        }
+        DAWN_INVALID_IF((surfaceInfo.capabilities.supportedTransforms &
+                         VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) == 0,
+                        "Vulkan SwapChain must support the identity transform.");
+
         config.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
 
-        if ((surfaceInfo.capabilities.supportedCompositeAlpha &
-             VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) == 0) {
-            return DAWN_VALIDATION_ERROR("Vulkan swapchain must support opaque alpha");
-        }
+        DAWN_INVALID_IF((surfaceInfo.capabilities.supportedCompositeAlpha &
+                         VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) == 0,
+                        "Vulkan SwapChain must support opaque alpha.");
+
         config.alphaMode = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
 
         // Choose the number of images for the swapchain= and clamp it to the min and max from the
@@ -453,7 +454,7 @@
             // then we'll need to have a second fallback that uses a blit shader :(
             if ((supportedUsages & VK_IMAGE_USAGE_TRANSFER_DST_BIT) == 0) {
                 return DAWN_INTERNAL_ERROR(
-                    "Swapchain cannot fallback to a blit because of a missing "
+                    "SwapChain cannot fallback to a blit because of a missing "
                     "VK_IMAGE_USAGE_TRANSFER_DST_BIT");
             }
             config.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp
index 70fbeee..93c0486 100644
--- a/src/dawn_native/vulkan/TextureVk.cpp
+++ b/src/dawn_native/vulkan/TextureVk.cpp
@@ -527,21 +527,18 @@
 
     MaybeError ValidateVulkanImageCanBeWrapped(const DeviceBase*,
                                                const TextureDescriptor* descriptor) {
-        if (descriptor->dimension != wgpu::TextureDimension::e2D) {
-            return DAWN_VALIDATION_ERROR("Texture must be 2D");
-        }
+        DAWN_INVALID_IF(descriptor->dimension != wgpu::TextureDimension::e2D,
+                        "Texture dimension (%s) is not %s.", descriptor->dimension,
+                        wgpu::TextureDimension::e2D);
 
-        if (descriptor->mipLevelCount != 1) {
-            return DAWN_VALIDATION_ERROR("Mip level count must be 1");
-        }
+        DAWN_INVALID_IF(descriptor->mipLevelCount != 1, "Mip level count (%u) is not 1.",
+                        descriptor->mipLevelCount);
 
-        if (descriptor->size.depthOrArrayLayers != 1) {
-            return DAWN_VALIDATION_ERROR("Array layer count must be 1");
-        }
+        DAWN_INVALID_IF(descriptor->size.depthOrArrayLayers != 1,
+                        "Array layer count (%u) is not 1.", descriptor->size.depthOrArrayLayers);
 
-        if (descriptor->sampleCount != 1) {
-            return DAWN_VALIDATION_ERROR("Sample count must be 1");
-        }
+        DAWN_INVALID_IF(descriptor->sampleCount != 1, "Sample count (%u) is not 1.",
+                        descriptor->sampleCount);
 
         return {};
     }
@@ -667,9 +664,8 @@
                                                external_memory::Service* externalMemoryService) {
         VkFormat format = VulkanImageFormat(ToBackend(GetDevice()), GetFormat().format);
         VkImageUsageFlags usage = VulkanImageUsage(GetInternalUsage(), GetFormat());
-        if (!externalMemoryService->SupportsCreateImage(descriptor, format, usage)) {
-            return DAWN_VALIDATION_ERROR("Creating an image from external memory is not supported");
-        }
+        DAWN_INVALID_IF(!externalMemoryService->SupportsCreateImage(descriptor, format, usage),
+                        "Creating an image from external memory is not supported.");
 
         mExternalState = ExternalState::PendingAcquire;
 
@@ -731,14 +727,12 @@
                                               VkImageLayout* releasedNewLayout) {
         Device* device = ToBackend(GetDevice());
 
-        if (mExternalState == ExternalState::Released) {
-            return DAWN_VALIDATION_ERROR("Can't export signal semaphore from signaled texture");
-        }
+        DAWN_INVALID_IF(mExternalState == ExternalState::Released,
+                        "Can't export a signal semaphore from signaled texture %s.", this);
 
-        if (mExternalAllocation == VK_NULL_HANDLE) {
-            return DAWN_VALIDATION_ERROR(
-                "Can't export signal semaphore from destroyed / non-external texture");
-        }
+        DAWN_INVALID_IF(
+            mExternalAllocation == VK_NULL_HANDLE,
+            "Can't export a signal semaphore from destroyed or non-external texture %s.", this);
 
         ASSERT(mSignalSemaphore != VK_NULL_HANDLE);
 
diff --git a/src/dawn_native/vulkan/external_memory/MemoryServiceDmaBuf.cpp b/src/dawn_native/vulkan/external_memory/MemoryServiceDmaBuf.cpp
index d3611d9..90b6373 100644
--- a/src/dawn_native/vulkan/external_memory/MemoryServiceDmaBuf.cpp
+++ b/src/dawn_native/vulkan/external_memory/MemoryServiceDmaBuf.cpp
@@ -55,7 +55,7 @@
                     return count;
                 }
             }
-            return DAWN_VALIDATION_ERROR("DRM format modifier not supported");
+            return DAWN_FORMAT_VALIDATION_ERROR("DRM format modifier not supported.");
         }
 
     }  // anonymous namespace
@@ -154,9 +154,9 @@
     ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
         const ExternalImageDescriptor* descriptor,
         VkImage image) {
-        if (descriptor->type != ExternalImageType::DmaBuf) {
-            return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not a dma-buf descriptor");
-        }
+        DAWN_INVALID_IF(descriptor->type != ExternalImageType::DmaBuf,
+                        "ExternalImageDescriptor is not a ExternalImageDescriptorDmaBuf.");
+
         const ExternalImageDescriptorDmaBuf* dmaBufDescriptor =
             static_cast<const ExternalImageDescriptorDmaBuf*>(descriptor);
         VkDevice device = mDevice->GetVkDevice();
@@ -177,9 +177,9 @@
         memoryRequirements.memoryTypeBits &= fdProperties.memoryTypeBits;
         int memoryTypeIndex = mDevice->GetResourceMemoryAllocator()->FindBestTypeIndex(
             memoryRequirements, MemoryKind::Opaque);
-        if (memoryTypeIndex == -1) {
-            return DAWN_VALIDATION_ERROR("Unable to find appropriate memory type for import");
-        }
+        DAWN_INVALID_IF(memoryTypeIndex == -1,
+                        "Unable to find an appropriate memory type for import.");
+
         MemoryImportParams params = {memoryRequirements.size,
                                      static_cast<uint32_t>(memoryTypeIndex)};
         return params;
@@ -188,9 +188,7 @@
     ResultOrError<VkDeviceMemory> Service::ImportMemory(ExternalMemoryHandle handle,
                                                         const MemoryImportParams& importParams,
                                                         VkImage image) {
-        if (handle < 0) {
-            return DAWN_VALIDATION_ERROR("Trying to import memory with invalid handle");
-        }
+        DAWN_INVALID_IF(handle < 0, "Importing memory with an invalid handle.");
 
         VkMemoryDedicatedAllocateInfo memoryDedicatedAllocateInfo;
         memoryDedicatedAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
@@ -220,9 +218,9 @@
 
     ResultOrError<VkImage> Service::CreateImage(const ExternalImageDescriptor* descriptor,
                                                 const VkImageCreateInfo& baseCreateInfo) {
-        if (descriptor->type != ExternalImageType::DmaBuf) {
-            return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not a dma-buf descriptor");
-        }
+        DAWN_INVALID_IF(descriptor->type != ExternalImageType::DmaBuf,
+                        "ExternalImageDescriptor is not a dma-buf descriptor.");
+
         const ExternalImageDescriptorDmaBuf* dmaBufDescriptor =
             static_cast<const ExternalImageDescriptorDmaBuf*>(descriptor);
         VkPhysicalDevice physicalDevice = ToBackend(mDevice->GetAdapter())->GetPhysicalDevice();
diff --git a/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp b/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp
index 70db38b..ad2c4c2 100644
--- a/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp
+++ b/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp
@@ -88,9 +88,9 @@
     ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
         const ExternalImageDescriptor* descriptor,
         VkImage image) {
-        if (descriptor->type != ExternalImageType::OpaqueFD) {
-            return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not an OpaqueFD descriptor");
-        }
+        DAWN_INVALID_IF(descriptor->type != ExternalImageType::OpaqueFD,
+                        "ExternalImageDescriptor is not an OpaqueFD descriptor.");
+
         const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor =
             static_cast<const ExternalImageDescriptorOpaqueFD*>(descriptor);
 
@@ -102,15 +102,13 @@
     ResultOrError<VkDeviceMemory> Service::ImportMemory(ExternalMemoryHandle handle,
                                                         const MemoryImportParams& importParams,
                                                         VkImage image) {
-        if (handle < 0) {
-            return DAWN_VALIDATION_ERROR("Trying to import memory with invalid handle");
-        }
+        DAWN_INVALID_IF(handle < 0, "Importing memory with an invalid handle.");
 
         VkMemoryRequirements requirements;
         mDevice->fn.GetImageMemoryRequirements(mDevice->GetVkDevice(), image, &requirements);
-        if (requirements.size > importParams.allocationSize) {
-            return DAWN_VALIDATION_ERROR("Requested allocation size is too small for image");
-        }
+        DAWN_INVALID_IF(requirements.size > importParams.allocationSize,
+                        "Requested allocation size (%u) is smaller than the image requires (%u).",
+                        importParams.allocationSize, requirements.size);
 
         VkImportMemoryFdInfoKHR importMemoryFdInfo;
         importMemoryFdInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR;
diff --git a/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp b/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp
index 6dbfcf9..c12bd85 100644
--- a/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp
+++ b/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp
@@ -88,9 +88,9 @@
     ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
         const ExternalImageDescriptor* descriptor,
         VkImage image) {
-        if (descriptor->type != ExternalImageType::OpaqueFD) {
-            return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not an OpaqueFD descriptor");
-        }
+        DAWN_INVALID_IF(descriptor->type != ExternalImageType::OpaqueFD,
+                        "ExternalImageDescriptor is not an OpaqueFD descriptor.");
+
         const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor =
             static_cast<const ExternalImageDescriptorOpaqueFD*>(descriptor);
 
@@ -102,15 +102,14 @@
     ResultOrError<VkDeviceMemory> Service::ImportMemory(ExternalMemoryHandle handle,
                                                         const MemoryImportParams& importParams,
                                                         VkImage image) {
-        if (handle == ZX_HANDLE_INVALID) {
-            return DAWN_VALIDATION_ERROR("Trying to import memory with invalid handle");
-        }
+        DAWN_INVALID_IF(handle == ZX_HANDLE_INVALID, "Importing memory with an invalid handle.");
 
         VkMemoryRequirements requirements;
         mDevice->fn.GetImageMemoryRequirements(mDevice->GetVkDevice(), image, &requirements);
-        if (requirements.size > importParams.allocationSize) {
-            return DAWN_VALIDATION_ERROR("Requested allocation size is too small for image");
-        }
+        DAWN_INVALID_IF(
+            requirements.size > importParams.allocationSize,
+            "Requested allocation size (%u) is smaller than the required image size (%u).",
+            importParams.allocationSize, requirements.size);
 
         VkImportMemoryZirconHandleInfoFUCHSIA importMemoryHandleInfo;
         importMemoryHandleInfo.sType =
diff --git a/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceFD.cpp b/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceFD.cpp
index b250056..b81f96c 100644
--- a/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceFD.cpp
+++ b/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceFD.cpp
@@ -67,9 +67,7 @@
     }
 
     ResultOrError<VkSemaphore> Service::ImportSemaphore(ExternalSemaphoreHandle handle) {
-        if (handle < 0) {
-            return DAWN_VALIDATION_ERROR("Trying to import semaphore with invalid handle");
-        }
+        DAWN_INVALID_IF(handle < 0, "Importing a semaphore with an invalid handle.");
 
         VkSemaphore semaphore = VK_NULL_HANDLE;
         VkSemaphoreCreateInfo info;
diff --git a/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceZirconHandle.cpp b/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceZirconHandle.cpp
index 656b9fe..d5bad90 100644
--- a/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceZirconHandle.cpp
+++ b/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceZirconHandle.cpp
@@ -60,9 +60,8 @@
     }
 
     ResultOrError<VkSemaphore> Service::ImportSemaphore(ExternalSemaphoreHandle handle) {
-        if (handle == ZX_HANDLE_INVALID) {
-            return DAWN_VALIDATION_ERROR("Trying to import semaphore with invalid handle");
-        }
+        DAWN_INVALID_IF(handle == ZX_HANDLE_INVALID,
+                        "Importing a semaphore with an invalid handle.");
 
         VkSemaphore semaphore = VK_NULL_HANDLE;
         VkSemaphoreCreateInfo info;