The Direct3D implementation of the RenderWindow class.
Inheritance: Axiom.Graphics.RenderWindow
Exemplo n.º 1
0
        public override RenderWindow CreateRenderWindow( string name, int width, int height, bool isFullScreen, NamedParameterList miscParams )
        {
            LogManager.Instance.Write("D3D9RenderSystem::createRenderWindow \"{0}\", {1}x{2} {3} ",
                                       name, width, height, isFullScreen ? "fullscreen" : "windowed");

            LogManager.Instance.Write( "miscParams: {0}",
                                       miscParams.Aggregate( new StringBuilder(),
                                                             ( s, kv ) =>
                                                             s.AppendFormat( "{0} = {1};", kv.Key, kv.Value ).AppendLine()
                                           ).ToString()
                );

            // Make sure we don't already have a render target of the
            // same name as the one supplied
            if (renderTargets.ContainsKey(name))
            {
                throw new Exception(String.Format("A render target of the same name '{0}' already exists." +
                                     "You cannot create a new window with this name.", name));
            }

            var window = new D3DRenderWindow(_activeD3DDriver, null);

            window.Create(name, width, height, isFullScreen, miscParams);

            _resourceManager.LockDeviceAccess();

            _deviceManager.LinkRenderWindow( window );

            _resourceManager.UnlockDeviceAccess();

            _renderWindows.Add( window );

            UpdateRenderSystemCapabilities( window );

            AttachRenderTarget( window );

            return window;
        }
        private bool CheckVertexTextureFormats(D3DRenderWindow renderWindow)
        {
            var anySupported = false;

            var bbSurf = (Surface[])renderWindow[ "DDBACKBUFFER" ];
            var bbSurfDesc = bbSurf[0].Description;

            for (var pf = PixelFormat.L8; pf < PixelFormat.Count; pf++)
            {
                var fmt = D3DHelper.ConvertEnum( pf );
                if ( !_pD3D.CheckDeviceFormat( _activeD3DDriver.AdapterNumber, DeviceType.Hardware, bbSurfDesc.Format,
                                               Usage.QueryVertexTexture, 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 override void DestroyRenderTarget(string name)
        {
            // Check in specialised lists
            if (primaryWindow.Name == name) {
                // We're destroying the primary window, so reset device and window
                primaryWindow = null;
            } else {
                // Check secondary windows
                foreach (RenderWindow window in secondaryWindows) {
                    if (window.Name == name) {
                        secondaryWindows.Remove(window);
                        break;
                    }
                }
            }

            // Do the real removal
            base.DestroyRenderTarget(name);

            // Did we destroy the primary?
            if (primaryWindow == null) {
                // device is no longer valid, so free it all up
                FreeDevice();
            }
        }
        private RenderSystemCapabilities UpdateRenderSystemCapabilities(D3DRenderWindow renderWindow)
        {
            var rsc = realCapabilities ?? new RenderSystemCapabilities();

            rsc.SetCategoryRelevant(CapabilitiesCategory.D3D9, true);
            rsc.DriverVersion = driverVersion;
            rsc.DeviceName = _activeD3DDriver.DriverDescription;
            rsc.RendersystemName = Name;

            // 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 = 2.19902e+012f;
            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 dev in _deviceManager)
            {
                var d3D9Device = dev.D3DDevice;

                // Check for hardware stencil support
                var pSurf = d3D9Device.DepthStencilSurface;
                if (pSurf != null)
                {
                    var surfDesc = pSurf.Description;

                    if (surfDesc.Format != Format.D15S1 &&
                        surfDesc.Format != Format.D24S8 &&
                        surfDesc.Format != Format.D24X4S4 &&
                        surfDesc.Format != Format.D24SingleS8)
                        rsc.UnsetCapability( Graphics.Capabilities.StencilBuffer );
                }

                // Check for hardware occlusion support
                //HRESULT hr = d3d9Device->CreateQuery(D3DQUERYTYPE_OCCLUSION, NULL);
                try
                {
                    new Query(d3D9Device, QueryType.Occlusion);
                }
                catch (Direct3D9Exception)
                {
                    rsc.UnsetCapability( Graphics.Capabilities.HardwareOcculusion );
                }
            }

            // Update RS caps using the minimum value found in adapter list.
            foreach (var pCurDriver in _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 & Caps2.CanAutoGenerateMipMap) == 0)
                    rsc.UnsetCapability( Graphics.Capabilities.HardwareMipMaps );

                // Check Dot product 3.
                if ((rkCurCaps.TextureOperationCaps & TextureOperationCaps.DotProduct3) == 0)
                    rsc.UnsetCapability( Graphics.Capabilities.Dot3 );

                // Check cube map support.
                if ((rkCurCaps.TextureCaps & TextureCaps.CubeMap) == 0)
                    rsc.UnsetCapability(Graphics.Capabilities.CubeMapping);
            
                // Scissor test
                if ((rkCurCaps.RasterCaps & RasterCaps.ScissorTest) == 0)
                    rsc.UnsetCapability(Graphics.Capabilities.ScissorTest);


                // Two-sided stencil
                if ((rkCurCaps.StencilCaps & StencilCaps.TwoSided) == 0)
                    rsc.UnsetCapability(Graphics.Capabilities.TwoSidedStencil);

                // stencil wrap
                if ((rkCurCaps.StencilCaps & StencilCaps.Increment) == 0 ||
                    (rkCurCaps.StencilCaps & 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 & DeclarationTypeCaps.UByte4) == 0)            
                    rsc.UnsetCapability(Graphics.Capabilities.VertexFormatUByte4);    

                // 3D textures?
                if ((rkCurCaps.TextureCaps & TextureCaps.VolumeMap) == 0)            
                    rsc.UnsetCapability(Graphics.Capabilities.Texture3D);            

                if ((rkCurCaps.TextureCaps & TextureCaps.Pow2) != 0)
                {
                    // Conditional support for non POW2
                    if ((rkCurCaps.TextureCaps & 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 & 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 & 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 & PrimitiveMiscCaps.PerStageConstant) == 0)
                    rsc.UnsetCapability(Graphics.Capabilities.PerStageConstant);

                // Advanced blend operations? min max subtract rev 
                if ((rkCurCaps.PrimitiveMiscCaps & 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 = _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[] {Format.R16F, Format.G16R16F, 
                Format.A16B16G16R16F, Format.R32F, Format.G32R32F, 
                Format.A32B32G32R32F};
            

            var bbSurf = (Surface[])renderWindow[ "DDBACKBUFFER" ];
            var bbSurfDesc = bbSurf[0].Description;

            for (var i = 0; i < 6; ++i)
            {
                if (!_pD3D.CheckDeviceFormat(_activeD3DDriver.AdapterNumber,
                    DeviceType.Hardware, bbSurfDesc.Format, 0, 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.TextureUnitCount = 4;
                    rsc.VertexTextureUnitsShared = false;
                }
            }    
            else
            {
                //True HW Instancing is supported since Shader model 3.0 ATI has a nasty
                //hack for enabling it in their SM 2.0 cards, but we don't (and won't) support it
                rsc.UnsetCapability( Graphics.Capabilities.VertexBufferInstanceData );
            }

            // 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 (_pD3D.CheckDeviceFormat(0, DeviceType.Hardware, Format.X8R8G8B8, 0, ResourceType.Surface,
                                                    (Format)( 'A' | ( 'T' ) << 8 | ( 'O' ) << 16 | ( 'C' ) << 24 ) ))
                        {
                            rsc.SetCapability( Graphics.Capabilities.AlphaToCoverage );
                        }
                        break;
                    case GPUVendor.Ati:
                        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;

                FireEvent("RenderSystemCapabilitiesCreated");

                InitializeFromRenderSystemCapabilities(currentCapabilities, renderWindow);
            }

            return rsc;
        }
        public override RenderWindow CreateRenderWindow(string name, int width, int height, bool isFullscreen, params object[] miscParams)
        {
            // Check we're not creating a secondary window when the primary
            // was fullscreen
            if (primaryWindow != null && primaryWindow.IsFullScreen) {
                throw new Exception("Cannot create secondary windows when the primary is full screen");
            } else if (primaryWindow != null && isFullscreen) {
                throw new Exception("Cannot create full screen secondary windows");
            }

            // Make sure we don't already have a render target of the
            // same name as the one supplied
            foreach (RenderTarget x in renderTargets) {
                if (x.Name == name)
                    throw new Exception("A render target of the same name '" + name +
                                        "' already exists.  You cannot create a new window with this name.");
            }

            RenderWindow win = new D3DRenderWindow(activeD3DDriver, primaryWindow != null);
            // create the window
            win.Create(name, width, height, isFullscreen, miscParams);
            // add the new render target
            AttachRenderTarget(win);

            // If this is the first window, get the D3D device and create the texture manager
            if (primaryWindow == null) {
                primaryWindow = (D3DRenderWindow)win;
                device = (Device)win.GetCustomAttribute("D3DDEVICE");

                // by creating our texture manager, singleton TextureManager will hold our implementation
                textureManager = new D3DTextureManager(device);

                // by creating our Gpu program manager, singleton GpuProgramManager will hold our implementation
                gpuProgramMgr = new D3DGpuProgramManager(device);

                // intializes the HardwareBufferManager singleton
                hardwareBufferManager = new D3DHardwareBufferManager(device);

                // Initialise the capabilities structures
                InitCapabilities();

                CreateAndApplyCache();
            } else {
                secondaryWindows.Add(win);
            }
            return win;
        }