Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
EffectProgram.Direct3D.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_DIRECT3D
4 using System.Collections.Generic;
5 using SharpDX.Direct3D11;
6 using SiliconStudio.Core;
7 using SiliconStudio.Paradox.Shaders;
8 
9 namespace SiliconStudio.Paradox.Graphics
10 {
11  internal partial class EffectProgram
12  {
13  private readonly EffectBytecode effectBytecode;
14  private VertexShader vertexShader;
15  private GeometryShader geometryShader;
16  private PixelShader pixelShader;
17  private HullShader hullShader;
18  private DomainShader domainShader;
19  private ComputeShader computeShader;
20  private EffectInputSignature inputSignature;
21 
22  private EffectProgram(GraphicsDevice device, EffectBytecode bytecode)
23  : base(device)
24  {
25  effectBytecode = bytecode;
26  CreateShaders();
27  }
28 
29  public EffectInputSignature InputSignature
30  {
31  get
32  {
33  return inputSignature;
34  }
35  }
36 
37  private void CreateShaders()
38  {
39  foreach (var shaderBytecode in effectBytecode.Stages)
40  {
41  var bytecodeRaw = shaderBytecode.Data;
42  var reflection = effectBytecode.Reflection;
43 
44  // TODO CACHE Shaders with a bytecode hash
45  switch (shaderBytecode.Stage)
46  {
47  case ShaderStage.Vertex:
48  vertexShader = new VertexShader(GraphicsDevice.NativeDevice, bytecodeRaw);
49  // Note: input signature can be reused when reseting device since it only stores non-GPU data,
50  // so just keep it if it has already been created before.
51  if (inputSignature == null)
52  inputSignature = EffectInputSignature.GetOrCreateLayout(new EffectInputSignature(shaderBytecode.Id, bytecodeRaw));
53  break;
54  case ShaderStage.Domain:
55  domainShader = new DomainShader(GraphicsDevice.NativeDevice, bytecodeRaw);
56  break;
57  case ShaderStage.Hull:
58  hullShader = new HullShader(GraphicsDevice.NativeDevice, bytecodeRaw);
59  break;
60  case ShaderStage.Geometry:
61  if (reflection.ShaderStreamOutputDeclarations != null && reflection.ShaderStreamOutputDeclarations.Count > 0)
62  {
63  // Calculate the strides
64  var soStrides = new List<int>();
65  foreach (var streamOutputElement in reflection.ShaderStreamOutputDeclarations)
66  {
67  for (int i = soStrides.Count; i < (streamOutputElement.Stream + 1); i++)
68  {
69  soStrides.Add(0);
70  }
71 
72  soStrides[streamOutputElement.Stream] += streamOutputElement.ComponentCount * sizeof(float);
73  }
74  var soElements = new StreamOutputElement[0]; // TODO CREATE StreamOutputElement from bytecode.Reflection.ShaderStreamOutputDeclarations
75  geometryShader = new GeometryShader(GraphicsDevice.NativeDevice, bytecodeRaw, soElements, soStrides.ToArray(), reflection.StreamOutputRasterizedStream);
76  }
77  else
78  {
79  geometryShader = new GeometryShader(GraphicsDevice.NativeDevice, bytecodeRaw);
80  }
81  break;
82  case ShaderStage.Pixel:
83  pixelShader = new PixelShader(GraphicsDevice.NativeDevice, bytecodeRaw);
84  break;
85  case ShaderStage.Compute:
86  computeShader = new ComputeShader(GraphicsDevice.NativeDevice, bytecodeRaw);
87  break;
88  }
89  }
90  }
91 
92  protected override void DestroyImpl()
93  {
94  Utilities.Dispose(ref pixelShader);
95  Utilities.Dispose(ref vertexShader);
96  Utilities.Dispose(ref geometryShader);
97  Utilities.Dispose(ref hullShader);
98  Utilities.Dispose(ref domainShader);
99  Utilities.Dispose(ref computeShader);
100  }
101 
102  /// <inheritdoc/>
103  protected internal override void OnDestroyed()
104  {
105  base.OnDestroyed();
106  DestroyImpl();
107  }
108 
109  /// <inheritdoc/>
110  protected internal override bool OnRecreate()
111  {
112  base.OnRecreate();
113  CreateShaders();
114  return true;
115  }
116 
117  internal void Apply(GraphicsDevice device)
118  {
119  // Not sure weither setting everything to NULL is important if no program is specified?
120  var nativeDeviceContext = device.NativeDeviceContext;
121  if (computeShader != null)
122  {
123  nativeDeviceContext.ComputeShader.Set(computeShader);
124  }
125  else
126  {
127  nativeDeviceContext.VertexShader.Set(vertexShader);
128  nativeDeviceContext.PixelShader.Set(pixelShader);
129  nativeDeviceContext.HullShader.Set(hullShader);
130  nativeDeviceContext.DomainShader.Set(domainShader);
131  nativeDeviceContext.GeometryShader.Set(geometryShader);
132  }
133  }
134  }
135 }
136 
137 #endif