SDL: gdk: Backport SDL3 MR #8844

From b5aec14d43b9b5531fb3b3c32afc1c4a0a6b50f7 Mon Sep 17 00:00:00 2001
From: Ethan Lee <[EMAIL REDACTED]>
Date: Sun, 21 Jan 2024 13:16:44 -0500
Subject: [PATCH] gdk: Backport SDL3 MR #8844

Co-authored-by: chalonverse <sanjay12@gmail.com>
---
 .gitignore                                    |   1 +
 VisualC-GDK/SDL/SDL.vcxproj                   |  24 +++
 VisualC-GDK/clean.sh                          |   1 +
 .../shaders/D3D12_PixelShader_Colors.hlsl     |  19 +++
 .../shaders/D3D12_PixelShader_NV12_BT601.hlsl |  43 +++++
 .../shaders/D3D12_PixelShader_NV12_BT709.hlsl |  43 +++++
 .../shaders/D3D12_PixelShader_NV12_JPEG.hlsl  |  43 +++++
 .../shaders/D3D12_PixelShader_NV21_BT601.hlsl |  43 +++++
 .../shaders/D3D12_PixelShader_NV21_BT709.hlsl |  43 +++++
 .../shaders/D3D12_PixelShader_NV21_JPEG.hlsl  |  43 +++++
 .../shaders/D3D12_PixelShader_Textures.hlsl   |  24 +++
 .../shaders/D3D12_PixelShader_YUV_BT601.hlsl  |  46 ++++++
 .../shaders/D3D12_PixelShader_YUV_BT709.hlsl  |  46 ++++++
 .../shaders/D3D12_PixelShader_YUV_JPEG.hlsl   |  46 ++++++
 VisualC-GDK/shaders/D3D12_VertexShader.hlsl   |  95 +++++++++++
 VisualC-GDK/shaders/buildshaders.bat          |  35 ++++
 docs/README-gdk.md                            |  19 ++-
 .../direct3d12/SDL_render_d3d12_xbox.cpp      | 151 +++++++++++++++++-
 src/render/direct3d12/SDL_render_d3d12_xbox.h |  29 +++-
 .../direct3d12/SDL_shaders_d3d12_xboxone.cpp  | 119 +++++++++++++-
 .../SDL_shaders_d3d12_xboxseries.cpp          | 119 +++++++++++++-
 21 files changed, 1023 insertions(+), 9 deletions(-)
 create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_Colors.hlsl
 create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT601.hlsl
 create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT709.hlsl
 create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_NV12_JPEG.hlsl
 create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT601.hlsl
 create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT709.hlsl
 create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_NV21_JPEG.hlsl
 create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_Textures.hlsl
 create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT601.hlsl
 create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT709.hlsl
 create mode 100644 VisualC-GDK/shaders/D3D12_PixelShader_YUV_JPEG.hlsl
 create mode 100644 VisualC-GDK/shaders/D3D12_VertexShader.hlsl
 create mode 100644 VisualC-GDK/shaders/buildshaders.bat

diff --git a/.gitignore b/.gitignore
index fb013e8bfe96..cced2f8ed8b5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -103,6 +103,7 @@ VisualC/visualtest/testsprite2_sample.actions
 VisualC/visualtest/testsprite2_sample.config
 VisualC/visualtest/testsprite2_sample.parameters
 VisualC-GDK/**/Layout
+VisualC-GDK/shaders/*.h
 
 # for Android
 android-project/local.properties
diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj
index ed071aa9da4c..7fe0d4105dc9 100644
--- a/VisualC-GDK/SDL/SDL.vcxproj
+++ b/VisualC-GDK/SDL/SDL.vcxproj
@@ -173,6 +173,12 @@
       <SubSystem>Windows</SubSystem>
       <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
     </Link>
+    <PreBuildEvent>
+      <Command>$(SolutionDir)\shaders\buildshaders.bat $(SolutionDir)</Command>
+    </PreBuildEvent>
+    <PreBuildEvent>
+      <Message>Building shader blobs (Xbox Series)</Message>
+    </PreBuildEvent>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Gaming.Xbox.XboxOne.x64'">
     <Midl>
@@ -201,6 +207,12 @@
       <SubSystem>Windows</SubSystem>
       <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
     </Link>
+    <PreBuildEvent>
+      <Command>$(SolutionDir)\shaders\buildshaders.bat $(SolutionDir) one</Command>
+    </PreBuildEvent>
+    <PreBuildEvent>
+      <Message>Building shader blobs (Xbox One)</Message>
+    </PreBuildEvent>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Gaming.Desktop.x64'">
     <Midl>
@@ -259,6 +271,12 @@
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
     </Link>
+    <PreBuildEvent>
+      <Command>$(SolutionDir)\shaders\buildshaders.bat $(SolutionDir)</Command>
+    </PreBuildEvent>
+    <PreBuildEvent>
+      <Message>Building shader blobs (Xbox Series)</Message>
+    </PreBuildEvent>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Gaming.Xbox.XboxOne.x64'">
     <Midl>
@@ -288,6 +306,12 @@
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
     </Link>
+    <PreBuildEvent>
+      <Command>$(SolutionDir)\shaders\buildshaders.bat $(SolutionDir) one</Command>
+    </PreBuildEvent>
+    <PreBuildEvent>
+      <Message>Building shader blobs (Xbox One)</Message>
+    </PreBuildEvent>
   </ItemDefinitionGroup>
   <ItemGroup>
     <ClInclude Include="..\..\include\begin_code.h" />
diff --git a/VisualC-GDK/clean.sh b/VisualC-GDK/clean.sh
index a026b71a30ef..235b79c49431 100755
--- a/VisualC-GDK/clean.sh
+++ b/VisualC-GDK/clean.sh
@@ -4,3 +4,4 @@ find . -type f \( -name '*.bmp' -o -name '*.wav' -o -name '*.dat' \) -print -del
 find . -depth -type d \( -name Gaming.Desktop.x64 \) -exec rm -rv {} \;
 find . -depth -type d \( -name Gaming.Xbox.Scarlett.x64 \) -exec rm -rv {} \;
 find . -depth -type d \( -name Gaming.Xbox.XboxOne.x64 \) -exec rm -rv {} \;
+rm shaders/*.h
diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_Colors.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_Colors.hlsl
new file mode 100644
index 000000000000..47eff4cc2444
--- /dev/null
+++ b/VisualC-GDK/shaders/D3D12_PixelShader_Colors.hlsl
@@ -0,0 +1,19 @@
+struct PixelShaderInput
+{
+    float4 pos : SV_POSITION;
+    float2 tex : TEXCOORD0;
+    float4 color : COLOR0;
+};
+
+#define ColorRS \
+    "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
+    "DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
+    "DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
+    "DENY_HULL_SHADER_ROOT_ACCESS )," \
+    "RootConstants(num32BitConstants=32, b0)"
+
+[RootSignature(ColorRS)]
+float4 main(PixelShaderInput input) : SV_TARGET0
+{
+    return input.color;
+}
\ No newline at end of file
diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT601.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT601.hlsl
new file mode 100644
index 000000000000..cffbc2261822
--- /dev/null
+++ b/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT601.hlsl
@@ -0,0 +1,43 @@
+Texture2D theTextureY : register(t0);
+Texture2D theTextureUV : register(t1);
+SamplerState theSampler : register(s0);
+
+struct PixelShaderInput
+{
+    float4 pos : SV_POSITION;
+    float2 tex : TEXCOORD0;
+    float4 color : COLOR0;
+};
+
+#define NVRS \
+    "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
+    "            DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
+    "            DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
+    "            DENY_HULL_SHADER_ROOT_ACCESS )," \
+    "RootConstants(num32BitConstants=32, b0),"\
+    "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )"
+
+[RootSignature(NVRS)]
+float4 main(PixelShaderInput input) : SV_TARGET
+{
+    const float3 offset = {-0.0627451017, -0.501960814, -0.501960814};
+    const float3 Rcoeff = {1.1644,  0.0000,  1.5960};
+    const float3 Gcoeff = {1.1644, -0.3918, -0.8130};
+    const float3 Bcoeff = {1.1644,  2.0172,  0.0000};
+
+    float4 Output;
+
+    float3 yuv;
+    yuv.x = theTextureY.Sample(theSampler, input.tex).r;
+    yuv.yz = theTextureUV.Sample(theSampler, input.tex).rg;
+
+    yuv += offset;
+    Output.r = dot(yuv, Rcoeff);
+    Output.g = dot(yuv, Gcoeff);
+    Output.b = dot(yuv, Bcoeff);
+    Output.a = 1.0f;
+
+    return Output * input.color;
+}
\ No newline at end of file
diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT709.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT709.hlsl
new file mode 100644
index 000000000000..81d409c94eb2
--- /dev/null
+++ b/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT709.hlsl
@@ -0,0 +1,43 @@
+Texture2D theTextureY : register(t0);
+Texture2D theTextureUV : register(t1);
+SamplerState theSampler : register(s0);
+
+struct PixelShaderInput
+{
+    float4 pos : SV_POSITION;
+    float2 tex : TEXCOORD0;
+    float4 color : COLOR0;
+};
+
+#define NVRS \
+    "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
+    "            DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
+    "            DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
+    "            DENY_HULL_SHADER_ROOT_ACCESS )," \
+    "RootConstants(num32BitConstants=32, b0),"\
+    "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )"
+
+[RootSignature(NVRS)]
+float4 main(PixelShaderInput input) : SV_TARGET
+{
+    const float3 offset = {-0.0627451017, -0.501960814, -0.501960814};
+    const float3 Rcoeff = {1.1644,  0.0000,  1.7927};
+    const float3 Gcoeff = {1.1644, -0.2132, -0.5329};
+    const float3 Bcoeff = {1.1644,  2.1124,  0.0000};
+
+    float4 Output;
+
+    float3 yuv;
+    yuv.x = theTextureY.Sample(theSampler, input.tex).r;
+    yuv.yz = theTextureUV.Sample(theSampler, input.tex).rg;
+
+    yuv += offset;
+    Output.r = dot(yuv, Rcoeff);
+    Output.g = dot(yuv, Gcoeff);
+    Output.b = dot(yuv, Bcoeff);
+    Output.a = 1.0f;
+
+    return Output * input.color;
+}
\ No newline at end of file
diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV12_JPEG.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV12_JPEG.hlsl
new file mode 100644
index 000000000000..494bce5192d3
--- /dev/null
+++ b/VisualC-GDK/shaders/D3D12_PixelShader_NV12_JPEG.hlsl
@@ -0,0 +1,43 @@
+Texture2D theTextureY : register(t0);
+Texture2D theTextureUV : register(t1);
+SamplerState theSampler : register(s0);
+
+struct PixelShaderInput
+{
+    float4 pos : SV_POSITION;
+    float2 tex : TEXCOORD0;
+    float4 color : COLOR0;
+};
+
+#define NVRS \
+    "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
+    "            DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
+    "            DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
+    "            DENY_HULL_SHADER_ROOT_ACCESS )," \
+    "RootConstants(num32BitConstants=32, b0),"\
+    "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )"
+
+[RootSignature(NVRS)]
+float4 main(PixelShaderInput input) : SV_TARGET
+{
+    const float3 offset = {0.0, -0.501960814, -0.501960814};
+    const float3 Rcoeff = {1.0000,  0.0000,  1.4020};
+    const float3 Gcoeff = {1.0000, -0.3441, -0.7141};
+    const float3 Bcoeff = {1.0000,  1.7720,  0.0000};
+
+    float4 Output;
+
+    float3 yuv;
+    yuv.x = theTextureY.Sample(theSampler, input.tex).r;
+    yuv.yz = theTextureUV.Sample(theSampler, input.tex).rg;
+
+    yuv += offset;
+    Output.r = dot(yuv, Rcoeff);
+    Output.g = dot(yuv, Gcoeff);
+    Output.b = dot(yuv, Bcoeff);
+    Output.a = 1.0f;
+
+    return Output * input.color;
+}
\ No newline at end of file
diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT601.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT601.hlsl
new file mode 100644
index 000000000000..794c763728af
--- /dev/null
+++ b/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT601.hlsl
@@ -0,0 +1,43 @@
+Texture2D theTextureY : register(t0);
+Texture2D theTextureUV : register(t1);
+SamplerState theSampler : register(s0);
+
+struct PixelShaderInput
+{
+    float4 pos : SV_POSITION;
+    float2 tex : TEXCOORD0;
+    float4 color : COLOR0;
+};
+
+#define NVRS \
+    "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
+    "            DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
+    "            DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
+    "            DENY_HULL_SHADER_ROOT_ACCESS )," \
+    "RootConstants(num32BitConstants=32, b0),"\
+    "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )"
+
+[RootSignature(NVRS)]
+float4 main(PixelShaderInput input) : SV_TARGET
+{
+    const float3 offset = {-0.0627451017, -0.501960814, -0.501960814};
+    const float3 Rcoeff = {1.1644,  0.0000,  1.5960};
+    const float3 Gcoeff = {1.1644, -0.3918, -0.8130};
+    const float3 Bcoeff = {1.1644,  2.0172,  0.0000};
+
+    float4 Output;
+
+    float3 yuv;
+    yuv.x = theTextureY.Sample(theSampler, input.tex).r;
+    yuv.yz = theTextureUV.Sample(theSampler, input.tex).gr;
+
+    yuv += offset;
+    Output.r = dot(yuv, Rcoeff);
+    Output.g = dot(yuv, Gcoeff);
+    Output.b = dot(yuv, Bcoeff);
+    Output.a = 1.0f;
+
+    return Output * input.color;
+}
\ No newline at end of file
diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT709.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT709.hlsl
new file mode 100644
index 000000000000..f5b9522c0f8c
--- /dev/null
+++ b/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT709.hlsl
@@ -0,0 +1,43 @@
+Texture2D theTextureY : register(t0);
+Texture2D theTextureUV : register(t1);
+SamplerState theSampler : register(s0);
+
+struct PixelShaderInput
+{
+    float4 pos : SV_POSITION;
+    float2 tex : TEXCOORD0;
+    float4 color : COLOR0;
+};
+
+#define NVRS \
+    "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
+    "            DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
+    "            DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
+    "            DENY_HULL_SHADER_ROOT_ACCESS )," \
+    "RootConstants(num32BitConstants=32, b0),"\
+    "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )"
+
+[RootSignature(NVRS)]
+float4 main(PixelShaderInput input) : SV_TARGET
+{
+    const float3 offset = {-0.0627451017, -0.501960814, -0.501960814};
+    const float3 Rcoeff = {1.1644,  0.0000,  1.7927};
+    const float3 Gcoeff = {1.1644, -0.2132, -0.5329};
+    const float3 Bcoeff = {1.1644,  2.1124,  0.0000};
+
+    float4 Output;
+
+    float3 yuv;
+    yuv.x = theTextureY.Sample(theSampler, input.tex).r;
+    yuv.yz = theTextureUV.Sample(theSampler, input.tex).gr;
+
+    yuv += offset;
+    Output.r = dot(yuv, Rcoeff);
+    Output.g = dot(yuv, Gcoeff);
+    Output.b = dot(yuv, Bcoeff);
+    Output.a = 1.0f;
+
+    return Output * input.color;
+}
\ No newline at end of file
diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV21_JPEG.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV21_JPEG.hlsl
new file mode 100644
index 000000000000..1b467b480369
--- /dev/null
+++ b/VisualC-GDK/shaders/D3D12_PixelShader_NV21_JPEG.hlsl
@@ -0,0 +1,43 @@
+Texture2D theTextureY : register(t0);
+Texture2D theTextureUV : register(t1);
+SamplerState theSampler : register(s0);
+
+struct PixelShaderInput
+{
+    float4 pos : SV_POSITION;
+    float2 tex : TEXCOORD0;
+    float4 color : COLOR0;
+};
+
+#define NVRS \
+    "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
+    "            DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
+    "            DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
+    "            DENY_HULL_SHADER_ROOT_ACCESS )," \
+    "RootConstants(num32BitConstants=32, b0),"\
+    "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )"
+
+[RootSignature(NVRS)]
+float4 main(PixelShaderInput input) : SV_TARGET
+{
+    const float3 offset = {0.0, -0.501960814, -0.501960814};
+    const float3 Rcoeff = {1.0000,  0.0000,  1.4020};
+    const float3 Gcoeff = {1.0000, -0.3441, -0.7141};
+    const float3 Bcoeff = {1.0000,  1.7720,  0.0000};
+
+    float4 Output;
+
+    float3 yuv;
+    yuv.x = theTextureY.Sample(theSampler, input.tex).r;
+    yuv.yz = theTextureUV.Sample(theSampler, input.tex).gr;
+
+    yuv += offset;
+    Output.r = dot(yuv, Rcoeff);
+    Output.g = dot(yuv, Gcoeff);
+    Output.b = dot(yuv, Bcoeff);
+    Output.a = 1.0f;
+
+    return Output * input.color;
+}
\ No newline at end of file
diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_Textures.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_Textures.hlsl
new file mode 100644
index 000000000000..0dcdf89c69ba
--- /dev/null
+++ b/VisualC-GDK/shaders/D3D12_PixelShader_Textures.hlsl
@@ -0,0 +1,24 @@
+Texture2D theTexture : register(t0);
+SamplerState theSampler : register(s0);
+
+struct PixelShaderInput
+{
+    float4 pos : SV_POSITION;
+    float2 tex : TEXCOORD0;
+    float4 color : COLOR0;
+};
+
+#define TextureRS \
+    "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
+    "            DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
+    "            DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
+    "            DENY_HULL_SHADER_ROOT_ACCESS )," \
+    "RootConstants(num32BitConstants=32, b0),"\
+    "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )"
+
+[RootSignature(TextureRS)]
+float4 main(PixelShaderInput input) : SV_TARGET
+{
+    return theTexture.Sample(theSampler, input.tex) * input.color;
+}
\ No newline at end of file
diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT601.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT601.hlsl
new file mode 100644
index 000000000000..09e58943a7f8
--- /dev/null
+++ b/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT601.hlsl
@@ -0,0 +1,46 @@
+Texture2D theTextureY : register(t0);
+Texture2D theTextureU : register(t1);
+Texture2D theTextureV : register(t2);
+SamplerState theSampler : register(s0);
+
+struct PixelShaderInput
+{
+    float4 pos : SV_POSITION;
+    float2 tex : TEXCOORD0;
+    float4 color : COLOR0;
+};
+
+#define YUVRS \
+    "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
+    "            DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
+    "            DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
+    "            DENY_HULL_SHADER_ROOT_ACCESS )," \
+    "RootConstants(num32BitConstants=32, b0),"\
+    "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( SRV(t2), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )"
+
+[RootSignature(YUVRS)]
+float4 main(PixelShaderInput input) : SV_TARGET
+{
+    const float3 offset = {-0.0627451017, -0.501960814, -0.501960814};
+    const float3 Rcoeff = {1.1644,  0.0000,  1.5960};
+    const float3 Gcoeff = {1.1644, -0.3918, -0.8130};
+    const float3 Bcoeff = {1.1644,  2.0172,  0.0000};
+
+    float4 Output;
+
+    float3 yuv;
+    yuv.x = theTextureY.Sample(theSampler, input.tex).r;
+    yuv.y = theTextureU.Sample(theSampler, input.tex).r;
+    yuv.z = theTextureV.Sample(theSampler, input.tex).r;
+
+    yuv += offset;
+    Output.r = dot(yuv, Rcoeff);
+    Output.g = dot(yuv, Gcoeff);
+    Output.b = dot(yuv, Bcoeff);
+    Output.a = 1.0f;
+
+    return Output * input.color;
+}
\ No newline at end of file
diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT709.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT709.hlsl
new file mode 100644
index 000000000000..f5aa0cd7e4ab
--- /dev/null
+++ b/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT709.hlsl
@@ -0,0 +1,46 @@
+Texture2D theTextureY : register(t0);
+Texture2D theTextureU : register(t1);
+Texture2D theTextureV : register(t2);
+SamplerState theSampler : register(s0);
+
+struct PixelShaderInput
+{
+    float4 pos : SV_POSITION;
+    float2 tex : TEXCOORD0;
+    float4 color : COLOR0;
+};
+
+#define YUVRS \
+    "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
+    "            DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
+    "            DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
+    "            DENY_HULL_SHADER_ROOT_ACCESS )," \
+    "RootConstants(num32BitConstants=32, b0),"\
+    "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( SRV(t2), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )"
+
+[RootSignature(YUVRS)]
+float4 main(PixelShaderInput input) : SV_TARGET
+{
+    const float3 offset = {-0.0627451017, -0.501960814, -0.501960814};
+    const float3 Rcoeff = {1.1644,  0.0000,  1.7927};
+    const float3 Gcoeff = {1.1644, -0.2132, -0.5329};
+    const float3 Bcoeff = {1.1644,  2.1124,  0.0000};
+
+    float4 Output;
+
+    float3 yuv;
+    yuv.x = theTextureY.Sample(theSampler, input.tex).r;
+    yuv.y = theTextureU.Sample(theSampler, input.tex).r;
+    yuv.z = theTextureV.Sample(theSampler, input.tex).r;
+
+    yuv += offset;
+    Output.r = dot(yuv, Rcoeff);
+    Output.g = dot(yuv, Gcoeff);
+    Output.b = dot(yuv, Bcoeff);
+    Output.a = 1.0f;
+
+    return Output * input.color;
+}
\ No newline at end of file
diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_YUV_JPEG.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_YUV_JPEG.hlsl
new file mode 100644
index 000000000000..84d09b8bff03
--- /dev/null
+++ b/VisualC-GDK/shaders/D3D12_PixelShader_YUV_JPEG.hlsl
@@ -0,0 +1,46 @@
+Texture2D theTextureY : register(t0);
+Texture2D theTextureU : register(t1);
+Texture2D theTextureV : register(t2);
+SamplerState theSampler : register(s0);
+
+struct PixelShaderInput
+{
+    float4 pos : SV_POSITION;
+    float2 tex : TEXCOORD0;
+    float4 color : COLOR0;
+};
+
+#define YUVRS \
+    "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
+    "            DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
+    "            DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
+    "            DENY_HULL_SHADER_ROOT_ACCESS )," \
+    "RootConstants(num32BitConstants=32, b0),"\
+    "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( SRV(t2), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )"
+
+[RootSignature(YUVRS)]
+float4 main(PixelShaderInput input) : SV_TARGET
+{
+    const float3 offset = {0.0, -0.501960814, -0.501960814};
+    const float3 Rcoeff = {1.0000,  0.0000,  1.4020};
+    const float3 Gcoeff = {1.0000, -0.3441, -0.7141};
+    const float3 Bcoeff = {1.0000,  1.7720,  0.0000};
+
+    float4 Output;
+
+    float3 yuv;
+    yuv.x = theTextureY.Sample(theSampler, input.tex).r;
+    yuv.y = theTextureU.Sample(theSampler, input.tex).r;
+    yuv.z = theTextureV.Sample(theSampler, input.tex).r;
+
+    yuv += offset;
+    Output.r = dot(yuv, Rcoeff);
+    Output.g = dot(yuv, Gcoeff);
+    Output.b = dot(yuv, Bcoeff);
+    Output.a = 1.0f;
+
+    return Output * input.color;
+}
\ No newline at end of file
diff --git a/VisualC-GDK/shaders/D3D12_VertexShader.hlsl b/VisualC-GDK/shaders/D3D12_VertexShader.hlsl
new file mode 100644
index 000000000000..e10b488925ef
--- /dev/null
+++ b/VisualC-GDK/shaders/D3D12_VertexShader.hlsl
@@ -0,0 +1,95 @@
+#pragma pack_matrix( row_major )
+
+struct VertexShaderConstants
+{
+    matrix model;
+    matrix projectionAndView;
+};
+ConstantBuffer<VertexShaderConstants> Constants : register(b0);
+
+struct VertexShaderInput
+{
+    float3 pos : POSITION;
+    float2 tex : TEXCOORD0;
+    float4 color : COLOR0;
+};
+
+struct VertexShaderOutput
+{
+    float4 pos : SV_POSITION;
+    float2 tex : TEXCOORD0;
+    float4 color : COLOR0;
+};
+
+#define ColorRS \
+    "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
+    "DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
+    "DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
+    "DENY_HULL_SHADER_ROOT_ACCESS )," \
+    "RootConstants(num32BitConstants=32, b0)"
+
+#define TextureRS \
+    "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
+    "            DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
+    "            DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
+    "            DENY_HULL_SHADER_ROOT_ACCESS )," \
+    "RootConstants(num32BitConstants=32, b0),"\
+    "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )"
+
+#define YUVRS \
+    "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
+    "            DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
+    "            DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
+    "            DENY_HULL_SHADER_ROOT_ACCESS )," \
+    "RootConstants(num32BitConstants=32, b0),"\
+    "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( SRV(t2), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )"
+
+#define NVRS \
+    "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
+    "            DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
+    "            DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
+    "            DENY_HULL_SHADER_ROOT_ACCESS )," \
+    "RootConstants(num32BitConstants=32, b0),"\
+    "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )"
+
+[RootSignature(ColorRS)]
+VertexShaderOutput mainColor(VertexShaderInput input)
+{
+    VertexShaderOutput output;
+    float4 pos = float4(input.pos, 1.0f);
+
+    // Transform the vertex position into projected space.
+    pos = mul(pos, Constants.model);
+    pos = mul(pos, Constants.projectionAndView);
+    output.pos = pos;
+
+    // Pass through texture coordinates and color values without transformation
+    output.tex = input.tex;
+    output.color = input.color;
+
+    return output;
+}
+
+[RootSignature(TextureRS)]
+VertexShaderOutput mainTexture(VertexShaderInput input)
+{
+    return mainColor(input);
+}
+
+[RootSignature(YUVRS)]
+VertexShaderOutput mainYUV(VertexShaderInput input)
+{
+    return mainColor(input);
+}
+
+[RootSignature(NVRS)]
+VertexShaderOutput mainNV(VertexShaderInput input)
+{
+    return mainColor(input);
+}
\ No newline at end of file
diff --git a/VisualC-GDK/shaders/buildshaders.bat b/VisualC-GDK/shaders/buildshaders.bat
new file mode 100644
index 000000000000..4447b5e2f826
--- /dev/null
+++ b/VisualC-GDK/shaders/buildshaders.bat
@@ -0,0 +1,35 @@
+if %2.==one. goto setxboxone
+rem Xbox Series compile
+set XBOXDXC="%GameDKLatest%\GXDK\bin\Scarlett\DXC.exe"
+set SUFFIX=_Series.h
+goto startbuild
+
+:setxboxone
+set XBOXDXC="%GameDKLatest%\GXDK\bin\XboxOne\DXC.exe"
+set SUFFIX=_One.h
+
+:startbuild
+echo Building with %XBOXDXC%
+cd "%1\shaders"
+rem Root Signatures
+%XBOXDXC% -E ColorRS -T rootsig_1_1 -rootsig-define ColorRS -Fh D3D12_RootSig_Color%SUFFIX% -Vn D3D12_RootSig_Color D3D12_VertexShader.hlsl
+%XBOXDXC% -E TextureRS -T rootsig_1_1 -rootsig-define TextureRS -Fh D3D12_RootSig_Texture%SUFFIX% -Vn D3D12_RootSig_Texture D3D12_VertexShader.hlsl
+%XBOXDXC% -E YUVRS -T rootsig_1_1 -rootsig-define YUVRS -Fh D3D12_RootSig_YUV%SUFFIX% -Vn D3D12_RootSig_YUV D3D12_VertexShader.hlsl
+%XBOXDXC% -E NVRS -T rootsig_1_1 -rootsig-define NVRS -Fh D3D12_RootSig_NV%SUFFIX% -Vn D3D12_RootSig_NV D3D12_VertexShader.hlsl
+rem Vertex Shaders
+%XBOXDXC% -E mainColor -T vs_6_0 -Fh D3D12_VertexShader_Color%SUFFIX% -Vn D3D12_VertexShader_Color D3D12_VertexShader.hlsl
+%XBOXDXC% -E mainTexture -T vs_6_0 -Fh D3D12_VertexShader_Texture%SUFFIX% -Vn D3D12_VertexShader_Texture D3D12_VertexShader.hlsl
+%XBOXDXC% -E mainNV -T vs_6_0 -Fh D3D12_VertexShader_NV%SUFFIX% -Vn D3D12_VertexShader_NV D3D12_VertexShader.hlsl
+%XBOXDXC% -E mainYUV -T vs_6_0 -Fh D3D12_VertexShader_YUV%SUFFIX% -Vn D3D12_VertexShader_YUV D3D12_VertexShader.hlsl
+rem Pixel Shaders
+%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_Colors%SUFFIX% -Vn D3D12_PixelShader_Colors D3D12_PixelShader_Colors.hlsl
+%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV12_BT601%SUFFIX% -Vn D3D12_PixelShader_NV12_BT601 D3D12_PixelShader_NV12_BT601.hlsl
+%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV12_BT709%SUFFIX% -Vn D3D12_PixelShader_NV12_BT709 D3D12_PixelShader_NV12_BT709.hlsl
+%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV12_JPEG%SUFFIX% -Vn D3D12_PixelShader_NV12_JPEG D3D12_PixelShader_NV12_JPEG.hlsl
+%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV21_BT601%SUFFIX% -Vn D3D12_PixelShader_NV21_BT601 D3D12_PixelShader_NV21_BT601.hlsl
+%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV21_BT709%SUFFIX% -Vn D3D12_PixelShader_NV21_BT709 D3D12_PixelShader_NV21_BT709.hlsl
+%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV21_JPEG%SUFFIX% -Vn D3D12_PixelShader_NV21_JPEG D3D12_PixelShader_NV21_JPEG.hlsl
+%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_Textures%SUFFIX% -Vn D3D12_PixelShader_Textures D3D12_PixelShader_Textures.hlsl
+%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_YUV_BT601%SUFFIX% -Vn D3D12_PixelShader_YUV_BT601 D3D12_PixelShader_YUV_BT601.hlsl
+%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_YUV_BT709%SUFFIX% -Vn D3D12_PixelShader_YUV_BT709 D3D12_PixelShader_YUV_BT709.hlsl
+%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_YUV_JPEG%SUFFIX% -Vn D3D12_PixelShader_YUV_JPEG D3D12_PixelShader_YUV_JPEG.hlsl
\ No newline at end of file
diff --git a/docs/README-gdk.md b/docs/README-gdk.md
index 248a418e792a..6718a6177293 100644
--- a/docs/README-gdk.md
+++ b/docs/README-gdk.md
@@ -3,7 +3,7 @@ GDK
 
 This port allows SDL applications to run via Microsoft's Game Development Kit (GDK).
 
-Windows (GDK) and  Xbox One/Xbox Series (GDKX) are supported. Although most of the Xbox code is included in the public SDL source code, NDA access is required for a small number of source files. If you have access to GDKX, these required Xbox files are posted on the GDK forums [here](https://forums.xboxlive.com/questions/130003/).
+Windows (GDK) and  Xbox One/Xbox Series (GDKX) are both supported and all the required code is included in this public SDL release. However, only licensed Xbox developers have access to the GDKX libraries which will allow you to build the Xbox targets.
 
 
 Requirements
@@ -11,6 +11,7 @@ Requirements
 
 * Microsoft Visual Studio 2022 (in theory, it should also work in 2017 or 2019, but this has not been tested)
 * Microsoft GDK June 2022 or newer (public release [here](https://github.com/microsoft/GDK/releases/tag/June_2022))
+* For Xbox, you will need the corresponding GDKX version (licensed developers only)
 * To publish a package or successfully authenticate a user, you will need to create an app id/configure services in Partner Center. However, for local testing purposes (without authenticating on Xbox Live), the identifiers used by the GDK test programs in the included solution will work.
 
 
@@ -33,7 +34,7 @@ The Windows GDK port supports the full set of Win32 APIs, renderers, controllers
   * Call `SDL_GDKGetDefaultUser` to get the default XUserHandle pointer.
   * `SDL_GetPrefPath` still works, but only for single-player titles.
 
-These functions mostly wrap around async APIs, and thus should be treated as synchronous alternatives. Also note that the single-player functions return on any OS errors, so be sure to validate the return values!
+  These func

(Patch may be truncated, please check the link at the top of this post.)