Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
EffectProgram.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 using System.Linq;
7 using System.Text;
8 using OpenTK.Graphics;
9 using SiliconStudio.Core;
10 using SiliconStudio.Core.Diagnostics;
11 using SiliconStudio.Core.Extensions;
12 using SiliconStudio.Paradox.Shaders;
13 #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
14 using OpenTK.Graphics.ES30;
15 #else
16 using OpenTK.Graphics.OpenGL;
17 #endif
18 
19 
20 namespace SiliconStudio.Paradox.Graphics
21 {
22  internal partial class EffectProgram
23  {
24  private LoggerResult reflectionResult = new LoggerResult();
25 
26  private readonly EffectBytecode effectBytecode;
27 
28  private EffectInputSignature inputSignature;
29 
30 #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
31  // Fake cbuffer emulation binding
32  internal struct Uniform
33  {
34  public ActiveUniformType Type;
35  public int UniformIndex;
36  public int Offset;
37  public int Count;
38  public int CompareSize;
39  }
40 
41  internal byte[] BoundUniforms;
42  internal List<Uniform> Uniforms = new List<Uniform>();
43 #endif
44 
45  internal struct Texture
46  {
47  public int TextureUnit;
48 
49  public Texture(int textureUnit)
50  {
51  TextureUnit = textureUnit;
52  }
53  }
54 
55  internal List<Texture> Textures = new List<Texture>();
56 
57  private EffectProgram(GraphicsDevice device, EffectBytecode bytecode)
58  : base(device)
59  {
60  effectBytecode = bytecode;
61  CreateShaders();
62  }
63 
64  private void CreateShaders()
65  {
66  using (GraphicsDevice.UseOpenGLCreationContext())
67  {
68  resourceId = GL.CreateProgram();
69 
70  // Attach shaders
71  foreach (var shader in effectBytecode.Stages)
72  {
73  ShaderType shaderStage;
74  switch (shader.Stage)
75  {
76  case ShaderStage.Vertex:
77  shaderStage = ShaderType.VertexShader;
78  inputSignature = EffectInputSignature.GetOrCreateLayout(new EffectInputSignature(shader.Id, shader.Data));
79  break;
80  case ShaderStage.Pixel:
81  shaderStage = ShaderType.FragmentShader;
82  break;
83  default:
84  throw new Exception("Unsupported shader stage");
85  break;
86  }
87 
88  var shaderSource = shader.GetDataAsString();
89 
90  var shaderId = GL.CreateShader(shaderStage);
91  GL.ShaderSource(shaderId, shaderSource);
92  GL.CompileShader(shaderId);
93 
94  int compileStatus;
95  GL.GetShader(shaderId, ShaderParameter.CompileStatus, out compileStatus);
96  if (compileStatus != 1)
97  {
98  var glErrorMessage = GL.GetShaderInfoLog(shaderId);
99  throw new InvalidOperationException("Error while compiling GLSL shader. [{0}]".ToFormat(glErrorMessage));
100  }
101 
102  GL.AttachShader(resourceId, shaderId);
103  }
104 
105 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
106  // Mark program as retrievable (necessary for later GL.GetProgramBinary).
107  GL.ProgramParameter(resourceId, AssemblyProgramParameterArb.ProgramBinaryRetrievableHint, 1);
108 #endif
109 
110  // Link OpenGL program
111  GL.LinkProgram(resourceId);
112 
113  // Check link results
114  int linkStatus;
115  GL.GetProgram(resourceId, ProgramParameter.LinkStatus, out linkStatus);
116  if (linkStatus != 1)
117  {
118  var infoLog = GL.GetProgramInfoLog(resourceId);
119  throw new InvalidOperationException("Error while linking GLSL shaders.\n" + infoLog);
120  }
121 
122  if (inputSignature.Attributes.Count == 0) // the shader wasn't analyzed yet
123  {
124  // Build attributes list for shader signature
125  int activeAttribCount;
126  GL.GetProgram(resourceId, ProgramParameter.ActiveAttributes, out activeAttribCount);
127 
128  for (int activeAttribIndex = 0; activeAttribIndex < activeAttribCount; ++activeAttribIndex)
129  {
130  int size;
131  ActiveAttribType type;
132  var attribName = GL.GetActiveAttrib(resourceId, activeAttribIndex, out size, out type);
133 #if SILICONSTUDIO_PLATFORM_ANDROID
134  var attribIndex = GL.GetAttribLocation(resourceId, new StringBuilder(attribName));
135 #else
136  var attribIndex = GL.GetAttribLocation(resourceId, attribName);
137 #endif
138  inputSignature.Attributes.Add(attribName, attribIndex);
139  }
140  }
141  CreateReflection(effectBytecode.Reflection, effectBytecode.Stages[0].Stage); // need to regenerate the Uniforms on OpenGL ES
142 
143 #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
144  // Allocate a buffer that can cache all the bound parameters
145  BoundUniforms = new byte[effectBytecode.Reflection.ConstantBuffers[0].Size];
146 #endif
147 
148  // TODO: Register "NoSampler", required by HLSL=>GLSL translation to support HLSL such as texture.Load().
149  }
150 
151  // output the gathered errors
152  foreach (var message in reflectionResult.Messages)
153  Console.WriteLine(message);
154  if (reflectionResult.HasErrors)
155  throw new Exception("Exception");
156  }
157 
158  public EffectInputSignature InputSignature
159  {
160  get { return inputSignature; }
161  }
162 
163  /// <inheritdoc/>
164  protected internal override bool OnRecreate()
165  {
166  base.OnRecreate();
167  CreateShaders();
168  return true;
169  }
170 
171  /// <inheritdoc/>
172  protected override void Destroy()
173  {
174  using (GraphicsDevice.UseOpenGLCreationContext())
175  {
176  GL.DeleteProgram(resourceId);
177  }
178 
179  resourceId = 0;
180 
181  base.Destroy();
182  }
183 
184  public void Apply(GraphicsDevice device)
185  {
186 #if DEBUG
187  device.EnsureContextActive();
188 #endif
189 
190  device.effectProgram = this;
191  device.BindProgram(ResourceId);
192  }
193 
194  /// <summary>
195  /// Create or updates the reflection for this shader
196  /// </summary>
197  /// <param name="effectReflection">the reflection from the hlsl</param>
198  /// <param name="stage">the shader pipeline stage</param>
199  private void CreateReflection(EffectReflection effectReflection, ShaderStage stage)
200  {
201  int currentProgram;
202  GL.GetInteger(GetPName.CurrentProgram, out currentProgram);
203  GL.UseProgram(resourceId);
204 
205 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
206  int uniformBlockCount;
207  GL.GetProgram(resourceId, ProgramParameter.ActiveUniformBlocks, out uniformBlockCount);
208 
209  for (int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
210  {
211  // TODO: get previous name to find te actual constant buffer in the reflexion
212  var constantBufferName = GL.GetActiveUniformBlockName(resourceId, uniformBlockIndex);
213 
214  var constantBufferDescriptionIndex = effectReflection.ConstantBuffers.FindIndex(x => x.Name == constantBufferName);
215  if (constantBufferDescriptionIndex == -1)
216  {
217  reflectionResult.Error("Unable to find the constant buffer description [{0}]", constantBufferName);
218  return;
219  }
220  var constantBufferIndex = effectReflection.ResourceBindings.FindIndex(x => x.Param.RawName == constantBufferName);
221  if (constantBufferIndex == -1)
222  {
223  reflectionResult.Error("Unable to find the constant buffer [{0}]", constantBufferName);
224  return;
225  }
226 
227  var constantBufferDescription = effectReflection.ConstantBuffers[constantBufferDescriptionIndex];
228  var constantBuffer = effectReflection.ResourceBindings[constantBufferIndex];
229 
230  GL.GetActiveUniformBlock(resourceId, uniformBlockIndex, ActiveUniformBlockParameter.UniformBlockDataSize, out constantBufferDescription.Size);
231 
232  int uniformCount;
233  GL.GetActiveUniformBlock(resourceId, uniformBlockIndex, ActiveUniformBlockParameter.UniformBlockActiveUniforms, out uniformCount);
234 
235  // set the binding
236  GL.UniformBlockBinding(resourceId, uniformBlockIndex, uniformBlockIndex);
237 
238  // Read uniforms desc
239  var uniformIndices = new int[uniformCount];
240  var uniformOffsets = new int[uniformCount];
241  var uniformTypes = new int[uniformCount];
242  var uniformNames = new string[uniformCount];
243  GL.GetActiveUniformBlock(resourceId, uniformBlockIndex, ActiveUniformBlockParameter.UniformBlockActiveUniformIndices, uniformIndices);
244  GL.GetActiveUniforms(resourceId, uniformIndices.Length, uniformIndices, ActiveUniformParameter.UniformOffset, uniformOffsets);
245  GL.GetActiveUniforms(resourceId, uniformIndices.Length, uniformIndices, ActiveUniformParameter.UniformType, uniformTypes);
246 
247  for (int uniformIndex = 0; uniformIndex < uniformIndices.Length; ++uniformIndex)
248  {
249  uniformNames[uniformIndex] = GL.GetActiveUniformName(resourceId, uniformIndices[uniformIndex]);
250  }
251 
252  // Reoder by offset
253  var indexMapping = uniformIndices.Select((x, i) => new UniformMergeInfo { Offset = uniformOffsets[i], Type = (ActiveUniformType)uniformTypes[i], Name = uniformNames[i], NextOffset = 0 }).OrderBy(x => x.Offset).ToArray();
254  indexMapping.Last().NextOffset = constantBufferDescription.Size;
255 
256  // Fill next offsets
257  for (int i = 1; i < indexMapping.Length; ++i)
258  {
259  indexMapping[i - 1].NextOffset = indexMapping[i].Offset;
260  }
261 
262  // Group arrays/structures into one variable (std140 layout is enough for offset determinism inside arrays/structures)
263  indexMapping = indexMapping.GroupBy(x =>
264  {
265  // Use only first part of name (ignore structure/array part)
266  var name = x.Name;
267  if (name.Contains(".")) { name = name.Substring(0, name.IndexOf('.')); }
268  if (name.Contains("[")) { name = name.Substring(0, name.IndexOf('[')); }
269  return name;
270  })
271  .Select(x =>
272  {
273  var result = x.First();
274  result.NextOffset = x.Last().NextOffset;
275 
276  // Check weither it's an array or a struct
277  int dotIndex = result.Name.IndexOf('.');
278  int arrayIndex = result.Name.IndexOf('[');
279 
280  if (x.Count() > 1 && arrayIndex == -1 && dotIndex == -1)
281  throw new InvalidOperationException();
282 
283  // TODO: Type processing
284 
285  result.Name = x.Key;
286  return result;
287  }).ToArray();
288 
289  foreach (var variableIndexGroup in indexMapping)
290  {
291  var variableIndex = -1;
292  for (var tentativeIndex = 0; tentativeIndex < constantBufferDescription.Members.Length; ++tentativeIndex)
293  {
294  if (constantBufferDescription.Members[tentativeIndex].Param.RawName == variableIndexGroup.Name)
295  {
296  variableIndex = tentativeIndex;
297  break;
298  }
299  }
300 
301  if (variableIndex == -1)
302  {
303  reflectionResult.Error("Unable to find uniform [{0}] in constant buffer [{1}]", variableIndexGroup.Name, constantBufferName);
304  continue;
305  }
306  var variable = constantBufferDescription.Members[variableIndex];
307  variable.Param.Type = GetTypeFromActiveUniformType(variableIndexGroup.Type);
308  variable.Offset = variableIndexGroup.Offset;
309  variable.Size = variable.Count * variable.RowCount * variable.ColumnCount * 4; // TODO: is there another possible value than 4?
310 
311  constantBufferDescription.Members[variableIndex] = variable;
312  }
313 
314  constantBufferDescription.Stage = stage;
315  constantBufferDescription.Type = ConstantBufferType.ConstantBuffer;
316 
317  constantBuffer.SlotCount = 1; // constant buffers are not arrays
318  constantBuffer.SlotStart = uniformBlockIndex;
319  constantBuffer.Stage = stage;
320 
321  // store the new values
322  effectReflection.ConstantBuffers[constantBufferDescriptionIndex] = constantBufferDescription;
323  effectReflection.ResourceBindings[constantBufferIndex] = constantBuffer;
324  }
325 #endif
326 
327  // Register textures, samplers, etc...
328  //TODO: (?) non texture/buffer uniform outside of a block
329  {
330  int activeUniformCount;
331  GL.GetProgram(resourceId, ProgramParameter.ActiveUniforms, out activeUniformCount);
332 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
333  var uniformTypes = new int[activeUniformCount];
334  GL.GetActiveUniforms(resourceId, activeUniformCount, Enumerable.Range(0, activeUniformCount).ToArray(), ActiveUniformParameter.UniformType, uniformTypes);
335 #endif
336 
337 #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
338  // Register global "fake" cbuffer
339  //var constantBuffer = new ShaderReflectionConstantBuffer
340  // {
341  // Name = "$Globals",
342  // Variables = new List<ShaderReflectionVariable>(),
343  // Type = ConstantBufferType.ConstantBuffer
344  // };
345  //shaderReflection.ConstantBuffers.Add(constantBuffer);
346  //shaderReflection.BoundResources.Add(new InputBindingDescription { BindPoint = 0, BindCount = 1, Name = constantBuffer.Name, Type = ShaderInputType.ConstantBuffer });
347 
348  // reset the size of the constant buffers
349  foreach (var constantBuffer in effectReflection.ConstantBuffers)
350  constantBuffer.Size = 0;
351 
352  // set the state of the constant buffers
353  foreach (var constantBuffer in effectReflection.ConstantBuffers)
354  constantBuffer.Stage = stage;
355  for (int i = 0; i < effectReflection.ResourceBindings.Count; i++)
356  {
357  if(effectReflection.ResourceBindings[i].Param.Class != EffectParameterClass.ConstantBuffer)
358  continue;
359 
360  var globalConstantBufferCopy = effectReflection.ResourceBindings[i];
361  globalConstantBufferCopy.Stage = stage;
362  effectReflection.ResourceBindings[i] = globalConstantBufferCopy;
363  }
364 
365  //Create a Globals constant buffer if necessary
366  var globalConstantBufferDescriptionIndex = effectReflection.ConstantBuffers.FindIndex(x => x.Name == "Globals");
367  var globalConstantBufferIndex = effectReflection.ResourceBindings.FindIndex(x => x.Param.RawName == "Globals");
368  if (globalConstantBufferDescriptionIndex == -1 && globalConstantBufferIndex == -1)
369  {
370  var newConstantBufferDescription = new ShaderConstantBufferDescription
371  {
372  Name = "Globals",
373  Stage = stage,
375  Size = 0,
376  Members = new EffectParameterValueData[0],
377  };
378  var newConstantBuffer = new EffectParameterResourceData
379  {
380  Stage = stage,
381  SlotStart = 0,
382  SlotCount = 1,
383  Param = { RawName = "Globals", KeyName = "Globals", Type = EffectParameterType.ConstantBuffer, Class = EffectParameterClass.ConstantBuffer }
384  };
385 
386  effectReflection.ConstantBuffers.Add(newConstantBufferDescription);
387  effectReflection.ResourceBindings.Add(newConstantBuffer);
388 
389  globalConstantBufferDescriptionIndex = effectReflection.ConstantBuffers.Count - 1;
390  globalConstantBufferIndex = effectReflection.ResourceBindings.Count - 1;
391  }
392 
393  // Merge all the variables in the Globals constant buffer
394  if (globalConstantBufferDescriptionIndex != -1 && globalConstantBufferIndex != -1)
395  {
396  var globalConstantBufferDescription = effectReflection.ConstantBuffers[globalConstantBufferDescriptionIndex];
397  for (int cstDescrIndex = 0; cstDescrIndex < effectReflection.ConstantBuffers.Count; ++cstDescrIndex)
398  {
399  if (cstDescrIndex == globalConstantBufferDescriptionIndex)
400  continue;
401 
402  var currentConstantBufferDescription = effectReflection.ConstantBuffers[cstDescrIndex];
403 
404  globalConstantBufferDescription.Members = ArrayExtensions.Concat(
405  globalConstantBufferDescription.Members, currentConstantBufferDescription.Members);
406 
407  effectReflection.ResourceBindings.RemoveAll(x => x.Param.RawName == currentConstantBufferDescription.Name);
408  }
409 
410  // only keep the active uniforms
411  globalConstantBufferDescription.Members =
412  globalConstantBufferDescription.Members.Where(x => GL.GetUniformLocation(resourceId,
413 #if SILICONSTUDIO_PLATFORM_ANDROID
414  new StringBuilder(x.Param.RawName)
415 #else
416  x.Param.RawName
417 #endif
418  ) >= 0).ToArray();
419 
420  // remove all the constant buffers and their resource bindings except the Globals one
421  effectReflection.ConstantBuffers.Clear();
422  effectReflection.ConstantBuffers.Add(globalConstantBufferDescription);
423  }
424  else if (globalConstantBufferDescriptionIndex != -1 && globalConstantBufferIndex == -1)
425  {
426  reflectionResult.Error("Globals constant buffer has a description and no resource binding");
427  }
428  else if (globalConstantBufferDescriptionIndex == -1 && globalConstantBufferIndex != -1)
429  {
430  reflectionResult.Error("Globals constant buffer has a description and no resource binding");
431  }
432 #endif
433 
434  int textureUnitCount = 0;
435 
436  for (int activeUniformIndex = 0; activeUniformIndex < activeUniformCount; ++activeUniformIndex)
437  {
438 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
439  var uniformType = (ActiveUniformType)uniformTypes[activeUniformIndex];
440  var uniformName = GL.GetActiveUniformName(resourceId, activeUniformIndex);
441 #else
442  ActiveUniformType uniformType;
443  int uniformCount;
444  var uniformName = GL.GetActiveUniform(resourceId, activeUniformIndex, out uniformCount, out uniformType);
445  //int uniformSize;
446  //GL.GetActiveUniform(resourceId, activeUniformIndex, out uniformSize, ActiveUniformType.Float);
447 #endif
448 
449  switch (uniformType)
450  {
451 #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
452  case ActiveUniformType.Bool:
453  case ActiveUniformType.Int:
454  AddUniform(effectReflection, sizeof(int) * 1, uniformCount, uniformName, uniformType);
455  break;
456  case ActiveUniformType.BoolVec2:
457  case ActiveUniformType.IntVec2:
458  AddUniform(effectReflection, sizeof(int) * 2, uniformCount, uniformName, uniformType);
459  break;
460  case ActiveUniformType.BoolVec3:
461  case ActiveUniformType.IntVec3:
462  AddUniform(effectReflection, sizeof(int) * 3, uniformCount, uniformName, uniformType);
463  break;
464  case ActiveUniformType.BoolVec4:
465  case ActiveUniformType.IntVec4:
466  AddUniform(effectReflection, sizeof(int) * 4, uniformCount, uniformName, uniformType);
467  break;
468  case ActiveUniformType.Float:
469  AddUniform(effectReflection, sizeof(float) * 1, uniformCount, uniformName, uniformType);
470  break;
471  case ActiveUniformType.FloatVec2:
472  AddUniform(effectReflection, sizeof(float) * 2, uniformCount, uniformName, uniformType);
473  break;
474  case ActiveUniformType.FloatVec3:
475  AddUniform(effectReflection, sizeof(float) * 3, uniformCount, uniformName, uniformType);
476  break;
477  case ActiveUniformType.FloatVec4:
478  AddUniform(effectReflection, sizeof(float) * 4, uniformCount, uniformName, uniformType);
479  break;
480  case ActiveUniformType.FloatMat4:
481  AddUniform(effectReflection, sizeof(float) * 4 * 4, uniformCount, uniformName, uniformType);
482  break;
483  case ActiveUniformType.FloatMat2:
484  case ActiveUniformType.FloatMat3:
485  throw new NotImplementedException();
486 #endif
487 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
488  case ActiveUniformType.Sampler1D:
489  case ActiveUniformType.Sampler3D:
490 #endif
491  case ActiveUniformType.Sampler2D:
492 #if SILICONSTUDIO_PLATFORM_ANDROID
493  var uniformIndex = GL.GetUniformLocation(resourceId, new StringBuilder(uniformName));
494 #else
495  var uniformIndex = GL.GetUniformLocation(resourceId, uniformName);
496 #endif
497 
498  // Temporary way to scan which texture and sampler created this texture_sampler variable (to fix with new HLSL2GLSL converter)
499 
500  var startIndex = -1;
501  var textureReflectionIndex = -1;
502  var samplerReflectionIndex = -1;
503  do
504  {
505  int middlePart = uniformName.IndexOf('_', startIndex + 1);
506  var textureName = middlePart != -1 ? uniformName.Substring(0, middlePart) : uniformName;
507  var samplerName = middlePart != -1 ? uniformName.Substring(middlePart + 1) : null;
508 
509  textureReflectionIndex =
510  effectReflection.ResourceBindings.FindIndex(x => x.Param.RawName == textureName);
511  samplerReflectionIndex =
512  effectReflection.ResourceBindings.FindIndex(x => x.Param.RawName == samplerName);
513 
514  if (textureReflectionIndex != -1 && samplerReflectionIndex != -1)
515  break;
516 
517  startIndex = middlePart;
518  } while (startIndex != -1);
519 
520  if (startIndex == -1 || textureReflectionIndex == -1 || samplerReflectionIndex == -1)
521  {
522  reflectionResult.Error("Unable to find sampler and texture corresponding to [{0}]", uniformName);
523  continue; // Error
524  }
525 
526  var textureReflection = effectReflection.ResourceBindings[textureReflectionIndex];
527  var samplerReflection = effectReflection.ResourceBindings[samplerReflectionIndex];
528 
529  // Update texture uniform mapping
530  GL.Uniform1(uniformIndex, textureUnitCount);
531 
532  textureReflection.Stage = stage;
533  //textureReflection.Param.RawName = uniformName;
534  textureReflection.Param.Type = GetTypeFromActiveUniformType(uniformType);
535  textureReflection.SlotStart = textureUnitCount;
536  textureReflection.SlotCount = 1; // TODO: texture arrays
537  textureReflection.Param.Class = EffectParameterClass.ShaderResourceView;
538 
539  samplerReflection.Stage = stage;
540  samplerReflection.SlotStart = textureUnitCount;
541  samplerReflection.SlotCount = 1; // TODO: texture arrays
542  samplerReflection.Param.Class = EffectParameterClass.Sampler;
543 
544  effectReflection.ResourceBindings[textureReflectionIndex] = textureReflection;
545  effectReflection.ResourceBindings[samplerReflectionIndex] = samplerReflection;
546 
547  Textures.Add(new Texture(textureUnitCount));
548 
549  textureUnitCount++;
550  break;
551  }
552  }
553  }
554 
555  GL.UseProgram(currentProgram);
556  }
557 
558 #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
559 
560  private void AddUniform(EffectReflection effectReflection, int uniformSize, int uniformCount, string uniformName, ActiveUniformType uniformType)
561  {
562  // clean the name
563  if (uniformName.Contains("."))
564  {
565  uniformName = uniformName.Substring(0, uniformName.IndexOf('.'));
566  }
567  if (uniformName.Contains("["))
568  {
569  uniformName = uniformName.Substring(0, uniformName.IndexOf('['));
570  }
571 
572  var indexOfConstantBufferDescription = effectReflection.ConstantBuffers.FindIndex(x => x.Name == "Globals");
573  var indexOfConstantBuffer = effectReflection.ResourceBindings.FindIndex(x => x.Param.RawName == "Globals");
574 
575  if (indexOfConstantBufferDescription == -1 || indexOfConstantBuffer == -1)
576  {
577  reflectionResult.Error("Unable to find uniform [{0}] in any constant buffer", uniformName);
578  return;
579  }
580 
581  var constantBufferDescription = effectReflection.ConstantBuffers[indexOfConstantBufferDescription];
582  var constantBuffer = effectReflection.ResourceBindings[indexOfConstantBuffer];
583 
584  var elementSize = uniformSize;
585 
586  // For array, each element is rounded to register size
587  if (uniformSize % 16 != 0 && uniformCount > 1)
588  {
589  constantBufferDescription.Size = (constantBufferDescription.Size + 15) / 16 * 16;
590  uniformSize = (uniformSize + 15) / 16 * 16;
591  }
592 
593  // Check if it can fits in the same register, otherwise starts at the next one
594  if (uniformCount == 1 && constantBufferDescription.Size / 16 != (constantBufferDescription.Size + uniformSize - 1) / 16)
595  constantBufferDescription.Size = (constantBufferDescription.Size + 15) / 16 * 16;
596 
597  var indexOfUniform = -1;
598  for (var tentativeIndex = 0; tentativeIndex < constantBufferDescription.Members.Length; ++tentativeIndex)
599  {
600  if (constantBufferDescription.Members[tentativeIndex].Param.RawName == uniformName)
601  {
602  indexOfUniform = tentativeIndex;
603  break;
604  }
605  }
606 
607  var variable = constantBufferDescription.Members[indexOfUniform];
608 
609  variable.Param.Type = GetTypeFromActiveUniformType(uniformType);
610  //variable.SourceOffset = variableIndexGroup.Offset;
611  variable.Offset = constantBufferDescription.Size;
612  variable.Count = uniformCount;
613  variable.Size = uniformSize*uniformCount;
614 
615  constantBufferDescription.Type = ConstantBufferType.ConstantBuffer;
616 
617  constantBuffer.SlotStart = 0;
618 
619  constantBufferDescription.Members[indexOfUniform] = variable;
620  effectReflection.ResourceBindings[indexOfConstantBuffer] = constantBuffer;
621 
622  // No need to compare last element padding.
623  // TODO: In case of float1/float2 arrays (rare) it is quite non-optimal to do a CompareMemory
624  var compareSize = uniformSize * (uniformCount - 1) + elementSize;
625 
626  Uniforms.Add(new Uniform
627  {
628  Type = uniformType,
629  Count = uniformCount,
630  CompareSize = compareSize,
631  Offset = constantBufferDescription.Size,
632 #if SILICONSTUDIO_PLATFORM_ANDROID
633  UniformIndex = GL.GetUniformLocation(resourceId, new StringBuilder(uniformName))
634 #else
635  UniformIndex = GL.GetUniformLocation(resourceId, uniformName)
636 #endif
637  });
638  constantBufferDescription.Size += uniformSize * uniformCount;
639  }
640 #endif
641 
642  private static int GetCountFromActiveUniformType(ActiveUniformType type)
643  {
644  switch (type)
645  {
646  case ActiveUniformType.Int:
647  case ActiveUniformType.Float:
648  case ActiveUniformType.Bool:
649  return 1;
650  case ActiveUniformType.IntVec2:
651 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
652  case ActiveUniformType.UnsignedIntVec2:
653 #endif
654  case ActiveUniformType.FloatVec2:
655  case ActiveUniformType.BoolVec2:
656  return 2;
657  case ActiveUniformType.IntVec3:
658 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
659  case ActiveUniformType.UnsignedIntVec3:
660 #endif
661  case ActiveUniformType.FloatVec3:
662  case ActiveUniformType.BoolVec3:
663  return 3;
664  case ActiveUniformType.IntVec4:
665 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
666  case ActiveUniformType.UnsignedIntVec4:
667 #endif
668  case ActiveUniformType.FloatVec4:
669  case ActiveUniformType.BoolVec4:
670  case ActiveUniformType.FloatMat2:
671  return 4;
672 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
673  case ActiveUniformType.FloatMat2x3:
674  case ActiveUniformType.FloatMat3x2:
675  return 6;
676  case ActiveUniformType.FloatMat2x4:
677  case ActiveUniformType.FloatMat4x2:
678  return 8;
679 #endif
680  case ActiveUniformType.FloatMat3:
681  return 9;
682 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
683  case ActiveUniformType.FloatMat3x4:
684  case ActiveUniformType.FloatMat4x3:
685  return 12;
686 #endif
687  case ActiveUniformType.FloatMat4:
688  return 16;
689 
690  case ActiveUniformType.Sampler2D:
691  case ActiveUniformType.SamplerCube:
692 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
693  case ActiveUniformType.Sampler1D:
694  case ActiveUniformType.Sampler3D:
695  case ActiveUniformType.Sampler1DShadow:
696  case ActiveUniformType.Sampler2DShadow:
697  case ActiveUniformType.Sampler2DRect:
698  case ActiveUniformType.Sampler2DRectShadow:
699  case ActiveUniformType.SamplerCubeShadow:
700  case ActiveUniformType.IntSampler1D:
701  case ActiveUniformType.IntSampler2D:
702  case ActiveUniformType.IntSampler3D:
703  case ActiveUniformType.IntSamplerCube:
704  case ActiveUniformType.IntSampler2DRect:
705  case ActiveUniformType.UnsignedIntSampler1D:
706  case ActiveUniformType.UnsignedIntSampler2D:
707  case ActiveUniformType.UnsignedIntSampler3D:
708  case ActiveUniformType.UnsignedIntSamplerCube:
709  case ActiveUniformType.UnsignedIntSampler2DRect:
710  return 1;
711  case ActiveUniformType.Sampler1DArray:
712  case ActiveUniformType.Sampler2DArray:
713  case ActiveUniformType.Sampler1DArrayShadow:
714  case ActiveUniformType.Sampler2DArrayShadow:
715  case ActiveUniformType.IntSampler1DArray:
716  case ActiveUniformType.IntSampler2DArray:
717  case ActiveUniformType.UnsignedIntSampler1DArray:
718  case ActiveUniformType.UnsignedIntSampler2DArray:
719  return 1;
720  case ActiveUniformType.SamplerBuffer:
721  case ActiveUniformType.IntSamplerBuffer:
722  case ActiveUniformType.UnsignedIntSamplerBuffer:
723  return 1;
724  case ActiveUniformType.Sampler2DMultisample:
725  case ActiveUniformType.IntSampler2DMultisample:
726  case ActiveUniformType.UnsignedIntSampler2DMultisample:
727  return 1;
728  case ActiveUniformType.Sampler2DMultisampleArray:
729  case ActiveUniformType.IntSampler2DMultisampleArray:
730  case ActiveUniformType.UnsignedIntSampler2DMultisampleArray:
731 #endif
732  return 1;
733  default:
734  //TODO: log error ?
735  return 0;
736  }
737  }
738 
739  private static EffectParameterClass GetClassFromActiveUniformType(ActiveUniformType type)
740  {
741  switch (type)
742  {
743  case ActiveUniformType.Int:
744  case ActiveUniformType.Float:
745  case ActiveUniformType.Bool:
746  return EffectParameterClass.Scalar;
747  case ActiveUniformType.FloatVec2:
748  case ActiveUniformType.FloatVec3:
749  case ActiveUniformType.FloatVec4:
750  case ActiveUniformType.IntVec2:
751  case ActiveUniformType.IntVec3:
752  case ActiveUniformType.IntVec4:
753  case ActiveUniformType.BoolVec2:
754  case ActiveUniformType.BoolVec3:
755  case ActiveUniformType.BoolVec4:
756 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
757  case ActiveUniformType.UnsignedIntVec2:
758  case ActiveUniformType.UnsignedIntVec3:
759  case ActiveUniformType.UnsignedIntVec4:
760 #endif
761  return EffectParameterClass.Vector;
762  case ActiveUniformType.FloatMat2:
763  case ActiveUniformType.FloatMat3:
764  case ActiveUniformType.FloatMat4:
765 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
766  case ActiveUniformType.FloatMat2x3:
767  case ActiveUniformType.FloatMat2x4:
768  case ActiveUniformType.FloatMat3x2:
769  case ActiveUniformType.FloatMat3x4:
770  case ActiveUniformType.FloatMat4x2:
771  case ActiveUniformType.FloatMat4x3:
772 #endif
773  return EffectParameterClass.MatrixColumns;
774  //return EffectParameterClass.MatrixRows;
775  //return EffectParameterClass.Vector;
776  case ActiveUniformType.Sampler2D:
777  case ActiveUniformType.SamplerCube:
778 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
779  case ActiveUniformType.Sampler1D:
780  case ActiveUniformType.Sampler3D:
781  case ActiveUniformType.Sampler1DShadow:
782  case ActiveUniformType.Sampler2DShadow:
783  case ActiveUniformType.Sampler2DRect:
784  case ActiveUniformType.Sampler2DRectShadow:
785  case ActiveUniformType.Sampler1DArray:
786  case ActiveUniformType.Sampler2DArray:
787  case ActiveUniformType.SamplerBuffer:
788  case ActiveUniformType.Sampler1DArrayShadow:
789  case ActiveUniformType.Sampler2DArrayShadow:
790  case ActiveUniformType.SamplerCubeShadow:
791  case ActiveUniformType.IntSampler1D:
792  case ActiveUniformType.IntSampler2D:
793  case ActiveUniformType.IntSampler3D:
794  case ActiveUniformType.IntSamplerCube:
795  case ActiveUniformType.IntSampler2DRect:
796  case ActiveUniformType.IntSampler1DArray:
797  case ActiveUniformType.IntSampler2DArray:
798  case ActiveUniformType.IntSamplerBuffer:
799  case ActiveUniformType.UnsignedIntSampler1D:
800  case ActiveUniformType.UnsignedIntSampler2D:
801  case ActiveUniformType.UnsignedIntSampler3D:
802  case ActiveUniformType.UnsignedIntSamplerCube:
803  case ActiveUniformType.UnsignedIntSampler2DRect:
804  case ActiveUniformType.UnsignedIntSampler1DArray:
805  case ActiveUniformType.UnsignedIntSampler2DArray:
806  case ActiveUniformType.UnsignedIntSamplerBuffer:
807  case ActiveUniformType.Sampler2DMultisample:
808  case ActiveUniformType.IntSampler2DMultisample:
809  case ActiveUniformType.UnsignedIntSampler2DMultisample:
810  case ActiveUniformType.Sampler2DMultisampleArray:
811  case ActiveUniformType.IntSampler2DMultisampleArray:
812  case ActiveUniformType.UnsignedIntSampler2DMultisampleArray:
813 #endif
814  return EffectParameterClass.TextureBuffer;
815  default:
816  //TODO: log error ?
817  return EffectParameterClass.Object;
818  }
819  }
820 
821  private static EffectParameterType GetTypeFromActiveUniformType(ActiveUniformType type)
822  {
823  switch (type)
824  {
825  case ActiveUniformType.Int:
826  case ActiveUniformType.IntVec2:
827  case ActiveUniformType.IntVec3:
828  case ActiveUniformType.IntVec4:
829  return EffectParameterType.Int;
830  case ActiveUniformType.Float:
831  case ActiveUniformType.FloatVec2:
832  case ActiveUniformType.FloatVec3:
833  case ActiveUniformType.FloatVec4:
834  case ActiveUniformType.FloatMat2:
835  case ActiveUniformType.FloatMat3:
836  case ActiveUniformType.FloatMat4:
837 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
838  case ActiveUniformType.FloatMat2x3:
839  case ActiveUniformType.FloatMat2x4:
840  case ActiveUniformType.FloatMat3x2:
841  case ActiveUniformType.FloatMat3x4:
842  case ActiveUniformType.FloatMat4x2:
843  case ActiveUniformType.FloatMat4x3:
844 #endif
845  return EffectParameterType.Float;
846  case ActiveUniformType.Bool:
847  case ActiveUniformType.BoolVec2:
848  case ActiveUniformType.BoolVec3:
849  case ActiveUniformType.BoolVec4:
850  return EffectParameterType.Bool;
851 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
852  case ActiveUniformType.UnsignedIntVec2:
853  case ActiveUniformType.UnsignedIntVec3:
854  case ActiveUniformType.UnsignedIntVec4:
855  return EffectParameterType.UInt;
856  case ActiveUniformType.Sampler1D:
857  case ActiveUniformType.Sampler1DShadow:
858  case ActiveUniformType.IntSampler1D:
859  case ActiveUniformType.UnsignedIntSampler1D:
860  return EffectParameterType.Texture1D;
861 #endif
862  case ActiveUniformType.Sampler2D:
863 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
864  case ActiveUniformType.Sampler2DShadow:
865  case ActiveUniformType.Sampler2DRect:
866  case ActiveUniformType.Sampler2DRectShadow:
867  case ActiveUniformType.IntSampler2D:
868  case ActiveUniformType.IntSampler2DRect:
869  case ActiveUniformType.UnsignedIntSampler2D:
870  case ActiveUniformType.UnsignedIntSampler2DRect:
871 #endif
872  return EffectParameterType.Texture2D;
873 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
874  case ActiveUniformType.Sampler3D:
875  case ActiveUniformType.IntSampler3D:
876  case ActiveUniformType.UnsignedIntSampler3D:
877  return EffectParameterType.Texture3D;
878 #endif
879  case ActiveUniformType.SamplerCube:
880 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
881  case ActiveUniformType.SamplerCubeShadow:
882  case ActiveUniformType.IntSamplerCube:
883  case ActiveUniformType.UnsignedIntSamplerCube:
884 #endif
885  return EffectParameterType.TextureCube;
886 #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
887  case ActiveUniformType.Sampler1DArray:
888  case ActiveUniformType.Sampler1DArrayShadow:
889  case ActiveUniformType.IntSampler1DArray:
890  case ActiveUniformType.UnsignedIntSampler1DArray:
891  return EffectParameterType.Texture1DArray;
892  case ActiveUniformType.Sampler2DArray:
893  case ActiveUniformType.Sampler2DArrayShadow:
894  case ActiveUniformType.IntSampler2DArray:
895  case ActiveUniformType.UnsignedIntSampler2DArray:
896  return EffectParameterType.Texture2DArray;
897  case ActiveUniformType.SamplerBuffer:
898  case ActiveUniformType.IntSamplerBuffer:
899  case ActiveUniformType.UnsignedIntSamplerBuffer:
900  return EffectParameterType.TextureBuffer;
901  case ActiveUniformType.Sampler2DMultisample:
902  case ActiveUniformType.IntSampler2DMultisample:
903  case ActiveUniformType.UnsignedIntSampler2DMultisample:
904  return EffectParameterType.Texture2DMultisampled;
905  case ActiveUniformType.Sampler2DMultisampleArray:
906  case ActiveUniformType.IntSampler2DMultisampleArray:
907  case ActiveUniformType.UnsignedIntSampler2DMultisampleArray:
908  return EffectParameterType.Texture2DMultisampledArray;
909 #endif
910  default:
911  //TODO: log error ?
912  return EffectParameterType.Void;
913  }
914  }
915 
916  class UniformMergeInfo
917  {
918  public ActiveUniformType Type;
919  public int Offset;
920  public int NextOffset;
921  public string Name;
922  }
923  }
924 }
925 #endif
SiliconStudio.Shaders.Ast.Hlsl.ConstantBuffer ConstantBuffer
The content is resized to fit in the destination dimensions while it preserves its native aspect rati...
ComponentBase.Destroy() event.
SiliconStudio.Core.Diagnostics.LoggerResult LoggerResult
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}.
Same as Deferred mode, except sprites are sorted by texture prior to drawing. This can improve perfor...
EffectParameterClass
Values that identify the class of a shader variable.
ShaderStage
Enum to specify shader stage.
Definition: ShaderStage.cs:12
_In_ size_t _In_ size_t size
Definition: DirectXTexP.h:175