//setup the ID based setters / getters public override void AddSetAttribute(IShaderDom shader, Action <CodeStatement> add, Type type) { //samplers first if (type == typeof(Xen.Graphics.State.TextureSamplerState)) { foreach (SharedSampler ss in allSamplers.Values) { //assign the sampler, if it matches. CodeExpression uid = new CodeFieldReferenceExpression(shader.ShaderClassEx, "sid" + ss.Index); CodeExpression sampler = new CodePropertyReferenceExpression(shader.Instance, Common.ToUpper(ss.SamplerDetails.Name)); CodeExpression assignIdsMatch = new CodeBinaryOperatorExpression(shader.AttributeAssignId, CodeBinaryOperatorType.IdentityEquality, uid); CodeStatement assignAttribute = new CodeAssignStatement(sampler, shader.AttributeAssignValue); CodeConditionStatement performAssign = new CodeConditionStatement(assignIdsMatch, assignAttribute, //call the assignment code new CodeMethodReturnStatement(new CodePrimitiveExpression(true))); //return true, set correctly. add(performAssign); } } if (!typeof(Microsoft.Xna.Framework.Graphics.Texture).IsAssignableFrom(type)) { return; } //now, all the non-global textures for (int i = 0; i < textures.Length; i++) { TextureAssociation tex = textures[i]; if ((tex.PsSamplers.Count > 0 || tex.VsSamplers.Count > 0) && tex.IsGlobal == false) { if (Common.GetTextureType(tex.Texture.Type) == type) { //assign CodeExpression uid = new CodeFieldReferenceExpression(shader.ShaderClassEx, "tid" + i); CodeExpression sampler = new CodePropertyReferenceExpression(shader.Instance, Common.ToUpper(tex.Texture.Name)); CodeExpression assignIdsMatch = new CodeBinaryOperatorExpression(shader.AttributeAssignId, CodeBinaryOperatorType.IdentityEquality, uid); CodeStatement assignAttribute = new CodeAssignStatement(sampler, shader.AttributeAssignValue); CodeConditionStatement performAssign = new CodeConditionStatement(assignIdsMatch, assignAttribute, //call the assignment code new CodeMethodReturnStatement(new CodePrimitiveExpression(true))); //return true, set correctly. add(performAssign); } } } }
public override void AddMembers(IShaderDom shader, Action <CodeTypeMember, string> add, Platform platform) { if (platform != Platform.Both) { return; } //static graphics ID CodeMemberField field = new CodeMemberField(typeof(int), gdIndexRef.FieldName); field.Attributes = MemberAttributes.Static | MemberAttributes.Final | MemberAttributes.Private; add(field, "Static graphics ID"); //if the class is extendable or extended, state.SetShaders() goes into it's own method if (isShaderExtenable || shaderExtendsFrom != null) { CodeExpression setShaders = new CodeMethodInvokeExpression( ShaderSystemRef, "SetShaders", VertexShaderRef, PixelShaderRef); CodeMemberMethod localSetShaders = new CodeMemberMethod(); localSetShaders.Name = "SetShaders"; localSetShaders.Parameters.Add(new CodeParameterDeclarationExpression(typeof(IShaderSystem), ShaderSystemRef.ParameterName)); localSetShaders.Attributes = MemberAttributes.Family; //is extended, override if (shaderExtendsFrom != null) { localSetShaders.Attributes |= MemberAttributes.Override; } localSetShaders.Statements.Add(setShaders); add(localSetShaders, "Local method required for shader extensions"); } }
public override void AddReadonlyMembers(IShaderDom shader, Action <CodeTypeMember, string> add, Platform platform) { if (platform == Platform.Both) { add(vsInputField, "array storing vertex usages, and element indices"); } }
public override void AddConstructor(IShaderDom shader, Action <CodeStatement> add) { //setup the default values for the masks and samplers if (psSamplers.Count > 0) { //set the PS mask to a big number CodeStatement assign = new CodeAssignStatement(new CodeFieldReferenceExpression(shader.Instance, "psm"), new CodePrimitiveExpression(int.MaxValue)); add(assign); } if (vsSamplers.Count > 0) { //set the PS mask to a big number CodeStatement assign = new CodeAssignStatement(new CodeFieldReferenceExpression(shader.Instance, "vsm"), new CodePrimitiveExpression(int.MaxValue)); add(assign); } //set the samplers to their defaults foreach (SharedSampler ss in allSamplers.Values) { //get the default as an int, //then cast it to a sampler state using explicit cast construction CodeExpression value = new CodeCastExpression(typeof(Xen.Graphics.State.TextureSamplerState), new CodePrimitiveExpression((int)ss.DefaultState)); //assign the value CodeStatement assign = new CodeAssignStatement(new CodeFieldReferenceExpression(shader.Instance, "ts" + ss.Index), value); add(assign); } }
//extract pairs of asmlistings / code registers private void ComputeListings(IShaderDom shader) { List <KeyValuePair <AsmListing, CodeExpression> > listings = new List <KeyValuePair <AsmListing, CodeExpression> >(); if (asm.VertexShader != null) { listings.Add(new KeyValuePair <AsmListing, CodeExpression>(asm.VertexShader, shader.VertexShaderRegistersRef)); } if (asm.PixelShader != null) { listings.Add(new KeyValuePair <AsmListing, CodeExpression>(asm.PixelShader, shader.PixelShaderRegistersRef)); } //preshaders if (asm.VertexPreShader != null) { listings.Add(new KeyValuePair <AsmListing, CodeExpression>(asm.VertexPreShader, shader.VertexPreShaderRegistersRef)); } if (asm.PixelPreShader != null) { listings.Add(new KeyValuePair <AsmListing, CodeExpression>(asm.PixelPreShader, shader.PixelPreShaderRegistersRef)); } this.listingRegisters = listings.ToArray(); }
private void ProcessConstants(IShaderDom shader) { RegisterSet registers = asm.CommonRegisters; for (int i = 0; i < registers.RegisterCount; i++) { Register reg = registers.GetRegister(i); if (reg.Category == RegisterCategory.Float4 || reg.Category == RegisterCategory.Boolean) { if (reg.Semantic == null) { this.attributeNames.Add(reg.Name); } else { ExtractSemantic(shader, reg); } } else if (reg.Semantic != null && reg.Category != RegisterCategory.Texture) { throw new CompileException(string.Format("Error parsing semantic for '{1} {0}'. Semantic bound types may only be processed as Float4 or Texture registers", reg.Name, reg.Type)); } } }
//add the member fields public override void SetupMembers(IShaderDom shader) { ComputeListings(shader); ProcessConstants(shader); for (int i = 0; i < attributeNames.Count; i++) { //create a field ref for the static that will be created //these are used to assign the value using 'SetAttribute' CodeFieldReferenceExpression field = new CodeFieldReferenceExpression(shader.ShaderClassEx, string.Format("cid{0}", i)); this.attributeFields.Add(field); //if it's an array, an array object needs to be created too. Create the ref to it now field = null; Register reg; Type type; //unused if (ExtractRegType(attributeNames[i], out reg, out type) && reg.ArraySize != -1) { field = new CodeFieldReferenceExpression(shader.Instance, string.Format("ca{0}", i)); } attributeArrayFields.Add(field); //may be null. } }
public override void AddStaticGraphicsInit(IShaderDom shader, Action <CodeStatement, string> add) { //assign the static graphics ID CodeStatement assign = new CodeAssignStatement(gdIndexRef, new CodePropertyReferenceExpression(ShaderSystemRef, "DeviceUniqueIndex")); add(assign, "set the graphics ID"); }
private void WriteBytes(IShaderDom shader, string name, byte[] data, Action <CodeTypeMember, string> add, CompileDirectives compileDirectives, bool isVS, bool isXbox) { //the byte array gets run through a simple compression scheme first... //generate the local byte array CodeMemberField field = new CodeMemberField(typeof(byte[]), name); field.Attributes = MemberAttributes.Final | MemberAttributes.Private | MemberAttributes.Static; data = ConstantArray.ArrayUtils.SimpleCompress(data); //if using the byte pool, then defer creating the array if (source.PoolShaderBytes) { if (isXbox) { field.InitExpression = source.BytePoolXbox.AddArray(data); } else { field.InitExpression = source.BytePoolPC.AddArray(data); } } else { //decompressed in code CodeMethodReferenceExpression decompressMethod = new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(typeof(ConstantArray.ArrayUtils)), "SimpleDecompress"); CodeExpression dataCode = ToArray(data, compileDirectives); //assign it inline field.InitExpression = new CodeMethodInvokeExpression(decompressMethod, dataCode); } add(field, string.Format("Static {0} shader byte code ({1})", isVS ? "vertex" : "pixel", isXbox ? "Xbox360" : "Windows")); }
private void GenerateNameIds(IShaderDom shader, Action <CodeTypeMember, string> add) { //each texture / sampler needs to be settable by ID foreach (SharedSampler ss in allSamplers.Values) { //create a uid for the sampler CodeMemberField field = new CodeMemberField(typeof(int), "sid" + ss.Index); field.Attributes = MemberAttributes.Private | MemberAttributes.Family | MemberAttributes.Static; add(field, string.Format("Name uid for sampler for '{0} {1}'", Common.ToUpper(ss.SamplerDetails.Type), ss.SamplerDetails.Name)); } //create for each texture for (int i = 0; i < textures.Length; i++) { TextureAssociation tex = textures[i]; if (tex.PsSamplers.Count > 0 || tex.VsSamplers.Count > 0) { //create a uid for the sampler CodeMemberField field = new CodeMemberField(typeof(int), "tid" + i); field.Attributes = MemberAttributes.Private | MemberAttributes.Family | MemberAttributes.Static; add(field, string.Format("Name uid for texture for '{0} {1}'", tex.Texture.Type, tex.Texture.Name)); } } }
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 AddReadonlyMembers(IShaderDom shader, Action<CodeTypeMember, string> add, Platform platform) { if (platform != Platform.Both) return; if (vsReg.FloatRegisterCount > 0) { CodeMemberField field = CreateShaderBufferField(shader, vsReg, shader.VertexShaderRegistersRef.FieldName); add(field, "Vertex shader register storage"); } //and the PS if (psReg.FloatRegisterCount > 0) { CodeMemberField field = CreateShaderBufferField(shader, psReg, shader.PixelShaderRegistersRef.FieldName); add(field, "Pixel shader register storage"); } //now do the boolean registers if (vsReg.BooleanRegisterCount > 0) { //create the vertex boolean registers CodeMemberField field = new CodeMemberField(typeof(bool[]), shader.VertexShaderBooleanRegistersRef.FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, "Vertex shader boolean register storage"); } //now the PS if (psReg.BooleanRegisterCount > 0) { //create the vertex boolean registers CodeMemberField field = new CodeMemberField(typeof(bool[]), shader.PixelShaderBooleanRegistersRef.FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, "Pixel shader boolean register storage"); } //blending if (vsBlendingReg != null && vsBlendingReg.FloatRegisterCount > 0 && shader.SourceShader.ManualExtensions) { CodeMemberField field = CreateShaderBufferField(shader, vsBlendingReg, shader.BlendShaderRegistersRef.FieldName); add(field, "Blend shader register storage"); } //instancing if (vsInstancingReg != null && vsInstancingReg.FloatRegisterCount > 0) { CodeMemberField field = CreateShaderBufferField(shader, vsInstancingReg, shader.InstancingShaderRegistersRef.FieldName); add(field, "Instancing shader register storage"); } }
public override void AddMembers(IShaderDom shader, Action <CodeTypeMember, string> add, Platform platform) { if (platform != Platform.Both) { return; } //if samplers are used, a integer is stored which will use bit masking //each bit represents if the sampler is dirty if (psSamplers.Count > 0) { //create mask CodeMemberField field = new CodeMemberField(typeof(int), "psm"); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, "Pixel Sampler dirty state bitmask"); } if (vsSamplers.Count > 0) { //create mask CodeMemberField field = new CodeMemberField(typeof(int), "vsm"); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, "Vertex Sampler dirty state bitmask"); } //add the sampler members foreach (SharedSampler ss in allSamplers.Values) { CodeMemberField field = new CodeMemberField(typeof(Xen.Graphics.State.TextureSamplerState), "ts" + ss.Index); field.Attributes = MemberAttributes.Private | MemberAttributes.Family; add(field, string.Format("Sampler state for '{0} {1}'", Common.ToUpper(ss.SamplerDetails.Type), ss.SamplerDetails.Name)); } //add the texture members for (int i = 0; i < textures.Length; i++) { TextureAssociation tex = textures[i]; if (tex.PsSamplers.Count > 0 || tex.VsSamplers.Count > 0) //only add if they are used { CodeMemberField field = new CodeMemberField(Common.GetTextureType(tex.Texture.Type), "tx" + i); field.Attributes = MemberAttributes.Private | MemberAttributes.Family; add(field, string.Format("Bound texture for '{0} {1}'", tex.Texture.Type, tex.Texture.Name)); } } //create the properties for the sampler states GenerateProperties(shader, add); GenerateNameIds(shader, add); }
public override void AddMembers(IShaderDom shader, Action <CodeTypeMember, string> add, Platform platform) { //create static ID's for the registers if (platform != Platform.Both) { return; } //static id's for named attributes for (int i = 0; i < attributeNames.Count; i++) { //static id of this attribute name CodeMemberField field = new CodeMemberField(typeof(int), attributeFields[i].FieldName); field.Attributes = MemberAttributes.Static | MemberAttributes.Private | MemberAttributes.Final; add(field, string.Format("Name ID for '{0}'", attributeNames[i])); CreateConstantSetters(shader, add, attributeNames[i], attributeFields[i], attributeArrayFields[i]); } //add the semantic change IDs foreach (SemanticMapping mapping in semanticMapping) { for (int i = 0; i < mapping.ChangeRefs.Length; i++) { CodeMemberField field = new CodeMemberField(typeof(int), mapping.ChangeRefs[i].FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, i != 0 ? null : string.Format("Change ID for Semantic bound attribute '{0}'", mapping.Register.Name)); } } //add the global refs and ids //add the global change IDs foreach (GlobalAttribute global in globals) { //global ID staics CodeMemberField field = new CodeMemberField(typeof(int), global.GlobalIdRef.FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final | MemberAttributes.Static; add(field, string.Format("TypeID for global attribute '{0} {1}'", global.Register.Type, global.Register.Name)); for (int i = 0; i < global.ChangeRefs.Length; i++) { field = new CodeMemberField(typeof(int), global.ChangeRefs[i].FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, i != 0 ? null : string.Format("Change ID for global attribute '{0} {1}'", global.Register.Type, global.Register.Name)); } } }
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 AddSetAttribute(IShaderDom shader, Action <CodeStatement> add, Type type) { List <CodeStatement> statements; if (attributeAssignment.TryGetValue(type, out statements)) { foreach (CodeStatement statement in statements) { add(statement); } } }
public override void AddStaticGraphicsInit(IShaderDom shader, Action <CodeStatement, string> add) { //initalise the static UIDs foreach (SharedSampler ss in allSamplers.Values) { //set the uid for the sampler CodeExpression uid = new CodeFieldReferenceExpression(shader.ShaderClassEx, "sid" + ss.Index); CodeExpression call = new CodeMethodInvokeExpression( new CodeMethodReferenceExpression(shader.ShaderSystemRef, "GetNameUniqueID"), new CodePrimitiveExpression(ss.SamplerDetails.Name)); CodeStatement assign = new CodeAssignStatement(uid, call); add(assign, null); } //and all the textures for (int i = 0; i < textures.Length; i++) { TextureAssociation tex = textures[i]; if (tex.PsSamplers.Count > 0 || tex.VsSamplers.Count > 0) { //set the uid for the sampler CodeExpression uid = new CodeFieldReferenceExpression(shader.ShaderClassEx, "tid" + i); CodeExpression call = new CodeMethodInvokeExpression( new CodeMethodReferenceExpression(shader.ShaderSystemRef, "GetNameUniqueID"), new CodePrimitiveExpression(tex.Texture.Name)); if (tex.IsGlobal) { //slightly differnet for globals. Need to call generic getter for the global index call = new CodeMethodInvokeExpression( new CodeMethodReferenceExpression(shader.ShaderSystemRef, "GetGlobalUniqueID", new CodeTypeReference(Common.GetTextureType(tex.Texture.Type))), new CodePrimitiveExpression(tex.Texture.Name)); } CodeStatement assign = new CodeAssignStatement(uid, call); add(assign, null); } } }
public override void AddChangedCondition(IShaderDom shader, Action <CodeExpression> add) { if (psSamplers.Count > 0) { //add the PS sampler mask CodeExpression mask = new CodeFieldReferenceExpression(shader.Instance, "psm"); add(new CodeBinaryOperatorExpression(mask, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(0))); } if (vsSamplers.Count > 0) { //add the VS sampler mask CodeExpression mask = new CodeFieldReferenceExpression(shader.Instance, "vsm"); add(new CodeBinaryOperatorExpression(mask, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(0))); } }
public override void AddReadonlyMembers(IShaderDom shader, Action <CodeTypeMember, string> add, Platform platform) { if (platform != Platform.Both) { return; } for (int i = 0; i < attributeNames.Count; i++) { //if it's an array, it needs an array object... Register reg; Type dataType; if (ExtractRegType(attributeNames[i], out reg, out dataType) && reg.ArraySize != -1) { //get the interface type for the field. Type interfaceType = typeof(Xen.Graphics.ShaderSystem.Constants.IArray <float>).GetGenericTypeDefinition(); interfaceType = interfaceType.MakeGenericType(dataType); CodeMemberField field = new CodeMemberField(interfaceType, this.attributeArrayFields[i].FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, string.Format("Array wrapper for '{0} {1}[{2}]'", reg.Type, attributeNames[i], reg.ArraySize)); } } //add the global array IDs (if there are any) foreach (GlobalAttribute global in globals) { for (int i = 0; i < global.ChangeRefs.Length; i++) { //if it's an array, also add the array objects if (global.Register.ArraySize != -1) { Type interfaceType = typeof(Xen.Graphics.ShaderSystem.Constants.IArray <float>).GetGenericTypeDefinition(); interfaceType = interfaceType.MakeGenericType(global.Type); //arrays are stored differently.. eg as IArray<Matrix> CodeMemberField field = new CodeMemberField(interfaceType, global.ArrayRefs[i].FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, i != 0 ? null : string.Format("Array access for global attribute '{0} {1}[{2}]'", global.Register.Type, global.Register.Name, global.Register.ArraySize)); } } } }
public override void AddChangedCondition(IShaderDom shader, Action <CodeExpression> add) { if (vsReg.FloatRegisterCount > 0) { add(new CodeFieldReferenceExpression(shader.VertexShaderRegistersRef, "change")); } if (psReg.FloatRegisterCount > 0) { add(new CodeFieldReferenceExpression(shader.PixelShaderRegistersRef, "change")); } if (vsPreReg != null && vsPreReg.FloatRegisterCount > 0) { add(new CodeFieldReferenceExpression(shader.VertexPreShaderRegistersRef, "change")); } if (psPreReg != null && psPreReg.FloatRegisterCount > 0) { add(new CodeFieldReferenceExpression(shader.PixelPreShaderRegistersRef, "change")); } }
public override void AddMembers(IShaderDom shader, Action <CodeTypeMember, string> add, Platform platform) { //add pixel and static vertex shaders if (platform != Platform.Both) { return; } CodeMemberField field = new CodeMemberField(typeof(VertexShader), shader.VertexShaderRef.FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final | MemberAttributes.Static; add(field, "Static vertex shader instance"); //ps field = new CodeMemberField(typeof(PixelShader), shader.PixelShaderRef.FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final | MemberAttributes.Static; add(field, "Static pixel shader instance"); }
private void ProcessConstants(IShaderDom shader) { RegisterSet registers = asm.CommonRegisters; for (int i = 0; i < registers.RegisterCount; i++) { Register reg = registers.GetRegister(i); if (reg.Category == RegisterCategory.Float4 || reg.Category == RegisterCategory.Boolean) { if (reg.Semantic == null) this.attributeNames.Add(reg.Name); else ExtractSemantic(shader, reg); } else if (reg.Semantic != null && reg.Category != RegisterCategory.Texture && reg.Category != RegisterCategory.Sampler) { throw new CompileException(string.Format("Error parsing semantic for '{1} {0}'. Semantic bound types may only be processed as Float4, Texture or Sampler registers", reg.Name, reg.Type)); } } }
public override void AddStaticGraphicsInit(IShaderDom shader, Action <CodeStatement, string> add) { //initalise the static ID's for (int i = 0; i < attributeNames.Count; i++) { //call state.GetNameUniqueID() CodeExpression call = new CodeMethodInvokeExpression( new CodeMethodReferenceExpression(shader.ShaderSystemRef, "GetNameUniqueID"), new CodePrimitiveExpression(attributeNames[i])); CodeStatement assign = new CodeAssignStatement(attributeFields[i], call); add(assign, null); } //setup the TypeIDs for global attributes //eg: //ShadowShaderBlend.g_id0 = state.GetGlobalUniqueID<Microsoft.Xna.Framework.Matrix[]>("shadowMapProjection"); foreach (GlobalAttribute global in globals) { //call state.GetGlobalUniqueID() Type type = global.Type; if (global.Register.ArraySize != -1) { type = type.MakeArrayType(); } CodeExpression call = new CodeMethodInvokeExpression( new CodeMethodReferenceExpression(shader.ShaderSystemRef, "GetGlobalUniqueID", new CodeTypeReference(type)), new CodePrimitiveExpression(global.Register.Name)); CodeStatement assign = new CodeAssignStatement(global.GlobalIdRef, call); add(assign, null); } }
public override void AddMembers(IShaderDom shader, Action <CodeTypeMember, string> add, Platform platform) { if (platform != Platform.Both) { return; } //add change values for boolean registers if (vsReg.BooleanRegisterCount > 0) { CodeMemberField field = new CodeMemberField(typeof(bool), shader.VertexShaderBooleanRegistersChangedRef.FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, null); } //now the PS if (psReg.BooleanRegisterCount > 0) { CodeMemberField field = new CodeMemberField(typeof(bool), shader.PixelShaderBooleanRegistersChangedRef.FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, 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 AddReadonlyMembers(IShaderDom shader, Action <CodeTypeMember, string> add, Platform platform) { Platform?writePlatform = null; if (this.platform == Platform.Both) { //shader is being built for both PC and xbox if (platform != Platform.Both) // writing system specific shader { writePlatform = platform; } } else { //shader is being built for just one platform writePlatform = this.platform; } if (writePlatform == null) { return; } if (writePlatform.Value == Platform.Windows) { //write windows WriteBytes(shader, shader.VertexShaderBytesRef.FieldName, this.vsBytesPc, add, shader.CompileDirectives, true, false); WriteBytes(shader, shader.PixelShaderBytesRef.FieldName, this.psBytesPc, add, shader.CompileDirectives, false, false); } else { //write xbox WriteBytes(shader, shader.VertexShaderBytesRef.FieldName, this.vsBytesXbox, add, shader.CompileDirectives, true, true); WriteBytes(shader, shader.PixelShaderBytesRef.FieldName, this.psBytesXbox, add, shader.CompileDirectives, false, true); } }
public virtual void AddStaticGraphicsInit(IShaderDom shader, Action<CodeStatement, string> add) { }
public virtual void AddWarm(IShaderDom shader, Action<CodeStatement, string> add) { }
//extract pairs of asmlistings / code registers private void ComputeListings(IShaderDom shader) { List<KeyValuePair<AsmListing, CodeExpression>> listings = new List<KeyValuePair<AsmListing, CodeExpression>>(); if (asm.VertexShader != null) listings.Add(new KeyValuePair<AsmListing,CodeExpression>(asm.VertexShader, shader.VertexShaderRegistersRef)); if (asm.PixelShader != null) listings.Add(new KeyValuePair<AsmListing,CodeExpression>(asm.PixelShader, shader.PixelShaderRegistersRef)); if (asm.BlendingShader != null) listings.Add(new KeyValuePair<AsmListing, CodeExpression>(asm.BlendingShader, shader.BlendShaderRegistersRef)); if (asm.InstancingShader != null) listings.Add(new KeyValuePair<AsmListing, CodeExpression>(asm.InstancingShader, shader.InstancingShaderRegistersRef)); this.listingRegisters = listings.ToArray(); }
public override void AddReadonlyMembers(IShaderDom shader, Action<CodeTypeMember, string> add, Platform platform) { if (platform != Platform.Both) return; /* for (int i = 0; i < attributeNames.Count; i++) { //if it's an array, it needs an array object... Register reg; Type dataType; if (ExtractRegType(attributeNames[i], out reg, out dataType) && reg.ArraySize != -1) { //get the interface type for the field. Type interfaceType = typeof(Xen.Graphics.ShaderSystem.Constants.IArray<float>).GetGenericTypeDefinition(); interfaceType = interfaceType.MakeGenericType(dataType); CodeMemberField field = new CodeMemberField(interfaceType, this.attributeArrayFields[i].FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, string.Format("Array wrapper for '{0} {1}[{2}]'", reg.Type, attributeNames[i], reg.ArraySize)); } } //add the global array IDs (if there are any) foreach (GlobalAttribute global in globals) { for (int i = 0; i < global.ChangeRefs.Length; i++) { //if it's an array, also add the array objects if (global.Register.ArraySize != -1) { Type interfaceType = typeof(Xen.Graphics.ShaderSystem.Constants.IArray<float>).GetGenericTypeDefinition(); interfaceType = interfaceType.MakeGenericType(global.Type); //arrays are stored differently.. eg as IArray<Matrix> CodeMemberField field = new CodeMemberField(interfaceType, global.ArrayRefs[i].FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, i != 0 ? null : string.Format("Array access for global attribute '{0} {1}[{2}]'", global.Register.Type, global.Register.Name, global.Register.ArraySize)); } } } */ }
public override void AddChangedCondition(IShaderDom shader, Action<CodeExpression> add) { if (vsReg.FloatRegisterCount > 0) add(shader.VertexShaderRegistersChangedRef); if (psReg.FloatRegisterCount > 0) add(shader.PixelShaderRegistersChangedRef); }
public override void AddConstructor(IShaderDom shader, Action <CodeStatement> add) { //set the semantic change IDs to -1 foreach (SemanticMapping mapping in semanticMapping) { for (int i = 0; i < mapping.ChangeRefs.Length; i++) { CodeAssignStatement assign = new CodeAssignStatement(mapping.ChangeRefs[i], new CodePrimitiveExpression(-1)); add(assign); } } //init the array attributes for (int i = 0; i < attributeNames.Count; i++) { //if it's an array, it needs an array object... Register reg; Type dataType; if (ExtractRegType(attributeNames[i], out reg, out dataType) && reg.ArraySize != -1) { //things get a bit funky here. //if the array is used by more than one register set, it must be wrapped up in a 'DualArray' //so a call to 'SetValue' on the array gets passed to both copies. //This can occur if both the vertex and pixel shader access a constant array, or a preshader, etc. Type dualType = typeof(Xen.Graphics.ShaderSystem.Constants.DualArray <float>).GetGenericTypeDefinition(); dualType = dualType.MakeGenericType(dataType); //this.attributeArrayFields[i].FieldName CodeExpression initExpression = null; Type arrayType = GetArrayType(reg); foreach (KeyValuePair <AsmListing, CodeExpression> listing in listingRegisters) { Register sreg; RegisterSet registers = listing.Key.RegisterSet; CodeExpression registersRef = listing.Value; if (registers.TryGetRegister(reg.Name, out sreg)) { CodeExpression create; create = new CodeObjectCreateExpression(arrayType, registersRef, //vreg new CodePrimitiveExpression(sreg.Index), new CodePrimitiveExpression(sreg.Size)); if (initExpression == null) { initExpression = create; } else { //darn. wrap in a dual array. initExpression = new CodeObjectCreateExpression( dualType, create, initExpression); } } } CodeAssignStatement assign = new CodeAssignStatement(this.attributeArrayFields[i], initExpression); add(assign); } } //set the global change IDs to -1 (unless it's an array)... foreach (GlobalAttribute global in globals) { 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) && sreg.Category != RegisterCategory.Boolean) { CodeAssignStatement assign = new CodeAssignStatement(global.ChangeRefs[changeRefIndex], new CodePrimitiveExpression(-1)); add(assign); //arrays require the array wrapper to be initalised if (global.Register.ArraySize != -1) { //arrays are stored differently.. eg as IArray<Matrix> //eg: //new Xen.Graphics.ShaderSystem.Constants.Matrix4Array(this.vreg, 217, 4); Type arrayType = GetArrayType(global.Register); CodeExpression create; create = new CodeObjectCreateExpression(arrayType, registersRef, //vreg new CodePrimitiveExpression(sreg.Index), new CodePrimitiveExpression(sreg.Size)); assign = new CodeAssignStatement(global.ArrayRefs[changeRefIndex], create); add(assign); } changeRefIndex++; } } } }
public virtual void Setup(IShaderDom shader) { }
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); }
//add the member fields public override void SetupMembers(IShaderDom shader) { ComputeListings(shader); ProcessConstants(shader); for (int i = 0; i < attributeNames.Count; i++) { //create a field ref for the static that will be created //these are used to assign the value using 'SetAttribute' CodeFieldReferenceExpression field = new CodeFieldReferenceExpression(shader.ShaderClassEx, string.Format("cid{0}",i)); this.attributeFields.Add(field); //if it's an array, an array object needs to be created too. Create the ref to it now field = null; Register reg; Type type;//unused if (ExtractRegType(attributeNames[i], out reg, out type) && reg.ArraySize != -1) field = new CodeFieldReferenceExpression(shader.Instance, string.Format("ca{0}", i)); attributeArrayFields.Add(field);//may be null. } }
public override void AddBindBegin(IShaderDom shader, Action<CodeStatement, string> add) { CodeExpression devIndex = new CodeFieldReferenceExpression(shader.ShaderSystemRef, "DeviceUniqueIndex"); //if extending in some way, then don't compare the devIndex to the class static, compare it to the virtual g uid CodeExpression classDevIndex = GraphicsDeviceUID; CodeExpression devChanged = new CodeBinaryOperatorExpression(devIndex, CodeBinaryOperatorType.IdentityInequality, classDevIndex); CodeStatement checkChanged = new CodeConditionStatement(devChanged, ETS(new CodeMethodInvokeExpression(Instance, "WarmShader", ShaderSystemRef)), // Call warm new CodeAssignStatement(BindShaderInstanceChange, new CodePrimitiveExpression(true))); add(checkChanged, "if the device changed, call Warm()"); //bind the shaders if tc is true (type has changed) //and that 'owner' is true (owns the shaders) //if (((tc && this.owner) // == true)) //{ // state.SetShaders(ShadowShader.vs, ShadowShader.ps); //} //for classes that are either extendable or extended from another shader, //then the SetShaders call is put into a virtual method that is overridden. }
public override void AddStaticGraphicsInit(IShaderDom shader, Action<CodeStatement, string> add) { //assign the static graphics ID CodeExpression deviceId = new CodePropertyReferenceExpression(ShaderSystemRef, "DeviceUniqueIndex"); CodeStatement assign = new CodeAssignStatement(gdIndexRef, deviceId); add(assign, "set the graphics ID"); assign = new CodeAssignStatement(new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "GraphicsID"), deviceId); add(assign, null); }
public override void AddMembers(IShaderDom shader, Action<CodeTypeMember, string> add, Platform platform) { if (platform != Platform.Both) return; //static graphics ID CodeMemberField field = new CodeMemberField(typeof(int),gdIndexRef.FieldName); field.Attributes = MemberAttributes.Static | MemberAttributes.Final | MemberAttributes.Private; add(field,"Static graphics ID"); }
public override void AddConstructor(IShaderDom shader, Action<CodeStatement> add) { //set the semantic change IDs to -1 foreach (SemanticMapping mapping in semanticMapping) { for (int i = 0; i < mapping.ChangeRefs.Length; i++) { CodeAssignStatement assign = new CodeAssignStatement(mapping.ChangeRefs[i], new CodePrimitiveExpression(-1)); add(assign); } } //set the global change IDs to -1 foreach (GlobalAttribute global in globals) { 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) && sreg.Category != RegisterCategory.Boolean) { CodeAssignStatement assign = new CodeAssignStatement(global.ChangeRefs[changeRefIndex], new CodePrimitiveExpression(-1)); add(assign); changeRefIndex++; } } } }
public virtual void AddStaticConstructor(IShaderDom shader, Action<CodeStatement> add) { }
public virtual void AddReadonlyMembers(IShaderDom shader, Action<CodeTypeMember, string> add, Platform platform) { }
public override void AddSetAttribute(IShaderDom shader, Action<CodeStatement> add, Type type) { List<CodeStatement> statements; if (attributeAssignment.TryGetValue(type, out statements)) { foreach (CodeStatement statement in statements) { add(statement); } } }
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 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))); } } } } }
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++; } } } } }
public override void AddReadonlyMembers(IShaderDom shader, Action <CodeTypeMember, string> add, Platform platform) { if (platform != Platform.Both) { return; } if (vsReg.FloatRegisterCount > 0) { //create the vertex registers CodeMemberField field = new CodeMemberField(typeof(ConstantArray), shader.VertexShaderRegistersRef.FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, "Vertex shader register storage"); } //and the PS if (psReg.FloatRegisterCount > 0) { //create the pixel registers CodeMemberField field = new CodeMemberField(typeof(ConstantArray), shader.PixelShaderRegistersRef.FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, "Pixel shader register storage"); } //now the Preshaders if (vsPreReg != null && vsPreReg.FloatRegisterCount > 0) { //create the vertex preshader registers CodeMemberField field = new CodeMemberField(typeof(ConstantArray), shader.VertexPreShaderRegistersRef.FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, "Vertex preshader register storage"); } //and the PS if (psPreReg != null && psPreReg.FloatRegisterCount > 0) { //create the pixel preshader registers CodeMemberField field = new CodeMemberField(typeof(ConstantArray), shader.PixelPreShaderRegistersRef.FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, "Pixel preshader register storage"); } //now do the boolean registers if (vsReg.BooleanRegisterCount > 0) { //create the vertex boolean registers CodeMemberField field = new CodeMemberField(typeof(bool[]), shader.VertexShaderBooleanRegistersRef.FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, "Vertex shader boolean register storage"); } //now the PS if (psReg.BooleanRegisterCount > 0) { //create the vertex boolean registers CodeMemberField field = new CodeMemberField(typeof(bool[]), shader.PixelShaderBooleanRegistersRef.FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, "Pixel shader boolean register storage"); } //add any statics created foreach (KeyValuePair <string, CodeExpression> array in staticArrays) { CodeMemberField field = new CodeMemberField(typeof(float[]), array.Key); field.Attributes = MemberAttributes.Private | MemberAttributes.Final | MemberAttributes.Static; field.InitExpression = array.Value; add(field, "Register default values"); } }
public virtual void SetupMembers(IShaderDom shader) { }
public override void AddMembers(IShaderDom shader, Action<CodeTypeMember, string> add, Platform platform) { //create static ID's for the registers if (platform != Platform.Both) return; //static id's for named attributes for (int i = 0; i < attributeNames.Count; i++) { //static id of this attribute name CodeMemberField field = new CodeMemberField(typeof(int), attributeFields[i].FieldName); field.Attributes = MemberAttributes.Static | MemberAttributes.Private | MemberAttributes.Final; add(field, string.Format("Name ID for '{0}'", attributeNames[i])); CreateConstantSetters(shader, add, attributeNames[i], attributeFields[i], attributeArrayFields[i]); } //add the semantic change IDs foreach (SemanticMapping mapping in semanticMapping) { for (int i = 0; i < mapping.ChangeRefs.Length; i++) { CodeMemberField field = new CodeMemberField(typeof(int), mapping.ChangeRefs[i].FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, i != 0 ? null : string.Format("Change ID for Semantic bound attribute '{0}'", mapping.Register.Name)); } } //add the global refs and ids //add the global change IDs foreach (GlobalAttribute global in globals) { //global ID staics CodeMemberField field = new CodeMemberField(typeof(int), global.GlobalIdRef.FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final | MemberAttributes.Static; add(field, string.Format("TypeID for global attribute '{0} {1}'", global.Register.Type, global.Register.Name)); for (int i = 0; i < global.ChangeRefs.Length; i++) { field = new CodeMemberField(typeof(int), global.ChangeRefs[i].FieldName); field.Attributes = MemberAttributes.Private | MemberAttributes.Final; add(field, i != 0 ? null : string.Format("Change ID for global attribute '{0} {1}'", global.Register.Type, global.Register.Name)); } } }
public virtual void AddChangedCondition(IShaderDom shader, Action<CodeExpression> add) { }
public virtual void AddSetAttribute(IShaderDom shader, Action<CodeStatement> add, Type type) { }
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 virtual void AddBindFinal(IShaderDom shader, Action<CodeStatement, string> add) { }
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++; } } } } }
//pull a semantic bound register private void ExtractSemantic(IShaderDom shader, Register reg) { string semantic = reg.Semantic; Type dataType = null; switch (reg.Rank) { case RegisterRank.FloatNx1: { switch (reg.Type) { case "float": case "float1"://? dataType = typeof(Single); break; case "float2": dataType = typeof(Vector2); break; case "float3": dataType = typeof(Vector3); break; case "float4": dataType = typeof(Vector4); break; } } break; case RegisterRank.FloatNx2: case RegisterRank.FloatNx3: case RegisterRank.FloatNx4: dataType = typeof(Matrix); break; case RegisterRank.IntNx1: case RegisterRank.IntNx2: case RegisterRank.IntNx3: case RegisterRank.IntNx4: { //ints are almost always mapped to floats for semantic bound types (EG vertex count) //since the register category has been validated to Float4, this is the case here switch (reg.Type) { case "int": case "int1"://? dataType = typeof(Single); break; case "int2": dataType = typeof(Vector2); break; case "int3": dataType = typeof(Vector3); break; case "int4": dataType = typeof(Vector4); break; } } break; case RegisterRank.Bool: dataType = typeof(Single); break; } if (reg.Category == RegisterCategory.Boolean) dataType = typeof(bool); if (semantic.Length == 6 && semantic.Equals("global", StringComparison.InvariantCultureIgnoreCase)) { //special case global value. if (dataType == null) throw new CompileException(string.Format("Error parsing semantic for '{0}'. Global values of type '{1}' are not supported.",reg.Name, reg.Type)); GlobalAttribute global = new GlobalAttribute(); global.Register = reg; global.Type = dataType; global.GlobalIdRef = new CodeFieldReferenceExpression(shader.ShaderClassEx, string.Format("gid{0}", globals.Count)); List<CodeFieldReferenceExpression> globalRefs = new List<CodeFieldReferenceExpression>(); List<CodeFieldReferenceExpression> arrayRefs = new List<CodeFieldReferenceExpression>(); foreach (KeyValuePair<AsmListing, CodeExpression> listing in listingRegisters) { Register sreg; RegisterSet registers = listing.Key.RegisterSet; CodeExpression registersRef = listing.Value; if (registers.TryGetRegister(reg.Name, out sreg)) { if (sreg.Category != RegisterCategory.Boolean) { string refId = string.Format("gc{0}", globalRefCount); globalRefs.Add(new CodeFieldReferenceExpression(shader.Instance, refId)); globalRefCount++; } } } global.ChangeRefs = globalRefs.ToArray(); globals.Add(global); return; } //special case bool isBlendMatrices = semantic.Equals("BLENDMATRICES", StringComparison.InvariantCultureIgnoreCase); if (reg.ArraySize != -1 && !isBlendMatrices) { //INVALID. EXTERMINATE. throw new CompileException(string.Format("Shader attribute '{0}' is defined as an array and has a semantic '{1}'. Semantics other than 'BLENDMATRICES' and 'GLOBAL' are invalid for Array types.", reg.Name, reg.Semantic)); } bool isTranspose = semantic.Length > 9 && semantic.EndsWith("transpose", StringComparison.InvariantCultureIgnoreCase); if (isTranspose) semantic = semantic.Substring(0, semantic.Length - 9); SemanticType? dataSemanticType = null; foreach (SemanticType semanticType in semanticTypes) { if (semanticType.Type == dataType && semanticType.Mapping.Equals(semantic, StringComparison.InvariantCultureIgnoreCase)) { dataSemanticType = semanticType; break; } } if (dataSemanticType == null) { //INVALID. EXTERMINATE. throw new CompileException(string.Format("Shader attribute '{0}' has unrecognised semantic '{1}'.", reg.Name, reg.Semantic)); } //create the mapping... SemanticMapping mapping = new SemanticMapping(); mapping.Register = reg; mapping.Type = dataSemanticType.Value; //figure out how often this semantic is used.. List<CodeFieldReferenceExpression> changeRefs = new List<CodeFieldReferenceExpression>(); foreach (KeyValuePair<AsmListing, CodeExpression> listing in listingRegisters) { Register sreg; RegisterSet registers = listing.Key.RegisterSet; CodeExpression registersRef = listing.Value; if (registers.TryGetRegister(reg.Name, out sreg)) { string changeId = string.Format("sc{0}", semanticMappingRefCount++); changeRefs.Add(new CodeFieldReferenceExpression(shader.Instance, changeId)); } } mapping.ChangeRefs = changeRefs.ToArray(); this.semanticMapping.Add(mapping); }
public override void AddReadonlyMembers(IShaderDom shader, Action<CodeTypeMember, string> add, Platform platform) { if (platform == Platform.Both) add(vsInputField, "array storing vertex usages, and element indices"); }
private bool ExtractAssignmentForExtenionBlock(CodeStatement assign, IShaderDom shader, AsmListing asmListing) { //special case, blending or instancing assignments need to go in an if block. if (asmListing == asm.BlendingShader) { blendExtensionAssignments.Add(assign); return true; } if (asmListing == asm.InstancingShader) { instancingExtensionAssignments.Add(assign); return true; } return false; }
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"); add(validateDeviceId, "Setup the shader"); }
public CodeStatement GetBlendDirectAssignment(IShaderDom dom) { foreach (SemanticMapping mapping in semanticMapping) { if (mapping.Register.Name == ShaderExtensionGenerator.blendMatricesName) { //call the direct blend matrix setter var invokeSet = new CodeMethodInvokeExpression(dom.ShaderSystemRef, "SetBlendMatricesDirect", new CodeFieldReferenceExpression(dom.EffectRef, "vsb_c"), Ref(mapping.ChangeRefs[0])); //change |= ...; return new CodeAssignStatement(dom.BindShaderInstanceChange, new CodeBinaryOperatorExpression(dom.BindShaderInstanceChange, CodeBinaryOperatorType.BitwiseOr, invokeSet)); } } return null; }
public override void AddBindFinal(IShaderDom shader, Action<CodeStatement, string> add) { //at the end of the bind, set call SetEffect. CodeExpression setShaders = new CodeMethodInvokeExpression( ShaderSystemRef, "SetEffect", new CodeThisReferenceExpression(), new CodeDirectionExpression(FieldDirection.Ref, EffectRef), shader.ShaderExtensionMode); CodeExpression condition = new CodeBinaryOperatorExpression(shader.BindShaderInstanceChange, CodeBinaryOperatorType.BitwiseOr, shader.ExtensionModeChange); add(new CodeConditionStatement(condition, ETS(setShaders)), "Finally, bind the effect"); }
public override void AddStaticGraphicsInit(IShaderDom shader, Action<CodeStatement, string> add) { //initalise the static ID's for (int i = 0; i < attributeNames.Count; i++) { //call state.GetNameUniqueID() CodeExpression call = new CodeMethodInvokeExpression( new CodeMethodReferenceExpression(shader.ShaderSystemRef, "GetNameUniqueID"), new CodePrimitiveExpression(attributeNames[i])); CodeStatement assign = new CodeAssignStatement(attributeFields[i], call); add(assign, null); } //setup the TypeIDs for global attributes //eg: //ShadowShaderBlend.g_id0 = state.GetGlobalUniqueID<Microsoft.Xna.Framework.Matrix[]>("shadowMapProjection"); foreach (GlobalAttribute global in globals) { //call state.GetGlobalUniqueID() Type type = global.Type; if (global.Register.ArraySize != -1) type = type.MakeArrayType(); CodeExpression call = new CodeMethodInvokeExpression( new CodeMethodReferenceExpression(shader.ShaderSystemRef, "GetGlobalUniqueID", new CodeTypeReference(type)), new CodePrimitiveExpression(global.Register.Name)); CodeStatement assign = new CodeAssignStatement(global.GlobalIdRef, call); add(assign, null); } }