Beispiel #1
0
        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);
        }