public TechniqueExtraData GetTechniqueDefaultValues(string name) { TechniqueExtraData value = null; techniqueDefaults.TryGetValue(name, out value); return(value); }
private AsmTechnique(string name, string source, TechniqueExtraData defaultValues) { Tokenizer tokenizer = new Tokenizer(source, false, true, true); this.name = name; this.defaultValues = defaultValues; //parse the asm, and extract the first pass. string pass = null; while (tokenizer.NextToken()) { if (tokenizer.Token.Equals("pass", StringComparison.InvariantCultureIgnoreCase)) { //may have a name next... tokenizer.NextToken(); string token = tokenizer.Token; if (token != "{") { //the name is specified tokenizer.NextToken(); token = tokenizer.Token; } //may be a new line while (token.Trim().Length == 0) { tokenizer.NextToken(); token = tokenizer.Token; } if (token != "{") { throw new CompileException("Unexpected token in assembly technique pass declaration, expected '{': " + token); } if (!tokenizer.ReadBlock()) { throw new CompileException("Unexpected end of string in assembly technique pass declaration"); } if (pass != null) { throw new CompileException("A shader technique may only define a single Pass"); } pass = tokenizer.Token; } } if (pass == null) { throw new CompileException("Technique '" + name + "' does not define a pass"); } ProcessPass(pass); }
public ShaderRegisters(SourceShader source, string techniqueName, Platform platform, IExtensionStatementProvider extensionStatementProvider) { AsmTechnique technique = source.GetAsmTechnique(techniqueName, platform); this.extensionStatementProvider = extensionStatementProvider; vsReg = technique.VertexShader.RegisterSet; psReg = technique.PixelShader.RegisterSet; if (technique.InstancingShader != null) vsInstancingReg = technique.InstancingShader.RegisterSet; if (technique.BlendingShader != null) vsBlendingReg = technique.BlendingShader.RegisterSet; if (technique.TechniqueExtraData != null) { this.techniqueData = technique.TechniqueExtraData; psDefault = technique.TechniqueExtraData.PixelShaderConstants; vsDefault = technique.TechniqueExtraData.VertexShaderConstants; psBooleanDefault = technique.TechniqueExtraData.PixelShaderBooleanConstants; vsBooleanDefault = technique.TechniqueExtraData.VertexShaderBooleanConstants; } }
private void ExtractEffectDefaults(Effect effect, List <Register> textures, SourceShader source, Platform platform) { //nasty-ness ensues! GraphicsDevice device = Graphics.GraphicsDevice; int maxVsConst = device.GraphicsDeviceCapabilities.MaxVertexShaderConstants; int maxPsConst = 32; int maxPsTextures = 16; int maxVsTextures = 4; bool setPsBooleanConstants = device.GraphicsDeviceCapabilities.PixelShaderVersion.Major == 3; bool[] shaderBooleanConstants = new bool[16]; List <Texture> allTextures = new List <Texture>(); foreach (EffectTechnique technique in effect.Techniques) { //Thanks to Darren Grant (again :) //annotate a Technique with 'BaseTypes' and the generates class will inherit from those types string[] baseTypes = new string[0]; foreach (EffectAnnotation annotation in technique.Annotations) { if (annotation.Name.Equals("BaseTypes", StringComparison.InvariantCulture) || annotation.Name.Equals("BaseType", StringComparison.InvariantCulture)) { baseTypes = annotation.GetValueString().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < baseTypes.Length; i++) { baseTypes[i] = baseTypes[i].Trim(); } } } Vector4[] psConstants = new Vector4[maxPsConst]; // pixel Vector4[] vsConstants = new Vector4[maxVsConst]; // not-pixel TextureSamplerState[] psSamplers = new TextureSamplerState[maxPsTextures]; TextureSamplerState[] vsSamplers = new TextureSamplerState[maxVsTextures]; int[] psTexturesIndex = new int[maxPsTextures]; int[] vsTexturesIndex = new int[maxVsTextures]; bool[] psBooleanConstants = new bool[16]; bool[] vsBooleanConstants = new bool[16]; allTextures.Clear(); Dictionary <string, Vector4[]> techniqueSingleValues = new Dictionary <string, Vector4[]>(); try { device.SetPixelShaderConstant(0, psConstants); device.SetVertexShaderConstant(0, vsConstants); device.SetVertexShaderConstant(0, shaderBooleanConstants); if (setPsBooleanConstants) { device.SetPixelShaderConstant(0, shaderBooleanConstants); } for (int i = 0; i < maxPsTextures; i++) { ResetSampler(device, i, true); } for (int i = 0; i < maxVsTextures; i++) { ResetSampler(device, i, false); } //assign the technique textures foreach (Register texReg in textures) { Type type = Common.GetTextureType(texReg.Type); Texture tex = Graphics.BeginGetTempTexture(type); effect.Parameters[texReg.Name].SetValue(tex); allTextures.Add(tex); } //bind the effect technique effect.CurrentTechnique = technique; effect.Begin(); if (technique.Passes.Count > 0) { EffectPass pass = technique.Passes[0]; pass.Begin(); pass.End(); } effect.End(); foreach (var param in effect.Parameters) { try { if (param.ParameterType == EffectParameterType.Single || param.ParameterType == EffectParameterType.Int32) { Vector4[] values = param.GetValueVector4Array(param.RowCount); techniqueSingleValues.Add(param.Name, values); } } catch { } } //all done. Now read back what has changed. :D psConstants = device.GetPixelShaderVector4ArrayConstant(0, maxPsConst); vsConstants = device.GetVertexShaderVector4ArrayConstant(0, maxVsConst); for (int i = 0; i < maxPsTextures; i++) { psSamplers[i] = GetState(device, i, true, allTextures, out psTexturesIndex[i]); } for (int i = 0; i < maxVsTextures; i++) { vsSamplers[i] = GetState(device, i, false, allTextures, out vsTexturesIndex[i]); } for (int i = 0; i < allTextures.Count; i++) { Graphics.EndGetTempTexture(allTextures[i]); } allTextures.Clear(); vsBooleanConstants = device.GetVertexShaderBooleanConstant(0, 16); psBooleanConstants = device.GetPixelShaderBooleanConstant(0, 16); } catch { //something went wrong... Eg, binding a SM 3.0 shader on SM 2.0 hardware device //Need to be running the Reference device throw new CompileException("Unable to compile shader: The DirectX Reference Device may be missing (Is the DirectX SDK Installed?)"); } TechniqueExtraData defaults = new TechniqueExtraData(); defaults.PixelSamplerStates = psSamplers; defaults.PixelShaderConstants = psConstants; defaults.VertexSamplerStates = vsSamplers; defaults.VertexShaderConstants = vsConstants; defaults.PixelSamplerTextureIndex = psTexturesIndex; defaults.VertexSamplerTextureIndex = vsTexturesIndex; defaults.TechniqueTextures = textures.ToArray(); defaults.ClassBaseTypes = baseTypes; defaults.PixelShaderBooleanConstants = psBooleanConstants; defaults.VertexShaderBooleanConstants = vsBooleanConstants; defaults.DefaultSingleValues = techniqueSingleValues; if (this.techniqueDefaults.ContainsKey(technique.Name) == false) { this.techniqueDefaults.Add(technique.Name, defaults); } } }
private void ExtractEffectDefaults(Effect effect, List<Register> textures, SourceShader source, Platform platform) { //nasty-ness ensues! GraphicsDevice device = Graphics.GraphicsDevice; int maxVsConst = 256; int maxPsConst = 32; int maxPsTextures = 16; int maxVsTextures = 4; bool[] shaderBooleanConstants = new bool[16]; List<Texture> allTextures = new List<Texture>(); foreach (EffectTechnique technique in effect.Techniques) { //Thanks to Darren Grant (again :) //annotate a Technique with 'BaseTypes' and the generates class will inherit from those types string[] baseTypes = new string[0]; foreach (EffectAnnotation annotation in technique.Annotations) { if (annotation.Name.Equals("BaseTypes", StringComparison.InvariantCulture) || annotation.Name.Equals("BaseType", StringComparison.InvariantCulture)) { baseTypes = annotation.GetValueString().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < baseTypes.Length; i++) baseTypes[i] = baseTypes[i].Trim(); } } float[] psConstants = new float[maxPsConst * 4]; // pixel float[] vsConstants = new float[maxVsConst * 4]; // not-pixel TextureSamplerState[] psSamplers = new TextureSamplerState[maxPsTextures]; TextureSamplerState[] vsSamplers = new TextureSamplerState[maxVsTextures]; int[] psTexturesIndex = new int[maxPsTextures]; int[] vsTexturesIndex = new int[maxVsTextures]; int[] psBooleanConstants = new int[16]; int[] vsBooleanConstants = new int[16]; allTextures.Clear(); Dictionary<string, Vector4[]> techniqueSingleValues = new Dictionary<string, Vector4[]>(); //get the device object devicePtr = device.GetType().GetField("pComPtr", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(device); var deviceInterop = new Xen.Graphics.ShaderSystem.Native.DeviceInterop((System.Reflection.Pointer)devicePtr); try { //I'm sure XNA won't mind... deviceInterop.ZeroShaderConstants(); for (int i = 0; i < maxPsTextures; i++) { deviceInterop.SetTextureFilters(i, false); ResetSampler(device, i, true); } for (int i = 0; i < maxVsTextures; i++) { deviceInterop.SetTextureFilters(i, true); ResetSampler(device, i, false); } //assign the technique textures foreach (Register texReg in textures) { Type type = Common.GetTextureType(texReg.Type); Texture tex = Graphics.BeginGetTempTexture(type); effect.Parameters[texReg.Name].SetValue(tex); allTextures.Add(tex); } //bind the effect technique effect.CurrentTechnique = technique; if (technique.Passes.Count > 0) { EffectPass pass = technique.Passes[0]; pass.Apply(); } foreach (var param in effect.Parameters) { try { if (param.ParameterType == EffectParameterType.Single || param.ParameterType == EffectParameterType.Int32) { Vector4[] values = param.GetValueVector4Array(param.RowCount); techniqueSingleValues.Add(param.Name, values); } } catch { } } //all done. Now read back what has changed. :D deviceInterop.GetShaderConstantsPS(psConstants); deviceInterop.GetShaderConstantsVS(vsConstants); //psConstants = device.GetPixelShaderVector4ArrayConstant(0, maxPsConst); //vsConstants = device.GetVertexShaderVector4ArrayConstant(0, maxVsConst); for (int i = 0; i < maxPsTextures; i++) psSamplers[i] = GetState(device, deviceInterop, i, true, allTextures, out psTexturesIndex[i]); for (int i = 0; i < maxVsTextures; i++) vsSamplers[i] = GetState(device, deviceInterop, i, false, allTextures, out vsTexturesIndex[i]); for (int i = 0; i < allTextures.Count; i++) Graphics.EndGetTempTexture(allTextures[i]); allTextures.Clear(); deviceInterop.GetShaderConstantsPS(psBooleanConstants); deviceInterop.GetShaderConstantsVS(vsBooleanConstants); //vsBooleanConstants = device.GetVertexShaderBooleanConstant(0, 16); //psBooleanConstants = device.GetPixelShaderBooleanConstant(0, 16); } catch { //something went wrong... Eg, binding a SM 3.0 shader on SM 2.0 hardware device throw new CompileException("An unexpected error occured while compiling shader: The DirectX device may not be XNA 'HiDef' capable"); } TechniqueExtraData defaults = new TechniqueExtraData(); defaults.PixelSamplerStates = psSamplers; defaults.PixelShaderConstants = Convert(psConstants); defaults.VertexSamplerStates = vsSamplers; defaults.VertexShaderConstants = Convert(vsConstants); defaults.PixelSamplerTextureIndex = psTexturesIndex; defaults.VertexSamplerTextureIndex = vsTexturesIndex; defaults.TechniqueTextures = textures.ToArray(); defaults.ClassBaseTypes = baseTypes; defaults.PixelShaderBooleanConstants = Convert(psBooleanConstants); defaults.VertexShaderBooleanConstants = Convert(vsBooleanConstants); defaults.DefaultSingleValues = techniqueSingleValues; if (this.techniqueDefaults.ContainsKey(technique.Name) == false) this.techniqueDefaults.Add(technique.Name, defaults); } }
private AsmTechnique(string name, string source, TechniqueExtraData defaultValues) { Tokenizer tokenizer = new Tokenizer(source, false, true, true); this.name = name; this.defaultValues = defaultValues; //parse the asm, and extract the first pass. string pass = null; string firstPassName = null; string blendPass = null, instancingPass = null; while (tokenizer.NextToken()) { if (tokenizer.Token.Equals("pass", StringComparison.InvariantCultureIgnoreCase)) { //may have a name next... tokenizer.NextToken(); string token = tokenizer.Token; string passName = null; if (token != "{") { //the name is specified passName = tokenizer.Token; tokenizer.NextToken(); token = tokenizer.Token; } //may be a new line while (token.Trim().Length == 0) { tokenizer.NextToken(); token = tokenizer.Token; } if (token != "{") throw new CompileException("Unexpected token in assembly technique pass declaration, expected '{': " + token); if (!tokenizer.ReadBlock()) throw new CompileException("Unexpected end of string in assembly technique pass declaration"); bool isAnimated, isInstancing; ExtractPassType(passName, out isAnimated, out isInstancing); string help = @" For example: technique TechniqueName { //default pass: pass { VertexShader = compile vs_2_0 BaseVS(); PixelShader = compile ps_2_0 BasePS(); } pass Animated { VertexShader = compile vs_2_0 AnimatedVS(); } pass Instancing { VertexShader = compile vs_2_0 InstancingVS(); } } Note, the instancing or animation passes may only replace the vertex shader"; if (pass != null) { if (blendPass == null && isAnimated) { blendPass = tokenizer.Token; } else if (instancingPass == null && isInstancing) { instancingPass = tokenizer.Token; } else throw new CompileException(@"A shader technique may only define a single Pass, or define a dedicated Animation and/or Instancing pass:"******"A shader technique must define a default pass before defining an instancing or animation pass:"******"Technique '" + name + "' does not define a pass"); ProcessPass(pass); this.vsBlendOverride = ProcessSupplimentaryPass(blendPass); this.vsInstancingOverride = ProcessSupplimentaryPass(instancingPass); SetupCommonRegisters(); if (this.vsBlendOverride != null) this.vsBlendOverride.RegisterSet.CompactDuplicateRegisters(this.vsListing.RegisterSet, "Animated", this.name); if (this.vsInstancingOverride != null) this.vsInstancingOverride.RegisterSet.CompactDuplicateRegisters(this.vsListing.RegisterSet, "Instancing", this.name); }