/// <summary> /// Merges all the <see cref="ModelRoot.LogicalBuffers"/> instances into a single, big one. /// </summary> /// <remarks> /// When merging the buffers, it also adjusts the BufferView offsets so the data they point to remains the same. /// /// If images are required to be included in the binary, call <see cref="ModelRoot.MergeImages"/> before calling <see cref="MergeBuffers"/> /// /// This action cannot be reversed. /// </remarks> public void MergeBuffers() { // retrieve all buffers and merge them into a single, big buffer var views = _bufferViews .OrderByDescending(item => item.Content.Count) .ToArray(); if (views.Length <= 1) { return; // nothing to do. } var sbbuilder = new _StaticBufferBuilder(0); foreach (var bv in views) { bv._IsolateBufferMemory(sbbuilder); } this._buffers.Clear(); var b = new Buffer(sbbuilder.ToArray()); this._buffers.Add(b); }
internal void _IsolateBufferMemory(_StaticBufferBuilder targetBuffer) { // retrieve old buffer var srcBuf = this.LogicalParent.LogicalBuffers[this._buffer].Content; var data = new Byte[this._byteLength]; Array.Copy(srcBuf, this._byteOffset ?? 0, data, 0, this._byteLength); // append data to new buffer this._buffer = targetBuffer.BufferIndex; this._byteLength = data.Length; this._byteOffset = targetBuffer.Append(data); }
/// <summary> /// Merges all the <see cref="LogicalBuffers"/> instances into buffers of <paramref name="maxSize"/> size. /// </summary> /// <param name="maxSize"> /// The maximum size of each buffer. /// Notice that if a single BufferView is larger than <paramref name="maxSize"/>, that buffer will be also larger. /// </param> public void MergeBuffers(int maxSize) { // retrieve all buffers and merge them into a single, big buffer var views = _bufferViews .OrderByDescending(item => item.Content.Count) .ToList(); if (views.Count <= 1) { return; // nothing to do. } // begin merge var buffers = new List <_StaticBufferBuilder>(); buffers.Add(new _StaticBufferBuilder(0)); foreach (var bv in views) { var last = buffers.Last(); var alreadyFull = last.BufferSize >= maxSize; var notEmpty = last.BufferSize > 0; var bvTooBig = (long)bv.Content.Count + last.BufferSize >= maxSize; if (alreadyFull || (notEmpty && bvTooBig)) { last = new _StaticBufferBuilder(buffers.Count); buffers.Add(last); } bv._IsolateBufferMemory(last); } // build final buffers this._buffers.Clear(); foreach (var buffer in buffers) { var b = new Buffer(buffer.ToArray()); this._buffers.Add(b); } }
/// <summary> /// Merges all the <see cref="LogicalBuffers"/> instances into a single big one. /// </summary> /// <remarks> /// <para> /// When merging the buffers, it also adjusts the BufferView offsets so the data they point to remains the same. /// </para> /// <para> /// If images are required to be included in the binary, call <see cref="MergeImages"/> /// before calling <see cref="MergeBuffers()"/>. /// </para> /// </remarks> /// <exception cref="InvalidOperationException"> /// .Net arrays have an upper limit of 2Gb, so this is the biggest a buffer can normally grow, /// so attempting to merge buffers that sum more than 2Gb will throw this exception. /// </exception> public void MergeBuffers() { // retrieve all buffers and merge them into a single, big buffer var views = _bufferViews .OrderByDescending(item => item.Content.Count) .ToList(); if (views.Count <= 1) { return; // nothing to do. } // check final size long totalLen = views.Sum(item => (long)item.Content.Count.WordPadded()); if (totalLen >= (long)int.MaxValue) { throw new InvalidOperationException("Can't merge a buffer larger than 2Gb"); } // begin merge var sbbuilder = new _StaticBufferBuilder(0); foreach (var bv in views) { bv._IsolateBufferMemory(sbbuilder); } // build final buffer this._buffers.Clear(); var b = new Buffer(sbbuilder.ToArray()); this._buffers.Add(b); }