Skip to content

Commit 44e6ec4

Browse files
Merge branch '10.x.x/release' into HDRP/backport-4265
2 parents f90683f + 08be9e0 commit 44e6ec4

File tree

9 files changed

+337
-112
lines changed

9 files changed

+337
-112
lines changed

com.unity.render-pipelines.core/Runtime/Common/ConstantBuffer.cs

Lines changed: 133 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public class ConstantBuffer
1919
/// <param name="shaderId">Shader porperty id to bind the constant buffer to.</param>
2020
public static void PushGlobal<CBType>(CommandBuffer cmd, in CBType data, int shaderId) where CBType : struct
2121
{
22-
var cb = TypedConstantBuffer<CBType>.instance;
22+
var cb = ConstantBufferSingleton<CBType>.instance;
2323

2424
cb.UpdateData(cmd, data);
2525
cb.SetGlobal(cmd, shaderId);
@@ -35,7 +35,7 @@ public static void PushGlobal<CBType>(CommandBuffer cmd, in CBType data, int sha
3535
/// <param name="shaderId">Shader porperty id to bind the constant buffer to.</param>
3636
public static void Push<CBType>(CommandBuffer cmd, in CBType data, ComputeShader cs, int shaderId) where CBType : struct
3737
{
38-
var cb = TypedConstantBuffer<CBType>.instance;
38+
var cb = ConstantBufferSingleton<CBType>.instance;
3939

4040
cb.UpdateData(cmd, data);
4141
cb.Set(cmd, cs, shaderId);
@@ -51,7 +51,7 @@ public static void Push<CBType>(CommandBuffer cmd, in CBType data, ComputeShader
5151
/// <param name="shaderId">Shader porperty id to bind the constant buffer to.</param>
5252
public static void Push<CBType>(CommandBuffer cmd, in CBType data, Material mat, int shaderId) where CBType : struct
5353
{
54-
var cb = TypedConstantBuffer<CBType>.instance;
54+
var cb = ConstantBufferSingleton<CBType>.instance;
5555

5656
cb.UpdateData(cmd, data);
5757
cb.Set(mat, shaderId);
@@ -65,7 +65,7 @@ public static void Push<CBType>(CommandBuffer cmd, in CBType data, Material mat,
6565
/// <param name="data">Input data of the constant buffer.</param>
6666
public static void UpdateData<CBType>(CommandBuffer cmd, in CBType data) where CBType : struct
6767
{
68-
var cb = TypedConstantBuffer<CBType>.instance;
68+
var cb = ConstantBufferSingleton<CBType>.instance;
6969

7070
cb.UpdateData(cmd, data);
7171
}
@@ -78,7 +78,7 @@ public static void UpdateData<CBType>(CommandBuffer cmd, in CBType data) where C
7878
/// <param name="shaderId">Shader porperty id to bind the constant buffer to.</param>
7979
public static void SetGlobal<CBType>(CommandBuffer cmd, int shaderId) where CBType : struct
8080
{
81-
var cb = TypedConstantBuffer<CBType>.instance;
81+
var cb = ConstantBufferSingleton<CBType>.instance;
8282

8383
cb.SetGlobal(cmd, shaderId);
8484
}
@@ -92,7 +92,7 @@ public static void SetGlobal<CBType>(CommandBuffer cmd, int shaderId) where CBTy
9292
/// <param name="shaderId">Shader porperty id to bind the constant buffer to.</param>
9393
public static void Set<CBType>(CommandBuffer cmd, ComputeShader cs, int shaderId) where CBType : struct
9494
{
95-
var cb = TypedConstantBuffer<CBType>.instance;
95+
var cb = ConstantBufferSingleton<CBType>.instance;
9696

9797
cb.Set(cmd, cs, shaderId);
9898
}
@@ -105,14 +105,14 @@ public static void Set<CBType>(CommandBuffer cmd, ComputeShader cs, int shaderId
105105
/// <param name="shaderId">Shader porperty id to bind the constant buffer to.</param>
106106
public static void Set<CBType>(Material mat, int shaderId) where CBType : struct
107107
{
108-
var cb = TypedConstantBuffer<CBType>.instance;
108+
var cb = ConstantBufferSingleton<CBType>.instance;
109109

110110
cb.Set(mat, shaderId);
111111
}
112112

113113
/// <summary>
114-
/// Release all currently allocated constant buffers.
115-
/// This needs to be called before shutting down the application.
114+
/// Release all currently allocated singleton constant buffers.
115+
/// This needs to be called before shutting down the application.
116116
/// </summary>
117117
public static void ReleaseAll()
118118
{
@@ -122,86 +122,149 @@ public static void ReleaseAll()
122122
m_RegisteredConstantBuffers.Clear();
123123
}
124124

125-
internal abstract class ConstantBufferBase
126-
{
127-
public abstract void Release();
128-
}
129-
130125
internal static void Register(ConstantBufferBase cb)
131126
{
132127
m_RegisteredConstantBuffers.Add(cb);
133128
}
134129

135-
class TypedConstantBuffer<CBType> : ConstantBufferBase where CBType : struct
136-
{
137-
// Used to track all global bindings used by this CB type.
138-
HashSet<int> m_GlobalBindings = new HashSet<int>();
139-
// Array is required by the ComputeBuffer SetData API
140-
CBType[] m_Data = new CBType[1];
130+
}
141131

142-
static TypedConstantBuffer<CBType> s_Instance = null;
143-
internal static TypedConstantBuffer<CBType> instance
144-
{
145-
get
146-
{
147-
if (s_Instance == null)
148-
s_Instance = new TypedConstantBuffer<CBType>();
149-
return s_Instance;
150-
}
151-
set
152-
{
153-
s_Instance = value;
154-
}
155-
}
156-
ComputeBuffer m_GPUConstantBuffer = null;
132+
/// <summary>
133+
/// The base class of Constant Buffer.
134+
/// </summary>
135+
public abstract class ConstantBufferBase
136+
{
137+
/// <summary>
138+
/// Release the constant buffer.
139+
/// </summary>
140+
public abstract void Release();
141+
}
157142

158-
TypedConstantBuffer()
159-
{
160-
m_GPUConstantBuffer = new ComputeBuffer(1, UnsafeUtility.SizeOf<CBType>(), ComputeBufferType.Constant);
161-
ConstantBuffer.Register(this);
162-
}
163143

164-
public void UpdateData(CommandBuffer cmd, in CBType data)
165-
{
166-
m_Data[0] = data;
144+
/// <summary>
145+
/// An instance of a constant buffer.
146+
/// </summary>
147+
/// <typeparam name="CBType">The type of structure representing the constant buffer data.</typeparam>
148+
public class ConstantBuffer<CBType> : ConstantBufferBase where CBType : struct
149+
{
150+
// Used to track all global bindings used by this CB type.
151+
HashSet<int> m_GlobalBindings = new HashSet<int>();
152+
// Array is required by the ComputeBuffer SetData API
153+
CBType[] m_Data = new CBType[1];
154+
155+
156+
ComputeBuffer m_GPUConstantBuffer = null;
157+
158+
/// <summary>
159+
/// Constant Buffer constructor.
160+
/// </summary>
161+
public ConstantBuffer()
162+
{
163+
m_GPUConstantBuffer = new ComputeBuffer(1, UnsafeUtility.SizeOf<CBType>(), ComputeBufferType.Constant);
164+
}
165+
166+
/// <summary>
167+
/// Update the GPU data of the constant buffer.
168+
/// </summary>
169+
/// <param name="cmd">Command Buffer used to execute the graphic commands.</param>
170+
/// <param name="data">Input data of the constant buffer.</param>
171+
public void UpdateData(CommandBuffer cmd, in CBType data)
172+
{
173+
m_Data[0] = data;
167174
#if UNITY_2021_1_OR_NEWER
168-
cmd.SetBufferData(m_GPUConstantBuffer, m_Data);
175+
cmd.SetBufferData(m_GPUConstantBuffer, m_Data);
169176
#else
170177
cmd.SetComputeBufferData(m_GPUConstantBuffer, m_Data);
171178
#endif
172-
}
179+
}
173180

174-
public void SetGlobal(CommandBuffer cmd, int shaderId)
175-
{
176-
m_GlobalBindings.Add(shaderId);
177-
cmd.SetGlobalConstantBuffer(m_GPUConstantBuffer, shaderId, 0, m_GPUConstantBuffer.stride);
178-
}
181+
/// <summary>
182+
/// Bind the constant buffer globally.
183+
/// </summary>
184+
/// <param name="cmd">Command Buffer used to execute the graphic commands.</param>
185+
/// <param name="shaderId">Shader porperty id to bind the constant buffer to.</param>
186+
public void SetGlobal(CommandBuffer cmd, int shaderId)
187+
{
188+
m_GlobalBindings.Add(shaderId);
189+
cmd.SetGlobalConstantBuffer(m_GPUConstantBuffer, shaderId, 0, m_GPUConstantBuffer.stride);
190+
}
179191

180-
public void Set(CommandBuffer cmd, ComputeShader cs, int shaderId)
181-
{
182-
cmd.SetComputeConstantBufferParam(cs, shaderId, m_GPUConstantBuffer, 0, m_GPUConstantBuffer.stride);
183-
}
192+
/// <summary>
193+
/// Bind the constant buffer to a compute shader.
194+
/// </summary>
195+
/// <param name="cmd">Command Buffer used to execute the graphic commands.</param>
196+
/// <param name="cs">Compute shader to which the constant buffer should be bound.</param>
197+
/// <param name="shaderId">Shader porperty id to bind the constant buffer to.</param>
198+
public void Set(CommandBuffer cmd, ComputeShader cs, int shaderId)
199+
{
200+
cmd.SetComputeConstantBufferParam(cs, shaderId, m_GPUConstantBuffer, 0, m_GPUConstantBuffer.stride);
201+
}
202+
203+
/// <summary>
204+
/// Bind the constant buffer to a material.
205+
/// </summary>
206+
/// <param name="mat">Material to which the constant buffer should be bound.</param>
207+
/// <param name="shaderId">Shader porperty id to bind the constant buffer to.</param>
208+
public void Set(Material mat, int shaderId)
209+
{
210+
// This isn't done via command buffer because as long as the buffer itself is not destroyed,
211+
// the binding stays valid. Only the commit of data needs to go through the command buffer.
212+
// We do it here anyway for now to simplify user API.
213+
mat.SetConstantBuffer(shaderId, m_GPUConstantBuffer, 0, m_GPUConstantBuffer.stride);
214+
}
215+
216+
/// <summary>
217+
/// Update the GPU data of the constant buffer and bind it globally.
218+
/// </summary>
219+
/// <param name="cmd">Command Buffer used to execute the graphic commands.</param>
220+
/// <param name="data">Input data of the constant buffer.</param>
221+
/// <param name="shaderId">Shader porperty id to bind the constant buffer to.</param>
222+
public void PushGlobal(CommandBuffer cmd, in CBType data, int shaderId)
223+
{
224+
UpdateData(cmd, data);
225+
SetGlobal(cmd, shaderId);
226+
}
227+
228+
/// <summary>
229+
/// Release the constant buffers.
230+
/// </summary>
231+
public override void Release()
232+
{
233+
// Depending on the device, globally bound buffers can leave stale "valid" shader ids pointing to a destroyed buffer.
234+
// In DX11 it does not cause issues but on Vulkan this will result in skipped drawcalls (even if the buffer is not actually accessed in the shader).
235+
// To avoid this kind of issues, it's good practice to "unbind" all globally bound buffers upon destruction.
236+
foreach (int shaderId in m_GlobalBindings)
237+
Shader.SetGlobalConstantBuffer(shaderId, (ComputeBuffer)null, 0, 0);
238+
m_GlobalBindings.Clear();
184239

185-
public void Set(Material mat, int shaderId)
240+
CoreUtils.SafeRelease(m_GPUConstantBuffer);
241+
}
242+
}
243+
244+
class ConstantBufferSingleton<CBType> : ConstantBuffer<CBType> where CBType : struct
245+
{
246+
static ConstantBufferSingleton<CBType> s_Instance = null;
247+
internal static ConstantBufferSingleton<CBType> instance
248+
{
249+
get
186250
{
187-
// This isn't done via command buffer because as long as the buffer itself is not destroyed,
188-
// the binding stays valid. Only the commit of data needs to go through the command buffer.
189-
// We do it here anyway for now to simplify user API.
190-
mat.SetConstantBuffer(shaderId, m_GPUConstantBuffer, 0, m_GPUConstantBuffer.stride);
251+
if (s_Instance == null)
252+
{
253+
s_Instance = new ConstantBufferSingleton<CBType>();
254+
ConstantBuffer.Register(s_Instance);
255+
}
256+
return s_Instance;
191257
}
192-
193-
public override void Release()
258+
set
194259
{
195-
// Depending on the device, globally bound buffers can leave stale "valid" shader ids pointing to a destroyed buffer.
196-
// In DX11 it does not cause issues but on Vulkan this will result in skipped drawcalls (even if the buffer is not actually accessed in the shader).
197-
// To avoid this kind of issues, it's good practice to "unbind" all globally bound buffers upon destruction.
198-
foreach (int shaderId in m_GlobalBindings)
199-
Shader.SetGlobalConstantBuffer(shaderId, (ComputeBuffer)null, 0, 0);
200-
m_GlobalBindings.Clear();
201-
202-
CoreUtils.SafeRelease(m_GPUConstantBuffer);
203-
s_Instance = null;
260+
s_Instance = value;
204261
}
205262
}
263+
264+
public override void Release()
265+
{
266+
base.Release();
267+
s_Instance = null;
268+
}
206269
}
207270
}

com.unity.render-pipelines.high-definition/Editor/BuildProcessors/HDRPPreprocessShaders.cs

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using UnityEngine.Rendering.HighDefinition;
88
using System.Diagnostics;
99
using Debug = UnityEngine.Debug;
10+
using System.Reflection;
1011

1112
namespace UnityEditor.Rendering.HighDefinition
1213
{
@@ -297,6 +298,11 @@ public void OnProcessComputeShader(ComputeShader shader, string kernelName, ILis
297298
if (HDRenderPipeline.currentAsset == null)
298299
return;
299300

301+
// Discard any compute shader use for raytracing if none of the RP asset required it
302+
ComputeShader unused;
303+
if (!ShaderBuildPreprocessor.playerNeedRaytracing && ShaderBuildPreprocessor.computeShaderCache.TryGetValue(shader.GetInstanceID(), out unused))
304+
return;
305+
300306
var exportLog = ShaderBuildPreprocessor.hdrpAssets.Count > 0
301307
&& ShaderBuildPreprocessor.hdrpAssets.Any(hdrpAsset => hdrpAsset.shaderVariantLogLevel != ShaderVariantLogLevel.Disabled);
302308

@@ -535,23 +541,73 @@ public void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList<Shad
535541
class ShaderBuildPreprocessor : IPreprocessBuildWithReport
536542
{
537543
private static List<HDRenderPipelineAsset> _hdrpAssets;
544+
private static Dictionary<int, ComputeShader> s_ComputeShaderCache;
545+
private static bool s_PlayerNeedRaytracing;
538546

539547
public static List<HDRenderPipelineAsset> hdrpAssets
540548
{
541549
get
542550
{
543-
if (_hdrpAssets == null || _hdrpAssets.Count == 0) GetAllValidHDRPAssets();
551+
if (_hdrpAssets == null || _hdrpAssets.Count == 0)
552+
GetAllValidHDRPAssets();
544553
return _hdrpAssets;
545554
}
546555
}
547556

557+
public static Dictionary<int, ComputeShader> computeShaderCache
558+
{
559+
get
560+
{
561+
if (s_ComputeShaderCache == null)
562+
BuilRaytracingComputeList();
563+
return s_ComputeShaderCache;
564+
}
565+
}
566+
567+
public static bool playerNeedRaytracing
568+
{
569+
get
570+
{
571+
return s_PlayerNeedRaytracing;
572+
}
573+
}
574+
575+
public static void BuilRaytracingComputeList()
576+
{
577+
if (s_ComputeShaderCache != null)
578+
s_ComputeShaderCache.Clear();
579+
else
580+
s_ComputeShaderCache = new Dictionary<int, ComputeShader>();
581+
582+
if (HDRenderPipeline.defaultAsset == null)
583+
return;
584+
585+
if (HDRenderPipeline.defaultAsset.renderPipelineRayTracingResources == null)
586+
return;
587+
588+
foreach (var fieldInfo in HDRenderPipeline.defaultAsset.renderPipelineRayTracingResources.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
589+
{
590+
ComputeShader computeshader;
591+
computeshader = fieldInfo.GetValue(HDRenderPipeline.defaultAsset.renderPipelineRayTracingResources) as ComputeShader;
592+
593+
if (computeshader != null)
594+
{
595+
s_ComputeShaderCache.Add(computeshader.GetInstanceID(), computeshader);
596+
}
597+
}
598+
}
599+
548600
static void GetAllValidHDRPAssets()
549601
{
602+
s_PlayerNeedRaytracing = false;
603+
550604
if (HDRenderPipeline.currentAsset == null)
551605
return;
552606

553-
if (_hdrpAssets != null) _hdrpAssets.Clear();
554-
else _hdrpAssets = new List<HDRenderPipelineAsset>();
607+
if (_hdrpAssets != null)
608+
_hdrpAssets.Clear();
609+
else
610+
_hdrpAssets = new List<HDRenderPipelineAsset>();
555611

556612
using (ListPool<HDRenderPipelineAsset>.Get(out var tmpAssets))
557613
{
@@ -642,6 +698,15 @@ static void GetAllValidHDRPAssets()
642698
Debug.LogWarning("There is no HDRP Asset provided in GraphicsSettings. Build time can be extremely long without it.");
643699
}
644700
}
701+
else
702+
{
703+
// Take the opportunity to know if we need raytracing at runtime
704+
foreach (var hdrpAsset in _hdrpAssets)
705+
{
706+
if (hdrpAsset.currentPlatformRenderPipelineSettings.supportRayTracing)
707+
s_PlayerNeedRaytracing = true;
708+
}
709+
}
645710

646711
/*
647712
Debug.Log(string.Format("{0} HDRP assets in build:{1}",

0 commit comments

Comments
 (0)