コード例 #1
0
        private Effect CreateEffect(string effectName, EffectBytecode bytecode, ShaderMixinParameters usedParameters)
        {
            Effect effect;

            lock (cachedEffects)
            {
                if (!cachedEffects.TryGetValue(bytecode, out effect))
                {
                    effect = new Effect(graphicsDeviceService.GraphicsDevice, bytecode, usedParameters)
                    {
                        Name = effectName
                    };
                    cachedEffects.Add(bytecode, effect);

#if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP
                    foreach (var type in bytecode.HashSources.Keys)
                    {
                        // TODO: the "/path" is hardcoded, used in ImportStreamCommand and ShaderSourceManager. Find a place to share this correctly.
                        using (var pathStream = Asset.OpenAsStream(EffectCompilerBase.GetStoragePathFromShaderType(type) + "/path"))
                            using (var reader = new StreamReader(pathStream))
                            {
                                var path = reader.ReadToEnd();
                                directoryWatcher.Track(path);
                            }
                    }
#endif
                }
            }
            return(effect);
        }
コード例 #2
0
ファイル: EffectNodeFactory.cs プロジェクト: vvvv/VL.Stride
 public string GetPathOfXkslShader(string effectName)
 {
     using (var pathStream = FileProvider.OpenStream(EffectCompilerBase.GetStoragePathFromShaderType(effectName) + "/path", VirtualFileMode.Open, VirtualFileAccess.Read))
         using (var reader = new StreamReader(pathStream))
         {
             return(reader.ReadToEnd());
         }
 }
コード例 #3
0
        private Effect CreateEffect(string effectName, EffectBytecodeCompilerResult effectBytecodeCompilerResult, CompilerResults compilerResult)
        {
            Effect effect;

            lock (cachedEffects)
            {
                if (!isInitialized)
                {
                    throw new InvalidOperationException("EffectSystem has been disposed. This Effect compilation has been cancelled.");
                }

                var usedParameters = compilerResult.UsedParameters;

                if (effectBytecodeCompilerResult.CompilationLog.HasErrors)
                {
                    // Unregister result (or should we keep it so that failure never change?)
                    List <CompilerResults> effectCompilerResults;
                    if (earlyCompilerCache.TryGetValue(effectName, out effectCompilerResults))
                    {
                        effectCompilerResults.Remove(compilerResult);
                    }
                }

                CheckResult(effectBytecodeCompilerResult.CompilationLog);

                var bytecode = effectBytecodeCompilerResult.Bytecode;
                if (bytecode == null)
                {
                    throw new InvalidOperationException("EffectCompiler returned no shader and no compilation error.");
                }

                if (!cachedEffects.TryGetValue(bytecode, out effect))
                {
                    effect = new Effect(graphicsDeviceService.GraphicsDevice, bytecode, usedParameters)
                    {
                        Name = effectName
                    };
                    cachedEffects.Add(bytecode, effect);

#if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP
                    foreach (var type in bytecode.HashSources.Keys)
                    {
                        // TODO: the "/path" is hardcoded, used in ImportStreamCommand and ShaderSourceManager. Find a place to share this correctly.
                        using (var pathStream = FileProvider.OpenStream(EffectCompilerBase.GetStoragePathFromShaderType(type) + "/path", VirtualFileMode.Open, VirtualFileAccess.Read))
                            using (var reader = new StreamReader(pathStream))
                            {
                                var path = reader.ReadToEnd();
                                directoryWatcher.Track(path);
                            }
                    }
#endif
                }
            }
            return(effect);
        }
コード例 #4
0
ファイル: EffectNodeFactory.cs プロジェクト: vvvv/VL.Stride
        public CompilerResults GetCompilerResults(string effectName, CompilerParameters compilerParameters)
        {
            if (effectName == null)
            {
                throw new ArgumentNullException("effectName");
            }
            if (compilerParameters == null)
            {
                throw new ArgumentNullException("compilerParameters");
            }

            // Setup compilation parameters
            compilerParameters.EffectParameters.Platform = GraphicsDevice.Platform;
            compilerParameters.EffectParameters.Profile  = DeviceManager?.ShaderProfile ?? GraphicsDevice.Features.RequestedProfile;
            // Copy optimization/debug levels
            compilerParameters.EffectParameters.OptimizationLevel = effectCompilerParameters.OptimizationLevel;
            compilerParameters.EffectParameters.Debug             = effectCompilerParameters.Debug;

            var source          = GetShaderSource(effectName);
            var compiler        = EffectSystem.Compiler;
            var compilerResults = compiler.Compile(source, compilerParameters);

            // Watch the source code files
            var effectBytecodeCompilerResult = compilerResults.Bytecode.WaitForResult();

            if (effectBytecodeCompilerResult.CompilationLog.HasErrors)
            {
                foreach (var m in effectBytecodeCompilerResult.CompilationLog.Messages)
                {
                    if (TryGetFilePath(m, out string path))
                    {
                        directoryWatcher.Track(path);
                    }
                }
            }
            else
            {
                var bytecode = effectBytecodeCompilerResult.Bytecode;
                foreach (var type in bytecode.HashSources.Keys)
                {
                    // TODO: the "/path" is hardcoded, used in ImportStreamCommand and ShaderSourceManager. Find a place to share this correctly.
                    using (var pathStream = FileProvider.OpenStream(EffectCompilerBase.GetStoragePathFromShaderType(type) + "/path", VirtualFileMode.Open, VirtualFileAccess.Read))
                        using (var reader = new StreamReader(pathStream))
                        {
                            var path = reader.ReadToEnd();
                            directoryWatcher.Track(path);
                        }
                }
            }

            return(compilerResults);
        }
コード例 #5
0
        public static string GetPathOfSdslShader(string effectName, IVirtualFileProvider fileProvider, IVirtualFileProvider dbFileProvider = null)
        {
            var path = EffectCompilerBase.GetStoragePathFromShaderType(effectName);

            if (fileProvider.TryGetFileLocation(path, out var filePath, out _, out _))
            {
                if (File.Exists(filePath))
                {
                    return(filePath);
                }
            }

            var pathUrl = path + "/path";

            if (fileProvider.FileExists(pathUrl))
            {
                using (var pathStream = fileProvider.OpenStream(pathUrl, VirtualFileMode.Open, VirtualFileAccess.Read))
                    using (var reader = new StreamReader(pathStream))
                    {
                        var dbPath = reader.ReadToEnd();
                        if (File.Exists(dbPath))
                        {
                            return(dbPath);
                        }
                    }
            }

            if (dbFileProvider != null)
            {
                return(GetPathOfSdslShader(effectName, dbFileProvider));
            }

            //find locally
            if (LocalShaderFilePaths.TryGetValue(effectName, out var fp))
            {
                return(fp);
            }

            return(null);
        }
コード例 #6
0
        protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
        {
            var compiler = GetOrCreateEffectCompiler(context);

            // Get main effect name (before the first dot)
            var isSdfx = ShaderMixinManager.Contains(effectName);
            var source = isSdfx ?
                         new ShaderMixinGeneratorSource(effectName) :
                         (ShaderSource) new ShaderClassSource(effectName);

            int permutationCount;

            lock (PermutationCount)
            {
                PermutationCount.TryGetValue(effectName, out permutationCount);
                permutationCount++;
                PermutationCount[effectName] = permutationCount;
            }
            commandContext.Logger.Verbose($"Trying permutation #{permutationCount} for effect [{effectName}]: \n{compilerParameters.ToStringPermutationsDetailed()}");

            var compilerResults = compiler.Compile(source, compilerParameters);

            // Copy logs and if there are errors, exit directly
            compilerResults.CopyTo(commandContext.Logger);
            if (compilerResults.HasErrors)
            {
                return(Task.FromResult(ResultStatus.Failed));
            }

            // Wait for result an check compilation status
            var completedTask = compilerResults.Bytecode.WaitForResult();

            completedTask.CompilationLog.CopyTo(commandContext.Logger);
            if (completedTask.CompilationLog.HasErrors)
            {
                return(Task.FromResult(ResultStatus.Failed));
            }

            // Register all dependencies
            var allSources = new HashSet <string>(
                completedTask.Bytecode.HashSources.Select(keyPair => keyPair.Key));

            foreach (var className in allSources)
            {
                commandContext.RegisterInputDependency(new ObjectUrl(UrlType.Content, EffectCompilerBase.GetStoragePathFromShaderType(className)));
            }

            // Generate sourcecode if configured
            if (compilerParameters.ContainsKey(EffectSourceCodeKeys.Enable))
            {
                var outputDirectory = UPath.Combine(package.RootDirectory, baseUrl);

                var fieldName = compilerParameters.Get(EffectSourceCodeKeys.FieldName);
                if (fieldName.StartsWith("binary"))
                {
                    fieldName = fieldName.Substring("binary".Length);
                    if (char.IsUpper(fieldName[0]))
                    {
                        fieldName = char.ToLower(fieldName[0]) + fieldName.Substring(1);
                    }
                }

                var outputClassFile     = effectName + "." + fieldName + "." + compilerParameters.EffectParameters.Platform + "." + compilerParameters.EffectParameters.Profile + ".cs";
                var fullOutputClassFile = Path.Combine(outputDirectory.ToWindowsPath(), outputClassFile);

                commandContext.Logger.Verbose($"Writing shader bytecode to .cs source [{fullOutputClassFile}].");
                using (var stream = new FileStream(fullOutputClassFile, FileMode.Create, FileAccess.Write, FileShare.Write))
                    EffectByteCodeToSourceCodeWriter.Write(effectName, compilerParameters, compilerResults.Bytecode.WaitForResult().Bytecode, new StreamWriter(stream, System.Text.Encoding.UTF8));
            }

            return(Task.FromResult(ResultStatus.Successful));
        }
コード例 #7
0
        protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
        {
            var compiler = GetOrCreateEffectCompiler(context);

            // Get main effect name (before the first dot)
            var isPdxfx = ShaderMixinManager.Contains(effectName);
            var source  = isPdxfx ? new ShaderMixinGeneratorSource(effectName) : (ShaderSource) new ShaderClassSource(effectName);

            int permutationCount;

            lock (PermutationCount)
            {
                PermutationCount.TryGetValue(effectName, out permutationCount);
                permutationCount++;
                PermutationCount[effectName] = permutationCount;
            }
            commandContext.Logger.Info("Trying permutation #{0} for effect [{1}]: \n{2}", permutationCount, effectName, compilerParameters.ToStringDetailed());

            var compilerResults = compiler.Compile(source, compilerParameters);

            // Copy logs and if there are errors, exit directlry
            compilerResults.CopyTo(commandContext.Logger);
            if (compilerResults.HasErrors)
            {
                return(Task.FromResult(ResultStatus.Failed));
            }

            // Register all dependencies
            var allSources = new HashSet <string>(compilerResults.Bytecode.WaitForResult().Bytecode.HashSources.Select(keyPair => keyPair.Key));

            foreach (var className in allSources)
            {
                commandContext.RegisterInputDependency(new ObjectUrl(UrlType.Internal, EffectCompilerBase.GetStoragePathFromShaderType(className)));
            }

            // Generate sourcecode if configured
            if (compilerParameters.ContainsKey(EffectSourceCodeKeys.Enable))
            {
                var outputDirectory     = UPath.Combine(context.Package.RootDirectory, baseUrl);
                var outputClassFile     = effectName + ".bytecode." + compilerParameters.Platform + "." + compilerParameters.Profile + ".cs";
                var fullOutputClassFile = Path.Combine(outputDirectory.ToWindowsPath(), outputClassFile);

                commandContext.Logger.Info("Writing shader bytecode to .cs source [{0}]", fullOutputClassFile);
                using (var stream = new FileStream(fullOutputClassFile, FileMode.Create, FileAccess.Write, FileShare.Write))
                    EffectByteCodeToSourceCodeWriter.Write(effectName, compilerParameters, compilerResults.Bytecode.WaitForResult().Bytecode, new StreamWriter(stream, System.Text.Encoding.UTF8));
            }

            return(Task.FromResult(ResultStatus.Successful));
        }