public void TestSimpleChild()
        {
            var properties = new ShaderMixinParameters();

            var mixin = GenerateMixin("DefaultSimpleChild", properties);
            mixin.CheckMixin("A", "B", "C", "C1", "C2");
        }
        public void TestSimple()
        {
            var properties = new ShaderMixinParameters();
            ShaderMixinParameters usedProperties;

            var mixin = GenerateMixin("DefaultSimple", properties, out usedProperties);
            mixin.CheckMixin("A", "B", "C");
        }
        public void TestSimpleCompose()
        {
            var properties = new ShaderMixinParameters();

            var mixin = GenerateMixin("DefaultSimpleCompose", properties);
            mixin.CheckMixin("A", "B", "C");
            mixin.CheckComposition("x", "X");
        }
Beispiel #4
0
        /// <summary>
        /// Converts the hlsl code into glsl and stores the result as plain text
        /// </summary>
        /// <param name="shaderSource">the hlsl shader</param>
        /// <param name="entryPoint">the entrypoint function name</param>
        /// <param name="stage">the shader pipeline stage</param>
        /// <param name="compilerParameters"></param>
        /// <param name="reflection">the reflection gathered from the hlsl analysis</param>
        /// <param name="sourceFilename">the name of the source file</param>
        /// <returns></returns>
        public ShaderBytecodeResult Compile(string shaderSource, string entryPoint, ShaderStage stage, ShaderMixinParameters compilerParameters, EffectReflection reflection, string sourceFilename = null)
        {
            var isOpenGLES = compilerParameters.Get(CompilerParameters.GraphicsPlatformKey) == GraphicsPlatform.OpenGLES;
            var isOpenGLES3 = compilerParameters.Get(CompilerParameters.GraphicsProfileKey) >= GraphicsProfile.Level_10_0;
            var shaderBytecodeResult = new ShaderBytecodeResult();
            byte[] rawData;

            var shader = Compile(shaderSource, entryPoint, stage, isOpenGLES, isOpenGLES3, shaderBytecodeResult, sourceFilename);

            if (shader == null)
                return shaderBytecodeResult;

            if (isOpenGLES)
            {
                // store both ES 2 and ES 3 on OpenGL ES platforms
                var shaderBytecodes = new ShaderLevelBytecode();
                if (isOpenGLES3)
                {
                    shaderBytecodes.DataES3 = shader;
                    shaderBytecodes.DataES2 = null;
                }
                else
                {
                    shaderBytecodes.DataES2 = shader;
                    shaderBytecodes.DataES3 = Compile(shaderSource, entryPoint, stage, true, true, shaderBytecodeResult, sourceFilename);
                }
                using (var stream = new MemoryStream())
                {
                    BinarySerialization.Write(stream, shaderBytecodes);
#if !SILICONSTUDIO_RUNTIME_CORECLR
                    rawData = stream.GetBuffer();
#else
// FIXME: Manu: The call to "ToArray()" might be slower than "GetBuffer()"
                    rawData = stream.ToArray();
#endif
                }
            }
            else
            {
                // store string on OpenGL platforms
                rawData = Encoding.ASCII.GetBytes(shader);
            }
            
            var bytecodeId = ObjectId.FromBytes(rawData);
            var bytecode = new ShaderBytecode(bytecodeId, rawData);
            bytecode.Stage = stage;

            shaderBytecodeResult.Bytecode = bytecode;
            
            return shaderBytecodeResult;
        }
Beispiel #5
0
        public void Init()
        {
            // Create and mount database file system
            var objDatabase = new ObjectDatabase("/data/db", "index", "/local/db");
            var databaseFileProvider = new DatabaseFileProvider(objDatabase);
            AssetManager.GetFileProvider = () => databaseFileProvider;

            Compiler = new EffectCompiler();
            Compiler.SourceDirectories.Add("shaders");
            MixinParameters = new ShaderMixinParameters();
            MixinParameters.Add(CompilerParameters.GraphicsPlatformKey, GraphicsPlatform.Direct3D11);
            MixinParameters.Add(CompilerParameters.GraphicsProfileKey, GraphicsProfile.Level_11_0);
            ResultLogger = new LoggerResult();
        }
        /// <summary>
        /// Generates the mixin.
        /// </summary>
        /// <param name="mixinName">Name of the mixin.</param>
        /// <param name="properties">The properties that the mixin will use.</param>
        /// <param name="usedProperties">The properties effectively used by the mixin.</param>
        /// <returns>ShaderMixinSource.</returns>
        private static ShaderMixinSource GenerateMixin(string mixinName, ParameterCollection properties, out ShaderMixinParameters usedProperties)
        {
            var allUsedProperties = new List<ShaderMixinParameters>();
            var mixin = ShaderMixinManager.Generate(mixinName, properties);

            usedProperties = mixin.UsedParameters;

            // Verify that output used properties are a subset of input properties
            Assert.That(usedProperties.IsSubsetOf(properties), Is.True);

            foreach(var usedProps in allUsedProperties)
                Assert.That(usedProps.IsSubsetOf(properties), Is.True);

            return mixin;
        }
        public void TestSimpleParams()
        {
            var properties = new ShaderMixinParameters();

            var mixin = GenerateMixin("DefaultSimpleParams", properties);
            mixin.CheckMixin("A", "B", "D");
            mixin.CheckComposition("y", "Y");
            mixin.CheckMacro("Test", "ok");

            // Set a key to modify the mixin
            properties.Set(Test7.TestParameters.param1, true);

            mixin = GenerateMixin("DefaultSimpleParams", properties);
            mixin.CheckMixin("A", "B", "C");
            mixin.CheckComposition("x", "X");
            mixin.CheckMacro("param2", 1);
        }
        public void Compile()
        {
            Console.WriteLine(@"Inside Thread");
            
            var parameters = new ShaderMixinParameters();
            parameters.Set(CompilerParameters.GraphicsPlatformKey, GraphicsPlatform.Direct3D11);
            parameters.Set(CompilerParameters.GraphicsProfileKey, GraphicsProfile.Level_11_0);

            var mixinTree = new ShaderMixinSource() { Name = "TestParallelMix", UsedParameters = parameters };

            var result = effectCompiler.Compile(mixinTree, new CompilerParameters()).WaitForResult();

            Assert.IsFalse(result.CompilationLog.HasErrors);
            Assert.IsNotNull(result);

            Console.WriteLine(@"Thread end");
        }
Beispiel #9
0
        public void TestSimpleParams()
        {
            var properties = new ShaderMixinParameters();

            var mixin = GenerateMixin("DefaultSimpleParams", properties);

            mixin.CheckMixin("A", "B", "D");
            mixin.CheckComposition("y", "Y");
            mixin.CheckMacro("Test", "ok");

            // Set a key to modify the mixin
            properties.Set(Test7.TestParameters.param1, true);

            mixin = GenerateMixin("DefaultSimpleParams", properties);
            mixin.CheckMixin("A", "B", "C");
            mixin.CheckComposition("x", "X");
            mixin.CheckMacro("param2", 1);
        }
Beispiel #10
0
        public ShaderBytecodeResult Compile(string shaderSource, string entryPoint, ShaderStage stage, ShaderMixinParameters compilerParameters, EffectReflection reflection, string sourceFilename = null)
        {
            var isDebug = compilerParameters.Get(CompilerParameters.DebugKey);
            var profile = compilerParameters.Get(CompilerParameters.GraphicsProfileKey);
            
            var shaderModel = ShaderStageToString(stage) + "_" + ShaderProfileFromGraphicsProfile(profile);

            var shaderFlags = ShaderFlags.None;
            if (isDebug)
            {
                shaderFlags = ShaderFlags.OptimizationLevel0 | ShaderFlags.Debug;
            }

            SharpDX.Configuration.ThrowOnShaderCompileError = false;

            // Compile using D3DCompiler
            var compilationResult = SharpDX.D3DCompiler.ShaderBytecode.Compile(shaderSource, entryPoint, shaderModel, shaderFlags, EffectFlags.None, null, null, sourceFilename);

            var byteCodeResult = new ShaderBytecodeResult();

            if (compilationResult.HasErrors)
            {
                // Log compilation errors
                byteCodeResult.Error(compilationResult.Message);
            }
            else
            {
                // As effect bytecode binary can changed when having debug infos (with d3dcompiler_47), we are calculating a bytecodeId on the stripped version
                var rawData = compilationResult.Bytecode.Strip(StripFlags.CompilerStripDebugInformation | StripFlags.CompilerStripReflectionData);
                var bytecodeId = ObjectId.FromBytes(rawData);
                byteCodeResult.Bytecode = new ShaderBytecode(bytecodeId, compilationResult.Bytecode.Data) { Stage = stage };

                // If compilation succeed, then we can update reflection.
                UpdateReflection(byteCodeResult.Bytecode, reflection, byteCodeResult);

                if (!string.IsNullOrEmpty(compilationResult.Message))
                {
                    byteCodeResult.Warning(compilationResult.Message);
                }
            }

            return byteCodeResult;
        }
Beispiel #11
0
        public void TestShaderCompilation()
        {
            var generics = new string[3];
            generics[0] = "Texturing.Texture1";
            generics[1] = "TEXCOORD0";
            generics[2] = "float4(2.0,1,1,1)";

            var compilerParameters = new ShaderMixinParameters();
            compilerParameters.Set(EffectSourceCodeKeys.Enable, true);
            compilerParameters.Set(CompilerParameters.GraphicsProfileKey, GraphicsProfile.Level_11_0);

            var mixinSource = new ShaderMixinSource { Name = "TestShaderCompilationGenericClass", UsedParameters = compilerParameters };
            mixinSource.Mixins.Add(new ShaderClassSource("GenericClass2", generics));

            var log = new CompilerResults();

            var compiler = new EffectCompiler();
            compiler.SourceDirectories.Add("shaders");

            var effectByteCode = compiler.Compile(mixinSource, new CompilerParameters());
        }
        public void Compile()
        {
            Console.WriteLine(@"Inside Thread");

            var parameters = new ShaderMixinParameters();

            parameters.Set(CompilerParameters.GraphicsPlatformKey, GraphicsPlatform.Direct3D11);
            parameters.Set(CompilerParameters.GraphicsProfileKey, GraphicsProfile.Level_11_0);

            var mixinTree = new ShaderMixinSource()
            {
                Name = "TestParallelMix", UsedParameters = parameters
            };

            var result = effectCompiler.Compile(mixinTree, new CompilerParameters()).WaitForResult();

            Assert.IsFalse(result.CompilationLog.HasErrors);
            Assert.IsNotNull(result);

            Console.WriteLine(@"Thread end");
        }
Beispiel #13
0
        /// <inheritdoc/>
        public override void Load()
        {
            base.Load();

            useMultipleRenderTargets = GraphicsDevice.Features.Profile >= GraphicsProfile.Level_10_0;

            for (var maxBlendCount = 2; maxBlendCount < 5; ++maxBlendCount)
            {
                var compilerParameter      = new CompilerParameters();
                var compilerParameterChild = new ShaderMixinParameters[maxBlendCount];
                for (var i = 0; i < maxBlendCount; ++i)
                {
                    var param = new ShaderMixinParameters();
                    param.Add(CubemapBlendRenderer.CubemapKey, GetTextureCubeKey(i));
                    compilerParameterChild[i] = param;
                }
                compilerParameter.Set(CubemapBlendRenderer.Cubemaps, compilerParameterChild);
                compilerParameter.Set(CubemapBlendRenderer.CubemapCount, maxBlendCount);
                compilerParameter.Set(CubemapBlendRenderer.UseMultipleRenderTargets, useMultipleRenderTargets);
                cubemapBlendEffects.Add(maxBlendCount, EffectSystem.LoadEffect("CubemapBlendEffect", compilerParameter));
            }
        }
Beispiel #14
0
        public void TestShaderParametersSerialization()
        {
            // Test serialization
            var shaderParameters = new ShaderMixinParameters("Test");

            shaderParameters.Set(PropertyInt, 5);
            var subShaderParameters = new ShaderMixinParameters("Sub");

            subShaderParameters.Set(PropertyInt, 6);
            shaderParameters.Set(PropertySub, subShaderParameters);

            var subShaderParametersArray  = new ShaderMixinParameters[1];
            var subShaderParametersArray1 = new ShaderMixinParameters("InArray1");

            subShaderParametersArray[0] = subShaderParametersArray1;
            subShaderParametersArray1.Set(PropertyInt, 7);
            shaderParameters.Set(PropertySubs, subShaderParametersArray);

            var memoryStream = new MemoryStream();
            var writer       = new BinarySerializationWriter(memoryStream);

            writer.Write(shaderParameters);
            writer.Flush();
            memoryStream.Position = 0;

            var reader = new BinarySerializationReader(memoryStream);
            var shaderParametersReloaded = reader.Read <ShaderMixinParameters>();

            // They should be strictly equal
            Assert.That(shaderParametersReloaded.IsSubsetOf(shaderParameters), Is.True);
            Assert.That(shaderParameters.IsSubsetOf(shaderParametersReloaded), Is.True);

            // Test subset
            // Check that by removing one key from the original parameters, the reloaded version is
            // no longer a subset
            subShaderParametersArray1.Remove(PropertyInt);
            Assert.That(shaderParametersReloaded.IsSubsetOf(shaderParameters), Is.False);
        }
Beispiel #15
0
        public void TestShaderCompilation()
        {
            var generics = new string[3];

            generics[0] = "Texturing.Texture1";
            generics[1] = "TEXCOORD0";
            generics[2] = "float4(2.0,1,1,1)";

            var mixinSource = new ShaderMixinSource();

            mixinSource.Mixins.Add(new ShaderClassSource("GenericClass2", generics));

            var compilerParameters = new ShaderMixinParameters();

            compilerParameters.Set(EffectSourceCodeKeys.Enable, true);
            compilerParameters.Set(CompilerParameters.GraphicsProfileKey, GraphicsProfile.Level_11_0);

            var log = new CompilerResults();

            var compiler = new EffectCompiler();

            compiler.SourceDirectories.Add("shaders");
            var effectByteCode = compiler.Compile(mixinSource, "TestShaderCompilationGenericClass", compilerParameters, null, null, log);
        }
Beispiel #16
0
        public override EffectBytecode Compile(ShaderMixinSource shaderMixinSource, string fullEffectName, ShaderMixinParameters compilerParameters, HashSet <string> modifiedShaders, HashSet <string> recentlyModifiedShaders, LoggerResult log)
        {
            // Load D3D compiler dll
            // Note: No lock, it's probably fine if it gets called from multiple threads at the same time.
            if (Platform.IsWindowsDesktop && !d3dcompilerLoaded)
            {
                NativeLibrary.PreloadLibrary("d3dcompiler_47.dll");
                d3dcompilerLoaded = true;
            }

            // Make a copy of shaderMixinSource. Use deep clone since shaderMixinSource can be altered during compilation (e.g. macros)
            var shaderMixinSourceCopy = new ShaderMixinSource();

            shaderMixinSourceCopy.DeepCloneFrom(shaderMixinSource);

            shaderMixinSource = shaderMixinSourceCopy;

            // Generate platform-specific macros
            var platform = compilerParameters.Get(CompilerParameters.GraphicsPlatformKey);

            switch (platform)
            {
            case GraphicsPlatform.Direct3D11:
                shaderMixinSource.AddMacro("SILICONSTUDIO_PARADOX_GRAPHICS_API_DIRECT3D", 1);
                shaderMixinSource.AddMacro("SILICONSTUDIO_PARADOX_GRAPHICS_API_DIRECT3D11", 1);
                break;

            case GraphicsPlatform.OpenGL:
                shaderMixinSource.AddMacro("SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGL", 1);
                shaderMixinSource.AddMacro("SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLCORE", 1);
                break;

            case GraphicsPlatform.OpenGLES:
                shaderMixinSource.AddMacro("SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGL", 1);
                shaderMixinSource.AddMacro("SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES", 1);
                break;

            default:
                throw new NotSupportedException();
            }

            // Generate the AST from the mixin description
            if (shaderMixinParser == null)
            {
                shaderMixinParser = new ShaderMixinParser();
                shaderMixinParser.SourceManager.LookupDirectoryList = SourceDirectories; // TODO: temp
                shaderMixinParser.SourceManager.UrlToFilePath       = UrlToFilePath;     // TODO: temp
            }

            if (recentlyModifiedShaders != null && recentlyModifiedShaders.Count > 0)
            {
                shaderMixinParser.DeleteObsoleteCache(GetShaderNames(recentlyModifiedShaders));
                recentlyModifiedShaders.Clear();
            }
            var parsingResult = shaderMixinParser.Parse(shaderMixinSource, shaderMixinSource.Macros.ToArray(), modifiedShaders);

            // Copy log from parser results to output
            CopyLogs(parsingResult, log);

            // Return directly if there are any errors
            if (parsingResult.HasErrors)
            {
                return(null);
            }

            // Convert the AST to HLSL
            var writer = new SiliconStudio.Shaders.Writer.Hlsl.HlslWriter {
                EnablePreprocessorLine = false
            };

            writer.Visit(parsingResult.Shader);
            var shaderSourceText = writer.Text;

            // -------------------------------------------------------
            // Save shader log
            // TODO: TEMP code to allow debugging generated shaders on Windows Desktop
#if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP
            var shaderId = ObjectId.FromBytes(Encoding.UTF8.GetBytes(shaderSourceText));

            var logDir = "log";
            if (!Directory.Exists(logDir))
            {
                Directory.CreateDirectory(logDir);
            }
            var shaderSourceFilename = Path.Combine(logDir, "shader_" + shaderId);
            lock (WriterLock) // protect write in case the same shader is created twice
            {
                if (!File.Exists(shaderSourceFilename))
                {
                    var builder = new StringBuilder();
                    builder.AppendLine("/***** Used Parameters *****");
                    builder.Append(" * EffectName: ");
                    builder.AppendLine(fullEffectName ?? "");
                    WriteParameters(builder, compilerParameters, 0, false);
                    builder.AppendLine(" ***************************/");
                    builder.Append(shaderSourceText);
                    File.WriteAllText(shaderSourceFilename, builder.ToString());
                }
            }
#endif
            // -------------------------------------------------------

            var bytecode = new EffectBytecode {
                Reflection = parsingResult.Reflection, HashSources = parsingResult.HashSources
            };

            // Select the correct backend compiler
            IShaderCompiler compiler;
            switch (platform)
            {
            case GraphicsPlatform.Direct3D11:
                compiler = new Direct3D.ShaderCompiler();
                break;

            case GraphicsPlatform.OpenGL:
            case GraphicsPlatform.OpenGLES:
                compiler = new OpenGL.ShaderCompiler();
                break;

            default:
                throw new NotSupportedException();
            }

            var shaderStageBytecodes = new List <ShaderBytecode>();

            foreach (var stageBinding in parsingResult.EntryPoints)
            {
                // Compile
                var result = compiler.Compile(shaderSourceText, stageBinding.Value, stageBinding.Key, compilerParameters, bytecode.Reflection, shaderSourceFilename);
                result.CopyTo(log);

                if (result.HasErrors)
                {
                    continue;
                }

                // -------------------------------------------------------
                // Append bytecode id to shader log
#if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP
                lock (WriterLock) // protect write in case the same shader is created twice
                {
                    if (File.Exists(shaderSourceFilename))
                    {
                        // Append at the end of the shader the bytecodes Id
                        File.AppendAllText(shaderSourceFilename, "\n// {0} {1}".ToFormat(stageBinding.Key, result.Bytecode.Id));
                    }
                }
#endif
                // -------------------------------------------------------

                shaderStageBytecodes.Add(result.Bytecode);

                // When this is a compute shader, there is no need to scan other stages
                if (stageBinding.Key == ShaderStage.Compute)
                {
                    break;
                }
            }

            // Get the current time of compilation
            bytecode.Time = DateTime.Now;

            // In case of Direct3D, we can safely remove reflection data as it is entirely resolved at compile time.
            if (platform == GraphicsPlatform.Direct3D11)
            {
                CleanupReflection(bytecode.Reflection);
            }

            bytecode.Stages = shaderStageBytecodes.ToArray();
            return(bytecode);
        }
        public void TestComplexParams()
        {
            var properties = new ShaderMixinParameters();

            // Populate the the properties used by the mixin
            var subParam1 = new Test1.SubParameters();
            var subParameters = new Test1.SubParameters[4];
            for (int i = 0; i < subParameters.Length; i++)
            {
                subParameters[i] = new Test1.SubParameters();
            }

            properties.Set(Test1.TestParameters.subParam1, subParam1);
            properties.Set(Test1.TestParameters.subParameters, subParameters);

            // Generate the mixin with default properties
            var mixin = GenerateMixin("DefaultComplexParams", properties);
            mixin.CheckMixin("A", "B", "C", "D");

            // Modify properties in order to modify mixin
            for (int i = 0; i < subParameters.Length; i++)
            {
                subParameters[i].Set(Test1.SubParameters.param1, (i & 1) == 0);
            }
            subParam1.Set(Test1.SubParameters.param2, 2);

            mixin = GenerateMixin("DefaultComplexParams", properties);
            mixin.CheckMixin("A", "B", "C", "C1", "C3");
        }
        public override EffectBytecode Compile(ShaderMixinSource mixin, string fullEffectName, ShaderMixinParameters compilerParameters, HashSet <string> modifiedShaders, HashSet <string> recentlyModifiedShaders, LoggerResult log)
        {
            var database = AssetManager.FileProvider;

            if (database == null)
            {
                throw new NotSupportedException("Using the cache requires to AssetManager.FileProvider to be valid.");
            }

            // remove the old shaders
            if (recentlyModifiedShaders != null && recentlyModifiedShaders.Count != 0)
            {
                RemoveObsoleteStoredResults(recentlyModifiedShaders);
            }

            var ids = ShaderMixinObjectId.Compute(mixin, compilerParameters);

            EffectBytecode bytecode = null;

            lock (storedResults)
            {
                if (storedResults.TryGetValue(ids.FullParametersId, out bytecode))
                {
                    return(bytecode);
                }

                // Final url of the compiled bytecode
                var compiledUrl = string.Format("{0}/{1}", CompiledShadersKey, ids.CompileParametersId);

                // ------------------------------------------------------------------------------------------------------------
                // 1) Try to load latest bytecode
                // ------------------------------------------------------------------------------------------------------------
                ObjectId bytecodeId;
                if (database.AssetIndexMap.TryGetValue(compiledUrl, out bytecodeId))
                {
                    using (var stream = database.ObjectDatabase.OpenStream(bytecodeId))
                    {
                        var localBytecode = BinarySerialization.Read <EffectBytecode>(stream);

                        // If latest bytecode is in sync
                        if (!Platform.IsWindowsDesktop || CheckBytecodeInSyncAgainstSources(localBytecode, database))
                        {
                            bytecode = localBytecode;

                            // if bytecode contains a modified shource, do not use it.
                            if (modifiedShaders != null && modifiedShaders.Count != 0 && IsBytecodeObsolete(bytecode, modifiedShaders))
                            {
                                bytecode = null;
                            }
                        }
                    }
                }

                // On non Windows platform, we are expecting to have the bytecode stored directly
                if (!Platform.IsWindowsDesktop && bytecode == null)
                {
                    Log.Error("Unable to find compiled shaders [{0}] for mixin [{1}] with parameters [{2}]", compiledUrl, mixin, compilerParameters.ToStringDetailed());
                    throw new InvalidOperationException("Unable to find compiled shaders [{0}]".ToFormat(compiledUrl));
                }

                // ------------------------------------------------------------------------------------------------------------
                // 2) Try to load from intermediate results
                // ------------------------------------------------------------------------------------------------------------
                if (bytecode == null)
                {
                    // Check if this id has already a ShaderBytecodeStore
                    var isObjectInDatabase = database.ObjectDatabase.Exists(ids.CompileParametersId);

                    // Try to load from an existing ShaderBytecode
                    if ((modifiedShaders == null || modifiedShaders.Count == 0) && isObjectInDatabase)
                    {
                        var stream = database.ObjectDatabase.OpenStream(ids.CompileParametersId, VirtualFileMode.Open, VirtualFileAccess.Read, VirtualFileShare.Read);
                        using (var resultsStore = new ShaderBytecodeStore(stream))
                        {
                            // Load new values
                            resultsStore.LoadNewValues();

                            var storedValues = resultsStore.GetValues();

                            foreach (KeyValuePair <HashSourceCollection, EffectBytecode> hashResults in storedValues)
                            {
                                if (CheckBytecodeInSyncAgainstSources(hashResults.Value, database))
                                {
                                    bytecode = hashResults.Value;
                                    break;
                                }
                            }
                        }
                    }

                    // --------------------------------------------------------------------------------------------------------
                    // 3) Bytecode was not found in the cache on disk, we need to compile it
                    // --------------------------------------------------------------------------------------------------------
                    if (bytecode == null)
                    {
                        // Open the database for writing
                        var stream = database.ObjectDatabase.OpenStream(ids.CompileParametersId, VirtualFileMode.OpenOrCreate, VirtualFileAccess.ReadWrite, VirtualFileShare.ReadWrite);
                        using (var resultsStore = new ShaderBytecodeStore(stream))
                        {
                            var localLogger = new LoggerResult();

                            // Compile the mixin
                            bytecode = base.Compile(mixin, fullEffectName, compilerParameters, modifiedShaders, recentlyModifiedShaders, localLogger);
                            log.Info("New effect compiled [{0}]\r\n{1}", ids.CompileParametersId, compilerParameters.ToStringDetailed());
                            localLogger.CopyTo(log);

                            // If there are any errors, return immediately
                            if (localLogger.HasErrors)
                            {
                                return(null);
                            }

                            // Else store the bytecode for this set of HashSources
                            resultsStore[bytecode.HashSources] = bytecode;
                        }
                    }

                    // Save latest bytecode into the storage
                    using (var stream = database.OpenStream(compiledUrl, VirtualFileMode.Create, VirtualFileAccess.Write, VirtualFileShare.Write))
                    {
                        BinarySerialization.Write(stream, bytecode);
                    }
                }
                else
                {
                    // clone the bytecode since it is not the first time we load it.
                    bytecode = bytecode.Clone();
                }

                // Store the bytecode in the memory cache
                storedResults[ids.FullParametersId] = bytecode;
            }

            return(bytecode);
        }
Beispiel #19
0
 public EffectCompileRequest(string effectName, ShaderMixinParameters usedParameters)
 {
     EffectName     = effectName;
     UsedParameters = usedParameters;
 }
        private EffectBytecodeCompilerResult CompileBytecode(ShaderMixinSource mixinTree, CompilerParameters compilerParameters, ObjectId mixinObjectId, DatabaseFileProvider database, string compiledUrl, ShaderMixinParameters usedParameters)
        {
            // Open the database for writing
            var log = new LoggerResult();

            // Note: this compiler is expected to not be async and directly write stuff in localLogger
            var compiledShader = base.Compile(mixinTree, compilerParameters).WaitForResult();

            compiledShader.CompilationLog.CopyTo(log);

            // If there are any errors, return immediately
            if (log.HasErrors)
            {
                lock (compilingShaders)
                {
                    compilingShaders.Remove(mixinObjectId);
                }

                return(new EffectBytecodeCompilerResult(null, log));
            }

            // Compute the bytecodeId
            var newBytecodeId = compiledShader.Bytecode.ComputeId();

            // Check if we really need to store the bytecode
            lock (bytecodes)
            {
                // Using custom serialization to the database to store an object with a custom id
                // TODO: Check if we really need to write the bytecode everytime even if id is not changed
                var memoryStream = new MemoryStream();
                compiledShader.Bytecode.WriteTo(memoryStream);
                memoryStream.Position = 0;
                database.ObjectDatabase.Write(memoryStream, newBytecodeId, true);
                database.AssetIndexMap[compiledUrl] = newBytecodeId;

                // Save bytecode Id to the database cache as well
                memoryStream.SetLength(0);
                memoryStream.Write((byte[])newBytecodeId, 0, ObjectId.HashSize);
                memoryStream.Position = 0;
                database.ObjectDatabase.Write(memoryStream, mixinObjectId, true);

                if (!bytecodes.ContainsKey(newBytecodeId))
                {
                    log.Info("New effect compiled #{0} [{1}] (db: {2})\r\n{3}", effectCompileCount, mixinObjectId, newBytecodeId, usedParameters.ToStringDetailed());
                    Interlocked.Increment(ref effectCompileCount);

                    // Replace or add new bytecode
                    bytecodes[newBytecodeId] = compiledShader.Bytecode;
                }
            }

            lock (compilingShaders)
            {
                compilingShaders.Remove(mixinObjectId);
            }

            return(compiledShader);
        }
 public override EffectBytecode Compile(ShaderMixinSource mixin, string fullEffectName, ShaderMixinParameters compilerParameters, HashSet <string> modifiedShaders, HashSet <string> recentlyModifiedShaders, LoggerResult log)
 {
     throw new NotSupportedException("Shader Compilation is not allowed at run time on this platform.");
 }
Beispiel #22
0
 public override EffectBytecode Compile(ShaderMixinSource mixin, string fullEffectName, ShaderMixinParameters compilerParameters, HashSet <string> modifiedShaders, HashSet <string> recentlyModifiedShaders, LoggerResult log)
 {
     return(compiler.Compile(mixin, fullEffectName, compilerParameters, modifiedShaders, recentlyModifiedShaders, log));
 }
Beispiel #23
0
        /// <summary>
        /// Converts the hlsl code into glsl and stores the result as plain text
        /// </summary>
        /// <param name="shaderSource">the hlsl shader</param>
        /// <param name="entryPoint">the entrypoint function name</param>
        /// <param name="stage">the shader pipeline stage</param>
        /// <param name="compilerParameters"></param>
        /// <param name="reflection">the reflection gathered from the hlsl analysis</param>
        /// <param name="sourceFilename">the name of the source file</param>
        /// <returns></returns>
        public ShaderBytecodeResult Compile(string shaderSource, string entryPoint, ShaderStage stage, ShaderMixinParameters compilerParameters, EffectReflection reflection, string sourceFilename = null)
        {
            var isOpenGLES           = compilerParameters.Get(CompilerParameters.GraphicsPlatformKey) == GraphicsPlatform.OpenGLES;
            var isOpenGLES3          = compilerParameters.Get(CompilerParameters.GraphicsProfileKey) >= GraphicsProfile.Level_10_0;
            var shaderBytecodeResult = new ShaderBytecodeResult();

            byte[] rawData;

            var shader = Compile(shaderSource, entryPoint, stage, isOpenGLES, isOpenGLES3, shaderBytecodeResult, sourceFilename);

            if (shader == null)
            {
                return(shaderBytecodeResult);
            }

            if (isOpenGLES)
            {
                // store both ES 2 and ES 3 on OpenGL ES platforms
                var shaderBytecodes = new ShaderLevelBytecode();
                if (isOpenGLES3)
                {
                    shaderBytecodes.DataES3 = shader;
                    shaderBytecodes.DataES2 = null;
                }
                else
                {
                    shaderBytecodes.DataES2 = shader;
                    shaderBytecodes.DataES3 = Compile(shaderSource, entryPoint, stage, true, true, shaderBytecodeResult, sourceFilename);
                }
                using (var stream = new MemoryStream())
                {
                    BinarySerialization.Write(stream, shaderBytecodes);
                    rawData = stream.GetBuffer();
                }
            }
            else
            {
                // store string on OpenGL platforms
                rawData = Encoding.ASCII.GetBytes(shader);
            }

            var bytecodeId = ObjectId.FromBytes(rawData);
            var bytecode   = new ShaderBytecode(bytecodeId, rawData);

            bytecode.Stage = stage;

            shaderBytecodeResult.Bytecode = bytecode;

            return(shaderBytecodeResult);
        }
        public void TestShaderParametersSerialization()
        {
            // Test serialization
            var shaderParameters = new ShaderMixinParameters("Test");
            shaderParameters.Set(PropertyInt, 5);
            var subShaderParameters = new ShaderMixinParameters("Sub");
            subShaderParameters.Set(PropertyInt, 6);
            shaderParameters.Set(PropertySub, subShaderParameters);

            var subShaderParametersArray = new ShaderMixinParameters[1];
            var subShaderParametersArray1 = new ShaderMixinParameters("InArray1");
            subShaderParametersArray[0] = subShaderParametersArray1;
            subShaderParametersArray1.Set(PropertyInt, 7);
            shaderParameters.Set(PropertySubs, subShaderParametersArray);

            var memoryStream = new MemoryStream();
            var writer = new BinarySerializationWriter(memoryStream);
            writer.Write(shaderParameters);
            writer.Flush();
            memoryStream.Position = 0;

            var reader = new BinarySerializationReader(memoryStream);
            var shaderParametersReloaded = reader.Read<ShaderMixinParameters>();

            // They should be strictly equal
            Assert.That(shaderParametersReloaded.IsSubsetOf(shaderParameters), Is.True);
            Assert.That(shaderParameters.IsSubsetOf(shaderParametersReloaded), Is.True);

            // Test subset
            // Check that by removing one key from the original parameters, the reloaded version is
            // no longer a subset
            subShaderParametersArray1.Remove(PropertyInt);
            Assert.That(shaderParametersReloaded.IsSubsetOf(shaderParameters), Is.False);
        }
 /// <summary>
 /// Compiles the ShaderMixinSource into a platform bytecode.
 /// </summary>
 /// <param name="mixin">The ShaderMixinSource.</param>
 /// <param name="fullEffectName">The name of the effect.</param>
 /// <param name="compilerParameters">The parameters used for compilation.</param>
 /// <param name="modifiedShaders">The list of modified shaders.</param>
 /// <param name="recentlyModifiedShaders">The list of recently modified shaders.</param>
 /// <param name="log">The logger.</param>
 /// <returns>The platform-dependent bytecode.</returns>
 public abstract EffectBytecode Compile(ShaderMixinSource mixin, string fullEffectName, ShaderMixinParameters compilerParameters, HashSet <string> modifiedShaders, HashSet <string> recentlyModifiedShaders, LoggerResult log);
        public CompilerResults Compile(ShaderSource shaderSource, CompilerParameters compilerParameters, HashSet <string> modifiedShaders, HashSet <string> recentlyModifiedShaders)
        {
            ShaderMixinSourceTree mixinTree;
            var shaderMixinGeneratorSource = shaderSource as ShaderMixinGeneratorSource;
            var mainUsedParameters         = new ShaderMixinParameters();
            var usedParameters             = new List <ShaderMixinParameters>();

            string effectName = null;

            if (shaderMixinGeneratorSource != null)
            {
                effectName = shaderMixinGeneratorSource.Name;

                // 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
                if (modifiedShaders == null || modifiedShaders.Count == 0)
                {
                    // perform an early test only based on the parameters
                    var foundCompilerResults = GetShaderFromParameters(effectName, compilerParameters);
                    if (foundCompilerResults != null)
                    {
                        var earlyCompilerResults = new CompilerResults();
                        earlyCompilerResults.Module             = string.Format("EffectCompile [{0}]", effectName);
                        earlyCompilerResults.MainBytecode       = foundCompilerResults.MainBytecode;
                        earlyCompilerResults.MainUsedParameters = foundCompilerResults.MainUsedParameters;
                        foreach (var foundBytecode in foundCompilerResults.Bytecodes)
                        {
                            earlyCompilerResults.Bytecodes.Add(foundBytecode.Key, foundBytecode.Value);
                        }

                        foreach (var foundUsedParameters in foundCompilerResults.UsedParameters)
                        {
                            earlyCompilerResults.UsedParameters.Add(foundUsedParameters.Key, foundUsedParameters.Value);
                        }
                        return(earlyCompilerResults);
                    }
                }
                mixinTree = ShaderMixinManager.Generate(effectName, compilerParameters, out mainUsedParameters, out usedParameters);
            }
            else
            {
                effectName = "Effect";

                var shaderMixinSource = shaderSource as ShaderMixinSource;
                var shaderClassSource = shaderSource as ShaderClassSource;

                if (shaderClassSource != null)
                {
                    shaderMixinSource = new ShaderMixinSource();
                    shaderMixinSource.Mixins.Add(shaderClassSource);
                }

                if (shaderMixinSource != null)
                {
                    mixinTree = new ShaderMixinSourceTree()
                    {
                        Mixin = shaderMixinSource
                    };
                }
                else
                {
                    throw new ArgumentException("Unsupported ShaderSource type [{0}]. Supporting only ShaderMixinSource/pdxfx, ShaderClassSource", "shaderSource");
                }
            }

            // Copy global parameters to used Parameters by default, as it is used by the compiler
            mainUsedParameters.Set(CompilerParameters.GraphicsPlatformKey, compilerParameters.Platform);
            mainUsedParameters.Set(CompilerParameters.GraphicsProfileKey, compilerParameters.Profile);
            mainUsedParameters.Set(CompilerParameters.DebugKey, compilerParameters.Debug);

            foreach (var parameters in usedParameters)
            {
                parameters.Set(CompilerParameters.GraphicsPlatformKey, compilerParameters.Platform);
                parameters.Set(CompilerParameters.GraphicsProfileKey, compilerParameters.Profile);
                parameters.Set(CompilerParameters.DebugKey, compilerParameters.Debug);
            }

            // Compile the whole mixin tree
            var compilerResults = new CompilerResults();

            compilerResults.Module = string.Format("EffectCompile [{0}]", effectName);
            var wasCompiled = Compile(string.Empty, effectName, mixinTree, mainUsedParameters, usedParameters, modifiedShaders, recentlyModifiedShaders, compilerResults);

            if (wasCompiled && shaderMixinGeneratorSource != null)
            {
                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(compilerResults);
                }
            }

            return(compilerResults);
        }
        /// <summary>
        /// Compile the effect and its children.
        /// </summary>
        /// <param name="effectName">The name of the effect (without the base effect name).</param>
        /// <param name="fullEffectName">The full name of the effect (with the base effect name).</param>
        /// <param name="mixinTree">The ShaderMixinSourceTree.</param>
        /// <param name="mainCompilerParameters">The parameters used to create the main effect.</param>
        /// <param name="compilerParameters">The parameters used to create the child effects</param>
        /// <param name="modifiedShaders">The list of modified shaders since the beginning of the runtime.</param>
        /// <param name="recentlyModifiedShaders">The list of modified shaders that have not been replaced yet.</param>
        /// <param name="compilerResults">The result of the compilation.</param>
        /// <returns>true if the compilation succeded, false otherwise.</returns>
        protected virtual bool Compile(string effectName, string fullEffectName, ShaderMixinSourceTree mixinTree, ShaderMixinParameters mainCompilerParameters, List <ShaderMixinParameters> compilerParameters, HashSet <string> modifiedShaders, HashSet <string> recentlyModifiedShaders, CompilerResults compilerResults)
        {
            if (mixinTree.Mixin == null)
            {
                return(false);
            }

            var cp       = compilerParameters.FirstOrDefault(x => x.Name == fullEffectName);
            var bytecode = Compile(mixinTree.Mixin, fullEffectName, cp ?? mainCompilerParameters, modifiedShaders, recentlyModifiedShaders, compilerResults);

            var wasCompiled = false;

            if (bytecode != null)
            {
                if (effectName == string.Empty)
                {
                    compilerResults.MainBytecode       = bytecode;
                    compilerResults.MainUsedParameters = mainCompilerParameters;
                }
                compilerResults.Bytecodes.Add(effectName, bytecode);
                compilerResults.UsedParameters.Add(effectName, cp);

                wasCompiled = true;
            }

            foreach (var childTree in mixinTree.Children)
            {
                var childEffectName     = effectName == string.Empty ? childTree.Key : effectName + "." + childTree.Key;
                var fullChildEffectName = fullEffectName == string.Empty ? childTree.Key : fullEffectName + "." + childTree.Key;
                wasCompiled |= Compile(childEffectName, fullChildEffectName, childTree.Value, mainCompilerParameters, compilerParameters, modifiedShaders, recentlyModifiedShaders, compilerResults);
            }

            return(wasCompiled);
        }
Beispiel #28
0
        public ShaderBytecodeResult Compile(string shaderSource, string entryPoint, ShaderStage stage, ShaderMixinParameters compilerParameters, EffectReflection reflection, string sourceFilename = null)
        {
            var isDebug = compilerParameters.Get(CompilerParameters.DebugKey);
            var profile = compilerParameters.Get(CompilerParameters.GraphicsProfileKey);
            
            var shaderModel = ShaderStageToString(stage) + "_" + ShaderProfileFromGraphicsProfile(profile);

            var shaderFlags = ShaderFlags.None;
            if (isDebug)
            {
                shaderFlags = ShaderFlags.OptimizationLevel0 | ShaderFlags.Debug;
            }

            SharpDX.Configuration.ThrowOnShaderCompileError = false;

            // Compile using D3DCompiler
            var compilationResult = SharpDX.D3DCompiler.ShaderBytecode.Compile(shaderSource, entryPoint, shaderModel, shaderFlags, EffectFlags.None, null, null, sourceFilename);

            var byteCodeResult = new ShaderBytecodeResult();

            if (compilationResult.HasErrors)
            {
                // Log compilation errors
                byteCodeResult.Error(compilationResult.Message);
            }
            else
            {
                // As effect bytecode binary can changed when having debug infos (with d3dcompiler_47), we are calculating a bytecodeId on the stripped version
                var rawData = compilationResult.Bytecode.Strip(StripFlags.CompilerStripDebugInformation | StripFlags.CompilerStripReflectionData);
                var bytecodeId = ObjectId.FromBytes(rawData);
                byteCodeResult.Bytecode = new ShaderBytecode(bytecodeId, compilationResult.Bytecode.Data) { Stage = stage };

                // If compilation succeed, then we can update reflection.
                UpdateReflection(byteCodeResult.Bytecode, reflection, byteCodeResult);

                if (!string.IsNullOrEmpty(compilationResult.Message))
                {
                    byteCodeResult.Warning(compilationResult.Message);
                }
            }

            return byteCodeResult;
        }
        private EffectBytecodeCompilerResult CompileBytecode(ShaderMixinSource mixinTree, CompilerParameters compilerParameters, ObjectId mixinObjectId, DatabaseFileProvider database, string compiledUrl, ShaderMixinParameters usedParameters)
        {
            // Open the database for writing
            var log = new LoggerResult();

            // Note: this compiler is expected to not be async and directly write stuff in localLogger
            var compiledShader = base.Compile(mixinTree, compilerParameters).WaitForResult();
            compiledShader.CompilationLog.CopyTo(log);
            
            // If there are any errors, return immediately
            if (log.HasErrors)
            {
                lock (compilingShaders)
                {
                    compilingShaders.Remove(mixinObjectId);
                }

                return new EffectBytecodeCompilerResult(null, log);
            }

            // Compute the bytecodeId
            var newBytecodeId = compiledShader.Bytecode.ComputeId();

            // Check if we really need to store the bytecode
            lock (bytecodes)
            {
                // Using custom serialization to the database to store an object with a custom id
                // TODO: Check if we really need to write the bytecode everytime even if id is not changed
                var memoryStream = new MemoryStream();
                compiledShader.Bytecode.WriteTo(memoryStream);
                memoryStream.Position = 0;
                database.ObjectDatabase.Write(memoryStream, newBytecodeId, true);
                database.AssetIndexMap[compiledUrl] = newBytecodeId;

                // Save bytecode Id to the database cache as well
                memoryStream.SetLength(0);
                memoryStream.Write((byte[])newBytecodeId, 0, ObjectId.HashSize);
                memoryStream.Position = 0;
                database.ObjectDatabase.Write(memoryStream, mixinObjectId, true);

                if (!bytecodes.ContainsKey(newBytecodeId))
                {
                    log.Info("New effect compiled #{0} [{1}] (db: {2})\r\n{3}", effectCompileCount, mixinObjectId, newBytecodeId, usedParameters.ToStringDetailed());
                    Interlocked.Increment(ref effectCompileCount);

                    // Replace or add new bytecode
                    bytecodes[newBytecodeId] = compiledShader.Bytecode;
                }
            }

            lock (compilingShaders)
            {
                compilingShaders.Remove(mixinObjectId);
            }

            return compiledShader;
        }
Beispiel #30
0
        /// <summary>
        /// Converts the hlsl code into glsl and stores the result as plain text
        /// </summary>
        /// <param name="shaderSource">the hlsl shader</param>
        /// <param name="entryPoint">the entrypoint function name</param>
        /// <param name="stage">the shader pipeline stage</param>
        /// <param name="compilerParameters"></param>
        /// <param name="reflection">the reflection gathered from the hlsl analysis</param>
        /// <param name="sourceFilename">the name of the source file</param>
        /// <returns></returns>
        public ShaderBytecodeResult Compile(string shaderSource, string entryPoint, ShaderStage stage, ShaderMixinParameters compilerParameters, EffectReflection reflection, string sourceFilename = null)
        {
            var isOpenGLES           = compilerParameters.Get(CompilerParameters.GraphicsPlatformKey) == GraphicsPlatform.OpenGLES;
            var shaderBytecodeResult = new ShaderBytecodeResult();


            PipelineStage pipelineStage = PipelineStage.None;

            switch (stage)
            {
            case ShaderStage.Vertex:
                pipelineStage = PipelineStage.Vertex;
                break;

            case ShaderStage.Pixel:
                pipelineStage = PipelineStage.Pixel;
                break;

            case ShaderStage.Geometry:
                shaderBytecodeResult.Error("Geometry stage can't be converted to OpenGL. Only Vertex and Pixel shaders are supported");
                break;

            case ShaderStage.Hull:
                shaderBytecodeResult.Error("Hull stage can't be converted to OpenGL. Only Vertex and Pixel shaders are supported");
                break;

            case ShaderStage.Domain:
                shaderBytecodeResult.Error("Domain stage can't be converted to OpenGL. Only Vertex and Pixel shaders are supported");
                break;

            case ShaderStage.Compute:
                shaderBytecodeResult.Error("Compute stage can't be converted to OpenGL. Only Vertex and Pixel shaders are supported");
                break;

            default:
                shaderBytecodeResult.Error("Unknown shader profile.");
                break;
            }

            if (shaderBytecodeResult.HasErrors)
            {
                return(shaderBytecodeResult);
            }

            // Convert from HLSL to GLSL
            // Note that for now we parse from shader as a string, but we could simply clone effectPass.Shader to avoid multiple parsing.
            var glslConvertor = new ShaderConverter(isOpenGLES);
            var glslShader    = glslConvertor.Convert(shaderSource, entryPoint, pipelineStage, sourceFilename, shaderBytecodeResult);

            // Add std140 layout
            foreach (var constantBuffer in glslShader.Declarations.OfType <ConstantBuffer>())
            {
                constantBuffer.Qualifiers |= new LayoutQualifier(new LayoutKeyValue("std140"));
            }

            // Output the result
            var glslShaderWriter = new HlslToGlslWriter();

            if (isOpenGLES)
            {
                glslShaderWriter.TrimFloatSuffix       = true;
                glslShaderWriter.GenerateUniformBlocks = false;
                foreach (var variable in glslShader.Declarations.OfType <Variable>())
                {
                    if (variable.Qualifiers.Contains(ParameterQualifier.In))
                    {
                        variable.Qualifiers.Values.Remove(ParameterQualifier.In);
                        // "in" becomes "attribute" in VS, "varying" in other stages
                        variable.Qualifiers.Values.Add(
                            pipelineStage == PipelineStage.Vertex
                                ? global::SiliconStudio.Shaders.Ast.Glsl.ParameterQualifier.Attribute
                                : global::SiliconStudio.Shaders.Ast.Glsl.ParameterQualifier.Varying);
                    }
                    if (variable.Qualifiers.Contains(ParameterQualifier.Out))
                    {
                        variable.Qualifiers.Values.Remove(ParameterQualifier.Out);
                        variable.Qualifiers.Values.Add(global::SiliconStudio.Shaders.Ast.Glsl.ParameterQualifier.Varying);
                    }
                }
            }

            // Write shader
            glslShaderWriter.Visit(glslShader);

            // Build shader source
            var glslShaderCode = new StringBuilder();

            // Append some header depending on target
            if (!isOpenGLES)
            {
                glslShaderCode
                .AppendLine("#version 420")
                .AppendLine();

                if (pipelineStage == PipelineStage.Pixel)
                {
                    glslShaderCode
                    .AppendLine("out vec4 gl_FragData[1];")
                    .AppendLine();
                }
            }

            if (isOpenGLES)
            {
                if (pipelineStage == PipelineStage.Pixel)
                {
                    glslShaderCode
                    .AppendLine("precision highp float;")
                    .AppendLine();
                }
            }

            glslShaderCode.Append(glslShaderWriter.Text);

            var realShaderSource = glslShaderCode.ToString();

            // optimize shader
            var optShaderSource = RunOptimizer(realShaderSource, isOpenGLES, false, pipelineStage == PipelineStage.Vertex);

            if (!String.IsNullOrEmpty(optShaderSource))
            {
                realShaderSource = optShaderSource;
            }

            var rawData    = Encoding.ASCII.GetBytes(realShaderSource);
            var bytecodeId = ObjectId.FromBytes(rawData);
            var bytecode   = new ShaderBytecode(bytecodeId, rawData);

            bytecode.Stage = stage;

            shaderBytecodeResult.Bytecode = bytecode;
            return(shaderBytecodeResult);
        }
        public void TestSimpleChildParams()
        {
            var properties = new ShaderMixinParameters();
            properties.Set(Test4.TestParameters.TestCount, 0);
            ShaderMixinParameters usedProperties;

            var mixin = GenerateMixin("DefaultSimpleChildParams", properties, out usedProperties);
            mixin.CheckMixin("A", "B", "C");

            var childMixin = GenerateMixin("DefaultSimpleChildParams.ChildParamsMixin", properties, out usedProperties);
            childMixin.CheckMixin("A", "B", "C1");
            Assert.IsTrue(childMixin.UsedParameters.ContainsKey(Test4.TestParameters.TestCount));
            Assert.AreEqual(0, childMixin.UsedParameters.Get(Test4.TestParameters.TestCount));
        }
        public void TestMixinAndComposeKeys()
        {
            var properties = new ShaderMixinParameters();

            var subCompute1Key = TestABC.TestParameters.UseComputeColor2.ComposeWith("SubCompute1");
            var subCompute2Key = TestABC.TestParameters.UseComputeColor2.ComposeWith("SubCompute2");
            var subComputesKey = TestABC.TestParameters.UseComputeColorRedirect.ComposeWith("SubComputes[0]");

            properties.Set(subCompute1Key, true);
            properties.Set(subComputesKey, true);

            var mixin = GenerateMixin("test_mixin_compose_keys", properties);
            mixin.CheckMixin("A");

            Assert.AreEqual(3, mixin.Compositions.Count);

            Assert.IsTrue(mixin.Compositions.ContainsKey("SubCompute1"));
            Assert.IsTrue(mixin.Compositions.ContainsKey("SubCompute2"));
            Assert.IsTrue(mixin.Compositions.ContainsKey("SubComputes"));

            Assert.AreEqual("mixin ComputeColor2", mixin.Compositions["SubCompute1"].ToString());
            Assert.AreEqual("mixin ComputeColor", mixin.Compositions["SubCompute2"].ToString());
            Assert.AreEqual("[mixin ComputeColorRedirect [{ColorRedirect = mixin ComputeColor2}]]", mixin.Compositions["SubComputes"].ToString());
        }
Beispiel #33
0
        /// <summary>
        /// Generates the mixin.
        /// </summary>
        /// <param name="mixinName">Name of the mixin.</param>
        /// <param name="properties">The properties that the mixin will use.</param>
        /// <param name="usedProperties">The properties effectively used by the mixin.</param>
        /// <returns>ShaderMixinSource.</returns>
        private static ShaderMixinSourceTree GenerateMixin(string mixinName, ParameterCollection properties, out ShaderMixinParameters usedProperties)
        {
            var allUsedProperties = new List <ShaderMixinParameters>();
            var mixin             = ShaderMixinManager.Generate(mixinName, properties);

            usedProperties = mixin.UsedParameters;

            // Verify that output used properties are a subset of input properties
            Assert.That(usedProperties.IsSubsetOf(properties), Is.True);

            foreach (var usedProps in allUsedProperties)
            {
                Assert.That(usedProps.IsSubsetOf(properties), Is.True);
            }

            return(mixin);
        }