Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
HalfBufferExtensions.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 using System;
4 using System.Linq;
5 using SiliconStudio.Paradox.Games;
6 using SiliconStudio.Paradox.Graphics;
7 using SiliconStudio.Core;
8 using SiliconStudio.Core.Mathematics;
9 using SiliconStudio.Paradox.Graphics.Data;
10 
11 namespace SiliconStudio.Paradox.Extensions
12 {
13  public static class HalfBufferExtensions
14  {
15  public unsafe static void CompactHalf(this VertexBufferBindingData vertexBufferBinding)
16  {
17  var vertexElementsWithOffsets = vertexBufferBinding.Declaration
18  .EnumerateWithOffsets()
19  .OrderBy(x => x.Offset)
20  .ToArray();
21 
22  var vertexElements = new VertexElementConvertInfo[vertexElementsWithOffsets.Length];
23 
24  int currentOffset = 0;
25  for (int index = 0; index < vertexElementsWithOffsets.Length; index++)
26  {
27  var vertexElementConvertInfo = new VertexElementConvertInfo();
28  vertexElementConvertInfo.VertexElementWithOffset = vertexElementsWithOffsets[index];
29  var vertexElement = vertexElementsWithOffsets[index].VertexElement;
30  var vertexElementFormat = vertexElementConvertInfo.VertexElementWithOffset.VertexElement.Format;
31 
32  // First iteration?
33  if (index == 0)
34  currentOffset = vertexElementsWithOffsets[index].Offset;
35 
36  vertexElements[index] = vertexElementConvertInfo;
37  vertexElementConvertInfo.OldFormat = vertexElementConvertInfo.VertexElementWithOffset.VertexElement.Format;
38 
39  int offsetShift = 0;
40 
41  switch (vertexElementFormat)
42  {
43  case PixelFormat.R32G32_Float:
44  vertexElementFormat = PixelFormat.R16G16_Float;
45 
46  // Adjust next offset if current object has been resized
47  offsetShift = Utilities.SizeOf<Half2>() - Utilities.SizeOf<Vector2>();
48  break;
49  case PixelFormat.R32G32B32_Float:
50  vertexElementFormat = PixelFormat.R16G16B16A16_Float;
51 
52  // Adjust next offset if current object has been resized
53  offsetShift = Utilities.SizeOf<Half4>() - Utilities.SizeOf<Vector3>();
54  break;
55  case PixelFormat.R32G32B32A32_Float:
56  vertexElementFormat = PixelFormat.R16G16B16A16_Float;
57 
58  // Adjust next offset if current object has been resized
59  offsetShift = Utilities.SizeOf<Half4>() - Utilities.SizeOf<Vector4>();
60  break;
61  }
62 
63  // Has format changed?
64  vertexElementConvertInfo.NeedConversion = vertexElementFormat != vertexElementConvertInfo.VertexElementWithOffset.VertexElement.Format;
65 
66  // Create new vertex element with adjusted offset, and maybe new vertex format (if modified)
67  vertexElementConvertInfo.VertexElementWithOffset.VertexElement
68  = new VertexElement(vertexElement.semanticName, vertexElement.SemanticIndex, vertexElementFormat, currentOffset);
69 
70  // Increment next offset by the same difference as in original declaration
71  if (index + 1 < vertexElementsWithOffsets.Length)
72  currentOffset += vertexElementsWithOffsets[index + 1].Offset - vertexElementsWithOffsets[index].Offset;
73 
74  currentOffset += offsetShift;
75 
76  vertexElements[index] = vertexElementConvertInfo;
77  }
78 
79  var oldVertexStride = vertexBufferBinding.Declaration.VertexStride;
80 
81  vertexBufferBinding.Declaration = new VertexDeclaration(vertexElements.Select(x => x.VertexElementWithOffset.VertexElement).ToArray());
82 
83  var newVertexStride = vertexBufferBinding.Declaration.VertexStride;
84  var newBufferData = new byte[vertexBufferBinding.Count * newVertexStride];
85  fixed (byte* oldBuffer = &vertexBufferBinding.Buffer.Value.Content[vertexBufferBinding.Offset])
86  fixed (byte* newBuffer = &newBufferData[0])
87  {
88  var oldBufferVertexPtr = (IntPtr)oldBuffer;
89  var newBufferVertexPtr = (IntPtr)newBuffer;
90  for (int i = 0; i < vertexBufferBinding.Count; ++i)
91  {
92  foreach (var element in vertexElements)
93  {
94  var oldBufferElementPtr = oldBufferVertexPtr + element.VertexElementWithOffset.Offset;
95  var newBufferElementPtr = newBufferVertexPtr + element.VertexElementWithOffset.VertexElement.AlignedByteOffset;
96 
97  if (element.NeedConversion)
98  {
99  // Convert floatX => halfX
100  switch (element.OldFormat)
101  {
102  case PixelFormat.R32G32_Float:
103  *((Half2*)newBufferElementPtr) = (Half2)(*((Vector2*)oldBufferElementPtr));
104  break;
105  case PixelFormat.R32G32B32_Float:
106  // Put 1.0f in
107  *((Half4*)newBufferElementPtr) = (Half4)(new Vector4(*((Vector3*)oldBufferElementPtr), 1.0f));
108  break;
109  case PixelFormat.R32G32B32A32_Float:
110  *((Half4*)newBufferElementPtr) = (Half4)(*((Vector4*)oldBufferElementPtr));
111  break;
112  }
113  }
114  else
115  {
116  // Copy as is
117  Utilities.CopyMemory(newBufferElementPtr, oldBufferElementPtr, element.VertexElementWithOffset.Size);
118  }
119  }
120 
121  oldBufferVertexPtr += oldVertexStride;
122  newBufferVertexPtr += newVertexStride;
123  }
124  }
125 
126  vertexBufferBinding.Offset = 0;
127  vertexBufferBinding.Buffer = new BufferData(BufferFlags.VertexBuffer, newBufferData);
128  }
129 
130  private struct VertexElementConvertInfo
131  {
133  public bool NeedConversion;
134  public PixelFormat OldFormat;
135  }
136  }
137 }
The layout of a vertex buffer with a set of VertexElement.
Represents a two dimensional mathematical vector.
Definition: Vector2.cs:42
SiliconStudio.Paradox.Games.Mathematics.Half4 Half4
Represents a three dimensional mathematical vector.
Definition: Vector3.cs:42
SiliconStudio.Core.Serialization.ContentReference< SiliconStudio.Paradox.Graphics.Data.BufferData > Buffer
Data field for SiliconStudio.Paradox.Graphics.VertexBufferBinding.Buffer.
Represents a four dimensional mathematical vector.
Definition: Vector4.cs:42
Data type for SiliconStudio.Paradox.Graphics.VertexBufferBinding.
static unsafe void CompactHalf(this VertexBufferBindingData vertexBufferBinding)
Content of a GPU buffer (vertex buffer, index buffer, etc...).
Definition: BufferData.cs:10
Defines a two component vector, using half precision floating point coordinates.
Definition: Half2.cs:34
Defines a four component vector, using half precision floating point coordinates. ...
Definition: Half4.cs:36
System.Int32 Offset
Data field for SiliconStudio.Paradox.Graphics.VertexBufferBinding.Offset.
PixelFormat
Defines various types of pixel formats.
Definition: PixelFormat.cs:32
A description of a single element for the input-assembler stage. This structure is related to Direct3...