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(Environment.ProcessorCount, 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); } }
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); }
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; }
public RenderViewStage(RenderStage renderStage) { Index = renderStage.Index; RenderNodes = null; SortedRenderNodes = null; }
/// <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]); }