/Core/Rendering/FXSourceCodeFunction.cs

https://github.com/framefield/tooll · C# · 181 lines · 153 code · 22 blank · 6 comment · 20 complexity · a5e388fe0de9312d3b08507e5b2f10eb MD5 · raw file

  1. // Copyright (c) 2016 Framefield. All rights reserved.
  2. // Released under the MIT license. (see LICENSE.txt)
  3. using System;
  4. using System.CodeDom.Compiler;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Text.RegularExpressions;
  9. using SharpDX;
  10. using SharpDX.D3DCompiler;
  11. using SharpDX.Direct3D11;
  12. namespace Framefield.Core.Rendering
  13. {
  14. public abstract class FXSourceCodeFunction : OperatorPart.Function, IFXSourceCode
  15. {
  16. public override void Dispose()
  17. {
  18. Utilities.DisposeObj(ref _effect);
  19. }
  20. public virtual string GetCode(int idx)
  21. {
  22. if (idx < OperatorPart.Connections.Count)
  23. {
  24. var context = new OperatorPartContext() { Time = 0.0f };
  25. return OperatorPart.Connections[idx].Eval(context).Text;
  26. }
  27. else
  28. return "";
  29. }
  30. public virtual void SetCode(int idx, string code)
  31. {
  32. if (idx < OperatorPart.Connections.Count)
  33. {
  34. var input = OperatorPartUtilities.FindLowestUnconnectedOpPart(OperatorPart.Connections[idx], 5);
  35. input.SetValue(new Text(code));
  36. var setValueAsDefaultCmd = new Commands.SetInputAsAndResetToDefaultCommand(input);
  37. setValueAsDefaultCmd.Do();
  38. }
  39. }
  40. public virtual int NumCodes()
  41. {
  42. return 1;
  43. }
  44. public virtual CompilerErrorCollection Compile(int codeIdx)
  45. {
  46. Utilities.DisposeObj(ref _effect);
  47. var errors = new CompilerErrorCollection();
  48. try
  49. {
  50. using (var compilationResult = ShaderBytecode.Compile(GetCode(codeIdx), "fx_5_0", ShaderFlags.OptimizationLevel3, EffectFlags.None, null, null))
  51. {
  52. _effect = new Effect(D3DDevice.Device, compilationResult);
  53. if (compilationResult.Message != null)
  54. {
  55. Logger.Warn("HLSL compile warning in '{0}':\n{1}", OperatorPart?.Name, compilationResult.Message);
  56. }
  57. }
  58. }
  59. catch (SharpDX.CompilationException ex)
  60. {
  61. errors = ErrorsFromString(ex.Message);
  62. Logger.Error("FX compile error:\n{0}", ex.Message);
  63. }
  64. return errors;
  65. }
  66. /* convert shader-errors that come in the format of:
  67. * c:\self.demos\tooll2\n\a(58,12): error X3004: undeclared identifier 'col2'
  68. * c:\self.demos\tooll2\n\a(58,5): error X3080: 'PS': function must return a value
  69. **/
  70. protected CompilerErrorCollection ErrorsFromString(string errorString)
  71. {
  72. var errors = new CompilerErrorCollection();
  73. var errorLinePattern = new Regex(@"\((\d+),(\d+)\): error\s*(\w+):\s*(.*?)\s*$");
  74. foreach (var line in errorString.Split('\n'))
  75. {
  76. var matches = errorLinePattern.Matches(line);
  77. if (matches.Count == 1)
  78. {
  79. var lineNumber = int.Parse(matches[0].Groups[1].Value);
  80. var column = int.Parse(matches[0].Groups[2].Value);
  81. string errorCode = matches[0].Groups[3].Value;
  82. string errorMessage = matches[0].Groups[4].Value;
  83. errors.Add(new CompilerError() { Column = column, ErrorNumber = errorCode, Line = lineNumber, ErrorText = errorMessage });
  84. }
  85. }
  86. return errors;
  87. }
  88. protected EffectVariable GetVariableByName(String variableName)
  89. {
  90. var x = _effect.GetVariableByName(variableName);
  91. if (x == null)
  92. {
  93. Logger.Error(this, "EffectVariable {0} not found", variableName);
  94. }
  95. return x;
  96. }
  97. protected void SetScalar(String variableName, float value)
  98. {
  99. var variable = _effect.GetVariableByName(variableName);
  100. if (variable == null)
  101. {
  102. Logger.Error(this, "Can't set undefined ShaderEffectVariable '{0}' to {1}", variableName, value);
  103. return;
  104. }
  105. var scalarVariable = variable.AsScalar();
  106. if (scalarVariable == null)
  107. {
  108. Logger.Error(this, "Can't set ShaderEffectVariable '{0}' to scalar {1}", variableName, value);
  109. return;
  110. }
  111. scalarVariable.Set(value);
  112. }
  113. protected void SetVector<T>(string variableName, T value) where T : struct
  114. {
  115. var variable = _effect.GetVariableByName(variableName);
  116. if (variable == null)
  117. {
  118. Logger.Error(this, "Can't set undefined ShaderEffectVariable '{0}' to {1}", variableName, value);
  119. return;
  120. }
  121. var vector = variable.AsVector();
  122. if (vector == null)
  123. {
  124. Logger.Error(this, "Can't set ShaderEffectVariable '{0}' to Vector4 {1}", variableName, value);
  125. return;
  126. }
  127. vector.Set(value);
  128. }
  129. protected void SetColor(string variableName, Color4 color)
  130. {
  131. SetVector(variableName, color);
  132. }
  133. protected void SetVector2(string variableName, Vector2 value)
  134. {
  135. SetVector(variableName, value);
  136. }
  137. protected void SetVector4(string variableName, Vector4 value)
  138. {
  139. SetVector(variableName, value);
  140. }
  141. protected void SetMatrix(String variableName, Matrix matrixValue)
  142. {
  143. var variable = _effect.GetVariableByName(variableName);
  144. if (variable == null)
  145. {
  146. Logger.Error(this, "Can't set undefined ShaderEffectVariable '{0}' to Matrix {1}", variableName, matrixValue);
  147. return;
  148. }
  149. var matrixVariable = variable.AsMatrix();
  150. if (matrixVariable == null)
  151. {
  152. Logger.Error(this, "Can't set ShaderEffectVariable '{0}' to Matrix {1}", variableName, matrixValue);
  153. return;
  154. }
  155. matrixVariable.SetMatrix(matrixValue);
  156. }
  157. protected Effect _effect = null;
  158. }
  159. }