A game about forced loneliness, made by TACStudios
1using System;
2using Unity.Mathematics;
3using UnityEngine.Rendering;
4
5#if ENABLE_VR && ENABLE_XR_MODULE
6using UnityEngine.XR;
7#endif
8
9namespace UnityEngine.Experimental.Rendering
10{
11 internal static class XRMirrorView
12 {
13 static readonly MaterialPropertyBlock s_MirrorViewMaterialProperty = new MaterialPropertyBlock();
14 static readonly ProfilingSampler k_MirrorViewProfilingSampler = new ProfilingSampler("XR Mirror View");
15
16 static readonly int k_SourceTex = Shader.PropertyToID("_SourceTex");
17 static readonly int k_SourceTexArraySlice = Shader.PropertyToID("_SourceTexArraySlice");
18 static readonly int k_ScaleBias = Shader.PropertyToID("_ScaleBias");
19 static readonly int k_ScaleBiasRt = Shader.PropertyToID("_ScaleBiasRt");
20 static readonly int k_SRGBRead = Shader.PropertyToID("_SRGBRead");
21 static readonly int k_SRGBWrite = Shader.PropertyToID("_SRGBWrite");
22 static readonly int k_MaxNits = Shader.PropertyToID("_MaxNits");
23 static readonly int k_SourceMaxNits = Shader.PropertyToID("_SourceMaxNits");
24 static readonly int k_SourceHDREncoding = Shader.PropertyToID("_SourceHDREncoding");
25 static readonly int k_ColorTransform = Shader.PropertyToID("_ColorTransform");
26
27#if ENABLE_VR && ENABLE_XR_MODULE
28 internal static void RenderMirrorView(CommandBuffer cmd, Camera camera, Material mat, XRDisplaySubsystem display)
29 {
30 // XRTODO : remove this check when the Quest plugin is fixed
31 if (Application.platform == RuntimePlatform.Android && !XRGraphicsAutomatedTests.running)
32 return;
33
34 if (display == null || !display.running || mat == null)
35 return;
36
37 int mirrorBlitMode = display.GetPreferredMirrorBlitMode();
38 if (display.GetMirrorViewBlitDesc(null, out var blitDesc, mirrorBlitMode))
39 {
40 using (new ProfilingScope(cmd, k_MirrorViewProfilingSampler))
41 {
42 cmd.SetRenderTarget(camera.targetTexture != null ? camera.targetTexture : new RenderTargetIdentifier(BuiltinRenderTextureType.CameraTarget));
43
44 if (blitDesc.nativeBlitAvailable)
45 {
46 display.AddGraphicsThreadMirrorViewBlit(cmd, blitDesc.nativeBlitInvalidStates, mirrorBlitMode);
47 }
48 else
49 {
50 for (int i = 0; i < blitDesc.blitParamsCount; ++i)
51 {
52 blitDesc.GetBlitParameter(i, out var blitParam);
53
54 Vector4 scaleBias = new Vector4(blitParam.srcRect.width, blitParam.srcRect.height, blitParam.srcRect.x, blitParam.srcRect.y);
55 Vector4 scaleBiasRt = new Vector4(blitParam.destRect.width, blitParam.destRect.height, blitParam.destRect.x, blitParam.destRect.y);
56
57 // Deal with y-flip
58 if (camera.targetTexture != null || camera.cameraType == CameraType.SceneView || camera.cameraType == CameraType.Preview)
59 {
60 scaleBias.y = -scaleBias.y;
61 scaleBias.w += blitParam.srcRect.height;
62 }
63
64 HDROutputSettings mainDisplayHdrSettings = HDROutputSettings.main;
65
66 // If we are writing to a HDR surface or reading from one we use the conversion shader to handle both
67 if (blitParam.srcHdrEncoded || mainDisplayHdrSettings.active)
68 {
69 ColorGamut mainDisplayColorGamut = mainDisplayHdrSettings.active ? mainDisplayHdrSettings.displayColorGamut
70 : ColorGamut.sRGB;
71 ColorGamut xrDisplayColorGamut = blitParam.srcHdrEncoded ? blitParam.srcHdrColorGamut
72 : ColorGamut.sRGB;
73
74 ColorPrimaries mainDisplayColorPrimaries = ColorGamutUtility.GetColorPrimaries(mainDisplayColorGamut);
75 ColorPrimaries xrDisplayColorPrimaries = ColorGamutUtility.GetColorPrimaries(xrDisplayColorGamut);
76
77 // Use the material? And use the passes?
78 HDROutputUtils.ConfigureHDROutput(s_MirrorViewMaterialProperty, mainDisplayColorGamut);
79 HDROutputUtils.ConfigureHDROutput(mat, HDROutputUtils.Operation.ColorConversion | HDROutputUtils.Operation.ColorEncoding);
80 int sourceHdrEncoding;
81 HDROutputUtils.GetColorEncodingForGamut(xrDisplayColorGamut, out sourceHdrEncoding);
82 s_MirrorViewMaterialProperty.SetInteger(k_SourceHDREncoding, sourceHdrEncoding);
83
84 float3x3 sourceToRec2020 = float3x3.identity;
85 if (xrDisplayColorPrimaries == ColorPrimaries.Rec709)
86 sourceToRec2020 = ColorSpaceUtils.Rec709ToRec2020Mat;
87 else if (xrDisplayColorPrimaries == ColorPrimaries.P3)
88 sourceToRec2020 = ColorSpaceUtils.P3D65ToRec2020Mat;
89
90 float3x3 rec2020ToDest = float3x3.identity;
91 if (mainDisplayColorPrimaries == ColorPrimaries.Rec709)
92 rec2020ToDest = ColorSpaceUtils.Rec2020ToRec709Mat;
93 else if (mainDisplayColorPrimaries == ColorPrimaries.P3)
94 rec2020ToDest = ColorSpaceUtils.Rec2020ToP3D65Mat;
95
96 // Quicker to go straight to a Matrix4x4 and multiply there? Or to store these as Matrix4x4 instead due to Unity missing a 3x3 type?
97 float3x3 colorTransform = math.mul(sourceToRec2020, rec2020ToDest);
98 Matrix4x4 m = new Matrix4x4((Vector4) new float4(colorTransform.c0, 0.0f),
99 (Vector4) new float4(colorTransform.c1, 0.0f), (Vector4) new float4(colorTransform.c2, 0.0f),
100 new Vector4(0.0f, 0.0f, 0.0f, 0.0f));
101 s_MirrorViewMaterialProperty.SetMatrix(k_ColorTransform, m);
102
103 s_MirrorViewMaterialProperty.SetFloat(k_MaxNits, mainDisplayHdrSettings.active ? mainDisplayHdrSettings.maxToneMapLuminance : 160.0f);
104 s_MirrorViewMaterialProperty.SetFloat(k_SourceMaxNits, blitParam.srcHdrEncoded ? blitParam.srcHdrMaxLuminance : 160.0f);
105 }
106
107 // For 8888 formats we always gamma correct eye textures : use explicit sRGB read in shader only if the source is not using sRGB format.
108 bool manualSRGBRead = !blitParam.srcTex.sRGB &&
109 (blitParam.srcTex.graphicsFormat == GraphicsFormat.R8G8B8A8_UNorm ||
110 blitParam.srcTex.graphicsFormat == GraphicsFormat.B8G8R8A8_UNorm);
111 s_MirrorViewMaterialProperty.SetFloat(k_SRGBRead, manualSRGBRead ? 1.0f : 0.0f);
112
113 // Perform explicit sRGB write in shader if color space is gamma
114 s_MirrorViewMaterialProperty.SetFloat(k_SRGBWrite, (QualitySettings.activeColorSpace == ColorSpace.Linear) ? 0.0f : 1.0f);
115
116 s_MirrorViewMaterialProperty.SetTexture(k_SourceTex, blitParam.srcTex);
117 s_MirrorViewMaterialProperty.SetVector(k_ScaleBias, scaleBias);
118 s_MirrorViewMaterialProperty.SetVector(k_ScaleBiasRt, scaleBiasRt);
119 s_MirrorViewMaterialProperty.SetFloat(k_SourceTexArraySlice, blitParam.srcTexArraySlice);
120
121 if (XRSystem.foveatedRenderingCaps.HasFlag(FoveatedRenderingCaps.NonUniformRaster) && blitParam.foveatedRenderingInfo != IntPtr.Zero)
122 {
123 cmd.ConfigureFoveatedRendering(blitParam.foveatedRenderingInfo);
124 cmd.EnableShaderKeyword("_FOVEATED_RENDERING_NON_UNIFORM_RASTER");
125 }
126
127 if (blitParam.srcTex.dimension != TextureDimension.Tex2DArray)
128 cmd.EnableShaderKeyword("DISABLE_TEXTURE2D_X_ARRAY");
129
130 cmd.DrawProcedural(Matrix4x4.identity, mat, 0, MeshTopology.Quads, 4, 1, s_MirrorViewMaterialProperty);
131
132 // Set back the XR texture for regular XR calls
133 if (blitParam.srcTex.dimension != TextureDimension.Tex2DArray && TextureXR.useTexArray)
134 cmd.DisableShaderKeyword("DISABLE_TEXTURE2D_X_ARRAY");
135 }
136 }
137 }
138 }
139
140 if (XRSystem.foveatedRenderingCaps.HasFlag(FoveatedRenderingCaps.NonUniformRaster))
141 {
142 cmd.DisableShaderKeyword("_FOVEATED_RENDERING_NON_UNIFORM_RASTER");
143 cmd.ConfigureFoveatedRendering(IntPtr.Zero);
144 }
145 }
146
147#endif
148 }
149}