Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
VertexArrayObject.OpenGL.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 #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGL
4 using System;
5 using System.Collections.Generic;
6 #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
7 using OpenTK.Graphics.ES30;
8 #else
9 using OpenTK.Graphics.OpenGL;
10 #endif
11 using SiliconStudio.Core;
12 using SiliconStudio.Core.Collections;
13 
14 namespace SiliconStudio.Paradox.Graphics
15 {
16  public partial class VertexArrayObject
17  {
18  internal IntPtr indexBufferOffset;
19  internal int indexElementSize;
20  internal int indexBufferId;
21  internal DrawElementsType drawElementsType;
22  private bool attribLocationStored = false;
23 
24  private readonly EffectInputSignature preferredInputSignature;
25  private VertexArrayObjectInstance preferredInstance;
26  private VertexAttrib[] vertexAttribs;
27 
28  private EffectInputSignature currentShaderSignature;
29  private VertexArrayObjectInstance currentInstance;
30 
31  private readonly Dictionary<EffectInputSignature, VertexArrayObjectInstance> registeredInstances = new Dictionary<EffectInputSignature, VertexArrayObjectInstance>(ReferenceEqualityComparer<EffectInputSignature>.Default);
32 
33  private VertexArrayObject(GraphicsDevice graphicsDevice, EffectInputSignature shaderSignature, IndexBufferBinding indexBufferBinding, VertexBufferBinding[] vertexBufferBindings)
34  : base(graphicsDevice)
35  {
36  this.vertexBufferBindings = vertexBufferBindings;
37  this.indexBufferBinding = indexBufferBinding;
38  this.preferredInputSignature = shaderSignature;
39 
40  CreateAttributes();
41  }
42 
43  private void CreateAttributes()
44  {
45  int vertexAttribCount = 0;
46  for (int i = 0; i < vertexBufferBindings.Length; ++i)
47  {
48  vertexAttribCount += vertexBufferBindings[i].Declaration.VertexElements.Length;
49  }
50 
51  vertexAttribs = new VertexAttrib[vertexAttribCount];
52  int j = 0;
53  for (int i = 0; i < vertexBufferBindings.Length; ++i)
54  {
55  var inputSlot = vertexBufferBindings[i];
56  var vertexBuffer = vertexBufferBindings[i].Buffer;
57 
58  foreach (var vertexElementAndOffset in inputSlot.Declaration.EnumerateWithOffsets())
59  {
60  var vertexElement = vertexElementAndOffset.VertexElement;
61  var attributeName = "a_" + vertexElement.SemanticName + vertexElement.SemanticIndex;
62 
63  var vertexElementFormat = ConvertVertexElementFormat(vertexElement.Format);
64 #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
65  IntPtr bufferStart = vertexBuffer.ResourceId == 0
66  ? vertexBuffer.StagingData
67  : (IntPtr)vertexBufferBindings[i].Offset;
68 #else
69  var bufferStart = (IntPtr)vertexBufferBindings[i].Offset;
70 #endif
71  vertexAttribs[j] = new VertexAttrib
72  {
73  VertexBufferId = vertexBuffer.ResourceId,
74  Index = -1,
75  IsInteger = IsInteger(vertexElementFormat.Type),
76  Size = vertexElementFormat.Size,
77  Type = vertexElementFormat.Type,
78  Normalized = vertexElementFormat.Normalized,
79  Stride = inputSlot.Declaration.VertexStride,
80  Offset = bufferStart + vertexElementAndOffset.Offset,
81  AttributeName = attributeName
82  };
83 
84  j++;
85  }
86  }
87 
88  if (indexBufferBinding != null)
89  {
90  indexBufferId = indexBufferBinding.Buffer.resourceId;
91 
92 #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
93  if (indexBufferBinding.Is32Bit)
94  throw new PlatformNotSupportedException("32 bits index buffer are not supported on OpenGL ES 2.0");
95  drawElementsType = DrawElementsType.UnsignedShort;
96  indexElementSize = 2;
97  indexBufferOffset = (indexBufferId == 0 ? indexBufferBinding.Buffer.StagingData : IntPtr.Zero) +
98  indexBufferBinding.Offset;
99 #else
100  drawElementsType = indexBufferBinding.Is32Bit ? DrawElementsType.UnsignedInt : DrawElementsType.UnsignedShort;
101  indexElementSize = indexBufferBinding.Is32Bit ? 4 : 2;
102  indexBufferOffset = (IntPtr)indexBufferBinding.Offset;
103 #endif
104  }
105 
106  // If we have a signature, we can already pre-create the instance
107  if (preferredInputSignature != null)
108  {
109  preferredInstance = GetInstance(preferredInputSignature);
110  }
111 
112  currentShaderSignature = preferredInputSignature;
113  currentInstance = preferredInstance;
114  }
115 
116  protected override void DestroyImpl()
117  {
118  // Dispose all instances
119  foreach (var vertexArrayObjectInstance in registeredInstances)
120  {
121  vertexArrayObjectInstance.Value.Dispose();
122  }
123 
124  registeredInstances.Clear();
125  }
126 
127  protected internal override bool OnRecreate()
128  {
129  CreateAttributes();
130  return true;
131  }
132 
133  internal bool RequiresApply(EffectInputSignature effectInputSignature)
134  {
135  return !ReferenceEquals(effectInputSignature, currentShaderSignature);
136  }
137 
138  internal void Apply(EffectInputSignature effectInputSignature)
139  {
140  if (effectInputSignature == null) throw new ArgumentNullException("effectInputSignature");
141 
142  // Optimization: If the current VAO and shader signature was previously used, we can use it directly without asking for a proper instance
143  if (RequiresApply(effectInputSignature))
144  {
145  currentInstance = ReferenceEquals(preferredInputSignature, effectInputSignature)
146  ? preferredInstance
147  : GetInstance(effectInputSignature);
148  currentShaderSignature = effectInputSignature;
149  }
150 
151  currentInstance.Apply(GraphicsDevice);
152  }
153 
154  private VertexArrayObjectInstance GetInstance(EffectInputSignature effectInputSignature)
155  {
156  VertexArrayObjectInstance inputLayout;
157  lock (registeredInstances)
158  {
159  if (!registeredInstances.TryGetValue(effectInputSignature, out inputLayout))
160  {
161  inputLayout = new VertexArrayObjectInstance(GraphicsDevice, effectInputSignature, vertexAttribs, indexBufferId);
162  registeredInstances.Add(effectInputSignature, inputLayout);
163  }
164  }
165  return inputLayout;
166  }
167 
168  private static bool IsInteger(VertexAttribPointerType type)
169  {
170  switch (type)
171  {
172  case VertexAttribPointerType.Byte:
173  case VertexAttribPointerType.UnsignedByte:
174  case VertexAttribPointerType.Short:
175  case VertexAttribPointerType.UnsignedShort:
176  case VertexAttribPointerType.Int:
177  case VertexAttribPointerType.UnsignedInt:
178  return true;
179  default:
180  return false;
181  }
182  }
183 
184  private struct ElementFormat
185  {
186  public VertexAttribPointerType Type;
187  public int Size;
188  public bool Normalized;
189 
190  public ElementFormat(VertexAttribPointerType type, int size, bool normalized = false)
191  {
192  Type = type;
193  Size = size;
194  Normalized = normalized;
195  }
196  }
197 
198  private static ElementFormat ConvertVertexElementFormat(PixelFormat format)
199  {
200  switch (format)
201  {
202  case PixelFormat.R8_SInt:
203  return new ElementFormat(VertexAttribPointerType.Byte, 1);
204  case PixelFormat.R8_UInt:
205  return new ElementFormat(VertexAttribPointerType.UnsignedByte, 1);
206  case PixelFormat.R16_SInt:
207  return new ElementFormat(VertexAttribPointerType.Short, 1);
208  case PixelFormat.R16_UInt:
209  return new ElementFormat(VertexAttribPointerType.UnsignedShort, 1);
210  case PixelFormat.R8G8_SInt:
211  return new ElementFormat(VertexAttribPointerType.Byte, 2);
212  case PixelFormat.R8G8_UInt:
213  return new ElementFormat(VertexAttribPointerType.UnsignedByte, 2);
214  case PixelFormat.R16G16_SInt:
215  return new ElementFormat(VertexAttribPointerType.Short, 2);
216  case PixelFormat.R16G16_UInt:
217  return new ElementFormat(VertexAttribPointerType.UnsignedShort, 2);
218  case PixelFormat.R8G8B8A8_SInt:
219  return new ElementFormat(VertexAttribPointerType.Byte, 4);
220  case PixelFormat.R8G8B8A8_UInt:
221  return new ElementFormat(VertexAttribPointerType.UnsignedByte, 4);
222  case PixelFormat.R16G16B16A16_SInt:
223  return new ElementFormat(VertexAttribPointerType.Short, 4);
224  case PixelFormat.R16G16B16A16_UInt:
225  return new ElementFormat(VertexAttribPointerType.UnsignedShort, 4);
226  case PixelFormat.R32_Float:
227  return new ElementFormat(VertexAttribPointerType.Float, 1);
228  case PixelFormat.R32G32_Float:
229  return new ElementFormat(VertexAttribPointerType.Float, 2);
230  case PixelFormat.R32G32B32_Float:
231  return new ElementFormat(VertexAttribPointerType.Float, 3);
232  case PixelFormat.R32G32B32A32_Float:
233  return new ElementFormat(VertexAttribPointerType.Float, 4);
234  case PixelFormat.R8_UNorm:
235  return new ElementFormat(VertexAttribPointerType.UnsignedByte, 1, true);
236  case PixelFormat.R8G8_UNorm:
237  return new ElementFormat(VertexAttribPointerType.UnsignedByte, 2, true);
238  case PixelFormat.R8G8B8A8_UNorm:
239  return new ElementFormat(VertexAttribPointerType.UnsignedByte, 4, true);
240  case PixelFormat.R8_SNorm:
241  return new ElementFormat(VertexAttribPointerType.Byte, 1, true);
242  case PixelFormat.R8G8_SNorm:
243  return new ElementFormat(VertexAttribPointerType.Byte, 2, true);
244  case PixelFormat.R8G8B8A8_SNorm:
245  return new ElementFormat(VertexAttribPointerType.Byte, 4, true);
246  case PixelFormat.R16_UNorm:
247  return new ElementFormat(VertexAttribPointerType.UnsignedShort, 1, true);
248  case PixelFormat.R16G16_UNorm:
249  return new ElementFormat(VertexAttribPointerType.UnsignedShort, 2, true);
250  case PixelFormat.R16G16B16A16_UNorm:
251  return new ElementFormat(VertexAttribPointerType.UnsignedShort, 4, true);
252  case PixelFormat.R16_SNorm:
253  return new ElementFormat(VertexAttribPointerType.Short, 1, true);
254  case PixelFormat.R16G16_SNorm:
255  return new ElementFormat(VertexAttribPointerType.Short, 2, true);
256  case PixelFormat.R16G16B16A16_SNorm:
257  return new ElementFormat(VertexAttribPointerType.Short, 4, true);
258 #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
259  // HALF_FLOAT for OpenGL ES 2.x (OES extension)
260  case PixelFormat.R16G16B16A16_Float:
261  return new ElementFormat((VertexAttribPointerType)0x8D61, 4); // HALF_FLOAT_OES
262  case PixelFormat.R16G16_Float:
263  return new ElementFormat((VertexAttribPointerType)0x8D61, 2); // HALF_FLOAT_OES
264 #else
265  // HALF_FLOAT for OpenGL and OpenGL ES 3.x (also used for OpenGL ES 2.0 under 3.0 emulator)
266  case PixelFormat.R16G16B16A16_Float:
267  return new ElementFormat((VertexAttribPointerType)0x8D61, 4); // HALF_FLOAT
268  case PixelFormat.R16G16_Float:
269  return new ElementFormat((VertexAttribPointerType)0x8D61, 2); // HALF_FLOAT
270 #endif
271  default:
272  throw new NotSupportedException();
273  }
274  }
275  }
276 }
277 #endif
SiliconStudio.Paradox.Graphics.Buffer Buffer
Definition: BasicEffect.cs:15
The type of the serialized type will be passed as a generic arguments of the serializer. Example: serializer of A becomes instantiated as Serializer{A}.
_In_ size_t _In_ size_t _In_ DXGI_FORMAT format
Definition: DirectXTexP.h:175
_In_ size_t _In_ size_t size
Definition: DirectXTexP.h:175
PixelFormat
Defines various types of pixel formats.
Definition: PixelFormat.cs:32