public void Prepare(bool parallel) { if (Interlocked.Exchange(ref State, State_Preparing) != State_Initialized) { throw new InvalidOperationException("Frame was not in initialized state when prepare operation began "); } if (false) { var totalBatches = Batch.LifetimeCount - InitialBatchCount; Console.WriteLine("Frame contains {0} batches", totalBatches); } BatchCombiner.CombineBatches(Batches); #if PSM Batches.Timsort(BatchComparer); #else Batches.Sort(BatchComparer); #endif if (!Monitor.TryEnter(PrepareLock, 5000)) { throw new InvalidOperationException("Spent more than five seconds waiting for a previous prepare operation."); } try { if (parallel) { RenderManager.ParallelPrepare(this); } else { PrepareSubset(0, Batches.Count); } } finally { Monitor.Exit(PrepareLock); } if (Interlocked.Exchange(ref State, State_Prepared) != State_Preparing) { throw new InvalidOperationException("Frame was not in preparing state when prepare operation completed"); } }
/// <summary> /// Scans over a list of batches and applies batch combiners to reduce the total number of batches sent to the GPU and /// improve batch preparation efficiency. Batches eliminated by combination are replaced with null. /// </summary> /// <param name="batches">The list of batches to perform a combination pass over.</param> /// <returns>The number of batches eliminated.</returns> public static int CombineBatches(UnorderedList <Batch> batches) { #if PSM batches.Timsort(BatchTypeSorter); #else batches.Sort(BatchTypeSorter); #endif int i = 0, j = i + 1, l = batches.Count, eliminatedCount = 0; Batch a, b; Type aType, bType; var _batches = batches.GetBuffer(); while ((i < l) && (j < l)) { a = _batches[i]; if (a == null) { i += 1; j = i + 1; continue; } aType = a.GetType(); b = _batches[j]; if (b == null) { j += 1; continue; } bType = b.GetType(); if ((aType != bType) || (a.Layer != b.Layer)) { i = j; j = i + 1; } else { bool combined = false; foreach (var combiner in Combiners) { if (combined = combiner.CanCombine(a, b)) { _batches[i] = _batches[j] = null; _batches[i] = combiner.Combine(a, b); _batches[i].Container = a.Container; if ((a != _batches[i]) && (a.ReleaseAfterDraw)) { a.ReleaseResources(); } if (b.ReleaseAfterDraw) { b.ReleaseResources(); } eliminatedCount += 1; break; } } j += 1; } } if (false && eliminatedCount > 0) { Console.WriteLine("Eliminated {0:0000} of {1:0000} batch(es)", eliminatedCount, batches.Count); } return(eliminatedCount); }