Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
Effect.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.Collections.Generic;
5 using System.Linq;
6 using SiliconStudio.Core;
7 using SiliconStudio.Core.Mathematics;
8 using SiliconStudio.Core.Serialization;
9 using SiliconStudio.Core.Serialization.Contents;
10 using SiliconStudio.Core.Serialization.Converters;
11 using SiliconStudio.Paradox.Effects;
12 using SiliconStudio.Paradox.Graphics.Internals;
13 using SiliconStudio.Paradox.Shaders;
14 using SiliconStudio.Paradox.Shaders.Compiler;
15 
16 namespace SiliconStudio.Paradox.Graphics
17 {
18  [ContentSerializer(typeof(DataContentConverterSerializer<Effect>))]
19  public class Effect : ComponentBase
20  {
21  private GraphicsDevice graphicsDeviceDefault;
22  private EffectProgram program;
23  private ShaderParameterUpdaterDefinition updaterDefinition;
24  private EffectParameterResourceBinding[] resourceBindings;
25  private ParameterCollection defaultParameters;
26  private EffectReflection reflection;
27  private EffectInputSignature inputSignature;
28  private readonly ParameterCollection parameters;
29  private const int DefaultParameterCollectionCount = 3;
30 
31  private EffectStateBindings effectStateBindings;
32 
33  public static readonly ParameterKey<RasterizerState> RasterizerStateKey = ParameterKeys.New<RasterizerState>();
34  public static readonly ParameterKey<DepthStencilState> DepthStencilStateKey = ParameterKeys.New<DepthStencilState>();
35  public static readonly ParameterKey<BlendState> BlendStateKey = ParameterKeys.New<BlendState>();
36 
37  internal ParameterCollection CompilationParameters;
38  internal ParameterCollection DefaultCompilationParameters;
39 
40  static Effect()
41  {
42  ConverterContext.RegisterConverter(new EffectConverter());
43  }
44 
45  /// <summary>
46  /// Initializes a new instance of the <see cref="Effect"/> class.
47  /// </summary>
48  /// <param name="device">The device.</param>
49  /// <param name="bytecode">The bytecode.</param>
50  public Effect(GraphicsDevice device, byte[] bytecode)
51  : this(device, BinarySerialization.Read<EffectBytecode>(bytecode))
52  {
53  }
54 
55  /// <summary>
56  /// Initializes a new instance of the <see cref="Effect"/> class.
57  /// </summary>
58  /// <param name="device">The device.</param>
59  /// <param name="bytecode">The bytecode.</param>
60  /// <param name="usedParameters">The parameters used to create this shader (from a pdxfx).</param>
61  /// <exception cref="System.ArgumentNullException">
62  /// device
63  /// or
64  /// bytecode
65  /// </exception>
66  public Effect(GraphicsDevice device, EffectBytecode bytecode, ParameterCollection usedParameters = null)
67  {
68  if (device == null) throw new ArgumentNullException("device");
69  if (bytecode == null) throw new ArgumentNullException("bytecode");
70 
71  parameters = new ParameterCollection();
72  Initialize(device, bytecode, usedParameters);
73  Changed = false;
74  }
75 
76  /// <summary>
77  /// Gets the input signature of this effect.
78  /// </summary>
79  /// <value>The input signature.</value>
80  public EffectInputSignature InputSignature
81  {
82  get
83  {
84  return inputSignature;
85  }
86  }
87 
88  /// <summary>
89  /// Gets the parameters.
90  /// </summary>
91  /// <value>The parameters.</value>
92  public ParameterCollection Parameters
93  {
94  get
95  {
96  return parameters;
97  }
98  }
99 
100  /// <summary>
101  /// Gets a boolean indicating if the effect changed since last update.
102  /// </summary>
103  /// <value>The changed.</value>
104  public bool Changed
105  {
106  get; internal set;
107  }
108 
109  public List<ShaderConstantBufferDescription> ConstantBuffers
110  {
111  get
112  {
113  return reflection.ConstantBuffers;
114  }
115  }
116 
117  public void Apply(bool applyEffectStates = false)
118  {
119  Apply(graphicsDeviceDefault, applyEffectStates);
120  }
121 
122  public void Apply(ParameterCollection paramCollection1, bool applyEffectStates = false)
123  {
124  Apply(graphicsDeviceDefault, paramCollection1, applyEffectStates);
125  }
126 
127  public void Apply(ParameterCollection paramCollection1, ParameterCollection paramCollection2, bool applyEffectStates = false)
128  {
129  Apply(graphicsDeviceDefault, paramCollection1, paramCollection2, applyEffectStates);
130  }
131 
132  public void Apply(ParameterCollection paramCollection1, ParameterCollection paramCollection2, ParameterCollection paramCollection3, bool applyEffectStates = false)
133  {
134  Apply(graphicsDeviceDefault, paramCollection1, paramCollection2, paramCollection3, applyEffectStates);
135  }
136 
137  public void Apply(ParameterCollection paramCollection1, ParameterCollection paramCollection2, ParameterCollection paramCollection3, ParameterCollection paramCollection4, bool applyEffectStates = false)
138  {
139  Apply(graphicsDeviceDefault, paramCollection1, paramCollection2, paramCollection3, paramCollection4, applyEffectStates);
140  }
141 
142  public void Apply(ParameterCollection paramCollection1, ParameterCollection paramCollection2, ParameterCollection paramCollection3, ParameterCollection paramCollection4, ParameterCollection paramCollection5, bool applyEffectStates = false)
143  {
144  Apply(graphicsDeviceDefault, paramCollection1, paramCollection2, paramCollection3, paramCollection4, paramCollection5, applyEffectStates);
145  }
146 
147  public void Apply(ParameterCollection paramCollection1, ParameterCollection paramCollection2, ParameterCollection paramCollection3, ParameterCollection paramCollection4, ParameterCollection paramCollection5, ParameterCollection paramCollection6, bool applyEffectStates = false)
148  {
149  Apply(graphicsDeviceDefault, paramCollection1, paramCollection2, paramCollection3, paramCollection4, paramCollection5, paramCollection6, applyEffectStates);
150  }
151 
152  public void Apply(ParameterCollection[] parameterCollections, bool applyEffectStates = false)
153  {
154  Apply(graphicsDeviceDefault, parameterCollections, applyEffectStates);
155  }
156 
157  public void UnbindResources()
158  {
159  UnbindResources(graphicsDeviceDefault);
160  }
161 
162  internal EffectParameterResourceBinding GetParameterFastUpdater<T>(ParameterKey<T> value)
163  {
164  for (int i = 0; i < resourceBindings.Length; i++)
165  {
166  if (resourceBindings[i].Description.Param.Key == value)
167  {
168  return resourceBindings[i];
169  }
170  }
171 
172  throw new ArgumentException("Parameter resource binding not found.", "value");
173  }
174 
175  public void Apply(GraphicsDevice graphicsDevice, bool applyEffectStates)
176  {
177  PrepareApply(graphicsDevice);
178  var stageStatus = graphicsDevice.StageStatus;
179 
180  stageStatus.ParameterCollections[0] = defaultParameters; // Default Parameters contains all registered Parameters used effectively by the effect
181  stageStatus.ParameterCollections[1] = parameters;
182  stageStatus.ParameterCollections[2] = graphicsDevice.Parameters; // GraphicsDevice.Parameters is overriding all parameters
183  stageStatus.UpdateParameters(graphicsDevice, updaterDefinition, DefaultParameterCollectionCount);
184  stageStatus.Apply(graphicsDevice, resourceBindings, ref effectStateBindings, applyEffectStates);
185  }
186 
187  public void Apply(GraphicsDevice graphicsDevice, ParameterCollection paramCollection1, bool applyEffectStates)
188  {
189  PrepareApply(graphicsDevice);
190  var stageStatus = graphicsDevice.StageStatus;
191 
192  stageStatus.ParameterCollections[0] = defaultParameters; // Default Parameters contains all registered Parameters used effectively by the effect
193  stageStatus.ParameterCollections[1] = parameters;
194  stageStatus.ParameterCollections[2] = paramCollection1;
195  stageStatus.ParameterCollections[3] = graphicsDevice.Parameters; // GraphicsDevice.Parameters is overriding all parameters
196  stageStatus.UpdateParameters(graphicsDevice, updaterDefinition, DefaultParameterCollectionCount + 1);
197  stageStatus.Apply(graphicsDevice, resourceBindings, ref effectStateBindings, applyEffectStates);
198  }
199 
200  public void Apply(GraphicsDevice graphicsDevice, ParameterCollection paramCollection1, ParameterCollection paramCollection2, bool applyEffectStates)
201  {
202  PrepareApply(graphicsDevice);
203  var stageStatus = graphicsDevice.StageStatus;
204 
205  stageStatus.ParameterCollections[0] = defaultParameters; // Default Parameters contains all registered Parameters used effectively by the effect
206  stageStatus.ParameterCollections[1] = parameters;
207  stageStatus.ParameterCollections[2] = paramCollection1;
208  stageStatus.ParameterCollections[3] = paramCollection2;
209  stageStatus.ParameterCollections[4] = graphicsDevice.Parameters; // GraphicsDevice.Parameters is overriding all parameters
210  stageStatus.UpdateParameters(graphicsDevice, updaterDefinition, DefaultParameterCollectionCount + 2);
211  stageStatus.Apply(graphicsDevice, resourceBindings, ref effectStateBindings, applyEffectStates);
212  }
213 
214  public void Apply(GraphicsDevice graphicsDevice, ParameterCollection paramCollection1, ParameterCollection paramCollection2, ParameterCollection paramCollection3, bool applyEffectStates)
215  {
216  PrepareApply(graphicsDevice);
217  var stageStatus = graphicsDevice.StageStatus;
218 
219  stageStatus.ParameterCollections[0] = defaultParameters; // Default Parameters contains all registered Parameters used effectively by the effect
220  stageStatus.ParameterCollections[1] = parameters;
221  stageStatus.ParameterCollections[2] = paramCollection1;
222  stageStatus.ParameterCollections[3] = paramCollection2;
223  stageStatus.ParameterCollections[4] = paramCollection3;
224  stageStatus.ParameterCollections[5] = graphicsDevice.Parameters; // GraphicsDevice.Parameters is overriding all parameters
225  stageStatus.UpdateParameters(graphicsDevice, updaterDefinition, DefaultParameterCollectionCount + 3);
226  stageStatus.Apply(graphicsDevice, resourceBindings, ref effectStateBindings, applyEffectStates);
227  }
228 
229  public void Apply(GraphicsDevice graphicsDevice, ParameterCollection paramCollection1, ParameterCollection paramCollection2, ParameterCollection paramCollection3, ParameterCollection paramCollection4, bool applyEffectStates)
230  {
231  PrepareApply(graphicsDevice);
232  var stageStatus = graphicsDevice.StageStatus;
233 
234  stageStatus.ParameterCollections[0] = defaultParameters; // Default Parameters contains all registered Parameters used effectively by the effect
235  stageStatus.ParameterCollections[1] = parameters;
236  stageStatus.ParameterCollections[2] = paramCollection1;
237  stageStatus.ParameterCollections[3] = paramCollection2;
238  stageStatus.ParameterCollections[4] = paramCollection3;
239  stageStatus.ParameterCollections[5] = paramCollection4;
240  stageStatus.ParameterCollections[6] = graphicsDevice.Parameters; // GraphicsDevice.Parameters is overriding all parameters
241  stageStatus.UpdateParameters(graphicsDevice, updaterDefinition, DefaultParameterCollectionCount + 4);
242  stageStatus.Apply(graphicsDevice, resourceBindings, ref effectStateBindings, applyEffectStates);
243  }
244 
245  public void Apply(GraphicsDevice graphicsDevice, ParameterCollection paramCollection1, ParameterCollection paramCollection2, ParameterCollection paramCollection3, ParameterCollection paramCollection4, ParameterCollection paramCollection5, bool applyEffectStates)
246  {
247  PrepareApply(graphicsDevice);
248  var stageStatus = graphicsDevice.StageStatus;
249 
250  stageStatus.ParameterCollections[0] = defaultParameters; // Default Parameters contains all registered Parameters used effectively by the effect
251  stageStatus.ParameterCollections[1] = parameters;
252  stageStatus.ParameterCollections[2] = paramCollection1;
253  stageStatus.ParameterCollections[3] = paramCollection2;
254  stageStatus.ParameterCollections[4] = paramCollection3;
255  stageStatus.ParameterCollections[5] = paramCollection4;
256  stageStatus.ParameterCollections[6] = paramCollection5;
257  stageStatus.ParameterCollections[7] = graphicsDevice.Parameters; // GraphicsDevice.Parameters is overriding all parameters
258  stageStatus.UpdateParameters(graphicsDevice, updaterDefinition, DefaultParameterCollectionCount + 5);
259  stageStatus.Apply(graphicsDevice, resourceBindings, ref effectStateBindings, applyEffectStates);
260  }
261 
262  public void Apply(GraphicsDevice graphicsDevice, ParameterCollection paramCollection1, ParameterCollection paramCollection2, ParameterCollection paramCollection3, ParameterCollection paramCollection4, ParameterCollection paramCollection5, ParameterCollection paramCollection6, bool applyEffectStates)
263  {
264  PrepareApply(graphicsDevice);
265  var stageStatus = graphicsDevice.StageStatus;
266 
267  stageStatus.ParameterCollections[0] = defaultParameters; // Default Parameters contains all registered Parameters used effectively by the effect
268  stageStatus.ParameterCollections[1] = parameters;
269  stageStatus.ParameterCollections[2] = paramCollection1;
270  stageStatus.ParameterCollections[3] = paramCollection2;
271  stageStatus.ParameterCollections[4] = paramCollection3;
272  stageStatus.ParameterCollections[5] = paramCollection4;
273  stageStatus.ParameterCollections[6] = paramCollection5;
274  stageStatus.ParameterCollections[7] = paramCollection6;
275  stageStatus.ParameterCollections[8] = graphicsDevice.Parameters; // GraphicsDevice.Parameters is overriding all parameters
276  stageStatus.UpdateParameters(graphicsDevice, updaterDefinition, DefaultParameterCollectionCount + 6);
277  stageStatus.Apply(graphicsDevice, resourceBindings, ref effectStateBindings, applyEffectStates);
278  }
279 
280  public void Apply(GraphicsDevice graphicsDevice, ParameterCollection[] parameterCollections, bool applyEffectStates)
281  {
282  if (parameterCollections == null) throw new ArgumentNullException("parameterCollections");
283 
284  PrepareApply(graphicsDevice);
285  var stageStatus = graphicsDevice.StageStatus;
286 
287  if ((parameterCollections.Length + DefaultParameterCollectionCount) > stageStatus.ParameterCollections.Length)
288  {
289  throw new ArgumentException(string.Format("Exceeding limit of number of parameter collections [{0}]", stageStatus.ParameterCollections.Length - DefaultParameterCollectionCount));
290  }
291 
292  stageStatus.ParameterCollections[0] = defaultParameters; // Default Parameters contains all registered Parameters used effectively by the effect
293  stageStatus.ParameterCollections[1] = parameters;
294  for (int i = 0; i < parameterCollections.Length; i++ )
295  {
296  stageStatus.ParameterCollections[i + DefaultParameterCollectionCount - 1] = parameterCollections[i];
297  }
298  stageStatus.ParameterCollections[parameterCollections.Length + DefaultParameterCollectionCount - 1] = graphicsDevice.Parameters; // GraphicsDevice.Parameters is overriding all parameters
299  stageStatus.UpdateParameters(graphicsDevice, updaterDefinition, parameterCollections.Length + DefaultParameterCollectionCount);
300  stageStatus.Apply(graphicsDevice, resourceBindings, ref effectStateBindings, applyEffectStates);
301  }
302 
303  public void UnbindResources(GraphicsDevice graphicsDevice)
304  {
305  var stageStatus = graphicsDevice.StageStatus;
306  stageStatus.UnbindResources(graphicsDevice, resourceBindings);
307  }
308 
309  public bool HasParameter(ParameterKey parameterKey)
310  {
311  return defaultParameters.ContainsKey(parameterKey);
312  }
313 
314  private void PrepareApply(GraphicsDevice graphicsDevice)
315  {
316  if (graphicsDevice == null) throw new ArgumentNullException("graphicsDevice");
317 
318  program.Apply(graphicsDevice);
319  graphicsDevice.CurrentEffect = this;
320  graphicsDevice.ApplyPlatformSpecificParams(this);
321  }
322 
323  internal void Initialize(GraphicsDevice device, EffectBytecode byteCode, ParameterCollection usedParameters)
324  {
325  Name = byteCode.Name;
326  graphicsDeviceDefault = device.RootDevice;
327  program = EffectProgram.New(graphicsDeviceDefault, byteCode);
328  reflection = byteCode.Reflection;
329 
330  // prepare resource bindings used internally
331  resourceBindings = new EffectParameterResourceBinding[byteCode.Reflection.ResourceBindings.Count];
332  for (int i = 0; i < resourceBindings.Length; i++)
333  {
334  resourceBindings[i].Description = byteCode.Reflection.ResourceBindings[i];
335  }
336  defaultParameters = new ParameterCollection();
337  inputSignature = program.InputSignature;
338  LoadDefaultParameters();
339 
340  CompilationParameters = new ParameterCollection();
341  DefaultCompilationParameters = new ParameterCollection();
342  if (usedParameters != null)
343  {
344  foreach (var parameter in usedParameters)
345  {
346  if (parameter.Key != CompilerParameters.DebugKey && parameter.Key != CompilerParameters.GraphicsPlatformKey && parameter.Key != CompilerParameters.GraphicsProfileKey)
347  CompilationParameters.SetObject(parameter.Key, parameter.Value);
348  }
349  }
350 
351  foreach (var key in CompilationParameters.Keys)
352  {
353  DefaultCompilationParameters.RegisterParameter(key, false);
354  }
355 
356  Changed = true;
357  }
358 
359  private void LoadDefaultParameters()
360  {
361  var shaderParameters = defaultParameters; // Default Parameters contains all registered Parameters used effectively by the effect
362  var constantBufferKeys = new Dictionary<string, ParameterKey<ParameterConstantBuffer>>();
363 
364  // Create parameter bindings
365  for (int i = 0; i < resourceBindings.Length; i++)
366  {
367  // Update binding key
368  var key = UpdateResourceBindingKey(ref resourceBindings[i].Description);
369 
370  // ConstantBuffers are handled by next loop
371  if (resourceBindings[i].Description.Param.Class != EffectParameterClass.ConstantBuffer)
372  {
373  shaderParameters.RegisterParameter(key, false);
374  }
375  }
376 
377  // Create constant buffers from descriptions (previously generated from shader reflection)
378  foreach (var constantBuffer in reflection.ConstantBuffers)
379  {
380  var constantBufferMembers = constantBuffer.Members;
381 
382  for (int i = 0; i < constantBufferMembers.Length; ++i)
383  {
384  // Update binding key
385  var key = UpdateValueBindingKey(ref constantBufferMembers[i]);
386 
387  // Register ParameterKey with this effect and store its index for direct access during rendering
388  shaderParameters.RegisterParameter(key, false);
389  }
390 
391  // Handle ConstantBuffer. Share the same key ParameterConstantBuffer with all the stages
392  var parameterConstantBuffer = new ParameterConstantBuffer(graphicsDeviceDefault, constantBuffer.Name, constantBuffer);
393  var constantBufferKey = ParameterKeys.New(parameterConstantBuffer, constantBuffer.Name);
394  shaderParameters.RegisterParameter(constantBufferKey, false);
395 
396  for (int i = 0; i < resourceBindings.Length; i++)
397  {
398  if (resourceBindings[i].Description.Param.Class == EffectParameterClass.ConstantBuffer && resourceBindings[i].Description.Param.Key.Name == constantBuffer.Name)
399  {
400  resourceBindings[i].Description.Param.Key = constantBufferKey;
401  }
402  }
403 
404  // Update constant buffer mapping (to avoid name clashes)
405  constantBufferKeys[constantBuffer.Name] = constantBufferKey;
406  }
407 
408  UpdateKeyIndices();
409 
410  // Once we have finished binding, we can fully prepare them
411  graphicsDeviceDefault.StageStatus.PrepareBindings(resourceBindings);
412  }
413 
414  private ParameterKey UpdateResourceBindingKey(ref EffectParameterResourceData binding)
415  {
416  var keyName = binding.Param.KeyName;
417 
418  switch (binding.Param.Class)
419  {
420  case EffectParameterClass.Sampler:
421  var newSamplerKey = (ParameterKey<SamplerState>)FindOrCreateResourceKey<SamplerState>(keyName);
422  binding.Param.Key = newSamplerKey;
423  var samplerBinding = reflection.SamplerStates.FirstOrDefault(x => x.KeyName == keyName);
424  if (samplerBinding != null)
425  {
426  samplerBinding.Key = newSamplerKey;
427  var samplerDescription = samplerBinding.Description;
428  defaultParameters.Set(newSamplerKey, SamplerState.New(graphicsDeviceDefault, samplerDescription));
429  }
430  break;
431  case EffectParameterClass.ConstantBuffer:
432  case EffectParameterClass.TextureBuffer:
433  case EffectParameterClass.ShaderResourceView:
434  case EffectParameterClass.UnorderedAccessView:
435  switch (binding.Param.Type)
436  {
437  case EffectParameterType.Buffer:
438  case EffectParameterType.ConstantBuffer:
439  case EffectParameterType.TextureBuffer:
440  case EffectParameterType.AppendStructuredBuffer:
441  case EffectParameterType.ByteAddressBuffer:
442  case EffectParameterType.ConsumeStructuredBuffer:
443  case EffectParameterType.StructuredBuffer:
444  case EffectParameterType.RWBuffer:
445  case EffectParameterType.RWStructuredBuffer:
446  case EffectParameterType.RWByteAddressBuffer:
447  binding.Param.Key = FindOrCreateResourceKey<Buffer>(keyName);
448  break;
449  case EffectParameterType.Texture1D:
450  case EffectParameterType.Texture1DArray:
451  case EffectParameterType.RWTexture1D:
452  case EffectParameterType.RWTexture1DArray:
453  binding.Param.Key = FindOrCreateResourceKey<Texture1D>(keyName);
454  break;
455  case EffectParameterType.Texture2D:
456  case EffectParameterType.Texture2DArray:
457  case EffectParameterType.Texture2DMultisampled:
458  case EffectParameterType.Texture2DMultisampledArray:
459  case EffectParameterType.RWTexture2D:
460  case EffectParameterType.RWTexture2DArray:
461  binding.Param.Key = FindOrCreateResourceKey<Texture2D>(keyName);
462  break;
463  case EffectParameterType.TextureCube:
464  case EffectParameterType.TextureCubeArray:
465  binding.Param.Key = FindOrCreateResourceKey<TextureCube>(keyName);
466  break;
467  case EffectParameterType.RWTexture3D:
468  case EffectParameterType.Texture3D:
469  binding.Param.Key = FindOrCreateResourceKey<Texture3D>(keyName);
470  break;
471  }
472  break;
473  }
474 
475  if (binding.Param.Key == null)
476  {
477  throw new InvalidOperationException(string.Format("Unable to find/generate key [{0}] with unsupported type [{1}/{2}]", binding.Param.KeyName, binding.Param.Class, binding.Param.Type));
478  }
479 
480  return binding.Param.Key;
481  }
482 
483  private ParameterKey UpdateValueBindingKey(ref EffectParameterValueData binding)
484  {
485  switch (binding.Param.Class)
486  {
487  case EffectParameterClass.Scalar:
488  switch (binding.Param.Type)
489  {
490  case EffectParameterType.Bool:
491  binding.Param.Key = FindOrCreateValueKey<bool>(binding);
492  break;
493  case EffectParameterType.Int:
494  binding.Param.Key = FindOrCreateValueKey<int>(binding);
495  break;
496  case EffectParameterType.UInt:
497  binding.Param.Key = FindOrCreateValueKey<uint>(binding);
498  break;
499  case EffectParameterType.Float:
500  binding.Param.Key = FindOrCreateValueKey<float>(binding);
501  break;
502  }
503  break;
504  case EffectParameterClass.Color:
505  {
506  var componentCount = binding.RowCount != 1 ? binding.RowCount : binding.ColumnCount;
507  switch (binding.Param.Type)
508  {
509  case EffectParameterType.Float:
510  binding.Param.Key = componentCount == 4
511  ? FindOrCreateValueKey<Color4>(binding)
512  : (componentCount == 3 ? (ParameterKey)FindOrCreateValueKey<Color3>(binding) : null);
513  break;
514  }
515  }
516  break;
517  case EffectParameterClass.Vector:
518  {
519  var componentCount = binding.RowCount != 1 ? binding.RowCount : binding.ColumnCount;
520  switch (binding.Param.Type)
521  {
522  case EffectParameterType.Bool:
523  case EffectParameterType.Int:
524  binding.Param.Key = componentCount == 4 ? (ParameterKey)FindOrCreateValueKey<Int4>(binding) : (componentCount == 3 ? FindOrCreateValueKey<Int3>(binding) : null);
525  break;
526  case EffectParameterType.UInt:
527  binding.Param.Key = componentCount == 4 ? FindOrCreateValueKey<UInt4>(binding) : null;
528  break;
529  case EffectParameterType.Float:
530  binding.Param.Key = componentCount == 4
531  ? FindOrCreateValueKey<Vector4>(binding)
532  : (componentCount == 3 ? (ParameterKey)FindOrCreateValueKey<Vector3>(binding) : (componentCount == 2 ? FindOrCreateValueKey<Vector2>(binding) : null));
533  break;
534  }
535  }
536  break;
537  case EffectParameterClass.MatrixRows:
538  case EffectParameterClass.MatrixColumns:
539  binding.Param.Key = FindOrCreateValueKey<Matrix>(binding);
540  break;
541  case EffectParameterClass.Struct:
542  binding.Param.Key = ParameterKeys.FindByName(binding.Param.KeyName);
543  break;
544  }
545 
546  if (binding.Param.Key == null)
547  {
548  throw new InvalidOperationException(string.Format("Unable to find/generate key [{0}] with unsupported type [{1}/{2}]", binding.Param.KeyName, binding.Param.Class, binding.Param.Type));
549  }
550 
551  if (binding.Count > 1)
552  {
553  // Unspecified array length: guess from shader and set default parameter with array matching shader size
554  binding.Param.Key = binding.Param.Key.CloneLength(binding.Count);
555  }
556 
557  return binding.Param.Key;
558  }
559 
560  private ParameterKey FindOrCreateResourceKey<T>(string name)
561  {
562  return ParameterKeys.FindByName(name) ?? ParameterKeys.New<T>(name);
563  }
564 
565  private ParameterKey FindOrCreateValueKey<T>(EffectParameterValueData binding) where T : struct
566  {
567  var name = binding.Param.KeyName;
568  return ParameterKeys.FindByName(name) ?? (binding.Count > 1 ? (ParameterKey)ParameterKeys.New<T[]>(name) : ParameterKeys.New<T>(name));
569  }
570 
571  private void UpdateKeyIndices()
572  {
573  // TODO: For now, rebuild indices after processing
574  // This code is ugly (esp. constant buffer one), it needs to be done directly within processing (as soon as new system is adopted)
575  var keys = new HashSet<ParameterKey>();
576 
577  var allParameterDependencies = new Dictionary<ParameterKey, ParameterDependency>();
578  var parameterDependencies = new HashSet<ParameterDependency>();
579 
580  // Always add graphics states
581  keys.Add(RasterizerStateKey);
582  keys.Add(DepthStencilStateKey);
583  keys.Add(BlendStateKey);
584 
585  // Handle dynamic values
586  foreach (var dynamicValue in defaultParameters.DynamicValues.Concat(parameters.DynamicValues))
587  {
588  allParameterDependencies[dynamicValue.Target] = new ParameterDependency { Destination = dynamicValue.Target, Dynamic = dynamicValue, Sources = dynamicValue.Dependencies };
589  }
590 
591  // effectPass.DefaultParameters.Keys contains shader requested keys.
592  // Compute dependencies and add them in "keys".
593  foreach (var key in defaultParameters.Keys)
594  {
595  UpdateRequiredKeys(keys, allParameterDependencies, key, parameterDependencies);
596  }
597 
598  // Make sure every key (in "keys") is set in DefaultParameters to have a valid fallback
599  foreach (var key in keys)
600  {
601  defaultParameters.RegisterParameter(key, false);
602  }
603 
604  updaterDefinition = new ShaderParameterUpdaterDefinition(keys, parameterDependencies);
605 
606  // Cache internal values by specified index in EffectPass parameters (since they will be used by a given EffectPass.ParameterUpdater)
607  var keyMapping = updaterDefinition.SortedKeys.Select((x, i) => new { x, i }).ToDictionary(k => k.x, k => k.i);
608  defaultParameters.SetKeyMapping(keyMapping);
609  parameters.SetKeyMapping(keyMapping);
610 
611  for (int i = 0; i < resourceBindings.Length; ++i)
612  {
613  resourceBindings[i].Description.Param.KeyIndex = Array.IndexOf(updaterDefinition.SortedKeys, resourceBindings[i].Description.Param.Key);
614  }
615 
616  // Update Constant buffers description
617  foreach (var internalValue in defaultParameters.InternalValues)
618  {
619  var cb = internalValue.Value.Object as ParameterConstantBuffer;
620  if (cb != null)
621  {
622  for (int i = 0; i < cb.ConstantBufferDesc.Members.Length; ++i)
623  {
624  var member = cb.ConstantBufferDesc.Members[i];
625  member.Param.KeyIndex = Array.IndexOf(updaterDefinition.SortedKeys, member.Param.Key);
626  cb.ConstantBufferDesc.Members[i] = member;
627  }
628  }
629  }
630 
631  // Update effect state bindings
632  effectStateBindings.RasterizerStateKeyIndex = Array.IndexOf(updaterDefinition.SortedKeys, RasterizerStateKey);
633  effectStateBindings.DepthStencilStateKeyIndex = Array.IndexOf(updaterDefinition.SortedKeys, DepthStencilStateKey);
634  effectStateBindings.BlendStateKeyIndex = Array.IndexOf(updaterDefinition.SortedKeys, BlendStateKey);
635  }
636 
637  private void UpdateRequiredKeys(HashSet<ParameterKey> requiredKeys, Dictionary<ParameterKey, ParameterDependency> allDependencies, ParameterKey key, HashSet<ParameterDependency> requiredDependencies)
638  {
639  if (requiredKeys.Add(key))
640  {
641  ParameterDependency dependency;
642  if (allDependencies.TryGetValue(key, out dependency))
643  {
644  requiredDependencies.Add(dependency);
645  foreach (var source in dependency.Sources)
646  {
647  // Add Dependencies (if not already overriden)
648  // This is done only at this level because top-level keys dependencies are supposed to be present.
649  var sourceMetadata = source.Metadatas.OfType<ParameterKeyMetadata>().FirstOrDefault();
650  if (sourceMetadata != null
651  && sourceMetadata.DefaultDynamicValue != null
652  && !allDependencies.ContainsKey(source))
653  {
654  allDependencies[source] = new ParameterDependency { Destination = source, Dynamic = sourceMetadata.DefaultDynamicValue, Sources = sourceMetadata.DefaultDynamicValue.Dependencies };
655  }
656  UpdateRequiredKeys(requiredKeys, allDependencies, source, requiredDependencies);
657  }
658  }
659  }
660  }
661  }
662 }
static readonly ParameterKey< GraphicsProfile > GraphicsProfileKey
The graphics profile target type.
A resource that is accessible by both the GPU (read only) and the CPU (write only). A dynamic resource is a good choice for a resource that will be updated by the CPU at least once per frame. To update a dynamic resource, use a Map method.
Describes a shader parameter for a valuetype (usually stored in constant buffers).
Key of an effect parameter.
Definition: ParameterKey.cs:15
void Apply(ParameterCollection paramCollection1, ParameterCollection paramCollection2, ParameterCollection paramCollection3, ParameterCollection paramCollection4, bool applyEffectStates=false)
Definition: Effect.cs:137
Represents a two dimensional mathematical vector.
Definition: Vector2.cs:42
Contains depth-stencil state for the device.
void Apply(GraphicsDevice graphicsDevice, ParameterCollection[] parameterCollections, bool applyEffectStates)
Definition: Effect.cs:280
Represents a color in the form of rgb.
Definition: Color3.cs:41
Binary serialization method helpers to easily read/write data from a stream.
static readonly ParameterKey< GraphicsPlatform > GraphicsPlatformKey
The compiler platform type.
void Apply(GraphicsDevice graphicsDevice, ParameterCollection paramCollection1, ParameterCollection paramCollection2, bool applyEffectStates)
Definition: Effect.cs:200
void Apply(GraphicsDevice graphicsDevice, ParameterCollection paramCollection1, ParameterCollection paramCollection2, ParameterCollection paramCollection3, ParameterCollection paramCollection4, ParameterCollection paramCollection5, ParameterCollection paramCollection6, bool applyEffectStates)
Definition: Effect.cs:262
Key of an gereric effect parameter.
void Apply(GraphicsDevice graphicsDevice, ParameterCollection paramCollection1, ParameterCollection paramCollection2, ParameterCollection paramCollection3, ParameterCollection paramCollection4, bool applyEffectStates)
Definition: Effect.cs:229
Represents a three dimensional mathematical vector.
Definition: Vector3.cs:42
void Apply(ParameterCollection paramCollection1, ParameterCollection paramCollection2, bool applyEffectStates=false)
Definition: Effect.cs:127
void Apply(ParameterCollection paramCollection1, bool applyEffectStates=false)
Definition: Effect.cs:122
void Apply(ParameterCollection[] parameterCollections, bool applyEffectStates=false)
Definition: Effect.cs:152
Effect(GraphicsDevice device, EffectBytecode bytecode, ParameterCollection usedParameters=null)
Initializes a new instance of the Effect class.
Definition: Effect.cs:66
void Apply(GraphicsDevice graphicsDevice, ParameterCollection paramCollection1, ParameterCollection paramCollection2, ParameterCollection paramCollection3, bool applyEffectStates)
Definition: Effect.cs:214
Base class for a framework component.
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.
Describes a shader parameter for a resource type.
bool HasParameter(ParameterKey parameterKey)
Definition: Effect.cs:309
void Apply(ParameterCollection paramCollection1, ParameterCollection paramCollection2, ParameterCollection paramCollection3, bool applyEffectStates=false)
Definition: Effect.cs:132
void UnbindResources(GraphicsDevice graphicsDevice)
Definition: Effect.cs:303
void Apply(ParameterCollection paramCollection1, ParameterCollection paramCollection2, ParameterCollection paramCollection3, ParameterCollection paramCollection4, ParameterCollection paramCollection5, ParameterCollection paramCollection6, bool applyEffectStates=false)
Definition: Effect.cs:147
void Apply(GraphicsDevice graphicsDevice, ParameterCollection paramCollection1, bool applyEffectStates)
Definition: Effect.cs:187
void Apply(bool applyEffectStates=false)
Definition: Effect.cs:117
Describes an input signature for an Effect.
The reflection data describing the parameters of a shader.
Effect(GraphicsDevice device, byte[] bytecode)
Initializes a new instance of the Effect class.
Definition: Effect.cs:50
void Apply(GraphicsDevice graphicsDevice, ParameterCollection paramCollection1, ParameterCollection paramCollection2, ParameterCollection paramCollection3, ParameterCollection paramCollection4, ParameterCollection paramCollection5, bool applyEffectStates)
Definition: Effect.cs:245
EffectParameterClass
Values that identify the class of a shader variable.
static readonly ParameterKey< bool > DebugKey
The debug flag.
Contains a compiled shader with bytecode for each stage.
A container to handle a hierarchical collection of effect variables.
void Apply(GraphicsDevice graphicsDevice, bool applyEffectStates)
Definition: Effect.cs:175
void Apply(ParameterCollection paramCollection1, ParameterCollection paramCollection2, ParameterCollection paramCollection3, ParameterCollection paramCollection4, ParameterCollection paramCollection5, bool applyEffectStates=false)
Definition: Effect.cs:142
Represents a 4x4 mathematical matrix.
Definition: Matrix.cs:47