/// <summary> /// Initializes a new instance of the <see cref="DeviceHandlerD3D9"/> class. /// </summary> /// <param name="dxgiAdapter">The target adapter.</param> /// <param name="isSoftwareAdapter">Are we in software mode?</param> /// <param name="debugEnabled">Is debug mode enabled?</param> internal DeviceHandlerD3D9(DXGI.Adapter1 dxgiAdapter, bool isSoftwareAdapter, bool debugEnabled) { // Update member variables m_dxgiAdapter = dxgiAdapter; try { // Just needed when on true hardware if (!isSoftwareAdapter) { //Prepare device creation D3D9.CreateFlags createFlags = D3D9.CreateFlags.HardwareVertexProcessing | D3D9.CreateFlags.PureDevice | D3D9.CreateFlags.FpuPreserve | D3D9.CreateFlags.Multithreaded; D3D9.PresentParameters presentparams = new D3D9.PresentParameters(); presentparams.Windowed = true; presentparams.SwapEffect = D3D9.SwapEffect.Discard; presentparams.DeviceWindowHandle = GetDesktopWindow(); presentparams.PresentationInterval = D3D9.PresentInterval.Default; presentparams.BackBufferCount = 1; //Create the device finally m_direct3DEx = new D3D9.Direct3DEx(); // Try to find the Direct3D9 adapter that maches given DXGI adapter m_adapterIndex = -1; for (int loop = 0; loop < m_direct3DEx.AdapterCount; loop++) { var d3d9AdapterInfo = m_direct3DEx.GetAdapterIdentifier(loop); if (d3d9AdapterInfo.DeviceId == m_dxgiAdapter.Description1.DeviceId) { m_adapterIndex = loop; break; } } // Direct3D 9 is only relevant on the primary device if (m_adapterIndex < 0) { return; } // Try to create the device m_deviceEx = new D3D9.DeviceEx(m_direct3DEx, m_adapterIndex, D3D9.DeviceType.Hardware, IntPtr.Zero, createFlags, presentparams); } else { //Not supported in software mode } } catch (Exception) { // No direct3d 9 interface support GraphicsHelper.SafeDispose(ref m_direct3DEx); GraphicsHelper.SafeDispose(ref m_deviceEx); } }
protected void CreateD3D9Device() { // Update focus window. var primaryRenderWindow = PrimaryWindow; // Case we have to share the same focus window. this._focusWindow = SharedFocusWindow != IntPtr.Zero ? SharedFocusWindow : primaryRenderWindow.WindowHandle; var pD3D9 = D3D9RenderSystem.Direct3D9; if ( IsMultihead ) { this.BehaviorFlags |= D3D9.CreateFlags.AdapterGroupDevice; } else { this.BehaviorFlags &= ~D3D9.CreateFlags.AdapterGroupDevice; } // Try to create the device with hardware vertex processing. this.BehaviorFlags |= D3D9.CreateFlags.HardwareVertexProcessing; var keepTrying = true; var loopCount = 0; LogManager.Instance.Write( "Creating D3D9 Device..." ); while ( keepTrying ) { try { this.pDevice = new D3D9.Device( pD3D9, AdapterNumber, DeviceType, this._focusWindow, this.BehaviorFlags, this.PresentationParams ); keepTrying = false; } catch ( DX.SharpDXException ex ) { LogManager.Instance.Write( "FAIL!" ); switch ( loopCount ) { case 0: // Try a second time, may fail the first time due to back buffer count, // which will be corrected down to 1 by the runtime LogManager.Instance.Write( "Trying to create the device a second time.." ); break; case 1: // Case hardware vertex processing failed. // Try to create the device with mixed vertex processing. this.BehaviorFlags &= ~D3D9.CreateFlags.HardwareVertexProcessing; this.BehaviorFlags |= D3D9.CreateFlags.MixedVertexProcessing; LogManager.Instance.Write( "Trying to create the device with mixed vertex processing.." ); break; case 2: // try to create the device with software vertex processing. this.BehaviorFlags &= ~D3D9.CreateFlags.MixedVertexProcessing; this.BehaviorFlags |= D3D9.CreateFlags.SoftwareVertexProcessing; LogManager.Instance.Write( "Trying to create the device with software vertex processing.." ); break; case 3: // try reference device DeviceType = D3D9.DeviceType.Reference; LogManager.Instance.Write( "Trying to create a reference device.." ); break; default: throw new AxiomException( "Cannot create device!", ex ); } ; loopCount++; } } ; // Get current device caps. this.d3d9DeviceCaps = this.pDevice.Capabilities; // Get current creation parameters caps. this.creationParams = this.pDevice.CreationParameters; this.D3D9DeviceCapsValid = true; // Initialize device states. SetupDeviceStates(); // Lock access to rendering device. D3D9RenderSystem.ResourceManager.LockDeviceAccess(); var pCurActiveDevice = this.pDeviceManager.ActiveDevice; this.pDeviceManager.ActiveDevice = this; // Inform all resources that new device created. D3D9RenderSystem.ResourceManager.NotifyOnDeviceCreate( this.pDevice ); this.pDeviceManager.ActiveDevice = pCurActiveDevice; // UnLock access to rendering device. D3D9RenderSystem.ResourceManager.UnlockDeviceAccess(); }
public D3D9Device( D3D9DeviceManager d3D9DeviceManager, int adapterNumber, IntPtr hMonitor, D3D9.DeviceType devType, D3D9.CreateFlags behaviourFlags ) { this.pDeviceManager = d3D9DeviceManager; AdapterNumber = adapterNumber; this._monitor = hMonitor; DeviceType = devType; this._focusWindow = IntPtr.Zero; this.BehaviorFlags = behaviourFlags; }
private D3D9Device _selectDevice(D3D9RenderWindow renderWindow, D3D9RenderWindowList renderWindowsGroup) { var renderSystem = D3D9RenderSystem.Instance; D3D9Device renderDevice = null; var direct3D9 = D3D9RenderSystem.Direct3D9; var nAdapterOrdinal = 0; // D3DADAPTER_DEFAULT var devType = D3D9.DeviceType.Hardware; D3D9.CreateFlags extraFlags = 0; var driverList = renderSystem.Direct3DDrivers; var nvAdapterFound = false; // Default group includes at least the given render window. renderWindowsGroup.Add(renderWindow); // Case we use nvidia performance HUD, override the device settings. if (renderWindow.IsNvPerfHUDEnable) { // Look for 'NVIDIA NVPerfHUD' adapter (<= v4) // or 'NVIDIA PerfHUD' (v5) // If it is present, override default settings for (var adapter = 0; adapter < direct3D9.AdapterCount; ++adapter) { var currDriver = driverList[adapter]; if (!currDriver.DriverDescription.Contains("PerfHUD")) { continue; } // renderDevice = null; nAdapterOrdinal = adapter; renderSystem._activeD3DDriver = currDriver; devType = D3D9.DeviceType.Reference; nvAdapterFound = true; break; } } // No special adapter should be used. if (nvAdapterFound == false) { renderSystem._activeD3DDriver = _findDriver(renderWindow); nAdapterOrdinal = renderSystem._activeD3DDriver.AdapterNumber; var bTryUsingMultiheadDevice = false; if (renderWindow.IsFullScreen) { bTryUsingMultiheadDevice = true; var osVersionInfo = System.Environment.OSVersion; // XP and below - multi-head will cause artifacts when vsync is on. if (osVersionInfo.Version.Major <= 5 && renderWindow.IsVSync) { bTryUsingMultiheadDevice = false; LogManager.Instance.Write( "D3D9 : Multi head disabled. It causes horizontal line when used in XP + VSync combination"); } // Vista and SP1 or SP2 - multi-head device can not be reset - it causes memory corruption. if (osVersionInfo.Version.Major == 6 && (osVersionInfo.ServicePack.Contains("Service Pack 1") || osVersionInfo.ServicePack.Contains("Service Pack 2"))) { bTryUsingMultiheadDevice = false; LogManager.Instance.Write( "D3D9 : Multi head disabled. It causes application run time crashes when used in Vista + SP 1 or 2 combination"); } } // Check if we can create a group of render windows // on the same device using the multi-head feature. if (bTryUsingMultiheadDevice) { var targetAdapterCaps = renderSystem._activeD3DDriver.D3D9DeviceCaps; var masterAdapterCaps = new Capabilities(); // Find the master device caps. if (targetAdapterCaps.MasterAdapterOrdinal == targetAdapterCaps.AdapterOrdinal) { masterAdapterCaps = targetAdapterCaps; } else { foreach (var currDriver in driverList) { var currDeviceCaps = currDriver.D3D9DeviceCaps; if (currDeviceCaps.AdapterOrdinal != targetAdapterCaps.MasterAdapterOrdinal) { continue; } masterAdapterCaps = currDeviceCaps; break; } } // Case the master adapter can handle multiple adapters. if (masterAdapterCaps.NumberOfAdaptersInGroup > 1) { // Create empty list of render windows composing this group. renderWindowsGroup.Clear(); while (renderWindowsGroup.Count < masterAdapterCaps.NumberOfAdaptersInGroup) { renderWindowsGroup.Add(null); } // Assign the current render window to it's place in the group. renderWindowsGroup[targetAdapterCaps.AdapterOrdinalInGroup] = renderWindow; // For each existing window - check if it belongs to the group. foreach (var currRenderWindow in renderSystem.RenderWindows) { if (!currRenderWindow.IsFullScreen) { continue; } var currDriver = _findDriver((D3D9RenderWindow)currRenderWindow); var currDeviceCaps = currDriver.D3D9DeviceCaps; if (currDeviceCaps.MasterAdapterOrdinal != masterAdapterCaps.AdapterOrdinal) { continue; } renderWindowsGroup[currDeviceCaps.AdapterOrdinalInGroup] = (D3D9RenderWindow)currRenderWindow; break; } var bDeviceGroupFull = true; // Check if render windows group is full and ready to be driven by // the master device. for (var i = 0; i < renderWindowsGroup.Count; ++i) { // This group misses required window -> go back to default. if (renderWindowsGroup[i] != null) { continue; } bDeviceGroupFull = false; renderWindowsGroup.Clear(); renderWindowsGroup.Add(renderWindow); break; } // Case device group is full -> we can use multi head device. if (bDeviceGroupFull) { var validateAllDevices = false; for (var i = 0; i < renderWindowsGroup.Count; ++i) { var currRenderWindow = renderWindowsGroup[i]; var currDevice = currRenderWindow.Device; // This is the master window if (i == 0) { // If master device exists - just release it. if (currDevice != null) { renderDevice = currDevice; renderDevice.Release(); } } // This is subordinate window. else { // If subordinate device exists - destroy it. if (currDevice != null) { currDevice.Destroy(); validateAllDevices = true; } } } // In case some device was destroyed - make sure all other devices are valid. // A possible scenario is that full screen window has been destroyed and it's handle // was used and the shared focus handle. All other devices used this handle and must be // recreated using other handles otherwise create device will fail. if (validateAllDevices) { foreach (var dev in this._renderDevices) { dev.ValidateFocusWindow(); } } } } } } // Do we want to preserve the FPU mode? Might be useful for scientific apps var options = renderSystem.ConfigOptions; ConfigOption opti; if (options.TryGetValue("Floating-point mode", out opti) && opti.Value == "Consistent") { extraFlags |= D3D9.CreateFlags.FpuPreserve; } #if AXIOM_THREAD_SUPPORT if (Configuration.Config.AxiomThreadLevel == 1) { extraFlags |= D3D9.CreateFlags.Multithreaded; } #endif // Try to find a matching device from current device list. if (renderDevice == null) { foreach (var currDevice in this._renderDevices) { if (currDevice.AdapterNumber != nAdapterOrdinal || currDevice.DeviceType != devType) { continue; } renderDevice = currDevice; break; } } // No matching device found -> try reference device type (might have been // previously created as a fallback, but don't change devType because HAL // should be preferred on creation) if (renderDevice == null) { foreach (var currDevice in this._renderDevices) { if (currDevice.AdapterNumber != nAdapterOrdinal || currDevice.DeviceType != D3D9.DeviceType.Reference) { continue; } renderDevice = currDevice; break; } } // No matching device found -> create new one. if (renderDevice == null) { renderDevice = new D3D9Device(this, nAdapterOrdinal, direct3D9.GetAdapterMonitor(nAdapterOrdinal), devType, extraFlags); this._renderDevices.Add(renderDevice); if (this._activeDevice == null) { ActiveDevice = renderDevice; } } return(renderDevice); }