Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
DynamicEffectCompiler.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 
5 using SiliconStudio.Core;
6 using SiliconStudio.Core.Collections;
7 using SiliconStudio.Paradox.Graphics;
8 using SiliconStudio.Paradox.Shaders.Compiler;
9 
10 namespace SiliconStudio.Paradox.Effects
11 {
12  /// <summary>
13  /// Provides a dynamic compiler for an effect based on parameters changed.
14  /// </summary>
15  public class DynamicEffectCompiler
16  {
17  private readonly EffectParameterUpdater updater;
18  private readonly FastList<ParameterCollection> parameterCollections;
19 
20  private readonly string effectName;
21 
22  /// <summary>
23  /// Initializes a new instance of the <see cref="DynamicEffectCompiler"/> class.
24  /// </summary>
25  /// <param name="services">The services.</param>
26  /// <param name="effectName">Name of the effect.</param>
27  /// <exception cref="System.ArgumentNullException">
28  /// services
29  /// or
30  /// effectName
31  /// </exception>
32  public DynamicEffectCompiler(IServiceRegistry services, string effectName)
33  {
34  if (services == null) throw new ArgumentNullException("services");
35  if (effectName == null) throw new ArgumentNullException("effectName");
36  Services = services;
37  this.effectName = effectName;
38  EffectSystem = Services.GetSafeServiceAs<EffectSystem>();
39  GraphicsDevice = Services.GetSafeServiceAs<IGraphicsDeviceService>().GraphicsDevice;
40  updater = new EffectParameterUpdater();
41  parameterCollections = new FastList<ParameterCollection>();
42  }
43 
44  /// <summary>
45  /// Gets the services.
46  /// </summary>
47  /// <value>The services.</value>
48  public IServiceRegistry Services { get; private set; }
49 
50  /// <summary>
51  /// Gets the name of the effect.
52  /// </summary>
53  /// <value>The name of the effect.</value>
54  public string EffectName
55  {
56  get
57  {
58  return effectName;
59  }
60  }
61 
62  /// <summary>
63  /// Gets or sets the effect system.
64  /// </summary>
65  /// <value>The effect system.</value>
66  private EffectSystem EffectSystem { get; set; }
67 
68  /// <summary>
69  /// Gets or sets the graphics device.
70  /// </summary>
71  /// <value>The graphics device.</value>
72  private GraphicsDevice GraphicsDevice { get; set; }
73 
74  /// <summary>
75  /// Update a dynamic effect instance based on its parameters.
76  /// </summary>
77  /// <param name="effectInstance">A dynmaic effect instance</param>
78  /// <returns><c>true</c> if the effect was recomiled on the effect instance, <c>false</c> otherwise.</returns>
79  public bool Update(DynamicEffectInstance effectInstance)
80  {
81  bool effectChanged = false;
82 
83  if (effectInstance.Effect != null && effectInstance.Effect.Changed)
84  {
85  effectInstance.UpdaterDefinition.Initialize(effectInstance.Effect);
86  UpdateLevels(effectInstance);
87  effectChanged = true;
88  }
89 
90  if (effectInstance.Effect == null || HasCollectionChanged(effectInstance))
91  {
92  CreateEffect(effectInstance);
93  effectChanged = true;
94  }
95 
96  return effectChanged;
97  }
98 
99  private bool HasCollectionChanged(DynamicEffectInstance effectInstance)
100  {
101  PrepareUpdater(effectInstance);
102  return updater.HasChanged(effectInstance.UpdaterDefinition);
103  }
104 
105  private void CreateEffect(DynamicEffectInstance effectInstance)
106  {
107  var compilerParameters = new CompilerParameters();
108  parameterCollections.Clear(true);
109  effectInstance.FillParameterCollections(parameterCollections);
110 
111  foreach (var parameterCollection in parameterCollections)
112  {
113  if (parameterCollection != null)
114  {
115  foreach (var parameter in parameterCollection.InternalValues)
116  {
117  compilerParameters.SetObject(parameter.Key, parameter.Value.Object);
118  }
119  }
120  }
121 
122  foreach (var parameter in GraphicsDevice.Parameters.InternalValues)
123  {
124  compilerParameters.SetObject(parameter.Key, parameter.Value.Object);
125  }
126 
127  // Compile shader
128  // possible exception in LoadEffect
129  var effect = EffectSystem.LoadEffect(EffectName, compilerParameters);
130 
131  if (!ReferenceEquals(effect, effectInstance.Effect))
132  {
133  // Copy back parameters set on previous effect to new effect
134  if (effectInstance.Effect != null)
135  {
136  foreach (var parameter in effectInstance.Effect.Parameters.InternalValues)
137  {
138  effect.Parameters.SetObject(parameter.Key, parameter.Value.Object);
139  }
140  }
141 
142  effectInstance.Effect = effect;
143  effectInstance.UpdaterDefinition = new EffectParameterUpdaterDefinition(effect);
144  }
145  else
146  {
147  // Same effect than previous one
148 
149  effectInstance.UpdaterDefinition.UpdateCounter(effect.CompilationParameters);
150  }
151 
152  UpdateLevels(effectInstance);
153  updater.UpdateCounters(effectInstance.UpdaterDefinition);
154  }
155 
156  private void UpdateLevels(DynamicEffectInstance effectInstance)
157  {
158  PrepareUpdater(effectInstance);
159  updater.ComputeLevels(effectInstance.UpdaterDefinition);
160  }
161 
162  /// <summary>
163  /// Prepare the EffectParameterUpdater for the effect instance.
164  /// </summary>
165  /// <param name="effectInstance">The effect instance.</param>
166  private void PrepareUpdater(DynamicEffectInstance effectInstance)
167  {
168  parameterCollections.Clear(true);
169  parameterCollections.Add(effectInstance.Effect.DefaultCompilationParameters);
170  effectInstance.FillParameterCollections(parameterCollections);
171  parameterCollections.Add(GraphicsDevice.Parameters);
172 
173  updater.Update(effectInstance.UpdaterDefinition, parameterCollections.Items, parameterCollections.Count);
174  }
175  }
176 }
A dynamic effect instance updated by DynamicEffectCompiler.
Service providing method to access GraphicsDevice life-cycle.
DynamicEffectCompiler(IServiceRegistry services, string effectName)
Initializes a new instance of the DynamicEffectCompiler class.
A service registry is a IServiceProvider that provides methods to register and unregister services...
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.
Provides a dynamic compiler for an effect based on parameters changed.
bool Changed
Gets a boolean indicating if the effect changed since last update.
Definition: Effect.cs:105
Effect Effect
Gets the effect currently being compiled.
bool Update(DynamicEffectInstance effectInstance)
Update a dynamic effect instance based on its parameters.
ParameterCollection Parameters
Gets the parameters attached to this particular device. This Parameters are used to override Effect p...