public void LinkRenderWindow(D3D9RenderWindow renderWindow) { // Detach from previous device. var renderDevice = renderWindow.Device; if (renderDevice != null) { renderDevice.DetachRenderWindow(renderWindow); } var renderWindowsGroup = new D3D9RenderWindowList(); // Select new device for this window. renderDevice = _selectDevice(renderWindow, renderWindowsGroup); // Link the windows group to the new device. for (var i = 0; i < renderWindowsGroup.Count; ++i) { var currWindow = renderWindowsGroup[i]; currWindow.Device = renderDevice; renderDevice.AttachRenderWindow(currWindow); renderDevice.SetAdapterOrdinalIndex(currWindow, i); } renderDevice.Acquire(); if (this._activeDevice == null) { ActiveDevice = renderDevice; } }
private D3D9Driver _findDriver(D3D9RenderWindow renderWindow) { var renderSystem = D3D9RenderSystem.Instance; var direct3D9 = D3D9RenderSystem.Direct3D9; var driverList = renderSystem.Direct3DDrivers; // Find the monitor this render window belongs to. var hRenderWindowMonitor = ScreenHelper.GetHandle(renderWindow.WindowHandle); // Find the matching driver using window monitor handle. foreach (var currDriver in driverList) { var hCurrAdpaterMonitor = direct3D9.GetAdapterMonitor(currDriver.AdapterNumber); if (hCurrAdpaterMonitor == hRenderWindowMonitor) { return(currDriver); } } return(null); }
private bool _checkVertexTextureFormats(D3D9RenderWindow renderWindow) { var anySupported = false; var bbSurf = (D3D9.Surface[])renderWindow["DDBACKBUFFER"]; var bbSurfDesc = bbSurf[0].Description; for (var pf = PixelFormat.L8; pf < PixelFormat.Count; ++pf) { var fmt = D3D9Helper.ConvertEnum(D3D9Helper.GetClosestSupported(pf)); if ( !this._pD3D.CheckDeviceFormat(this._activeD3DDriver.AdapterNumber, D3D9.DeviceType.Hardware, bbSurfDesc.Format, D3D9.Usage.QueryVertexTexture, D3D9.ResourceType.Texture, fmt)) { continue; } // cool, at least one supported anySupported = true; LogManager.Instance.Write("D3D9: Vertex texture format supported - {0}", PixelUtil.GetFormatName(pf)); } return(anySupported); }
public void DetachRenderWindow( D3D9RenderWindow renderWindow ) { RenderWindowResources renderWindowResources; if ( this._mapRenderWindowToResources.TryGetValue( renderWindow, out renderWindowResources ) ) { // The focus window in which the d3d9 device created on is detached. // resources must be acquired again. if ( this._focusWindow == renderWindow.WindowHandle ) { this._focusWindow = IntPtr.Zero; } // Case this is the shared focus window. if ( renderWindow.WindowHandle == SharedFocusWindow ) { SharedWindowHandle = IntPtr.Zero; } ReleaseRenderWindowResources( renderWindowResources ); renderWindowResources.SafeDispose(); this._mapRenderWindowToResources.Remove( renderWindow ); } UpdateRenderWindowsIndices(); }
public void AttachRenderWindow( D3D9RenderWindow renderWindow ) { if ( !this._mapRenderWindowToResources.ContainsKey( renderWindow ) ) { var renderWindowResources = new RenderWindowResources(); renderWindowResources.AdapterOrdinalInGroupIndex = 0; renderWindowResources.Acquired = false; this._mapRenderWindowToResources.Add( renderWindow, renderWindowResources ); } UpdateRenderWindowsIndices(); }
protected KeyValuePair<D3D9RenderWindow, RenderWindowResources> GetRenderWindowIterator( D3D9RenderWindow renderWindow ) { if ( !this._mapRenderWindowToResources.ContainsKey( renderWindow ) ) { throw new AxiomException( "Render window was not attached to this device !!" ); } return new KeyValuePair<D3D9RenderWindow, RenderWindowResources>( renderWindow, this._mapRenderWindowToResources[ renderWindow ] ); }
public void CopyContentsToMemory( D3D9RenderWindow renderWindow, PixelBox dst, RenderTarget.FrameBuffer buffer ) { var resources = this._mapRenderWindowToResources[ renderWindow ]; var swapChain = IsSwapChainWindow( renderWindow ); if ( ( dst.Left < 0 ) || ( dst.Right > renderWindow.Width ) || ( dst.Top < 0 ) || ( dst.Bottom > renderWindow.Height ) || ( dst.Front != 0 ) || ( dst.Back != 1 ) ) { throw new AxiomException( "Invalid box." ); } var desc = new D3D9.SurfaceDescription(); DX.DataRectangle lockedRect; D3D9.Surface pTempSurf = null, pSurf = null; if ( buffer == RenderTarget.FrameBuffer.Auto ) { buffer = RenderTarget.FrameBuffer.Front; } if ( buffer == RenderTarget.FrameBuffer.Front ) { var dm = this.pDevice.GetDisplayMode( 0 ); desc.Width = dm.Width; desc.Height = dm.Height; desc.Format = D3D9.Format.A8R8G8B8; pTempSurf = D3D9.Surface.CreateOffscreenPlain( this.pDevice, desc.Width, desc.Height, desc.Format, D3D9.Pool.SystemMemory ); try { if ( swapChain ) { resources.SwapChain.GetFrontBufferData( pTempSurf ); } else { pTempSurf = this.pDevice.GetFrontBufferData( 0 ); } } catch ( DX.SharpDXException ex ) { pTempSurf.SafeDispose(); throw new AxiomException( "Can't get front buffer: {0}", ex.Message ); } if ( renderWindow.IsFullScreen ) { try { if ( ( dst.Left == 0 ) && ( dst.Right == renderWindow.Width ) && ( dst.Top == 0 ) && ( dst.Bottom == renderWindow.Height ) ) { lockedRect = pTempSurf.LockRectangle( D3D9.LockFlags.ReadOnly | D3D9.LockFlags.NoSystemLock ); } else { var rect = new System.Drawing.Rectangle( dst.Left, dst.Top, dst.Right - dst.Left, dst.Bottom - dst.Top ); lockedRect = pTempSurf.LockRectangle( rect, D3D9.LockFlags.ReadOnly | D3D9.LockFlags.NoSystemLock ); } } catch { pTempSurf.SafeDispose(); throw new AxiomException( "Can't lock rect" ); } } else { //GetClientRect(mHWnd, &srcRect); var srcRect = new System.Drawing.Rectangle( dst.Left, dst.Top, dst.Right - dst.Left, dst.Bottom - dst.Top ); var point = new System.Drawing.Point( srcRect.Left, srcRect.Top ); point = System.Windows.Forms.Control.FromHandle( renderWindow.WindowHandle ).PointToScreen( point ); srcRect = new System.Drawing.Rectangle( point.X, point.Y, srcRect.Right + point.X - srcRect.Left, srcRect.Bottom + point.Y - dst.Top ); desc.Width = srcRect.Right - srcRect.Left; desc.Height = srcRect.Bottom - srcRect.Top; try { lockedRect = pTempSurf.LockRectangle( srcRect, D3D9.LockFlags.ReadOnly | D3D9.LockFlags.NoSystemLock ); } catch { pTempSurf.SafeDispose(); throw new AxiomException( "Can't lock rect" ); } } } else { pSurf.SafeDispose(); pSurf = swapChain ? resources.SwapChain.GetBackBuffer( 0 ) : this.pDevice.GetBackBuffer( 0, 0 ); desc = pSurf.Description; pTempSurf = D3D9.Surface.CreateOffscreenPlain( this.pDevice, desc.Width, desc.Height, desc.Format, D3D9.Pool.SystemMemory ); if ( desc.MultiSampleType == D3D9.MultisampleType.None ) { var hr = this.pDevice.GetRenderTargetData( pSurf, pTempSurf ); if ( hr.Failure ) { pTempSurf.SafeDispose(); throw new AxiomException( "Can't get render target data" ); } } else { var pStretchSurf = D3D9.Surface.CreateRenderTarget( this.pDevice, desc.Width, desc.Height, desc.Format, D3D9.MultisampleType.None, 0, false ); var hr = this.pDevice.StretchRectangle( pSurf, pStretchSurf, D3D9.TextureFilter.None ); if ( hr.Failure ) { pTempSurf.SafeDispose(); pStretchSurf.SafeDispose(); throw new AxiomException( "Can't stretch rect" ); } hr = this.pDevice.GetRenderTargetData( pStretchSurf, pTempSurf ); if ( hr.Failure ) { pTempSurf.SafeDispose(); pStretchSurf.SafeDispose(); throw new AxiomException( "Can't get render target data" ); } pStretchSurf.SafeDispose(); } try { if ( ( dst.Left == 0 ) && ( dst.Right == renderWindow.Width ) && ( dst.Top == 0 ) && ( dst.Bottom == renderWindow.Height ) ) { lockedRect = pTempSurf.LockRectangle( D3D9.LockFlags.ReadOnly | D3D9.LockFlags.NoSystemLock ); } else { var rect = new System.Drawing.Rectangle( dst.Left, dst.Top, dst.Right - dst.Left, dst.Bottom - dst.Top ); lockedRect = pTempSurf.LockRectangle( rect, D3D9.LockFlags.ReadOnly | D3D9.LockFlags.NoSystemLock ); } } catch { pTempSurf.SafeDispose(); throw new AxiomException( "Can't lock rect" ); } } var format = D3D9Helper.ConvertEnum( desc.Format ); if ( format == PixelFormat.Unknown ) { pTempSurf.SafeDispose(); throw new AxiomException( "Unsupported format" ); } using ( var data = BufferBase.Wrap( lockedRect.DataPointer, lockedRect.Pitch*dst.Height ) ) { var src = new PixelBox( dst.Width, dst.Height, 1, format, data ); src.RowPitch = lockedRect.Pitch/PixelUtil.GetNumElemBytes( format ); src.SlicePitch = desc.Height*src.RowPitch; PixelConverter.BulkPixelConversion( src, dst ); } pTempSurf.SafeDispose(); pSurf.SafeDispose(); }
private RenderSystemCapabilities _updateRenderSystemCapabilities(D3D9RenderWindow renderWindow) { var rsc = realCapabilities ?? new RenderSystemCapabilities(); rsc.SetCategoryRelevant(CapabilitiesCategory.D3D9, true); rsc.DriverVersion = driverVersion; rsc.DeviceName = this._activeD3DDriver.DriverDescription; rsc.RendersystemName = Name; // Supports fixed-function rsc.SetCapability(Graphics.Capabilities.FixedFunction); // Init caps to maximum. rsc.TextureUnitCount = 1024; rsc.SetCapability(Graphics.Capabilities.AnisotropicFiltering); rsc.SetCapability(Graphics.Capabilities.HardwareMipMaps); rsc.SetCapability(Graphics.Capabilities.Dot3); rsc.SetCapability(Graphics.Capabilities.CubeMapping); rsc.SetCapability(Graphics.Capabilities.ScissorTest); rsc.SetCapability(Graphics.Capabilities.TwoSidedStencil); rsc.SetCapability(Graphics.Capabilities.StencilWrap); rsc.SetCapability(Graphics.Capabilities.HardwareOcculusion); rsc.SetCapability(Graphics.Capabilities.UserClipPlanes); rsc.SetCapability(Graphics.Capabilities.VertexFormatUByte4); rsc.SetCapability(Graphics.Capabilities.Texture3D); rsc.SetCapability(Graphics.Capabilities.NonPowerOf2Textures); rsc.NonPOW2TexturesLimited = false; rsc.MultiRenderTargetCount = Config.MaxMultipleRenderTargets; rsc.SetCapability(Graphics.Capabilities.MRTDifferentBitDepths); rsc.SetCapability(Graphics.Capabilities.PointSprites); rsc.SetCapability(Graphics.Capabilities.PointExtendedParameters); rsc.MaxPointSize = 10.0f; rsc.SetCapability(Graphics.Capabilities.MipmapLODBias); rsc.SetCapability(Graphics.Capabilities.PerStageConstant); rsc.SetCapability(Graphics.Capabilities.StencilBuffer); rsc.StencilBufferBitCount = 8; rsc.SetCapability(Graphics.Capabilities.AdvancedBlendOperations); //rsc.SetCapability( Graphics.Capabilities.RTTSerperateDepthBuffer ); //rsc.SetCapability( Graphics.Capabilities.RTTMainDepthbufferAttachable ); //rsc.SetCapability( Graphics.Capabilities.RTTDepthbufferResolutionLessEqual ); //rsc.SetCapability( Graphics.Capabilities.VertexBufferInstanceData ); //rsc.SetCapability( Graphics.Capabilities.CanGetCompiledShaderBuffer ); foreach (var device in this._deviceManager) { var d3D9Device = device.D3DDevice; // Check for hardware stencil support var pSurf = d3D9Device.DepthStencilSurface; if (pSurf != null) { var surfDesc = pSurf.Description; //TODO //pSurf.Release(); if (surfDesc.Format != D3D9.Format.D15S1 && surfDesc.Format != D3D9.Format.D24S8 && surfDesc.Format != D3D9.Format.D24X4S4 && surfDesc.Format != D3D9.Format.D24SingleS8) { rsc.UnsetCapability(Graphics.Capabilities.StencilBuffer); } } // Check for hardware occlusion support try { new D3D9.Query(d3D9Device, D3D9.QueryType.Occlusion); } catch (DX.SharpDXException) { rsc.UnsetCapability(Graphics.Capabilities.HardwareOcculusion); } } // Update RS caps using the minimum value found in adapter list. foreach (var pCurDriver in this._driverList) { var rkCurCaps = pCurDriver.D3D9DeviceCaps; if (rkCurCaps.MaxSimultaneousTextures < rsc.TextureUnitCount) { rsc.TextureUnitCount = rkCurCaps.MaxSimultaneousTextures; } // Check for Anisotropy. if (rkCurCaps.MaxAnisotropy <= 1) { rsc.UnsetCapability(Graphics.Capabilities.AnisotropicFiltering); } // Check automatic mipmap generation. if ((rkCurCaps.Caps2 & D3D9.Caps2.CanAutoGenerateMipMap) == 0) { rsc.UnsetCapability(Graphics.Capabilities.HardwareMipMaps); } // Check Dot product 3. if ((rkCurCaps.TextureOperationCaps & D3D9.TextureOperationCaps.DotProduct3) == 0) { rsc.UnsetCapability(Graphics.Capabilities.Dot3); } // Check cube map support. if ((rkCurCaps.TextureCaps & D3D9.TextureCaps.CubeMap) == 0) { rsc.UnsetCapability(Graphics.Capabilities.CubeMapping); } // Scissor test if ((rkCurCaps.RasterCaps & D3D9.RasterCaps.ScissorTest) == 0) { rsc.UnsetCapability(Graphics.Capabilities.ScissorTest); } // Two-sided stencil if ((rkCurCaps.StencilCaps & D3D9.StencilCaps.TwoSided) == 0) { rsc.UnsetCapability(Graphics.Capabilities.TwoSidedStencil); } // stencil wrap if ((rkCurCaps.StencilCaps & D3D9.StencilCaps.Increment) == 0 || (rkCurCaps.StencilCaps & D3D9.StencilCaps.Decrement) == 0) { rsc.UnsetCapability(Graphics.Capabilities.StencilWrap); } // User clip planes if (rkCurCaps.MaxUserClipPlanes == 0) { rsc.UnsetCapability(Graphics.Capabilities.UserClipPlanes); } // UBYTE4 type? if ((rkCurCaps.DeclarationTypes & D3D9.DeclarationTypeCaps.UByte4) == 0) { rsc.UnsetCapability(Graphics.Capabilities.VertexFormatUByte4); } // 3D textures? if ((rkCurCaps.TextureCaps & D3D9.TextureCaps.VolumeMap) == 0) { rsc.UnsetCapability(Graphics.Capabilities.Texture3D); } if ((rkCurCaps.TextureCaps & D3D9.TextureCaps.Pow2) != 0) { // Conditional support for non POW2 if ((rkCurCaps.TextureCaps & D3D9.TextureCaps.NonPow2Conditional) != 0) { rsc.NonPOW2TexturesLimited = true; } // Only power of 2 supported. else { rsc.UnsetCapability(Graphics.Capabilities.NonPowerOf2Textures); } } // Number of render targets if (rkCurCaps.SimultaneousRTCount < rsc.MultiRenderTargetCount) { rsc.MultiRenderTargetCount = Utility.Min(rkCurCaps.SimultaneousRTCount, Config.MaxMultipleRenderTargets); } if ((rkCurCaps.PrimitiveMiscCaps & D3D9.PrimitiveMiscCaps.MrtIndependentBitDepths) == 0) { rsc.UnsetCapability(Graphics.Capabilities.MRTDifferentBitDepths); } // Point sprites if (rkCurCaps.MaxPointSize <= 1.0f) { rsc.UnsetCapability(Graphics.Capabilities.PointSprites); // sprites and extended parameters go together in D3D rsc.UnsetCapability(Graphics.Capabilities.PointExtendedParameters); } // Take the minimum point size. if (rkCurCaps.MaxPointSize < rsc.MaxPointSize) { rsc.MaxPointSize = rkCurCaps.MaxPointSize; } // Mipmap LOD biasing? if ((rkCurCaps.RasterCaps & D3D9.RasterCaps.MipMapLodBias) == 0) { rsc.UnsetCapability(Graphics.Capabilities.MipmapLODBias); } // Do we support per-stage src_manual constants? // HACK - ATI drivers seem to be buggy and don't support per-stage constants properly? // TODO: move this to RSC if ((rkCurCaps.PrimitiveMiscCaps & D3D9.PrimitiveMiscCaps.PerStageConstant) == 0) { rsc.UnsetCapability(Graphics.Capabilities.PerStageConstant); } // Advanced blend operations? min max subtract rev if ((rkCurCaps.PrimitiveMiscCaps & D3D9.PrimitiveMiscCaps.BlendOperation) == 0) { rsc.UnsetCapability(Graphics.Capabilities.AdvancedBlendOperations); } } // Blending between stages supported rsc.SetCapability(Graphics.Capabilities.Blending); // We always support compression, D3DX will decompress if device does not support rsc.SetCapability(Graphics.Capabilities.TextureCompression); rsc.SetCapability(Graphics.Capabilities.TextureCompressionDXT); // We always support VBOs rsc.SetCapability(Graphics.Capabilities.VertexBuffer); _convertVertexShaderCaps(rsc); _convertPixelShaderCaps(rsc); // Adapter details var adapterId = this._activeD3DDriver.AdapterIdentifier; // determine vendor // Full list of vendors here: http://www.pcidatabase.com/vendors.php?sort=id switch (adapterId.VendorId) { case 0x10DE: rsc.Vendor = GPUVendor.Nvidia; break; case 0x1002: rsc.Vendor = GPUVendor.Ati; break; case 0x163C: case 0x8086: rsc.Vendor = GPUVendor.Intel; break; case 0x5333: rsc.Vendor = GPUVendor.S3; break; case 0x3D3D: rsc.Vendor = GPUVendor._3DLabs; break; case 0x102B: rsc.Vendor = GPUVendor.Matrox; break; case 0x1039: rsc.Vendor = GPUVendor.Sis; break; default: rsc.Vendor = GPUVendor.Unknown; break; } // Infinite projection? // We have no capability for this, so we have to base this on our // experience and reports from users // Non-vertex program capable hardware does not appear to support it if (rsc.HasCapability(Graphics.Capabilities.VertexPrograms)) { // GeForce4 Ti (and presumably GeForce3) does not // render infinite projection properly, even though it does in GL // So exclude all cards prior to the FX range from doing infinite if (rsc.Vendor != GPUVendor.Nvidia || // not nVidia !((adapterId.DeviceId >= 0x200 && adapterId.DeviceId <= 0x20F) || //gf3 (adapterId.DeviceId >= 0x250 && adapterId.DeviceId <= 0x25F) || //gf4ti (adapterId.DeviceId >= 0x280 && adapterId.DeviceId <= 0x28F) || //gf4ti (adapterId.DeviceId >= 0x170 && adapterId.DeviceId <= 0x18F) || //gf4 go (adapterId.DeviceId >= 0x280 && adapterId.DeviceId <= 0x28F))) //gf4ti go { rsc.SetCapability(Graphics.Capabilities.InfiniteFarPlane); } } // We always support rendertextures bigger than the frame buffer rsc.SetCapability(Graphics.Capabilities.HardwareRenderToTexture); // Determine if any floating point texture format is supported var floatFormats = new[] { D3D9.Format.R16F, D3D9.Format.G16R16F, D3D9.Format.A16B16G16R16F, D3D9.Format.R32F, D3D9.Format.G32R32F, D3D9.Format.A32B32G32R32F }; var bbSurf = (D3D9.Surface[])renderWindow["DDBACKBUFFER"]; var bbSurfDesc = bbSurf[0].Description; for (var i = 0; i < 6; ++i) { if ( !this._pD3D.CheckDeviceFormat(this._activeD3DDriver.AdapterNumber, D3D9.DeviceType.Hardware, bbSurfDesc.Format, 0, D3D9.ResourceType.Texture, floatFormats[i])) { continue; } rsc.SetCapability(Graphics.Capabilities.TextureFloat); break; } // TODO: make convertVertex/Fragment fill in rsc // TODO: update the below line to use rsc // Vertex textures if (rsc.IsShaderProfileSupported("vs_3_0")) { // Run through all the texture formats looking for any which support // vertex texture fetching. Must have at least one! // All ATI Radeon up to X1n00 say they support vs_3_0, // but they support no texture formats for vertex texture fetch (cheaters!) if (_checkVertexTextureFormats(renderWindow)) { rsc.SetCapability(Graphics.Capabilities.VertexTextureFetch); // always 4 vertex texture units in vs_3_0, and never shared rsc.VertexTextureUnitCount = 4; rsc.VertexTextureUnitsShared = false; } } // Check alpha to coverage support // this varies per vendor! But at least SM3 is required if (rsc.IsShaderProfileSupported("ps_3_0")) { // NVIDIA needs a separate check switch (rsc.Vendor) { case GPUVendor.Nvidia: if (this._pD3D.CheckDeviceFormat(0, D3D9.DeviceType.Hardware, D3D9.Format.X8R8G8B8, 0, D3D9.ResourceType.Surface, (D3D9.Format)('A' | ('T') << 8 | ('O') << 16 | ('C') << 24))) { rsc.SetCapability(Graphics.Capabilities.AlphaToCoverage); } break; case GPUVendor.Ati: // There is no check on ATI, we have to assume SM3 == support rsc.SetCapability(Graphics.Capabilities.AlphaToCoverage); break; } // no other cards have Dx9 hacks for alpha to coverage, as far as I know } if (realCapabilities == null) { realCapabilities = rsc; realCapabilities.AddShaderProfile("hlsl"); // if we are using custom capabilities, then // mCurrentCapabilities has already been loaded if (!useCustomCapabilities) { currentCapabilities = realCapabilities; } InitializeFromRenderSystemCapabilities(currentCapabilities, renderWindow); } return(rsc); }
public bool Validate( D3D9RenderWindow renderWindow ) { // Validate that the render window should run on this device. if ( !ValidateDisplayMonitor( renderWindow ) ) { return false; } // Validate that this device created on the correct target focus window handle ValidateFocusWindow(); // Validate that the render window dimensions matches to back buffer dimensions. ValidateBackBufferSize( renderWindow ); // Validate that this device is in valid rendering state. return ValidateDeviceState( renderWindow ); }
public void SetAdapterOrdinalIndex( D3D9RenderWindow renderWindow, int adapterOrdinalInGroupIndex ) { var it = this._mapRenderWindowToResources[ renderWindow ]; it.AdapterOrdinalInGroupIndex = adapterOrdinalInGroupIndex; UpdateRenderWindowsIndices(); }
protected void ValidateBackBufferSize( D3D9RenderWindow renderWindow ) { var renderWindowResources = this._mapRenderWindowToResources[ renderWindow ]; // Case size has been changed. if ( renderWindow.Width != renderWindowResources.PresentParameters.BackBufferWidth || renderWindow.Height != renderWindowResources.PresentParameters.BackBufferHeight ) { if ( renderWindow.Width > 0 ) { renderWindowResources.PresentParameters.BackBufferWidth = renderWindow.Width; } if ( renderWindow.Height > 0 ) { renderWindowResources.PresentParameters.BackBufferHeight = renderWindow.Height; } Invalidate( renderWindow ); } }
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); }
private RenderSystemCapabilities _updateRenderSystemCapabilities( D3D9RenderWindow renderWindow ) { var rsc = realCapabilities ?? new RenderSystemCapabilities(); rsc.SetCategoryRelevant( CapabilitiesCategory.D3D9, true ); rsc.DriverVersion = driverVersion; rsc.DeviceName = this._activeD3DDriver.DriverDescription; rsc.RendersystemName = Name; // Supports fixed-function rsc.SetCapability( Graphics.Capabilities.FixedFunction ); // Init caps to maximum. rsc.TextureUnitCount = 1024; rsc.SetCapability( Graphics.Capabilities.AnisotropicFiltering ); rsc.SetCapability( Graphics.Capabilities.HardwareMipMaps ); rsc.SetCapability( Graphics.Capabilities.Dot3 ); rsc.SetCapability( Graphics.Capabilities.CubeMapping ); rsc.SetCapability( Graphics.Capabilities.ScissorTest ); rsc.SetCapability( Graphics.Capabilities.TwoSidedStencil ); rsc.SetCapability( Graphics.Capabilities.StencilWrap ); rsc.SetCapability( Graphics.Capabilities.HardwareOcculusion ); rsc.SetCapability( Graphics.Capabilities.UserClipPlanes ); rsc.SetCapability( Graphics.Capabilities.VertexFormatUByte4 ); rsc.SetCapability( Graphics.Capabilities.Texture3D ); rsc.SetCapability( Graphics.Capabilities.NonPowerOf2Textures ); rsc.NonPOW2TexturesLimited = false; rsc.MultiRenderTargetCount = Config.MaxMultipleRenderTargets; rsc.SetCapability( Graphics.Capabilities.MRTDifferentBitDepths ); rsc.SetCapability( Graphics.Capabilities.PointSprites ); rsc.SetCapability( Graphics.Capabilities.PointExtendedParameters ); rsc.MaxPointSize = 10.0f; rsc.SetCapability( Graphics.Capabilities.MipmapLODBias ); rsc.SetCapability( Graphics.Capabilities.PerStageConstant ); rsc.SetCapability( Graphics.Capabilities.StencilBuffer ); rsc.StencilBufferBitCount = 8; rsc.SetCapability( Graphics.Capabilities.AdvancedBlendOperations ); //rsc.SetCapability( Graphics.Capabilities.RTTSerperateDepthBuffer ); //rsc.SetCapability( Graphics.Capabilities.RTTMainDepthbufferAttachable ); //rsc.SetCapability( Graphics.Capabilities.RTTDepthbufferResolutionLessEqual ); //rsc.SetCapability( Graphics.Capabilities.VertexBufferInstanceData ); //rsc.SetCapability( Graphics.Capabilities.CanGetCompiledShaderBuffer ); foreach ( var device in this._deviceManager ) { var d3D9Device = device.D3DDevice; // Check for hardware stencil support var pSurf = d3D9Device.DepthStencilSurface; if ( pSurf != null ) { var surfDesc = pSurf.Description; //TODO //pSurf.Release(); if ( surfDesc.Format != D3D9.Format.D15S1 && surfDesc.Format != D3D9.Format.D24S8 && surfDesc.Format != D3D9.Format.D24X4S4 && surfDesc.Format != D3D9.Format.D24SingleS8 ) { rsc.UnsetCapability( Graphics.Capabilities.StencilBuffer ); } } // Check for hardware occlusion support try { new D3D9.Query( d3D9Device, D3D9.QueryType.Occlusion ); } catch ( DX.SharpDXException ) { rsc.UnsetCapability( Graphics.Capabilities.HardwareOcculusion ); } } // Update RS caps using the minimum value found in adapter list. foreach ( var pCurDriver in this._driverList ) { var rkCurCaps = pCurDriver.D3D9DeviceCaps; if ( rkCurCaps.MaxSimultaneousTextures < rsc.TextureUnitCount ) { rsc.TextureUnitCount = rkCurCaps.MaxSimultaneousTextures; } // Check for Anisotropy. if ( rkCurCaps.MaxAnisotropy <= 1 ) { rsc.UnsetCapability( Graphics.Capabilities.AnisotropicFiltering ); } // Check automatic mipmap generation. if ( ( rkCurCaps.Caps2 & D3D9.Caps2.CanAutoGenerateMipMap ) == 0 ) { rsc.UnsetCapability( Graphics.Capabilities.HardwareMipMaps ); } // Check Dot product 3. if ( ( rkCurCaps.TextureOperationCaps & D3D9.TextureOperationCaps.DotProduct3 ) == 0 ) { rsc.UnsetCapability( Graphics.Capabilities.Dot3 ); } // Check cube map support. if ( ( rkCurCaps.TextureCaps & D3D9.TextureCaps.CubeMap ) == 0 ) { rsc.UnsetCapability( Graphics.Capabilities.CubeMapping ); } // Scissor test if ( ( rkCurCaps.RasterCaps & D3D9.RasterCaps.ScissorTest ) == 0 ) { rsc.UnsetCapability( Graphics.Capabilities.ScissorTest ); } // Two-sided stencil if ( ( rkCurCaps.StencilCaps & D3D9.StencilCaps.TwoSided ) == 0 ) { rsc.UnsetCapability( Graphics.Capabilities.TwoSidedStencil ); } // stencil wrap if ( ( rkCurCaps.StencilCaps & D3D9.StencilCaps.Increment ) == 0 || ( rkCurCaps.StencilCaps & D3D9.StencilCaps.Decrement ) == 0 ) { rsc.UnsetCapability( Graphics.Capabilities.StencilWrap ); } // User clip planes if ( rkCurCaps.MaxUserClipPlanes == 0 ) { rsc.UnsetCapability( Graphics.Capabilities.UserClipPlanes ); } // UBYTE4 type? if ( ( rkCurCaps.DeclarationTypes & D3D9.DeclarationTypeCaps.UByte4 ) == 0 ) { rsc.UnsetCapability( Graphics.Capabilities.VertexFormatUByte4 ); } // 3D textures? if ( ( rkCurCaps.TextureCaps & D3D9.TextureCaps.VolumeMap ) == 0 ) { rsc.UnsetCapability( Graphics.Capabilities.Texture3D ); } if ( ( rkCurCaps.TextureCaps & D3D9.TextureCaps.Pow2 ) != 0 ) { // Conditional support for non POW2 if ( ( rkCurCaps.TextureCaps & D3D9.TextureCaps.NonPow2Conditional ) != 0 ) { rsc.NonPOW2TexturesLimited = true; } // Only power of 2 supported. else { rsc.UnsetCapability( Graphics.Capabilities.NonPowerOf2Textures ); } } // Number of render targets if ( rkCurCaps.SimultaneousRTCount < rsc.MultiRenderTargetCount ) { rsc.MultiRenderTargetCount = Utility.Min( rkCurCaps.SimultaneousRTCount, Config.MaxMultipleRenderTargets ); } if ( ( rkCurCaps.PrimitiveMiscCaps & D3D9.PrimitiveMiscCaps.MrtIndependentBitDepths ) == 0 ) { rsc.UnsetCapability( Graphics.Capabilities.MRTDifferentBitDepths ); } // Point sprites if ( rkCurCaps.MaxPointSize <= 1.0f ) { rsc.UnsetCapability( Graphics.Capabilities.PointSprites ); // sprites and extended parameters go together in D3D rsc.UnsetCapability( Graphics.Capabilities.PointExtendedParameters ); } // Take the minimum point size. if ( rkCurCaps.MaxPointSize < rsc.MaxPointSize ) { rsc.MaxPointSize = rkCurCaps.MaxPointSize; } // Mipmap LOD biasing? if ( ( rkCurCaps.RasterCaps & D3D9.RasterCaps.MipMapLodBias ) == 0 ) { rsc.UnsetCapability( Graphics.Capabilities.MipmapLODBias ); } // Do we support per-stage src_manual constants? // HACK - ATI drivers seem to be buggy and don't support per-stage constants properly? // TODO: move this to RSC if ( ( rkCurCaps.PrimitiveMiscCaps & D3D9.PrimitiveMiscCaps.PerStageConstant ) == 0 ) { rsc.UnsetCapability( Graphics.Capabilities.PerStageConstant ); } // Advanced blend operations? min max subtract rev if ( ( rkCurCaps.PrimitiveMiscCaps & D3D9.PrimitiveMiscCaps.BlendOperation ) == 0 ) { rsc.UnsetCapability( Graphics.Capabilities.AdvancedBlendOperations ); } } // Blending between stages supported rsc.SetCapability( Graphics.Capabilities.Blending ); // We always support compression, D3DX will decompress if device does not support rsc.SetCapability( Graphics.Capabilities.TextureCompression ); rsc.SetCapability( Graphics.Capabilities.TextureCompressionDXT ); // We always support VBOs rsc.SetCapability( Graphics.Capabilities.VertexBuffer ); _convertVertexShaderCaps( rsc ); _convertPixelShaderCaps( rsc ); // Adapter details var adapterId = this._activeD3DDriver.AdapterIdentifier; // determine vendor // Full list of vendors here: http://www.pcidatabase.com/vendors.php?sort=id switch ( adapterId.VendorId ) { case 0x10DE: rsc.Vendor = GPUVendor.Nvidia; break; case 0x1002: rsc.Vendor = GPUVendor.Ati; break; case 0x163C: case 0x8086: rsc.Vendor = GPUVendor.Intel; break; case 0x5333: rsc.Vendor = GPUVendor.S3; break; case 0x3D3D: rsc.Vendor = GPUVendor._3DLabs; break; case 0x102B: rsc.Vendor = GPUVendor.Matrox; break; case 0x1039: rsc.Vendor = GPUVendor.Sis; break; default: rsc.Vendor = GPUVendor.Unknown; break; } // Infinite projection? // We have no capability for this, so we have to base this on our // experience and reports from users // Non-vertex program capable hardware does not appear to support it if ( rsc.HasCapability( Graphics.Capabilities.VertexPrograms ) ) { // GeForce4 Ti (and presumably GeForce3) does not // render infinite projection properly, even though it does in GL // So exclude all cards prior to the FX range from doing infinite if ( rsc.Vendor != GPUVendor.Nvidia || // not nVidia !( ( adapterId.DeviceId >= 0x200 && adapterId.DeviceId <= 0x20F ) || //gf3 ( adapterId.DeviceId >= 0x250 && adapterId.DeviceId <= 0x25F ) || //gf4ti ( adapterId.DeviceId >= 0x280 && adapterId.DeviceId <= 0x28F ) || //gf4ti ( adapterId.DeviceId >= 0x170 && adapterId.DeviceId <= 0x18F ) || //gf4 go ( adapterId.DeviceId >= 0x280 && adapterId.DeviceId <= 0x28F ) ) ) //gf4ti go { rsc.SetCapability( Graphics.Capabilities.InfiniteFarPlane ); } } // We always support rendertextures bigger than the frame buffer rsc.SetCapability( Graphics.Capabilities.HardwareRenderToTexture ); // Determine if any floating point texture format is supported var floatFormats = new[] { D3D9.Format.R16F, D3D9.Format.G16R16F, D3D9.Format.A16B16G16R16F, D3D9.Format.R32F, D3D9.Format.G32R32F, D3D9.Format.A32B32G32R32F }; var bbSurf = (D3D9.Surface[])renderWindow[ "DDBACKBUFFER" ]; var bbSurfDesc = bbSurf[ 0 ].Description; for ( var i = 0; i < 6; ++i ) { if ( !this._pD3D.CheckDeviceFormat( this._activeD3DDriver.AdapterNumber, D3D9.DeviceType.Hardware, bbSurfDesc.Format, 0, D3D9.ResourceType.Texture, floatFormats[ i ] ) ) { continue; } rsc.SetCapability( Graphics.Capabilities.TextureFloat ); break; } // TODO: make convertVertex/Fragment fill in rsc // TODO: update the below line to use rsc // Vertex textures if ( rsc.IsShaderProfileSupported( "vs_3_0" ) ) { // Run through all the texture formats looking for any which support // vertex texture fetching. Must have at least one! // All ATI Radeon up to X1n00 say they support vs_3_0, // but they support no texture formats for vertex texture fetch (cheaters!) if ( _checkVertexTextureFormats( renderWindow ) ) { rsc.SetCapability( Graphics.Capabilities.VertexTextureFetch ); // always 4 vertex texture units in vs_3_0, and never shared rsc.VertexTextureUnitCount = 4; rsc.VertexTextureUnitsShared = false; } } // Check alpha to coverage support // this varies per vendor! But at least SM3 is required if ( rsc.IsShaderProfileSupported( "ps_3_0" ) ) { // NVIDIA needs a separate check switch ( rsc.Vendor ) { case GPUVendor.Nvidia: if ( this._pD3D.CheckDeviceFormat( 0, D3D9.DeviceType.Hardware, D3D9.Format.X8R8G8B8, 0, D3D9.ResourceType.Surface, (D3D9.Format)( 'A' | ( 'T' ) << 8 | ( 'O' ) << 16 | ( 'C' ) << 24 ) ) ) { rsc.SetCapability( Graphics.Capabilities.AlphaToCoverage ); } break; case GPUVendor.Ati: // There is no check on ATI, we have to assume SM3 == support rsc.SetCapability( Graphics.Capabilities.AlphaToCoverage ); break; } // no other cards have Dx9 hacks for alpha to coverage, as far as I know } if ( realCapabilities == null ) { realCapabilities = rsc; realCapabilities.AddShaderProfile( "hlsl" ); // if we are using custom capabilities, then // mCurrentCapabilities has already been loaded if ( !useCustomCapabilities ) { currentCapabilities = realCapabilities; } InitializeFromRenderSystemCapabilities( currentCapabilities, renderWindow ); } return rsc; }
private bool _checkVertexTextureFormats( D3D9RenderWindow renderWindow ) { var anySupported = false; var bbSurf = (D3D9.Surface[])renderWindow[ "DDBACKBUFFER" ]; var bbSurfDesc = bbSurf[ 0 ].Description; for ( var pf = PixelFormat.L8; pf < PixelFormat.Count; ++pf ) { var fmt = D3D9Helper.ConvertEnum( D3D9Helper.GetClosestSupported( pf ) ); if ( !this._pD3D.CheckDeviceFormat( this._activeD3DDriver.AdapterNumber, D3D9.DeviceType.Hardware, bbSurfDesc.Format, D3D9.Usage.QueryVertexTexture, D3D9.ResourceType.Texture, fmt ) ) { continue; } // cool, at least one supported anySupported = true; LogManager.Instance.Write( "D3D9: Vertex texture format supported - {0}", PixelUtil.GetFormatName( pf ) ); } return anySupported; }
protected bool Acquire( D3D9RenderWindow renderWindow ) { var it = GetRenderWindowIterator( renderWindow ); AcquireRenderWindowResources( it ); return true; }
public D3D9.Surface GetBackBuffer( D3D9RenderWindow renderWindow ) { var it = this._mapRenderWindowToResources[ renderWindow ]; return it.BackBuffer; }
protected bool ValidateDisplayMonitor( D3D9RenderWindow renderWindow ) { // Ignore full screen since it doesn't really move and it is possible // that it created using multi-head adapter so for a subordinate the // native monitor handle and this device handle will be different. if ( renderWindow.IsFullScreen ) { return true; } // Find the monitor this render window belongs to. // Note: In Ogre, there was MONITOR_DEFAULTTONULL as flag of the MonitorFromWindow method, // while Screen.FromHandle method always use MONITOR_DEFAULTTONEAREST flag. var hRenderWindowMonitor = ScreenHelper.GetHandle( renderWindow.WindowHandle ); // This window doesn't intersect with any of the display monitor if ( hRenderWindowMonitor == IntPtr.Zero ) { return false; } // Case this window changed monitor. if ( hRenderWindowMonitor != this._monitor ) { // Lock access to rendering device. D3D9RenderSystem.ResourceManager.LockDeviceAccess(); this.pDeviceManager.LinkRenderWindow( renderWindow ); // UnLock access to rendering device. D3D9RenderSystem.ResourceManager.UnlockDeviceAccess(); return false; } return true; }
public void Invalidate( D3D9RenderWindow renderWindow ) { this._mapRenderWindowToResources[ renderWindow ].Acquired = false; }
public void Present( D3D9RenderWindow renderWindow ) { var renderWindowResources = this._mapRenderWindowToResources[ renderWindow ]; // Skip present while current device state is invalid. if ( this.DeviceLost || renderWindowResources.Acquired == false || IsDeviceLost ) { return; } try { if ( IsMultihead ) { // Only the master will call present method results in synchronized // buffer swap for the rest of the implicit swap chain. if ( PrimaryWindow == renderWindow ) { this.pDevice.Present(); } } else { renderWindowResources.SwapChain.Present( 0 ); } LastPresentFrame = Root.Instance.NextFrameNumber; } catch ( DX.SharpDXException ex ) { if ( ex.ResultCode == D3D9.ResultCode.DeviceLost ) { ReleaseRenderWindowResources( renderWindowResources ); NotifyDeviceLost(); } else { throw new AxiomException( "Error Presenting surfaces", ex ); } } }
protected bool ValidateDeviceState( D3D9RenderWindow renderWindow ) { var renderWindowResources = this._mapRenderWindowToResources[ renderWindow ]; var hr = this.pDevice.TestCooperativeLevel(); // Case device is not valid for rendering. if ( hr.Failure ) { // device lost, and we can't reset // can't do anything about it here, wait until we get // D3DERR_DEVICENOTRESET; rendering calls will silently fail until // then (except Present, but we ignore device lost there too) if ( hr == D3D9.ResultCode.DeviceLost ) { ReleaseRenderWindowResources( renderWindowResources ); NotifyDeviceLost(); return false; } // device lost, and we can reset /*else*/ if ( hr == D3D9.ResultCode.DeviceNotReset ) { var deviceRestored = Reset(); // Device was not restored yet. if ( deviceRestored == false ) { // Wait a while Thread.Sleep( 50 ); return false; } } } // Render window resources explicitly invalidated. (Resize or window mode switch) if ( renderWindowResources.Acquired == false ) { if ( PrimaryWindow == renderWindow ) { var deviceRestored = Reset(); // Device was not restored yet. if ( deviceRestored == false ) { // Wait a while Thread.Sleep( 50 ); return false; } } else { Acquire( renderWindow ); } } return true; }
protected bool IsSwapChainWindow( D3D9RenderWindow renderWindow ) { var it = this._mapRenderWindowToResources[ renderWindow ]; return it.PresentParametersIndex != 0 && !renderWindow.IsFullScreen; }