Use the ImageView's format in clear operations

Added support for using the ImageView's format
to perform clear operations.

Bug b/119620767

Tests: dEQP-VK.image.mutable.*_draw_copy

Change-Id: I3ea6d3264435bbd8390c7a8907e0c7a54c4c6783
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/28508
Tested-by: Alexis Hétu <sugoi@google.com>
Presubmit-Ready: Alexis Hétu <sugoi@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/Device/Blitter.cpp b/src/Device/Blitter.cpp
index be209a3..ea0bc96 100644
--- a/src/Device/Blitter.cpp
+++ b/src/Device/Blitter.cpp
@@ -34,20 +34,21 @@
 		delete blitCache;
 	}
 
-	void Blitter::clear(void *pixel, vk::Format format, vk::Image *dest, const VkImageSubresourceRange& subresourceRange, const VkRect2D* renderArea)
+	void Blitter::clear(void *pixel, vk::Format format, vk::Image *dest, const vk::Format& viewFormat, const VkImageSubresourceRange& subresourceRange, const VkRect2D* renderArea)
 	{
 		VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(subresourceRange.aspectMask);
-		if(dest->getFormat(aspect) == VK_FORMAT_UNDEFINED)
+		vk::Format dstFormat = vk::Image::GetFormat(viewFormat, aspect);
+		if(dstFormat == VK_FORMAT_UNDEFINED)
 		{
 			return;
 		}
 
-		if(fastClear(pixel, format, dest, subresourceRange, renderArea))
+		if(fastClear(pixel, format, dest, dstFormat, subresourceRange, renderArea))
 		{
 			return;
 		}
 
-		State state(format, dest->getFormat(aspect), 1, dest->getSampleCountFlagBits(), { 0xF });
+		State state(format, dstFormat, 1, dest->getSampleCountFlagBits(), { 0xF });
 		Routine *blitRoutine = getRoutine(state);
 		if(!blitRoutine)
 		{
@@ -112,7 +113,7 @@
 		}
 	}
 
-	bool Blitter::fastClear(void *pixel, vk::Format format, vk::Image *dest, const VkImageSubresourceRange& subresourceRange, const VkRect2D* renderArea)
+	bool Blitter::fastClear(void *pixel, vk::Format format, vk::Image *dest, const vk::Format& viewFormat, const VkImageSubresourceRange& subresourceRange, const VkRect2D* renderArea)
 	{
 		if(format != VK_FORMAT_R32G32B32A32_SFLOAT)
 		{
@@ -128,7 +129,7 @@
 		uint32_t packed;
 
 		VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(subresourceRange.aspectMask);
-		switch(dest->getFormat(aspect))
+		switch(viewFormat)
 		{
 		case VK_FORMAT_R5G6B5_UNORM_PACK16:
 			packed = ((uint16_t)(31 * b + 0.5f) << 0) |
@@ -203,7 +204,7 @@
 					{
 						uint8_t *d = slice;
 
-						switch(dest->getFormat(aspect).bytes())
+						switch(viewFormat.bytes())
 						{
 						case 2:
 							for(uint32_t i = 0; i < area.extent.height; i++)
diff --git a/src/Device/Blitter.hpp b/src/Device/Blitter.hpp
index bc4a41d..acd2732 100644
--- a/src/Device/Blitter.hpp
+++ b/src/Device/Blitter.hpp
@@ -104,12 +104,12 @@
 		Blitter();
 		virtual ~Blitter();
 
-		void clear(void *pixel, vk::Format format, vk::Image *dest, const VkImageSubresourceRange& subresourceRange, const VkRect2D* renderArea = nullptr);
+		void clear(void *pixel, vk::Format format, vk::Image *dest, const vk::Format& viewFormat, const VkImageSubresourceRange& subresourceRange, const VkRect2D* renderArea = nullptr);
 
 		void blit(vk::Image *src, vk::Image *dst, VkImageBlit region, VkFilter filter);
 
 	private:
-		bool fastClear(void *pixel, vk::Format format, vk::Image *dest, const VkImageSubresourceRange& subresourceRange, const VkRect2D* renderArea);
+		bool fastClear(void *pixel, vk::Format format, vk::Image *dest, const vk::Format& viewFormat, const VkImageSubresourceRange& subresourceRange, const VkRect2D* renderArea);
 
 		bool read(Float4 &color, Pointer<Byte> element, const State &state);
 		bool write(Float4 &color, Pointer<Byte> element, const State &state);
diff --git a/src/Vulkan/VkFormat.cpp b/src/Vulkan/VkFormat.cpp
index d7dedf5..c201389 100644
--- a/src/Vulkan/VkFormat.cpp
+++ b/src/Vulkan/VkFormat.cpp
@@ -382,6 +382,323 @@
 	}
 }
 
+VkFormat Format::compatibleFormat() const
+{
+	// According to the Vulkan 1.1 Spec, 37.1.6. Format Compatibility Classes:
+	// "Uncompressed color formats are compatible with each other if they occupy
+	//  the same number of bits per texel block. Compressed color formats are
+	//  compatible with each other if the only difference between them is the
+	//  numerical type of the uncompressed pixels (e.g. signed vs. unsigned, or
+	//  SRGB vs. UNORM encoding). Each depth/stencil format is only compatible
+	//  with itself. In the following table, all the formats in the same row are
+	//  compatible."
+
+	// Return a single format per group of compatible formats, for quick comparison
+	switch(format)
+	{
+	// 8 - bit, Block size 1 byte, 1 texel / block

+	case VK_FORMAT_R4G4_UNORM_PACK8:

+	case VK_FORMAT_R8_UNORM:

+	case VK_FORMAT_R8_SNORM:

+	case VK_FORMAT_R8_USCALED:

+	case VK_FORMAT_R8_SSCALED:

+	case VK_FORMAT_R8_UINT:

+	case VK_FORMAT_R8_SINT:

+	case VK_FORMAT_R8_SRGB:

+		return VK_FORMAT_R8_UNORM;

+

+	// 16 - bit, Block size 2 bytes, 1 texel / block

+	case VK_FORMAT_R4G4B4A4_UNORM_PACK16:

+	case VK_FORMAT_B4G4R4A4_UNORM_PACK16:

+	case VK_FORMAT_R5G6B5_UNORM_PACK16:

+	case VK_FORMAT_B5G6R5_UNORM_PACK16:

+	case VK_FORMAT_R5G5B5A1_UNORM_PACK16:

+	case VK_FORMAT_B5G5R5A1_UNORM_PACK16:

+	case VK_FORMAT_A1R5G5B5_UNORM_PACK16:

+	case VK_FORMAT_R8G8_UNORM:

+	case VK_FORMAT_R8G8_SNORM:

+	case VK_FORMAT_R8G8_USCALED:

+	case VK_FORMAT_R8G8_SSCALED:

+	case VK_FORMAT_R8G8_UINT:

+	case VK_FORMAT_R8G8_SINT:

+	case VK_FORMAT_R8G8_SRGB:

+	case VK_FORMAT_R16_UNORM:

+	case VK_FORMAT_R16_SNORM:

+	case VK_FORMAT_R16_USCALED:

+	case VK_FORMAT_R16_SSCALED:

+	case VK_FORMAT_R16_UINT:

+	case VK_FORMAT_R16_SINT:

+	case VK_FORMAT_R16_SFLOAT:

+	case VK_FORMAT_R10X6_UNORM_PACK16:

+	case VK_FORMAT_R12X4_UNORM_PACK16:

+		return VK_FORMAT_R16_UNORM;

+

+	// 24 - bit, Block size 3 bytes, 1 texel / block

+	case VK_FORMAT_R8G8B8_UNORM:

+	case VK_FORMAT_R8G8B8_SNORM:

+	case VK_FORMAT_R8G8B8_USCALED:

+	case VK_FORMAT_R8G8B8_SSCALED:

+	case VK_FORMAT_R8G8B8_UINT:

+	case VK_FORMAT_R8G8B8_SINT:

+	case VK_FORMAT_R8G8B8_SRGB:

+	case VK_FORMAT_B8G8R8_UNORM:

+	case VK_FORMAT_B8G8R8_SNORM:

+	case VK_FORMAT_B8G8R8_USCALED:

+	case VK_FORMAT_B8G8R8_SSCALED:

+	case VK_FORMAT_B8G8R8_UINT:

+	case VK_FORMAT_B8G8R8_SINT:

+	case VK_FORMAT_B8G8R8_SRGB:

+		return VK_FORMAT_R8G8B8_UNORM;

+

+	// 32 - bit, Block size 4 bytes, 1 texel / block

+	case VK_FORMAT_R8G8B8A8_UNORM:

+	case VK_FORMAT_R8G8B8A8_SNORM:

+	case VK_FORMAT_R8G8B8A8_USCALED:

+	case VK_FORMAT_R8G8B8A8_SSCALED:

+	case VK_FORMAT_R8G8B8A8_UINT:

+	case VK_FORMAT_R8G8B8A8_SINT:

+	case VK_FORMAT_R8G8B8A8_SRGB:

+	case VK_FORMAT_B8G8R8A8_UNORM:

+	case VK_FORMAT_B8G8R8A8_SNORM:

+	case VK_FORMAT_B8G8R8A8_USCALED:

+	case VK_FORMAT_B8G8R8A8_SSCALED:

+	case VK_FORMAT_B8G8R8A8_UINT:

+	case VK_FORMAT_B8G8R8A8_SINT:

+	case VK_FORMAT_B8G8R8A8_SRGB:

+	case VK_FORMAT_A8B8G8R8_UNORM_PACK32:

+	case VK_FORMAT_A8B8G8R8_SNORM_PACK32:

+	case VK_FORMAT_A8B8G8R8_USCALED_PACK32:

+	case VK_FORMAT_A8B8G8R8_SSCALED_PACK32:

+	case VK_FORMAT_A8B8G8R8_UINT_PACK32:

+	case VK_FORMAT_A8B8G8R8_SINT_PACK32:

+	case VK_FORMAT_A8B8G8R8_SRGB_PACK32:

+	case VK_FORMAT_A2R10G10B10_UNORM_PACK32:

+	case VK_FORMAT_A2R10G10B10_SNORM_PACK32:

+	case VK_FORMAT_A2R10G10B10_USCALED_PACK32:

+	case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:

+	case VK_FORMAT_A2R10G10B10_UINT_PACK32:

+	case VK_FORMAT_A2R10G10B10_SINT_PACK32:

+	case VK_FORMAT_A2B10G10R10_UNORM_PACK32:

+	case VK_FORMAT_A2B10G10R10_SNORM_PACK32:

+	case VK_FORMAT_A2B10G10R10_USCALED_PACK32:

+	case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:

+	case VK_FORMAT_A2B10G10R10_UINT_PACK32:

+	case VK_FORMAT_A2B10G10R10_SINT_PACK32:

+	case VK_FORMAT_R16G16_UNORM:

+	case VK_FORMAT_R16G16_SNORM:

+	case VK_FORMAT_R16G16_USCALED:

+	case VK_FORMAT_R16G16_SSCALED:

+	case VK_FORMAT_R16G16_UINT:

+	case VK_FORMAT_R16G16_SINT:

+	case VK_FORMAT_R16G16_SFLOAT:

+	case VK_FORMAT_R32_UINT:

+	case VK_FORMAT_R32_SINT:

+	case VK_FORMAT_R32_SFLOAT:

+	case VK_FORMAT_B10G11R11_UFLOAT_PACK32:

+	case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:

+	case VK_FORMAT_R10X6G10X6_UNORM_2PACK16:

+	case VK_FORMAT_R12X4G12X4_UNORM_2PACK16:

+		return VK_FORMAT_R8G8B8A8_UNORM;

+

+	// 48 - bit, Block size 6 bytes, 1 texel / block

+	case VK_FORMAT_R16G16B16_UNORM:

+	case VK_FORMAT_R16G16B16_SNORM:

+	case VK_FORMAT_R16G16B16_USCALED:

+	case VK_FORMAT_R16G16B16_SSCALED:

+	case VK_FORMAT_R16G16B16_UINT:

+	case VK_FORMAT_R16G16B16_SINT:

+	case VK_FORMAT_R16G16B16_SFLOAT:

+		return VK_FORMAT_R16G16B16_UNORM;

+

+	// 64 - bit, Block size 8 bytes, 1 texel / block

+	case VK_FORMAT_R16G16B16A16_UNORM:

+	case VK_FORMAT_R16G16B16A16_SNORM:

+	case VK_FORMAT_R16G16B16A16_USCALED:

+	case VK_FORMAT_R16G16B16A16_SSCALED:

+	case VK_FORMAT_R16G16B16A16_UINT:

+	case VK_FORMAT_R16G16B16A16_SINT:

+	case VK_FORMAT_R16G16B16A16_SFLOAT:

+	case VK_FORMAT_R32G32_UINT:

+	case VK_FORMAT_R32G32_SINT:

+	case VK_FORMAT_R32G32_SFLOAT:

+	case VK_FORMAT_R64_UINT:

+	case VK_FORMAT_R64_SINT:

+	case VK_FORMAT_R64_SFLOAT:

+		return VK_FORMAT_R16G16B16A16_UNORM;

+

+	// 96 - bit, Block size 12 bytes, 1 texel / block

+	case VK_FORMAT_R32G32B32_UINT:

+	case VK_FORMAT_R32G32B32_SINT:

+	case VK_FORMAT_R32G32B32_SFLOAT:

+		return VK_FORMAT_R32G32B32_UINT;

+

+	// 128 - bit, Block size 16 bytes, 1 texel / block

+	case VK_FORMAT_R32G32B32A32_UINT:

+	case VK_FORMAT_R32G32B32A32_SINT:

+	case VK_FORMAT_R32G32B32A32_SFLOAT:

+	case VK_FORMAT_R64G64_UINT:

+	case VK_FORMAT_R64G64_SINT:

+	case VK_FORMAT_R64G64_SFLOAT:

+		return VK_FORMAT_R32G32B32A32_UINT;

+

+	// 192 - bit, Block size 24 bytes, 1 texel / block

+	case VK_FORMAT_R64G64B64_UINT:

+	case VK_FORMAT_R64G64B64_SINT:

+	case VK_FORMAT_R64G64B64_SFLOAT:

+		return VK_FORMAT_R64G64B64_UINT;

+

+	// 256 - bit, Block size 32 bytes, 1 texel / block

+	case VK_FORMAT_R64G64B64A64_UINT:

+	case VK_FORMAT_R64G64B64A64_SINT:

+	case VK_FORMAT_R64G64B64A64_SFLOAT:

+		return VK_FORMAT_R64G64B64A64_UINT;

+

+	// BC1_RGB(64 bit), Block size 8 bytes, 16 texels / block

+	case VK_FORMAT_BC1_RGB_UNORM_BLOCK:

+	case VK_FORMAT_BC1_RGB_SRGB_BLOCK:

+		return VK_FORMAT_BC1_RGB_UNORM_BLOCK;

+

+	// BC1_RGBA(64 bit), Block size 8 bytes, 16 texels / block

+	case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:

+	case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:

+		return VK_FORMAT_BC1_RGBA_UNORM_BLOCK;

+

+	// BC2(128 bit), Block size 16 bytes, 16 texels / block

+	case VK_FORMAT_BC2_UNORM_BLOCK:

+	case VK_FORMAT_BC2_SRGB_BLOCK:

+		return VK_FORMAT_BC2_UNORM_BLOCK;

+

+	// BC3(128 bit), Block size 16 bytes, 16 texels / block

+	case VK_FORMAT_BC3_UNORM_BLOCK:

+	case VK_FORMAT_BC3_SRGB_BLOCK:

+		return VK_FORMAT_BC3_UNORM_BLOCK;

+

+	// BC4(64 bit), Block size 8 bytes, 16 texels / block

+	case VK_FORMAT_BC4_UNORM_BLOCK:

+	case VK_FORMAT_BC4_SNORM_BLOCK:

+		return VK_FORMAT_BC4_UNORM_BLOCK;

+

+	// BC5(128 bit), Block size 16 bytes, 16 texels / block

+	case VK_FORMAT_BC5_UNORM_BLOCK:

+	case VK_FORMAT_BC5_SNORM_BLOCK:

+		return VK_FORMAT_BC5_UNORM_BLOCK;

+

+	// BC6H(128 bit), Block size 16 bytes, 16 texels / block

+	case VK_FORMAT_BC6H_UFLOAT_BLOCK:

+	case VK_FORMAT_BC6H_SFLOAT_BLOCK:

+		return VK_FORMAT_BC6H_UFLOAT_BLOCK;

+

+	// BC7(128 bit), Block size 16 bytes, 16 texels / block

+	case VK_FORMAT_BC7_UNORM_BLOCK:

+	case VK_FORMAT_BC7_SRGB_BLOCK:

+		return VK_FORMAT_BC7_UNORM_BLOCK;

+

+	// ETC2_RGB(64 bit), Block size 8 bytes, 16 texels / block

+	case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:

+	case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:

+		return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;

+

+	// ETC2_RGBA(64 bit), Block size 8 bytes, 16 texels / block

+	case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:

+	case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:

+		return VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;

+

+	// ETC2_EAC_RGBA(64 bit), Block size 8 bytes, 16 texels / block

+	case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:

+	case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:

+		return VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;

+

+	// EAC_R(64 bit), Block size 8 bytes, 16 texels / block

+	case VK_FORMAT_EAC_R11_UNORM_BLOCK:

+	case VK_FORMAT_EAC_R11_SNORM_BLOCK:

+		return VK_FORMAT_EAC_R11_UNORM_BLOCK;

+

+	// EAC_RG(128 bit), Block size 16 bytes, 16 texels / block

+	case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:

+	case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:

+		return VK_FORMAT_EAC_R11G11_UNORM_BLOCK;

+

+	// ASTC_4x4(128 bit), Block size 16 bytes, 16 texels / block

+	case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:

+	case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:

+		return VK_FORMAT_ASTC_4x4_UNORM_BLOCK;

+

+	// ASTC_5x4(128 bit), Block size 16 bytes, 20 texels / block

+	case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:

+	case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:

+		return VK_FORMAT_ASTC_5x4_UNORM_BLOCK;

+

+	// ASTC_5x5(128 bit), Block size 16 bytes, 25 texels / block

+	case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:

+	case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:

+		return VK_FORMAT_ASTC_5x5_UNORM_BLOCK;

+

+	// ASTC_6x5(128 bit), Block size 16 bytes, 30 texels / block

+	case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:

+	case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:

+		return VK_FORMAT_ASTC_6x5_UNORM_BLOCK;

+

+	// ASTC_6x6(128 bit), Block size 16 bytes, 36 texels / block

+	case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:

+	case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:

+		return VK_FORMAT_ASTC_6x6_UNORM_BLOCK;

+

+	// ASTC_8x5(128 bit), Block size 16 bytes, 40 texels / block

+	case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:

+	case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:

+		return VK_FORMAT_ASTC_8x5_UNORM_BLOCK;

+

+	// ASTC_8x6(128 bit), Block size 16 bytes, 48 texels / block

+	case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:

+	case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:

+		return VK_FORMAT_ASTC_8x6_UNORM_BLOCK;

+

+	// ASTC_8x8(128 bit), Block size 16 bytes, 64 texels / block

+	case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:

+	case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:

+		return VK_FORMAT_ASTC_8x8_UNORM_BLOCK;

+

+	// ASTC_10x5(128 bit), Block size 16 bytes, 50 texels / block

+	case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:

+	case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:

+		return VK_FORMAT_ASTC_10x5_UNORM_BLOCK;

+

+	// ASTC_10x6(128 bit), Block size 16 bytes, 60 texels / block

+	case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:

+	case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:

+		return VK_FORMAT_ASTC_10x6_UNORM_BLOCK;

+

+	// ASTC_10x8(128 bit), Block size 16 bytes, 80 texels / block

+	case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:

+	case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:

+		return VK_FORMAT_ASTC_10x8_UNORM_BLOCK;

+

+	// ASTC_10x10(128 bit), Block size 16 bytes, 100 texels / block

+	case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:

+	case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:

+		return VK_FORMAT_ASTC_10x10_UNORM_BLOCK;

+

+	// ASTC_12x10(128 bit), Block size 16 bytes, 120 texels / block

+	case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:

+	case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:

+		return VK_FORMAT_ASTC_12x10_UNORM_BLOCK;

+

+	// ASTC_12x12(128 bit), Block size 16 bytes, 144 texels / block

+	case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:

+	case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
+		return VK_FORMAT_ASTC_12x12_UNORM_BLOCK;
+
+	// All other formats are only compatible with themselves
+	default:
+		return format;
+	}
+}
+
+bool Format::isCompatible(const Format& other) const
+{
+	return compatibleFormat() == other.compatibleFormat();
+}
+
 int Format::blockWidth() const
 {
 	switch(format)
diff --git a/src/Vulkan/VkFormat.h b/src/Vulkan/VkFormat.h
index 5721d06..24a3724 100644
--- a/src/Vulkan/VkFormat.h
+++ b/src/Vulkan/VkFormat.h
@@ -45,6 +45,7 @@
 	bool isSRGBwritable() const;
 	bool isFloatFormat() const;
 
+	bool isCompatible(const Format& other) const;
 	bool isCompressed() const;
 	int blockWidth() const;
 	int blockHeight() const;
@@ -68,6 +69,8 @@
 	bool isRGBComponent(int component) const;
 
 private:
+	VkFormat compatibleFormat() const;
+
 	VkFormat format = VK_FORMAT_UNDEFINED;
 };
 
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp
index ba7cdad..cce91d7 100644
--- a/src/Vulkan/VkImage.cpp
+++ b/src/Vulkan/VkImage.cpp
@@ -502,6 +502,11 @@
 
 Format Image::getFormat(VkImageAspectFlagBits aspect) const
 {
+	return GetFormat(format, aspect);
+}
+
+Format Image::GetFormat(const vk::Format& format, VkImageAspectFlagBits aspect)
+{
 	switch(aspect)
 	{
 	case VK_IMAGE_ASPECT_DEPTH_BIT:
@@ -644,7 +649,7 @@
 	        mipLevels : (subresourceRange.baseMipLevel + subresourceRange.levelCount)) - 1;
 }
 
-void Image::clear(void* pixelData, VkFormat format, const VkImageSubresourceRange& subresourceRange, const VkRect2D& renderArea)
+void Image::clear(void* pixelData, VkFormat pixelFormat, const vk::Format& viewFormat, const VkImageSubresourceRange& subresourceRange, const VkRect2D& renderArea)
 {
 	if((subresourceRange.baseMipLevel != 0) ||
 	   (subresourceRange.levelCount != 1))
@@ -652,7 +657,7 @@
 		UNIMPLEMENTED("subresourceRange");
 	}
 
-	device->getBlitter()->clear(pixelData, format, this, subresourceRange, &renderArea);
+	device->getBlitter()->clear(pixelData, pixelFormat, this, viewFormat, subresourceRange, &renderArea);
 }
 
 void Image::clear(const VkClearColorValue& color, const VkImageSubresourceRange& subresourceRange)
@@ -662,7 +667,7 @@
 		UNIMPLEMENTED("aspectMask");
 	}
 
-	device->getBlitter()->clear((void*)color.float32, getClearFormat(), this, subresourceRange);
+	device->getBlitter()->clear((void*)color.float32, getClearFormat(), this, format, subresourceRange);
 }
 
 void Image::clear(const VkClearDepthStencilValue& color, const VkImageSubresourceRange& subresourceRange)
@@ -677,18 +682,18 @@
 	{
 		VkImageSubresourceRange depthSubresourceRange = subresourceRange;
 		depthSubresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
-		device->getBlitter()->clear((void*)(&color.depth), VK_FORMAT_D32_SFLOAT, this, depthSubresourceRange);
+		device->getBlitter()->clear((void*)(&color.depth), VK_FORMAT_D32_SFLOAT, this, format, depthSubresourceRange);
 	}
 
 	if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
 	{
 		VkImageSubresourceRange stencilSubresourceRange = subresourceRange;
 		stencilSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
-		device->getBlitter()->clear((void*)(&color.stencil), VK_FORMAT_S8_UINT, this, stencilSubresourceRange);
+		device->getBlitter()->clear((void*)(&color.stencil), VK_FORMAT_S8_UINT, this, format, stencilSubresourceRange);
 	}
 }
 
-void Image::clear(const VkClearValue& clearValue, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange)
+void Image::clear(const VkClearValue& clearValue, const vk::Format& viewFormat, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange)
 {
 	if(!((subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
 	     (subresourceRange.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT |
@@ -701,7 +706,7 @@
 
 	if(subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
 	{
-		clear((void*)(clearValue.color.float32), getClearFormat(), subresourceRange, renderArea);
+		clear((void*)(clearValue.color.float32), getClearFormat(), viewFormat, subresourceRange, renderArea);
 	}
 	else
 	{
@@ -709,14 +714,14 @@
 		{
 			VkImageSubresourceRange depthSubresourceRange = subresourceRange;
 			depthSubresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
-			clear((void*)(&clearValue.depthStencil.depth), VK_FORMAT_D32_SFLOAT, depthSubresourceRange, renderArea);
+			clear((void*)(&clearValue.depthStencil.depth), VK_FORMAT_D32_SFLOAT, viewFormat, depthSubresourceRange, renderArea);
 		}
 
 		if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
 		{
 			VkImageSubresourceRange stencilSubresourceRange = subresourceRange;
 			stencilSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
-			clear((void*)(&clearValue.depthStencil.stencil), VK_FORMAT_S8_UINT, stencilSubresourceRange, renderArea);
+			clear((void*)(&clearValue.depthStencil.stencil), VK_FORMAT_S8_UINT, viewFormat, stencilSubresourceRange, renderArea);
 		}
 	}
 }
diff --git a/src/Vulkan/VkImage.hpp b/src/Vulkan/VkImage.hpp
index f9af23f..dffccbb 100644
--- a/src/Vulkan/VkImage.hpp
+++ b/src/Vulkan/VkImage.hpp
@@ -47,7 +47,7 @@
 	void copyFrom(VkBuffer srcBuffer, const VkBufferImageCopy& region);
 
 	void blit(VkImage dstImage, const VkImageBlit& region, VkFilter filter);
-	void clear(const VkClearValue& clearValue, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange);
+	void clear(const VkClearValue& clearValue, const vk::Format& viewFormat, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange);
 	void clear(const VkClearColorValue& color, const VkImageSubresourceRange& subresourceRange);
 	void clear(const VkClearDepthStencilValue& color, const VkImageSubresourceRange& subresourceRange);
 
@@ -67,6 +67,8 @@
 	bool                     isCube() const;
 	uint8_t*                 end() const;
 
+	static Format            GetFormat(const vk::Format& format, VkImageAspectFlagBits aspect);
+
 private:
 	void copy(VkBuffer buffer, const VkBufferImageCopy& region, bool bufferIsSource);
 	VkDeviceSize getStorageSize(VkImageAspectFlags flags) const;
@@ -82,7 +84,7 @@
 	VkExtent2D bufferExtentInBlocks(const VkExtent2D& extent, const VkBufferImageCopy& region) const;
 	int bytesPerTexel(VkImageAspectFlagBits flags) const;
 	VkFormat getClearFormat() const;
-	void clear(void* pixelData, VkFormat format, const VkImageSubresourceRange& subresourceRange, const VkRect2D& renderArea);
+	void clear(void* pixelData, VkFormat pixelFormat, const vk::Format& viewFormat, const VkImageSubresourceRange& subresourceRange, const VkRect2D& renderArea);
 	int borderSize(VkImageAspectFlagBits aspect) const;
 
 	const Device *const      device = nullptr;
diff --git a/src/Vulkan/VkImageView.cpp b/src/Vulkan/VkImageView.cpp
index 1d7bcab..e8b7be9 100644
--- a/src/Vulkan/VkImageView.cpp
+++ b/src/Vulkan/VkImageView.cpp
@@ -87,14 +87,14 @@
 		UNIMPLEMENTED("imageTypesMatch");
 	}
 
-	if(image->getFormat() != format)
+	if(!format.isCompatible(image->getFormat()))
 	{
-		UNIMPLEMENTED("format");
+		UNIMPLEMENTED("incompatible formats");
 	}
 
 	VkImageSubresourceRange sr = subresourceRange;
 	sr.aspectMask = aspectMask;
-	image->clear(clearValue, renderArea, sr);
+	image->clear(clearValue, format, renderArea, sr);
 }
 
 void ImageView::clear(const VkClearValue& clearValue, const VkImageAspectFlags aspectMask, const VkClearRect& renderArea)
@@ -106,10 +106,10 @@
 		UNIMPLEMENTED("imageTypesMatch");
 	}
 
-	if(image->getFormat() != format)
+	if(!format.isCompatible(image->getFormat()))
 	{
-		UNIMPLEMENTED("format");
-	}
+		UNIMPLEMENTED("incompatible formats");
+	}

 
 	VkImageSubresourceRange sr;
 	sr.aspectMask = aspectMask;
@@ -118,7 +118,7 @@
 	sr.baseArrayLayer = renderArea.baseArrayLayer + subresourceRange.baseArrayLayer;
 	sr.layerCount = renderArea.layerCount;
 
-	image->clear(clearValue, renderArea.rect, sr);
+	image->clear(clearValue, format, renderArea.rect, sr);
 }
 
 void ImageView::resolve(ImageView* resolveAttachment)