-
Notifications
You must be signed in to change notification settings - Fork 869
Expand file tree
/
Copy pathRenderingLayerUtils.cs
More file actions
180 lines (162 loc) · 6.92 KB
/
RenderingLayerUtils.cs
File metadata and controls
180 lines (162 loc) · 6.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
using System;
using System.Collections.Generic;
using UnityEngine.Experimental.Rendering;
namespace UnityEngine.Rendering.Universal
{
/// <summary>
/// Helper class for handling rendering layers.
/// </summary>
internal static class RenderingLayerUtils
{
public enum Event
{
DepthNormalPrePass,
Opaque,
}
public enum MaskSize
{
Bits8,
Bits16,
Bits24,
Bits32,
}
public static void CombineRendererEvents(bool isDeferred, int msaaSampleCount, Event rendererEvent, ref Event combinedEvent)
{
// Rendering layers can not use MSAA resolve, because it encodes integer
if (msaaSampleCount > 1 && !isDeferred)
combinedEvent = Event.DepthNormalPrePass;
// Otherwise we combine them by selecting the min of the two...
else
combinedEvent = Combine(combinedEvent, rendererEvent);
}
/// <summary>
/// Returns True if <see cref="UniversalRenderer"/> will require rendering layers texture.
/// </summary>
/// <param name="universalRenderer"></param>
/// <param name="rendererFeatures">List of renderer features used by the renderer</param>
/// <param name="msaaSampleCount">MSAA sample count</param>
/// <param name="combinedEvent">Event at which rendering layers texture needs to be created</param>
/// <param name="combinedMaskSize">The mask size of rendering layers texture</param>
public static bool RequireRenderingLayers(UniversalRenderer universalRenderer, List<ScriptableRendererFeature> rendererFeatures, int msaaSampleCount, out Event combinedEvent, out MaskSize combinedMaskSize)
{
RenderingMode renderingMode = universalRenderer.renderingModeActual;
bool accurateGBufferNormals = universalRenderer.accurateGbufferNormals;
return RequireRenderingLayers(rendererFeatures, renderingMode, accurateGBufferNormals, msaaSampleCount,
out combinedEvent, out combinedMaskSize);
}
internal static bool RequireRenderingLayers(List<ScriptableRendererFeature> rendererFeatures, RenderingMode renderingMode, bool accurateGbufferNormals, int msaaSampleCount, out Event combinedEvent, out MaskSize combinedMaskSize)
{
combinedEvent = Event.Opaque;
combinedMaskSize = MaskSize.Bits8;
bool isDeferred = renderingMode == RenderingMode.Deferred;
bool result = false;
foreach (var rendererFeature in rendererFeatures)
{
if (rendererFeature.isActive)
{
result |= rendererFeature.RequireRenderingLayers(isDeferred, accurateGbufferNormals, out Event rendererEvent, out MaskSize rendererMaskSize);
combinedEvent = Combine(combinedEvent, rendererEvent);
combinedMaskSize = Combine(combinedMaskSize, rendererMaskSize);
}
}
// Rendering layers can not use MSAA resolve, because it encodes integer
if (msaaSampleCount > 1 && combinedEvent == Event.Opaque)
combinedEvent = Event.DepthNormalPrePass;
// Make sure texture has enough bits to encode all rendering layers in urp global settings
if (UniversalRenderPipelineGlobalSettings.instance)
{
int count = UniversalRenderPipelineGlobalSettings.instance.renderingLayerMaskNames.Length;
MaskSize maskSize = RenderingLayerUtils.GetMaskSize(count);
combinedMaskSize = Combine(combinedMaskSize, maskSize);
}
return result;
}
/// <summary>
/// Setups properties that are needed for accessing rendering layers texture.
/// </summary>
/// <param name="cmd">Used command buffer</param>
/// <param name="maskSize">The mask size of rendering layers texture</param>
public static void SetupProperties(CommandBuffer cmd, MaskSize maskSize)
{
int bits = GetBits(maskSize);
// Pre-computes properties used for packing/unpacking
uint maxInt = bits != 32 ? (1u << bits) - 1u : uint.MaxValue;
float rcpMaxInt = Unity.Mathematics.math.rcp(maxInt);
cmd.SetGlobalInt(ShaderPropertyId.renderingLayerMaxInt, (int)maxInt);
cmd.SetGlobalFloat(ShaderPropertyId.renderingLayerRcpMaxInt, rcpMaxInt);
}
/// <summary>
/// Converts rendering layers texture mask size to graphics format.
/// </summary>
public static GraphicsFormat GetFormat(MaskSize maskSize)
{
switch (maskSize)
{
case MaskSize.Bits8:
return GraphicsFormat.R8_UNorm;
case MaskSize.Bits16:
return GraphicsFormat.R16_UNorm;
case MaskSize.Bits24:
case MaskSize.Bits32:
return GraphicsFormat.R32_SFloat;
default:
throw new NotImplementedException();
}
}
/// <summary>
/// Masks rendering layers with those that available in urp global settings.
/// </summary>
public static uint ToValidRenderingLayers(uint renderingLayers)
{
if (UniversalRenderPipelineGlobalSettings.instance)
{
uint validRenderingLayers = UniversalRenderPipelineGlobalSettings.instance.validRenderingLayers;
return validRenderingLayers & renderingLayers;
}
return renderingLayers;
}
static MaskSize GetMaskSize(int bits)
{
int bytes = (bits + 7) / 8;
switch (bytes)
{
case 0:
return MaskSize.Bits8;
case 1:
return MaskSize.Bits8;
case 2:
return MaskSize.Bits16;
case 3:
return MaskSize.Bits24;
case 4:
return MaskSize.Bits32;
default:
return MaskSize.Bits32;
}
}
static int GetBits(MaskSize maskSize)
{
switch (maskSize)
{
case MaskSize.Bits8:
return 8;
case MaskSize.Bits16:
return 16;
case MaskSize.Bits24:
return 24;
case MaskSize.Bits32:
return 32;
default:
throw new NotImplementedException();
}
}
static Event Combine(Event a, Event b)
{
return (Event)Mathf.Min((int)a, (int)b);
}
static MaskSize Combine(MaskSize a, MaskSize b)
{
return (MaskSize)Mathf.Max((int)a, (int)b);
}
}
}