Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
Buffer.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 //
4 // Copyright (c) 2010-2012 SharpDX - Alexandre Mutel
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to deal
8 // in the Software without restriction, including without limitation the rights
9 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 // copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 // THE SOFTWARE.
23 
24 using System;
25 using SiliconStudio.Core;
26 using SiliconStudio.Core.Serialization.Converters;
27 
28 namespace SiliconStudio.Paradox.Graphics
29 {
30  /// <summary>
31  /// All-in-One Buffer class linked <see cref="SharpDX.Direct3D11.Buffer"/>.
32  /// </summary>
33  /// <remarks>
34  /// This class is able to create constant buffers, indexelementCountrtex buffers, structured buffer, raw buffers, argument buffers.
35  /// </remarks>
36  [DataConverter(AutoGenerate = false, ContentReference = true)]
37  public partial class Buffer : GraphicsResource
38  {
39  protected int elementCount;
40 
41  /// <summary>
42  /// Gets the description of this buffer.
43  /// </summary>
44  public readonly BufferDescription Description;
45 
46  /// <summary>
47  /// Gets the number of elements.
48  /// </summary>
49  /// <remarks>
50  /// This value is valid for structured buffers, raw buffers and index buffers that are used as a SharedResourceView.
51  /// </remarks>
52  public int ElementCount
53  {
54  get
55  {
56  return elementCount;
57  }
58  protected set
59  {
60  elementCount = value;
61  }
62  }
63 
64  /// <summary>
65  /// Gets the type of this belementCount /// </summary>
66  public readonly BufferFlags BufferFlags;
67 
68  /// <summary>
69  /// Gets the default view format of this buffer.
70  /// </summary>
71  public readonly PixelFormat ViewFormat;
72 
73  /// <summary>
74  /// Return an equivalent staging texture CPU read-writable from this instance.
75  /// </summary>
76  /// <returns>A new instance of this buffer as a staging resource</returns>
77  public Buffer ToStaging()
78  {
79  var stagingDesc = Description;
80  stagingDesc.Usage = GraphicsResourceUsage.Staging;
81  stagingDesc.BufferFlags = BufferFlags.None;
82  return new Buffer(GraphicsDevice, stagingDesc, BufferFlags.None, ViewFormat, IntPtr.Zero);
83  }
84 
85  /// <summary>
86  /// Clones this instance.
87  /// </summary>
88  /// <returns>A clone of this instance</returns>
89  /// <remarks>
90  /// This method will not copy the content of the buffer to the clone
91  /// </remarks>
92  public Buffer Clone()
93  {
94  return new Buffer(GraphicsDevice, Description, BufferFlags, ViewFormat, IntPtr.Zero);
95  }
96 
97  /// <summary>
98  /// Gets the content of this buffer to an array of data.
99  /// </summary>
100  /// <typeparam name="TData">The type of the T data.</typeparam>
101  /// <remarks>
102  /// This method is only working when called from the main thread that is accessing the main <see cref="GraphicsDevice"/>.
103  /// This method creates internally a stagging resource if this texture is not already a stagging resouce, copies to it and map it to memory. Use method with explicit staging resource
104  /// for optimal performances.</remarks>
105  public TData[] GetData<TData>() where TData : struct
106  {
107  var toData = new TData[this.Description.SizeInBytes / Utilities.SizeOf<TData>()];
108  GetData(toData);
109  return toData;
110  }
111 
112  /// <summary>
113  /// Copies the content of this buffer to an array of data.
114  /// </summary>
115  /// <typeparam name="TData">The type of the T data.</typeparam>
116  /// <param name="toData">The destination buffer to receive a copy of the texture datas.</param>
117  /// <remarks>
118  /// This method is only working when called from the main thread that is accessing the main <see cref="GraphicsDevice"/>.
119  /// This method creates internally a stagging resource if this texture is not already a stagging resouce, copies to it and map it to memory. Use method with explicit staging resource
120  /// for optimal performances.</remarks>
121  public void GetData<TData>(TData[] toData) where TData : struct
122  {
123  // Get data from this resource
124  if (this.Description.Usage == GraphicsResourceUsage.Staging)
125  {
126  // Directly if this is a staging resource
127  GetData(this, toData);
128  }
129  else
130  {
131  // Unefficient way to use the Copy method using dynamic staging texture
132  using (var throughStaging = this.ToStaging())
133  GetData(throughStaging, toData);
134  }
135  }
136 
137  /// <summary>
138  /// Copies the content of this buffer to an array of data.
139  /// </summary>
140  /// <typeparam name="TData">The type of the T data.</typeparam>
141  /// <param name="toData">The destination buffer to receive a copy of the texture datas.</param>
142  /// <remarks>
143  /// This method is only working when called from the main thread that is accessing the main <see cref="GraphicsDevice"/>.
144  /// This method creates internally a stagging resource if this texture is not already a stagging resouce, copies to it and map it to memory. Use method with explicit staging resource
145  /// for optimal performances.</remarks>
146  public void GetData<TData>(ref TData toData) where TData : struct
147  {
148  // Get data from this resource
149  if (this.Description.Usage == GraphicsResourceUsage.Staging)
150  {
151  // Directly if this is a staging resource
152  GetData(this, ref toData);
153  }
154  else
155  {
156  // Unefficient way to use the Copy method using dynamic staging texture
157  using (var throughStaging = this.ToStaging())
158  GetData(throughStaging, ref toData);
159  }
160  }
161 
162  /// <summary>
163  /// Copies the content of this buffer from GPU memory to an array of data on CPU memory using a specific staging resource.
164  /// </summary>
165  /// <typeparam name="TData">The type of the T data.</typeparam>
166  /// <param name="stagingTexture">The staging buffer used to transfer the buffer.</param>
167  /// <param name="toData">To data.</param>
168  /// <exception cref="System.ArgumentException">When strides is different from optimal strides, and TData is not the same size as the pixel format, or Width * Height != toData.Length</exception>
169  /// <remarks>
170  /// This method is only working when called from the main thread that is accessing the main <see cref="GraphicsDevice"/>.
171  /// </remarks>
172  public unsafe void GetData<TData>(Buffer stagingTexture, ref TData toData) where TData : struct
173  {
174  GetData(stagingTexture, new DataPointer(Interop.Fixed(ref toData), Utilities.SizeOf<TData>()));
175  }
176 
177  /// <summary>
178  /// Copies the content of this buffer from GPU memory to an array of data on CPU memory using a specific staging resource.
179  /// </summary>
180  /// <typeparam name="TData">The type of the T data.</typeparam>
181  /// <param name="stagingTexture">The staging buffer used to transfer the buffer.</param>
182  /// <param name="toData">To data.</param>
183  /// <exception cref="System.ArgumentException">When strides is different from optimal strides, and TData is not the same size as the pixel format, or Width * Height != toData.Length</exception>
184  /// <remarks>
185  /// This method is only working when called from the main thread that is accessing the main <see cref="GraphicsDevice"/>.
186  /// </remarks>
187  public unsafe void GetData<TData>(Buffer stagingTexture, TData[] toData) where TData : struct
188  {
189  GetData(stagingTexture, new DataPointer(Interop.Fixed(toData), toData.Length * Utilities.SizeOf<TData>()));
190  }
191 
192  /// <summary>
193  /// Copies the content of a single structure data from CPU memory to this buffer into GPU memory.
194  /// </summary>
195  /// <typeparam name="TData">The type of the T data.</typeparam>
196  /// <param name="fromData">The data to copy from.</param>
197  /// <param name="offsetInBytes">The offset in bytes to write to.</param>
198  /// <exception cref="System.ArgumentException"></exception>
199  /// <remarks>
200  /// This method is only working when called from the main thread that is accessing the main <see cref="GraphicsDevice"/>. See the unmanaged documentation about Map/UnMap for usage and restrictions.
201  /// </remarks>
202  public void SetData<TData>(ref TData fromData, int offsetInBytes = 0) where TData : struct
203  {
204  SetData(GraphicsDevice, ref fromData, offsetInBytes);
205  }
206 
207  /// <summary>
208  /// Copies the content an array of data from CPU memory to this buffer into GPU memory.
209  /// </summary>
210  /// <typeparam name="TData">The type of the T data.</typeparam>
211  /// <param name="fromData">The data to copy from.</param>
212  /// <param name="offsetInBytes">The offset in bytes to write to.</param>
213  /// <exception cref="System.ArgumentException"></exception>
214  /// <remarks>
215  /// This method is only working when called from the main thread that is accessing the main <see cref="GraphicsDevice"/>. See the unmanaged documentation about Map/UnMap for usage and restrictions.
216  /// </remarks>
217  public unsafe void SetData<TData>(TData[] fromData, int offsetInBytes = 0) where TData : struct
218  {
219  SetData(GraphicsDevice, fromData, offsetInBytes);
220  }
221 
222  /// <summary>
223  /// Copies the content an array of data on CPU memory to this buffer into GPU memory.
224  /// </summary>
225  /// <param name="fromData">A data pointer.</param>
226  /// <param name="offsetInBytes">The offset in bytes to write to.</param>
227  /// <exception cref="System.ArgumentException"></exception>
228  /// <remarks>
229  /// This method is only working when called from the main thread that is accessing the main <see cref="GraphicsDevice"/>. See the unmanaged documentation about Map/UnMap for usage and restrictions.
230  /// </remarks>
231  public void SetData(DataPointer fromData, int offsetInBytes = 0)
232  {
233  SetData(GraphicsDevice, fromData, offsetInBytes);
234  }
235 
236  /// <summary>
237  /// Copies the content an array of data on CPU memory to this buffer into GPU memory.
238  /// </summary>
239  /// <typeparam name="TData">The type of the T data.</typeparam>
240  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
241  /// <param name="fromData">The data to copy from.</param>
242  /// <param name="offsetInBytes">The offset in bytes to write to.</param>
243  /// <exception cref="System.ArgumentException"></exception>
244  /// <remarks>
245  /// See the unmanaged documentation about Map/UnMap for usage and restrictions.
246  /// </remarks>
247  public unsafe void SetData<TData>(GraphicsDevice device, ref TData fromData, int offsetInBytes = 0) where TData : struct
248  {
249  SetData(device, new DataPointer(Interop.Fixed(ref fromData), Utilities.SizeOf<TData>()), offsetInBytes);
250  }
251 
252  /// <summary>
253  /// Copies the content an array of data on CPU memory to this buffer into GPU memory.
254  /// </summary>
255  /// <typeparam name="TData">The type of the T data.</typeparam>
256  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
257  /// <param name="fromData">The data to copy from.</param>
258  /// <param name="offsetInBytes">The offset in bytes to write to.</param>
259  /// <exception cref="System.ArgumentException"></exception>
260  /// <remarks>
261  /// See the unmanaged documentation about Map/UnMap for usage and restrictions.
262  /// </remarks>
263  public unsafe void SetData<TData>(GraphicsDevice device, TData[] fromData, int offsetInBytes = 0) where TData : struct
264  {
265  SetData(device, new DataPointer(Interop.Fixed(fromData), (fromData.Length * Utilities.SizeOf<TData>())), offsetInBytes);
266  }
267 
268 
269  /// <summary>
270  /// Copies the content of this buffer from GPU memory to a CPU memory using a specific staging resource.
271  /// </summary>
272  /// <param name="stagingTexture">The staging buffer used to transfer the buffer.</param>
273  /// <param name="toData">To data pointer.</param>
274  /// <exception cref="System.ArgumentException">When strides is different from optimal strides, and TData is not the same size as the pixel format, or Width * Height != toData.Length</exception>
275  /// <remarks>
276  /// This method is only working when called from the main thread that is accessing the main <see cref="GraphicsDevice"/>.
277  /// </remarks>
278  public void GetData(Buffer stagingTexture, DataPointer toData)
279  {
280  // Check size validity of data to copy to
281  if (toData.Size > this.Description.SizeInBytes)
282  throw new ArgumentException("Length of TData is larger than size of buffer");
283 
284  // Copy the texture to a staging resource
285  if (!ReferenceEquals(this, stagingTexture))
286  GraphicsDevice.Copy(this, stagingTexture);
287 
288  // Map the staging resource to a CPU accessible memory
289  var mappedResource = GraphicsDevice.MapSubresource(stagingTexture, 0, MapMode.Read);
290  Utilities.CopyMemory(toData.Pointer, mappedResource.DataBox.DataPointer, toData.Size);
291  // Make sure that we unmap the resource in case of an exception
292  GraphicsDevice.UnmapSubresource(mappedResource);
293  }
294 
295  /// <summary>
296  /// Copies the content an array of data on CPU memory to this buffer into GPU memory.
297  /// </summary>
298  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
299  /// <param name="fromData">A data pointer.</param>
300  /// <param name="offsetInBytes">The offset in bytes to write to.</param>
301  /// <exception cref="System.ArgumentException"></exception>
302  /// <remarks>
303  /// See the unmanaged documentation about Map/UnMap for usage and restrictions.
304  /// </remarks>
305  public void SetData(GraphicsDevice device, DataPointer fromData, int offsetInBytes = 0)
306  {
307  // Check size validity of data to copy to
308  if (fromData.Size > this.Description.SizeInBytes)
309  throw new ArgumentException("Size of data to upload larger than size of buffer");
310 
311  // If this texture is declared as default usage, we can only use UpdateSubresource, which is not optimal but better than nothing
312  if (this.Description.Usage == GraphicsResourceUsage.Default)
313  {
314  // Setup the dest region inside the buffer
315  if ((this.Description.BufferFlags & BufferFlags.ConstantBuffer) != 0)
316  {
317  device.UpdateSubresource(this, 0, new DataBox(fromData.Pointer, 0, 0));
318  }
319  else
320  {
321  var destRegion = new ResourceRegion(offsetInBytes, 0, 0, offsetInBytes + fromData.Size, 1, 1);
322  device.UpdateSubresource(this, 0, new DataBox(fromData.Pointer, 0, 0), destRegion);
323  }
324  }
325  else
326  {
327  if (offsetInBytes > 0)
328  throw new ArgumentException("offset is only supported for textured declared with ResourceUsage.Default", "offsetInBytes");
329 
330  var mappedResource = device.MapSubresource(this, 0, MapMode.WriteDiscard);
331  Utilities.CopyMemory(mappedResource.DataBox.DataPointer, fromData.Pointer, fromData.Size);
332  device.UnmapSubresource(mappedResource);
333  }
334  }
335 
336  /// <summary>
337  /// Creates a new <see cref="Buffer" /> instance.
338  /// </summary>
339  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
340  /// <param name="description">The description of the buffer.</param>
341  /// <param name="viewFormat">View format used if the buffer is used as a shared resource view.</param>
342  /// <returns>An instance of a new <see cref="Buffer" /></returns>
343  public static Buffer New(GraphicsDevice device, BufferDescription description, PixelFormat viewFormat = PixelFormat.None)
344  {
345  var bufferType = description.BufferFlags;
346  return new Buffer(device, description, bufferType, viewFormat, IntPtr.Zero);
347  }
348 
349  /// <summary>
350  /// Creates a new <see cref="Buffer" /> instance.
351  /// </summary>
352  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
353  /// <param name="bufferSize">Size of the buffer in bytes.</param>
354  /// <param name="bufferFlags">The buffer flags to specify the type of buffer.</param>
355  /// <param name="usage">The usage.</param>
356  /// <returns>An instance of a new <see cref="Buffer" /></returns>
357  public static Buffer New(GraphicsDevice device, int bufferSize, BufferFlags bufferFlags, GraphicsResourceUsage usage = GraphicsResourceUsage.Default)
358  {
359  return New(device, bufferSize, 0, bufferFlags, PixelFormat.None, usage);
360  }
361 
362  /// <summary>
363  /// Creates a new <see cref="Buffer" /> instance.
364  /// </summary>
365  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
366  /// <param name="elementCount">Number of T elment in this buffer.</param>
367  /// <param name="bufferFlags">The buffer flags to specify the type of buffer.</param>
368  /// <param name="usage">The usage.</param>
369  /// <returns>An instance of a new <see cref="Buffer" /></returns>
370  public static Buffer<T> New<T>(GraphicsDevice device, int elementCount, BufferFlags bufferFlags, GraphicsResourceUsage usage = GraphicsResourceUsage.Default) where T : struct
371  {
372  int bufferSize = Utilities.SizeOf<T>() * elementCount;
373  int elementSize = Utilities.SizeOf<T>();
374 
375  var description = NewDescription(bufferSize, elementSize, bufferFlags, usage);
376  return new Buffer<T>(device, description, bufferFlags, PixelFormat.None, IntPtr.Zero);
377  }
378 
379  /// <summary>
380  /// Creates a new <see cref="Buffer" /> instance.
381  /// </summary>
382  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
383  /// <param name="bufferSize">Size of the buffer in bytes.</param>
384  /// <param name="bufferFlags">The buffer flags to specify the type of buffer.</param>
385  /// <param name="viewFormat">The view format must be specified if the buffer is declared as a shared resource view.</param>
386  /// <param name="usage">The usage.</param>
387  /// <returns>An instance of a new <see cref="Buffer" /></returns>
388  public static Buffer New(GraphicsDevice device, int bufferSize, BufferFlags bufferFlags, PixelFormat viewFormat, GraphicsResourceUsage usage = GraphicsResourceUsage.Default)
389  {
390  return New(device, bufferSize, 0, bufferFlags, viewFormat, usage);
391  }
392 
393  /// <summary>
394  /// Creates a new <see cref="Buffer" /> instance.
395  /// </summary>
396  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
397  /// <param name="bufferSize">Size of the buffer in bytes.</param>
398  /// <param name="elementSize">Size of an element in the buffer.</param>
399  /// <param name="bufferFlags">The buffer flags to specify the type of buffer.</param>
400  /// <param name="usage">The usage.</param>
401  /// <returns>An instance of a new <see cref="Buffer" /></returns>
402  public static Buffer New(GraphicsDevice device, int bufferSize, int elementSize, BufferFlags bufferFlags, GraphicsResourceUsage usage = GraphicsResourceUsage.Default)
403  {
404  return New(device, bufferSize, elementSize, bufferFlags, PixelFormat.None, usage);
405  }
406 
407  /// <summary>
408  /// Creates a new <see cref="Buffer" /> instance.
409  /// </summary>
410  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
411  /// <param name="bufferSize">Size of the buffer in bytes.</param>
412  /// <param name="elementSize">Size of an element in the buffer.</param>
413  /// <param name="bufferFlags">The buffer flags to specify the type of buffer.</param>
414  /// <param name="viewFormat">The view format must be specified if the buffer is declared as a shared resource view.</param>
415  /// <param name="usage">The usage.</param>
416  /// <returns>An instance of a new <see cref="Buffer" /></returns>
417  public static Buffer New(GraphicsDevice device, int bufferSize, int elementSize, BufferFlags bufferFlags, PixelFormat viewFormat, GraphicsResourceUsage usage = GraphicsResourceUsage.Default)
418  {
419  viewFormat = CheckPixelFormat(bufferFlags, elementSize, viewFormat);
420  var description = NewDescription(bufferSize, elementSize, bufferFlags, usage);
421  return new Buffer(device, description, bufferFlags, viewFormat, IntPtr.Zero);
422  }
423 
424  /// <summary>
425  /// Creates a new <see cref="Buffer" /> instance.
426  /// </summary>
427  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
428  /// <typeparam name="T">Type of the buffer, to get the sizeof from.</typeparam>
429  /// <param name="value">The initial value of this buffer.</param>
430  /// <param name="bufferFlags">The buffer flags to specify the type of buffer.</param>
431  /// <param name="usage">The usage.</param>
432  /// <returns>An instance of a new <see cref="Buffer" /></returns>
433  public static Buffer<T> New<T>(GraphicsDevice device, ref T value, BufferFlags bufferFlags, GraphicsResourceUsage usage = GraphicsResourceUsage.Default) where T : struct
434  {
435  return New(device, ref value, bufferFlags, PixelFormat.None, usage);
436  }
437 
438  /// <summary>
439  /// Creates a new <see cref="Buffer" /> instance.
440  /// </summary>
441  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
442  /// <typeparam name="T">Type of the buffer, to get the sizeof from.</typeparam>
443  /// <param name="value">The initial value of this buffer.</param>
444  /// <param name="bufferFlags">The buffer flags to specify the type of buffer.</param>
445  /// <param name="viewFormat">The view format must be specified if the buffer is declared as a shared resource view.</param>
446  /// <param name="usage">The usage.</param>
447  /// <returns>An instance of a new <see cref="Buffer" /></returns>
448  public static unsafe Buffer<T> New<T>(GraphicsDevice device, ref T value, BufferFlags bufferFlags, PixelFormat viewFormat, GraphicsResourceUsage usage = GraphicsResourceUsage.Default) where T : struct
449  {
450  int bufferSize = Utilities.SizeOf<T>();
451  int elementSize = ((bufferFlags & BufferFlags.StructuredBuffer) != 0) ? Utilities.SizeOf<T>() : 0;
452 
453  viewFormat = CheckPixelFormat(bufferFlags, elementSize, viewFormat);
454 
455  var description = NewDescription(bufferSize, elementSize, bufferFlags, usage);
456  return new Buffer<T>(device, description, bufferFlags, viewFormat, (IntPtr)Interop.Fixed(ref value));
457  }
458 
459  /// <summary>
460  /// Creates a new <see cref="Buffer" /> instance.
461  /// </summary>
462  /// <typeparam name="T">Type of the buffer, to get the sizeof from.</typeparam>
463  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
464  /// <param name="initialValue">The initial value of this buffer.</param>
465  /// <param name="bufferFlags">The buffer flags to specify the type of buffer.</param>
466  /// <param name="usage">The usage.</param>
467  /// <returns>An instance of a new <see cref="Buffer" /></returns>
468  public static Buffer<T> New<T>(GraphicsDevice device, T[] initialValue, BufferFlags bufferFlags, GraphicsResourceUsage usage = GraphicsResourceUsage.Default) where T : struct
469  {
470  return New(device, initialValue, bufferFlags, PixelFormat.None, usage);
471  }
472 
473  /// <summary>
474  /// Creates a new <see cref="Buffer" /> instance.
475  /// </summary>
476  /// <typeparam name="T">Type of the buffer, to get the sizeof from.</typeparam>
477  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
478  /// <param name="initialValue">The initial value of this buffer.</param>
479  /// <param name="bufferFlags">The buffer flags to specify the type of buffer.</param>
480  /// <param name="viewFormat">The view format must be specified if the buffer is declared as a shared resource view.</param>
481  /// <param name="usage">The usage.</param>
482  /// <returns>An instance of a new <see cref="Buffer" /></returns>
483  public static unsafe Buffer<T> New<T>(GraphicsDevice device, T[] initialValue, BufferFlags bufferFlags, PixelFormat viewFormat, GraphicsResourceUsage usage = GraphicsResourceUsage.Default) where T : struct
484  {
485  int bufferSize = Utilities.SizeOf<T>() * initialValue.Length;
486  int elementSize = Utilities.SizeOf<T>();
487  viewFormat = CheckPixelFormat(bufferFlags, elementSize, viewFormat);
488 
489  var description = NewDescription(bufferSize, elementSize, bufferFlags, usage);
490  return new Buffer<T>(device, description, bufferFlags, viewFormat, (IntPtr)Interop.Fixed(initialValue));
491  }
492 
493  /// <summary>
494  /// Creates a new <see cref="Buffer" /> instance from a byte array.
495  /// </summary>
496  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
497  /// <param name="initialValue">The initial value of this buffer.</param>
498  /// <param name="elementSize">Size of an element. Must be equal to 2 or 4 for an index buffer, or to the size of a struct for a structured/typed buffer. Can be set to 0 for other buffers.</param>
499  /// <param name="bufferFlags">The buffer flags to specify the type of buffer.</param>
500  /// <param name="viewFormat">The view format must be specified if the buffer is declared as a shared resource view.</param>
501  /// <param name="usage">The usage.</param>
502  /// <returns>An instance of a new <see cref="Buffer" /></returns>
503  public static unsafe Buffer New(GraphicsDevice device, byte[] initialValue, int elementSize, BufferFlags bufferFlags, PixelFormat viewFormat = PixelFormat.None, GraphicsResourceUsage usage = GraphicsResourceUsage.Immutable)
504  {
505  int bufferSize = initialValue.Length;
506  viewFormat = CheckPixelFormat(bufferFlags, elementSize, viewFormat);
507 
508  var description = NewDescription(bufferSize, elementSize, bufferFlags, usage);
509  return new Buffer(device, description, bufferFlags, viewFormat, (IntPtr)Interop.Fixed(initialValue));
510  }
511 
512  /// <summary>
513  /// Creates a new <see cref="Buffer" /> instance.
514  /// </summary>
515  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
516  /// <param name="dataPointer">The data pointer.</param>
517  /// <param name="elementSize">Size of the element.</param>
518  /// <param name="bufferFlags">The buffer flags to specify the type of buffer.</param>
519  /// <param name="usage">The usage.</param>
520  /// <returns>An instance of a new <see cref="Buffer" /></returns>
521  public static Buffer New(GraphicsDevice device, DataPointer dataPointer, int elementSize, BufferFlags bufferFlags, GraphicsResourceUsage usage = GraphicsResourceUsage.Default)
522  {
523  return New(device, dataPointer, elementSize, bufferFlags, PixelFormat.None, usage);
524  }
525 
526  /// <summary>
527  /// Creates a new <see cref="Buffer" /> instance.
528  /// </summary>
529  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
530  /// <param name="dataPointer">The data pointer.</param>
531  /// <param name="elementSize">Size of the element.</param>
532  /// <param name="bufferFlags">The buffer flags to specify the type of buffer.</param>
533  /// <param name="viewFormat">The view format must be specified if the buffer is declared as a shared resource view.</param>
534  /// <param name="usage">The usage.</param>
535  /// <returns>An instance of a new <see cref="Buffer" /></returns>
536  public static Buffer New(GraphicsDevice device, DataPointer dataPointer, int elementSize, BufferFlags bufferFlags, PixelFormat viewFormat, GraphicsResourceUsage usage = GraphicsResourceUsage.Default)
537  {
538  int bufferSize = dataPointer.Size;
539  viewFormat = CheckPixelFormat(bufferFlags, elementSize, viewFormat);
540  var description = NewDescription(bufferSize, elementSize, bufferFlags, usage);
541  return new Buffer(device, description, bufferFlags, viewFormat, dataPointer.Pointer);
542  }
543 
544  private static PixelFormat CheckPixelFormat(BufferFlags bufferFlags, int elementSize, PixelFormat viewFormat)
545  {
546  if ((bufferFlags & BufferFlags.IndexBuffer) != 0 && (bufferFlags & BufferFlags.ShaderResource) != 0)
547  {
548  if (elementSize != 2 && elementSize != 4)
549  throw new ArgumentException("Element size must be set to sizeof(short) = 2 or sizeof(int) = 4 for index buffer if index buffer is bound to a ShaderResource", "elementSize");
550 
551  viewFormat = elementSize == 2 ? PixelFormat.R16_UInt : PixelFormat.R32_UInt;
552  }
553  return viewFormat;
554  }
555 
556  private static BufferDescription NewDescription(int bufferSize, int elementSize, BufferFlags bufferFlags, GraphicsResourceUsage usage)
557  {
558  return new BufferDescription() {
559  SizeInBytes = bufferSize,
560  StructureByteStride = (bufferFlags & BufferFlags.StructuredBuffer) != 0 ? elementSize : 0,
561  BufferFlags = bufferFlags,
562  Usage = usage,
563  };
564  }
565 
566  /// <summary>
567  /// Reload <see cref="Buffer"/> from given data if <see cref="GraphicsDevice"/> has been reset.
568  /// </summary>
569  /// <typeparam name="T"></typeparam>
570  /// <param name="dataPointer">The data pointer.</param>
571  /// <returns>This instance.</returns>
572  public Buffer RecreateWith<T>(T[] dataPointer) where T : struct
573  {
574  Reload = (graphicsResource) => ((Buffer)graphicsResource).Recreate(dataPointer);
575 
576  return this;
577  }
578 
579  /// <summary>
580  /// Reload <see cref="Buffer"/> from given data if <see cref="GraphicsDevice"/> has been reset.
581  /// </summary>
582  /// <typeparam name="T"></typeparam>
583  /// <param name="dataPointer">The data pointer.</param>
584  /// <returns>This instance.</returns>
585  public Buffer RecreateWith(IntPtr dataPointer)
586  {
587  Reload = (graphicsResource) => ((Buffer)graphicsResource).Recreate(dataPointer);
588 
589  return this;
590  }
591 
592  /// <summary>
593  /// Explicitly recreate buffer with given data. Usually called after a <see cref="GraphicsDevice"/> reset.
594  /// </summary>
595  /// <typeparam name="T"></typeparam>
596  /// <param name="dataPointer"></param>
597  public void Recreate<T>(T[] dataPointer) where T : struct
598  {
599  Utilities.Pin(dataPointer, Recreate);
600  }
601  }
602 
603  /// <summary>
604  /// A buffer with typed information.
605  /// </summary>
606  /// <typeparam name="T">Type of an element of this buffer.</typeparam>
607  public class Buffer<T> : Buffer where T : struct
608  {
609  protected internal Buffer(GraphicsDevice device, BufferDescription description, BufferFlags bufferFlags, PixelFormat viewFormat, IntPtr dataPointer) : base(device, description, bufferFlags, viewFormat, dataPointer)
610  {
611  this.ElementSize = Utilities.SizeOf<T>();
612  this.ElementCount = Description.SizeInBytes / ElementSize;
613  }
614 
615  /// <summary>
616  /// Gets the size of element T.
617  /// </summary>
618  public readonly int ElementSize;
619 
620  /// <summary>
621  /// Gets the content of this texture to an array of data.
622  /// </summary>
623  /// <returns>An array of data.</returns>
624  /// <remarks>This method is only working when called from the main thread that is accessing the main <see cref="GraphicsDevice" />.
625  /// This method creates internally a stagging resource if this texture is not already a stagging resouce, copies to it and map it to memory. Use method with explicit staging resource
626  /// for optimal performances.</remarks>
627  public T[] GetData()
628  {
629  return GetData<T>();
630  }
631 
632  /// <summary>
633  /// Copies the content of a single structure data from CPU memory to this buffer into GPU memory.
634  /// </summary>
635  /// <param name="fromData">The data to copy from.</param>
636  /// <param name="offsetInBytes">The offset in bytes to write to.</param>
637  /// <exception cref="System.ArgumentException"></exception>
638  /// <remarks>
639  /// This method is only working when called from the main thread that is accessing the main <see cref="GraphicsDevice"/>. See the unmanaged documentation about Map/UnMap for usage and restrictions.
640  /// </remarks>
641  public void SetData(ref T fromData, int offsetInBytes = 0)
642  {
643  base.SetData(ref fromData, offsetInBytes);
644  }
645 
646  /// <summary>
647  /// Copies the content an array of data from CPU memory to this buffer into GPU memory.
648  /// </summary>
649  /// <param name="fromData">The data to copy from.</param>
650  /// <param name="offsetInBytes">The offset in bytes to write to.</param>
651  /// <remarks>
652  /// This method is only working when called from the main thread that is accessing the main <see cref="GraphicsDevice"/>. See the unmanaged documentation about Map/UnMap for usage and restrictions.
653  /// </remarks>
654  public void SetData(T[] fromData, int offsetInBytes = 0)
655  {
656  base.SetData(fromData, offsetInBytes);
657  }
658 
659  /// <summary>
660  /// Copies the content of a single structure data from CPU memory to this buffer into GPU memory.
661  /// </summary>
662  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
663  /// <param name="fromData">The data to copy from.</param>
664  /// <param name="offsetInBytes">The offset in bytes to write to.</param>
665  /// <exception cref="System.ArgumentException"></exception>
666  /// <remarks>
667  /// This method is only working when called from the main thread that is accessing the main <see cref="GraphicsDevice"/>. See the unmanaged documentation about Map/UnMap for usage and restrictions.
668  /// </remarks>
669  public void SetData(GraphicsDevice device, ref T fromData, int offsetInBytes = 0)
670  {
671  base.SetData(device, ref fromData, offsetInBytes);
672  }
673 
674  /// <summary>
675  /// Copies the content an array of data from CPU memory to this buffer into GPU memory.
676  /// </summary>
677  /// <param name="device">The <see cref="GraphicsDevice"/>.</param>
678  /// <param name="fromData">The data to copy from.</param>
679  /// <param name="offsetInBytes">The offset in bytes to write to.</param>
680  /// <remarks>
681  /// This method is only working when called from the main thread that is accessing the main <see cref="GraphicsDevice"/>. See the unmanaged documentation about Map/UnMap for usage and restrictions.
682  /// </remarks>
683  public void SetData(GraphicsDevice device, T[] fromData, int offsetInBytes = 0)
684  {
685  base.SetData(fromData, offsetInBytes);
686  }
687  }
688 }
static Buffer New(GraphicsDevice device, int bufferSize, int elementSize, BufferFlags bufferFlags, PixelFormat viewFormat, GraphicsResourceUsage usage=GraphicsResourceUsage.Default)
Creates a new Buffer instance.
Definition: Buffer.cs:417
T[] GetData()
Gets the content of this texture to an array of data.
Definition: Buffer.cs:627
static unsafe Buffer New(GraphicsDevice device, byte[] initialValue, int elementSize, BufferFlags bufferFlags, PixelFormat viewFormat=PixelFormat.None, GraphicsResourceUsage usage=GraphicsResourceUsage.Immutable)
Creates a new Buffer instance from a byte array.
Definition: Buffer.cs:503
void SetData(DataPointer fromData, int offsetInBytes=0)
Copies the content an array of data on CPU memory to this buffer into GPU memory. ...
Definition: Buffer.cs:231
static Buffer New(GraphicsDevice device, int bufferSize, BufferFlags bufferFlags, PixelFormat viewFormat, GraphicsResourceUsage usage=GraphicsResourceUsage.Default)
Creates a new Buffer instance.
Definition: Buffer.cs:388
Buffer Clone()
Clones this instance.
Definition: Buffer.cs:92
Base class for converters to/from a data type.
GraphicsResourceUsage
Identifies expected resource use during rendering. The usage directly reflects whether a resource is ...
void SetData(GraphicsDevice device, T[] fromData, int offsetInBytes=0)
Copies the content an array of data from CPU memory to this buffer into GPU memory.
Definition: Buffer.cs:683
void SetData(GraphicsDevice device, ref T fromData, int offsetInBytes=0)
Copies the content of a single structure data from CPU memory to this buffer into GPU memory...
Definition: Buffer.cs:669
void SetData(T[] fromData, int offsetInBytes=0)
Copies the content an array of data from CPU memory to this buffer into GPU memory.
Definition: Buffer.cs:654
All-in-One Buffer class linked SharpDX.Direct3D11.Buffer.
SiliconStudio.Paradox.Graphics.Buffer Buffer
Definition: BasicEffect.cs:15
static Buffer New(GraphicsDevice device, DataPointer dataPointer, int elementSize, BufferFlags bufferFlags, PixelFormat viewFormat, GraphicsResourceUsage usage=GraphicsResourceUsage.Default)
Creates a new Buffer instance.
Definition: Buffer.cs:536
Performs primitive-based rendering, creates resources, handles system-level variables, adjusts gamma ramp levels, and creates shaders. See The+GraphicsDevice+class to learn more about the class.
A buffer with typed information.
Definition: Buffer.cs:607
static Buffer New(GraphicsDevice device, BufferDescription description, PixelFormat viewFormat=PixelFormat.None)
Creates a new Buffer instance.
Definition: Buffer.cs:343
static Buffer New(GraphicsDevice device, int bufferSize, BufferFlags bufferFlags, GraphicsResourceUsage usage=GraphicsResourceUsage.Default)
Creates a new Buffer instance.
Definition: Buffer.cs:357
readonly int ElementSize
Gets the size of element T.
Definition: Buffer.cs:618
static Buffer New(GraphicsDevice device, int bufferSize, int elementSize, BufferFlags bufferFlags, GraphicsResourceUsage usage=GraphicsResourceUsage.Default)
Creates a new Buffer instance.
Definition: Buffer.cs:402
readonly PixelFormat ViewFormat
Gets the default view format of this buffer.
Definition: Buffer.cs:71
void GetData(Buffer stagingTexture, DataPointer toData)
Copies the content of this buffer from GPU memory to a CPU memory using a specific staging resource...
Definition: Buffer.cs:278
readonly BufferDescription Description
Gets the description of this buffer.
Definition: Buffer.cs:44
static Buffer New(GraphicsDevice device, DataPointer dataPointer, int elementSize, BufferFlags bufferFlags, GraphicsResourceUsage usage=GraphicsResourceUsage.Default)
Creates a new Buffer instance.
Definition: Buffer.cs:521
Provides access to data organized in 3D.
Definition: DataBox.cs:12
void SetData(ref T fromData, int offsetInBytes=0)
Copies the content of a single structure data from CPU memory to this buffer into GPU memory...
Definition: Buffer.cs:641
void SetData(GraphicsDevice device, DataPointer fromData, int offsetInBytes=0)
Copies the content an array of data on CPU memory to this buffer into GPU memory. ...
Definition: Buffer.cs:305
PixelFormat
Defines various types of pixel formats.
Definition: PixelFormat.cs:32
readonly BufferFlags BufferFlags
Gets the type of this belementCount ///
Definition: Buffer.cs:66
Buffer RecreateWith(IntPtr dataPointer)
Reload Buffer from given data if GraphicsDevice has been reset.
Definition: Buffer.cs:585
Buffer ToStaging()
Return an equivalent staging texture CPU read-writable from this instance.
Definition: Buffer.cs:77