Пример #1
0
        public TechniqueExtraData GetTechniqueDefaultValues(string name)
        {
            TechniqueExtraData value = null;

            techniqueDefaults.TryGetValue(name, out value);
            return(value);
        }
Пример #2
0
        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;
			}
		}
Пример #4
0
        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);
		}