Example #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AssetCloner" /> struct.
        /// </summary>
        /// <param name="value">The value to clone.</param>
        /// <param name="flags">Cloning flags</param>
        private AssetCloner(object value, AssetClonerFlags flags)
        {
            this.flags = flags;
            invariantObjects = null;

            // Clone only if value is not a value type
            if (value != null && !value.GetType().IsValueType)
            {
                invariantObjects = new List<object>();
                // TODO: keepOnlySealedOverride is currently ignored
                // TODO Clone is not supporting SourceCodeAsset (The SourceCodeAsset.Text won't be cloned)
                var stream = new MemoryStream();
                var writer = new BinarySerializationWriter(stream);
                writer.Context.SerializerSelector = ClonerSelector;
                var refFlag = (flags & AssetClonerFlags.ReferenceAsNull) != 0
                    ? ContentSerializerContext.AttachedReferenceSerialization.AsNull
                    : ContentSerializerContext.AttachedReferenceSerialization.AsSerializableVersion;
                writer.Context.Set(InvariantObjectListProperty, invariantObjects);
                writer.Context.Set(ContentSerializerContext.SerializeAttachedReferenceProperty, refFlag);
                writer.SerializeExtended(value, ArchiveMode.Serialize);
                writer.Flush();

                // Retrieve back object references
                objectReferences = writer.Context.Get(MemberSerializer.ObjectSerializeReferences);

                streamOrValueType = stream;
            }
            else
            {
                streamOrValueType = value;
                objectReferences = null;
            }
        }
Example #2
0
        protected override void ComputeParameterHash(Stream stream)
        {
            base.ComputeParameterHash(stream);

            var writer = new BinarySerializationWriter(stream);
            writer.Write(commandId);
        }
        protected override void ComputeParameterHash(BinarySerializationWriter writer)
        {
            base.ComputeParameterHash(writer);

            writer.Write(SourcePath);
            writer.Write(Location);
        }
        protected override void ComputeParameterHash(BinarySerializationWriter writer)
        {
            base.ComputeParameterHash(writer);

            // Regenerate new shaders if magic header changed
            uint effectbyteCodeMagicNumber = EffectBytecode.MagicHeader;
            writer.Serialize(ref effectbyteCodeMagicNumber, ArchiveMode.Serialize);
        }
 protected override void ComputeParameterHash(BinarySerializationWriter writer)
 {
     base.ComputeParameterHash(writer);
     uint effectbyteCodeMagicNumber = EffectBytecode.MagicHeader;
     writer.Serialize(ref effectbyteCodeMagicNumber, ArchiveMode.Serialize);
     writer.Serialize(ref effectName, ArchiveMode.Serialize);
     writer.Serialize(ref compilerParameters, ArchiveMode.Serialize);
 }
        protected override void ComputeParameterHash(Stream stream)
        {
            base.ComputeParameterHash(stream);

            var writer = new BinarySerializationWriter(stream);
            writer.Write(SourcePath);
            writer.Write(Location);
        }
Example #7
0
        private static byte[] EncodeObject(object obj)
        {
            var memoryStream = new MemoryStream();
            var writer = new BinarySerializationWriter(memoryStream);
            writer.Context.SerializerSelector = SerializerSelector.AssetWithReuse;
            writer.Context.Set(ContentSerializerContext.SerializeAttachedReferenceProperty, ContentSerializerContext.AttachedReferenceSerialization.AsSerializableVersion);
            writer.SerializeExtended(ref obj, ArchiveMode.Serialize);

            return memoryStream.ToArray();
        }
Example #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AssetCloner" /> struct.
        /// </summary>
        /// <param name="value">The value to clone.</param>
        /// <param name="flags">Cloning flags</param>
        private AssetCloner(object value, AssetClonerFlags flags)
        {
            this.flags = flags;
            invariantObjects = null;
            objectReferences = null;

            // Clone only if value is not a value type
            if (value != null && !value.GetType().IsValueType)
            {
                invariantObjects = new List<object>();

                // TODO: keepOnlySealedOverride is currently ignored
                // TODO Clone is not supporting SourceCodeAsset (The SourceCodeAsset.Text won't be cloned)

                var stream = new MemoryStream();
                var writer = new BinarySerializationWriter(stream);
                writer.Context.SerializerSelector = ClonerSelector;
                var refFlag = (flags & AssetClonerFlags.ReferenceAsNull) != 0
                    ? ContentSerializerContext.AttachedReferenceSerialization.AsNull
                    : ContentSerializerContext.AttachedReferenceSerialization.AsSerializableVersion;
                writer.Context.Set(InvariantObjectListProperty, invariantObjects);
                writer.Context.Set(ContentSerializerContext.SerializeAttachedReferenceProperty, refFlag);
                writer.SerializeExtended(value, ArchiveMode.Serialize);
                writer.Flush();

                // Retrieve back all object references that were discovered while serializing
                // They will be used layer by OnObjectDeserialized when cloning ShadowObject datas
                var objectRefs = writer.Context.Get(MemberSerializer.ObjectSerializeReferences);
                if (objectRefs != null)
                {
                    // Remap object references to a simple array
                    objectReferences = new object[objectRefs.Count];
                    foreach (var objRef in objectRefs)
                    {
                        objectReferences[objRef.Value] = objRef.Key;
                    }
                }

                streamOrValueType = stream;
            }
            else
            {
                streamOrValueType = value;
            }
        }
        public void NotifyEffectUsed(EffectCompileRequest effectCompileRequest)
        {
            Task.Run(async () =>
            {
                // Silently fails if connection already failed previously
                var socketMessageLayerTask = GetOrCreateConnection();
                if (socketMessageLayerTask.IsFaulted)
                    return;

                // Send any effect request remotely (should fail if not connected)
                var socketMessageLayer = await socketMessageLayerTask;

                var memoryStream = new MemoryStream();
                var binaryWriter = new BinarySerializationWriter(memoryStream);
                binaryWriter.Context.SerializerSelector = SerializerSelector.AssetWithReuse;
                binaryWriter.SerializeExtended(effectCompileRequest, ArchiveMode.Serialize, null);

                await socketMessageLayer.Send(new RemoteEffectCompilerEffectRequested { Request = memoryStream.ToArray() });
            });
        }
Example #10
0
        public static async Task UnpackAPK()
        {
            // get the apk last update time
            var packageManager = PlatformAndroid.Context.PackageManager;
            var packageInfo = packageManager.GetPackageInfo(PlatformAndroid.Context.PackageName, PackageInfoFlags.Activities);
            var lastUpdateTime = packageInfo.LastUpdateTime;
            var sourceDir = PlatformAndroid.Context.ApplicationInfo.SourceDir;

            // evaluate if asset data should be extracted from apk file
            var shouldExtractAssets = true;
            if (ApplicationTemporary.FileExists(LastExtractedApkFileName))
            {
                Int64 extractedLastUpdateTime = 0;
                using (var file = ApplicationTemporary.OpenStream(LastExtractedApkFileName, VirtualFileMode.Open, VirtualFileAccess.Read))
                {
                    var binaryReader = new BinarySerializationReader(file);
                    binaryReader.Serialize(ref extractedLastUpdateTime, ArchiveMode.Deserialize);
                }

                shouldExtractAssets = extractedLastUpdateTime != lastUpdateTime;
            }

            // Copy assets
            if (shouldExtractAssets)
            {
                var assets = PlatformAndroid.Context.Assets;

                // Make sure assets exists
                var logger = GlobalLogger.GetLogger("VFS");
                CopyFileOrDirectory(logger, sourceDir, "assets/data/", string.Empty);

                // update value of extracted last update time
                using (var stream = ApplicationTemporary.OpenStream(LastExtractedApkFileName, VirtualFileMode.Create, VirtualFileAccess.Write, VirtualFileShare.None))
                {
                    var binaryWriter = new BinarySerializationWriter(stream);
                    binaryWriter.Write(lastUpdateTime);
                }
            }
        }
Example #11
0
        public static void SaveFromMemory(PixelBuffer[] pixelBuffers, int count, ImageDescription description, System.IO.Stream imageStream)
        {
            var stream = new BinarySerializationWriter(imageStream);

            // Write magic code
            stream.Write(MagicCode);

            // Write image header
            imageDescriptionSerializer.Serialize(ref description, ArchiveMode.Serialize, stream);

            // Write total size
            int totalSize = 0;
            foreach (var pixelBuffer in pixelBuffers)
                totalSize += pixelBuffer.BufferStride;

            stream.Write(totalSize);

            // Write buffers contiguously
            foreach (var pixelBuffer in pixelBuffers)
            {
                stream.Serialize(pixelBuffer.DataPointer, pixelBuffer.BufferStride);
            }
        }
Example #12
0
        protected override void ComputeParameterHash(Stream stream)
        {
            base.ComputeParameterHash(stream);

            // Really necesary? (need system for identical blob reuse)
            var writer = new BinarySerializationWriter(stream);
            writer.Write(InputUrl);
            writer.Write(OutputUrl);
            writer.Write(Width);
            writer.Write(Height);
            writer.Write(IsAbsolute);
            writer.Write(Format);
            writer.Write(GenerateMipmaps);
        }
Example #13
0
        protected override void ComputeParameterHash(BinarySerializationWriter writer)
        {
            base.ComputeParameterHash(writer);

            writer.Write(commandId);
        }
Example #14
0
 protected override void ComputeParameterHash(BinarySerializationWriter writer)
 {
     writer.Write(Source);
     writer.Write(OutputUrl);
 }
        private EffectBytecodeCompilerResult CompileBytecode(ShaderMixinSource mixinTree, EffectCompilerParameters effectParameters, CompilerParameters compilerParameters, ObjectId mixinObjectId, DatabaseFileProvider database, string compiledUrl)
        {
            // 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, effectParameters, 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);
                
                // Write current cache at the end (not part of the pure bytecode, but we use this as meta info)
                var writer = new BinarySerializationWriter(memoryStream);
                writer.Write(CurrentCache);

                memoryStream.Position = 0;
                database.ObjectDatabase.Write(memoryStream, newBytecodeId, true);
                database.ContentIndexMap[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.Verbose("New effect compiled #{0} [{1}] (db: {2})\r\n{3}", effectCompileCount, mixinObjectId, newBytecodeId, compilerParameters?.ToStringPermutationsDetailed());
                    Interlocked.Increment(ref effectCompileCount);

                    // Replace or add new bytecode
                    bytecodes[newBytecodeId] = new KeyValuePair<EffectBytecode, EffectBytecodeCacheLoadSource>(compiledShader.Bytecode, EffectBytecodeCacheLoadSource.JustCompiled);
                }
            }

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

            return compiledShader;
        }
Example #16
0
        protected override void ComputeParameterHash(BinarySerializationWriter writer)
        {
            base.ComputeParameterHash(writer);

            writer.SerializeExtended(this, ArchiveMode.Serialize);
        }
Example #17
0
        /// <inheritdoc/>
        public CompilationResult Compile(string shaderSource, string entryPoint, string profile, string sourceFileName = "unknown")
        {
            string realShaderSource;

            if (profile == "glsl")
            {
                // Compile directly as GLSL
                realShaderSource = shaderSource;
            }
            else
            {
                // Convert HLSL to GLSL
                PipelineStage stage;
                var profileParts = profile.Split('_');
                switch (profileParts[0])
                {
                    case "vs":
                        stage = PipelineStage.Vertex;
                        break;
                    case "ps":
                        stage = PipelineStage.Pixel;
                        break;
                    case "gs":
                    case "hs":
                    case "ds":
                    case "cs":
                        throw new NotImplementedException("This shader stage can't be converted to OpenGL.");
                    default:
                        throw new NotSupportedException("Unknown shader profile.");
                }

                // 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, stage);

                // 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(
                                stage == 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 (stage == PipelineStage.Pixel)
                        glslShaderCode
                            .AppendLine("out vec4 gl_FragData[1];")
                            .AppendLine();
                }

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

                glslShaderCode.Append(glslShaderWriter.Text);

                realShaderSource = glslShaderCode.ToString();
            }

            var shaderBytecodeData = new OpenGLShaderBytecodeData
                {
                    IsBinary = false,
                    EntryPoint = entryPoint,
                    Profile = profile,
                    Source = realShaderSource,
                };

            // Encode shader source to a byte array (no universal StageBytecode format for OpenGL)
            var memoryStream = new MemoryStream();
            var binarySerializationWriter = new BinarySerializationWriter(memoryStream);
            shaderBytecodeData.Serialize(binarySerializationWriter, ArchiveMode.Serialize);

            return new CompilationResult(new ShaderBytecode(memoryStream.ToArray()), false, null);
        }
        /// <summary>
        /// Writes an object instance to the specified stream.
        /// </summary>
        /// <typeparam name="T">Type of the object to write</typeparam>
        /// <param name="stream">The stream to write the object instance to.</param>
        /// <param name="value">The value to write.</param>
        public static void Write <T>([NotNull] Stream stream, T value)
        {
            var writer = new BinarySerializationWriter(stream);

            writer.Write(value);
        }
 protected override void ComputeAssemblyHash(BinarySerializationWriter writer)
 {
     writer.Write(DataSerializer.BinaryFormatVersion);
     writer.Write(EffectBytecode.MagicHeader);
 }
Example #20
0
        public void Test()
        {
            var prefab = new PrefabAsset();

            var modelComponent = new ModelComponent();
            var entity = new Entity()
            {
                modelComponent
            };
            prefab.Hierarchy.Entities.Add(entity);
            prefab.Hierarchy.RootEntities.Add(entity.Id);

            var material1 = new MaterialNull();
            IdentifiableHelper.SetId(material1, new Guid("39E2B226-8752-4678-8E93-76FFBFBA337B"));
            var material2 = new MaterialNull();
            IdentifiableHelper.SetId(material2, new Guid("CC4F1B31-FBB7-4360-A3E7-060BDFDA0695"));
            modelComponent.Materials.Add(material1);
            modelComponent.Materials.Add(material2);

            Action<PrefabAsset> checkPrefab = (newPrefab) =>
            {
                var previousEntityDesign = newPrefab.Hierarchy.Entities.FirstOrDefault();

                Assert.NotNull(previousEntityDesign);

                var previousEntity = previousEntityDesign.Entity;


                var component = previousEntity.Get<ModelComponent>();
                Assert.NotNull(component);

                Assert.AreEqual(2, component.Materials.Count);

                var newMaterial1 = component.Materials[0];
                Assert.AreEqual(IdentifiableHelper.GetId(material1), IdentifiableHelper.GetId(newMaterial1));
                var newMaterial2 = component.Materials[1];
                Assert.AreEqual(IdentifiableHelper.GetId(material2), IdentifiableHelper.GetId(newMaterial2));
            };

            // Test yaml serialization
            {
                using (var stream = new MemoryStream())
                {
                    AssetSerializer.Save(stream, prefab);

                    stream.Position = 0;
                    var serializedVersion = Encoding.UTF8.GetString(stream.ToArray());
                    Console.WriteLine(serializedVersion);

                    stream.Position = 0;
                    var newPrefab = (PrefabAsset)AssetSerializer.Load(stream, "myentity");
                    checkPrefab(newPrefab);
                }
            }

            // Test cloning
            var newPrefabClone = (PrefabAsset)AssetCloner.Clone(prefab);
            checkPrefab(newPrefabClone);

            // Test runtime serialization (runtime serialization is removing MaterialNull and replacing it by a null)
            {
                var stream = new MemoryStream();
                var writer = new BinarySerializationWriter(stream) { Context = { SerializerSelector = SerializerSelector.AssetWithReuse } };
                writer.SerializeExtended(entity, ArchiveMode.Serialize);
                writer.Flush();
                stream.Position = 0;

                var reader = new BinarySerializationReader(stream) { Context = { SerializerSelector = SerializerSelector.AssetWithReuse } };

                Entity newEntity = null;
                reader.SerializeExtended(ref newEntity, ArchiveMode.Deserialize);

                Assert.NotNull(newEntity);

                var component = newEntity.Get<ModelComponent>();
                Assert.NotNull(component);

                Assert.AreEqual(2, component.Materials.Count);

                Assert.Null(component.Materials[0]);
                Assert.Null(component.Materials[1]);
            }
        }
Example #21
0
 protected override void ComputeParameterHash(BinarySerializationWriter writer)
 {
     // force execution of the command with a new GUID
     var newGuid = Guid.NewGuid();
     writer.Serialize(ref newGuid, ArchiveMode.Serialize);
 }
Example #22
0
        public void ComputeCommandHash(Stream stream, IPrepareContext prepareContext)
        {
            var writer = new BinarySerializationWriter(stream);
            writer.Context.SerializerSelector = SerializerSelector.AssetWithReuse;

            writer.Write(CommandCacheVersion);

            // Compute assembly hash
            ComputeAssemblyHash(writer);

            // Compute parameters hash
            ComputeParameterHash(writer);

            // Compute static input files hash (parameter dependent)
            ComputeInputFilesHash(writer, prepareContext);
        }
Example #23
0
 protected virtual void ComputeParameterHash(BinarySerializationWriter writer)
 {
     // Do nothing by default
 }
Example #24
0
 /// <summary>
 /// Writes this <see cref="EffectBytecode" /> to a stream with its magic number.
 /// </summary>
 /// <param name="stream">The stream.</param>
 /// <exception cref="System.ArgumentNullException">stream</exception>
 public void WriteTo(Stream stream)
 {
     if (stream == null) throw new ArgumentNullException("stream");
     var writer = new BinarySerializationWriter(stream);
     writer.Write(MagicHeader);
     writer.Write(this);
 }
Example #25
0
        protected void ComputeInputFilesHash(BinarySerializationWriter writer, IPrepareContext prepareContext)
        {
            var inputFiles = GetInputFiles();
            if (inputFiles == null)
                return;

            foreach (var inputFile in inputFiles)
            {
                var hash = prepareContext.ComputeInputHash(inputFile.Type, inputFile.Path);
                if (hash == ObjectId.Empty)
                {
                    writer.NativeStream.WriteByte(0);
                }
                else
                {
                    writer.NativeStream.Write((byte[])hash, 0, ObjectId.HashSize);
                }
            }
        }
Example #26
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);
        }
Example #27
0
        protected virtual void ComputeAssemblyHash(BinarySerializationWriter writer)
        {
            // Use binary format version (bumping it forces everything to be reevaluated)
            writer.Write(DataSerializer.BinaryFormatVersion);

            // Gets the hash of the assembly of the command
            writer.Write(AssemblyHash.ComputeAssemblyHash(GetType().Assembly));
        }
Example #28
0
        private ObjectId GetHashId()
        {
            // This methods use the stream that is already filled-up by the standard binary serialization of the object
            // Here we add ids and overrides metadata informations to the stream in order to calculate an accurate id
            var stream = streamOrValueType as MemoryStream;
            if (stream != null)
            {
                // ------------------------------------------------------
                // Un-comment the following code to debug the ObjectId of the serialized version without taking into account overrides
                // ------------------------------------------------------
                //var savedPosition = stream.Position;
                //stream.Position = 0;
                //var intermediateHashId = ObjectId.FromBytes(stream.ToArray());
                //stream.Position = savedPosition;

                var writer = new BinarySerializationWriter(stream);
                Dictionary<string, OverrideType> overrides = null;
                List<string> orderedNames = null;
                foreach (var objectRef in objectReferences)
                {
                    //// If the object is actually a reference to another asset, we can skip it as their won't be any overrides
                    //if (AttachedReferenceManager.GetAttachedReference(objectRef) != null)
                    //{
                    //    continue;
                    //}

                    // Else gets the id if there are any (including shadows that are not part of the standard serialization)
                    var shadowObject = ShadowObject.GetOrCreate(objectRef);
                    if (shadowObject.IsIdentifiable)
                    {
                        // Get the shadow id (may be a non-shadow, so we may duplicate it in the stream (e.g Entity)
                        // but it should not be a big deal
                        var id = shadowObject.GetId(objectRef);
                        writer.Write(id);
                    }

                    // Dump all members with overrides informations
                    foreach (var item in shadowObject)
                    {
                        if (item.Key.Item2 == Override.OverrideKey)
                        {
                            // Use the member name to ensure a stable id
                            var memberName = ((IMemberDescriptor)item.Key.Item1).Name;
                            // Only creates the overrides dictionary if needed
                            if (overrides == null)
                            {
                                overrides = new Dictionary<string, OverrideType>();
                            }
                            overrides.Add(memberName, (OverrideType)item.Value);
                        }
                    }

                    // Write any overrides information to the stream
                    if (overrides != null)
                    {
                        // Collect names and order them by alphabetical order in order to make sure that we will get a stable id 
                        // (Dictionary doesn't ensure order)
                        if (orderedNames == null)
                        {
                            orderedNames = new List<string>();
                        }
                        orderedNames.Clear();
                        foreach (var entry in overrides)
                        {
                            orderedNames.Add(entry.Key);
                        }
                        orderedNames.Sort();

                        // Write all overrides for the current object reference
                        foreach (var name in orderedNames)
                        {
                            writer.Write(name);
                            // Write the override as an int
                            writer.Write((int)overrides[name]);
                        }

                        // Clear overrides for next entry
                        overrides.Clear();
                    }
                }

                writer.Flush();
                stream.Position = 0;

                return ObjectId.FromBytes(stream.ToArray());
            }

            return ObjectId.Empty;
        }