Ejemplo n.º 1
0
        internal void RecordCommandLists(MyCullQuery processedCullQuery, Queue <CommandList> outCommandLists)
        {
            ProfilerShort.Begin("PrepareWork");

            ProfilerShort.Begin("Init");
            Debug.Assert(m_workList.Count == 0, "Work list not cleared after use!");

            foreach (List <MyRenderCullResultFlat> cullResults in m_passElements)
            {
                cullResults.Clear();
                m_resultListPool.Deallocate(cullResults);
            }
            m_passElements.Clear();
            m_passElements2.Clear();

            for (int renderPassIndex = 0; renderPassIndex < processedCullQuery.Size; ++renderPassIndex)
            {
                if (!MyRender11.DeferredContextsEnabled)
                {
                    processedCullQuery.RenderingPasses[renderPassIndex].SetImmediate(true);
                }

                m_passElements.Add(m_resultListPool.Allocate());
                m_passElements2.Add(null);
            }

            ProfilerShort.BeginNextBlock("Flatten");
            for (int i = 0; i < processedCullQuery.Size; ++i)
            {
                m_affectedQueueIds.SetSize(0);
                var frustumQuery = processedCullQuery.FrustumCullQueries[i];

                for (int renderPassIndex = 0; renderPassIndex < processedCullQuery.Size; renderPassIndex++)
                {
                    if ((processedCullQuery.RenderingPasses[renderPassIndex].ProcessingMask & frustumQuery.Bitmask) > 0)
                    {
                        m_affectedQueueIds.Add(renderPassIndex);
                    }
                }

                var cullProxies = frustumQuery.List;
                var queryType   = frustumQuery.Type;

                foreach (MyCullProxy cullProxy in cullProxies)
                {
                    var renderableProxies = cullProxy.RenderableProxies;
                    if (renderableProxies == null)
                    {
                        continue;
                    }

                    for (int proxyIndex = 0; proxyIndex < renderableProxies.Length; ++proxyIndex)
                    {
                        var flag = renderableProxies[proxyIndex].DrawSubmesh.Flags;
                        if (queryType == MyFrustumEnum.MainFrustum)
                        {
                            if ((flag & MyDrawSubmesh.MySubmeshFlags.Gbuffer) != MyDrawSubmesh.MySubmeshFlags.Gbuffer)
                            {
                                continue;
                            }
                        }
                        else if (queryType == MyFrustumEnum.ShadowCascade || queryType == MyFrustumEnum.ShadowProjection)
                        {
                            if ((flag & MyDrawSubmesh.MySubmeshFlags.Depth) != MyDrawSubmesh.MySubmeshFlags.Depth)
                            {
                                continue;
                            }
                        }

                        MyRenderableProxy renderableProxy = renderableProxies[proxyIndex];
                        ulong             sortKey         = cullProxy.SortingKeys[proxyIndex];

                        var item = new MyRenderCullResultFlat
                        {
                            SortKey     = sortKey,
                            RenderProxy = renderableProxy,
                        };

                        if (renderableProxy.Material != MyMeshMaterialId.NULL && renderableProxy.Material.Info.Technique == MyMeshDrawTechnique.GLASS)
                        {
                            if (queryType == MyFrustumEnum.MainFrustum)
                            {
                                MyStaticGlassRenderer.Renderables.Add(item);
                            }

                            continue;
                        }

                        for (int queueIndex = 0; queueIndex < m_affectedQueueIds.Count; ++queueIndex)
                        {
                            var queueId = m_affectedQueueIds[queueIndex];
                            m_passElements[queueId].Add(item);
                        }
                    }
                }

                // proxy 2
                var list2 = frustumQuery.List2;

                // flatten and sort
                m_flattenedKeys.SetSize(0);
                m_indirectionList.SetSize(0);
                m_location.SetSize(0);

                int indirectionCounter = 0;
                for (int list2Index = 0; list2Index < list2.Count; ++list2Index)
                {
                    for (int sortKeyIndex = 0; sortKeyIndex < list2[list2Index].SortingKeys.Length; sortKeyIndex++)
                    {
                        m_flattenedKeys.Add(list2[list2Index].SortingKeys[sortKeyIndex]);
                        m_indirectionList.Add(indirectionCounter++);
                        m_location.Add(MyTuple.Create(list2Index, sortKeyIndex));
                    }
                }

                MyRenderableProxy_2[] flattenedProxies = null;

                if (indirectionCounter > 0)
                {
                    flattenedProxies = new MyRenderableProxy_2[indirectionCounter];
                }

                m_sortingKeysComparer.Values = m_flattenedKeys;
                m_indirectionList.Sort(0, m_indirectionList.Count, m_sortingKeysComparer);

                if (flattenedProxies != null)
                {
                    for (int e = 0; e < indirectionCounter; e++)
                    {
                        var l = m_location[m_indirectionList[e]];
                        flattenedProxies[e] = list2[l.Item1].Proxies[l.Item2];
                    }
                }

                for (int l = 0; l < m_affectedQueueIds.Count; l++)
                {
                    m_passElements2[m_affectedQueueIds[l]] = flattenedProxies;
                }
            }

            ProfilerShort.BeginNextBlock("Sort");

            m_tmpSortListDictionary.Clear();
            m_resultSortedKeys.Clear();
            for (int i = 0; i < m_passElements.Count; i++)
            {
                var flatCullResults = m_passElements[i];

                foreach (MyRenderCullResultFlat element in flatCullResults)
                {
                    List <MyPassCullResult> sortList;
                    if (!m_tmpSortListDictionary.TryGetValue(element.SortKey, out sortList))
                    {
                        sortList = m_sortListPool.Allocate();
                        m_tmpSortListDictionary.Add(element.SortKey, sortList);
                        m_resultSortedKeys.Add(element.SortKey);
                    }

                    sortList.Add(new MyPassCullResult()
                    {
                        PassIndex = i, CullResult = element
                    });
                }

                flatCullResults.Clear();
            }

            m_resultSortedKeys.Sort();
            foreach (ulong sortKey in m_resultSortedKeys)
            {
                List <MyPassCullResult> sortList = m_tmpSortListDictionary[sortKey];
                foreach (var result in sortList)
                {
                    m_passElements[result.PassIndex].Add(result.CullResult);
                }

                sortList.SetSize(0);
                m_sortListPool.Deallocate(sortList);
            }

            int jobsNum = GetRenderingThreadsNum();

            // always amortize this path
            ProfilerShort.BeginNextBlock("WorkAmortization");

            //passElements.RemoveAll(x => x.Count == 0);

            int workSum = 0;

            foreach (var list in m_passElements)
            {
                workSum += list.Count;
            }

            int batchWork = (workSum + jobsNum - 1) / jobsNum;

            Debug.Assert(m_subworks.Count == 0);

            int work = 0;

            for (int passElementIndex = 0; passElementIndex < m_passElements.Count; ++passElementIndex)
            {
                var flatCullResults = m_passElements[passElementIndex];
                if (flatCullResults.Count == 0)
                {
                    MyObjectPoolManager.Deallocate(processedCullQuery.RenderingPasses[passElementIndex]);
                    processedCullQuery.RenderingPasses[passElementIndex] = null;
                    if (m_passElements2[passElementIndex] == null || m_passElements2[passElementIndex].Length == 0)
                    {
                        continue;
                    }
                }

                if (processedCullQuery.RenderingPasses[passElementIndex] == null)
                {
                    continue;
                }

                int passBegin = 0;

                if (m_passElements2[passElementIndex] != null && m_passElements2[passElementIndex].Length > 0)
                {
                    m_subworks.Add(new MyRenderingWorkItem
                    {
                        Pass  = processedCullQuery.RenderingPasses[passElementIndex].Fork(),
                        List2 = m_passElements2[passElementIndex]
                    });
                }

                while (passBegin < flatCullResults.Count)
                {
                    int toTake = Math.Min(flatCullResults.Count - passBegin, batchWork - work);

                    var workItem = new MyRenderingWorkItem
                    {
                        Renderables = flatCullResults,
                        Begin       = passBegin,
                        End         = passBegin + toTake
                    };

                    if (toTake < flatCullResults.Count && workItem.End != workItem.Renderables.Count)
                    {
                        workItem.Pass = processedCullQuery.RenderingPasses[passElementIndex].Fork();
                    }
                    else
                    {
                        workItem.Pass = processedCullQuery.RenderingPasses[passElementIndex];
                        processedCullQuery.RenderingPasses[passElementIndex] = null;    // Consume the pass so it doesn't get cleaned up later with the cull query, but instead with the work item
                    }

                    m_subworks.Add(workItem);

                    passBegin += toTake;
                    work      += toTake;

                    Debug.Assert(work <= batchWork);
                    if (work != batchWork)
                    {
                        continue;
                    }

                    if (MyRender11.DeferredContextsEnabled)
                    {
                        var renderWork = MyObjectPoolManager.Allocate <MyRenderingWorkRecordCommands>();
                        renderWork.Init(MyManagers.DeferredRCs.AcquireRC(), m_subworks);
                        m_workList.Add(renderWork);
                    }
                    else
                    {
                        var renderWork = MyObjectPoolManager.Allocate <MyRenderingWorkRecordCommands>();
                        renderWork.Init(m_subworks);
                        m_workList.Add(renderWork);
                    }

                    work = 0;

                    m_subworks.Clear();
                }
            }
            if (m_subworks.Count > 0)
            {
                if (MyRender11.DeferredContextsEnabled)
                {
                    var renderWork = MyObjectPoolManager.Allocate <MyRenderingWorkRecordCommands>();
                    renderWork.Init(MyManagers.DeferredRCs.AcquireRC(), m_subworks);
                    m_workList.Add(renderWork);
                }
                else
                {
                    var renderWork = MyObjectPoolManager.Allocate <MyRenderingWorkRecordCommands>();
                    renderWork.Init(m_subworks);
                    m_workList.Add(renderWork);
                }
                m_subworks.Clear();
            }

            ProfilerShort.End();

            ProfilerShort.End();

            DoRecordingWork(outCommandLists);

            foreach (var renderWork in m_workList)
            {
                foreach (var pass in renderWork.Passes)
                {
                    ProfilerShort.Begin(pass.DebugName);
                    ProfilerShort.End(0,
                                      new VRage.Library.Utils.MyTimeSpan(pass.Elapsed));
                }
                MyObjectPoolManager.Deallocate(renderWork);
            }
            m_workList.Clear();
        }
        internal static void Dispatch_LoopPassThenObject(List <MyRenderingPass> queues, MyCullQuery cullingResults, Queue <CommandList> accumulator)
        {
            MyRender11.GetRenderProfiler().StartProfilingBlock("PrepareWork");

            m_workList.Clear();
            accumulator.Clear();

            List <List <MyRenderCullResultFlat> > passElements  = new List <List <MyRenderCullResultFlat> >();
            List <MyRenderableProxy_2[]>          passElements2 = new List <MyRenderableProxy_2[]>();


            foreach (var q in queues)
            {
                if (!MyRender11.DeferredContextsEnabled)
                {
                    q.SetImmediate(true);
                }

                passElements.Add(new List <MyRenderCullResultFlat>());
                passElements2.Add(null);
            }

            //bool okAfterCull = false;

            for (int i = 0; i < cullingResults.Size; i++)
            {
                var affectedQueueIds = new List <int>();

                for (int j = 0; j < queues.Count; j++)
                {
                    if ((queues[j].ProcessingMask & cullingResults.FrustumQuery[i].Bitmask) > 0)
                    {
                        affectedQueueIds.Add(j);
                    }
                }

                //if (cullingResults.FrustumQuery[i].Type == MyFrustumEnum.MainFrustum)
                //{
                //    foreach (var e in cullingResults.FrustumQuery[i].List)
                //    {
                //        if (e.Proxies[0].Parent.m_owner.ID == 1417)
                //        {
                //            okAfterCull = true;
                //            break;
                //        }
                //    }
                //}

                // proxy
                var list = cullingResults.FrustumQuery[i].List;
                for (int j = 0; j < list.Count; j++)
                {
                    for (int k = 0; k < list[j].Proxies.Length; k++)
                    {
                        var proxy   = list[j].Proxies[k];
                        var sortKey = list[j].SortingKeys[k];

                        for (int l = 0; l < affectedQueueIds.Count; l++)
                        {
                            var item = new MyRenderCullResultFlat();
                            item.renderProxy = proxy;
                            item.sortKey     = sortKey;

                            passElements[affectedQueueIds[l]].Add(item);
                        }
                    }
                }

                // proxy 2
                var list2 = cullingResults.FrustumQuery[i].List2;

                // flatten and sort
                List <UInt64>            flattenedKeys = new List <ulong>();
                List <int>               indirection   = new List <int>();
                List <Tuple <int, int> > location      = new List <Tuple <int, int> >();

                int c = 0;
                for (int a = 0; a < list2.Count; a++)
                {
                    for (int b = 0; b < list2[a].SortingKeys.Length; b++)
                    {
                        flattenedKeys.Add(list2[a].SortingKeys[b]);
                        indirection.Add(c++);
                        location.Add(Tuple.Create(a, b));
                    }
                }

                MyRenderableProxy_2[] flattenedProxies = new MyRenderableProxy_2[c];

                var comparerer = new MySortingKeysComparerer();
                comparerer.Values = flattenedKeys;
                indirection.Sort(0, indirection.Count, comparerer);

                for (int e = 0; e < c; e++)
                {
                    var l = location[indirection[e]];
                    flattenedProxies[e] = list2[l.Item1].Proxies[l.Item2];
                }


                for (int l = 0; l < affectedQueueIds.Count; l++)
                {
                    passElements2[affectedQueueIds[l]] = flattenedProxies;
                }
            }

            foreach (var list in passElements)
            {
                list.Sort(MyCullResultsComparer.Instance);
            }

            //var okAfterSort = false;

            //for (int i = 0; i < queues.Count; i++ )
            //{
            //    if (queues[i] as MyGBufferPass != null)
            //    {
            //        foreach (var e in passElements[i])
            //        {
            //            if (e.renderProxy.Parent.m_owner.ID == 1417)
            //            {
            //                okAfterSort = true;
            //                break;
            //            }
            //        }
            //    }
            //}

            int jobsNum = GetRenderingThreadsNum();

            // always amortize this path
            MyRender11.GetRenderProfiler().StartProfilingBlock("WorkAmortization");

            //passElements.RemoveAll(x => x.Count == 0);

            int workSum = 0;

            foreach (var list in passElements)
            {
                workSum += list.Count;
            }

            int batchWork = (workSum + jobsNum - 1) / jobsNum;

            //var renderingWork = new MyRenderingWork_LoopPassObject();
            var subworks = new List <MyRenderingWorkItem>();

            int work = 0;

            for (int i = 0; i < passElements.Count; i++)
            {
                var list      = passElements[i];
                int passBegin = 0;

                subworks.Add(new MyRenderingWorkItem {
                    Pass = queues[i].Fork(), List2 = passElements2[i]
                });

                while (passBegin < list.Count)
                {
                    var toTake = Math.Min(list.Count - passBegin, batchWork - work);

                    var workItem = new MyRenderingWorkItem();
                    if (toTake < list.Count)
                    {
                        workItem.Pass = queues[i].Fork();
                    }
                    else
                    {
                        workItem.Pass = queues[i];
                    }

                    workItem.Renderables = list;
                    workItem.Begin       = passBegin;
                    workItem.End         = passBegin + toTake;

                    //renderingWork.m_subworks.Add(workItem);
                    subworks.Add(workItem);

                    passBegin += toTake;
                    work      += toTake;

                    if (work == batchWork)
                    {
                        if (MyRender11.DeferredContextsEnabled)
                        {
                            m_workList.Add(new MyRenderingWork_LoopPassThenObject(MyRenderContextPool.AcquireRC(), subworks));
                        }
                        else
                        {
                            m_workList.Add(new MyRenderingWork_LoopPassThenObject(subworks));
                        }

                        work     = 0;
                        subworks = new List <MyRenderingWorkItem>();
                        ///renderingWork = new MyRenderingWork_LoopPassObject(, subworks);
                    }
                }
            }
            if (subworks.Count > 0)
            {
                if (MyRender11.DeferredContextsEnabled)
                {
                    m_workList.Add(new MyRenderingWork_LoopPassThenObject(MyRenderContextPool.AcquireRC(), subworks));
                }
                else
                {
                    m_workList.Add(new MyRenderingWork_LoopPassThenObject(subworks));
                }
            }

            //bool okInWorklist = false;
            //foreach(var wl in m_workList)
            //{
            //    var impl = wl as MyRenderingWork_LoopPassThenObject;


            //    foreach(var sub in impl.m_subworks)
            //    {
            //        if((sub.Pass as MyGBufferPass) != null && sub.Renderables != null)
            //        {
            //            foreach(var r in sub.Renderables)
            //            {
            //                if(r.renderProxy.Parent.m_owner.ID == 1417)
            //                {
            //                    okInWorklist = true;
            //                    break;
            //                }
            //            }
            //        }
            //    }
            //}

            MyRender11.GetRenderProfiler().EndProfilingBlock();
            MyRender11.GetRenderProfiler().EndProfilingBlock();


            ScheduleAndWait(accumulator);
        }