/// <summary> /// Synchronously renders a complete frame to the specified render target. /// Automatically sets up the device's viewport and the view transform of your materials and restores them afterwards. /// </summary> public bool SynchronousDrawToRenderTarget(RenderTarget2D renderTarget, DefaultMaterialSet materials, Action <Frame> drawBehavior) { if (renderTarget.IsDisposed) { return(false); } if (!SynchronousDrawsEnabled) { throw new InvalidOperationException("Synchronous draws not available inside of Game.Draw"); } WaitForActiveDraw(); var oldDrawIsActive = Interlocked.Exchange(ref _SynchronousDrawIsActive, 1); if (oldDrawIsActive != 0) { throw new InvalidOperationException("A synchronous draw is already in progress"); } _SynchronousDrawFinishedSignal.Reset(); WaitForActiveDraw(); try { using (var frame = Manager.CreateFrame()) { materials.PushViewTransform(ViewTransform.CreateOrthographic(renderTarget.Width, renderTarget.Height)); ClearBatch.AddNew(frame, int.MinValue, materials.Clear, clearColor: Color.Transparent); drawBehavior(frame); PrepareNextFrame(frame, false); var oldRenderTargets = Device.GetRenderTargets(); var oldViewport = Device.Viewport; try { Device.SetRenderTarget(renderTarget); RenderManager.ResetDeviceState(Device); Device.Viewport = new Viewport(0, 0, renderTarget.Width, renderTarget.Height); RenderFrameToDraw(frame, false); } finally { Device.SetRenderTargets(oldRenderTargets); materials.PopViewTransform(); Device.Viewport = oldViewport; } } return(true); } finally { _SynchronousDrawFinishedSignal.Set(); Interlocked.Exchange(ref _SynchronousDrawIsActive, 0); } }
private bool DoSynchronousDrawToRenderTarget( RenderTarget2D renderTarget, DefaultMaterialSet materials, Delegate drawBehavior, object userData, ref ViewTransform?viewTransform, string description ) { var oldLazyState = materials.LazyViewTransformChanges; try { materials.LazyViewTransformChanges = false; materials.ApplyViewTransform(materials.ViewTransform, true); using (var frame = Manager.CreateFrame(this)) { frame.ChangeRenderTargets = false; frame.Label = description; if (viewTransform.HasValue) { materials.PushViewTransform(in viewTransform); } else { materials.PushViewTransform(ViewTransform.CreateOrthographic(renderTarget.Width, renderTarget.Height)); } try { // FIXME: Should queued draws run here? They are probably meant to run in the next real frame var singleBehavior = drawBehavior as Action <Frame>; var multiBehavior = drawBehavior as PendingDrawHandler; if (singleBehavior != null) { singleBehavior(frame); } else if (multiBehavior != null) { multiBehavior(frame, materials, userData); } else { throw new ArgumentException("Draw behavior was not of a compatible type"); } RunBeforePrepareHandlers(); PrepareNextFrame(frame, false); Manager.DeviceManager.SetRenderTarget(renderTarget); RenderManager.ResetDeviceState(Device); Device.Clear(Color.Transparent); RenderFrameToDraw(frame, false); // We don't have to push/pop anymore because the stacks are cleared at the end of a frame. return(true); } finally { materials.PopViewTransform(); } } } finally { materials.LazyViewTransformChanges = oldLazyState; } }
public override void Issue(DeviceManager manager) { manager.BatchGroupStack.Push(this); base.Issue(manager); // HACK: If the user set a material on us explicitly, apply our parameters to it if (Material != null) { Material.Flush(manager, ref MaterialParameters); } if (OcclusionQuery != null) { OcclusionQuery.Begin(); } bool pop = false; if (ViewTransform.HasValue || ViewTransformModifier != null) { if (MaterialSet == null) { throw new NullReferenceException("MaterialSet must be set if ViewTransform or ViewTransformModifier are set"); } var vt = ViewTransform ?? MaterialSet.ViewTransform; if (ViewTransformModifier != null) { ViewTransformModifier(ref vt, _UserData); } // FIXME: We shouldn't need force: true MaterialSet.PushViewTransform(in vt, force: true); pop = true; } if (_Before != null) { _Before(manager, _UserData); } try { // manager.Device.SetStringMarkerEXT(this.ToString()); using (var b = _DrawCalls.GetBuffer(false)) { for (int i = 0; i < b.Count; i++) { if (b[i] != null) { b[i].IssueAndWrapExceptions(manager); } } } } finally { if (_After != null) { _After(manager, _UserData); } if (OcclusionQuery != null) { OcclusionQuery.End(); } if (pop) { MaterialSet.PopViewTransform(force: true); } manager.BatchGroupStack.Pop(); } }