コード例 #1
0
        public override void AddWarm(IShaderDom shader, Action <CodeStatement, string> add)
        {
            //dispose the shaders (if the exist)

            CodeBinaryOperatorExpression notNull = new CodeBinaryOperatorExpression(shader.VertexShaderRef, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression((VertexShader)null));

            //dipose
            CodeConditionStatement disposer = new CodeConditionStatement(notNull,
                                                                         shader.ETS(new CodeMethodInvokeExpression(shader.VertexShaderRef, "Dispose")));

            add(disposer, null);

            //ps
            notNull = new CodeBinaryOperatorExpression(shader.PixelShaderRef, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression((PixelShader)null));

            //dipose
            disposer = new CodeConditionStatement(notNull,
                                                  shader.ETS(new CodeMethodInvokeExpression(shader.PixelShaderRef, "Dispose")));
            add(disposer, null);


            //and then recreate them using the shader system

            //state.CreateShaders(out ShadowShader.vs, out ShadowShader.ps, ShadowShader.vsb, ShadowShader.psb, 23, 15, 3, 0);


            int vsInstructions = asmTechnique.VertexShader.GetCommandCount() - 1;
            int psInstructions = asmTechnique.PixelShader.GetCommandCount() - 1;

            int vsPreShaderInstructions = 0;
            int psPreShaderInstructions = 0;

            if (asmTechnique.VertexPreShader != null)
            {
                psPreShaderInstructions = asmTechnique.VertexPreShader.GetCommandCount() - 1;
            }
            if (asmTechnique.PixelPreShader != null)
            {
                psPreShaderInstructions = asmTechnique.PixelPreShader.GetCommandCount() - 1;
            }

            CodeExpression create = new CodeMethodInvokeExpression(shader.ShaderSystemRef, "CreateShaders",
                                                                   new CodeDirectionExpression(FieldDirection.Out, shader.VertexShaderRef),
                                                                   new CodeDirectionExpression(FieldDirection.Out, shader.PixelShaderRef),
                                                                   shader.VertexShaderBytesRef,
                                                                   shader.PixelShaderBytesRef,
                                                                   new CodePrimitiveExpression(vsInstructions),
                                                                   new CodePrimitiveExpression(psInstructions),
                                                                   new CodePrimitiveExpression(vsPreShaderInstructions),
                                                                   new CodePrimitiveExpression(psPreShaderInstructions));

            add(shader.ETS(create), "Create the shader instances");
        }
コード例 #2
0
        public override void AddWarm(IShaderDom shader, Action <CodeStatement, string> add)
        {
            //return from the method if the device index hasn't changed

            CodeStatement returnCondition =
                new CodeConditionStatement(
                    new CodeBinaryOperatorExpression(GraphicsDeviceUID, CodeBinaryOperatorType.IdentityEquality, new CodePropertyReferenceExpression(ShaderSystemRef, "DeviceUniqueIndex")),
                    new CodeMethodReturnStatement());

            add(returnCondition, "Shader is already warmed");

            //this doesn't happen for extended classes
            if (shader.SourceShader.GetShaderExtension(this.techniqueName) == null)
            {
                add(validateDeviceId, "Setup the shader");
            }
            else
            {
                //however the base class Warm method is called
                CodeExpression baseCall = new CodeMethodInvokeExpression(
                    new CodeBaseReferenceExpression(), "WarmShader", shader.ShaderSystemRef);

                add(shader.ETS(baseCall), null);

                //and assign the g uid
                CodeStatement assign = new CodeAssignStatement(
                    GraphicsDeviceUID, new CodePropertyReferenceExpression(ShaderSystemRef, "DeviceUniqueIndex"));

                add(assign, null);
            }
        }
コード例 #3
0
        public override void AddBind(IShaderDom shader, Action <CodeStatement, string> add)
        {
            //call the preshaders

            if (vertexPreShader != null)
            {
                CodeExpression call      = new CodeMethodInvokeExpression(shader.Instance, "vspre");
                CodeExpression condition = new CodeBinaryOperatorExpression(new CodeFieldReferenceExpression(shader.VertexPreShaderRegistersRef, "change"), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(true));
                CodeStatement  invoke    = new CodeConditionStatement(condition, shader.ETS(call));

                add(invoke, "run the vertex preshader");
            }

            //pixel
            if (pixelPreShader != null)
            {
                CodeExpression call      = new CodeMethodInvokeExpression(shader.Instance, "pspre");
                CodeExpression condition = new CodeBinaryOperatorExpression(new CodeFieldReferenceExpression(shader.PixelPreShaderRegistersRef, "change"), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(true));
                CodeStatement  invoke    = new CodeConditionStatement(condition, shader.ETS(call));

                add(invoke, "run the pixel preshader");
            }
        }
コード例 #4
0
ファイル: Registers.cs プロジェクト: ARLM-Attic/xna-xen
        public override void AddBindEnd(IShaderDom shader, Action <CodeStatement, string> add)
        {
            //set the constants
            //eg:

            /*
             *
             * if (((this.vreg.change == true)
             || (ic == true)))
             ||{
             ||     state.SetShaderConstants(this.vreg.array, null);
             ||     this.vreg.change = false;
             ||}
             */

            CodeExpression vreg = new CodePrimitiveExpression(null);
            CodeExpression preg = vreg;

            CodeExpression setConstantsCondition = null;

            if (vsReg.FloatRegisterCount > 0)
            {
                //local variable storing the registers
                CodeVariableDeclarationStatement vregd = new CodeVariableDeclarationStatement(typeof(Vector4[]), "vc");
                vregd.InitExpression = vreg;
                vreg = new CodeVariableReferenceExpression(vregd.Name);
                add(vregd, "Vertex shader registers");

                //assign if changed
                CodeBinaryOperatorExpression assignCondition = new CodeBinaryOperatorExpression(
                    new CodeBinaryOperatorExpression(new CodeFieldReferenceExpression(shader.VertexShaderRegistersRef, "change"), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(true)),
                    CodeBinaryOperatorType.BooleanOr,
                    new CodeBinaryOperatorExpression(shader.BindShaderInstanceChange, CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(true)));

                //assign
                CodeConditionStatement assign = new CodeConditionStatement(assignCondition,
                                                                           new CodeAssignStatement(new CodeVariableReferenceExpression(vregd.Name), new CodeFieldReferenceExpression(shader.VertexShaderRegistersRef, "array")),
                                                                           new CodeAssignStatement(new CodeFieldReferenceExpression(shader.VertexShaderRegistersRef, "change"), new CodePrimitiveExpression(false)));

                add(assign, null);

                setConstantsCondition = new CodeBinaryOperatorExpression(vreg, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null));
            }

            //again for PS
            if (psReg.FloatRegisterCount > 0)
            {
                //local variable storing the registers
                CodeVariableDeclarationStatement pregd = new CodeVariableDeclarationStatement(typeof(Vector4[]), "pc");
                pregd.InitExpression = preg;
                preg = new CodeVariableReferenceExpression(pregd.Name);
                add(pregd, "Pixel shader registers");

                //assign if changed
                CodeBinaryOperatorExpression assignCondition = new CodeBinaryOperatorExpression(
                    new CodeBinaryOperatorExpression(new CodeFieldReferenceExpression(shader.PixelShaderRegistersRef, "change"), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(true)),
                    CodeBinaryOperatorType.BooleanOr,
                    new CodeBinaryOperatorExpression(shader.BindShaderInstanceChange, CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(true)));

                //assign
                CodeConditionStatement assign = new CodeConditionStatement(assignCondition,
                                                                           new CodeAssignStatement(new CodeVariableReferenceExpression(pregd.Name), new CodeFieldReferenceExpression(shader.PixelShaderRegistersRef, "array")),
                                                                           new CodeAssignStatement(new CodeFieldReferenceExpression(shader.PixelShaderRegistersRef, "change"), new CodePrimitiveExpression(false)));

                add(assign, null);

                CodeExpression condition = new CodeBinaryOperatorExpression(preg, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null));
                if (setConstantsCondition != null)
                {
                    setConstantsCondition = new CodeBinaryOperatorExpression(condition, CodeBinaryOperatorType.BooleanOr, setConstantsCondition);
                }
                else
                {
                    setConstantsCondition = condition;
                }
            }

            if (setConstantsCondition != null)
            {
                //set the shaders
                CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression(shader.ShaderSystemRef, "SetShaderConstants", vreg, preg);

                //invoke if the constants are not null.

                add(new CodeConditionStatement(setConstantsCondition, shader.ETS(invoke)), null);
            }


            setConstantsCondition = null;

            //set the boolean registers
            if (vsReg.BooleanRegisterCount > 0 ||
                psReg.BooleanRegisterCount > 0)
            {
                CodeExpression vsb = new CodePrimitiveExpression(null);
                CodeExpression psb = new CodePrimitiveExpression(null);

                if (vsReg.BooleanRegisterCount > 0)
                {
                    CodeVariableDeclarationStatement vs_var = new CodeVariableDeclarationStatement(typeof(bool[]), "vcb", new CodePrimitiveExpression(null));
                    add(vs_var, null);
                    vsb = new CodeVariableReferenceExpression(vs_var.Name);
                    CodeConditionStatement changed = new CodeConditionStatement(shader.VertexShaderBooleanRegistersChangedRef,
                                                                                new CodeAssignStatement(vsb, shader.VertexShaderBooleanRegistersRef),
                                                                                new CodeAssignStatement(shader.VertexShaderBooleanRegistersChangedRef, new CodePrimitiveExpression(false)));
                    add(changed, null);
                    setConstantsCondition = new CodeBinaryOperatorExpression(vsb, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null));
                }
                if (psReg.BooleanRegisterCount > 0)
                {
                    CodeVariableDeclarationStatement ps_var = new CodeVariableDeclarationStatement(typeof(bool[]), "pcb", new CodePrimitiveExpression(null));
                    add(ps_var, null);
                    psb = new CodeVariableReferenceExpression(ps_var.Name);
                    CodeConditionStatement changed = new CodeConditionStatement(shader.PixelShaderBooleanRegistersChangedRef,
                                                                                new CodeAssignStatement(psb, shader.PixelShaderBooleanRegistersRef),
                                                                                new CodeAssignStatement(shader.PixelShaderBooleanRegistersChangedRef, new CodePrimitiveExpression(false)));
                    add(changed, null);

                    CodeBinaryOperatorExpression condition = new CodeBinaryOperatorExpression(psb, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null));
                    if (setConstantsCondition == null)
                    {
                        setConstantsCondition = condition;
                    }
                    else
                    {
                        setConstantsCondition = new CodeBinaryOperatorExpression(setConstantsCondition, CodeBinaryOperatorType.BooleanOr, condition);
                    }
                }
                //invoke the call to set the constants
                //set the shaders
                CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression(shader.ShaderSystemRef, "SetShaderBooleanConstants", vsb, psb);

                add(new CodeConditionStatement(setConstantsCondition, shader.ETS(invoke)), null);
            }
        }
コード例 #5
0
ファイル: Registers.cs プロジェクト: ARLM-Attic/xna-xen
        public override void AddConstructor(IShaderDom shader, Action <CodeStatement> add)
        {
            //setup registers
            if (vsReg.FloatRegisterCount > 0)
            {
                //assign
                CodeExpression create = new CodeObjectCreateExpression(typeof(ConstantArray),
                                                                       new CodePrimitiveExpression(vsReg.FloatRegisterCount)); //create with the number of registers

                add(new CodeAssignStatement(shader.VertexShaderRegistersRef, create));

                //call the set method?
                int            offset;
                CodeExpression initArray = InitaliseConstants(vsReg.FloatRegisterCount, vsDefault, shader.CompileDirectives, out offset);

                if (initArray != null)
                {
                    //the array will be stored statically as a member, so not to leak.
                    string name = "vreg_def";
                    staticArrays.Add(name, initArray);

                    CodeMethodInvokeExpression setCall = new CodeMethodInvokeExpression(shader.VertexShaderRegistersRef, "Set",
                                                                                        new CodePrimitiveExpression(offset), new CodeFieldReferenceExpression(shader.ShaderClassEx, name)); // start from zero
                    add(shader.ETS(setCall));
                }
            }

            //and the PS

            if (psReg.FloatRegisterCount > 0)
            {
                //create the vertex registers
                CodeExpression create = new CodeObjectCreateExpression(typeof(ConstantArray),
                                                                       new CodePrimitiveExpression(psReg.FloatRegisterCount)); //create with the number of registers

                add(new CodeAssignStatement(shader.PixelShaderRegistersRef, create));

                //call the set method?
                int            offset;
                CodeExpression initArray = InitaliseConstants(psReg.FloatRegisterCount, psDefault, shader.CompileDirectives, out offset);

                if (initArray != null)
                {
                    //the array will be stored statically as a member, so not to leak.
                    string name = "preg_def";
                    staticArrays.Add(name, initArray);

                    CodeMethodInvokeExpression setCall = new CodeMethodInvokeExpression(shader.PixelShaderRegistersRef, "Set",
                                                                                        new CodePrimitiveExpression(offset), new CodeFieldReferenceExpression(shader.ShaderClassEx, name));
                    add(shader.ETS(setCall));
                }
            }


            //setup preshader registers
            if (vsPreReg != null && vsPreReg.FloatRegisterCount > 0)
            {
                CodeExpression create = new CodeObjectCreateExpression(typeof(ConstantArray),
                                                                       new CodePrimitiveExpression(vsPreReg.FloatRegisterCount)); //create with the number of registers
                add(new CodeAssignStatement(shader.VertexPreShaderRegistersRef, create));

                //call the set method?
                int            offset;
                CodeExpression initArray = GeneratePreShaderFloatDefaults(this.techniqueData, vsPreReg, vsPreReg.FloatRegisterCount, shader.CompileDirectives, out offset);

                if (initArray != null)
                {
                    string name = "vpreg_def";
                    staticArrays.Add(name, initArray);

                    CodeMethodInvokeExpression setCall = new CodeMethodInvokeExpression(shader.VertexPreShaderRegistersRef, "Set",
                                                                                        new CodePrimitiveExpression(offset), new CodeFieldReferenceExpression(shader.ShaderClassEx, name)); // start from zero
                    add(shader.ETS(setCall));
                }
            }
            //pixel preshader
            if (psPreReg != null && psPreReg.FloatRegisterCount > 0)
            {
                //assign
                CodeExpression create = new CodeObjectCreateExpression(typeof(ConstantArray),
                                                                       new CodePrimitiveExpression(psPreReg.FloatRegisterCount)); //create with the number of registers
                add(new CodeAssignStatement(shader.PixelPreShaderRegistersRef, create));

                //call the set method?
                int            offset;
                CodeExpression initArray = GeneratePreShaderFloatDefaults(this.techniqueData, psPreReg, psPreReg.FloatRegisterCount, shader.CompileDirectives, out offset);

                if (initArray != null)
                {
                    string name = "ppreg_def";
                    staticArrays.Add(name, initArray);

                    CodeMethodInvokeExpression setCall = new CodeMethodInvokeExpression(shader.PixelPreShaderRegistersRef, "Set",
                                                                                        new CodePrimitiveExpression(offset), new CodeFieldReferenceExpression(shader.ShaderClassEx, name)); // start from zero
                    add(shader.ETS(setCall));
                }
            }

            //boolean registers
            if (vsReg.BooleanRegisterCount > 0)
            {
                //assign
                CodeExpression create = new CodeArrayCreateExpression(typeof(bool),
                                                                      new CodePrimitiveExpression(vsReg.BooleanRegisterCount)); //create with the number of registers

                add(new CodeAssignStatement(shader.VertexShaderBooleanRegistersRef, create));
                add(new CodeAssignStatement(shader.VertexShaderBooleanRegistersChangedRef, new CodePrimitiveExpression(true)));

                //if any are default non-zero, assign them.
                if (vsBooleanDefault != null)
                {
                    for (int i = 0; i < this.vsBooleanDefault.Length && i < vsReg.BooleanRegisterCount; i++)
                    {
                        if (this.vsBooleanDefault[i])
                        {
                            add(new CodeAssignStatement(new CodeArrayIndexerExpression(shader.VertexShaderBooleanRegistersRef, new CodePrimitiveExpression(i)), new CodePrimitiveExpression(true)));
                        }
                    }
                }
            }
            //and the PS...
            if (psReg.BooleanRegisterCount > 0)
            {
                //assign
                CodeExpression create = new CodeArrayCreateExpression(typeof(bool),
                                                                      new CodePrimitiveExpression(psReg.BooleanRegisterCount)); //create with the number of registers

                add(new CodeAssignStatement(shader.PixelShaderBooleanRegistersRef, create));
                add(new CodeAssignStatement(shader.PixelShaderBooleanRegistersChangedRef, new CodePrimitiveExpression(true)));

                //if any are default non-zero, assign them.
                if (psBooleanDefault != null)
                {
                    for (int i = 0; i < this.psBooleanDefault.Length && i < psReg.BooleanRegisterCount; i++)
                    {
                        if (this.psBooleanDefault[i])
                        {
                            add(new CodeAssignStatement(new CodeArrayIndexerExpression(shader.PixelShaderBooleanRegistersRef, new CodePrimitiveExpression(i)), new CodePrimitiveExpression(true)));
                        }
                    }
                }
            }
        }
コード例 #6
0
        private void CreateConstantSetters(IShaderDom shader, Action <CodeTypeMember, string> add, string name, CodeExpression assignmentField, CodeExpression assignmentArrayField)
        {
            /*
             * Something like:
             *
             * public void SetInvTargetSize(ref Microsoft.Xna.Framework.Vector2 value)
             * {
             *      this.vreg.SetVector2(130, ref value);
             * }
             *
             * public Microsoft.Xna.Framework.Vector2 InvTargetSize
             * {
             *      set
             *      {
             *              this.SetInvTargetSize(ref value);
             *      }
             * }*/

            Register reg;
            Type     dataType;
            bool     hasSetMethod;
            int      stride;

            if (!ExtractRegType(name, out reg, out dataType, out hasSetMethod, out stride))
            {
                return;
            }

            Type arrayOrSingleType = dataType;

            //right...

            //create the method of the given type.


            //public void SetInvTargetSize(ref Microsoft.Xna.Framework.Vector2 value)
            CodeStatementCollection methodStatements = new CodeStatementCollection();

            CodeParameterDeclarationExpression param = new CodeParameterDeclarationExpression(dataType, "value");

            if (reg.ArraySize == -1)
            {
                param.Direction = FieldDirection.Ref;
            }
            else
            {
                arrayOrSingleType = dataType.MakeArrayType();
                param.Type        = new CodeTypeReference(arrayOrSingleType);
            }

            CodeExpression valueRef = new CodeArgumentReferenceExpression(param.Name);

            //when there isn't a set method, there is just a set property
            if (!hasSetMethod)
            {
                valueRef = new CodePropertySetValueReferenceExpression();
            }

            //create the guts
            //depends on what constants use it...

            //eg:
            //this.vreg.SetVector2(130, ref value);

            Register sreg;

            if (dataType == typeof(bool))
            {
                //special case for booleans, assign the array directly.
                //looks like:
                //
                // if (preg_bool[index] != value)
                // {
                //  preg_bool[index] = value;
                //  preg_bool_changed = true;
                // }

                foreach (KeyValuePair <AsmListing, CodeExpression> listing in listingRegisters)
                {
                    RegisterSet    registers    = listing.Key.RegisterSet;
                    CodeExpression registersRef = listing.Value;

                    if (registers.TryGetRegister(name, out sreg))
                    {
                        if (listing.Key == asm.PixelShader)
                        {
                            CodeExpression arrayIndex = new CodeArrayIndexerExpression(shader.PixelShaderBooleanRegistersRef, new CodePrimitiveExpression(sreg.Index));

                            CodeStatement assign = new CodeAssignStatement(arrayIndex, new CodePropertySetValueReferenceExpression());
                            CodeStatement change = new CodeAssignStatement(shader.PixelShaderBooleanRegistersChangedRef, new CodePrimitiveExpression(true));

                            CodeStatement condition = new CodeConditionStatement(
                                new CodeBinaryOperatorExpression(arrayIndex, CodeBinaryOperatorType.IdentityInequality, new CodePropertySetValueReferenceExpression()),
                                new CodeStatement[] { assign, change });

                            methodStatements.Add(condition);
                        }
                        if (listing.Key == asm.VertexShader)
                        {
                            CodeExpression arrayIndex = new CodeArrayIndexerExpression(shader.VertexShaderBooleanRegistersRef, new CodePrimitiveExpression(sreg.Index));

                            CodeStatement assign = new CodeAssignStatement(arrayIndex, new CodePropertySetValueReferenceExpression());
                            CodeStatement change = new CodeAssignStatement(shader.VertexShaderBooleanRegistersChangedRef, new CodePrimitiveExpression(true));

                            CodeStatement condition = new CodeConditionStatement(
                                new CodeBinaryOperatorExpression(arrayIndex, CodeBinaryOperatorType.IdentityInequality, new CodePropertySetValueReferenceExpression()),
                                new CodeStatement[] { assign, change });

                            methodStatements.Add(condition);
                        }
                    }
                }
            }
            else
            {
                string targetName = "Set" + dataType.Name;

                if (dataType == typeof(Matrix))
                {
                    targetName += stride;
                    targetName += "Transpose";
                }

                if (reg.ArraySize == -1)
                {
                    //not an array..

                    foreach (KeyValuePair <AsmListing, CodeExpression> listing in listingRegisters)
                    {
                        RegisterSet    registers    = listing.Key.RegisterSet;
                        CodeExpression registersRef = listing.Value;

                        if (registers.TryGetRegister(name, out sreg))
                        {
                            //set the regiser (eg, may be vertex shader register)
                            CodeExpression methodInvoke =
                                new CodeMethodInvokeExpression(registersRef, targetName,
                                                               new CodePrimitiveExpression(sreg.Index),
                                                               new CodeDirectionExpression(FieldDirection.Ref, valueRef));

                            methodStatements.Add(shader.ETS(methodInvoke));
                        }
                    }
                }
                else
                {
                    //is an array...
                    //simply call SetArray on the array object.
                    CodeExpression methodInvoke =
                        new CodeMethodInvokeExpression(assignmentArrayField, "SetArray",
                                                       valueRef);

                    methodStatements.Add(shader.ETS(methodInvoke));
                }
            }

            string upperName = Common.ToUpper(name);

            //there is always a setable property
            CodeMemberProperty property = new CodeMemberProperty();

            property.Name       = upperName;
            property.Type       = param.Type;
            property.Attributes = MemberAttributes.Final | MemberAttributes.Public;
            property.HasSet     = reg.ArraySize == -1;
            property.HasGet     = reg.ArraySize != -1;

            //there isn't always a set method
            CodeMemberMethod method = null;

            CodeStatement assignAttribute = null;

            if (hasSetMethod || reg.ArraySize != -1)
            {
                //create the method to set the value
                string methodName = "Set" + upperName;

                method            = new CodeMemberMethod();
                method.Name       = methodName;
                method.Attributes = MemberAttributes.Final | MemberAttributes.Public;

                method.Parameters.Add(param);
                method.Statements.AddRange(methodStatements);


                //create a property that calls the Set method if not an array, get method if it is an array

                if (reg.ArraySize == -1)
                {
                    //is not an array
                    CodeExpression invokeSetter =
                        new CodeMethodInvokeExpression(
                            shader.Instance, method.Name,
                            new CodeDirectionExpression(FieldDirection.Ref, new CodePropertySetValueReferenceExpression()));

                    property.SetStatements.Add(invokeSetter);
                }
                else
                {
                    //is an array, return the array object directly.
                    property.GetStatements.Add(new CodeMethodReturnStatement(assignmentArrayField));

                    //set the type of the property to IArray<float>, etc
                    Type interfaceType = typeof(Xen.Graphics.ShaderSystem.Constants.IArray <float>).GetGenericTypeDefinition();
                    interfaceType = interfaceType.MakeGenericType(dataType);

                    property.Type = new CodeTypeReference(interfaceType);
                }



                //call the method as well for attribute assign
                CodeExpression assignSetter =
                    new CodeMethodInvokeExpression(
                        shader.Instance, method.Name,
                        new CodeDirectionExpression(param.Direction, shader.AttributeAssignValue));

                assignAttribute = shader.ETS(assignSetter);
            }
            else
            {
                //create a property to directly set the value

                property.SetStatements.AddRange(methodStatements);

                //attribute assign sets the property
                assignAttribute = new CodeAssignStatement(
                    new CodePropertyReferenceExpression(shader.Instance, property.Name),
                    shader.AttributeAssignValue);
            }


            if (reg.ArraySize > 0)
            {
                if (method != null)
                {
                    add(method, string.Format("Set the shader array value '{0} {1}[{2}]'", reg.Type, reg.Name, reg.ArraySize));
                }
                add(property, string.Format("Get the array for the shader value '{0} {1}[{2}]'", reg.Type, reg.Name, reg.ArraySize));
            }
            else
            {
                if (method != null)
                {
                    add(method, string.Format("Set the shader value '{0} {1}'", reg.Type, reg.Name));
                }
                add(property, string.Format("Assign the shader value '{0} {1}'", reg.Type, reg.Name));
            }

            //create the attribute assignment value statement.

            List <CodeStatement> assignList;

            if (!attributeAssignment.TryGetValue(arrayOrSingleType, out assignList))
            {
                assignList = new List <CodeStatement>();
                attributeAssignment.Add(arrayOrSingleType, assignList);
            }

            //create the statement...

            CodeExpression assignIdsMatch =
                new CodeBinaryOperatorExpression(shader.AttributeAssignId, CodeBinaryOperatorType.IdentityEquality, assignmentField);

            CodeConditionStatement performAssign =
                new CodeConditionStatement(assignIdsMatch,
                                           assignAttribute,                                                   //call the assignment code
                                           new CodeMethodReturnStatement(new CodePrimitiveExpression(true))); //return true, set correctly.

            assignList.Add(performAssign);
        }
コード例 #7
0
        public override void AddBind(IShaderDom shader, Action <CodeStatement, string> add)
        {
            //bind the semantics bound attributes
            foreach (SemanticMapping mapping in semanticMapping)
            {
                //eg:
                //state.SetWorldMatrix(this.vreg.Matrix4Transpose(8), ref this.v_8);

                string method    = string.Format("Set{0}{1}", mapping.Type.Mapping, mapping.Type.Type.Name);
                bool   transpose = mapping.Type.Transpose ^ (mapping.Type.Type == typeof(Matrix));

                string registerTypeName = mapping.Type.Type.Name;
                if (mapping.Type.Type == typeof(Matrix))
                {
                    registerTypeName += (int)mapping.Register.Rank;
                }
                if (transpose)
                {
                    registerTypeName += "Transpose";
                }

                //for each register set, see if it uses this mapping

                int changeRefIndex = 0;
                foreach (KeyValuePair <AsmListing, CodeExpression> listing in listingRegisters)
                {
                    Register       sreg;
                    RegisterSet    registers    = listing.Key.RegisterSet;
                    CodeExpression registersRef = listing.Value;

                    if (registers.TryGetRegister(mapping.Register.Name, out sreg))
                    {
                        //it does.. so the constants need setting..
                        //state.SetWorldMatrix(this.vreg.Matrix4Transpose(8), ref this.v_8);

                        CodeExpression changeRef = new CodeDirectionExpression(FieldDirection.Ref, mapping.ChangeRefs[changeRefIndex]);

                        CodeExpression getRegister =                            //this.vreg.Matrix4Transpose(8)
                                                     new CodeMethodInvokeExpression(registersRef, registerTypeName, new CodePrimitiveExpression(sreg.Index));

                        //invoke
                        CodeExpression invokeSet =
                            new CodeMethodInvokeExpression(shader.ShaderSystemRef, method, getRegister, changeRef);

                        add(shader.ETS(invokeSet), changeRefIndex != 0 ? null : string.Format("Set the value for attribute '{0}'", mapping.Register.Name));

                        changeRefIndex++;
                    }
                }
            }

            //bind the shader globals

            foreach (GlobalAttribute global in globals)
            {
                string registerTypeName = global.Type.Name;
                if (global.Type == typeof(Matrix))
                {
                    registerTypeName += (int)global.Register.Rank;
                    registerTypeName += "Transpose";
                }

                int changeRefIndex = 0;
                foreach (KeyValuePair <AsmListing, CodeExpression> listing in listingRegisters)
                {
                    Register       sreg;
                    RegisterSet    registers    = listing.Key.RegisterSet;
                    CodeExpression registersRef = listing.Value;

                    if (registers.TryGetRegister(global.Register.Name, out sreg))
                    {
                        //special case the booleans, as they have different logic to set globally.
                        if (sreg.Category == RegisterCategory.Boolean)
                        {
                            if (global.Register.ArraySize != -1)
                            {
                                throw new CompileException("'GLOBAL' Boolean Arrays are not supported");
                            }

                            //this is a bit of a hack :-/
                            //need to figure out if this is a vertex or pixel boolean constant.
                            if (listing.Key == asm.VertexShader)
                            {
                                add(shader.ETS(
                                        new CodeMethodInvokeExpression(shader.ShaderSystemRef, "SetGlobal", shader.VertexShaderBooleanRegistersRef, new CodePrimitiveExpression(sreg.Index), global.GlobalIdRef, new CodeDirectionExpression(FieldDirection.Ref, shader.VertexShaderBooleanRegistersChangedRef))),
                                    string.Format("Set the value for global 'bool {0}'", global.Register.Name));
                            }
                            if (listing.Key == asm.PixelShader)
                            {
                                add(shader.ETS(
                                        new CodeMethodInvokeExpression(shader.ShaderSystemRef, "SetGlobal", shader.PixelShaderBooleanRegistersRef, new CodePrimitiveExpression(sreg.Index), global.GlobalIdRef, new CodeDirectionExpression(FieldDirection.Ref, shader.PixelShaderBooleanRegistersChangedRef))),
                                    string.Format("Set the value for global 'bool {0}'", global.Register.Name));
                            }
                        }
                        else
                        {
                            //eg:
                            //state.SetGlobal(this.vreg.Matrix4Transpose(8), ShadowShaderBlend.g_id0, ref this.g_0);

                            CodeExpression getRegister =                                //this.vreg.Matrix4Transpose(8)
                                                         new CodeMethodInvokeExpression(registersRef, registerTypeName, new CodePrimitiveExpression(sreg.Index));

                            CodeExpression changeParam = new CodeDirectionExpression(FieldDirection.Ref, global.ChangeRefs[changeRefIndex]);

                            CodeExpression invokeSet;

                            //logic changes for arrays

                            if (global.Register.ArraySize != -1)
                            {
                                invokeSet =
                                    new CodeMethodInvokeExpression(shader.ShaderSystemRef, "SetGlobal", global.ArrayRefs[changeRefIndex], global.GlobalIdRef, changeParam);
                                //state.SetGlobal(this.ga0, ShadowShaderBlend.g_id0, ref this.g_0);
                            }
                            else
                            {
                                //state.SetGlobal(this.vreg.Matrix4Transpose(8), ShadowShaderBlend.g_id0, ref this.g_0);
                                invokeSet =
                                    new CodeMethodInvokeExpression(shader.ShaderSystemRef, "SetGlobal", getRegister, global.GlobalIdRef, changeParam);
                            }

                            add(shader.ETS(invokeSet), changeRefIndex != 0 ? null : string.Format("Set the value for global '{0}'", global.Register.Name));

                            changeRefIndex++;
                        }
                    }
                }
            }
        }
コード例 #8
0
        //bind the samplers / textures
        public override void AddBind(IShaderDom shader, Action <CodeStatement, string> add)
        {
            // assign global textures first...


            bool firstAssign = true;

            for (int i = 0; i < this.textures.Length; i++)
            {
                if ((this.textures[i].PsSamplers.Count > 0 ||
                     this.textures[i].VsSamplers.Count > 0) &&
                    this.textures[i].IsGlobal)
                {
                    //assign the global

                    //a bit like:
                    //this.ShadowMap = state.GetGlobalTexture2D(ShadowShaderBlend.tid0);

                    CodeExpression uid  = new CodeFieldReferenceExpression(shader.ShaderClassEx, "tid" + i);
                    CodeExpression prop = new CodePropertyReferenceExpression(shader.Instance, Common.ToUpper(this.textures[i].Texture.Name));

                    CodeExpression call = new CodeMethodInvokeExpression(shader.ShaderSystemRef, "GetGlobal" + this.textures[i].Texture.Type, uid);

                    CodeStatement assign = new CodeAssignStatement(prop, call);

                    add(assign, firstAssign ? "Assign global textures" : null);
                    firstAssign = false;
                }
            }


            //bind the samplers / textures
            //looks something like this:

            /*
             *
             * if ((ic == true))
             * {
             *      this.ps_m = 65535;
             * }
             * if ((this.ps_m != 0))
             * {
             *      if (((this.ps_m & 1)
             *                              == 1))
             *      {
             *              state.SetPixelShaderSampler(0, this.ps_0t, this.ps_0);
             *      }
             *      if (((this.ps_m & 2)
             *                              == 2))
             *      {
             *              state.SetPixelShaderSampler(1, this.ps_1t, this.ps_1);
             *      }
             *      this.ps_m = 0;
             * }
             *
             */

            CodeExpression psm = new CodeFieldReferenceExpression(shader.Instance, "psm");
            CodeExpression vsm = new CodeFieldReferenceExpression(shader.Instance, "vsm");

            if (psSamplers.Count == 0 && vsSamplers.Count == 0)
            {
                return;
            }

            CodeStatement[] wipe = new CodeStatement[(psSamplers.Count > 0 ? 1 : 0) + (vsSamplers.Count > 0 ? 1 : 0)];
            if (psSamplers.Count > 0)
            {
                wipe[0] = new CodeAssignStatement(psm, new CodePrimitiveExpression(int.MaxValue));
            }
            if (vsSamplers.Count > 0)
            {
                wipe[wipe.Length - 1] = new CodeAssignStatement(vsm, new CodePrimitiveExpression(int.MaxValue));
            }

            //if instance changed, set the masks to big numbers
            CodeStatement maskWipe = new CodeConditionStatement(
                new CodeBinaryOperatorExpression(shader.BindShaderInstanceChange, CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(true)),
                wipe);

            add(maskWipe, "Reset change masks");

            //setup the pixel samplers
            if (psSamplers.Count > 0)
            {
                List <CodeStatement> statements = new List <CodeStatement>();

                //set the samplers
                foreach (SharedSampler ss in this.allSamplers.Values)
                {
                    /*
                     *      if (((this.ps_m & 1)
                     *                              == 1))
                     *      {
                     *              state.SetPixelShaderSampler(0, this.ps_0t, this.ps_0);
                     *      }
                     */
                    if (ss.PsIndex != -1)
                    {
                        //find the matching texture
                        int texIndex = -1;
                        for (int i = 0; i < this.textures.Length; i++)
                        {
                            if (textures[i].PsSamplers.Contains(ss.PsIndex))
                            {
                                texIndex = i;
                                break;
                            }
                        }

                        CodeExpression sampler = new CodeFieldReferenceExpression(shader.Instance, "ts" + ss.Index);
                        CodeExpression texture = new CodeFieldReferenceExpression(shader.Instance, "tx" + texIndex);
                        CodeExpression masked  = new CodeBinaryOperatorExpression(psm, CodeBinaryOperatorType.BitwiseAnd, new CodePrimitiveExpression(1 << ss.PsIndex));

                        CodeExpression assign = new CodeMethodInvokeExpression(shader.ShaderSystemRef, "SetPixelShaderSampler",
                                                                               new CodePrimitiveExpression(ss.PsIndex), texture, sampler);

                        CodeStatement full = new CodeConditionStatement(
                            new CodeBinaryOperatorExpression(masked, CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(1 << ss.PsIndex)),
                            shader.ETS(assign));

                        statements.Add(full);
                    }
                }


                //reset the mask
                statements.Add(new CodeAssignStatement(psm, new CodePrimitiveExpression((int)0)));

                //add it all up.
                //if the mask is non-zero,
                CodeStatement setAll = new CodeConditionStatement(
                    new CodeBinaryOperatorExpression(psm, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression((int)0)),
                    statements.ToArray());

                add(setAll, "Set pixel shader samplers");
            }


            //do it all again for VS
            if (vsSamplers.Count > 0)
            {
                List <CodeStatement> statements = new List <CodeStatement>();

                //set the samplers
                foreach (SharedSampler ss in this.allSamplers.Values)
                {
                    if (ss.VsIndex != -1)
                    {
                        //find the matching texture
                        int texIndex = -1;
                        for (int i = 0; i < this.textures.Length; i++)
                        {
                            if (textures[i].VsSamplers.Contains(ss.VsIndex))
                            {
                                texIndex = i;
                                break;
                            }
                        }

                        CodeExpression sampler = new CodeFieldReferenceExpression(shader.Instance, "ts" + ss.Index);
                        CodeExpression texture = new CodeFieldReferenceExpression(shader.Instance, "tx" + texIndex);
                        CodeExpression masked  = new CodeBinaryOperatorExpression(vsm, CodeBinaryOperatorType.BitwiseAnd, new CodePrimitiveExpression(1 << ss.VsIndex));

                        CodeExpression assign = new CodeMethodInvokeExpression(shader.ShaderSystemRef, "SetVertexShaderSampler",
                                                                               new CodePrimitiveExpression(ss.VsIndex), texture, sampler);

                        CodeStatement full = new CodeConditionStatement(
                            new CodeBinaryOperatorExpression(masked, CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(1 << ss.VsIndex)),
                            shader.ETS(assign));

                        statements.Add(full);
                    }
                }


                //reset the mask
                statements.Add(new CodeAssignStatement(vsm, new CodePrimitiveExpression((int)0)));

                //add it all up.
                //if the mask is non-zero,
                CodeStatement setAll = new CodeConditionStatement(
                    new CodeBinaryOperatorExpression(vsm, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression((int)0)),
                    statements.ToArray());

                add(setAll, "Set vertex shader samplers");
            }
        }
コード例 #9
0
		private void CreateConstantSetters(IShaderDom shader, Action<CodeTypeMember, string> add, string name, CodeExpression assignmentField, CodeExpression assignmentArrayField)
		{
			/*
			 * Something like:

			public void SetInvTargetSize(ref Microsoft.Xna.Framework.Vector2 value)
			{
				this.vreg.SetVector2(130, ref value);
			}

			public Microsoft.Xna.Framework.Vector2 InvTargetSize
			{
				set
				{
					this.SetInvTargetSize(ref value);
				}
			}*/

			Register reg;
			Type dataType;
			bool hasSetMethod;
			int stride;

			if (!ExtractRegType(name, out reg, out dataType, out hasSetMethod, out stride))
				return;

			Type arrayOrSingleType = dataType;

			//right...

			//create the method of the given type.


			//public void SetInvTargetSize(ref Microsoft.Xna.Framework.Vector2 value)
			CodeStatementCollection methodStatements = new CodeStatementCollection();

			CodeParameterDeclarationExpression param = new CodeParameterDeclarationExpression(dataType, "value");
			List<CodeParameterDeclarationExpression> additionalParams = new List<CodeParameterDeclarationExpression>();

			if (reg.ArraySize == -1)
				param.Direction = FieldDirection.Ref;
			else
			{
				arrayOrSingleType = dataType.MakeArrayType();
				param.Type = new CodeTypeReference(arrayOrSingleType);

				//add array params, readIndex, writeIndex, count
				additionalParams.Add(new CodeParameterDeclarationExpression(typeof(uint), "readIndex"));
				additionalParams.Add(new CodeParameterDeclarationExpression(typeof(uint), "writeIndex"));
				additionalParams.Add(new CodeParameterDeclarationExpression(typeof(uint), "count"));
			}

			CodeExpression valueRef = new CodeArgumentReferenceExpression(param.Name);

			//when there isn't a set method, there is just a set property
			if (!hasSetMethod)
				valueRef = new CodePropertySetValueReferenceExpression();

			//create the guts
			//depends on what constants use it...

			//eg:
			//this.vreg.SetVector2(130, ref value);

			Register sreg;

			if (dataType == typeof(bool))
			{
				//special case for booleans, assign the array directly.
				//looks like:
				// 
				// if (preg_bool[index] != value)
				// {
				//  preg_bool[index] = value;
				//  preg_bool_changed = true;
				// }

				foreach (KeyValuePair<AsmListing, CodeExpression> listing in listingRegisters)
				{
					RegisterSet registers = listing.Key.RegisterSet;
					CodeExpression registersRef = listing.Value;

					if (registers.TryGetRegister(name, out sreg))
					{
						if (listing.Key == asm.PixelShader)
						{
							CodeExpression arrayIndex = new CodeArrayIndexerExpression(shader.PixelShaderBooleanRegistersRef, new CodePrimitiveExpression(sreg.Index));

							CodeStatement assign = new CodeAssignStatement(arrayIndex, new CodePropertySetValueReferenceExpression());
							CodeStatement change = new CodeAssignStatement(shader.PixelShaderBooleanRegistersChangedRef, new CodePrimitiveExpression(true));

							CodeStatement condition = new CodeConditionStatement(
								new CodeBinaryOperatorExpression(arrayIndex, CodeBinaryOperatorType.IdentityInequality, new CodePropertySetValueReferenceExpression()),
								new CodeStatement[]{assign, change});

							methodStatements.Add(condition);
						}
						if (listing.Key == asm.VertexShader)
						{
							CodeExpression arrayIndex = new CodeArrayIndexerExpression(shader.VertexShaderBooleanRegistersRef, new CodePrimitiveExpression(sreg.Index));

							CodeStatement assign = new CodeAssignStatement(arrayIndex, new CodePropertySetValueReferenceExpression());
							CodeStatement change = new CodeAssignStatement(shader.VertexShaderBooleanRegistersChangedRef, new CodePrimitiveExpression(true));

							CodeStatement condition = new CodeConditionStatement(
								new CodeBinaryOperatorExpression(arrayIndex, CodeBinaryOperatorType.IdentityInequality, new CodePropertySetValueReferenceExpression()),
								new CodeStatement[] { assign, change });

							methodStatements.Add(condition);
						}
					}
				}
			}
			else
			{
				//some array set methods require temporary values, but should only be created once.
				bool tempValuesCreated = false;

				foreach (KeyValuePair<AsmListing, CodeExpression> listing in listingRegisters)
				{
					RegisterSet registers = listing.Key.RegisterSet;
					CodeExpression registersRef = listing.Value;

					if (registers.TryGetRegister(name, out sreg))
					{
						//Assign the register array data
						AssignRegister(dataType, sreg, reg, listing.Value, valueRef, methodStatements, ref tempValuesCreated);

						//set changed
						CodeExpression changeValue = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), (registersRef as CodeFieldReferenceExpression).FieldName + "_change");

						methodStatements.Add(new CodeAssignStatement(changeValue, new CodePrimitiveExpression(true)));
					}
				}
			}

			string upperName = Common.ToUpper(name);

			//there is always a setable property
			CodeMemberProperty property = new CodeMemberProperty();
			property.Name = upperName;
			property.Type = param.Type;
			property.Attributes = MemberAttributes.Final | MemberAttributes.Public;
			property.HasSet = true;
			property.HasGet = false;

			//there isn't always a set method
			CodeMemberMethod method = null;

			CodeStatement assignAttribute = null;

			if (hasSetMethod || reg.ArraySize != -1)
			{
				//create the method to set the value
				string methodName = "Set" + upperName;

				method = new CodeMemberMethod();
				method.Name = methodName;
				method.Attributes = MemberAttributes.Final | MemberAttributes.Public;

				method.Parameters.Add(param);
				method.Parameters.AddRange(additionalParams.ToArray());
				method.Statements.AddRange(methodStatements);


				//create a property that calls the Set method

				//is not an array
				CodeMethodInvokeExpression invokeSetter =
					new CodeMethodInvokeExpression(
						shader.Instance, method.Name,
						new CodeDirectionExpression(reg.ArraySize == -1 ? FieldDirection.Ref : FieldDirection.In, new CodePropertySetValueReferenceExpression()));

				if (reg.ArraySize != -1)
				{
					//add method ops (readIndex, writeIndex, count)
					invokeSetter.Parameters.Add(new CodePrimitiveExpression(0));
					invokeSetter.Parameters.Add(new CodePrimitiveExpression(0));
					invokeSetter.Parameters.Add(new CodeCastExpression(typeof(uint), new CodePropertyReferenceExpression(valueRef, "Length")));
				}

				property.SetStatements.Add(invokeSetter);



				//call the method as well for attribute assign
				CodeMethodInvokeExpression assignSetter = 
					new CodeMethodInvokeExpression(
						shader.Instance, method.Name,
						new CodeDirectionExpression(param.Direction, shader.AttributeAssignValue));

				if (reg.ArraySize != -1)
				{
					//add method ops (readIndex, writeIndex, count)
					assignSetter.Parameters.Add(new CodePrimitiveExpression(0));
					assignSetter.Parameters.Add(new CodePrimitiveExpression(0));
					assignSetter.Parameters.Add(new CodeCastExpression(typeof(uint), new CodePropertyReferenceExpression(valueRef, "Length")));
				}

				assignAttribute = shader.ETS(assignSetter);
			}
			else
			{
				//create a property to directly set the value

				property.SetStatements.AddRange(methodStatements);

				//attribute assign sets the property
				assignAttribute = new CodeAssignStatement(
					new CodePropertyReferenceExpression(shader.Instance, property.Name),
						shader.AttributeAssignValue);
			}
			

			if (reg.ArraySize > 0)
			{
				if (method != null)
					add(method, string.Format("Set the shader array value '{0} {1}[{2}]'", reg.Type, reg.Name, reg.ArraySize));
				add(property, string.Format("Set and copy the array data for the shader value '{0} {1}[{2}]'", reg.Type, reg.Name, reg.ArraySize));
			}
			else
			{
				if (method != null)
					add(method, string.Format("Set the shader value '{0} {1}'", reg.Type, reg.Name));
				add(property, string.Format("Assign the shader value '{0} {1}'", reg.Type, reg.Name));
			}

			//create the attribute assignment value statement.

			List<CodeStatement> assignList;
			if (!attributeAssignment.TryGetValue(arrayOrSingleType, out assignList))
			{
				assignList = new List<CodeStatement>();
				attributeAssignment.Add(arrayOrSingleType, assignList);
			}

			//create the statement...
			
			CodeExpression assignIdsMatch =
				new CodeBinaryOperatorExpression(shader.AttributeAssignId,  CodeBinaryOperatorType.IdentityEquality, assignmentField);

			CodeConditionStatement performAssign =
				new CodeConditionStatement(assignIdsMatch,
					assignAttribute, //call the assignment code
					new CodeMethodReturnStatement(new CodePrimitiveExpression(true))); //return true, set correctly.

			assignList.Add(performAssign);
		}
コード例 #10
0
		public override void AddBind(IShaderDom shader, Action<CodeStatement, string> add)
		{
			bool requiresUnused = false;

			//bind the semantics bound attributes
			foreach (SemanticMapping mapping in semanticMapping)
			{
				//eg:
				//state.SetWorldMatrix(this.vreg.Matrix4Transpose(8), ref this.v_8);

				string method = string.Format("Set{0}{1}", mapping.Type.Mapping, mapping.Type.Type.Name);

				if (mapping.Type.IsArray)
					method += "Array";

				//for each register set, see if it uses this mapping

				int changeRefIndex = 0;
				foreach (KeyValuePair<AsmListing, CodeExpression> listing in listingRegisters)
				{
					Register sreg;
					RegisterSet registers = listing.Key.RegisterSet;
					CodeExpression registersRef = listing.Value;

					if (registers.TryGetRegister(mapping.Register.Name, out sreg))
					{
						//it does.. so the constants need setting..
						//changed |= state.SetWorldMatrix(ref this.vreg[8], ref this.vreg[9], ref this.vreg[9], ref unused, ref this.v_8);

						CodeExpression changeRef = Ref(mapping.ChangeRefs[changeRefIndex]);

						CodeExpression getRegisterX =	//this.vreg[8]
							new CodeArrayIndexerExpression(registersRef, new CodePrimitiveExpression(sreg.Index));

						//invoke
						CodeExpression invokeSet = null;

						if (mapping.Type.IsArray)
						{
							invokeSet = new CodeMethodInvokeExpression(shader.ShaderSystemRef, method, registersRef, new CodePrimitiveExpression(sreg.Index), new CodePrimitiveExpression(sreg.Size), changeRef);
						}
						else
						{
							if (mapping.Type.Type == typeof(Matrix))
							{
								int rank = (int)mapping.Register.Rank;
								if (rank != 4 && requiresUnused == false) // an 'unused' variable is required
								{
									//add a temporary. A matrix being set may not use all 4 rows. Need a temp write target
									add(new CodeVariableDeclarationStatement(typeof(Vector4), "unused", new CodeObjectCreateExpression(typeof(Vector4))), null);
									requiresUnused = true;
								}

								//setter takes in X,Y,Z,W registers
								CodeExpression unused = new CodeVariableReferenceExpression("unused");
								CodeExpression Y = rank >= 2 ? new CodeArrayIndexerExpression(registersRef, new CodePrimitiveExpression(sreg.Index + 1)) : unused;
								CodeExpression Z = rank >= 3 ? new CodeArrayIndexerExpression(registersRef, new CodePrimitiveExpression(sreg.Index + 2)) : unused;
								CodeExpression W = rank >= 4 ? new CodeArrayIndexerExpression(registersRef, new CodePrimitiveExpression(sreg.Index + 3)) : unused;

								invokeSet = new CodeMethodInvokeExpression(shader.ShaderSystemRef, method, Ref(getRegisterX), Ref(Y), Ref(Z), Ref(W), changeRef);
							}
							else
								invokeSet = new CodeMethodInvokeExpression(shader.ShaderSystemRef, method, Ref(getRegisterX), changeRef);
						}

						//update the change value appropriately
						CodeExpression changeValue = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), (registersRef as CodeFieldReferenceExpression).FieldName + "_change");

						//change |= ...;
						CodeStatement assign = new CodeAssignStatement(changeValue, 
							new CodeBinaryOperatorExpression(changeValue, CodeBinaryOperatorType.BitwiseOr,
								invokeSet));

						if (ExtractAssignmentForExtenionBlock(assign, shader, listing.Key))
							continue;

						add(assign, changeRefIndex != 0 ? null : string.Format("Set the value for attribute '{0}'", mapping.Register.Name));

						changeRefIndex++;
					}
				}
			}

			//bind the shader globals

			foreach (GlobalAttribute global in globals)
			{
				string registerTypeName = global.Type.Name;
				if (global.Type == typeof(Matrix))
				{
					registerTypeName += (int)global.Register.Rank;
				}
				
				int changeRefIndex = 0;
				foreach (KeyValuePair<AsmListing, CodeExpression> listing in listingRegisters)
				{
					Register sreg;
					RegisterSet registers = listing.Key.RegisterSet;
					CodeExpression registersRef = listing.Value;

					bool isMatrix = global.Type == typeof(Matrix);

					if (registers.TryGetRegister(global.Register.Name, out sreg))
					{
						//special case the booleans, as they have different logic to set globally.
						if (sreg.Category == RegisterCategory.Boolean)
						{
							if (global.Register.ArraySize != -1)
								throw new CompileException("'GLOBAL' Boolean Arrays are not supported");


							//this is a bit of a hack :-/
							//need to figure out if this is a vertex or pixel boolean constant.
							if (listing.Key == asm.VertexShader)
							{
								CodeExpression setValue = new CodeMethodInvokeExpression(shader.ShaderSystemRef, "SetGlobalBool", shader.VertexShaderBooleanRegistersRef, new CodePrimitiveExpression(sreg.Index), global.GlobalIdRef);

								//update the change flag
								CodeExpression invoke = new CodeBinaryOperatorExpression(
									shader.VertexShaderBooleanRegistersChangedRef, CodeBinaryOperatorType.BitwiseOr,
									setValue);

								add(shader.ETS(invoke),
									string.Format("Set the value for global 'bool {0}'", global.Register.Name));
							}
							if (listing.Key == asm.PixelShader)
							{
								CodeExpression setValue = new CodeMethodInvokeExpression(shader.ShaderSystemRef, "SetGlobalBool", shader.PixelShaderBooleanRegistersRef, new CodePrimitiveExpression(sreg.Index), global.GlobalIdRef);
								
								//update the change flag
								CodeExpression invoke = new CodeBinaryOperatorExpression(
									shader.PixelShaderBooleanRegistersChangedRef, CodeBinaryOperatorType.BitwiseOr,
									setValue);

								add(shader.ETS(invoke),
									string.Format("Set the value for global 'bool {0}'", global.Register.Name));
							}
						}
						else
						{
							//eg:
							//changed |= state.SetGlobalMatrix3(ref this.vreg[8], ref this.vreg[9], ref this.vreg[10], ShadowShaderBlend.g_id0, ref this.g_0);

							CodeExpression getRegisterX =	//this.vreg[8]
								new CodeArrayIndexerExpression(registersRef, new CodePrimitiveExpression(sreg.Index));

							string methodName = "SetGlobal" + global.Type.Name;
							int rank = (int)global.Register.Rank;

							if (isMatrix)
								methodName += rank;

							//eg, SetGlobalMatrix3

							CodeExpression changeRef = Ref(global.ChangeRefs[changeRefIndex]);
							CodeExpression invokeSet;

							//logic changes for arrays

							if (global.Register.ArraySize != -1)
							{
								//SetGlobalMatrix3 for Arrays takes in the array itself as the first arg.
								invokeSet =
									new CodeMethodInvokeExpression(shader.ShaderSystemRef, methodName, registersRef, new CodePrimitiveExpression(global.Register.Index), new CodePrimitiveExpression(global.Register.Size + global.Register.Index), global.GlobalIdRef, changeRef);
								//state.SetGlobal(this.ga0, ShadowShaderBlend.g_id0, ref this.g_0);
							}
							else
							{
								//SetGlobalMatrix3 for non-arays takes a variable number of arguements
								if (isMatrix)
								{
									List<CodeExpression> args = new List<CodeExpression>();
									//add X
									args.Add(Ref(getRegisterX));
									if (rank >= 2) args.Add(Ref(new CodeArrayIndexerExpression(registersRef, new CodePrimitiveExpression(sreg.Index + 1))));
									if (rank >= 3) args.Add(Ref(new CodeArrayIndexerExpression(registersRef, new CodePrimitiveExpression(sreg.Index + 2))));
									if (rank >= 4) args.Add(Ref(new CodeArrayIndexerExpression(registersRef, new CodePrimitiveExpression(sreg.Index + 3))));

									args.Add(global.GlobalIdRef);
									args.Add(changeRef);
									
									invokeSet =
										new CodeMethodInvokeExpression(shader.ShaderSystemRef, methodName, args.ToArray());
								}
								else
									invokeSet =
										new CodeMethodInvokeExpression(shader.ShaderSystemRef, methodName, Ref(getRegisterX), global.GlobalIdRef, changeRef);
							}

								
							//update the change value appropriately
							CodeExpression changeValue = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), (registersRef as CodeFieldReferenceExpression).FieldName + "_change");

							//change |= ...;
							CodeStatement assign = new CodeAssignStatement(changeValue, 
								new CodeBinaryOperatorExpression(changeValue, CodeBinaryOperatorType.BitwiseOr,
									invokeSet));

							if (ExtractAssignmentForExtenionBlock(assign, shader, listing.Key))
								continue;

							add(assign, changeRefIndex != 0 ? null : string.Format("Set the value for global '{0}'", global.Register.Name));

							changeRefIndex++;
						}
					}
				}
			}
		}
コード例 #11
0
		private static CodeConditionStatement GenerateAssignConstantsInvoke(IShaderDom shader, CodeStatement setDirty, CodeExpression bufferRef, CodeExpression changeRef, string name)
		{
			CodeBinaryOperatorExpression assignCondition = new CodeBinaryOperatorExpression(
							changeRef, CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(true));

			//assign the effect params directly

			//assign
			CodeConditionStatement assign = new CodeConditionStatement(assignCondition,
				shader.ETS(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(shader.EffectRef, name), "SetValue", bufferRef)),
				new CodeAssignStatement(changeRef, new CodePrimitiveExpression(false)),
				setDirty);
			return assign;
		}
コード例 #12
0
		public override void AddBindEnd(IShaderDom shader, Action<CodeStatement, string> add)
		{
			//set the constants
			//eg:
			/*
			 * 
			if (((this.vreg.change == true)
						|| (ic == true)))
			{
				state.SetShaderConstants(this.vreg.array, null);
				this.vreg.change = false;
			}
			 */

			CodeExpression vreg = new CodePrimitiveExpression(null);
			CodeExpression preg = vreg;
			
			CodeStatement setDirty = new CodeAssignStatement(shader.BindShaderInstanceChange, new CodePrimitiveExpression(true));

			if (vsReg.FloatRegisterCount > 0)
			{
				//assign if changed
				CodeConditionStatement assign = GenerateAssignConstantsInvoke(shader, setDirty, shader.VertexShaderRegistersRef, shader.VertexShaderRegistersChangedRef, "vs_c");

				add(assign, null);
			}

			//again for PS
			if (psReg.FloatRegisterCount > 0)
			{
				//assign if changed
				CodeConditionStatement assign = GenerateAssignConstantsInvoke(shader, setDirty, shader.PixelShaderRegistersRef, shader.PixelShaderRegistersChangedRef, "ps_c");

				add(assign, null);
			}

			//assing for blending, if it's there
			if (vsBlendingReg != null && vsBlendingReg.FloatRegisterCount > 0)
			{
				CodeConditionStatement condition = new CodeConditionStatement(shader.ShaderExtensionIsBlending);

				if (extensionStatementProvider.IsBlendingBufferNotShared)
				{
					condition.TrueStatements.Add(extensionStatementProvider.GetBlendDirectAssignment(shader));
				}
				else
				{
					//assign if changed
					CodeConditionStatement assign = GenerateAssignConstantsInvoke(shader, setDirty, shader.BlendShaderRegistersRef, shader.BlendShaderRegistersChangedRef, "vsb_c");

					//write in a mode statement
					condition.TrueStatements.AddRange(extensionStatementProvider.GetBlendExtensionAssignments());
					condition.TrueStatements.Add(assign);
				}

				add(condition, null);
			}

			//assing for instancing, if it's there
			if (vsInstancingReg != null && vsInstancingReg.FloatRegisterCount > 0)
			{
				//assign if changed
				CodeConditionStatement assign = GenerateAssignConstantsInvoke(shader, setDirty, shader.InstancingShaderRegistersRef, shader.InstancingShaderRegistersChangdRef, "vsi_c");

				//write in a mode statement
				CodeConditionStatement condition = new CodeConditionStatement(shader.ShaderExtensionIsInstancing, extensionStatementProvider.GetInstancingExtensionAssignments());
				condition.TrueStatements.Add(assign);

				add(condition, null);
			}

			//set the boolean registers
			if (vsReg.BooleanRegisterCount > 0)
			{
				//assign
				CodeExpression assign = new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(shader.EffectRef, "vs_b"), "SetValue", shader.VertexShaderBooleanRegistersRef);

				//assign the effect params directly
				CodeConditionStatement changed = new CodeConditionStatement(shader.VertexShaderBooleanRegistersRef,
										shader.ETS(assign), setDirty,
										new CodeAssignStatement(shader.VertexShaderBooleanRegistersChangedRef, new CodePrimitiveExpression(false)));

				add(changed, null);
			}
			if (vsReg.BooleanRegisterCount > 0)
			{
				//assign
				CodeExpression assign = new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(shader.EffectRef, "ps_b"), "SetValue", shader.PixelShaderBooleanRegistersRef);

				//assign the effect params directly
				CodeConditionStatement changed = new CodeConditionStatement(shader.PixelShaderBooleanRegistersChangedRef,
										shader.ETS(assign), setDirty,
										new CodeAssignStatement(shader.PixelShaderBooleanRegistersChangedRef, new CodePrimitiveExpression(false)));

				add(changed, null);
			}
		}
コード例 #13
0
		public override void AddBind(IShaderDom shader, Action<CodeStatement, string> add)
		{
			//call the preshaders

			if (vertexPreShader != null)
			{
				CodeExpression call = new CodeMethodInvokeExpression(shader.Instance, "vspre");
				CodeExpression condition = new CodeBinaryOperatorExpression(new CodeFieldReferenceExpression(shader.VertexPreShaderRegistersRef, "change"),  CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(true));
				CodeStatement invoke = new CodeConditionStatement(condition, shader.ETS(call));

				add(invoke, "run the vertex preshader");
			}
			
			//pixel
			if (pixelPreShader != null)
			{
				CodeExpression call = new CodeMethodInvokeExpression(shader.Instance, "pspre");
				CodeExpression condition = new CodeBinaryOperatorExpression(new CodeFieldReferenceExpression(shader.PixelPreShaderRegistersRef, "change"),  CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(true));
				CodeStatement invoke = new CodeConditionStatement(condition, shader.ETS(call));

				add(invoke, "run the pixel preshader");
			}
		}
コード例 #14
0
		//bind the samplers / textures
		public override void AddBind(IShaderDom shader, Action<CodeStatement, string> add)
		{
			// assign global textures first...

			bool firstAssign = true;
			for (int i = 0; i < this.textures.Length; i++)
			{
				if ((this.textures[i].PsSamplers.Count > 0 ||
					this.textures[i].VsSamplers.Count > 0) &&
					this.textures[i].IsGlobal)
				{
					//assign the global

					//a bit like:
					//this.ShadowMap = state.GetGlobalTexture2D(ShadowShaderBlend.tid0);

					CodeExpression uid = new CodeFieldReferenceExpression(shader.ShaderClassEx, "tid" + i);
					CodeExpression prop = new CodePropertyReferenceExpression(shader.Instance, Common.ToUpper(this.textures[i].Texture.Name));

					CodeExpression call = new CodeMethodInvokeExpression(shader.ShaderSystemRef, "GetGlobal" + this.textures[i].Texture.Type, uid);

					CodeStatement assign = new CodeAssignStatement(prop, call);

					add(assign, firstAssign ? "Assign global textures" : null);
					firstAssign = false;
				}
			}


			// assign global samplers...

			firstAssign = true;
			foreach (KeyValuePair<string,SharedSampler> sampler in allSamplers)
			{
				if (sampler.Value.IsGlobal)
				{
					//assign the global
					int i = sampler.Value.Index;

					//a bit like:
					//this.ShadowMapSampler = state.GetGlobalTextureSamplerState(ShadowShaderBlend.sid0);

					CodeExpression uid = new CodeFieldReferenceExpression(shader.ShaderClassEx, "sid" + i);
					CodeExpression prop = new CodePropertyReferenceExpression(shader.Instance, sampler.Key);

					CodeExpression call = new CodeMethodInvokeExpression(shader.ShaderSystemRef, "GetGlobalTextureSamplerState", uid);

					CodeStatement assign = new CodeAssignStatement(prop, call);

					add(assign, firstAssign ? "Assign global sampler" : null);
					firstAssign = false;
				}
			}


			//bind the samplers / textures
	
			//change:
			CodeExpression ptc = new CodeFieldReferenceExpression(shader.Instance, "ptc");
			CodeExpression vtc = new CodeFieldReferenceExpression(shader.Instance, "vtc");

			//setup the pixel samplers
			if (psSamplers.Count > 0)
			{
				CodeExpression condition = new CodeBinaryOperatorExpression(shader.BindShaderInstanceChange, CodeBinaryOperatorType.BitwiseOr, ptc);

				CodeExpression textures = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "ptx");
				CodeExpression samplers = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "pts");
				CodeExpression assign = new CodeMethodInvokeExpression(shader.ShaderSystemRef, "SetPixelShaderSamplers",textures, samplers);

				CodeStatement combine = new CodeConditionStatement(condition,shader.ETS(assign), new CodeAssignStatement(ptc,new CodePrimitiveExpression(false)));
				add(combine, "Assign pixel shader textures and samplers");
			}

			//do it all again for VS
			if (vsSamplers.Count > 0)
			{
				CodeExpression condition = new CodeBinaryOperatorExpression(shader.BindShaderInstanceChange, CodeBinaryOperatorType.BitwiseOr, vtc);

				CodeExpression textures = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "vtx");
				CodeExpression samplers = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "vts");
				CodeExpression assign = new CodeMethodInvokeExpression(shader.ShaderSystemRef, "SetVertexShaderSamplers", textures, samplers);

				CodeStatement combine = new CodeConditionStatement(condition, shader.ETS(assign), new CodeAssignStatement(vtc, new CodePrimitiveExpression(false)));
				add(combine, "Assign pixel shader textures and samplers");
			}
		}