/MonoGame.Framework/Graphics/Effect/EffectParameter.cs

https://bitbucket.org/refuzion/monogame · C# · 608 lines · 470 code · 113 blank · 25 comment · 128 complexity · 7610c9bee92415901f7ee83e5bc039df MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Diagnostics;
  6. namespace Microsoft.Xna.Framework.Graphics
  7. {
  8. [DebuggerDisplay("{ParameterClass} {ParameterType} {Name} : {Semantic}")]
  9. public class EffectParameter
  10. {
  11. /// <summary>
  12. /// The next state key used when an effect parameter
  13. /// is updated by any of the 'set' methods.
  14. /// </summary>
  15. internal static ulong NextStateKey { get; private set; }
  16. internal EffectParameter( EffectParameterClass class_,
  17. EffectParameterType type,
  18. string name,
  19. int rowCount,
  20. int columnCount,
  21. string semantic,
  22. EffectAnnotationCollection annotations,
  23. EffectParameterCollection elements,
  24. EffectParameterCollection structMembers,
  25. object data )
  26. {
  27. ParameterClass = class_;
  28. ParameterType = type;
  29. Name = name;
  30. Semantic = semantic;
  31. Annotations = annotations;
  32. RowCount = rowCount;
  33. ColumnCount = columnCount;
  34. Elements = elements;
  35. StructureMembers = structMembers;
  36. Data = data;
  37. StateKey = unchecked(NextStateKey++);
  38. }
  39. internal EffectParameter(EffectParameter cloneSource)
  40. {
  41. // Share all the immutable types.
  42. ParameterClass = cloneSource.ParameterClass;
  43. ParameterType = cloneSource.ParameterType;
  44. Name = cloneSource.Name;
  45. Semantic = cloneSource.Semantic;
  46. Annotations = cloneSource.Annotations;
  47. RowCount = cloneSource.RowCount;
  48. ColumnCount = cloneSource.ColumnCount;
  49. // Clone the mutable types.
  50. Elements = cloneSource.Elements.Clone();
  51. StructureMembers = cloneSource.StructureMembers.Clone();
  52. // The data is mutable, so we have to clone it.
  53. var array = cloneSource.Data as Array;
  54. if (array != null)
  55. Data = array.Clone();
  56. StateKey = unchecked(NextStateKey++);
  57. }
  58. public string Name { get; private set; }
  59. public string Semantic { get; private set; }
  60. public EffectParameterClass ParameterClass { get; private set; }
  61. public EffectParameterType ParameterType { get; private set; }
  62. public int RowCount { get; private set; }
  63. public int ColumnCount { get; private set; }
  64. public EffectParameterCollection Elements { get; private set; }
  65. public EffectParameterCollection StructureMembers { get; private set; }
  66. public EffectAnnotationCollection Annotations { get; private set; }
  67. // TODO: Using object adds alot of boxing/unboxing overhead
  68. // and garbage generation. We should consider a templated
  69. // type implementation to fix this!
  70. internal object Data { get; private set; }
  71. /// <summary>
  72. /// The current state key which is used to detect
  73. /// if the parameter value has been changed.
  74. /// </summary>
  75. internal ulong StateKey { get; private set; }
  76. public bool GetValueBoolean ()
  77. {
  78. if (ParameterClass != EffectParameterClass.Scalar || ParameterType != EffectParameterType.Bool)
  79. throw new InvalidCastException();
  80. #if DIRECTX
  81. return ((int[])Data)[0] != 0;
  82. #else
  83. // MojoShader encodes even booleans into a float.
  84. return ((float[])Data)[0] != 0.0f;
  85. #endif
  86. }
  87. public bool[] GetValueBooleanArray ()
  88. {
  89. throw new NotImplementedException();
  90. }
  91. public int GetValueInt32 ()
  92. {
  93. if (ParameterClass != EffectParameterClass.Scalar || ParameterType != EffectParameterType.Int32)
  94. throw new InvalidCastException();
  95. #if DIRECTX
  96. return ((int[])Data)[0];
  97. #else
  98. // MojoShader encodes integers into a float.
  99. return (int)((float[])Data)[0];
  100. #endif
  101. }
  102. public int[] GetValueInt32Array ()
  103. {
  104. throw new NotImplementedException();
  105. }
  106. public Matrix GetValueMatrix ()
  107. {
  108. if (ParameterClass != EffectParameterClass.Matrix || ParameterType != EffectParameterType.Single)
  109. throw new InvalidCastException();
  110. if (RowCount != 4 || ColumnCount != 4)
  111. throw new InvalidCastException();
  112. var floatData = (float[])Data;
  113. return new Matrix( floatData[0], floatData[4], floatData[8], floatData[12],
  114. floatData[1], floatData[5], floatData[9], floatData[13],
  115. floatData[2], floatData[6], floatData[10], floatData[14],
  116. floatData[3], floatData[7], floatData[11], floatData[15]);
  117. }
  118. public Matrix[] GetValueMatrixArray (int count)
  119. {
  120. throw new NotImplementedException();
  121. }
  122. public Quaternion GetValueQuaternion ()
  123. {
  124. throw new NotImplementedException();
  125. }
  126. public Quaternion[] GetValueQuaternionArray ()
  127. {
  128. throw new NotImplementedException();
  129. }
  130. public Single GetValueSingle ()
  131. {
  132. // TODO: Should this fetch int and bool as a float?
  133. if (ParameterClass != EffectParameterClass.Scalar || ParameterType != EffectParameterType.Single)
  134. throw new InvalidCastException();
  135. return ((float[])Data)[0];
  136. }
  137. public Single[] GetValueSingleArray ()
  138. {
  139. if (Elements != null && Elements.Count > 0)
  140. {
  141. var ret = new Single[RowCount * ColumnCount * Elements.Count];
  142. for (int i=0; i<Elements.Count; i++)
  143. {
  144. var elmArray = Elements[i].GetValueSingleArray();
  145. for (var j = 0; j < elmArray.Length; j++)
  146. ret[RowCount*ColumnCount*i+j] = elmArray[j];
  147. }
  148. return ret;
  149. }
  150. switch(ParameterClass)
  151. {
  152. case EffectParameterClass.Scalar:
  153. return new Single[] { GetValueSingle () };
  154. case EffectParameterClass.Vector:
  155. case EffectParameterClass.Matrix:
  156. if (Data is Matrix)
  157. return Matrix.ToFloatArray((Matrix)Data);
  158. else
  159. return (float[])Data;
  160. default:
  161. throw new NotImplementedException();
  162. }
  163. }
  164. public string GetValueString ()
  165. {
  166. if (ParameterClass != EffectParameterClass.Object || ParameterType != EffectParameterType.String)
  167. throw new InvalidCastException();
  168. return ((string[])Data)[0];
  169. }
  170. public Texture2D GetValueTexture2D ()
  171. {
  172. if (ParameterClass != EffectParameterClass.Object || ParameterType != EffectParameterType.Texture2D)
  173. throw new InvalidCastException();
  174. return (Texture2D)Data;
  175. }
  176. #if !GLES
  177. public Texture3D GetValueTexture3D ()
  178. {
  179. if (ParameterClass != EffectParameterClass.Object || ParameterType != EffectParameterType.Texture3D)
  180. throw new InvalidCastException();
  181. return (Texture3D)Data;
  182. }
  183. #endif
  184. public TextureCube GetValueTextureCube ()
  185. {
  186. throw new NotImplementedException();
  187. }
  188. public Vector2 GetValueVector2 ()
  189. {
  190. if (ParameterClass != EffectParameterClass.Vector || ParameterType != EffectParameterType.Single)
  191. throw new InvalidCastException();
  192. var vecInfo = (float[])Data;
  193. return new Vector2(vecInfo[0],vecInfo[1]);
  194. }
  195. public Vector2[] GetValueVector2Array ()
  196. {
  197. throw new NotImplementedException();
  198. }
  199. public Vector3 GetValueVector3 ()
  200. {
  201. if (ParameterClass != EffectParameterClass.Vector || ParameterType != EffectParameterType.Single)
  202. throw new InvalidCastException();
  203. var vecInfo = (float[])Data;
  204. return new Vector3(vecInfo[0],vecInfo[1],vecInfo[2]);
  205. }
  206. public Vector3[] GetValueVector3Array ()
  207. {
  208. throw new NotImplementedException();
  209. }
  210. public Vector4 GetValueVector4 ()
  211. {
  212. if (ParameterClass != EffectParameterClass.Vector || ParameterType != EffectParameterType.Single)
  213. throw new InvalidCastException();
  214. var vecInfo = (float[])Data;
  215. return new Vector4(vecInfo[0],vecInfo[1],vecInfo[2],vecInfo[3]);
  216. }
  217. public Vector4[] GetValueVector4Array ()
  218. {
  219. throw new NotImplementedException();
  220. }
  221. public void SetValue (bool value)
  222. {
  223. if (ParameterClass != EffectParameterClass.Scalar || ParameterType != EffectParameterType.Bool)
  224. throw new InvalidCastException();
  225. #if DIRECTX
  226. // We store the bool as an integer as that
  227. // is what the constant buffers expect.
  228. ((int[])Data)[0] = value ? 1 : 0;
  229. #else
  230. // MojoShader encodes even booleans into a float.
  231. ((float[])Data)[0] = value ? 1 : 0;
  232. #endif
  233. StateKey = unchecked(NextStateKey++);
  234. }
  235. public void SetValue (bool[] value)
  236. {
  237. throw new NotImplementedException();
  238. }
  239. public void SetValue (int value)
  240. {
  241. if (ParameterClass != EffectParameterClass.Scalar || ParameterType != EffectParameterType.Int32)
  242. throw new InvalidCastException();
  243. #if DIRECTX
  244. ((int[])Data)[0] = value;
  245. #else
  246. // MojoShader encodes integers into a float.
  247. ((float[])Data)[0] = value;
  248. #endif
  249. StateKey = unchecked(NextStateKey++);
  250. }
  251. public void SetValue (int[] value)
  252. {
  253. throw new NotImplementedException();
  254. }
  255. public void SetValue(Matrix value)
  256. {
  257. // HLSL expects matrices to be transposed by default.
  258. // These unrolled loops do the transpose during assignment.
  259. if (RowCount == 4 && ColumnCount == 4)
  260. {
  261. var fData = (float[])Data;
  262. fData[0] = value.M11;
  263. fData[1] = value.M21;
  264. fData[2] = value.M31;
  265. fData[3] = value.M41;
  266. fData[4] = value.M12;
  267. fData[5] = value.M22;
  268. fData[6] = value.M32;
  269. fData[7] = value.M42;
  270. fData[8] = value.M13;
  271. fData[9] = value.M23;
  272. fData[10] = value.M33;
  273. fData[11] = value.M43;
  274. fData[12] = value.M14;
  275. fData[13] = value.M24;
  276. fData[14] = value.M34;
  277. fData[15] = value.M44;
  278. }
  279. else if (RowCount == 4 && ColumnCount == 3)
  280. {
  281. var fData = (float[])Data;
  282. fData[0] = value.M11;
  283. fData[1] = value.M21;
  284. fData[2] = value.M31;
  285. fData[3] = value.M41;
  286. fData[4] = value.M12;
  287. fData[5] = value.M22;
  288. fData[6] = value.M32;
  289. fData[7] = value.M42;
  290. fData[8] = value.M13;
  291. fData[9] = value.M23;
  292. fData[10] = value.M33;
  293. fData[11] = value.M43;
  294. }
  295. else if (RowCount == 3 && ColumnCount == 4)
  296. {
  297. var fData = (float[])Data;
  298. fData[0] = value.M11;
  299. fData[1] = value.M21;
  300. fData[2] = value.M31;
  301. fData[3] = value.M12;
  302. fData[4] = value.M22;
  303. fData[5] = value.M32;
  304. fData[6] = value.M13;
  305. fData[7] = value.M23;
  306. fData[8] = value.M33;
  307. fData[9] = value.M14;
  308. fData[10] = value.M24;
  309. fData[11] = value.M34;
  310. }
  311. else if (RowCount == 3 && ColumnCount == 3)
  312. {
  313. var fData = (float[])Data;
  314. fData[0] = value.M11;
  315. fData[1] = value.M21;
  316. fData[2] = value.M31;
  317. fData[3] = value.M12;
  318. fData[4] = value.M22;
  319. fData[5] = value.M32;
  320. fData[6] = value.M13;
  321. fData[7] = value.M23;
  322. fData[8] = value.M33;
  323. }
  324. StateKey = unchecked(NextStateKey++);
  325. }
  326. public void SetValueTranspose(Matrix value)
  327. {
  328. // HLSL expects matrices to be transposed by default, so copying them straight
  329. // from the in-memory version effectively transposes them back to row-major.
  330. if (RowCount == 4 && ColumnCount == 4)
  331. {
  332. var fData = (float[])Data;
  333. fData[0] = value.M11;
  334. fData[1] = value.M12;
  335. fData[2] = value.M13;
  336. fData[3] = value.M14;
  337. fData[4] = value.M21;
  338. fData[5] = value.M22;
  339. fData[6] = value.M23;
  340. fData[7] = value.M24;
  341. fData[8] = value.M31;
  342. fData[9] = value.M32;
  343. fData[10] = value.M33;
  344. fData[11] = value.M34;
  345. fData[12] = value.M41;
  346. fData[13] = value.M42;
  347. fData[14] = value.M43;
  348. fData[15] = value.M44;
  349. }
  350. else if (RowCount == 4 && ColumnCount == 3)
  351. {
  352. var fData = (float[])Data;
  353. fData[0] = value.M11;
  354. fData[1] = value.M12;
  355. fData[2] = value.M13;
  356. fData[3] = value.M21;
  357. fData[4] = value.M22;
  358. fData[5] = value.M23;
  359. fData[6] = value.M31;
  360. fData[7] = value.M32;
  361. fData[8] = value.M33;
  362. fData[9] = value.M41;
  363. fData[10] = value.M42;
  364. fData[11] = value.M43;
  365. }
  366. else if (RowCount == 3 && ColumnCount == 4)
  367. {
  368. var fData = (float[])Data;
  369. fData[0] = value.M11;
  370. fData[1] = value.M12;
  371. fData[2] = value.M13;
  372. fData[3] = value.M14;
  373. fData[4] = value.M21;
  374. fData[5] = value.M22;
  375. fData[6] = value.M23;
  376. fData[7] = value.M24;
  377. fData[8] = value.M31;
  378. fData[9] = value.M32;
  379. fData[10] = value.M33;
  380. fData[11] = value.M34;
  381. }
  382. else if (RowCount == 3 && ColumnCount == 3)
  383. {
  384. var fData = (float[])Data;
  385. fData[0] = value.M11;
  386. fData[1] = value.M12;
  387. fData[2] = value.M13;
  388. fData[3] = value.M21;
  389. fData[4] = value.M22;
  390. fData[5] = value.M23;
  391. fData[6] = value.M31;
  392. fData[7] = value.M32;
  393. fData[8] = value.M33;
  394. }
  395. StateKey = unchecked(NextStateKey++);
  396. }
  397. public void SetValue (Matrix[] value)
  398. {
  399. for (var i = 0; i < value.Length; i++)
  400. Elements[i].SetValue (value[i]);
  401. StateKey = unchecked(NextStateKey++);
  402. }
  403. public void SetValue (Quaternion value)
  404. {
  405. throw new NotImplementedException();
  406. }
  407. public void SetValue (Quaternion[] value)
  408. {
  409. throw new NotImplementedException();
  410. }
  411. public void SetValue (Single value)
  412. {
  413. if (ParameterType != EffectParameterType.Single)
  414. throw new InvalidCastException();
  415. #if PSM
  416. if(Data == null) {
  417. return;
  418. }
  419. #endif
  420. ((float[])Data)[0] = value;
  421. StateKey = unchecked(NextStateKey++);
  422. }
  423. public void SetValue (Single[] value)
  424. {
  425. for (var i=0; i<value.Length; i++)
  426. Elements[i].SetValue (value[i]);
  427. StateKey = unchecked(NextStateKey++);
  428. }
  429. public void SetValue (string value)
  430. {
  431. throw new NotImplementedException();
  432. }
  433. public void SetValue (Texture value)
  434. {
  435. if (this.ParameterType != EffectParameterType.Texture &&
  436. this.ParameterType != EffectParameterType.Texture1D &&
  437. this.ParameterType != EffectParameterType.Texture2D &&
  438. this.ParameterType != EffectParameterType.Texture3D &&
  439. this.ParameterType != EffectParameterType.TextureCube)
  440. {
  441. throw new InvalidCastException();
  442. }
  443. Data = value;
  444. StateKey = unchecked(NextStateKey++);
  445. }
  446. public void SetValue (Vector2 value)
  447. {
  448. if (ParameterClass != EffectParameterClass.Vector || ParameterType != EffectParameterType.Single)
  449. throw new InvalidCastException();
  450. var fData = (float[])Data;
  451. fData[0] = value.X;
  452. fData[1] = value.Y;
  453. StateKey = unchecked(NextStateKey++);
  454. }
  455. public void SetValue (Vector2[] value)
  456. {
  457. for (var i = 0; i < value.Length; i++)
  458. Elements[i].SetValue (value[i]);
  459. StateKey = unchecked(NextStateKey++);
  460. }
  461. public void SetValue (Vector3 value)
  462. {
  463. if (ParameterClass != EffectParameterClass.Vector || ParameterType != EffectParameterType.Single)
  464. throw new InvalidCastException();
  465. var fData = (float[])Data;
  466. fData[0] = value.X;
  467. fData[1] = value.Y;
  468. fData[2] = value.Z;
  469. StateKey = unchecked(NextStateKey++);
  470. }
  471. public void SetValue (Vector3[] value)
  472. {
  473. for (var i = 0; i < value.Length; i++)
  474. Elements[i].SetValue (value[i]);
  475. StateKey = unchecked(NextStateKey++);
  476. }
  477. public void SetValue (Vector4 value)
  478. {
  479. if (ParameterClass != EffectParameterClass.Vector || ParameterType != EffectParameterType.Single)
  480. throw new InvalidCastException();
  481. var fData = (float[])Data;
  482. fData[0] = value.X;
  483. fData[1] = value.Y;
  484. fData[2] = value.Z;
  485. fData[3] = value.W;
  486. StateKey = unchecked(NextStateKey++);
  487. }
  488. public void SetValue (Vector4[] value)
  489. {
  490. for (var i = 0; i < value.Length; i++)
  491. Elements[i].SetValue (value[i]);
  492. StateKey = unchecked(NextStateKey++);
  493. }
  494. }
  495. }