@@ -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}
0 commit comments