Пример #1
0
        /// <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);
            }
        }
Пример #2
0
		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();
		}
Пример #3
0
		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;
		}
Пример #4
0
        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);
        }