/// <summary> /// Attempts to set the hardware that will be used for rendering by the system. You do not need to call this method before /// starting the system: Reasonable defaults will be selected for you. /// </summary> /// <param name="gpuIndex">The <see cref="GraphicsProcessingUnit.Index">index</see> slot of the gpu to use.</param> /// <param name="displayIndex">The <see cref="OutputDisplay.Index">index</see> slot of the output to use.</param> /// <exception cref="ArgumentOutOfRangeException">Thrown if </exception> /// <exception cref="InvalidOperationException">Thrown if you attempt to set the hardware while the /// <see cref="LosgapSystem">system</see> is running (you must stop the system to change the hardware).</exception> /// <seealso cref="SetHardware(Ophidian.Losgap.Rendering.GraphicsProcessingUnit,Ophidian.Losgap.Rendering.OutputDisplay)"/> public static void SetHardware(int gpuIndex, int displayGPUIndex, int?displayIndex) { using (RenderStateBarrier.AcquirePermit(withLock: staticMutationLock)) { if (installedGPUs == null) { throw new InvalidOperationException("Can not set hardware before module has been added."); } if (LosgapSystem.IsRunning) { throw new InvalidOperationException("Can not set hardware while system is running."); } if (gpuIndex >= installedGPUs.Length || gpuIndex < 0) { throw new ArgumentOutOfRangeException("gpuIndex"); } if (displayIndex == null) { displayIndex = 0; } selectedGPUIndex = gpuIndex; selectedOutputGPUIndex = displayGPUIndex; selectedOutputIndex = displayIndex; Logger.Log("Selected GPU set to " + SelectedGPU); Logger.Log("Selected output GPU set to " + SelectedOutputGPU); Logger.Log("Selected output set to " + SelectedOutputDisplay); } }
private unsafe static void OnSystemStarting() { // Lock here because this method is called from a triggered public event using (RenderStateBarrier.AcquirePermit(withLock: staticMutationLock)) { CreateDeviceIfNecessary(); } }
/// <summary> /// Remove all <see cref="RenderPass"/>es from the pipeline. /// </summary> public static void ClearPasses() { using (RenderStateBarrier.AcquirePermit(withLock: staticMutationLock)) { activePasses.Clear(); } Logger.Log("Removed all render passes."); }
/// <summary> /// Removes a previously-added <see cref="RenderPass"/> from the renderer. The pass will no longer be executed on each frame. /// </summary> /// <param name="renderPass">The pass to remove. Must not be null, and must currently be added.</param> public static void RemoveRenderPass(RenderPass renderPass) { if (renderPass == null) { throw new ArgumentNullException("renderPass"); } using (RenderStateBarrier.AcquirePermit(withLock: staticMutationLock)) { if (!activePasses.Remove(renderPass)) { throw new InvalidOperationException("Render pass not currently added."); } Logger.Log("Removed " + renderPass + "."); } }
/// <summary> /// Add a new <see cref="RenderPass"/> to the renderer. The pass will be executed on each frame, after all previously-added /// passes. You can insert the new pass ahead of others in the list instead using <see cref="InsertRenderPass"/>. /// </summary> /// <param name="renderPass">The render pass to add. Must not be null or already added.</param> public static void AddRenderPass(RenderPass renderPass) { if (renderPass == null) { throw new ArgumentNullException("renderPass"); } lock (staticMutationLock) { if (activePasses.Contains(renderPass)) { throw new InvalidOperationException("Render pass already added."); } using (RenderStateBarrier.AcquirePermit()) activePasses.Add(renderPass); Logger.Log("Added " + renderPass + "."); } }
private unsafe static void CreateDeviceIfNecessary() { using (RenderStateBarrier.AcquirePermit()) { // Create device if (device == DeviceHandle.NULL) { Logger.Debug("Creating device..."); DeviceHandle outDeviceHandle; InteropBool outSupportsMT; InteropUtils.CallNative( NativeMethods.DeviceFactory_CreateDevice, SelectedGPU.Index, SelectedOutputGPU.Index, SelectedOutputDisplay.Index, (IntPtr)(&outDeviceHandle), (IntPtr)(&outSupportsMT) ).ThrowOnFailure(); Device = outDeviceHandle; deviceSupportsMTRendering = outSupportsMT; if (!deviceSupportsMTRendering) { Logger.Warn("Selected adapter/device does not support multithreaded command lists. " + "Multithreaded rendering will be disabled, resulting in a potentially significant performance penalty. " + "You are strongly recommended to upgrade your graphics drivers to the latest version."); } } // Create thread-local device context wrapper if (threadLocalDeviceContext == null) { Logger.Debug("Creating thread-local device context wrapper..."); threadLocalDeviceContext = new ThreadLocal <DeviceContextHandle>(CreateThreadLocalDeviceContext, true); } } }
private unsafe static void OnSystemExited() { // Lock here because this method is called from a triggered public event using (RenderStateBarrier.AcquirePermit(withLock: staticMutationLock)) { // Close windows Logger.Debug("Closing windows..."); HashSet <Window> openWindowsCopy = new HashSet <Window>(); Window.OpenWindows.CopyTo(openWindowsCopy); foreach (Window window in openWindowsCopy) { window.Close(); } // Destroy device contexts Logger.Debug("Destroying device contexts..."); threadLocalDeviceContext.Values.ForEach(dc => InteropUtils.CallNative(NativeMethods.ContextFactory_ReleaseContext, dc)); threadLocalDeviceContext = null; // Destroy device Logger.Debug("Destroying device..."); InteropUtils.CallNative(NativeMethods.DeviceFactory_ReleaseDevice, Device).ThrowOnFailure(); Device = DeviceHandle.NULL; } }
/// <summary> /// Inserts a new <see cref="RenderPass"/> in to the rendering pipeline, to be executed on each frame before <paramref name="insertionKey"/>. /// </summary> /// <param name="renderPass">The pass to add. Must not be null or already added.</param> /// <param name="insertionKey">The already-added pass to insert <paramref name="renderPass"/> in front of. Must not be null, and must /// currently be added.</param> public static void InsertRenderPass(RenderPass renderPass, RenderPass insertionKey) { if (renderPass == null) { throw new ArgumentNullException("renderPass"); } if (insertionKey == null) { throw new ArgumentNullException("insertionKey"); } lock (staticMutationLock) { if (activePasses.Contains(renderPass)) { throw new InvalidOperationException("Render pass already added."); } else if (!activePasses.Contains(insertionKey)) { throw new InvalidOperationException("Insertion key pass not currently added."); } using (RenderStateBarrier.AcquirePermit()) activePasses.Insert(activePasses.IndexOf(insertionKey), renderPass); Logger.Log("Added " + renderPass + "."); } }