public RenderViewFeatureStage(RenderStage renderStage, int renderNodeStart, int renderNodeEnd)
 {
     RenderStage     = renderStage;
     RenderNodeStart = renderNodeStart;
     RenderNodeEnd   = renderNodeEnd;
 }
Exemple #2
0
        public void Draw(RenderDrawContext renderDrawContext, RenderView renderView, RenderStage renderStage)
        {
            // Sync point: draw (from now, we should execute with a graphics device context to perform rendering)

            // Look for the RenderViewStage corresponding to this RenderView | RenderStage combination
            var renderViewStage = RenderViewStage.Invalid;

            foreach (var currentRenderViewStage in renderView.RenderStages)
            {
                if (currentRenderViewStage.Index == renderStage.Index)
                {
                    renderViewStage = currentRenderViewStage;
                    break;
                }
            }

            if (renderViewStage.Index == -1)
            {
                throw new InvalidOperationException("Requested RenderView|RenderStage combination doesn't exist. Please add it to RenderView.RenderStages.");
            }

            // Perform updates once per change of RenderView
            foreach (var renderFeature in RenderFeatures)
            {
                renderFeature.Draw(renderDrawContext, renderView, renderViewStage);
            }

            // Generate and execute draw jobs
            var renderNodes     = renderViewStage.SortedRenderNodes;
            var renderNodeCount = renderViewStage.RenderNodes.Count;

            if (renderNodeCount == 0)
            {
                return;
            }

            if (!GraphicsDevice.IsDeferred)
            {
                int currentStart, currentEnd;
                for (currentStart = 0; currentStart < renderNodeCount; currentStart = currentEnd)
                {
                    var currentRenderFeature = renderNodes[currentStart].RootRenderFeature;
                    currentEnd = currentStart + 1;
                    while (currentEnd < renderNodeCount && renderNodes[currentEnd].RootRenderFeature == currentRenderFeature)
                    {
                        currentEnd++;
                    }

                    // Divide into task chunks for parallelism
                    currentRenderFeature.Draw(renderDrawContext, renderView, renderViewStage, currentStart, currentEnd);
                }
            }
            else
            {
                // Create at most one batch per processor
                int batchCount = Math.Min(Xenko.Core.Threading.Dispatcher.MaxDegreeOfParallelism, renderNodeCount);
                int batchSize  = (renderNodeCount + (batchCount - 1)) / batchCount;
                batchCount = (renderNodeCount + (batchSize - 1)) / batchSize;

                // Remember state
                var depthStencilBuffer = renderDrawContext.CommandList.DepthStencilBuffer;
                int renderTargetCount  = renderDrawContext.CommandList.RenderTargetCount;
                if (renderTargets == null)
                {
                    renderTargets = new Texture[renderDrawContext.CommandList.RenderTargets.Length];
                }
                for (int i = 0; i < renderTargetCount; ++i)
                {
                    renderTargets[i] = renderDrawContext.CommandList.RenderTargets[i];
                }
                var viewport = renderDrawContext.CommandList.Viewport;
                var scissor  = renderDrawContext.CommandList.Scissor;

                // Collect one command list per batch and the main one up to this point
                if (commandLists == null || commandLists.Length < batchCount + 1)
                {
                    Array.Resize(ref commandLists, batchCount + 1);
                }
                commandLists[0] = renderDrawContext.CommandList.Close();

                Dispatcher.For(0, batchCount, () => renderDrawContext.RenderContext.GetThreadContext(), (batchIndex, threadContext) =>
                {
                    threadContext.CommandList.Reset();
                    threadContext.CommandList.ClearState();

                    // Transfer state to all command lists
                    threadContext.CommandList.SetRenderTargets(depthStencilBuffer, renderTargetCount, renderTargets);
                    threadContext.CommandList.SetViewport(viewport);
                    threadContext.CommandList.SetScissorRectangle(scissor);

                    var currentStart = batchSize * batchIndex;
                    int currentEnd;

                    var endExclusive = Math.Min(renderNodeCount, currentStart + batchSize);

                    if (endExclusive <= currentStart)
                    {
                        return;
                    }

                    for (; currentStart < endExclusive; currentStart = currentEnd)
                    {
                        var currentRenderFeature = renderNodes[currentStart].RootRenderFeature;
                        currentEnd = currentStart + 1;
                        while (currentEnd < endExclusive && renderNodes[currentEnd].RootRenderFeature == currentRenderFeature)
                        {
                            currentEnd++;
                        }

                        // Divide into task chunks for parallelism
                        currentRenderFeature.Draw(threadContext, renderView, renderViewStage, currentStart, currentEnd);
                    }

                    commandLists[batchIndex + 1] = threadContext.CommandList.Close();
                });

                GraphicsDevice.ExecuteCommandLists(batchCount + 1, commandLists);

                renderDrawContext.CommandList.Reset();
                renderDrawContext.CommandList.ClearState();

                // Reapply previous state
                renderDrawContext.CommandList.SetRenderTargets(depthStencilBuffer, renderTargetCount, renderTargets);
                renderDrawContext.CommandList.SetViewport(viewport);
                renderDrawContext.CommandList.SetScissorRectangle(scissor);
            }
        }
Exemple #3
0
 /// <summary>
 /// Gets the effect slot for a given render stage.
 /// </summary>
 /// <param name="renderStage"></param>
 /// <returns></returns>
 public EffectPermutationSlot GetEffectPermutationSlot(RenderStage renderStage)
 {
     return(effectSlots[renderStage.Index]);
 }
Exemple #4
0
        internal RenderNodeReference CreateRenderNode(RenderObject renderObject, RenderView renderView, ViewObjectNodeReference renderPerViewNode, RenderStage renderStage)
        {
            var renderNode = new RenderNode(renderObject, renderView, renderPerViewNode, renderStage);

            // Create view node
            var index  = RenderNodes.Add(renderNode);
            var result = new RenderNodeReference(index);

            return(result);
        }
Exemple #5
0
 public RenderNode(RenderObject renderObject, RenderView renderView, ViewObjectNodeReference viewObjectNode, RenderStage renderStage)
 {
     RenderObject     = renderObject;
     RenderView       = renderView;
     ViewObjectNode   = viewObjectNode;
     EffectObjectNode = EffectObjectNodeReference.Invalid;
     RenderStage      = renderStage;
     RenderEffect     = null;
     Resources        = null;
 }