2 using System
.Collections
.Generic
;
3 using UnityEngine
.Assertions
;
4 using UnityEngine
.Rendering
;
6 namespace UnityEngine
.Experimental
.Rendering
8 public delegate Vector2Int
ScaleFunc(Vector2Int size
);
10 public partial class RTHandleSystem
: IDisposable
12 public enum ResizeMode
18 // Parameters for auto-scaled Render Textures
19 bool m_ScaledRTSupportsMSAA
= false;
20 MSAASamples m_ScaledRTCurrentMSAASamples
= MSAASamples
.None
;
21 HashSet
<RTHandle
> m_AutoSizedRTs
;
22 RTHandle
[] m_AutoSizedRTsArray
; // For fast iteration
23 HashSet
<RTHandle
> m_ResizeOnDemandRTs
;
28 public RTHandleSystem()
30 m_AutoSizedRTs
= new HashSet
<RTHandle
>();
31 m_ResizeOnDemandRTs
= new HashSet
<RTHandle
>();
41 // Call this once to set the initial size and allow msaa targets or not.
42 public void Initialize(int width
, int height
, bool scaledRTsupportsMSAA
, MSAASamples scaledRTMSAASamples
)
44 Debug
.Assert(m_AutoSizedRTs
.Count
== 0, "RTHandle.Initialize should only be called once before allocating any Render Texture.");
47 m_MaxHeights
= height
;
49 m_ScaledRTSupportsMSAA
= scaledRTsupportsMSAA
;
50 m_ScaledRTCurrentMSAASamples
= scaledRTMSAASamples
;
53 public void Release(RTHandle rth
)
57 Assert
.AreEqual(this, rth
.m_Owner
);
62 public void SetReferenceSize(int width
, int height
, MSAASamples msaaSamples
)
64 width
= Mathf
.Max(width
, 1);
65 height
= Mathf
.Max(height
, 1);
67 bool sizeChanged
= width
> GetMaxWidth() || height
> GetMaxHeight();
68 bool msaaSamplesChanged
= (msaaSamples
!= m_ScaledRTCurrentMSAASamples
);
70 if (sizeChanged
|| msaaSamplesChanged
)
72 Resize(width
, height
, msaaSamples
, sizeChanged
, msaaSamplesChanged
);
76 public void ResetReferenceSize(int width
, int height
, MSAASamples msaaSamples
)
78 width
= Mathf
.Max(width
, 1);
79 height
= Mathf
.Max(height
, 1);
81 bool sizeChanged
= width
> GetMaxWidth() || height
> GetMaxHeight();
82 bool msaaSamplesChanged
= (msaaSamples
!= m_ScaledRTCurrentMSAASamples
);
84 if (sizeChanged
|| msaaSamplesChanged
)
86 Resize(width
, height
, msaaSamples
, sizeChanged
, msaaSamplesChanged
);
90 public void SwitchResizeMode(RTHandle rth
, ResizeMode mode
)
94 case ResizeMode
.OnDemand
:
95 m_AutoSizedRTs
.Remove(rth
);
96 m_ResizeOnDemandRTs
.Add(rth
);
99 // Resize now so it is consistent with other auto resize RTHs
100 if (m_ResizeOnDemandRTs
.Contains(rth
))
102 m_ResizeOnDemandRTs
.Remove(rth
);
103 m_AutoSizedRTs
.Add(rth
);
108 public void DemandResize(RTHandle rth
)
110 Assert
.IsTrue(m_ResizeOnDemandRTs
.Contains(rth
), "The RTHandle is not an resize on demand handle in this RTHandleSystem. Please call SwitchToResizeOnDemand(rth, true) before resizing on demand.");
112 // Grab the render texture
114 rth
.referenceSize
= new Vector2Int(m_MaxWidths
, m_MaxHeights
);
115 var scaledSize
= rth
.GetScaledSize(rth
.referenceSize
);
116 scaledSize
= Vector2Int
.Max(Vector2Int
.one
, scaledSize
);
118 // Did the size change?
119 var sizeChanged
= rt
.width
!= scaledSize
.x
|| rt
.height
!= scaledSize
.y
;
120 // If this is an MSAA texture, did the sample count change?
121 var msaaSampleChanged
= rth
.m_EnableMSAA
&& rt
.antiAliasing
!= (int)m_ScaledRTCurrentMSAASamples
;
123 if (sizeChanged
|| msaaSampleChanged
)
125 // Free this render texture
128 // Update the antialiasing count
129 if (rth
.m_EnableMSAA
)
130 rt
.antiAliasing
= (int)m_ScaledRTCurrentMSAASamples
;
133 rt
.width
= scaledSize
.x
;
134 rt
.height
= scaledSize
.y
;
136 // Generate a new name
137 rt
.name
= CoreUtils
.GetRenderTargetAutoName(
144 enableMSAA: rth
.m_EnableMSAA
,
145 msaaSamples: m_ScaledRTCurrentMSAASamples
148 // Create the new texture
153 public int GetMaxWidth() { return m_MaxWidths; }
154 public int GetMaxHeight() { return m_MaxHeights; }
156 void Dispose(bool disposing
)
160 Array
.Resize(ref m_AutoSizedRTsArray
, m_AutoSizedRTs
.Count
);
161 m_AutoSizedRTs
.CopyTo(m_AutoSizedRTsArray
);
162 for (int i
= 0, c
= m_AutoSizedRTsArray
.Length
; i
< c
; ++i
)
164 var rt
= m_AutoSizedRTsArray
[i
];
167 m_AutoSizedRTs
.Clear();
169 Array
.Resize(ref m_AutoSizedRTsArray
, m_ResizeOnDemandRTs
.Count
);
170 m_ResizeOnDemandRTs
.CopyTo(m_AutoSizedRTsArray
);
171 for (int i
= 0, c
= m_AutoSizedRTsArray
.Length
; i
< c
; ++i
)
173 var rt
= m_AutoSizedRTsArray
[i
];
176 m_ResizeOnDemandRTs
.Clear();
177 m_AutoSizedRTsArray
= null;
181 void Resize(int width
, int height
, MSAASamples msaaSamples
, bool sizeChanged
, bool msaaSampleChanged
)
183 m_MaxWidths
= Math
.Max(width
, m_MaxWidths
);
184 m_MaxHeights
= Math
.Max(height
, m_MaxHeights
);
185 m_ScaledRTCurrentMSAASamples
= msaaSamples
;
187 var maxSize
= new Vector2Int(m_MaxWidths
, m_MaxHeights
);
189 Array
.Resize(ref m_AutoSizedRTsArray
, m_AutoSizedRTs
.Count
);
190 m_AutoSizedRTs
.CopyTo(m_AutoSizedRTsArray
);
192 for (int i
= 0, c
= m_AutoSizedRTsArray
.Length
; i
< c
; ++i
)
194 // Grab the RT Handle
195 var rth
= m_AutoSizedRTsArray
[i
];
197 // If we are only processing MSAA sample count change, make sure this RT is an MSAA one
198 if (!sizeChanged
&& msaaSampleChanged
&& !rth
.m_EnableMSAA
)
203 // Force its new reference size
204 rth
.referenceSize
= maxSize
;
206 // Grab the render texture
207 var renderTexture
= rth
.m_RT
;
209 // Free the previous version
210 renderTexture
.Release();
212 // Get the scaled size
213 var scaledSize
= rth
.GetScaledSize(maxSize
);
215 renderTexture
.width
= Mathf
.Max(scaledSize
.x
, 1);
216 renderTexture
.height
= Mathf
.Max(scaledSize
.y
, 1);
218 // If this is a msaa texture, make sure to update its msaa count
219 if (rth
.m_EnableMSAA
)
221 renderTexture
.antiAliasing
= (int)m_ScaledRTCurrentMSAASamples
;
224 // Regenerate the name
225 renderTexture
.name
= CoreUtils
.GetRenderTargetAutoName(renderTexture
.width
, renderTexture
.height
, renderTexture
.volumeDepth
, renderTexture
.format
, rth
.m_Name
, mips
: renderTexture
.useMipMap
, enableMSAA
: rth
.m_EnableMSAA
, msaaSamples
: m_ScaledRTCurrentMSAASamples
);
227 // Create the render texture
228 renderTexture
.Create();
232 // This method wraps around regular RenderTexture creation.
233 // There is no specific logic applied to RenderTextures created this way.
234 public RTHandle
Alloc(
238 DepthBits depthBufferBits
= DepthBits
.None
,
239 RenderTextureFormat colorFormat
= RenderTextureFormat
.Default
,
240 FilterMode filterMode
= FilterMode
.Point
,
241 TextureWrapMode wrapMode
= TextureWrapMode
.Repeat
,
242 TextureDimension dimension
= TextureDimension
.Tex2D
,
244 bool enableRandomWrite
= false,
245 bool useMipMap
= false,
246 bool autoGenerateMips
= true,
248 float mipMapBias
= 0f
,
249 MSAASamples msaaSamples
= MSAASamples
.None
,
250 bool bindTextureMS
= false,
251 bool useDynamicScale
= false,
252 VRTextureUsage vrUsage
= VRTextureUsage
.None
,
253 RenderTextureMemoryless memoryless
= RenderTextureMemoryless
.None
,
257 bool enableMSAA
= msaaSamples
!= MSAASamples
.None
;
258 if (!enableMSAA
&& bindTextureMS
== true)
260 Debug
.LogWarning("RTHandle allocated without MSAA but with bindMS set to true, forcing bindMS to false.");
261 bindTextureMS
= false;
264 var rt
= new RenderTexture(width
, height
, (int)depthBufferBits
, colorFormat
, sRGB
? RenderTextureReadWrite
.sRGB
: RenderTextureReadWrite
.Linear
)
266 hideFlags
= HideFlags
.HideAndDontSave
,
267 volumeDepth
= slices
,
268 filterMode
= filterMode
,
270 dimension
= dimension
,
271 enableRandomWrite
= enableRandomWrite
,
272 useMipMap
= useMipMap
,
273 autoGenerateMips
= autoGenerateMips
,
274 anisoLevel
= anisoLevel
,
275 mipMapBias
= mipMapBias
,
276 antiAliasing
= (int)msaaSamples
,
277 bindTextureMS
= bindTextureMS
,
278 useDynamicScale
= useDynamicScale
,
280 memorylessMode
= memoryless
,
281 name
= CoreUtils
.GetRenderTargetAutoName(width
, height
, slices
, colorFormat
, name
, mips
: useMipMap
, enableMSAA
: enableMSAA
, msaaSamples
: msaaSamples
)
285 RTCategory category
= enableMSAA
? RTCategory
.MSAA
: RTCategory
.Regular
;
286 var newRT
= new RTHandle(this);
287 newRT
.SetRenderTexture(rt
, category
);
288 newRT
.useScaling
= false;
289 newRT
.m_EnableRandomWrite
= enableRandomWrite
;
290 newRT
.m_EnableMSAA
= enableMSAA
;
293 newRT
.referenceSize
= new Vector2Int(width
, height
);
298 // Next two methods are used to allocate RenderTexture that depend on the frame settings (resolution and msaa for now)
299 // RenderTextures allocated this way are meant to be defined by a scale of camera resolution (full/half/quarter resolution for example).
300 // The idea is that internally the system will scale up the size of all render texture so that it amortizes with time and not reallocate when a smaller size is required (which is what happens with TemporaryRTs).
301 // Since MSAA cannot be changed on the fly for a given RenderTexture, a separate instance will be created if the user requires it. This instance will be the one used after the next call of SetReferenceSize if MSAA is required.
302 public RTHandle
Alloc(
305 DepthBits depthBufferBits
= DepthBits
.None
,
306 RenderTextureFormat colorFormat
= RenderTextureFormat
.Default
,
307 FilterMode filterMode
= FilterMode
.Point
,
308 TextureWrapMode wrapMode
= TextureWrapMode
.Repeat
,
309 TextureDimension dimension
= TextureDimension
.Tex2D
,
311 bool enableRandomWrite
= false,
312 bool useMipMap
= false,
313 bool autoGenerateMips
= true,
315 float mipMapBias
= 0f
,
316 bool enableMSAA
= false,
317 bool bindTextureMS
= false,
318 bool useDynamicScale
= false,
319 VRTextureUsage vrUsage
= VRTextureUsage
.None
,
320 RenderTextureMemoryless memoryless
= RenderTextureMemoryless
.None
,
324 // If an MSAA target is requested, make sure the support was on
326 Debug
.Assert(m_ScaledRTSupportsMSAA
);
328 int width
= Mathf
.Max(Mathf
.RoundToInt(scaleFactor
.x
* GetMaxWidth()), 1);
329 int height
= Mathf
.Max(Mathf
.RoundToInt(scaleFactor
.y
* GetMaxHeight()), 1);
331 var rth
= AllocAutoSizedRenderTexture(width
,
353 rth
.referenceSize
= new Vector2Int(width
, height
);
355 rth
.scaleFactor
= scaleFactor
;
360 // You can provide your own scaling function for advanced scaling schemes (e.g. scaling to
361 // the next POT). The function takes a Vec2 as parameter that holds max width & height
362 // values for the current manager context and returns a Vec2 of the final size in pixels.
365 // size => new Vector2Int(size.x / 2, size.y),
369 public RTHandle
Alloc(
372 DepthBits depthBufferBits
= DepthBits
.None
,
373 RenderTextureFormat colorFormat
= RenderTextureFormat
.Default
,
374 FilterMode filterMode
= FilterMode
.Point
,
375 TextureWrapMode wrapMode
= TextureWrapMode
.Repeat
,
376 TextureDimension dimension
= TextureDimension
.Tex2D
,
378 bool enableRandomWrite
= false,
379 bool useMipMap
= false,
380 bool autoGenerateMips
= true,
382 float mipMapBias
= 0f
,
383 bool enableMSAA
= false,
384 bool bindTextureMS
= false,
385 bool useDynamicScale
= false,
386 VRTextureUsage vrUsage
= VRTextureUsage
.None
,
387 RenderTextureMemoryless memoryless
= RenderTextureMemoryless
.None
,
391 var scaleFactor
= scaleFunc(new Vector2Int(GetMaxWidth(), GetMaxHeight()));
392 int width
= Mathf
.Max(scaleFactor
.x
, 1);
393 int height
= Mathf
.Max(scaleFactor
.y
, 1);
395 var rth
= AllocAutoSizedRenderTexture(width
,
417 rth
.referenceSize
= new Vector2Int(width
, height
);
419 rth
.scaleFunc
= scaleFunc
;
424 RTHandle
AllocAutoSizedRenderTexture(
428 DepthBits depthBufferBits
,
429 RenderTextureFormat colorFormat
,
430 FilterMode filterMode
,
431 TextureWrapMode wrapMode
,
432 TextureDimension dimension
,
434 bool enableRandomWrite
,
436 bool autoGenerateMips
,
441 bool useDynamicScale
,
442 VRTextureUsage vrUsage
,
443 RenderTextureMemoryless memoryless
,
447 // Here user made a mistake in setting up msaa/bindMS, hence the warning
448 if (!enableMSAA
&& bindTextureMS
== true)
450 Debug
.LogWarning("RTHandle allocated without MSAA but with bindMS set to true, forcing bindMS to false.");
451 bindTextureMS
= false;
454 bool allocForMSAA
= m_ScaledRTSupportsMSAA
? enableMSAA
: false;
455 // Here we purposefully disable MSAA so we just force the bindMS param to false.
458 bindTextureMS
= false;
461 // MSAA Does not support random read/write.
462 bool UAV
= enableRandomWrite
;
463 if (allocForMSAA
&& (UAV
== true))
465 Debug
.LogWarning("RTHandle that is MSAA-enabled cannot allocate MSAA RT with 'enableRandomWrite = true'.");
469 int msaaSamples
= allocForMSAA
? (int)m_ScaledRTCurrentMSAASamples
: 1;
470 RTCategory category
= allocForMSAA
? RTCategory
.MSAA
: RTCategory
.Regular
;
472 var rt
= new RenderTexture(width
, height
, (int)depthBufferBits
, colorFormat
, sRGB
? RenderTextureReadWrite
.sRGB
: RenderTextureReadWrite
.Linear
)
474 hideFlags
= HideFlags
.HideAndDontSave
,
475 volumeDepth
= slices
,
476 filterMode
= filterMode
,
478 dimension
= dimension
,
479 enableRandomWrite
= UAV
,
480 useMipMap
= useMipMap
,
481 autoGenerateMips
= autoGenerateMips
,
482 anisoLevel
= anisoLevel
,
483 mipMapBias
= mipMapBias
,
484 antiAliasing
= msaaSamples
,
485 bindTextureMS
= bindTextureMS
,
486 useDynamicScale
= useDynamicScale
,
488 memorylessMode
= memoryless
,
489 name
= CoreUtils
.GetRenderTargetAutoName(width
, height
, slices
, colorFormat
, name
, mips
: useMipMap
, enableMSAA
: allocForMSAA
, msaaSamples
: m_ScaledRTCurrentMSAASamples
)
493 var rth
= new RTHandle(this);
494 rth
.SetRenderTexture(rt
, category
);
495 rth
.m_EnableMSAA
= enableMSAA
;
496 rth
.m_EnableRandomWrite
= enableRandomWrite
;
497 rth
.useScaling
= true;
499 m_AutoSizedRTs
.Add(rth
);
503 public string DumpRTInfo()
506 Array
.Resize(ref m_AutoSizedRTsArray
, m_AutoSizedRTs
.Count
);
507 m_AutoSizedRTs
.CopyTo(m_AutoSizedRTsArray
);
508 for (int i
= 0, c
= m_AutoSizedRTsArray
.Length
; i
< c
; ++i
)
510 var rt
= m_AutoSizedRTsArray
[i
].rt
;
511 result
= string.Format("{0}\nRT ({1})\t Format: {2} W: {3} H {4}\n", result
, i
, rt
.format
, rt
.width
, rt
.height
);