Exemple #1
0
        //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);
        }
Exemple #2
0
        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;
            }
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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);
        }