diff --git a/sources/engine/Xenko.Assets/Materials/MaterialAssetCompiler.cs b/sources/engine/Xenko.Assets/Materials/MaterialAssetCompiler.cs index dfa365a9ee..fd7306ed91 100644 --- a/sources/engine/Xenko.Assets/Materials/MaterialAssetCompiler.cs +++ b/sources/engine/Xenko.Assets/Materials/MaterialAssetCompiler.cs @@ -53,7 +53,7 @@ private class MaterialCompileCommand : AssetCommand public MaterialCompileCommand(string url, AssetItem assetItem, MaterialAsset value, AssetCompilerContext context) : base(url, value, assetItem.Package) { - Version = 4; + Version = 5; this.assetItem = assetItem; colorSpace = context.GetColorSpace(); assetUrl = new UFile(url); diff --git a/sources/engine/Xenko.Assets/XenkoPackageUpgrader.cs b/sources/engine/Xenko.Assets/XenkoPackageUpgrader.cs index 4b0ed7c086..3b7d26c98a 100644 --- a/sources/engine/Xenko.Assets/XenkoPackageUpgrader.cs +++ b/sources/engine/Xenko.Assets/XenkoPackageUpgrader.cs @@ -40,6 +40,24 @@ public partial class XenkoPackageUpgrader : PackageUpgrader public override bool Upgrade(PackageLoadParameters loadParameters, PackageSession session, ILogger log, Package dependentPackage, PackageDependency dependency, Package dependencyPackage, IList assetFiles) { + if (dependency.Version.MinVersion < new PackageVersion("3.1.0.2-beta01")) + { + foreach (var assetFile in assetFiles) + { + // Add new generic parameter to ShadowMapReceiverDirectional in effect log + if (assetFile.FilePath.GetFileExtension() == ".xkeffectlog") + { + var assetContent = assetFile.AssetContent ?? File.ReadAllBytes(assetFile.FilePath.FullPath); + var assetContentString = System.Text.Encoding.UTF8.GetString(assetContent); + var newAssetContentString = System.Text.RegularExpressions.Regex.Replace(assetContentString, @"([ ]*)- ClassName:", "$1- !ShaderClassSource\r\n$1 ClassName:"); + if (assetContentString != newAssetContentString) + { + // Need replacement, update with replaced text + assetFile.AssetContent = System.Text.Encoding.UTF8.GetBytes(newAssetContentString); + } + } + } + } return true; } diff --git a/sources/engine/Xenko.Rendering/Rendering/Materials/ComputeColors/ComputeBinaryBase.cs b/sources/engine/Xenko.Rendering/Rendering/Materials/ComputeColors/ComputeBinaryBase.cs index 06c31be030..dc0fc3bd8e 100644 --- a/sources/engine/Xenko.Rendering/Rendering/Materials/ComputeColors/ComputeBinaryBase.cs +++ b/sources/engine/Xenko.Rendering/Rendering/Materials/ComputeColors/ComputeBinaryBase.cs @@ -82,8 +82,8 @@ public override IEnumerable GetChildren(object context = null) public override ShaderSource GenerateShaderSource(ShaderGeneratorContext context, MaterialComputeColorKeys baseKeys) { - var leftShaderSource = LeftChild.GenerateShaderSource(context, baseKeys); - var rightShaderSource = RightChild.GenerateShaderSource(context, baseKeys); + var leftShaderSource = LeftChild?.GenerateShaderSource(context, baseKeys); + var rightShaderSource = RightChild?.GenerateShaderSource(context, baseKeys); var shaderSource = new ShaderClassSource(GetCorrespondingShaderSourceName(Operator)); var mixin = new ShaderMixinSource(); diff --git a/sources/engine/Xenko.Rendering/Rendering/Materials/ComputeColors/ComputeColors.cd b/sources/engine/Xenko.Rendering/Rendering/Materials/ComputeColors/ComputeColors.cd index 7b8d1a84f7..bd0e0d1fd7 100644 --- a/sources/engine/Xenko.Rendering/Rendering/Materials/ComputeColors/ComputeColors.cd +++ b/sources/engine/Xenko.Rendering/Rendering/Materials/ComputeColors/ComputeColors.cd @@ -17,7 +17,7 @@ - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + AAAAAAAAAAQAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAA= Rendering\Materials\ComputeColors\ComputeBinaryColor.cs @@ -33,7 +33,7 @@ - AAAAAAAEAAAAAAAEAAAAAAAAAAAAAAAAAAIAAAAAAAA= + IAAAAAAEAAAAAIAEIAAAAAAABAAAAAAAAAIAAAAAAAA= Rendering\Materials\ComputeColors\ComputeColor.cs @@ -49,7 +49,7 @@ - AAAAAAAEAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAA= + IAAAAAAEAAQAAAAEIAAAAAAAAAAAAAAAAAAAAAAAAAA= Rendering\Materials\ComputeColors\ComputeFloat4.cs @@ -72,14 +72,14 @@ - AACAAAAGAACIAAAEACAAAAAAAQAQQAAAAAAEgAAAgAA= + AAAAAAAGAAAAAAAEACAAAAAAAAAAQAAAAAAEAAAAgAA= Rendering\Materials\ComputeColors\ComputeShaderClassBase.cs - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + AAgAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAA= Rendering\Materials\ComputeColors\ComputeShaderClassColor.cs @@ -95,14 +95,14 @@ - AAAAAAAEAAAQAAAEAAIAAAAAAAACAAAQAAIAIAIAgAA= + AAAAAAAUAAAQAIAEAAIgAAAAAAACAAAQAAIAIAIAgAA= Rendering\Materials\ComputeColors\ComputeTextureBase.cs - AAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + IAAIAAAQAgAQAAAAIAAAAAAAAAAAAAAAAAAAAAEAAAA= Rendering\Materials\ComputeColors\ComputeTextureColor.cs @@ -110,24 +110,24 @@ - AAAAAAAgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + AAAIAAAwAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= Rendering\Materials\ComputeColors\ComputeTextureScalar.cs - + AAAEAAAEAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAA= - Rendering\Materials\ComputeColors\ComputeStreamBase.cs + Rendering\Materials\ComputeColors\ComputeVertexStreamBase.cs - + - AAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Rendering\Materials\ComputeColors\ComputeStreamColor.cs + AAAEAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Rendering\Materials\ComputeColors\ComputeVertexStreamScalar.cs @@ -156,15 +156,15 @@ - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + AAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAA= Rendering\Materials\IComputeColor.cs - - + + AAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAA= - Rendering\Materials\ComputeColors\IComputeStream.cs + Rendering\Materials\ComputeColors\IComputeVertexStream.cs diff --git a/sources/engine/Xenko.Rendering/Rendering/Materials/MaterialBlendLayerContext.cs b/sources/engine/Xenko.Rendering/Rendering/Materials/MaterialBlendLayerContext.cs index b269797d5b..ac2f1d0abc 100644 --- a/sources/engine/Xenko.Rendering/Rendering/Materials/MaterialBlendLayerContext.cs +++ b/sources/engine/Xenko.Rendering/Rendering/Materials/MaterialBlendLayerContext.cs @@ -155,14 +155,14 @@ public ShaderSource GenerateStreamInitializers(MaterialShaderStage stage) // the streams coming from the material layers foreach (var streamInitializer in stageContext.StreamInitializers) { - mixin.Mixins.Add(streamInitializer); + mixin.Mixins.Add(new ShaderClassSource(streamInitializer)); } stageContext.StreamInitializers.Clear(); // the streams specific to a stage // TODO: Use StreamInitializers instead of streams initializers hardcoded in MaterialPixelShadingStream.ResetStream if (stage == MaterialShaderStage.Pixel) - mixin.Mixins.Add("MaterialPixelShadingStream"); + mixin.Mixins.Add(new ShaderClassSource("MaterialPixelShadingStream")); return mixin; } diff --git a/sources/engine/Xenko.Rendering/Rendering/Materials/Materials.cd b/sources/engine/Xenko.Rendering/Rendering/Materials/Materials.cd index b609febb56..981c2f4410 100644 --- a/sources/engine/Xenko.Rendering/Rendering/Materials/Materials.cd +++ b/sources/engine/Xenko.Rendering/Rendering/Materials/Materials.cd @@ -6,92 +6,15 @@ @@ -488,7 +397,7 @@ - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + AAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= Rendering\Materials\IMaterialFeature.cs @@ -539,7 +448,7 @@ - AAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= Rendering\Materials\IMaterialShadingModelFeature.cs @@ -556,6 +465,8 @@ + + @@ -578,6 +489,8 @@ + + diff --git a/sources/engine/Xenko.Rendering/Rendering/Materials/ShadingModelShaderBuilder.cs b/sources/engine/Xenko.Rendering/Rendering/Materials/ShadingModelShaderBuilder.cs index d88af0fc7b..89e8b66729 100644 --- a/sources/engine/Xenko.Rendering/Rendering/Materials/ShadingModelShaderBuilder.cs +++ b/sources/engine/Xenko.Rendering/Rendering/Materials/ShadingModelShaderBuilder.cs @@ -20,4 +20,4 @@ public class ShadingModelShaderBuilder public ShaderSource LightDependentSurface { get; set; } } -} \ No newline at end of file +} diff --git a/sources/engine/Xenko.Shaders.Compiler/ShaderSourceComparer.cs b/sources/engine/Xenko.Shaders.Compiler/ShaderSourceComparer.cs index 65966bc5ce..f5dc44062e 100644 --- a/sources/engine/Xenko.Shaders.Compiler/ShaderSourceComparer.cs +++ b/sources/engine/Xenko.Shaders.Compiler/ShaderSourceComparer.cs @@ -28,10 +28,10 @@ public override bool Equals(ShaderSource x, ShaderSource y) if (x.GetType() != y.GetType()) return false; - if (x is ShaderClassSource) + if (x is ShaderClassCode) { - var x1 = (ShaderClassSource)x; - var y1 = (ShaderClassSource)y; + var x1 = (ShaderClassCode)x; + var y1 = (ShaderClassCode)y; return x1.ClassName == y1.ClassName && ArrayExtensions.ArraysEqual(x1.GenericArguments, y1.GenericArguments); } @@ -59,9 +59,9 @@ public override int GetHashCode(ShaderSource obj) unchecked { - if (obj is ShaderClassSource) + if (obj is ShaderClassCode) { - var obj1 = (ShaderClassSource)obj; + var obj1 = (ShaderClassCode)obj; return obj1.ClassName.GetHashCode() ^ ArrayExtensions.ComputeHash(obj1.GenericArguments); } diff --git a/sources/engine/Xenko.Shaders.Parser/Mixins/ModuleMixinInfo.cs b/sources/engine/Xenko.Shaders.Parser/Mixins/ModuleMixinInfo.cs index 98b3094add..a428103476 100644 --- a/sources/engine/Xenko.Shaders.Parser/Mixins/ModuleMixinInfo.cs +++ b/sources/engine/Xenko.Shaders.Parser/Mixins/ModuleMixinInfo.cs @@ -67,13 +67,13 @@ public ShaderClassType MixinAst } /// - /// Tests if this instance is a of the specified type name + /// Tests if this instance is a of the specified type name /// /// The type name to test /// true if same type name public bool IsShaderClass(string typeName) { - var classSource = ShaderSource as ShaderClassSource; + var classSource = ShaderSource as ShaderClassCode; if (classSource == null) { return false; diff --git a/sources/engine/Xenko.Shaders.Parser/Mixins/ShaderLoader.cs b/sources/engine/Xenko.Shaders.Parser/Mixins/ShaderLoader.cs index a7b836decf..8309639820 100644 --- a/sources/engine/Xenko.Shaders.Parser/Mixins/ShaderLoader.cs +++ b/sources/engine/Xenko.Shaders.Parser/Mixins/ShaderLoader.cs @@ -92,7 +92,7 @@ public class LoadedShaderClassType /// /// A ShaderClassType or null if there was some errors. /// shaderClassSource - public LoadedShaderClassType LoadClassSource(ShaderClassSource shaderClassSource, Xenko.Core.Shaders.Parser.ShaderMacro[] shaderMacros, LoggerResult log, bool autoGenericInstances) + public LoadedShaderClassType LoadClassSource(ShaderClassCode shaderClassSource, Xenko.Core.Shaders.Parser.ShaderMacro[] shaderMacros, LoggerResult log, bool autoGenericInstances) { if (shaderClassSource == null) throw new ArgumentNullException("shaderClassSource"); @@ -103,7 +103,7 @@ public LoadedShaderClassType LoadClassSource(ShaderClassSource shaderClassSource foreach (var gen in shaderClassSource.GenericArguments) generics += "___" + gen; } - var shaderClassType = LoadShaderClass(shaderClassSource.ClassName, generics, log, shaderMacros); + var shaderClassType = LoadShaderClass(shaderClassSource, generics, log, shaderMacros); if (shaderClassType == null) return null; @@ -275,7 +275,7 @@ Expression CreateExpressionFromString(string name) return (Expression)result.Root.AstNode; } - private LoadedShaderClassType LoadShaderClass(ShaderClassSource classSource, string generics, LoggerResult log, Xenko.Core.Shaders.Parser.ShaderMacro[] macros = null) + private LoadedShaderClassType LoadShaderClass(ShaderClassCode classSource, string generics, LoggerResult log, Xenko.Core.Shaders.Parser.ShaderMacro[] macros = null) { var type = classSource.ClassName; if (type == null) throw new ArgumentNullException("type"); @@ -291,8 +291,14 @@ private LoadedShaderClassType LoadShaderClass(ShaderClassSource classSource, str return shaderClass; } - // Load file - var shaderSource = SourceManager.LoadShaderSource(type); + ShaderSourceManager.ShaderSourceWithHash shaderSource; + + // Load shader source code + if (classSource is ShaderClassString shaderClassString) + shaderSource = SourceManager.LoadShaderSource(type, shaderClassString.ShaderSourceCode); + else + shaderSource = SourceManager.LoadShaderSource(type); + string preprocessedSource; try { @@ -405,7 +411,7 @@ private static string GenerateGenericClassName(ShaderClassType shaderClassType) return shaderClassType.Name.Text + (shaderClassType.GenericParameters == null ? string.Empty : "_" + string.Join("_", shaderClassType.GenericParameters.Select(x => x.ToString().Replace('.', '_')))); } - private static string GenerateGenericClassName(ShaderClassSource source) + private static string GenerateGenericClassName(ShaderClassCode source) { // Generate class name if (source.GenericArguments != null && source.GenericArguments.Length > 0) diff --git a/sources/engine/Xenko.Shaders.Parser/Mixins/ShaderSourceManager.cs b/sources/engine/Xenko.Shaders.Parser/Mixins/ShaderSourceManager.cs index f7c922fc84..ef5825a03f 100644 --- a/sources/engine/Xenko.Shaders.Parser/Mixins/ShaderSourceManager.cs +++ b/sources/engine/Xenko.Shaders.Parser/Mixins/ShaderSourceManager.cs @@ -112,16 +112,21 @@ public static ShaderSourceWithHash CreateShaderSourceWithHash(string type, strin /// Loads the shader source with the specified type name. /// /// The typeName. + /// Optional shader source code. Can be use for shaders that don't have a source file /// ShaderSourceWithHash. /// If the file was not found - public ShaderSourceWithHash LoadShaderSource(string type) + public ShaderSourceWithHash LoadShaderSource(string type, string shaderSourceCode = null) { lock (locker) { - // Load file ShaderSourceWithHash shaderSource; if (!loadedShaderSources.TryGetValue(type, out shaderSource)) { + // Load from string + if (!string.IsNullOrWhiteSpace(shaderSourceCode)) + return CreateShaderSourceWithHash(type, shaderSourceCode); + + // Load file var sourceUrl = FindFilePath(type); if (sourceUrl != null) { diff --git a/sources/engine/Xenko.Shaders.Parser/Mixins/XenkoShaderLibrary.cs b/sources/engine/Xenko.Shaders.Parser/Mixins/XenkoShaderLibrary.cs index 99baf94d34..244fe2009c 100644 --- a/sources/engine/Xenko.Shaders.Parser/Mixins/XenkoShaderLibrary.cs +++ b/sources/engine/Xenko.Shaders.Parser/Mixins/XenkoShaderLibrary.cs @@ -148,7 +148,7 @@ private void ExtendLibrary(ShaderSource shaderSource, Xenko.Core.Shaders.Parser. foreach (var composition in ((ShaderMixinSource)shaderSource).Compositions) ExtendLibrary(composition.Value, newMacros, mixinToAnalyze); } - else if (shaderSource is ShaderClassSource) + else if (shaderSource is ShaderClassCode) mixinToAnalyze.Add(GetModuleMixinInfo(shaderSource, macros)); else if (shaderSource is ShaderArraySource) { @@ -261,9 +261,9 @@ private ModuleMixinInfo BuildMixinInfo(ShaderSource shaderSource, Xenko.Core.Sha { ModuleMixinInfo mixinInfo = null; - if (shaderSource is ShaderClassSource) + if (shaderSource is ShaderClassCode) { - var shaderClassSource = shaderSource as ShaderClassSource; + var shaderClassSource = shaderSource as ShaderClassCode; mixinInfo = new ModuleMixinInfo { ShaderSource = shaderClassSource, Macros = macros }; LoadMixinFromClassSource(mixinInfo); } @@ -305,7 +305,7 @@ private ModuleMixinInfo BuildMixinInfo(ShaderSource shaderSource, Xenko.Core.Sha /// the ModuleMixinInfo private void LoadMixinFromClassSource(ModuleMixinInfo mixinInfo) { - var classSource = (ShaderClassSource)mixinInfo.ShaderSource; + var classSource = (ShaderClassCode)mixinInfo.ShaderSource; // If we allow to parse non instantiated generics, put empty generic arguments to let the ShaderLoader correctly expand the class var shaderClass = ShaderLoader.LoadClassSource(classSource, mixinInfo.Macros, mixinInfo.Log, AllowNonInstantiatedGenerics); diff --git a/sources/engine/Xenko.Shaders.Parser/ShaderMixinParser.cs b/sources/engine/Xenko.Shaders.Parser/ShaderMixinParser.cs index 775566779e..589dd9d232 100644 --- a/sources/engine/Xenko.Shaders.Parser/ShaderMixinParser.cs +++ b/sources/engine/Xenko.Shaders.Parser/ShaderMixinParser.cs @@ -135,7 +135,7 @@ internal ShaderCompilationContext ParseAndAnalyze(ShaderMixinSource shaderMixinS moduleMixinInfo.Log.CopyTo(parsingResult); var ast = moduleMixinInfo.MixinAst; - var shaderClassSource = moduleMixinInfo.ShaderSource as ShaderClassSource; + var shaderClassSource = moduleMixinInfo.ShaderSource as ShaderClassCode; // If we have a ShaderClassSource and it is not an inline one, then we can store the hash sources if (ast != null && shaderClassSource != null) { @@ -362,7 +362,7 @@ private static List BuildCompositionsDictionary(ShaderSource shader } - if (shaderSource is ShaderClassSource) + if (shaderSource is ShaderClassCode) { var finalModule = compilationContext.GetModuleMixinFromShaderSource(shaderSource); diff --git a/sources/engine/Xenko.Shaders.Tests/TestMixinGenerator.Extensions.cs b/sources/engine/Xenko.Shaders.Tests/TestMixinGenerator.Extensions.cs index 89b7befad6..e565b1dbab 100644 --- a/sources/engine/Xenko.Shaders.Tests/TestMixinGenerator.Extensions.cs +++ b/sources/engine/Xenko.Shaders.Tests/TestMixinGenerator.Extensions.cs @@ -39,7 +39,7 @@ public static void CheckComposition(this ShaderMixinSource mixin, string key, st Assert.True(source != null, $"Source composition for key [{key}] cannot be null"); - var classSource = source as ShaderClassSource; + var classSource = source as ShaderClassCode; if (classSource != null) { var sourceString = classSource.ToClassName(); diff --git a/sources/engine/Xenko.Shaders.Tests/TestShaderLoadingString.cs b/sources/engine/Xenko.Shaders.Tests/TestShaderLoadingString.cs new file mode 100644 index 0000000000..d1dea31165 --- /dev/null +++ b/sources/engine/Xenko.Shaders.Tests/TestShaderLoadingString.cs @@ -0,0 +1,81 @@ +// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. +using System.IO; + +using Xunit; + +using Xenko.Core.Diagnostics; +using Xenko.Core.IO; +using Xenko.Core.Serialization.Contents; +using Xenko.Core.Storage; +using Xenko.Core.Mathematics; +using Xenko.Games; +using Xenko.Shaders.Parser.Mixins; + +using LoggerResult = Xenko.Core.Shaders.Utility.LoggerResult; + +namespace Xenko.Shaders.Tests +{ + public class TestShaderLoadingString + { + private ShaderSourceManager sourceManager; + private ShaderLoader shaderLoader; + + + const string ShaderSourceName = "ConstantCol"; + const string ShaderSourceCode = +@"shader ConstantCol : ComputeColor +{ + override float4 Compute() + { + return Value; + } +};"; + + public TestShaderLoadingString() + { + // Create and mount database file system + var objDatabase = ObjectDatabase.CreateDefaultDatabase(); + var databaseFileProvider = new DatabaseFileProvider(objDatabase); + + sourceManager = new ShaderSourceManager(databaseFileProvider); + sourceManager.LookupDirectoryList.Add(@"shaders"); + shaderLoader = new ShaderLoader(sourceManager); + } + + [Fact] + public void TestSimple() + { + var simple = sourceManager.LoadShaderSource(ShaderSourceName, ShaderSourceCode); + + // Make sure that SourceManager will fail if type is not found + Assert.Throws(() => sourceManager.LoadShaderSource("BiduleNotFound")); + + // Reload it and check that it is not loaded twice + var simple2 = sourceManager.LoadShaderSource(ShaderSourceName, ShaderSourceCode); + + //TODO: cannot compare structure references + //Assert.That(ReferenceEquals(simple, simple2), Is.True); + Assert.Equal(simple, simple2); + } + + [Fact] + public void TestLoadAst() + { + var log = new LoggerResult(); + + var shaderClassString = new ShaderClassString(ShaderSourceName, ShaderSourceCode, new Vector4(1, 1, 1, 1)); + + var simple = shaderLoader.LoadClassSource(shaderClassString, new Xenko.Core.Shaders.Parser.ShaderMacro[0], log, false)?.Type; + + Assert.Single(simple.Members); + + var shaderClassString2 = new ShaderClassString(ShaderSourceName, ShaderSourceCode, new Vector4(1, 1, 1, 1)); + + var simple2 = shaderLoader.LoadClassSource(shaderClassString2, new Xenko.Core.Shaders.Parser.ShaderMacro[0], log, false)?.Type; + + // Make sure that a class is not duplicated in memory + Assert.True(ReferenceEquals(simple, simple2)); + } + } +} diff --git a/sources/engine/Xenko.Shaders/Compiler/EffectCompilerBase.cs b/sources/engine/Xenko.Shaders/Compiler/EffectCompilerBase.cs index d2de78f0c5..d5abe84b72 100644 --- a/sources/engine/Xenko.Shaders/Compiler/EffectCompilerBase.cs +++ b/sources/engine/Xenko.Shaders/Compiler/EffectCompilerBase.cs @@ -47,7 +47,7 @@ public CompilerResults Compile(ShaderSource shaderSource, CompilerParameters com else { mixinToCompile = shaderSource as ShaderMixinSource; - var shaderClassSource = shaderSource as ShaderClassSource; + var shaderClassSource = shaderSource as ShaderClassCode; if (shaderClassSource != null) { diff --git a/sources/engine/Xenko.Shaders/ShaderClassCode.cs b/sources/engine/Xenko.Shaders/ShaderClassCode.cs new file mode 100644 index 0000000000..02c99528b4 --- /dev/null +++ b/sources/engine/Xenko.Shaders/ShaderClassCode.cs @@ -0,0 +1,66 @@ +// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Linq; +using System.Text; + +using Xenko.Core; +using Xenko.Core.Serialization; + +namespace Xenko.Shaders +{ + /// + /// A common base class for shader classes with source code. + /// + [DataContract("ShaderClassCode")] + public abstract class ShaderClassCode : ShaderSource + { + /// + /// Gets the name of the class. + /// + /// The name of the class. + [DataMember(10)] + public string ClassName { get; set; } + + /// + /// Gets the generic parameters. + /// + /// The generic parameters. + [DefaultValue(null), DataStyle(DataStyle.Compact)] + [DataMember(20)] + public string[] GenericArguments { get; set; } + + [DefaultValue(null)] + [DataMember(30)] + public Dictionary GenericParametersArguments { get; set; } + + /// + /// Returns a class name as a that represents this instance. + /// + /// A class name as a that represents this instance. + public string ToClassName() + { + if (GenericArguments == null) + return ClassName; + + var result = new StringBuilder(); + result.Append(ClassName); + if (GenericArguments != null && GenericArguments.Length > 0) + { + result.Append('<'); + result.Append(string.Join(",", GenericArguments)); + result.Append('>'); + } + + return result.ToString(); + } + + public override string ToString() + { + return ToClassName(); + } + } +} diff --git a/sources/engine/Xenko.Shaders/ShaderClassSource.cs b/sources/engine/Xenko.Shaders/ShaderClassSource.cs index 2a514b6861..a8ce1f5182 100644 --- a/sources/engine/Xenko.Shaders/ShaderClassSource.cs +++ b/sources/engine/Xenko.Shaders/ShaderClassSource.cs @@ -13,29 +13,11 @@ namespace Xenko.Shaders { /// - /// A shader class used for mixin. + /// A shader class based on .xksl file, used for mixin. /// [DataContract("ShaderClassSource")] - public sealed class ShaderClassSource : ShaderSource, IEquatable + public sealed class ShaderClassSource : ShaderClassCode, IEquatable { - /// - /// Gets the name of the class. - /// - /// The name of the class. - [DataMember(10)] - public string ClassName { get; set; } - - /// - /// Gets the generic parameters. - /// - /// The generic parameters. - [DefaultValue(null), DataStyle(DataStyle.Compact)] - [DataMember(20)] - public string[] GenericArguments { get; set; } - - [DefaultValue(null)] - [DataMember(30)] - public Dictionary GenericParametersArguments { get; set; } /// /// Initializes a new instance of the class. @@ -86,27 +68,6 @@ public ShaderClassSource(string className, params object[] genericArguments) } } - /// - /// Returns a class name as a that represents this instance. - /// - /// A class name as a that represents this instance. - public string ToClassName() - { - if (GenericArguments == null) - return ClassName; - - var result = new StringBuilder(); - result.Append(ClassName); - if (GenericArguments != null && GenericArguments.Length > 0) - { - result.Append('<'); - result.Append(string.Join(",", GenericArguments)); - result.Append('>'); - } - - return result.ToString(); - } - public bool Equals(ShaderClassSource shaderClassSource) { if (ReferenceEquals(null, shaderClassSource)) return false; diff --git a/sources/engine/Xenko.Shaders/ShaderClassString.cs b/sources/engine/Xenko.Shaders/ShaderClassString.cs new file mode 100644 index 0000000000..68c52dc341 --- /dev/null +++ b/sources/engine/Xenko.Shaders/ShaderClassString.cs @@ -0,0 +1,119 @@ +// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Linq; +using System.Text; + +using Xenko.Core; +using Xenko.Core.Serialization; + +namespace Xenko.Shaders +{ + /// + /// A shader class based on source code string, used for mixin. + /// + [DataContract("ShaderClassString")] + public sealed class ShaderClassString : ShaderClassCode, IEquatable + { + /// + /// Gets the source code of this shader class as string, XKSL syntax. + /// + /// The source code of the shader class. + public string ShaderSourceCode { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public ShaderClassString() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Name of the class. + public ShaderClassString(string className, string shaderSourceCode) + : this(className, shaderSourceCode, null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Name of the class. + /// The generic parameters. + public ShaderClassString(string className, string shaderSourceCode, params string[] genericArguments) + { + ClassName = className; + ShaderSourceCode = shaderSourceCode; + GenericArguments = genericArguments; + } + + /// + /// Initializes a new instance of the class. + /// + /// Name of the class. + /// The generic parameters. + public ShaderClassString(string className, string shaderSourceCode, params object[] genericArguments) + { + ClassName = className; + ShaderSourceCode = shaderSourceCode; + + if (genericArguments != null) + { + GenericArguments = new string[genericArguments.Length]; + for (int i = 0; i < genericArguments.Length; ++i) + { + var genArg = genericArguments[i]; + if (genArg is bool boolArg) + GenericArguments[i] = boolArg ? "true" : "false"; + else + GenericArguments[i] = genArg == null ? "null" : Convert.ToString(genArg, CultureInfo.InvariantCulture); + } + } + } + + public bool Equals(ShaderClassString shaderClassString) + { + if (ReferenceEquals(null, shaderClassString)) return false; + if (ReferenceEquals(this, shaderClassString)) return true; + return string.Equals(ClassName, shaderClassString.ClassName) && Utilities.Compare(GenericArguments, shaderClassString.GenericArguments); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((ShaderClassString)obj); + } + + public override int GetHashCode() + { + unchecked + { + int hashCode = ClassName?.GetHashCode() ?? 0; + if (GenericArguments != null) + { + foreach (var current in GenericArguments) + hashCode = (hashCode * 397) ^ (current?.GetHashCode() ?? 0); + } + + return hashCode; + } + } + + public override object Clone() + { + return new ShaderClassString(ClassName, ShaderSourceCode, GenericArguments = GenericArguments != null ? GenericArguments.ToArray() : null); + } + + public override string ToString() + { + return ToClassName(); + } + } +} diff --git a/sources/engine/Xenko.Shaders/ShaderMixinContext.cs b/sources/engine/Xenko.Shaders/ShaderMixinContext.cs index ab2ac8956a..5417e0d4e0 100644 --- a/sources/engine/Xenko.Shaders/ShaderMixinContext.cs +++ b/sources/engine/Xenko.Shaders/ShaderMixinContext.cs @@ -288,18 +288,17 @@ public void Mixin(ShaderMixinSource mixinTree, ShaderSource shaderSource) return; } - var shaderMixinSource = shaderSource as ShaderMixinSource; - if (shaderMixinSource != null) + if (shaderSource is ShaderMixinSource shaderMixinSource) { mixinTree.CloneFrom(shaderMixinSource); } - else if (shaderSource is ShaderClassSource) + else if (shaderSource is ShaderClassCode shaderClassCode) { - mixinTree.Mixins.Add((ShaderClassSource)shaderSource); + mixinTree.Mixins.Add(shaderClassCode); } - else if (shaderSource is ShaderMixinGeneratorSource) + else if (shaderSource is ShaderMixinGeneratorSource mixinGeneratorSource) { - Mixin(mixinTree, ((ShaderMixinGeneratorSource)shaderSource).Name); + Mixin(mixinTree, mixinGeneratorSource.Name); } else { diff --git a/sources/engine/Xenko.Shaders/ShaderMixinSource.cs b/sources/engine/Xenko.Shaders/ShaderMixinSource.cs index caa6da3470..312ac062ea 100644 --- a/sources/engine/Xenko.Shaders/ShaderMixinSource.cs +++ b/sources/engine/Xenko.Shaders/ShaderMixinSource.cs @@ -12,7 +12,7 @@ namespace Xenko.Shaders { /// - /// A mixin performing a combination of and other mixins. + /// A mixin performing a combination of and other mixins. /// [DataContract("ShaderMixinSource")] [NonIdentifiableCollectionItems] @@ -23,7 +23,7 @@ public sealed class ShaderMixinSource : ShaderSource, IEquatable public ShaderMixinSource() { - Mixins = new List(); + Mixins = new List(); Compositions = new Core.Collections.SortedList(); Macros = new List(); } @@ -51,7 +51,7 @@ public ShaderMixinSource() /// /// The mixins. [DataMember(10)] - public List Mixins { get; set; } + public List Mixins { get; set; } /// /// Gets or sets the compositions. @@ -133,7 +133,7 @@ public void DeepCloneFrom(ShaderMixinSource parent) throw new ArgumentNullException("parent", $"Cannot deep clone mixin [{Name}] from a null parent"); foreach (var mixin in parent.Mixins) - Mixins.Add((ShaderClassSource)mixin.Clone()); + Mixins.Add((ShaderClassCode)mixin.Clone()); Macros.AddRange(parent.Macros); foreach (var shaderBasic in parent.Compositions) { @@ -176,7 +176,7 @@ public override object Clone() { var newMixin = (ShaderMixinSource)MemberwiseClone(); newMixin.Compositions = Compositions == null ? null : ToSortedList(Compositions.Select(x => new KeyValuePair(x.Key, (ShaderSource)x.Value.Clone()))); - newMixin.Mixins = Mixins == null ? null : Mixins.Select(x => (ShaderClassSource)x.Clone()).ToList(); + newMixin.Mixins = Mixins == null ? null : Mixins.Select(x => (ShaderClassCode)x.Clone()).ToList(); newMixin.Macros = Macros == null ? null : new List(Macros.ToArray()); return newMixin; } diff --git a/sources/shared/SharedAssemblyInfo.cs b/sources/shared/SharedAssemblyInfo.cs index b2a7851c8e..ea3a4d0158 100644 --- a/sources/shared/SharedAssemblyInfo.cs +++ b/sources/shared/SharedAssemblyInfo.cs @@ -49,7 +49,7 @@ internal class XenkoVersion /// - -betaXX: development version (XX should corespond to development asset versioning) /// - -betaXX-YYYY: beta release (YYYY is the git height since current version has been bumped) /// - public const string NuGetVersionSuffix = "-beta02"; + public const string NuGetVersionSuffix = "-sfx"; /// /// The build metadata, usually +g[git_hash] during package. Automatically set by Xenko.GitVersioning.GenerateVersionFile.