A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3using UnityEngine.Assertions;
4using UnityEngine.Experimental.Rendering;
5
6#if UNITY_EDITOR
7using UnityEditor;
8#endif
9
10namespace UnityEngine.Rendering
11{
12 /// <summary>
13 /// Scaled function used to compute the size of a RTHandle for the current frame.
14 /// </summary>
15 /// <param name="size">Reference size of the RTHandle system for the frame.</param>
16 /// <returns>The size of the RTHandled computed from the reference size.</returns>
17 public delegate Vector2Int ScaleFunc(Vector2Int size);
18
19 /// <summary>
20 /// List of properties of the RTHandle System for the current frame.
21 /// </summary>
22 public struct RTHandleProperties
23 {
24 /// <summary>
25 /// Size set as reference at the previous frame
26 /// </summary>
27 public Vector2Int previousViewportSize;
28 /// <summary>
29 /// Size of the render targets at the previous frame
30 /// </summary>
31 public Vector2Int previousRenderTargetSize;
32 /// <summary>
33 /// Size set as reference at the current frame
34 /// </summary>
35 public Vector2Int currentViewportSize;
36 /// <summary>
37 /// Size of the render targets at the current frame
38 /// </summary>
39 public Vector2Int currentRenderTargetSize;
40 /// <summary>
41 /// Scale factor from RTHandleSystem max size to requested reference size (referenceSize/maxSize)
42 /// (x,y) current frame (z,w) last frame (this is only used for buffered RTHandle Systems)
43 /// </summary>
44 public Vector4 rtHandleScale;
45 }
46
47 /// <summary>
48 /// Information about the allocation of a RTHandle
49 /// </summary>
50 public struct RTHandleAllocInfo
51 {
52 /// <summary> Number of slices of the RTHandle.</summary>
53 public int slices { get; set; }
54
55 /// <summary> GraphicsFormat of a color buffer.</summary>
56 public GraphicsFormat format { get; set; }
57
58 /// <summary> Filtering mode of the RTHandle.</summary>
59 public FilterMode filterMode { get; set; }
60
61 /// <summary> Addressing mode of the RTHandle.</summary>
62 public TextureWrapMode wrapModeU { get; set; }
63
64 /// <summary> Addressing mode of the RTHandle.</summary>
65 public TextureWrapMode wrapModeV { get; set; }
66
67 /// <summary> Addressing mode of the RTHandle.</summary>
68 public TextureWrapMode wrapModeW { get; set; }
69
70 /// <summary> Texture dimension of the RTHandle.</summary>
71 public TextureDimension dimension { get; set; }
72
73 /// <summary> Set to true to enable UAV random read writes on the texture.</summary>
74 public bool enableRandomWrite { get; set; }
75
76 /// <summary> Set to true if the texture should have mipmaps.</summary>
77 public bool useMipMap { get; set; }
78
79 /// <summary> Set to true to automatically generate mipmaps.</summary>
80 public bool autoGenerateMips { get; set; }
81
82 /// <summary> Anisotropic filtering level.</summary>
83 public int anisoLevel { get; set; }
84
85 /// <summary> Bias applied to mipmaps during filtering.</summary>
86 public float mipMapBias { get; set; }
87
88 /// <summary> Number of MSAA samples for the RTHandle.</summary>
89 public MSAASamples msaaSamples { get; set; }
90
91 /// <summary> Set to true if the texture needs to be bound as a multisampled texture in the shader.</summary>
92 public bool bindTextureMS { get; set; }
93
94 /// <summary> See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</summary>
95 public bool useDynamicScale { get; set; }
96
97 /// <summary> Use this property to set the render texture memoryless modes.</summary>
98 public RenderTextureMemoryless memoryless { get; set; }
99
100 /// <summary> Special treatment of the VR eye texture used in stereoscopic rendering.</summary>
101 public VRTextureUsage vrUsage { get; set; }
102
103 /// <summary> Name of the RTHandle.</summary>
104 public string name { get; set; }
105
106 /// <summary>
107 /// RTHandleAllocInfo constructor.
108 /// </summary>
109 /// <param name="name">Name of the RTHandle.</param>
110 public RTHandleAllocInfo(string name = "")
111 {
112 this.slices = 1;
113 this.format = GraphicsFormat.R8G8B8A8_SRGB;
114 this.filterMode = FilterMode.Point;
115 this.wrapModeU = TextureWrapMode.Repeat;
116 this.wrapModeV = TextureWrapMode.Repeat;
117 this.wrapModeW = TextureWrapMode.Repeat;
118 this.dimension = TextureDimension.Tex2D;
119 this.enableRandomWrite = false;
120 this.useMipMap = false;
121 this.autoGenerateMips = true;
122 this.anisoLevel = 1;
123 this.mipMapBias = 0f;
124 this.msaaSamples = MSAASamples.None;
125 this.bindTextureMS = false;
126 this.useDynamicScale = false;
127 this.memoryless = RenderTextureMemoryless.None;
128 this.vrUsage = VRTextureUsage.None;
129 this.name = name;
130 }
131 }
132
133 /// <summary>
134 /// System managing a set of RTHandle textures
135 /// </summary>
136 public partial class RTHandleSystem : IDisposable
137 {
138 internal enum ResizeMode
139 {
140 Auto,
141 OnDemand
142 }
143
144 // Parameters for auto-scaled Render Textures
145 bool m_HardwareDynamicResRequested = false;
146 HashSet<RTHandle> m_AutoSizedRTs;
147 RTHandle[] m_AutoSizedRTsArray; // For fast iteration
148 HashSet<RTHandle> m_ResizeOnDemandRTs;
149 RTHandleProperties m_RTHandleProperties;
150
151 /// <summary>
152 /// Current properties of the RTHandle System.
153 /// </summary>
154 public RTHandleProperties rtHandleProperties { get { return m_RTHandleProperties; } }
155
156 int m_MaxWidths = 0;
157 int m_MaxHeights = 0;
158#if UNITY_EDITOR
159 // In editor every now and then we must reset the size of the rthandle system if it was set very high and then switched back to a much smaller scale.
160 int m_FramesSinceLastReset = 0;
161#endif
162
163 /// <summary>
164 /// RTHandleSystem constructor.
165 /// </summary>
166 public RTHandleSystem()
167 {
168 m_AutoSizedRTs = new HashSet<RTHandle>();
169 m_ResizeOnDemandRTs = new HashSet<RTHandle>();
170 m_MaxWidths = 1;
171 m_MaxHeights = 1;
172 }
173
174 /// <summary>
175 /// Disposable pattern implementation
176 /// </summary>
177 public void Dispose()
178 {
179 Dispose(true);
180 }
181
182 /// <summary>
183 /// Initialize the RTHandle system.
184 /// </summary>
185 /// <param name="width">Initial reference rendering width.</param>
186 /// <param name="height">Initial reference rendering height.</param>
187 public void Initialize(int width, int height)
188 {
189 if (m_AutoSizedRTs.Count != 0)
190 {
191 string leakingResources = "Unreleased RTHandles:";
192 foreach (var rt in m_AutoSizedRTs)
193 {
194 leakingResources = string.Format("{0}\n {1}", leakingResources, rt.name);
195 }
196 Debug.LogError(string.Format("RTHandleSystem.Initialize should only be called once before allocating any Render Texture. This may be caused by an unreleased RTHandle resource.\n{0}\n", leakingResources));
197 }
198
199 m_MaxWidths = width;
200 m_MaxHeights = height;
201
202 m_HardwareDynamicResRequested = DynamicResolutionHandler.instance.RequestsHardwareDynamicResolution();
203 }
204
205 /// <summary>
206 /// Initialize the RTHandle system.
207 /// </summary>
208 /// <param name="width">Initial reference rendering width.</param>
209 /// <param name="height">Initial reference rendering height.</param>
210 /// <param name="useLegacyDynamicResControl">Use legacy hardware DynamicResolution control in RTHandle system.</param>
211 [Obsolete("useLegacyDynamicResControl is deprecated. Please use SetHardwareDynamicResolutionState() instead.")]
212 public void Initialize(int width, int height, bool useLegacyDynamicResControl = false)
213 {
214 Initialize(width, height);
215
216 if (useLegacyDynamicResControl)
217 m_HardwareDynamicResRequested = true;
218 }
219
220 /// <summary>
221 /// Release memory of a RTHandle from the RTHandle System
222 /// </summary>
223 /// <param name="rth">RTHandle that should be released.</param>
224 public void Release(RTHandle rth)
225 {
226 if (rth != null)
227 {
228 Assert.AreEqual(this, rth.m_Owner);
229 rth.Release();
230 }
231 }
232
233 internal void Remove(RTHandle rth)
234 {
235 m_AutoSizedRTs.Remove(rth);
236 }
237
238 /// <summary>
239 /// Reset the reference size of the system and reallocate all textures.
240 /// </summary>
241 /// <param name="width">New width.</param>
242 /// <param name="height">New height.</param>
243 public void ResetReferenceSize(int width, int height)
244 {
245 m_MaxWidths = width;
246 m_MaxHeights = height;
247 SetReferenceSize(width, height, reset: true);
248 }
249
250 /// <summary>
251 /// Sets the reference rendering size for subsequent rendering for the RTHandle System
252 /// </summary>
253 /// <param name="width">Reference rendering width for subsequent rendering.</param>
254 /// <param name="height">Reference rendering height for subsequent rendering.</param>
255 public void SetReferenceSize(int width, int height)
256 {
257 SetReferenceSize(width, height, false);
258 }
259
260 /// <summary>
261 /// Sets the reference rendering size for subsequent rendering for the RTHandle System
262 /// </summary>
263 /// <param name="width">Reference rendering width for subsequent rendering.</param>
264 /// <param name="height">Reference rendering height for subsequent rendering.</param>
265 /// <param name="reset">If set to true, the new width and height will override the old values even if they are not bigger.</param>
266 public void SetReferenceSize(int width, int height, bool reset)
267 {
268 m_RTHandleProperties.previousViewportSize = m_RTHandleProperties.currentViewportSize;
269 m_RTHandleProperties.previousRenderTargetSize = m_RTHandleProperties.currentRenderTargetSize;
270 Vector2 lastFrameMaxSize = new Vector2(GetMaxWidth(), GetMaxHeight());
271
272 width = Mathf.Max(width, 1);
273 height = Mathf.Max(height, 1);
274
275#if UNITY_EDITOR
276 // If the reference size is significantly higher than the current actualWidth/Height and it is larger than 1440p dimensions, we reset the reference size every several frames
277 // in editor to avoid issues if a large resolution was temporarily set.
278 const int resetInterval = 100;
279 if (((m_MaxWidths / (float)width) > 2.0f && m_MaxWidths > 2560) ||
280 ((m_MaxHeights / (float)height) > 2.0f && m_MaxHeights > 1440))
281 {
282 if (m_FramesSinceLastReset > resetInterval)
283 {
284 m_FramesSinceLastReset = 0;
285 ResetReferenceSize(width, height);
286 }
287 m_FramesSinceLastReset++;
288 }
289 else
290 {
291 // If some cameras is a reasonable resolution size, we dont reset.
292 m_FramesSinceLastReset = 0;
293 }
294#endif
295
296 bool sizeChanged = width > GetMaxWidth() || height > GetMaxHeight() || reset;
297 if (sizeChanged)
298 {
299 Resize(width, height, sizeChanged);
300 }
301
302 m_RTHandleProperties.currentViewportSize = new Vector2Int(width, height);
303 m_RTHandleProperties.currentRenderTargetSize = new Vector2Int(GetMaxWidth(), GetMaxHeight());
304
305 // If the currentViewportSize is 0, it mean we are the first frame of rendering (can happen when doing domain reload for example or for reflection probe)
306 // in this case the scalePrevious below could be invalided. But some effect rely on having a correct value like TAA with the history buffer for the first frame.
307 // to work around this, when we detect that size is 0, we setup previous size to current size.
308 if (m_RTHandleProperties.previousViewportSize.x == 0)
309 {
310 m_RTHandleProperties.previousViewportSize = m_RTHandleProperties.currentViewportSize;
311 m_RTHandleProperties.previousRenderTargetSize = m_RTHandleProperties.currentRenderTargetSize;
312 lastFrameMaxSize = new Vector2(GetMaxWidth(), GetMaxHeight());
313 }
314
315 var scales = CalculateRatioAgainstMaxSize(m_RTHandleProperties.currentViewportSize);
316 if (DynamicResolutionHandler.instance.HardwareDynamicResIsEnabled() && m_HardwareDynamicResRequested)
317 {
318 // Making the final scale in 'drs' space, since the final scale must account for rounding pixel values.
319 m_RTHandleProperties.rtHandleScale = new Vector4(scales.x, scales.y, m_RTHandleProperties.rtHandleScale.x, m_RTHandleProperties.rtHandleScale.y);
320 }
321 else
322 {
323 Vector2 scalePrevious = m_RTHandleProperties.previousViewportSize / lastFrameMaxSize;
324 m_RTHandleProperties.rtHandleScale = new Vector4(scales.x, scales.y, scalePrevious.x, scalePrevious.y);
325 }
326 }
327
328 internal Vector2 CalculateRatioAgainstMaxSize(in Vector2Int viewportSize)
329 {
330 Vector2 maxSize = new Vector2(GetMaxWidth(), GetMaxHeight());
331
332 if (DynamicResolutionHandler.instance.HardwareDynamicResIsEnabled() && m_HardwareDynamicResRequested && viewportSize != DynamicResolutionHandler.instance.finalViewport)
333 {
334 //for hardware resolution, the final goal is to figure out a scale from finalViewport into maxViewport.
335 //This is however wrong! because the actualViewport might not fit the finalViewport perfectly, due to rounding.
336 //A correct way is to instead downscale the maxViewport, and keep the final scale in terms of downsampled buffers.
337 Vector2 currentScale = (Vector2)viewportSize / (Vector2)DynamicResolutionHandler.instance.finalViewport;
338 maxSize = DynamicResolutionHandler.instance.ApplyScalesOnSize(new Vector2Int(GetMaxWidth(), GetMaxHeight()), currentScale);
339 }
340
341 return new Vector2((float)viewportSize.x / maxSize.x, (float)viewportSize.y / maxSize.y);
342 }
343
344 /// <summary>
345 /// Enable or disable hardware dynamic resolution for the RTHandle System
346 /// </summary>
347 /// <param name="enableHWDynamicRes">State of hardware dynamic resolution.</param>
348 public void SetHardwareDynamicResolutionState(bool enableHWDynamicRes)
349 {
350 if (enableHWDynamicRes != m_HardwareDynamicResRequested)
351 {
352 m_HardwareDynamicResRequested = enableHWDynamicRes;
353
354 Array.Resize(ref m_AutoSizedRTsArray, m_AutoSizedRTs.Count);
355 m_AutoSizedRTs.CopyTo(m_AutoSizedRTsArray);
356 for (int i = 0, c = m_AutoSizedRTsArray.Length; i < c; ++i)
357 {
358 var rth = m_AutoSizedRTsArray[i];
359
360 // Grab the render texture
361 var renderTexture = rth.m_RT;
362 if (renderTexture)
363 {
364 // Free the previous version
365 renderTexture.Release();
366
367 renderTexture.useDynamicScale = m_HardwareDynamicResRequested && rth.m_EnableHWDynamicScale;
368
369 // Create the render texture
370 renderTexture.Create();
371 }
372 }
373 }
374 }
375
376 internal void SwitchResizeMode(RTHandle rth, ResizeMode mode)
377 {
378 // Don't do anything is scaling isn't enabled on this RT
379 // TODO: useScaling should probably be moved to ResizeMode.Fixed or something
380 if (!rth.useScaling)
381 return;
382
383 switch (mode)
384 {
385 case ResizeMode.OnDemand:
386 m_AutoSizedRTs.Remove(rth);
387 m_ResizeOnDemandRTs.Add(rth);
388 break;
389 case ResizeMode.Auto:
390 // Resize now so it is consistent with other auto resize RTHs
391 if (m_ResizeOnDemandRTs.Contains(rth))
392 DemandResize(rth);
393 m_ResizeOnDemandRTs.Remove(rth);
394 m_AutoSizedRTs.Add(rth);
395 break;
396 }
397 }
398
399 void DemandResize(RTHandle rth)
400 {
401 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.");
402
403 // Grab the render texture
404 var rt = rth.m_RT;
405 rth.referenceSize = new Vector2Int(m_MaxWidths, m_MaxHeights);
406 var scaledSize = rth.GetScaledSize(rth.referenceSize);
407 scaledSize = Vector2Int.Max(Vector2Int.one, scaledSize);
408
409 // Did the size change?
410 var sizeChanged = rt.width != scaledSize.x || rt.height != scaledSize.y;
411
412 if (sizeChanged)
413 {
414 // Free this render texture
415 rt.Release();
416
417 // Update the size
418 rt.width = scaledSize.x;
419 rt.height = scaledSize.y;
420
421 // Generate a new name
422 rt.name = CoreUtils.GetRenderTargetAutoName(
423 rt.width,
424 rt.height,
425 rt.volumeDepth,
426 (rt.depthStencilFormat!=GraphicsFormat.None)? rt.depthStencilFormat : rt.graphicsFormat,
427 rt.dimension,
428 rth.m_Name,
429 mips: rt.useMipMap,
430 enableMSAA: rth.m_EnableMSAA,
431 msaaSamples: (MSAASamples)rt.antiAliasing,
432 dynamicRes: rt.useDynamicScale,
433 dynamicResExplicit: rt.useDynamicScaleExplicit
434 );
435
436 // Create the new texture
437 rt.Create();
438 }
439 }
440
441 /// <summary>
442 /// Returns the maximum allocated width of the RTHandle System.
443 /// </summary>
444 /// <returns>Maximum allocated width of the RTHandle System.</returns>
445 public int GetMaxWidth() { return m_MaxWidths; }
446 /// <summary>
447 /// Returns the maximum allocated height of the RTHandle System.
448 /// </summary>
449 /// <returns>Maximum allocated height of the RTHandle System.</returns>
450 public int GetMaxHeight() { return m_MaxHeights; }
451
452 void Dispose(bool disposing)
453 {
454 if (disposing)
455 {
456 Array.Resize(ref m_AutoSizedRTsArray, m_AutoSizedRTs.Count);
457 m_AutoSizedRTs.CopyTo(m_AutoSizedRTsArray);
458 for (int i = 0, c = m_AutoSizedRTsArray.Length; i < c; ++i)
459 {
460 var rt = m_AutoSizedRTsArray[i];
461 Release(rt);
462 }
463 m_AutoSizedRTs.Clear();
464
465 Array.Resize(ref m_AutoSizedRTsArray, m_ResizeOnDemandRTs.Count);
466 m_ResizeOnDemandRTs.CopyTo(m_AutoSizedRTsArray);
467 for (int i = 0, c = m_AutoSizedRTsArray.Length; i < c; ++i)
468 {
469 var rt = m_AutoSizedRTsArray[i];
470 Release(rt);
471 }
472 m_ResizeOnDemandRTs.Clear();
473 m_AutoSizedRTsArray = null;
474 }
475 }
476
477 void Resize(int width, int height, bool sizeChanged)
478 {
479 m_MaxWidths = Math.Max(width, m_MaxWidths);
480 m_MaxHeights = Math.Max(height, m_MaxHeights);
481
482 var maxSize = new Vector2Int(m_MaxWidths, m_MaxHeights);
483
484 Array.Resize(ref m_AutoSizedRTsArray, m_AutoSizedRTs.Count);
485 m_AutoSizedRTs.CopyTo(m_AutoSizedRTsArray);
486
487 for (int i = 0, c = m_AutoSizedRTsArray.Length; i < c; ++i)
488 {
489 // Grab the RT Handle
490 var rth = m_AutoSizedRTsArray[i];
491
492 // Force its new reference size
493 rth.referenceSize = maxSize;
494
495 // Grab the render texture
496 var renderTexture = rth.m_RT;
497
498 // Free the previous version
499 renderTexture.Release();
500
501 // Get the scaled size
502 var scaledSize = rth.GetScaledSize(maxSize);
503
504 renderTexture.width = Mathf.Max(scaledSize.x, 1);
505 renderTexture.height = Mathf.Max(scaledSize.y, 1);
506
507 // Regenerate the name
508 renderTexture.name = CoreUtils.GetRenderTargetAutoName(renderTexture.width, renderTexture.height, renderTexture.volumeDepth
509 , (renderTexture.depthStencilFormat != GraphicsFormat.None) ? renderTexture.depthStencilFormat : renderTexture.graphicsFormat
510 , renderTexture.dimension, rth.m_Name, mips: renderTexture.useMipMap, enableMSAA: rth.m_EnableMSAA
511 , msaaSamples: (MSAASamples)renderTexture.antiAliasing, dynamicRes: renderTexture.useDynamicScale, dynamicResExplicit: renderTexture.useDynamicScaleExplicit);
512
513 // Create the render texture
514 renderTexture.Create();
515 }
516 }
517
518 /// <summary>
519 /// Allocate a new fixed sized RTHandle.
520 /// </summary>
521 /// <param name="width">With of the RTHandle.</param>
522 /// <param name="height">Heigh of the RTHandle.</param>
523 /// <param name="slices">Number of slices of the RTHandle.</param>
524 /// <param name="depthBufferBits">Bit depths of a depth buffer.</param>
525 /// <param name="colorFormat">GraphicsFormat of a color buffer.</param>
526 /// <param name="filterMode">Filtering mode of the RTHandle.</param>
527 /// <param name="wrapMode">Addressing mode of the RTHandle.</param>
528 /// <param name="dimension">Texture dimension of the RTHandle.</param>
529 /// <param name="enableRandomWrite">Set to true to enable UAV random read writes on the texture.</param>
530 /// <param name="useMipMap">Set to true if the texture should have mipmaps.</param>
531 /// <param name="autoGenerateMips">Set to true to automatically generate mipmaps.</param>
532 /// <param name="isShadowMap">Set to true if the depth buffer should be used as a shadow map.</param>
533 /// <param name="anisoLevel">Anisotropic filtering level.</param>
534 /// <param name="mipMapBias">Bias applied to mipmaps during filtering.</param>
535 /// <param name="msaaSamples">Number of MSAA samples for the RTHandle.</param>
536 /// <param name="bindTextureMS">Set to true if the texture needs to be bound as a multisampled texture in the shader.</param>
537 /// <param name="useDynamicScale">[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</param>
538 /// <param name="useDynamicScaleExplicit">[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</param>
539 /// <param name="memoryless">Use this property to set the render texture memoryless modes.</param>
540 /// <param name="vrUsage">Special treatment of the VR eye texture used in stereoscopic rendering.</param>
541 /// <param name="name">Name of the RTHandle.</param>
542 /// <returns>A new RTHandle.</returns>
543 public RTHandle Alloc(
544 int width,
545 int height,
546 int slices = 1,
547 DepthBits depthBufferBits = DepthBits.None,
548 GraphicsFormat colorFormat = GraphicsFormat.R8G8B8A8_SRGB,
549 FilterMode filterMode = FilterMode.Point,
550 TextureWrapMode wrapMode = TextureWrapMode.Repeat,
551 TextureDimension dimension = TextureDimension.Tex2D,
552 bool enableRandomWrite = false,
553 bool useMipMap = false,
554 bool autoGenerateMips = true,
555 bool isShadowMap = false,
556 int anisoLevel = 1,
557 float mipMapBias = 0f,
558 MSAASamples msaaSamples = MSAASamples.None,
559 bool bindTextureMS = false,
560 bool useDynamicScale = false,
561 bool useDynamicScaleExplicit = false,
562 RenderTextureMemoryless memoryless = RenderTextureMemoryless.None,
563 VRTextureUsage vrUsage = VRTextureUsage.None,
564 string name = ""
565 )
566 {
567 var format = (depthBufferBits != DepthBits.None) ? GraphicsFormatUtility.GetDepthStencilFormat((int)depthBufferBits) : colorFormat;
568
569 return Alloc(width, height, format, wrapMode, wrapMode, wrapMode, slices, filterMode, dimension, enableRandomWrite, useMipMap,
570 autoGenerateMips, isShadowMap, anisoLevel, mipMapBias, msaaSamples, bindTextureMS, useDynamicScale, useDynamicScaleExplicit, memoryless, vrUsage, name);
571 }
572
573 /// <summary>
574 /// Allocate a new fixed sized RTHandle.
575 /// </summary>
576 /// <param name="width">With of the RTHandle.</param>
577 /// <param name="height">Heigh of the RTHandle.</param>
578 /// <param name="format">GraphicsFormat of a color or depth stencil buffer.</param>
579 /// <param name="slices">Number of slices of the RTHandle.</param>
580 /// <param name="filterMode">Filtering mode of the RTHandle.</param>
581 /// <param name="wrapMode">Addressing mode of the RTHandle.</param>
582 /// <param name="dimension">Texture dimension of the RTHandle.</param>
583 /// <param name="enableRandomWrite">Set to true to enable UAV random read writes on the texture.</param>
584 /// <param name="useMipMap">Set to true if the texture should have mipmaps.</param>
585 /// <param name="autoGenerateMips">Set to true to automatically generate mipmaps.</param>
586 /// <param name="isShadowMap">Set to true if the depth buffer should be used as a shadow map.</param>
587 /// <param name="anisoLevel">Anisotropic filtering level.</param>
588 /// <param name="mipMapBias">Bias applied to mipmaps during filtering.</param>
589 /// <param name="msaaSamples">Number of MSAA samples for the RTHandle.</param>
590 /// <param name="bindTextureMS">Set to true if the texture needs to be bound as a multisampled texture in the shader.</param>
591 /// <param name="useDynamicScale">[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</param>
592 /// <param name="useDynamicScaleExplicit">[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</param>
593 /// <param name="memoryless">Use this property to set the render texture memoryless modes.</param>
594 /// <param name="vrUsage">Special treatment of the VR eye texture used in stereoscopic rendering.</param>
595 /// <param name="name">Name of the RTHandle.</param>
596 /// <returns>A new RTHandle.</returns>
597 public RTHandle Alloc(
598 int width,
599 int height,
600 GraphicsFormat format,
601 int slices = 1,
602 FilterMode filterMode = FilterMode.Point,
603 TextureWrapMode wrapMode = TextureWrapMode.Repeat,
604 TextureDimension dimension = TextureDimension.Tex2D,
605 bool enableRandomWrite = false,
606 bool useMipMap = false,
607 bool autoGenerateMips = true,
608 bool isShadowMap = false,
609 int anisoLevel = 1,
610 float mipMapBias = 0f,
611 MSAASamples msaaSamples = MSAASamples.None,
612 bool bindTextureMS = false,
613 bool useDynamicScale = false,
614 bool useDynamicScaleExplicit = false,
615 RenderTextureMemoryless memoryless = RenderTextureMemoryless.None,
616 VRTextureUsage vrUsage = VRTextureUsage.None,
617 string name = ""
618 )
619 {
620 return Alloc(width, height, format, wrapMode, wrapMode, wrapMode, slices, filterMode, dimension, enableRandomWrite, useMipMap,
621 autoGenerateMips, isShadowMap, anisoLevel, mipMapBias, msaaSamples, bindTextureMS, useDynamicScale, useDynamicScaleExplicit, memoryless, vrUsage, name);
622 }
623
624 /// <summary>
625 /// Allocate a new fixed sized RTHandle.
626 /// </summary>
627 /// <param name="width">With of the RTHandle.</param>
628 /// <param name="height">Heigh of the RTHandle.</param>
629 /// <param name="wrapModeU">U coordinate wrapping mode of the RTHandle.</param>
630 /// <param name="wrapModeV">V coordinate wrapping mode of the RTHandle.</param>
631 /// <param name="wrapModeW">W coordinate wrapping mode of the RTHandle.</param>
632 /// <param name="slices">Number of slices of the RTHandle.</param>
633 /// <param name="depthBufferBits">Bit depths of a depth buffer.</param>
634 /// <param name="colorFormat">GraphicsFormat of a color buffer.</param>
635 /// <param name="filterMode">Filtering mode of the RTHandle.</param>
636 /// <param name="dimension">Texture dimension of the RTHandle.</param>
637 /// <param name="enableRandomWrite">Set to true to enable UAV random read writes on the texture.</param>
638 /// <param name="useMipMap">Set to true if the texture should have mipmaps.</param>
639 /// <param name="autoGenerateMips">Set to true to automatically generate mipmaps.</param>
640 /// <param name="isShadowMap">Set to true if the depth buffer should be used as a shadow map.</param>
641 /// <param name="anisoLevel">Anisotropic filtering level.</param>
642 /// <param name="mipMapBias">Bias applied to mipmaps during filtering.</param>
643 /// <param name="msaaSamples">Number of MSAA samples for the RTHandle.</param>
644 /// <param name="bindTextureMS">Set to true if the texture needs to be bound as a multisampled texture in the shader.</param>
645 /// <param name="useDynamicScale">[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</param>
646 /// <param name="useDynamicScaleExplicit">[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</param>
647 /// <param name="memoryless">Use this property to set the render texture memoryless modes.</param>
648 /// <param name="vrUsage">Special treatment of the VR eye texture used in stereoscopic rendering.</param>
649 /// <param name="name">Name of the RTHandle.</param>
650 /// <returns>A new RTHandle.</returns>
651 public RTHandle Alloc(
652 int width,
653 int height,
654 TextureWrapMode wrapModeU,
655 TextureWrapMode wrapModeV,
656 TextureWrapMode wrapModeW = TextureWrapMode.Repeat,
657 int slices = 1,
658 DepthBits depthBufferBits = DepthBits.None,
659 GraphicsFormat colorFormat = GraphicsFormat.R8G8B8A8_SRGB,
660 FilterMode filterMode = FilterMode.Point,
661 TextureDimension dimension = TextureDimension.Tex2D,
662 bool enableRandomWrite = false,
663 bool useMipMap = false,
664 bool autoGenerateMips = true,
665 bool isShadowMap = false,
666 int anisoLevel = 1,
667 float mipMapBias = 0f,
668 MSAASamples msaaSamples = MSAASamples.None,
669 bool bindTextureMS = false,
670 bool useDynamicScale = false,
671 bool useDynamicScaleExplicit = false,
672 RenderTextureMemoryless memoryless = RenderTextureMemoryless.None,
673 VRTextureUsage vrUsage = VRTextureUsage.None,
674 string name = ""
675 )
676 {
677 var format = (depthBufferBits != DepthBits.None) ? GraphicsFormatUtility.GetDepthStencilFormat((int)depthBufferBits) : colorFormat;
678
679 return Alloc(
680 width,
681 height,
682 format,
683 wrapModeU,
684 wrapModeV,
685 wrapModeW,
686 slices,
687 filterMode,
688 dimension,
689 enableRandomWrite,
690 useMipMap,
691 autoGenerateMips ,
692 isShadowMap,
693 anisoLevel,
694 mipMapBias,
695 msaaSamples,
696 bindTextureMS,
697 useDynamicScale,
698 useDynamicScaleExplicit,
699 memoryless,
700 vrUsage,
701 name
702 );
703 }
704
705 /// <summary>
706 /// Allocate a new fixed sized RTHandle.
707 /// </summary>
708 /// <param name="width">With of the RTHandle.</param>
709 /// <param name="height">Heigh of the RTHandle.</param>
710 /// <param name="format">GraphicsFormat of the color or a depth stencil buffer.</param>
711 /// <param name="wrapModeU">U coordinate wrapping mode of the RTHandle.</param>
712 /// <param name="wrapModeV">V coordinate wrapping mode of the RTHandle.</param>
713 /// <param name="wrapModeW">W coordinate wrapping mode of the RTHandle.</param>
714 /// <param name="slices">Number of slices of the RTHandle.</param>
715 /// <param name="filterMode">Filtering mode of the RTHandle.</param>
716 /// <param name="dimension">Texture dimension of the RTHandle.</param>
717 /// <param name="enableRandomWrite">Set to true to enable UAV random read writes on the texture.</param>
718 /// <param name="useMipMap">Set to true if the texture should have mipmaps.</param>
719 /// <param name="autoGenerateMips">Set to true to automatically generate mipmaps.</param>
720 /// <param name="isShadowMap">Set to true if the depth buffer should be used as a shadow map.</param>
721 /// <param name="anisoLevel">Anisotropic filtering level.</param>
722 /// <param name="mipMapBias">Bias applied to mipmaps during filtering.</param>
723 /// <param name="msaaSamples">Number of MSAA samples for the RTHandle.</param>
724 /// <param name="bindTextureMS">Set to true if the texture needs to be bound as a multisampled texture in the shader.</param>
725 /// <param name="useDynamicScale">[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</param>
726 /// <param name="useDynamicScaleExplicit">[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</param>
727 /// <param name="memoryless">Use this property to set the render texture memoryless modes.</param>
728 /// <param name="vrUsage">Special treatment of the VR eye texture used in stereoscopic rendering.</param>
729 /// <param name="name">Name of the RTHandle.</param>
730 /// <returns>A new RTHandle.</returns>
731 public RTHandle Alloc(
732 int width,
733 int height,
734 GraphicsFormat format,
735 TextureWrapMode wrapModeU,
736 TextureWrapMode wrapModeV,
737 TextureWrapMode wrapModeW = TextureWrapMode.Repeat,
738 int slices = 1,
739 FilterMode filterMode = FilterMode.Point,
740 TextureDimension dimension = TextureDimension.Tex2D,
741 bool enableRandomWrite = false,
742 bool useMipMap = false,
743 bool autoGenerateMips = true,
744 bool isShadowMap = false,
745 int anisoLevel = 1,
746 float mipMapBias = 0f,
747 MSAASamples msaaSamples = MSAASamples.None,
748 bool bindTextureMS = false,
749 bool useDynamicScale = false,
750 bool useDynamicScaleExplicit = false,
751 RenderTextureMemoryless memoryless = RenderTextureMemoryless.None,
752 VRTextureUsage vrUsage = VRTextureUsage.None,
753 string name = ""
754 )
755 {
756 var rt = CreateRenderTexture(
757 width, height, format, slices, filterMode, wrapModeU, wrapModeV, wrapModeW, dimension, enableRandomWrite, useMipMap
758 , autoGenerateMips, isShadowMap, anisoLevel, mipMapBias, msaaSamples, bindTextureMS
759 , useDynamicScale, useDynamicScaleExplicit, memoryless, vrUsage, name);
760
761 var newRT = new RTHandle(this);
762 newRT.SetRenderTexture(rt);
763 newRT.useScaling = false;
764 newRT.m_EnableRandomWrite = enableRandomWrite;
765 newRT.m_EnableMSAA = msaaSamples != MSAASamples.None;
766 newRT.m_EnableHWDynamicScale = useDynamicScale;
767 newRT.m_Name = name;
768
769 newRT.referenceSize = new Vector2Int(width, height);
770
771 return newRT;
772 }
773
774 private RenderTexture CreateRenderTexture(
775 int width,
776 int height,
777 GraphicsFormat format,
778 int slices,
779 FilterMode filterMode,
780 TextureWrapMode wrapModeU,
781 TextureWrapMode wrapModeV,
782 TextureWrapMode wrapModeW,
783 TextureDimension dimension,
784 bool enableRandomWrite,
785 bool useMipMap,
786 bool autoGenerateMips,
787 bool isShadowMap,
788 int anisoLevel,
789 float mipMapBias,
790 MSAASamples msaaSamples,
791 bool bindTextureMS,
792 bool useDynamicScale,
793 bool useDynamicScaleExplicit,
794 RenderTextureMemoryless memoryless,
795 VRTextureUsage vrUsage,
796 string name)
797 {
798 bool enableMSAA = msaaSamples != MSAASamples.None;
799 // Here user made a mistake in setting up msaa/bindMS, hence the warning
800 if (!enableMSAA && bindTextureMS == true)
801 {
802 Debug.LogWarning("RTHandle allocated without MSAA but with bindMS set to true, forcing bindMS to false.");
803 bindTextureMS = false;
804 }
805
806 // MSAA Does not support random read/write.
807 if (enableMSAA && (enableRandomWrite == true))
808 {
809 Debug.LogWarning("RTHandle that is MSAA-enabled cannot allocate MSAA RT with 'enableRandomWrite = true'.");
810 enableRandomWrite = false;
811 }
812
813 bool isDepthStencilFormat = GraphicsFormatUtility.IsDepthStencilFormat(format);
814 string fullName;
815 GraphicsFormat colorFormat, depthStencilFormat, stencilFormat;
816 ShadowSamplingMode shadowSamplingMode = ShadowSamplingMode.None;
817
818 if (isShadowMap)
819 {
820 //This is the same "magic" behavior like setting the desc.colorFormat = RenderTextureFormat.Shadowmap
821 //We elevate the magic to here to only use the explict properties (graphicsFormat, depthStencilFormat, ShadowSamplingMode) from now.
822 int depthBits = GraphicsFormatUtility.GetDepthBits(format);
823 if (depthBits < 16) depthBits = 16;
824
825 depthStencilFormat = GraphicsFormatUtility.GetDepthStencilFormat(depthBits, 0);
826 colorFormat = GraphicsFormat.None;
827 stencilFormat = GraphicsFormat.None;
828 shadowSamplingMode = ShadowSamplingMode.CompareDepths;
829
830 fullName = CoreUtils.GetRenderTargetAutoName(width, height, slices, RenderTextureFormat.Shadowmap, name, mips: useMipMap, enableMSAA: enableMSAA, msaaSamples: msaaSamples);
831 }
832 else if (isDepthStencilFormat)
833 {
834 //depth stencil texture
835 colorFormat = GraphicsFormat.None;
836 depthStencilFormat = format;
837 stencilFormat = GetStencilFormat(format);
838
839 fullName = CoreUtils.GetRenderTargetAutoName(width, height, slices, format, dimension, name, mips: useMipMap, enableMSAA: enableMSAA, msaaSamples: msaaSamples, dynamicRes: useDynamicScale, dynamicResExplicit: useDynamicScaleExplicit);
840 }
841 else
842 {
843 // color texture
844 colorFormat = format;
845 depthStencilFormat = GraphicsFormat.None;
846 stencilFormat = GraphicsFormat.None;
847
848 fullName = CoreUtils.GetRenderTargetAutoName(width, height, slices, format, dimension, name, mips: useMipMap, enableMSAA: enableMSAA, msaaSamples: msaaSamples, dynamicRes: useDynamicScale, dynamicResExplicit: useDynamicScaleExplicit);
849 }
850
851 var desc = new RenderTextureDescriptor(width, height, colorFormat, depthStencilFormat)
852 {
853 msaaSamples = (int)msaaSamples,
854 volumeDepth = slices,
855 stencilFormat = stencilFormat,
856 dimension = dimension,
857 shadowSamplingMode = shadowSamplingMode,
858 vrUsage = vrUsage,
859 memoryless = memoryless,
860 useMipMap = useMipMap,
861 autoGenerateMips = autoGenerateMips,
862 enableRandomWrite = enableRandomWrite,
863 bindMS = bindTextureMS,
864 useDynamicScale = m_HardwareDynamicResRequested && useDynamicScale,
865 useDynamicScaleExplicit = m_HardwareDynamicResRequested && useDynamicScaleExplicit
866 };
867
868 var rt = new RenderTexture(desc);
869
870 rt.name = fullName;
871
872 rt.anisoLevel = anisoLevel;
873 rt.mipMapBias = mipMapBias;
874 rt.hideFlags = HideFlags.HideAndDontSave;
875 rt.filterMode = filterMode;
876
877 rt.wrapModeU = wrapModeU;
878 rt.wrapModeV = wrapModeV;
879 rt.wrapModeW = wrapModeW;
880
881 rt.Create();
882 return rt;
883 }
884
885 /// <summary>
886 /// Allocate a new fixed sized RTHandle.
887 /// </summary>
888 /// <param name="width">With of the RTHandle.</param>
889 /// <param name="height">Height of the RTHandle.</param>
890 /// <param name="info">Struct containing details of allocation</param>
891 /// <returns>A new RTHandle.</returns>
892 public RTHandle Alloc(int width, int height, RTHandleAllocInfo info)
893 {
894 bool isShadowMap = false;
895 bool useDynamicScaleExplicit = false;
896
897 var rt = CreateRenderTexture(
898 width, height, info.format, info.slices, info.filterMode, info.wrapModeU, info.wrapModeV, info.wrapModeW, info.dimension, info.enableRandomWrite, info.useMipMap
899 , info.autoGenerateMips, isShadowMap, info.anisoLevel, info.mipMapBias, info.msaaSamples, info.bindTextureMS
900 , info.useDynamicScale, useDynamicScaleExplicit, info.memoryless, info.vrUsage, info.name);
901
902 var newRT = new RTHandle(this);
903 newRT.SetRenderTexture(rt);
904 newRT.useScaling = false;
905 newRT.m_EnableRandomWrite = info.enableRandomWrite;
906 newRT.m_EnableMSAA = info.msaaSamples != MSAASamples.None;
907 newRT.m_EnableHWDynamicScale = info.useDynamicScale;
908 newRT.m_Name = info.name;
909
910 newRT.referenceSize = new Vector2Int(width, height);
911
912 return newRT;
913 }
914
915 // Next two methods are used to allocate RenderTexture that depend on the frame settings (resolution and msaa for now)
916 // RenderTextures allocated this way are meant to be defined by a scale of camera resolution (full/half/quarter resolution for example).
917 // 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).
918 // 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.
919
920 /// <summary>
921 /// Calculate the dimensions (in pixels) of the RTHandles given the scale factor.
922 /// </summary>
923 /// <param name="scaleFactor">The scale factor to use when calculating the dimensions. The base unscaled size used, is the sizes passed to the last ResetReferenceSize call.</param>
924 /// <returns>The calculated dimensions.</returns>
925 public Vector2Int CalculateDimensions(Vector2 scaleFactor)
926 {
927 return new Vector2Int(
928 Mathf.Max(Mathf.RoundToInt(scaleFactor.x * GetMaxWidth()), 1),
929 Mathf.Max(Mathf.RoundToInt(scaleFactor.y * GetMaxHeight()), 1)
930 );
931 }
932
933 /// <summary>
934 /// Allocate a new automatically sized RTHandle.
935 /// </summary>
936 /// <param name="scaleFactor">Constant scale for the RTHandle size computation.</param>
937 /// <param name="format">GraphicsFormat of a color or depth stencil buffer.</param>
938 /// <param name="slices">Number of slices of the RTHandle.</param>
939 /// <param name="filterMode">Filtering mode of the RTHandle.</param>
940 /// <param name="wrapMode">Addressing mode of the RTHandle.</param>
941 /// <param name="dimension">Texture dimension of the RTHandle.</param>
942 /// <param name="enableRandomWrite">Set to true to enable UAV random read writes on the texture.</param>
943 /// <param name="useMipMap">Set to true if the texture should have mipmaps.</param>
944 /// <param name="autoGenerateMips">Set to true to automatically generate mipmaps.</param>
945 /// <param name="isShadowMap">Set to true if the depth buffer should be used as a shadow map.</param>
946 /// <param name="anisoLevel">Anisotropic filtering level.</param>
947 /// <param name="mipMapBias">Bias applied to mipmaps during filtering.</param>
948 /// <param name="msaaSamples">Number of MSAA samples.</param>
949 /// <param name="bindTextureMS">Set to true if the texture needs to be bound as a multisampled texture in the shader.</param>
950 /// <param name="useDynamicScale">[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</param>
951 /// <param name="useDynamicScaleExplicit">[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</param>
952 /// <param name="memoryless">Use this property to set the render texture memoryless modes.</param>
953 /// <param name="vrUsage">Special treatment of the VR eye texture used in stereoscopic rendering.</param>
954 /// <param name="name">Name of the RTHandle.</param>
955 /// <returns>A new RTHandle.</returns>
956 public RTHandle Alloc(
957 Vector2 scaleFactor,
958 GraphicsFormat format,
959 int slices = 1,
960 FilterMode filterMode = FilterMode.Point,
961 TextureWrapMode wrapMode = TextureWrapMode.Repeat,
962 TextureDimension dimension = TextureDimension.Tex2D,
963 bool enableRandomWrite = false,
964 bool useMipMap = false,
965 bool autoGenerateMips = true,
966 bool isShadowMap = false,
967 int anisoLevel = 1,
968 float mipMapBias = 0f,
969 MSAASamples msaaSamples = MSAASamples.None,
970 bool bindTextureMS = false,
971 bool useDynamicScale = false,
972 bool useDynamicScaleExplicit = false,
973 RenderTextureMemoryless memoryless = RenderTextureMemoryless.None,
974 VRTextureUsage vrUsage = VRTextureUsage.None,
975 string name = ""
976 )
977 {
978 var actualDimensions = CalculateDimensions(scaleFactor);
979
980 var rth = AllocAutoSizedRenderTexture(actualDimensions.x,
981 actualDimensions.y,
982 slices,
983 format,
984 filterMode,
985 wrapMode,
986 dimension,
987 enableRandomWrite,
988 useMipMap,
989 autoGenerateMips,
990 isShadowMap,
991 anisoLevel,
992 mipMapBias,
993 msaaSamples,
994 bindTextureMS,
995 useDynamicScale,
996 useDynamicScaleExplicit,
997 memoryless,
998 vrUsage,
999 name
1000 );
1001
1002 rth.referenceSize = actualDimensions;
1003
1004 rth.scaleFactor = scaleFactor;
1005 return rth;
1006 }
1007
1008 /// <summary>
1009 /// Allocate a new automatically sized RTHandle.
1010 /// </summary>
1011 /// <param name="scaleFactor">Constant scale for the RTHandle size computation.</param>
1012 /// <param name="slices">Number of slices of the RTHandle.</param>
1013 /// <param name="depthBufferBits">Bit depths of a depth buffer.</param>
1014 /// <param name="colorFormat">GraphicsFormat of a color buffer.</param>
1015 /// <param name="filterMode">Filtering mode of the RTHandle.</param>
1016 /// <param name="wrapMode">Addressing mode of the RTHandle.</param>
1017 /// <param name="dimension">Texture dimension of the RTHandle.</param>
1018 /// <param name="enableRandomWrite">Set to true to enable UAV random read writes on the texture.</param>
1019 /// <param name="useMipMap">Set to true if the texture should have mipmaps.</param>
1020 /// <param name="autoGenerateMips">Set to true to automatically generate mipmaps.</param>
1021 /// <param name="isShadowMap">Set to true if the depth buffer should be used as a shadow map.</param>
1022 /// <param name="anisoLevel">Anisotropic filtering level.</param>
1023 /// <param name="mipMapBias">Bias applied to mipmaps during filtering.</param>
1024 /// <param name="msaaSamples">Number of MSAA samples.</param>
1025 /// <param name="bindTextureMS">Set to true if the texture needs to be bound as a multisampled texture in the shader.</param>
1026 /// <param name="useDynamicScale">[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</param>
1027 /// <param name="useDynamicScaleExplicit">[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</param>
1028 /// <param name="memoryless">Use this property to set the render texture memoryless modes.</param>
1029 /// <param name="vrUsage">Special treatment of the VR eye texture used in stereoscopic rendering.</param>
1030 /// <param name="name">Name of the RTHandle.</param>
1031 /// <returns>A new RTHandle.</returns>
1032 public RTHandle Alloc(
1033 Vector2 scaleFactor,
1034 int slices = 1,
1035 DepthBits depthBufferBits = DepthBits.None,
1036 GraphicsFormat colorFormat = GraphicsFormat.R8G8B8A8_SRGB,
1037 FilterMode filterMode = FilterMode.Point,
1038 TextureWrapMode wrapMode = TextureWrapMode.Repeat,
1039 TextureDimension dimension = TextureDimension.Tex2D,
1040 bool enableRandomWrite = false,
1041 bool useMipMap = false,
1042 bool autoGenerateMips = true,
1043 bool isShadowMap = false,
1044 int anisoLevel = 1,
1045 float mipMapBias = 0f,
1046 MSAASamples msaaSamples = MSAASamples.None,
1047 bool bindTextureMS = false,
1048 bool useDynamicScale = false,
1049 bool useDynamicScaleExplicit = false,
1050 RenderTextureMemoryless memoryless = RenderTextureMemoryless.None,
1051 VRTextureUsage vrUsage = VRTextureUsage.None,
1052 string name = ""
1053 )
1054 {
1055 var format = (depthBufferBits != DepthBits.None) ? GraphicsFormatUtility.GetDepthStencilFormat((int)depthBufferBits) : colorFormat;
1056
1057 return Alloc(scaleFactor,
1058 format,
1059 slices,
1060 filterMode,
1061 wrapMode,
1062 dimension,
1063 enableRandomWrite,
1064 useMipMap,
1065 autoGenerateMips,
1066 isShadowMap,
1067 anisoLevel,
1068 mipMapBias,
1069 msaaSamples,
1070 bindTextureMS,
1071 useDynamicScale,
1072 useDynamicScaleExplicit,
1073 memoryless,
1074 vrUsage,
1075 name
1076 );
1077 }
1078
1079 /// <summary>
1080 /// Allocate a new automatically sized RTHandle.
1081 /// </summary>
1082 /// <param name="scaleFactor">Constant scale for the RTHandle size computation.</param>
1083 /// <param name="info">Struct containing details of allocation</param>
1084 /// <returns>A new RTHandle.</returns>
1085 public RTHandle Alloc(Vector2 scaleFactor, RTHandleAllocInfo info)
1086 {
1087 int width = Mathf.Max(Mathf.RoundToInt(scaleFactor.x * GetMaxWidth()), 1);
1088 int height = Mathf.Max(Mathf.RoundToInt(scaleFactor.y * GetMaxHeight()), 1);
1089
1090 var rth = AllocAutoSizedRenderTexture(width, height, info);
1091 rth.referenceSize = new Vector2Int(width, height);
1092 rth.scaleFactor = scaleFactor;
1093
1094 return rth;
1095 }
1096
1097 //
1098 // You can provide your own scaling function for advanced scaling schemes (e.g. scaling to
1099 // the next POT). The function takes a Vec2 as parameter that holds max width & height
1100 // values for the current manager context and returns a Vec2 of the final size in pixels.
1101 //
1102 // var rth = Alloc(
1103 // size => new Vector2Int(size.x / 2, size.y),
1104 // [...]
1105 // );
1106 //
1107
1108 /// <summary>
1109 /// Calculate the dimensions (in pixels) of the RTHandles given the scale function. The base unscaled size used, is the sizes passed to the last ResetReferenceSize call.
1110 /// </summary>
1111 /// <param name="scaleFunc">The scale function to use when calculating the dimensions.</param>
1112 /// <returns>The calculated dimensions.</returns>
1113 public Vector2Int CalculateDimensions(ScaleFunc scaleFunc)
1114 {
1115 var scaleFactor = scaleFunc(new Vector2Int(GetMaxWidth(), GetMaxHeight()));
1116 return new Vector2Int(
1117 Mathf.Max(scaleFactor.x, 1),
1118 Mathf.Max(scaleFactor.y, 1)
1119 );
1120 }
1121
1122 /// <summary>
1123 /// Allocate a new automatically sized RTHandle.
1124 /// </summary>
1125 /// <param name="scaleFunc">Function used for the RTHandle size computation.</param>
1126 /// <param name="slices">Number of slices of the RTHandle.</param>
1127 /// <param name="depthBufferBits">Bit depths of a depth buffer.</param>
1128 /// <param name="colorFormat">GraphicsFormat of a color buffer.</param>
1129 /// <param name="filterMode">Filtering mode of the RTHandle.</param>
1130 /// <param name="wrapMode">Addressing mode of the RTHandle.</param>
1131 /// <param name="dimension">Texture dimension of the RTHandle.</param>
1132 /// <param name="enableRandomWrite">Set to true to enable UAV random read writes on the texture.</param>
1133 /// <param name="useMipMap">Set to true if the texture should have mipmaps.</param>
1134 /// <param name="autoGenerateMips">Set to true to automatically generate mipmaps.</param>
1135 /// <param name="isShadowMap">Set to true if the depth buffer should be used as a shadow map.</param>
1136 /// <param name="anisoLevel">Anisotropic filtering level.</param>
1137 /// <param name="mipMapBias">Bias applied to mipmaps during filtering.</param>
1138 /// <param name="msaaSamples">Number of MSAA samples.</param>
1139 /// <param name="bindTextureMS">Set to true if the texture needs to be bound as a multisampled texture in the shader.</param>
1140 /// <param name="useDynamicScale">[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</param>
1141 /// <param name="useDynamicScaleExplicit">[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</param>
1142 /// <param name="memoryless">Use this property to set the render texture memoryless modes.</param>
1143 /// <param name="vrUsage">Special treatment of the VR eye texture used in stereoscopic rendering.</param>
1144 /// <param name="name">Name of the RTHandle.</param>
1145 /// <returns>A new RTHandle.</returns>
1146 public RTHandle Alloc(
1147 ScaleFunc scaleFunc,
1148 int slices = 1,
1149 DepthBits depthBufferBits = DepthBits.None,
1150 GraphicsFormat colorFormat = GraphicsFormat.R8G8B8A8_SRGB,
1151 FilterMode filterMode = FilterMode.Point,
1152 TextureWrapMode wrapMode = TextureWrapMode.Repeat,
1153 TextureDimension dimension = TextureDimension.Tex2D,
1154 bool enableRandomWrite = false,
1155 bool useMipMap = false,
1156 bool autoGenerateMips = true,
1157 bool isShadowMap = false,
1158 int anisoLevel = 1,
1159 float mipMapBias = 0f,
1160 MSAASamples msaaSamples = MSAASamples.None,
1161 bool bindTextureMS = false,
1162 bool useDynamicScale = false,
1163 bool useDynamicScaleExplicit = false,
1164 RenderTextureMemoryless memoryless = RenderTextureMemoryless.None,
1165 VRTextureUsage vrUsage = VRTextureUsage.None,
1166 string name = ""
1167 )
1168 {
1169 var format = (depthBufferBits != DepthBits.None) ? GraphicsFormatUtility.GetDepthStencilFormat((int)depthBufferBits) : colorFormat;
1170
1171 return Alloc(scaleFunc,
1172 format,
1173 slices,
1174 filterMode,
1175 wrapMode,
1176 dimension,
1177 enableRandomWrite,
1178 useMipMap,
1179 autoGenerateMips,
1180 isShadowMap,
1181 anisoLevel,
1182 mipMapBias,
1183 msaaSamples,
1184 bindTextureMS,
1185 useDynamicScale,
1186 useDynamicScaleExplicit,
1187 memoryless,
1188 vrUsage,
1189 name
1190 );
1191 }
1192
1193 /// <summary>
1194 /// Allocate a new automatically sized RTHandle.
1195 /// </summary>
1196 /// <param name="scaleFunc">Function used for the RTHandle size computation.</param>
1197 /// <param name="format">GraphicsFormat of a color or depth stencil buffer.</param>
1198 /// <param name="slices">Number of slices of the RTHandle.</param>
1199 /// <param name="filterMode">Filtering mode of the RTHandle.</param>
1200 /// <param name="wrapMode">Addressing mode of the RTHandle.</param>
1201 /// <param name="dimension">Texture dimension of the RTHandle.</param>
1202 /// <param name="enableRandomWrite">Set to true to enable UAV random read writes on the texture.</param>
1203 /// <param name="useMipMap">Set to true if the texture should have mipmaps.</param>
1204 /// <param name="autoGenerateMips">Set to true to automatically generate mipmaps.</param>
1205 /// <param name="isShadowMap">Set to true if the depth buffer should be used as a shadow map.</param>
1206 /// <param name="anisoLevel">Anisotropic filtering level.</param>
1207 /// <param name="mipMapBias">Bias applied to mipmaps during filtering.</param>
1208 /// <param name="msaaSamples">Number of MSAA samples.</param>
1209 /// <param name="bindTextureMS">Set to true if the texture needs to be bound as a multisampled texture in the shader.</param>
1210 /// <param name="useDynamicScale">[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</param>
1211 /// <param name="useDynamicScaleExplicit">[See Dynamic Resolution documentation](https://docs.unity3d.com/Manual/DynamicResolution.html)</param>
1212 /// <param name="memoryless">Use this property to set the render texture memoryless modes.</param>
1213 /// <param name="vrUsage">Special treatment of the VR eye texture used in stereoscopic rendering.</param>
1214 /// <param name="name">Name of the RTHandle.</param>
1215 /// <returns>A new RTHandle.</returns>
1216 public RTHandle Alloc(
1217 ScaleFunc scaleFunc,
1218 GraphicsFormat format,
1219 int slices = 1,
1220 FilterMode filterMode = FilterMode.Point,
1221 TextureWrapMode wrapMode = TextureWrapMode.Repeat,
1222 TextureDimension dimension = TextureDimension.Tex2D,
1223 bool enableRandomWrite = false,
1224 bool useMipMap = false,
1225 bool autoGenerateMips = true,
1226 bool isShadowMap = false,
1227 int anisoLevel = 1,
1228 float mipMapBias = 0f,
1229 MSAASamples msaaSamples = MSAASamples.None,
1230 bool bindTextureMS = false,
1231 bool useDynamicScale = false,
1232 bool useDynamicScaleExplicit = false,
1233 RenderTextureMemoryless memoryless = RenderTextureMemoryless.None,
1234 VRTextureUsage vrUsage = VRTextureUsage.None,
1235 string name = ""
1236 )
1237 {
1238 var actualDimensions = CalculateDimensions(scaleFunc);
1239
1240 var rth = AllocAutoSizedRenderTexture(actualDimensions.x,
1241 actualDimensions.y,
1242 slices,
1243 format,
1244 filterMode,
1245 wrapMode,
1246 dimension,
1247 enableRandomWrite,
1248 useMipMap,
1249 autoGenerateMips,
1250 isShadowMap,
1251 anisoLevel,
1252 mipMapBias,
1253 msaaSamples,
1254 bindTextureMS,
1255 useDynamicScale,
1256 useDynamicScaleExplicit,
1257 memoryless,
1258 vrUsage,
1259 name
1260 );
1261
1262 rth.referenceSize = actualDimensions;
1263
1264 rth.scaleFunc = scaleFunc;
1265 return rth;
1266 }
1267
1268 /// <summary>
1269 /// Allocate a new automatically sized RTHandle.
1270 /// </summary>
1271 /// <param name="scaleFunc">Function used for the RTHandle size computation.</param>
1272 /// <param name="info">Struct containing details of allocation</param>
1273 /// <returns>A new RTHandle.</returns>
1274 public RTHandle Alloc(ScaleFunc scaleFunc, RTHandleAllocInfo info)
1275 {
1276 var scaleFactor = scaleFunc(new Vector2Int(GetMaxWidth(), GetMaxHeight()));
1277 int width = Mathf.Max(scaleFactor.x, 1);
1278 int height = Mathf.Max(scaleFactor.y, 1);
1279
1280 var rth = AllocAutoSizedRenderTexture(width, height, info);
1281 rth.referenceSize = new Vector2Int(width, height);
1282 rth.scaleFunc = scaleFunc;
1283
1284 return rth;
1285 }
1286
1287 // Internal function
1288 RTHandle AllocAutoSizedRenderTexture(
1289 int width,
1290 int height,
1291 int slices,
1292 GraphicsFormat format,
1293 FilterMode filterMode,
1294 TextureWrapMode wrapMode,
1295 TextureDimension dimension,
1296 bool enableRandomWrite,
1297 bool useMipMap,
1298 bool autoGenerateMips,
1299 bool isShadowMap,
1300 int anisoLevel,
1301 float mipMapBias,
1302 MSAASamples msaaSamples,
1303 bool bindTextureMS,
1304 bool useDynamicScale,
1305 bool useDynamicScaleExplicit,
1306 RenderTextureMemoryless memoryless,
1307 VRTextureUsage vrUsage,
1308 string name
1309 )
1310 {
1311 var rt = CreateRenderTexture(
1312 width, height, format, slices, filterMode, wrapMode, wrapMode, wrapMode, dimension, enableRandomWrite, useMipMap
1313 , autoGenerateMips, isShadowMap, anisoLevel, mipMapBias, msaaSamples, bindTextureMS
1314 , useDynamicScale, useDynamicScaleExplicit, memoryless, vrUsage, name);
1315
1316 var rth = new RTHandle(this);
1317 rth.SetRenderTexture(rt);
1318 rth.m_EnableMSAA = msaaSamples != MSAASamples.None;
1319 rth.m_EnableRandomWrite = enableRandomWrite;
1320 rth.useScaling = true;
1321 rth.m_EnableHWDynamicScale = useDynamicScale;
1322 rth.m_Name = name;
1323 m_AutoSizedRTs.Add(rth);
1324 return rth;
1325 }
1326
1327 RTHandle AllocAutoSizedRenderTexture(int width, int height, RTHandleAllocInfo info)
1328 {
1329 bool isShadowMap = false;
1330 bool useDynamicScaleExplicit = false;
1331
1332 var rt = CreateRenderTexture(
1333 width, height, info.format, info.slices, info.filterMode, info.wrapModeU, info.wrapModeV, info.wrapModeW, info.dimension, info.enableRandomWrite, info.useMipMap
1334 , info.autoGenerateMips, isShadowMap, info.anisoLevel, info.mipMapBias, info.msaaSamples, info.bindTextureMS
1335 , info.useDynamicScale, useDynamicScaleExplicit, info.memoryless, info.vrUsage, info.name);
1336
1337 var rth = new RTHandle(this);
1338 rth.SetRenderTexture(rt);
1339 rth.m_EnableMSAA = info.msaaSamples != MSAASamples.None;
1340 rth.m_EnableRandomWrite = info.enableRandomWrite;
1341 rth.useScaling = true;
1342 rth.m_EnableHWDynamicScale = info.useDynamicScale;
1343 rth.m_Name = info.name;
1344 m_AutoSizedRTs.Add(rth);
1345 return rth;
1346 }
1347
1348 /// <summary>
1349 /// Allocate a RTHandle from a regular RenderTexture.
1350 /// </summary>
1351 /// <param name="texture">Input texture</param>
1352 /// <param name="transferOwnership">Says if the RTHandleSystem has the ownership of the external RenderTarget, false by default</param>
1353 /// <returns>A new RTHandle referencing the input texture.</returns>
1354 public RTHandle Alloc(RenderTexture texture, bool transferOwnership = false)
1355 {
1356 var rth = new RTHandle(this);
1357#if UNITY_EDITOR
1358 Debug.Assert(!(EditorUtility.IsPersistent(texture) == true && transferOwnership == true),
1359 "RTHandle should not have ownership of RenderTarget asset, set transfer ownership as false");
1360#endif
1361 rth.SetRenderTexture(texture, transferOwnership);
1362 rth.m_EnableMSAA = false;
1363 rth.m_EnableRandomWrite = false;
1364 rth.useScaling = false;
1365 rth.m_EnableHWDynamicScale = false;
1366 rth.m_Name = texture.name;
1367 return rth;
1368 }
1369
1370 /// <summary>
1371 /// Allocate a RTHandle from a regular Texture.
1372 /// </summary>
1373 /// <param name="texture">Input texture</param>
1374 /// <returns>A new RTHandle referencing the input texture.</returns>
1375 public RTHandle Alloc(Texture texture)
1376 {
1377 var rth = new RTHandle(this);
1378 rth.SetTexture(texture);
1379 rth.m_EnableMSAA = false;
1380 rth.m_EnableRandomWrite = false;
1381 rth.useScaling = false;
1382 rth.m_EnableHWDynamicScale = false;
1383 rth.m_Name = texture.name;
1384 return rth;
1385 }
1386
1387 /// <summary>
1388 /// Allocate a RTHandle from a regular render target identifier.
1389 /// </summary>
1390 /// <param name="texture">Input render target identifier.</param>
1391 /// <returns>A new RTHandle referencing the input render target identifier.</returns>
1392 public RTHandle Alloc(RenderTargetIdentifier texture)
1393 {
1394 return Alloc(texture, "");
1395 }
1396
1397 /// <summary>
1398 /// Allocate a RTHandle from a regular render target identifier.
1399 /// </summary>
1400 /// <param name="texture">Input render target identifier.</param>
1401 /// <param name="name">Name of the texture.</param>
1402 /// <returns>A new RTHandle referencing the input render target identifier.</returns>
1403 public RTHandle Alloc(RenderTargetIdentifier texture, string name)
1404 {
1405 var rth = new RTHandle(this);
1406 rth.SetTexture(texture);
1407 rth.m_EnableMSAA = false;
1408 rth.m_EnableRandomWrite = false;
1409 rth.useScaling = false;
1410 rth.m_EnableHWDynamicScale = false;
1411 rth.m_Name = name;
1412 return rth;
1413 }
1414
1415 private static RTHandle Alloc(RTHandle tex)
1416 {
1417 Debug.LogError("Allocation a RTHandle from another one is forbidden.");
1418 return null;
1419 }
1420
1421 internal string DumpRTInfo()
1422 {
1423 string result = "";
1424 Array.Resize(ref m_AutoSizedRTsArray, m_AutoSizedRTs.Count);
1425 m_AutoSizedRTs.CopyTo(m_AutoSizedRTsArray);
1426 for (int i = 0, c = m_AutoSizedRTsArray.Length; i < c; ++i)
1427 {
1428 var rt = m_AutoSizedRTsArray[i].rt;
1429 result = string.Format("{0}\nRT ({1})\t Format: {2} W: {3} H {4}\n", result, i, rt.format, rt.width, rt.height);
1430 }
1431
1432 return result;
1433 }
1434
1435 private GraphicsFormat GetStencilFormat(GraphicsFormat depthStencilFormat)
1436 {
1437 return (GraphicsFormatUtility.IsStencilFormat(depthStencilFormat) && SystemInfo.IsFormatSupported(GraphicsFormat.R8_UInt, GraphicsFormatUsage.StencilSampling)) ?
1438 GraphicsFormat.R8_UInt : GraphicsFormat.None;
1439 }
1440 }
1441}