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"); }
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); } }
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"); } }
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); } }
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))); } } } } }
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); }
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++; } } } } }
//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"); } }
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); }
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++; } } } } }
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; }
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); } }
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"); } }
//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"); } }