private CompilerResults GetCompilerResults(string effectName, CompilerParameters compilerParameters) { compilerParameters.Profile = GraphicsDevice.ShaderProfile.HasValue ? GraphicsDevice.ShaderProfile.Value : GraphicsDevice.Features.Profile; #if SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGLCORE compilerParameters.Platform = GraphicsPlatform.OpenGL; #endif #if SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGLES compilerParameters.Platform = GraphicsPlatform.OpenGLES; #endif // Compile shader var isXkfx = ShaderMixinManager.Contains(effectName); // getting the effect from the used parameters only makes sense when the source files are the same // TODO: improve this by updating earlyCompilerCache - cache can still be relevant CompilerResults compilerResult = null; if (isXkfx) { // perform an early test only based on the parameters compilerResult = GetShaderFromParameters(effectName, compilerParameters); } if (compilerResult == null) { var source = isXkfx ? new ShaderMixinGeneratorSource(effectName) : (ShaderSource) new ShaderClassSource(effectName); compilerResult = compiler.Compile(source, compilerParameters); var effectRequested = EffectUsed; if (effectRequested != null) { effectRequested(new EffectCompileRequest(effectName, compilerResult.UsedParameters)); } if (!compilerResult.HasErrors && isXkfx) { lock (earlyCompilerCache) { List <CompilerResults> effectCompilerResults; if (!earlyCompilerCache.TryGetValue(effectName, out effectCompilerResults)) { effectCompilerResults = new List <CompilerResults>(); earlyCompilerCache.Add(effectName, effectCompilerResults); } // Register bytecode used parameters so that they are checked when another effect is instanced effectCompilerResults.Add(compilerResult); } } } foreach (var message in compilerResult.Messages) { Log.Log(message); } return(compilerResult); }
private CompilerResults GetCompilerResults(string effectName, CompilerParameters compilerParameters) { // Compile shader var isXkfx = ShaderMixinManager.Contains(effectName); // getting the effect from the used parameters only makes sense when the source files are the same // TODO: improve this by updating earlyCompilerCache - cache can still be relevant CompilerResults compilerResult = null; if (isXkfx) { // perform an early test only based on the parameters compilerResult = GetShaderFromParameters(effectName, compilerParameters); } if (compilerResult == null) { var effectRequested = EffectUsed; if (effectRequested != null) { effectRequested(new EffectCompileRequest(effectName, new CompilerParameters(compilerParameters))); } var source = isXkfx ? new ShaderMixinGeneratorSource(effectName) : (ShaderSource) new ShaderClassSource(effectName); compilerResult = compiler.Compile(source, compilerParameters); if (!compilerResult.HasErrors && isXkfx) { lock (earlyCompilerCache) { List <CompilerResults> effectCompilerResults; if (!earlyCompilerCache.TryGetValue(effectName, out effectCompilerResults)) { effectCompilerResults = new List <CompilerResults>(); earlyCompilerCache.Add(effectName, effectCompilerResults); } // Register bytecode used parameters so that they are checked when another effect is instanced effectCompilerResults.Add(compilerResult); } } } foreach (var message in compilerResult.Messages) { Log.Log(message); } return(compilerResult); }
/// <summary> /// Performs the maximal reduction. /// </summary> //public Dictionary<UFile, Image> Run(EffectCompilerBase compiler) public bool Run(EffectCompilerBase compiler) { var result = true; if (commandList.Count > 0) { if (plane == null) { plane = GeometricPrimitive.Plane.New(graphicsDevice, 2.0f, 2.0f); } var assetManager = new AssetManager(); assetManager.Serializer.RegisterSerializer(new GpuTextureSerializer2(graphicsDevice)); var textures = new Dictionary <string, Graphics.Texture>(); var materialTreeShaderCreator = new MaterialTreeShaderCreator(Material); var textureVisitor = new MaterialTextureVisitor(Material); var compilerParameters = new CompilerParameters { Platform = GraphicsPlatform.Direct3D11, Profile = GraphicsProfile.Level_11_0 }; foreach (var command in commandList) { var computeColorShader = materialTreeShaderCreator.GenerateShaderForReduction(command.OldNode); if (computeColorShader == null) { continue; } var finalShader = new ShaderMixinSource(); finalShader.Mixins.Add(new ShaderClassSource("FlattenLayers")); finalShader.Compositions.Add("outColor", computeColorShader); var results = compiler.Compile(finalShader, compilerParameters); if (results.HasErrors) { continue; } command.TreeEffect = new Graphics.Effect(graphicsDevice, results.MainBytecode, results.MainUsedParameters); command.Parameters = new ParameterCollection(); var maxWidth = 0; var maxHeight = 0; var allTextures = textureVisitor.GetAllTextureValues(command.OldNode); foreach (var texSlot in allTextures) { Graphics.Texture tex; if (!textures.TryGetValue(texSlot.TextureName, out tex)) { //TODO: change load so that texture can be unloaded. tex = assetManager.Load <Graphics.Texture>(texSlot.TextureName); textures.Add(texSlot.TextureName, tex); } if (tex == null) { throw new FileNotFoundException("Texture " + texSlot.TextureName + " not found"); } command.Parameters.Set(texSlot.UsedParameterKey, tex); maxWidth = Math.Max(maxWidth, tex.ViewWidth); maxHeight = Math.Max(maxHeight, tex.ViewHeight); // can take min, a user-defined size, or clamp the min/max // exclude mask? } command.RenderTarget = Graphics.Texture.New2D(graphicsDevice, maxWidth, maxHeight, PixelFormat.R8G8B8A8_UNorm, TextureFlags.ShaderResource | TextureFlags.RenderTarget); command.ToExecute = true; } // remove wrong commands commandList.RemoveAll(x => !x.ToExecute); var nodeReplacer = new MaterialNodeReplacer(Material); foreach (var command in commandList.Where(x => x.ToExecute)) { lock (graphicsDevice) { graphicsDevice.Clear(command.RenderTarget, Color4.Black); graphicsDevice.SetRenderTarget(command.RenderTarget); graphicsDevice.SetRasterizerState(graphicsDevice.RasterizerStates.CullNone); graphicsDevice.SetDepthStencilState(graphicsDevice.DepthStencilStates.None); command.TreeEffect.Apply(command.Parameters); plane.Draw(); // save texture SaveTexture(command.RenderTarget, command.TextureUrl, assetManager); } // make new tree var newNode = new MaterialTextureNode(command.TextureUrl.FullPath, command.TexcoordIndex, Vector2.One, Vector2.Zero); nodeReplacer.Replace(command.OldNode, newNode); // save new material? command.ToExecute = false; } foreach (var command in commandList) { command.TreeEffect.Dispose(); command.RenderTarget.Dispose(); } foreach (var texture in textures) { texture.Value.Dispose(); } textures.Clear(); foreach (var tex in textures) { assetManager.Unload(tex); } textures.Clear(); result = commandList.All(x => !x.ToExecute); commandList.Clear(); } return(result); }
private CompilerResults GetCompilerResults(string effectName, CompilerParameters compilerParameters) { compilerParameters.Profile = GraphicsDevice.ShaderProfile.HasValue ? GraphicsDevice.ShaderProfile.Value : GraphicsDevice.Features.Profile; #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLCORE compilerParameters.Platform = GraphicsPlatform.OpenGL; #endif #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES compilerParameters.Platform = GraphicsPlatform.OpenGLES; #endif // Compile shader var isPdxfx = ShaderMixinManager.Contains(effectName); // getting the effect from the used parameters only makes sense when the source files are the same // TODO: improve this by updating earlyCompilerCache - cache can still be relevant CompilerResults compilerResult = null; if (isPdxfx) { // perform an early test only based on the parameters compilerResult = GetShaderFromParameters(effectName, compilerParameters); } if (compilerResult == null) { var source = isPdxfx ? new ShaderMixinGeneratorSource(effectName) : (ShaderSource) new ShaderClassSource(effectName); compilerResult = compiler.Compile(source, compilerParameters); #if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP // If enabled, request this effect compile // TODO: For now we save usedParameters, but ideally we probably want to have a list of everything that might be use by a given // pdxfx and filter against this, so that branches not taken on a specific situation/platform can still be reproduced on another. // Alternatively, we could save full compilerParameters, but we would have to ignore certain things that are not serializable, such as Texture. lock (effectCompileRecordLock) { if (recordedEffectCompile != null) { var effectCompileRequest = new EffectCompileRequest(effectName, compilerResult.UsedParameters); if (!recordedEffectCompile.Contains(effectCompileRequest)) { recordedEffectCompile[effectCompileRequest] = true; } } } #endif if (!compilerResult.HasErrors && isPdxfx) { lock (earlyCompilerCache) { List <CompilerResults> effectCompilerResults; if (!earlyCompilerCache.TryGetValue(effectName, out effectCompilerResults)) { effectCompilerResults = new List <CompilerResults>(); earlyCompilerCache.Add(effectName, effectCompilerResults); } // Register bytecode used parameters so that they are checked when another effect is instanced effectCompilerResults.Add(compilerResult); } } } foreach (var message in compilerResult.Messages) { Log.Log(message); } return(compilerResult); }