/// <summary> /// Sets targets. /// </summary> /// <param name="renderTargets"></param> public void SetTargets(DepthStencilSurface depthStencil, params RenderTargetSurface[] renderTargets) { int w = -1; int h = -1; if (renderTargets.Length > 8) { throw new ArgumentException("Could not bind more than 8 render targets"); } lock (deviceContext) { this.depthStencilSurface = depthStencil; renderTargets.CopyTo(renderTargetSurfaces, 0); if (depthStencil != null) { w = depthStencil.Width; h = depthStencil.Height; } if (renderTargets.Any()) { if (w == -1 || h == -1) { w = renderTargets.First().Width; h = renderTargets.First().Height; } if (!renderTargets.All(surf => surf.Width == w && surf.Height == h)) { throw new ArgumentException("All surfaces must be the same size", "renderTargets"); } } DepthStencilView dsv = depthStencil == null ? null : depthStencil.DSV; RenderTargetView[] rtvs = renderTargets.Select(rt => rt.RTV).ToArray(); if (!rtvs.Any()) { deviceContext.OutputMerger.SetTargets(dsv, (RenderTargetView)null); } else { deviceContext.OutputMerger.SetTargets(dsv, rtvs); } if (w > 0 && h > 0) { SetViewport(0, 0, w, h); } } }
/// <summary> /// Creates render target /// </summary> /// <param name="rs"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="format"></param> public DepthStencilCube ( GraphicsDevice device, DepthFormat format, int size, int samples, string debugName = "" ) : base ( device ) { bool msaa = samples > 1; CheckSamplesCount( samples ); SampleCount = samples; Format = format; SampleCount = samples; Width = size; Height = size; Depth = 1; var texDesc = new Texture2DDescription(); texDesc.Width = Width; texDesc.Height = Height; texDesc.ArraySize = 6; texDesc.BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource; texDesc.CpuAccessFlags = CpuAccessFlags.None; texDesc.Format = Converter.ConvertToTex( format ); texDesc.MipLevels = 1; texDesc.OptionFlags = ResourceOptionFlags.TextureCube; texDesc.SampleDescription = new DXGI.SampleDescription(samples, 0); texDesc.Usage = ResourceUsage.Default; texCube = new D3D.Texture2D( device.Device, texDesc ); var srvDesc = new ShaderResourceViewDescription(); srvDesc.Dimension = samples > 1 ? ShaderResourceViewDimension.Texture2DMultisampled : ShaderResourceViewDimension.Texture2D; srvDesc.Format = Converter.ConvertToSRV( format ); srvDesc.Texture2D.MostDetailedMip = 0; srvDesc.Texture2D.MipLevels = 1; SRV = new ShaderResourceView( device.Device, texCube ); // // Create surfaces : // surfaces = new DepthStencilSurface[ 6 ]; for ( int face=0; face<6; face++) { var rtvDesc = new DepthStencilViewDescription(); rtvDesc.Texture2DArray.MipSlice = 0; rtvDesc.Texture2DArray.FirstArraySlice = face; rtvDesc.Texture2DArray.ArraySize = 1; rtvDesc.Dimension = msaa ? DepthStencilViewDimension.Texture2DMultisampledArray : DepthStencilViewDimension.Texture2DArray; rtvDesc.Format = Converter.ConvertToDSV( format ); var dsv = new DepthStencilView( device.Device, texCube, rtvDesc ); int subResId = Resource.CalculateSubResourceIndex( 0, face, 1 ); surfaces[face] = new DepthStencilSurface( dsv, format, Width, Height, SampleCount ); } }
/// <summary> /// Clear depth stencil surface /// </summary> /// <param name="surface"></param> /// <param name="depth"></param> /// <param name="stencil"></param> public void Clear ( DepthStencilSurface surface, float depth = 1, byte stencil = 0 ) { lock (deviceContext) { deviceContext.ClearDepthStencilView( surface.DSV, DepthStencilClearFlags.Depth|DepthStencilClearFlags.Stencil, depth, stencil ); } }
/// <summary> /// /// </summary> /// <param name="depthStencil"></param> /// <param name="renderTargets"></param> public void GetTargets ( out DepthStencilSurface depthStencil, out RenderTargetSurface[] renderTargets ) { depthStencil = depthStencilSurface; renderTargets = renderTargetSurfaces.ToArray(); }
/// <summary> /// Sets targets. /// </summary> /// <param name="renderTargets"></param> public void SetTargets ( DepthStencilSurface depthStencil, params RenderTargetSurface[] renderTargets ) { int w = -1; int h = -1; if (renderTargets.Length>8) { throw new ArgumentException("Could not bind more than 8 render targets"); } lock (deviceContext) { this.depthStencilSurface = depthStencil; renderTargets.CopyTo( renderTargetSurfaces, 0 ); if (depthStencil!=null) { w = depthStencil.Width; h = depthStencil.Height; } if (renderTargets.Any()) { if (w==-1 || h==-1) { w = renderTargets.First().Width; h = renderTargets.First().Height; } if ( !renderTargets.All( surf => surf.Width == w && surf.Height == h ) ) { throw new ArgumentException("All surfaces must be the same size", "renderTargets"); } } DepthStencilView dsv = depthStencil == null ? null : depthStencil.DSV; RenderTargetView[] rtvs = renderTargets.Select( rt => rt.RTV ).ToArray(); if (!rtvs.Any()) { deviceContext.OutputMerger.SetTargets( dsv, (RenderTargetView)null ); } else { deviceContext.OutputMerger.SetTargets( dsv, rtvs ); } if (w>0 && h>0) { SetViewport( 0, 0, w, h ); } } }
/// <summary> /// /// </summary> /// <param name="gameTime"></param> internal void RenderShadow ( GameTime gameTime, Viewport viewport, Matrix view, Matrix projection, RenderTargetSurface particleShadow, DepthStencilSurface depthBuffer ) { var colorTarget = particleShadow; var depthTarget = depthBuffer; RenderGeneric( "Particles Shadow", gameTime, null, viewport, view, projection, colorTarget, depthTarget, null, Flags.DRAW_SHADOW ); }
/// <summary> /// /// </summary> void RenderGeneric ( string passName, GameTime gameTime, Camera camera, Viewport viewport, Matrix view, Matrix projection, RenderTargetSurface colorTarget, DepthStencilSurface depthTarget, ShaderResource depthValues, Flags flags ) { var device = Game.GraphicsDevice; if (rs.SkipParticles) { return; } using ( new PixEvent(passName) ) { device.ResetStates(); // // Setup images : // if (Images!=null && !Images.IsDisposed) { imagesCB.SetData( Images.GetNormalizedRectangles( MaxImages ) ); } SetupGPUParameters( 0, renderWorld, view, projection, flags ); device.ComputeShaderConstants[0] = paramsCB ; // // Render // using (new PixEvent("Drawing")) { device.ResetStates(); // target and viewport : device.SetTargets( depthTarget, colorTarget ); device.SetViewport( viewport ); // params CB : device.ComputeShaderConstants[0] = paramsCB ; device.VertexShaderConstants[0] = paramsCB ; device.GeometryShaderConstants[0] = paramsCB ; device.PixelShaderConstants[0] = paramsCB ; // atlas CB : device.VertexShaderConstants[1] = imagesCB ; device.GeometryShaderConstants[1] = imagesCB ; device.PixelShaderConstants[1] = imagesCB ; // sampler & textures : device.PixelShaderSamplers[0] = SamplerState.LinearClamp4Mips ; device.PixelShaderResources[0] = Images==null? rs.WhiteTexture.Srv : Images.Texture.Srv; device.PixelShaderResources[5] = depthValues; device.GeometryShaderResources[1] = simulationBuffer ; device.GeometryShaderResources[2] = simulationBuffer ; device.GeometryShaderResources[3] = sortParticlesBuffer; device.GeometryShaderResources[4] = particleLighting; // setup PS : device.PipelineState = factory[ (int)flags ]; // GPU time : 0.81 ms -> 0.91 ms device.Draw( MaxSimulatedParticles, 0 ); } } }
/// <summary> /// Creates depth stencil texture, view and shader resource with format D24S8 /// </summary> /// <param name="rs"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="format"></param> public DepthStencil2D(GraphicsDevice device, DepthFormat format, int width, int height, int samples = 1) : base(device) { Log.Debug("DepthStencil2D: f:{0} w:{1} h:{2} s:{3}", format, width, height, samples); CheckSamplesCount(samples); Width = width; Height = height; Depth = 1; Format = format; SampleCount = samples; var bindFlags = BindFlags.DepthStencil; if (device.GraphicsProfile == GraphicsProfile.HiDef) { bindFlags |= BindFlags.ShaderResource; } else if (device.GraphicsProfile == GraphicsProfile.Reach) { if (samples == 1) { bindFlags |= BindFlags.ShaderResource; } } var texDesc = new Texture2DDescription(); texDesc.Width = width; texDesc.Height = height; texDesc.ArraySize = 1; texDesc.BindFlags = bindFlags; texDesc.CpuAccessFlags = CpuAccessFlags.None; texDesc.Format = Converter.ConvertToTex(format); texDesc.MipLevels = 1; texDesc.OptionFlags = ResourceOptionFlags.None; texDesc.SampleDescription = new DXGI.SampleDescription(samples, 0); texDesc.Usage = ResourceUsage.Default; var dsvDesc = new DepthStencilViewDescription(); dsvDesc.Dimension = samples > 1 ? DepthStencilViewDimension.Texture2DMultisampled : DepthStencilViewDimension.Texture2D; dsvDesc.Format = Converter.ConvertToDSV(format); dsvDesc.Flags = DepthStencilViewFlags.None; var srvDesc = new ShaderResourceViewDescription(); srvDesc.Dimension = samples > 1 ? ShaderResourceViewDimension.Texture2DMultisampled : ShaderResourceViewDimension.Texture2D; srvDesc.Format = Converter.ConvertToSRV(format); srvDesc.Texture2D.MostDetailedMip = 0; srvDesc.Texture2D.MipLevels = 1; tex2D = new D3D.Texture2D(device.Device, texDesc); var dsv = new DepthStencilView(device.Device, tex2D, dsvDesc); if (bindFlags.HasFlag(BindFlags.ShaderResource)) { SRV = new ShaderResourceView(device.Device, tex2D, srvDesc); } surface = new DepthStencilSurface(dsv, format, width, height, samples); }
/// <summary> /// Clear depth stencil surface /// </summary> /// <param name="surface"></param> /// <param name="depth"></param> /// <param name="stencil"></param> public void Clear(DepthStencilSurface surface, float depth = 1, byte stencil = 0) { lock (deviceContext) { deviceContext.ClearDepthStencilView(surface.DSV, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, depth, stencil); } }
/// <summary> /// /// </summary> /// <param name="depthStencil"></param> /// <param name="renderTargets"></param> public void GetTargets(out DepthStencilSurface depthStencil, out RenderTargetSurface[] renderTargets) { depthStencil = depthStencilSurface; renderTargets = renderTargetSurfaces.ToArray(); }
/// <summary> /// Creates render target /// </summary> /// <param name="rs"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="format"></param> public DepthStencilCube(GraphicsDevice device, DepthFormat format, int size, int samples, string debugName = "") : base(device) { bool msaa = samples > 1; CheckSamplesCount(samples); SampleCount = samples; Format = format; SampleCount = samples; Width = size; Height = size; Depth = 1; var texDesc = new Texture2DDescription(); texDesc.Width = Width; texDesc.Height = Height; texDesc.ArraySize = 6; texDesc.BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource; texDesc.CpuAccessFlags = CpuAccessFlags.None; texDesc.Format = Converter.ConvertToTex(format); texDesc.MipLevels = 1; texDesc.OptionFlags = ResourceOptionFlags.TextureCube; texDesc.SampleDescription = new DXGI.SampleDescription(samples, 0); texDesc.Usage = ResourceUsage.Default; texCube = new D3D.Texture2D(device.Device, texDesc); var srvDesc = new ShaderResourceViewDescription(); srvDesc.Dimension = samples > 1 ? ShaderResourceViewDimension.Texture2DMultisampled : ShaderResourceViewDimension.Texture2D; srvDesc.Format = Converter.ConvertToSRV(format); srvDesc.Texture2D.MostDetailedMip = 0; srvDesc.Texture2D.MipLevels = 1; SRV = new ShaderResourceView(device.Device, texCube); // // Create surfaces : // surfaces = new DepthStencilSurface[6]; for (int face = 0; face < 6; face++) { var rtvDesc = new DepthStencilViewDescription(); rtvDesc.Texture2DArray.MipSlice = 0; rtvDesc.Texture2DArray.FirstArraySlice = face; rtvDesc.Texture2DArray.ArraySize = 1; rtvDesc.Dimension = msaa ? DepthStencilViewDimension.Texture2DMultisampledArray : DepthStencilViewDimension.Texture2DArray; rtvDesc.Format = Converter.ConvertToDSV(format); var dsv = new DepthStencilView(device.Device, texCube, rtvDesc); int subResId = Resource.CalculateSubResourceIndex(0, face, 1); surfaces[face] = new DepthStencilSurface(dsv, format, Width, Height, SampleCount); } }