public SourceDom(SourceShader shader, string baseNamespace, CodeDomProvider provider) { this.codeProvider = provider; this.directives = new CompileDirectives(provider); this.source = shader; this.baseNamespace = baseNamespace; string namespaceName = baseNamespace; if (!shader.UseParentNamespace) { namespaceName += "." + Common.ToUpper(Path.GetFileNameWithoutExtension(source.FileName)); } this.outputNamespace = namespaceName; HlslTechnique[] techniques = shader.GetAllTechniques(); if (shader.DefinePlatform) { //create a copy for each platform //xbox first this.rootPcNamespace = new CodeNamespace(namespaceName); this.rootXboxNamespace = new CodeNamespace(namespaceName); for (int i = 0; i < techniques.Length; i++) { //build the PC shaders if ((techniques[i].Platform & Platform.Windows) == Platform.Windows) { ShaderDom dom = new ShaderDom(source, techniques[i].Name, Platform.Windows, directives); this.rootPcNamespace.Types.Add(dom.CodeTypeDeclaration); } } for (int i = 0; i < techniques.Length; i++) { //build the xbox shaders if ((techniques[i].Platform & Platform.Xbox) == Platform.Xbox) { ShaderDom dom = new ShaderDom(source, techniques[i].Name, Platform.Xbox, directives); this.rootXboxNamespace.Types.Add(dom.CodeTypeDeclaration); } } } else { this.rootNamespace = new CodeNamespace(namespaceName); for (int i = 0; i < techniques.Length; i++) { //build the combined pc / xbox shaders if ((techniques[i].Platform & Platform.Both) == Platform.Both) { ShaderDom dom = new ShaderDom(source, techniques[i].Name, Platform.Both, directives); this.rootNamespace.Types.Add(dom.CodeTypeDeclaration); } } } }
public static CodeExpression ToArray <T>(T[] data, CompileDirectives compileDirectives) { CodeExpression[] exp = new CodeExpression[data.Length]; for (int i = 0; i < exp.Length; i++) { exp[i] = new CodePrimitiveExpression(data[i]); } CodeArrayCreateExpression array = new CodeArrayCreateExpression(typeof(T[]), exp); if (!compileDirectives.IsCSharp) { return(array); } //optimize the array a bit.. so it's stored in a smaller space StringBuilder output = new StringBuilder(data.Length * 8); CodeGeneratorOptions options = new CodeGeneratorOptions(); options.IndentString = ""; using (TextWriter writer = new StringWriter(output)) compileDirectives.CodeDomProvider.GenerateCodeFromExpression(array, writer, options); output.Replace(Environment.NewLine, ""); return(new CodeSnippetExpression(output.ToString())); }
public SourceDom(SourceShader shader, string baseNamespace, CodeDomProvider provider) { this.codeProvider = provider; this.directives = new CompileDirectives(provider); this.source = shader; this.baseNamespace = baseNamespace; string namespaceName = baseNamespace; if (!shader.UseParentNamespace) namespaceName += "." + Common.ToUpper(Path.GetFileNameWithoutExtension(source.FileName)); this.outputNamespace = namespaceName; HlslTechnique[] techniques = shader.GetAllTechniques(); if (shader.DefinePlatform) { //create a copy for each platform //xbox first this.rootPcNamespace = new CodeNamespace(namespaceName); this.rootXboxNamespace = new CodeNamespace(namespaceName); for (int i = 0; i < techniques.Length; i++) { //build the PC shaders if ((techniques[i].Platform & Platform.Windows) == Platform.Windows) { ShaderDom dom = new ShaderDom(source, techniques[i].Name, Platform.Windows, directives); this.rootPcNamespace.Types.Add(dom.CodeTypeDeclaration); } } for (int i = 0; i < techniques.Length; i++) { //build the xbox shaders if ((techniques[i].Platform & Platform.Xbox) == Platform.Xbox) { ShaderDom dom = new ShaderDom(source, techniques[i].Name, Platform.Xbox, directives); this.rootXboxNamespace.Types.Add(dom.CodeTypeDeclaration); } } } else { this.rootNamespace = new CodeNamespace(namespaceName); for (int i = 0; i < techniques.Length; i++) { //build the combined pc / xbox shaders if ((techniques[i].Platform & Platform.Both) == Platform.Both) { ShaderDom dom = new ShaderDom(source, techniques[i].Name, Platform.Both, directives); this.rootNamespace.Types.Add(dom.CodeTypeDeclaration); } } } }
//compresses a vector4 array down by removing the zero elements on the start/end (which is often A LOT) private CodeExpression InitaliseConstants(int count, Vector4[] values, CompileDirectives directives, out int offset) { offset = 0; if (count > values.Length) { count = values.Length; } if (values == null) { return(null); } int maxNonZero = -1; int minNonZero = int.MaxValue; for (int i = 0; i < count; i++) { if (values[i] != Vector4.Zero) { maxNonZero = Math.Max(maxNonZero, i); minNonZero = Math.Min(minNonZero, i); } } if (maxNonZero >= minNonZero) { //sub array float[] array = new float[Math.Min(values.Length, maxNonZero - minNonZero + 1) * 4]; for (int i = minNonZero; i <= maxNonZero; i++) { array[(i - minNonZero) * 4 + 0] = values[i].X; array[(i - minNonZero) * 4 + 1] = values[i].Y; array[(i - minNonZero) * 4 + 2] = values[i].Z; array[(i - minNonZero) * 4 + 3] = values[i].W; } for (int i = 0; i < array.Length; i++) { //remove any NaN values if (float.IsNaN(array[i])) { array[i] = 0; } } offset = minNonZero; return(ShaderBytes.ToArray(array, directives)); } return(null); }
public void GeneratePool(CodeTypeDeclarationCollection typeList, CompileDirectives compileDirectives) { Guid nameExt = Guid.NewGuid(); string name = "pool" + nameExt.ToString("N").ToUpper(); CodeTypeDeclaration type = new CodeTypeDeclaration(name); type.IsClass = true; type.TypeAttributes = System.Reflection.TypeAttributes.Class | System.Reflection.TypeAttributes.Sealed; CodeExpression typeRef = new CodeTypeReferenceExpression(name); typeList.Add(type); int index = 0; //add all the pools to the type. foreach (KeyValuePair <ByteArray, CodeFieldReferenceExpression> item in this.pool) { //create the static member string itemName = "item" + index++; //decompressed in code CodeMethodReferenceExpression decompressMethod = new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(typeof(ConstantArray.ArrayUtils)), "SimpleDecompress"); CodeExpression dataCode = ShaderBytes.ToArray(item.Key.Array, compileDirectives); CodeMemberField field = new CodeMemberField(typeof(byte[]), itemName); field.Attributes = MemberAttributes.Static | MemberAttributes.Public | MemberAttributes.Final; //assign it inline field.InitExpression = new CodeMethodInvokeExpression(decompressMethod, dataCode); type.Members.Add(field); item.Value.FieldName = itemName; item.Value.TargetObject = typeRef; } }
public ShaderDom(SourceShader source, string techniqueName, Platform platform, CompileDirectives directives) { this.domList = new List<DomBase>(); this.domList.Add(this); //add custom dom's this.domList.Add(new ShaderBytes(source, techniqueName, platform)); //needs to be passed to the registers as an interface provider ConstantSetup constantes = new ConstantSetup(source, techniqueName, platform); this.domList.Add(new ShaderRegisters(source, techniqueName, platform, constantes)); this.domList.Add(constantes); this.domList.Add(new ShaderTextures(source, techniqueName, platform)); foreach (DomBase dom in domList) dom.Setup(this); this.techniqueName = techniqueName; this.source = source; this.platform = platform; classDom = new CodeTypeDeclaration(techniqueName); classDom.IsClass = true; classDom.Attributes = MemberAttributes.Final | MemberAttributes.Public; classDom.TypeAttributes = TypeAttributes.Sealed | TypeAttributes.Public | TypeAttributes.Class; //provide a useful comment to the class GenerateClassComment(); if (source.GenerateInternalClass) { classDom.Attributes = MemberAttributes.Final | MemberAttributes.Assembly; classDom.TypeAttributes = TypeAttributes.NestedAssembly | TypeAttributes.Class | TypeAttributes.Sealed; } classDom.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(System.Diagnostics.DebuggerStepThroughAttribute)))); classDom.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(System.CodeDom.Compiler.GeneratedCodeAttribute)),new CodeAttributeArgument(new CodePrimitiveExpression(GetType().Assembly.ManifestModule.Name)),new CodeAttributeArgument(new CodePrimitiveExpression(GetType().Assembly.ManifestModule.ModuleVersionId.ToString())))); classDom.BaseTypes.Add(new CodeTypeReference(typeof(BaseShader))); //add custom base types to the shader //these are defined in TechniqueExtraData AsmTechnique asmTechnique = this.source.GetAsmTechnique(this.techniqueName, this.platform); if (asmTechnique.TechniqueExtraData != null && asmTechnique.TechniqueExtraData.ClassBaseTypes != null) { foreach (string baseTypeName in asmTechnique.TechniqueExtraData.ClassBaseTypes) classDom.BaseTypes.Add(new CodeTypeReference(baseTypeName)); } this.directives = directives; SetupMembers(techniqueName); foreach (DomBase dom in domList) dom.SetupMembers(this); CreateConstructor(); CreateStaticGraphicsInitMethod(); CreateBindMethod(); CreateWarmShaderMethod(); CreateChangedMethod(); CreateVertexInputMethods(); CodeTypeMemberCollection pcMembers = new CodeTypeMemberCollection(); CodeTypeMemberCollection xboxMembers = new CodeTypeMemberCollection(); foreach (DomBase dom in this.domList) { dom.AddMembers(this, delegate(CodeTypeMember s, string c) { Comment(s, c); classDom.Members.Add(s); }, Platform.Both); if (!source.DefinePlatform) // no need for specialization when the platform is constant { dom.AddMembers(this, delegate(CodeTypeMember s, string c) { Comment(s, c); pcMembers.Add(s); }, Platform.Windows); dom.AddMembers(this, delegate(CodeTypeMember s, string c) { Comment(s, c); xboxMembers.Add(s); }, Platform.Xbox); } } foreach (DomBase dom in this.domList) { dom.AddReadonlyMembers(this, delegate(CodeTypeMember s, string c) { CodeTypeMember readonlySnip = directives.CreateReadOnlySnippet(); Comment(readonlySnip ?? s, c); if (readonlySnip != null) classDom.Members.Add(readonlySnip); classDom.Members.Add(s); }, Platform.Both); if (!source.DefinePlatform) { dom.AddReadonlyMembers(this, delegate(CodeTypeMember s, string c) { CodeTypeMember readonlySnip = directives.CreateReadOnlySnippet(); Comment(readonlySnip ?? s, c); if (readonlySnip != null) pcMembers.Add(readonlySnip); pcMembers.Add(s); }, Platform.Windows); dom.AddReadonlyMembers(this, delegate(CodeTypeMember s, string c) { CodeTypeMember readonlySnip = directives.CreateReadOnlySnippet(); Comment(readonlySnip ?? s, c); if (readonlySnip != null) xboxMembers.Add(readonlySnip); xboxMembers.Add(s); }, Platform.Xbox); } } if (pcMembers.Count > 0 || xboxMembers.Count > 0) { //add #if / else blocks classDom.Members.Add(directives.IfXboxStatement); foreach (CodeTypeMember type in xboxMembers) classDom.Members.Add(type); classDom.Members.Add(directives.ElseStatement); foreach (CodeTypeMember type in pcMembers) classDom.Members.Add(type); classDom.Members.Add(directives.EndifStatement); } //finally, create the attribute setters CreateSetAttributeMethod(typeof(float), "SetAttributeImpl", "attribute"); CreateSetAttributeMethod(typeof(Vector2), "SetAttributeImpl", "attribute"); CreateSetAttributeMethod(typeof(Vector3), "SetAttributeImpl", "attribute"); CreateSetAttributeMethod(typeof(Vector4), "SetAttributeImpl", "attribute"); CreateSetAttributeMethod(typeof(Matrix), "SetAttributeImpl", "attribute"); CreateSetAttributeMethod(typeof(bool), "SetAttributeImpl", "attribute"); CreateSetAttributeMethod(typeof(float[]), "SetAttributeImpl", "attribute"); CreateSetAttributeMethod(typeof(Vector2[]), "SetAttributeImpl", "attribute"); CreateSetAttributeMethod(typeof(Vector3[]), "SetAttributeImpl", "attribute"); CreateSetAttributeMethod(typeof(Vector4[]), "SetAttributeImpl", "attribute"); CreateSetAttributeMethod(typeof(Matrix[]), "SetAttributeImpl", "attribute"); CreateSetAttributeMethod(typeof(Xen.Graphics.TextureSamplerState), "SetSamplerStateImpl", "sampler"); CreateSetAttributeMethod(typeof(Texture), "SetTextureImpl", "texture"); CreateSetAttributeMethod(typeof(Texture2D), "SetTextureImpl", "texture"); CreateSetAttributeMethod(typeof(Texture3D), "SetTextureImpl", "texture"); CreateSetAttributeMethod(typeof(TextureCube), "SetTextureImpl", "texture"); }
private CodeExpression GeneratePreShaderFloatDefaults(TechniqueExtraData defaults, RegisterSet registers, int count, CompileDirectives directives, out int offset) { offset = 0; if (count == 0 || defaults == null) { return(null); } Vector4[] constants = new Vector4[count]; bool set = false; foreach (KeyValuePair <string, Vector4[]> entry in defaults.DefaultSingleValues) { Register reg; if (registers.TryGetRegister(entry.Key, out reg)) { if (reg.Category == RegisterCategory.Float4) { for (int i = 0; i < Math.Max(1, reg.ArraySize) && i < entry.Value.Length && i < count - reg.Index; i++) { constants[i + reg.Index] = entry.Value[i]; set = true; } } } } if (!set) { return(null); } return(InitaliseConstants(count, constants, directives, out offset)); }
public ShaderDom(SourceShader source, string techniqueName, Platform platform, CompileDirectives directives) { this.domList = new List <DomBase>(); this.domList.Add(this); this.isShaderExtenable = source.GetShaderExtended(techniqueName); this.shaderExtendsFrom = source.GetShaderExtension(techniqueName); //add custom dom's this.domList.Add(new ShaderBytes(source, techniqueName, platform)); if (shaderExtendsFrom == null) { this.domList.Add(new ShaderRegisters(source, techniqueName, platform)); this.domList.Add(new ConstantSetup(source, techniqueName, platform)); this.domList.Add(new ShaderTextures(source, techniqueName, platform)); this.domList.Add(new Preshaders(source, techniqueName, platform)); } foreach (DomBase dom in domList) { dom.Setup(this); } this.techniqueName = techniqueName; this.source = source; this.platform = platform; classDom = new CodeTypeDeclaration(techniqueName); classDom.IsClass = true; classDom.Attributes = MemberAttributes.Final | MemberAttributes.Public; classDom.TypeAttributes = TypeAttributes.Sealed | TypeAttributes.Public | TypeAttributes.Class; //provide a useful comment to the class GenerateClassComment(); if (source.GenerateInternalClass) { classDom.Attributes = MemberAttributes.Final | MemberAttributes.Assembly; classDom.TypeAttributes = TypeAttributes.NestedAssembly | TypeAttributes.Class | TypeAttributes.Sealed; } if (isShaderExtenable) { classDom.Attributes = MemberAttributes.Public; classDom.TypeAttributes = TypeAttributes.Public | TypeAttributes.Class; if (source.GenerateInternalClass) { classDom.Attributes = MemberAttributes.Assembly; classDom.TypeAttributes = TypeAttributes.NestedAssembly | TypeAttributes.Class; } } classDom.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(System.Diagnostics.DebuggerStepThroughAttribute)))); classDom.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(System.CodeDom.Compiler.GeneratedCodeAttribute)), new CodeAttributeArgument(new CodePrimitiveExpression(GetType().Assembly.ManifestModule.Name)), new CodeAttributeArgument(new CodePrimitiveExpression(GetType().Assembly.ManifestModule.ModuleVersionId.ToString())))); if (shaderExtendsFrom != null) { classDom.BaseTypes.Add(new CodeTypeReference(shaderExtendsFrom)); } else { classDom.BaseTypes.Add(new CodeTypeReference(typeof(BaseShader))); } //add custom base types to the shader //these are defined in TechniqueExtraData AsmTechnique asmTechnique = this.source.GetAsmTechnique(this.techniqueName, this.platform); if (asmTechnique.TechniqueExtraData != null && asmTechnique.TechniqueExtraData.ClassBaseTypes != null) { foreach (string baseTypeName in asmTechnique.TechniqueExtraData.ClassBaseTypes) { classDom.BaseTypes.Add(new CodeTypeReference(baseTypeName)); } } this.directives = directives; SetupMembers(techniqueName); foreach (DomBase dom in domList) { dom.SetupMembers(this); } if (shaderExtendsFrom == null) { CreateConstructor(); CreateStaticGraphicsInitMethod(); CreateBindMethod(); } if (shaderExtendsFrom != null || isShaderExtenable) { CreateLocalDeviceIndexProperty(); } CreateWarmShaderMethod(); if (shaderExtendsFrom == null) { CreateChangedMethod(); } CreateVertexInputMethods(); if (shaderExtendsFrom == null) { CreateShaderConstantHashMethod(); } CodeTypeMemberCollection pcMembers = new CodeTypeMemberCollection(); CodeTypeMemberCollection xboxMembers = new CodeTypeMemberCollection(); foreach (DomBase dom in this.domList) { dom.AddMembers(this, delegate(CodeTypeMember s, string c) { Comment(s, c); classDom.Members.Add(s); }, Platform.Both); if (!source.DefinePlatform) // no need for specialization when the platform is constant { dom.AddMembers(this, delegate(CodeTypeMember s, string c) { Comment(s, c); pcMembers.Add(s); }, Platform.Windows); dom.AddMembers(this, delegate(CodeTypeMember s, string c) { Comment(s, c); xboxMembers.Add(s); }, Platform.Xbox); } } foreach (DomBase dom in this.domList) { dom.AddReadonlyMembers(this, delegate(CodeTypeMember s, string c) { CodeTypeMember readonlySnip = directives.CreateReadOnlySnippet(); Comment(readonlySnip ?? s, c); if (readonlySnip != null) { classDom.Members.Add(readonlySnip); } classDom.Members.Add(s); }, Platform.Both); if (!source.DefinePlatform) { dom.AddReadonlyMembers(this, delegate(CodeTypeMember s, string c) { CodeTypeMember readonlySnip = directives.CreateReadOnlySnippet(); Comment(readonlySnip ?? s, c); if (readonlySnip != null) { pcMembers.Add(readonlySnip); } pcMembers.Add(s); }, Platform.Windows); dom.AddReadonlyMembers(this, delegate(CodeTypeMember s, string c) { CodeTypeMember readonlySnip = directives.CreateReadOnlySnippet(); Comment(readonlySnip ?? s, c); if (readonlySnip != null) { xboxMembers.Add(readonlySnip); } xboxMembers.Add(s); }, Platform.Xbox); } } if (pcMembers.Count > 0 || xboxMembers.Count > 0) { //add #if / else blocks classDom.Members.Add(directives.IfXboxStatement); foreach (CodeTypeMember type in xboxMembers) { classDom.Members.Add(type); } classDom.Members.Add(directives.ElseStatement); foreach (CodeTypeMember type in pcMembers) { classDom.Members.Add(type); } classDom.Members.Add(directives.EndifStatement); } //finally, create the attribute setters CreateSetAttributeMethod(typeof(float), "SetAttribute", "attribute"); CreateSetAttributeMethod(typeof(Vector2), "SetAttribute", "attribute"); CreateSetAttributeMethod(typeof(Vector3), "SetAttribute", "attribute"); CreateSetAttributeMethod(typeof(Vector4), "SetAttribute", "attribute"); CreateSetAttributeMethod(typeof(Matrix), "SetAttribute", "attribute"); CreateSetAttributeMethod(typeof(bool), "SetAttribute", "attribute"); CreateSetAttributeMethod(typeof(float[]), "SetAttribute", "attribute"); CreateSetAttributeMethod(typeof(Vector2[]), "SetAttribute", "attribute"); CreateSetAttributeMethod(typeof(Vector3[]), "SetAttribute", "attribute"); CreateSetAttributeMethod(typeof(Vector4[]), "SetAttribute", "attribute"); CreateSetAttributeMethod(typeof(Matrix[]), "SetAttribute", "attribute"); CreateSetAttributeMethod(typeof(Xen.Graphics.State.TextureSamplerState), "SetSamplerState", "sampler"); CreateSetAttributeMethod(typeof(Texture), "SetTexture", "texture"); CreateSetAttributeMethod(typeof(Texture2D), "SetTexture", "texture"); CreateSetAttributeMethod(typeof(Texture3D), "SetTexture", "texture"); CreateSetAttributeMethod(typeof(TextureCube), "SetTexture", "texture"); }
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")); }