//compresses a vector4 array down by removing the zero elements on the start/end (which is often A LOT) private CodeExpression InitaliseConstants(int count, Vector4[] values, CompileDirectives directives, out int offset) { offset = 0; if (count > values.Length) { count = values.Length; } if (values == null) { return(null); } int maxNonZero = -1; int minNonZero = int.MaxValue; for (int i = 0; i < count; i++) { if (values[i] != Vector4.Zero) { maxNonZero = Math.Max(maxNonZero, i); minNonZero = Math.Min(minNonZero, i); } } if (maxNonZero >= minNonZero) { //sub array float[] array = new float[Math.Min(values.Length, maxNonZero - minNonZero + 1) * 4]; for (int i = minNonZero; i <= maxNonZero; i++) { array[(i - minNonZero) * 4 + 0] = values[i].X; array[(i - minNonZero) * 4 + 1] = values[i].Y; array[(i - minNonZero) * 4 + 2] = values[i].Z; array[(i - minNonZero) * 4 + 3] = values[i].W; } for (int i = 0; i < array.Length; i++) { //remove any NaN values if (float.IsNaN(array[i])) { array[i] = 0; } } offset = minNonZero; return(ShaderBytes.ToArray(array, directives)); } return(null); }
public void GeneratePool(CodeTypeDeclarationCollection typeList, CompileDirectives compileDirectives) { Guid nameExt = Guid.NewGuid(); string name = "pool" + nameExt.ToString("N").ToUpper(); CodeTypeDeclaration type = new CodeTypeDeclaration(name); type.IsClass = true; type.TypeAttributes = System.Reflection.TypeAttributes.Class | System.Reflection.TypeAttributes.Sealed; CodeExpression typeRef = new CodeTypeReferenceExpression(name); typeList.Add(type); int index = 0; //add all the pools to the type. foreach (KeyValuePair <ByteArray, CodeFieldReferenceExpression> item in this.pool) { //create the static member string itemName = "item" + index++; //decompressed in code CodeMethodReferenceExpression decompressMethod = new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(typeof(ConstantArray.ArrayUtils)), "SimpleDecompress"); CodeExpression dataCode = ShaderBytes.ToArray(item.Key.Array, compileDirectives); CodeMemberField field = new CodeMemberField(typeof(byte[]), itemName); field.Attributes = MemberAttributes.Static | MemberAttributes.Public | MemberAttributes.Final; //assign it inline field.InitExpression = new CodeMethodInvokeExpression(decompressMethod, dataCode); type.Members.Add(field); item.Value.FieldName = itemName; item.Value.TargetObject = typeRef; } }
private void CreateShaderConstantHashMethod() { //create the GetShaderConstantHash() method //protected abstract int[] GetShaderConstantHash(bool ps); //this method is only used during shader merging (for validation). CodeMemberMethod hash = new CodeMemberMethod(); hash.Name = "GetShaderConstantHash"; hash.Attributes = MemberAttributes.Family | MemberAttributes.Override; hash.Parameters.Add(new CodeParameterDeclarationExpression(typeof(bool), "ps")); hash.ReturnType = new CodeTypeReference(typeof(int[])); Comment(hash, "Gets an array containing approximate hash codes for the constants used by this shader (Used for validation when merging two shaders)"); classDom.Members.Add(hash); int[] vsHashSet = this.source.GetAsmTechnique(this.techniqueName, this.platform).VertexShader.RegisterSet.GetHashSet(); int[] psHashSet = this.source.GetAsmTechnique(this.techniqueName, this.platform).PixelShader.RegisterSet.GetHashSet(); //the input 'ps' selects the set. CodeStatement valueOut = new CodeConditionStatement(new CodeArgumentReferenceExpression("ps"), new CodeStatement[] { new CodeMethodReturnStatement(ShaderBytes.ToArray(psHashSet, this.directives)) }, //true, PS new CodeStatement[] { new CodeMethodReturnStatement(ShaderBytes.ToArray(vsHashSet, this.directives)) } //false, VS ); hash.Statements.Add(valueOut); }
private void CreateVertexInputMethods() { AsmListing asmVS = this.source.GetAsmTechnique(this.techniqueName, this.platform).VertexShader; //create the GetVertexInputCount() and GetVertexInput() methods CodeMemberMethod count = new CodeMemberMethod(); count.Name = "GetVertexInputCount"; count.Attributes = MemberAttributes.Family | MemberAttributes.Override; count.ReturnType = new CodeTypeReference(typeof(int)); Comment(count, "Returns the number of vertex inputs used by this shader"); count.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(asmVS.InputCount))); classDom.Members.Add(count); //inputs are stored in a static array //create it... int[] arrayValues = new int[asmVS.InputCount * 2]; for (int i = 0; i < asmVS.InputCount; i++) { arrayValues[i] = (int)asmVS.GetInput(i).Usage; arrayValues[i + asmVS.InputCount] = (int)asmVS.GetInput(i).Index; } this.vsInputField = new CodeMemberField(typeof(int[]), "vin"); this.vsInputField.Attributes = MemberAttributes.Private | MemberAttributes.Static | MemberAttributes.Final; this.vsInputField.InitExpression = ShaderBytes.ToArray(arrayValues, this.directives); CodeFieldReferenceExpression vsInputRef = new CodeFieldReferenceExpression(ShaderClassEx, vsInputField.Name); //protected internal abstract void GetVertexInput(int index, out VertexElementUsage elementUsage, out int elementIndex); CodeMemberMethod getInput = new CodeMemberMethod(); getInput.Name = "GetVertexInput"; getInput.Attributes = MemberAttributes.Family | MemberAttributes.Override; CodeParameterDeclarationExpression indexParam = new CodeParameterDeclarationExpression(typeof(int), "i"); getInput.Parameters.Add(indexParam); CodeParameterDeclarationExpression param = new CodeParameterDeclarationExpression(typeof(VertexElementUsage), "usage"); param.Direction = FieldDirection.Out; getInput.Parameters.Add(param); param = new CodeParameterDeclarationExpression(typeof(int), "index"); param.Direction = FieldDirection.Out; getInput.Parameters.Add(param); CodeArgumentReferenceExpression indexRef = new CodeArgumentReferenceExpression(indexParam.Name); //the element index is stored at 'i + asmVS.InputCount' CodeExpression indexArray = new CodeArrayIndexerExpression(vsInputRef, new CodeBinaryOperatorExpression(indexRef, CodeBinaryOperatorType.Add, new CodePrimitiveExpression(asmVS.InputCount))); //and the usage must be cast CodeExpression usageCast = new CodeCastExpression(typeof(VertexElementUsage), new CodeArrayIndexerExpression(vsInputRef, indexRef)); getInput.Statements.Add(new CodeAssignStatement(new CodeArgumentReferenceExpression("usage"), usageCast)); getInput.Statements.Add(new CodeAssignStatement(new CodeArgumentReferenceExpression("index"), indexArray)); Comment(getInput, "Returns a vertex input used by this shader"); classDom.Members.Add(getInput); }