diff --git a/Source/Engine/Graphics/PixelFormat.h b/Source/Engine/Graphics/PixelFormat.h
index 9335b10c6..0326eb36f 100644
--- a/Source/Engine/Graphics/PixelFormat.h
+++ b/Source/Engine/Graphics/PixelFormat.h
@@ -558,6 +558,11 @@ API_ENUM() enum class PixelFormat : uint32
///
YUY2 = 108,
+ ///
+ /// Packed YUV 4:2:0 video texture format. Texture uses separate views to access the luma (Y) plane separately from the chroma (UV) planes. For luminance data view, the mapping to the view channel is Y->R8. For chrominance data view, the mapping to the view channel is U->R8 and V->G8.
+ ///
+ NV12 = 109,
+
///
/// The maximum format value (for internal use only).
///
diff --git a/Source/Engine/Graphics/PixelFormatExtensions.cpp b/Source/Engine/Graphics/PixelFormatExtensions.cpp
index 2b1f68457..2a341eec4 100644
--- a/Source/Engine/Graphics/PixelFormatExtensions.cpp
+++ b/Source/Engine/Graphics/PixelFormatExtensions.cpp
@@ -150,6 +150,8 @@ void PixelFormatExtensions::Init()
PixelFormat::BC4_UNorm,
};
InitFormat(formats8, 4);
+
+ sizeOfInBits[(int32)PixelFormat::NV12] = 12;
}
int32 PixelFormatExtensions::SizeInBits(PixelFormat format)
@@ -379,6 +381,7 @@ bool PixelFormatExtensions::IsVideo(const PixelFormat format)
switch (format)
{
case PixelFormat::YUY2:
+ case PixelFormat::NV12:
return true;
default:
return false;
diff --git a/Source/Engine/Graphics/RenderTools.cpp b/Source/Engine/Graphics/RenderTools.cpp
index e27cacf9c..3e47d974c 100644
--- a/Source/Engine/Graphics/RenderTools.cpp
+++ b/Source/Engine/Graphics/RenderTools.cpp
@@ -349,6 +349,10 @@ void RenderTools::ComputePitch(PixelFormat format, int32 width, int32 height, ui
rowPitch = ((width + 1) >> 1) * 4;
slicePitch = rowPitch * height;
break;
+ case PixelFormat::NV12:
+ rowPitch = width;
+ slicePitch = width * height * 3 / 2;
+ break;
default:
// Default byte alignment
rowPitch = (width * PixelFormatExtensions::SizeInBits(format) + 7) / 8;
diff --git a/Source/Engine/GraphicsDevice/DirectX/RenderToolsDX.cpp b/Source/Engine/GraphicsDevice/DirectX/RenderToolsDX.cpp
index 43e751395..b82126702 100644
--- a/Source/Engine/GraphicsDevice/DirectX/RenderToolsDX.cpp
+++ b/Source/Engine/GraphicsDevice/DirectX/RenderToolsDX.cpp
@@ -9,7 +9,7 @@
// @formatter:off
-DXGI_FORMAT PixelFormatToDXGIFormat[109] =
+DXGI_FORMAT PixelFormatToDXGIFormat[110] =
{
DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_R32G32B32A32_TYPELESS,
@@ -120,6 +120,7 @@ DXGI_FORMAT PixelFormatToDXGIFormat[109] =
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNorm
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNorm_sRGB
DXGI_FORMAT_YUY2,
+ DXGI_FORMAT_NV12,
};
// @formatter:on
diff --git a/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.cpp
index d1fe90ee2..5c0a66d75 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.cpp
@@ -8,7 +8,7 @@
// @formatter:off
-VkFormat RenderToolsVulkan::PixelFormatToVkFormat[109] =
+VkFormat RenderToolsVulkan::PixelFormatToVkFormat[110] =
{
VK_FORMAT_UNDEFINED,
VK_FORMAT_R32G32B32A32_SFLOAT,
@@ -119,6 +119,7 @@ VkFormat RenderToolsVulkan::PixelFormatToVkFormat[109] =
VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
VK_FORMAT_G8B8G8R8_422_UNORM, // YUY2
+ VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, // NV12
};
VkBlendFactor RenderToolsVulkan::BlendToVkBlendFactor[20] =
diff --git a/Source/Engine/Video/MF/VideoBackendMF.cpp b/Source/Engine/Video/MF/VideoBackendMF.cpp
index 0fb52b765..b1f57bd6a 100644
--- a/Source/Engine/Video/MF/VideoBackendMF.cpp
+++ b/Source/Engine/Video/MF/VideoBackendMF.cpp
@@ -96,6 +96,8 @@ namespace MF
player.Format = PixelFormat::B5G6R5_UNorm;
else if (subtype == MFVideoFormat_RGB555)
player.Format = PixelFormat::B5G5R5A1_UNorm;
+ else if (subtype == MFVideoFormat_NV12)
+ player.Format = PixelFormat::NV12;
else if (subtype == MFVideoFormat_YUY2)
player.Format = PixelFormat::YUY2;
#if (WDK_NTDDI_VERSION >= NTDDI_WIN10)