SharpDX.DXGI.SampleDescription GetSampleDescription(uint samples) { SharpDX.DXGI.SampleDescription[] descs = new SharpDX.DXGI.SampleDescription[16]; samples = Math.Max(1u, Math.Min(samples, 16u)); descs[0].Count = 1; descs[0].Quality = 0; for (uint i = 1, last = 0; i < samples; i++) { SharpDX.Direct3D12.FeatureDataMultisampleQualityLevels levels = new SharpDX.Direct3D12.FeatureDataMultisampleQualityLevels(); levels.Format = _format; levels.SampleCount = (int)i + 1; levels.Flags = SharpDX.Direct3D12.MultisampleQualityLevelFlags.None; levels.QualityLevelCount = 0; _dev.CheckFeatureSupport(SharpDX.Direct3D12.Feature.MultisampleQualityLevels, ref levels); if (levels.QualityLevelCount > 0) { descs[i].Count = levels.SampleCount; descs[i].Quality = 0; last = i; } else { descs[i] = descs[last]; } } return(descs[samples - 1]); }
public GBuffer(int width, int height, SampleDescription sampleDesc, params SharpDX.DXGI.Format[] targetFormats) { System.Diagnostics.Debug.Assert(targetFormats != null && targetFormats.Length > 0 && targetFormats.Length < 9, "Between 1 and 8 target formats must be provided"); this.width = width; this.height = height; this.sampleDescription = sampleDesc; RTFormats = targetFormats; }
/// <summary> /// Initializes a new instance of the <see cref="EngineDevice"/> class. /// </summary> internal EngineDevice(GraphicsCore core, GraphicsCoreConfiguration coreConfiguration, DXGI.Adapter1 adapter, bool isSoftwareAdapter, bool debugEnabled) { m_core = core; m_adapter1 = adapter; m_adapterDesc1 = m_adapter1.Description1; m_isSoftwareAdapter = isSoftwareAdapter; m_debugEnabled = debugEnabled; m_configuration = new GraphicsDeviceConfiguration(coreConfiguration); // Set default antialiasing configurations m_sampleDescWithAntialiasing = new DXGI.SampleDescription(1, 0); // Initialize all direct3D APIs try { #if UNIVERSAL m_handlerD3D11 = new DeviceHandlerD3D11(adapter, debugEnabled); m_handlerDXGI = new DeviceHandlerDXGI(adapter, m_handlerD3D11.Device1); #endif #if DESKTOP m_handlerD3D11 = new DeviceHandlerD3D11(adapter, debugEnabled); m_handlerDXGI = new DeviceHandlerDXGI(adapter, m_handlerD3D11.Device1); m_handlerD3D9 = new DeviceHandlerD3D9(adapter, isSoftwareAdapter, debugEnabled); #endif } catch (Exception ex) { m_initializationException = ex; #if UNIVERSAL m_handlerD3D11 = null; m_handlerDXGI = null; #endif #if DESKTOP m_handlerD3D11 = null; m_handlerDXGI = null; m_handlerD3D9 = null; #endif } // Set default configuration m_configuration.TextureQuality = !isSoftwareAdapter && m_handlerD3D11.IsDirect3D10OrUpperHardware ? TextureQuality.Hight : TextureQuality.Low; m_configuration.GeometryQuality = !isSoftwareAdapter && m_handlerD3D11.IsDirect3D10OrUpperHardware ? GeometryQuality.Hight : GeometryQuality.Low; // Initialize handlers for feature support information if (m_initializationException == null) { m_isStandardAntialiasingSupported = CheckIsStandardAntialiasingPossible(); } // Initialize direct2D handler finally if (m_handlerD3D11 != null) { m_handlerD2D = new DeviceHandlerD2D(m_core, this); this.FakeRenderTarget2D = m_handlerD2D.RenderTarget; } }
public ResourceDescription(ResourceDimension dimension, long alignment, long width, int height, short depthOrArraySize, short mipLevels, Format format, int sampleCount, int sampleQuality, TextureLayout layout, ResourceFlags optionFlags) { Dimension = dimension; Alignment = alignment; Width = width; Height = height; DepthOrArraySize = depthOrArraySize; MipLevels = mipLevels; Format = format; SampleDescription = new SampleDescription(sampleCount, sampleQuality); Layout = layout; Flags = optionFlags; }
public override void Init(IntPtr display, IntPtr window, uint samples, bool vsync, bool sRGB) { _display = display; _window = window; System.Console.WriteLine("Creating D3D12 render context"); CreateDevice(); CreateCommandQueue(); CreateSwapChain(window, vsync); _format = sRGB ? SharpDX.DXGI.Format.R8G8B8A8_UNorm_SRgb : SharpDX.DXGI.Format.R8G8B8A8_UNorm; _sampleDesc = GetSampleDescription(samples); samples = (uint)_sampleDesc.Count; CreateHeaps(); CreateBuffers(); CreateCommandList(); _device = new RenderDeviceD3D12(_dev.NativePointer, _fence.NativePointer, (int)_format, (int)SharpDX.DXGI.Format.D24_UNorm_S8_UInt, _sampleDesc.Count, sRGB); }
/// <summary> /// main thread /// </summary> /// <param name="panel"></param> /// <param name="dpi"></param> internal static void CreateD3DInstance(ref SwapChainComponent com) { int width = (int)com.panel.Width; int height = (int)com.panel.Height; dpi = (int)com.dpi; com.port = new Viewport(0, 0, width, height, 0, 1); D2D.d3dContext.Rasterizer.SetViewport(com.port); var multisampleDesc = new Dxgi.SampleDescription(1, 0); var desc = new Dxgi.SwapChainDescription1() { // Automatic sizing AlphaMode = Dxgi.AlphaMode.Premultiplied, Width = width, Height = height, Format = Dxgi.Format.B8G8R8A8_UNorm, Stereo = false, SampleDescription = multisampleDesc, Usage = Dxgi.Usage.RenderTargetOutput, BufferCount = 2, SwapEffect = Dxgi.SwapEffect.FlipSequential, Scaling = Dxgi.Scaling.Stretch }; using (var dxgiDevice2 = D2D.d3dDevice.QueryInterface <Dxgi.Device2>()) using (var dxgiAdapter = dxgiDevice2.Adapter) using (var dxgiFactory2 = dxgiAdapter.GetParent <Dxgi.Factory2>()) using (com.NativePanel = ComObject.As <Dxgi.ISwapChainPanelNative>(com.panel)) { com.swapChain = new Dxgi.SwapChain1(dxgiFactory2, dxgiDevice2, ref desc, null); com.NativePanel.SwapChain = com.swapChain; dxgiDevice2.MaximumFrameLatency = 1; } using (com.backbuffer = D3D11.Texture2D.FromSwapChain <D3D11.Texture2D>(com.swapChain, 0)) com.TargetView = new D3D11.RenderTargetView(D2D.d3dDevice, com.backbuffer); using (com.depthbuffer = new D3D11.Texture2D(D2D.d3dDevice, new D3D11.Texture2DDescription() { Format = Dxgi.Format.D24_UNorm_S8_UInt, ArraySize = 1, MipLevels = 1, Width = width, Height = height, SampleDescription = multisampleDesc, Usage = D3D11.ResourceUsage.Default, BindFlags = D3D11.BindFlags.DepthStencil, })) com.StencilView = new D3D11.DepthStencilView(D2D.d3dDevice, com.depthbuffer); D2D.d3dContext.OutputMerger.SetTargets(com.StencilView, com.TargetView); var bitmapProperties = new D2D1.BitmapProperties1( new D2D1.PixelFormat(Dxgi.Format.B8G8R8A8_UNorm, D2D1.AlphaMode.Premultiplied), com.dpi, com.dpi, D2D1.BitmapOptions.Target | D2D1.BitmapOptions.CannotDraw); using (var dxgiBackBuffer = com.swapChain.GetBackBuffer <Dxgi.Surface>(0)) { com.Bitmap = new D2D1.Bitmap1(D2D.d2dContext, dxgiBackBuffer, bitmapProperties); } D2D.d2dContext.Target = com.Bitmap; D2D.d2dContext.TextAntialiasMode = D2D1.TextAntialiasMode.Cleartype; }
unsafe void InitializeInner(AntiAliasingMode antiAliasingMode) { worldMatrix = Matrix.Identity; textMatrix = Matrix.Identity; device = new D3D11.Device(DriverType.Hardware, D3D11.DeviceCreationFlags.None, new[] { FeatureLevel.Level_11_1, FeatureLevel.Level_11_0, FeatureLevel.Level_10_1, FeatureLevel.Level_10_0 }); tkDevice = TK.GraphicsDevice.New(device); deviceContext = device.ImmediateContext; deviceContext.Rasterizer.State = device.CreateRasterizerState(); //TODO: replace with precompiled bytecode const string shaderFile = @"..\..\..\GameUtils\Graphics\shaders.fx"; ShaderBytecode vertexShaderBytecode = ShaderBytecode.CompileFromFile(shaderFile, "VS", "vs_4_0", ShaderFlags.Debug); ShaderBytecode pixelShaderBytecode = ShaderBytecode.CompileFromFile(shaderFile, "PS", "ps_4_0", ShaderFlags.Debug); InitializeShaders(vertexShaderBytecode, pixelShaderBytecode); indexBuffers = new D3D11.Buffer[BufferCount]; vertexBuffers = new D3D11.Buffer[BufferCount]; for (int i = 0, indexBufferSize = IndexBufferStartSize, vertexBufferSize = VertexBufferStartSize; i < BufferCount; i++, indexBufferSize <<= BufferSizeStep, vertexBufferSize <<= BufferSizeStep) { indexBuffers[i] = device.CreateDynamicBuffer(sizeof(int) * indexBufferSize, D3D11.BindFlags.IndexBuffer); vertexBuffers[i] = device.CreateDynamicBuffer(sizeof(Vertex) * vertexBufferSize, D3D11.BindFlags.VertexBuffer); } currentBufferIndex = 0; indexBuffer = indexBuffers[0]; vertexBuffer = vertexBuffers[0]; //indexBuffer = device.CreateDynamicBuffer(sizeof(int) * IndexBufferSize, D3D11.BindFlags.IndexBuffer); //vertexBuffer = device.CreateDynamicBuffer(sizeof(Vertex) * VertexBufferSize, D3D11.BindFlags.VertexBuffer); matrixBuffer = device.CreateConstantBuffer(sizeof(MatrixBuffer)); brushBuffer = device.CreateConstantBuffer(sizeof(Brush.BrushBuffer)); deviceContext.InputAssembler.SetIndexBuffer(indexBuffer, DXGI.Format.R32_UInt, 0); deviceContext.InputAssembler.SetVertexBuffers(0, new D3D11.VertexBufferBinding(vertexBuffer, sizeof(Vertex), 0)); deviceContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; blendState = device.CreateBlendState(); deviceContext.OutputMerger.SetBlendState(blendState); currentWrapMode = WrapMode.Clamp; currentInterpolationMode = InterpolationMode.Linear; samplerState = device.CreateSamplerState(WrapMode.Clamp, InterpolationMode.Linear); deviceContext.PixelShader.SetSampler(0, samplerState); sampleDescription = device.GetMultisamplingLevel(antiAliasingMode); defaultDepthStencilState = device.CreateDepthStencilState(D3D11.Comparison.Always, D3D11.StencilOperation.Keep, D3D11.StencilOperation.Keep); clipDepthStencilState = device.CreateDepthStencilState(D3D11.Comparison.Never, D3D11.StencilOperation.Replace, D3D11.StencilOperation.Keep); clippingDepthStencilState = device.CreateDepthStencilState(D3D11.Comparison.Equal, D3D11.StencilOperation.Keep, D3D11.StencilOperation.Keep); deviceContext.OutputMerger.SetDepthStencilState(defaultDepthStencilState); }
public Framework(string title, int width, int height, bool depth, bool stencil, bool _VSync) { // Create the display to display on Window = new Form() { StartPosition = FormStartPosition.CenterScreen, ClientSize = new Size(width, height), Text = title, TopMost = true, }; Window.StartPosition = FormStartPosition.Manual; Window.Location = new Point(1100, 80); Window.FormBorderStyle = FormBorderStyle.Fixed3D; Window.WindowState =FormWindowState.Normal; Window.CreateControl(); VerticalSyncEnabled = _VSync; CreateDevice(); // Create a description of the display mode var modeDescription = new ModeDescription() { Format = Format.R8G8B8A8_UNorm, RefreshRate = new Rational(60, 1), Scaling = DisplayModeScaling.Unspecified, ScanlineOrdering = DisplayModeScanlineOrder.Unspecified, Width = width, Height = height, }; // Create a description of the sampling for multisampling or antialiasing var sampleDescription = new SampleDescription() { Count = 1, Quality = 0, }; // Create a description of the swap chain or front and back buffers var swapDescription = new SwapChainDescription() { ModeDescription = modeDescription, SampleDescription = sampleDescription, BufferCount = 1, Flags = SwapChainFlags.None, IsWindowed = true, OutputHandle = Window.Handle, SwapEffect = SwapEffect.Discard, Usage = Usage.RenderTargetOutput, }; // Create the DirectX 11 Device SharpDX.Direct3D11.Device.CreateWithSwapChain(SharpDX.Direct3D.DriverType.Hardware, DeviceCreationFlags.BgraSupport|DeviceCreationFlags.Debug, swapDescription, out Device, out swapChain); DContext = Device.ImmediateContext; // Create the factory which manages general graphics resources // Ignore all windows events Factory = swapChain.GetParent<Factory>(); Factory.MakeWindowAssociation(Window.Handle, WindowAssociationFlags.IgnoreAll); Factory.Dispose(); // New RenderTargetView from the backbuffer var backBuffer = Texture2D.FromSwapChain<Texture2D>(swapChain, 0); RenderTargetView = new RenderTargetView(Device, backBuffer); RenderTargetView.DebugName = "std"; // Release pointer to the back buffer as we no longer need it. backBuffer.Dispose(); frame_width=Window.ClientSize.Width; frame_height=Window.ClientSize.Height; #region Zdepth if (depth || stencil) { _depth=true; var textureDescription = new Texture2DDescription() { Width = frame_width, Height = frame_height, MipLevels = 1, ArraySize = 1, Format = (stencil) ? Format.D32_Float : Format.D24_UNorm_S8_UInt, SampleDescription = sampleDescription, Usage = ResourceUsage.Default, BindFlags = BindFlags.DepthStencil, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.None, }; var texture = new Texture2D(Device, textureDescription); var depthStencilViewDescription = new DepthStencilViewDescription() { Format = textureDescription.Format, Dimension = DepthStencilViewDimension.Texture2DMultisampled }; DepthStencilView = new DepthStencilView(Device, texture, depthStencilViewDescription); DContext.OutputMerger.SetTargets(DepthStencilView, RenderTargetView); } else { DContext.OutputMerger.SetTargets(RenderTargetView); } if (depth && !stencil) depthStencilClear = DepthStencilClearFlags.Depth; else if (stencil && !depth) depthStencilClear = DepthStencilClearFlags.Stencil; else if (stencil && depth) depthStencilClear = DepthStencilClearFlags.Stencil | DepthStencilClearFlags.Depth; #endregion #region Rasterizer RasterizerStateDescription RAS = new RasterizerStateDescription(); RAS.IsMultisampleEnabled = true; //important for AA RAS.CullMode = CullMode.Back; RAS.DepthBias = 0; RAS.DepthBiasClamp = 0.0f; RAS.FillMode = FillMode.Solid; RAS.IsDepthClipEnabled = false; RAS.IsFrontCounterClockwise = true; DContext.Rasterizer.State = new RasterizerState(Device, RAS); #endregion // Setup the camera viewport var viewport = new Viewport() { TopLeftX = 0, TopLeftY = 0, Width = width, Height = height, MinDepth = 0.0f, MaxDepth = 1.0f, }; DContext.Rasterizer.SetViewports(viewport); Stopwatch = new Stopwatch(); }
public static D3D.Texture2D CreateSurface(this D3D.Device device, int width, int height, DXGI.SampleDescription sampleDescription, out D3D.RenderTargetView renderTarget) { var desc = new D3D.Texture2DDescription { Width = width, Height = height, MipLevels = 1, ArraySize = 1, Format = DXGI.Format.R8G8B8A8_UNorm, SampleDescription = sampleDescription, Usage = D3D.ResourceUsage.Default, BindFlags = D3D.BindFlags.RenderTarget | D3D.BindFlags.ShaderResource, CpuAccessFlags = D3D.CpuAccessFlags.None, OptionFlags = D3D.ResourceOptionFlags.Shared, }; var surface = new D3D.Texture2D(device, desc); var targetDesc = new D3D.RenderTargetViewDescription { Format = desc.Format, Dimension = desc.SampleDescription.Count == 1 ? D3D.RenderTargetViewDimension.Texture2D : D3D.RenderTargetViewDimension.Texture2DMultisampled, }; renderTarget = new D3D.RenderTargetView(device, surface, targetDesc); return(surface); }
/// <summary> /// Initializes a new instance of the <see cref="RenderTargetCube"/> class. /// </summary> /// <param name="graphicsDevice">The graphics device.</param> /// <param name="size">The width and height of a texture cube face in pixels.</param> /// <param name="mipMap"><see langword="true"/> to generate a full mipmap chain; otherwise <see langword="false"/>.</param> /// <param name="preferredFormat">The preferred format of the surface.</param> /// <param name="preferredDepthFormat">The preferred format of the depth-stencil buffer.</param> /// <param name="preferredMultiSampleCount">The preferred number of multisample locations.</param> /// <param name="usage">The usage mode of the render target.</param> public RenderTargetCube(GraphicsDevice graphicsDevice, int size, bool mipMap, SurfaceFormat preferredFormat, DepthFormat preferredDepthFormat, int preferredMultiSampleCount, RenderTargetUsage usage) : base(graphicsDevice, size, mipMap, preferredFormat, true) { DepthStencilFormat = preferredDepthFormat; MultiSampleCount = preferredMultiSampleCount; RenderTargetUsage = usage; #if DIRECTX // Create one render target view per cube map face. _renderTargetViews = new RenderTargetView[6]; for (int i = 0; i < _renderTargetViews.Length; i++) { var renderTargetViewDescription = new RenderTargetViewDescription { Dimension = RenderTargetViewDimension.Texture2DArray, Format = SharpDXHelper.ToFormat(preferredFormat), Texture2DArray = { ArraySize = 1, FirstArraySlice = i, MipSlice = 0 } }; _renderTargetViews[i] = new RenderTargetView(graphicsDevice._d3dDevice, _texture, renderTargetViewDescription); } // If we don't need a depth buffer then we're done. if (preferredDepthFormat == DepthFormat.None) return; var sampleDescription = new SampleDescription(1, 0); if (preferredMultiSampleCount > 1) { sampleDescription.Count = preferredMultiSampleCount; sampleDescription.Quality = (int)StandardMultisampleQualityLevels.StandardMultisamplePattern; } var depthStencilDescription = new Texture2DDescription { Format = SharpDXHelper.ToFormat(preferredDepthFormat), ArraySize = 1, MipLevels = 1, Width = size, Height = size, SampleDescription = sampleDescription, BindFlags = BindFlags.DepthStencil, }; using (var depthBuffer = new SharpDX.Direct3D11.Texture2D(graphicsDevice._d3dDevice, depthStencilDescription)) { var depthStencilViewDescription = new DepthStencilViewDescription { Dimension = DepthStencilViewDimension.Texture2D, Format = SharpDXHelper.ToFormat(preferredDepthFormat), }; _depthStencilView = new DepthStencilView(graphicsDevice._d3dDevice, depthBuffer, depthStencilViewDescription); } #else throw new NotImplementedException(); #endif }
/// <summary> /// Checks for standard antialiasing support. /// </summary> private bool CheckIsStandardAntialiasingPossible() { // Very important to check possible antialiasing // More on the used technique // see http://msdn.microsoft.com/en-us/library/windows/apps/dn458384.aspx D3D11.FormatSupport formatSupport = m_handlerD3D11.Device1.CheckFormatSupport(GraphicsHelper.DEFAULT_TEXTURE_FORMAT); if ((formatSupport & D3D11.FormatSupport.MultisampleRenderTarget) != D3D11.FormatSupport.MultisampleRenderTarget) { return(false); } if ((formatSupport & D3D11.FormatSupport.MultisampleResolve) != D3D11.FormatSupport.MultisampleResolve) { return(false); } if (m_handlerD3D11.FeatureLevel == SharpDX.Direct3D.FeatureLevel.Level_9_1) { return(false); } try { D3D11.Texture2DDescription textureDescription = new D3D11.Texture2DDescription(); textureDescription.Width = 100; textureDescription.Height = 100; textureDescription.MipLevels = 1; textureDescription.ArraySize = 1; textureDescription.Format = GraphicsHelper.DEFAULT_TEXTURE_FORMAT; textureDescription.Usage = D3D11.ResourceUsage.Default; textureDescription.SampleDescription = new DXGI.SampleDescription(2, 0); textureDescription.BindFlags = D3D11.BindFlags.ShaderResource | D3D11.BindFlags.RenderTarget; textureDescription.CpuAccessFlags = D3D11.CpuAccessFlags.None; textureDescription.OptionFlags = D3D11.ResourceOptionFlags.None; D3D11.Texture2D testTexture = new D3D11.Texture2D(m_handlerD3D11.Device1, textureDescription); GraphicsHelper.SafeDispose(ref testTexture); } catch (Exception) { return(false); } // Check for quality levels int lowQualityLevels = m_handlerD3D11.Device1.CheckMultisampleQualityLevels(GraphicsHelper.DEFAULT_TEXTURE_FORMAT, 2); int mediumQualityLevels = m_handlerD3D11.Device1.CheckMultisampleQualityLevels(GraphicsHelper.DEFAULT_TEXTURE_FORMAT, 4); int hightQualityLevels = m_handlerD3D11.Device1.CheckMultisampleQualityLevels(GraphicsHelper.DEFAULT_TEXTURE_FORMAT, 8); // Generate sample descriptions for each possible quality level if (lowQualityLevels > 0) { m_antialiasingConfigLow = new DXGI.SampleDescription(2, lowQualityLevels - 1); } if (mediumQualityLevels > 0) { m_antialiasingConfigMedium = new DXGI.SampleDescription(4, mediumQualityLevels - 1); } if (hightQualityLevels > 0) { m_antialiasingConfigHigh = new DXGI.SampleDescription(8, hightQualityLevels - 1); } return(lowQualityLevels > 0); }
/// <summary> /// Initializes a new engine, sets view , tex manager /// camera , mesh manager , texture manager , line manager /// volume manager /// </summary> /// <param name="width">The width of the Render target</param> /// <param name="height">The height of the Render target</param> public Engine(int Width, int Height, Form form) { // pass the settings of resolution Settings.Resolution = new System.Drawing.Size(Width, Height); /// set the handles for full screen or windows this.form = form; this.FormHandle = form.Handle; /// Create the factory which manages general graphics resources g_factory = new Factory(); g_factory.MakeWindowAssociation(this.FormHandle, WindowAssociationFlags.IgnoreAll); // find correct adapter int adapterCount = g_factory.GetAdapterCount(); //MessageBox.Show(adapterCount.ToString()); // we try to select the PerfHUD adapter for (int i = 0; i < adapterCount; i++) { Adapter adapt = g_factory.GetAdapter(i); //MessageBox.Show(adapt.Description.Description); if (adapt.Description.Description == "NVIDIA PerfHUD") { g_device = new Device( adapt, DeviceCreationFlags.Debug); } Console.WriteLine(i.ToString() + adapt.Description.Description); } if (g_device == null) { #if true /// Create the DirectX Device g_device = new Device(g_factory.GetAdapter(1), (Settings.Debug) ? DeviceCreationFlags.Debug : DeviceCreationFlags.None, new FeatureLevel[] { FeatureLevel.Level_11_0 }); #else g_device = new Device(DriverType.Warp, (Settings.Debug) ? DeviceCreationFlags.Debug : DeviceCreationFlags.None, new FeatureLevel[] { FeatureLevel.Level_11_0 }); #endif // check if we have one device to our system if (!(((g_device.FeatureLevel & FeatureLevel.Level_10_0) != 0) || ((g_device.FeatureLevel & FeatureLevel.Level_10_1) != 0) || ((g_device.FeatureLevel & FeatureLevel.Level_11_0) != 0))) { // if we don't have we just simulate #region Create the device base on swapChain /// Create a description of the display mode g_modeDesc = new ModeDescription(); /// Standard 32-bit RGBA g_modeDesc.Format = Format.R8G8B8A8_UNorm; /// Refresh rate of 60Hz (60 / 1 = 60) g_modeDesc.RefreshRate = new Rational(60, 1); /// Default g_modeDesc.Scaling = DisplayModeScaling.Unspecified; g_modeDesc.ScanlineOrdering = DisplayModeScanlineOrder.Progressive; /// ClientSize is the size of the /// form without the title and borders g_modeDesc.Width = Width; g_modeDesc.Height = Height; /// Create a description of the samping /// for multisampling or antialiasing g_sampleDesc = new SampleDescription(); /// No multisampling g_sampleDesc.Count = 1; g_sampleDesc.Quality = 0; /// Create a description of the swap /// chain or front and back buffers g_swapDesc = new SwapChainDescription(); /// link the ModeDescription g_swapDesc.ModeDescription = g_modeDesc; /// link the SampleDescription g_swapDesc.SampleDescription = g_sampleDesc; /// Number of buffers (including the front buffer) g_swapDesc.BufferCount = 1; g_swapDesc.Flags = SwapChainFlags.AllowModeSwitch; g_swapDesc.IsWindowed = true; /// The output window (the windows being rendered to) g_swapDesc.OutputHandle = this.FormHandle; /// Scrap the contents of the buffer every frame g_swapDesc.SwapEffect = SwapEffect.Discard; /// Indicate that this SwapChain /// is going to be a Render target g_swapDesc.Usage = Usage.RenderTargetOutput; //g_swapChain = new SwapChain(g_factory, g_device, g_swapDesc); try { /// Create the actual swap chain /// Here we set and the device type Device.CreateWithSwapChain(DriverType.Warp, (Settings.Debug) ? DeviceCreationFlags.Debug : DeviceCreationFlags.None, new FeatureLevel[] { Settings.FeatureLevel }, g_swapDesc, out g_device, out g_swapChain); } catch (Exception ex) { /// Create the actual swap chain /// Here we set and the device type Device.CreateWithSwapChain(DriverType.Reference, (Settings.Debug) ? DeviceCreationFlags.Debug : DeviceCreationFlags.None, new FeatureLevel[] { Settings.FeatureLevel }, g_swapDesc, out g_device, out g_swapChain); } /// Create the factory which manages general graphics resources g_factory = g_swapChain.GetParent<Factory>(); g_factory.MakeWindowAssociation(this.FormHandle, WindowAssociationFlags.IgnoreAll); #endregion } else { #if false #region Create the device base on swapChain /// Create a description of the display mode g_modeDesc = new ModeDescription(); /// Standard 32-bit RGBA g_modeDesc.Format = Format.R8G8B8A8_UNorm; /// Refresh rate of 60Hz (60 / 1 = 60) g_modeDesc.RefreshRate = new Rational(60, 1); /// Default g_modeDesc.Scaling = DisplayModeScaling.Unspecified; g_modeDesc.ScanlineOrdering = DisplayModeScanlineOrdering.Progressive; /// ClientSize is the size of the /// form without the title and borders g_modeDesc.Width = Width; g_modeDesc.Height = Height; /// Create a description of the samping /// for multisampling or antialiasing g_sampleDesc = new SampleDescription(); /// No multisampling g_sampleDesc.Count = 1; g_sampleDesc.Quality = 0; /// Create a description of the swap /// chain or front and back buffers g_swapDesc = new SwapChainDescription(); /// link the ModeDescription g_swapDesc.ModeDescription = g_modeDesc; /// link the SampleDescription g_swapDesc.SampleDescription = g_sampleDesc; /// Number of buffers (including the front buffer) g_swapDesc.BufferCount = 1; g_swapDesc.Flags = SwapChainFlags.None; g_swapDesc.IsWindowed = true; /// The output window (the windows being rendered to) g_swapDesc.OutputHandle = FormHandle; /// Scrap the contents of the buffer every frame g_swapDesc.SwapEffect = SwapEffect.Discard; /// Indicate that this SwapChain /// is going to be a Render target g_swapDesc.Usage = Usage.RenderTargetOutput; g_swapChain = new SwapChain(g_factory, g_device, g_swapDesc); #endregion #endif } // set the feature level Settings.FeatureLevel = g_device.FeatureLevel; } /// init mesh manager g_MeshManager = new Object3DManager(); /// init deferred device //DeferredDev1 = new DeviceContext( Engine.g_device ); //DeferredDev2 = new DeviceContext( Engine.g_device ); // init the image factory... g_image_factory = new ImagingFactory(); /// Set flag to indicate that engine is running g_Running = true; Logger.WriteLine("The Graphing Engine have be start "); // set the event handler RenderLoopHandler = new EventHandler(RenderLoop); var rtb = new RenderTargetBlendDescription() { IsBlendEnabled = true, BlendOperation = BlendOperation.Add, AlphaBlendOperation = BlendOperation.Add, DestinationBlend = BlendOption.One, DestinationAlphaBlend = BlendOption.Zero, SourceBlend = BlendOption.One, SourceAlphaBlend = BlendOption.One, RenderTargetWriteMask = ColorWriteMaskFlags.All }; BlendStateDescription blendDesc = new BlendStateDescription(); blendDesc.AlphaToCoverageEnable = false; blendDesc.IndependentBlendEnable = false; blendDesc.RenderTarget[0] = rtb; g_blendState = new BlendState(g_device, blendDesc); DepthStencilStateDescription dssd = new DepthStencilStateDescription(); dssd.DepthComparison = Comparison.Less; dssd.IsDepthEnabled = true; g_depthStencilState = new DepthStencilState(g_device, new DepthStencilStateDescription()); }
public void Inizialize(Device device, Viewport viewport, SwapChainDescription description, DeviceContext context, SwapChain swapChain) { int S = Global.Settings.MultiSample; if (S == 0) S++; SampleDescription _SampleDescription = new SampleDescription(S, 0); //Буфер глубины Texture2DDescription DepthStencilDescription = new Texture2DDescription(); DepthStencilDescription.Width = (int)viewport.Width; DepthStencilDescription.Height = (int)viewport.Height; DepthStencilDescription.MipLevels = 1; DepthStencilDescription.ArraySize = 1; DepthStencilDescription.Format = Format.D32_Float; DepthStencilDescription.SampleDescription = _SampleDescription; DepthStencilDescription.Usage = ResourceUsage.Default; DepthStencilDescription.BindFlags = BindFlags.DepthStencil; DepthStencilDescription.CpuAccessFlags = CpuAccessFlags.None; DepthStencilDescription.OptionFlags = ResourceOptionFlags.None; DepthStencil = new Texture2D(device, DepthStencilDescription); DepthStencilView = new DepthStencilView(device, DepthStencil); //HDR буффер Texture2DDescription HDRDescription = new Texture2DDescription(); HDRDescription.MipLevels = 1; HDRDescription.ArraySize = 1; HDRDescription.Width = (int)viewport.Width; HDRDescription.Height = (int)viewport.Height; HDRDescription.Format = Format.R16G16B16A16_Float; HDRDescription.SampleDescription = _SampleDescription; HDRDescription.Usage = ResourceUsage.Default; HDRDescription.BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource; HDRDescription.CpuAccessFlags = CpuAccessFlags.None; HDRDescription.OptionFlags = ResourceOptionFlags.None; HDRTexture = new Texture2D(device, HDRDescription); HDRSRV = new ShaderResourceView(device, HDRTexture); RenderTargetViewDescription RTVD = new RenderTargetViewDescription(); RTVD.Format = HDRDescription.Format; RTVD.Dimension = RenderTargetViewDimension.Texture2DMultisampled; RTVD.Texture2DMSArray.FirstArraySlice = 0; RTVD.Texture2DMSArray.ArraySize = 1; RTVD.Texture2D.MipSlice = 0; HDRTarget = new RenderTargetView(device, HDRTexture, RTVD); SamplerStateDescription a = new SamplerStateDescription(); a.AddressU = TextureAddressMode.Wrap; a.AddressV = TextureAddressMode.Wrap; a.AddressW = TextureAddressMode.Wrap; a.Filter = Filter.MinMagMipPoint; HDRSS = new SamplerState(device, ref a); //Depth ////////////////////////////////////////////////////////////////////////// Texture2DDescription DepthDescription = new Texture2DDescription(); DepthDescription.Width = (int)viewport.Width; DepthDescription.Height = (int)viewport.Height; DepthDescription.MipLevels = 1; DepthDescription.ArraySize = 1; DepthDescription.Format = Format.R32_Float; DepthDescription.Usage = ResourceUsage.Default; DepthDescription.BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource; DepthDescription.SampleDescription = new SampleDescription(1, 0); DepthDescription.CpuAccessFlags = CpuAccessFlags.None; DepthDescription.OptionFlags = ResourceOptionFlags.None; DepthTexture = new Texture2D(device, DepthDescription); DepthSRV = new ShaderResourceView(device, DepthTexture); RenderTargetViewDescription DTVD = new RenderTargetViewDescription(); DTVD.Format = DepthDescription.Format; DTVD.Dimension = RenderTargetViewDimension.Texture2D; DTVD.Texture2DMSArray.FirstArraySlice = 0; DTVD.Texture2DMSArray.ArraySize = 1; DTVD.Texture2D.MipSlice = 0; DepthTarget = new RenderTargetView(device, DepthTexture, DTVD); DepthStencilDescription.SampleDescription = new SampleDescription(1, 0); DepthMapStencil = new Texture2D(device, DepthStencilDescription); DepthMapStencilView = new DepthStencilView(device, DepthMapStencil); // create a view of our render target, which is the backbuffer of the swap chain we just created using (var resource = Resource.FromSwapChain<Texture2D>(swapChain, 0)) renderTarget = new RenderTargetView(device, resource); }
private void SetView(int Width, int Height) { ///////////////////////////////////////////////////////////////////////// Set the ModeDescription /// Create a description of the display mode m_ModeDesc = new ModeDescription(); /// Standard 32-bit RGBA m_ModeDesc.Format = backFormat; /// Refresh rate of 60Hz (60 / 1 = 60) m_ModeDesc.RefreshRate = new Rational(Settings.FrameRate, 1); /// Default m_ModeDesc.Scaling = DisplayModeScaling.Centered; m_ModeDesc.ScanlineOrdering = DisplayModeScanlineOrder.Progressive; /// ClientSize is the size of the /// form without the title and borders m_ModeDesc.Width = Width; m_ModeDesc.Height = Height; ///////////////////////////////////////////////////////////////////////// Set the SampleDescription /// Create a description of the sampling /// for multisampling or antialiasing m_SampleDesc = new SampleDescription(); /// No multisampling m_SampleDesc.Count = 1; m_SampleDesc.Quality = 0; ///////////////////////////////////////////////////////////////////////// Set the SampleDescription /// Create a description of the swap /// chain or front and back buffers m_SwapDesc = new SwapChainDescription(); /// link the ModeDescription m_SwapDesc.ModeDescription = m_ModeDesc; /// link the SampleDescription m_SwapDesc.SampleDescription = m_SampleDesc; /// Number of buffers (including the front buffer) m_SwapDesc.BufferCount = 1; m_SwapDesc.Flags = SwapChainFlags.None; m_SwapDesc.IsWindowed = true; /// The output window (the windows being rendered to) m_SwapDesc.OutputHandle = this.m_RenderControl; /// Scrap the contents of the buffer every frame m_SwapDesc.SwapEffect = SwapEffect.Discard; /// Indicate that this SwapChain /// is going to be a Render target m_SwapDesc.Usage = Usage.RenderTargetOutput; ///////////////////////////////////////////////////////////////////////// Create Chain // release the old chain if (m_SwapChain != null) m_SwapChain.Dispose(); /// Create the actual swap chain m_SwapChain = new SwapChain(Engine.g_factory, Engine.g_device, m_SwapDesc); ///////////////////////////////////////////////////////////////////////// Set the Render Target m_RenderStencil = Texture2D.FromSwapChain<Texture2D>(m_SwapChain, 0); /// Create and set the Render target - /// the surface that we're actually going to draw on m_RenderTarget = new RenderTargetView( Engine.g_device, m_RenderStencil); ///////////////////////////////////////////////////////////////////////// Set the m_DepthStencil and m_DepthStencilView /// Create depth stencil texture /// and setup its settings Texture2DDescription descDepth = new Texture2DDescription(); descDepth.Width = Width; descDepth.Height = Height; descDepth.MipLevels = 1; descDepth.ArraySize = 1; descDepth.Format = Format.D32_Float; descDepth.SampleDescription = new SampleDescription(1, 0); descDepth.Usage = ResourceUsage.Default; descDepth.BindFlags = BindFlags.DepthStencil; descDepth.CpuAccessFlags = CpuAccessFlags.None; descDepth.OptionFlags = ResourceOptionFlags.None; /// create the depth stencil view /// and setup its settings DepthStencilViewDescription descDSV = new DepthStencilViewDescription(); descDSV.Format = descDepth.Format; descDSV.Dimension = DepthStencilViewDimension.Texture2D; //descDSV.MipSlice = 0; m_DepthStencil = new Texture2D(Engine.g_device, descDepth); m_DepthStencilView = new DepthStencilView(Engine.g_device, m_DepthStencil, descDSV); }
public CreationSettings(Size renderTargetDimensions, bool createDepthStencil, SampleDescription sampleDescription, RenderTargetClearSettings renderTargetClearSettings, DepthStencilClearSettings depthStencilClearSettings) { Dimensions = renderTargetDimensions; RenderTargetClearSettings = renderTargetClearSettings; CreateDepthStencil = createDepthStencil; SampleDescription = sampleDescription; DepthStencilClearSettings = depthStencilClearSettings; }
private static void ConfigureSample(out SampleDescription description) { description.Count = 1; description.Quality = 0; }
private Texture2D CreateTexture(int width, int height, bool multiSampling) { var description = new SharpDX.Direct3D10.Texture2DDescription(); description.ArraySize = 1; description.BindFlags = SharpDX.Direct3D10.BindFlags.RenderTarget | SharpDX.Direct3D10.BindFlags.ShaderResource; description.CpuAccessFlags = CpuAccessFlags.None; description.Format = Format.B8G8R8A8_UNorm; description.MipLevels = 1; // Multi-sample anti-aliasing int count, quality; if (multiSampling) { count = 8; quality = device.CheckMultisampleQualityLevels(description.Format, count); if (quality == 0) { count = 4; quality = device.CheckMultisampleQualityLevels(description.Format, count); } if (quality == 0) count = 1; } else count = 1; if (count == 1) quality = 1; SampleDescription sampleDesc = new SampleDescription(count, 0); description.SampleDescription = sampleDesc; description.Usage = ResourceUsage.Default; description.OptionFlags = ResourceOptionFlags.Shared; description.Height = (int)height; description.Width = (int)width; return new Texture2D(device, description); }
public SwapChainRenderTarget( GraphicsDevice graphicsDevice, IntPtr windowHandle, int width, int height, bool mipMap, SurfaceFormat surfaceFormat, DepthFormat depthFormat, int preferredMultiSampleCount, RenderTargetUsage usage, PresentInterval presentInterval) : base( graphicsDevice, width, height, mipMap, surfaceFormat, depthFormat, preferredMultiSampleCount, usage, SurfaceType.SwapChainRenderTarget) { var dxgiFormat = surfaceFormat == SurfaceFormat.Color ? SharpDX.DXGI.Format.B8G8R8A8_UNorm : SharpDXHelper.ToFormat(surfaceFormat); var multisampleDesc = new SampleDescription(1, 0); if (preferredMultiSampleCount > 1) { multisampleDesc.Count = preferredMultiSampleCount; multisampleDesc.Quality = (int)StandardMultisampleQualityLevels.StandardMultisamplePattern; } var desc = new SwapChainDescription() { ModeDescription = { Format = dxgiFormat, Scaling = DisplayModeScaling.Stretched, Width = width, Height = height, }, OutputHandle = windowHandle, SampleDescription = multisampleDesc, Usage = Usage.RenderTargetOutput, BufferCount = 2, SwapEffect = SharpDXHelper.ToSwapEffect(presentInterval), IsWindowed = true, }; PresentInterval = presentInterval; // Once the desired swap chain description is configured, it must // be created on the same adapter as our D3D Device var d3dDevice = graphicsDevice._d3dDevice; // First, retrieve the underlying DXGI Device from the D3D Device. // Creates the swap chain using (var dxgiDevice = d3dDevice.QueryInterface<Device1>()) using (var dxgiAdapter = dxgiDevice.Adapter) using (var dxgiFactory = dxgiAdapter.GetParent<Factory1>()) { _swapChain = new SwapChain(dxgiFactory, dxgiDevice, desc); } // Obtain the backbuffer for this window which will be the final 3D rendertarget. var backBuffer = SharpDX.Direct3D11.Resource.FromSwapChain<SharpDX.Direct3D11.Texture2D>(_swapChain, 0); // Create a view interface on the rendertarget to use on bind. _renderTargetViews = new[] { new RenderTargetView(d3dDevice, backBuffer) }; // Get the rendertarget dimensions for later. var backBufferDesc = backBuffer.Description; var targetSize = new Point(backBufferDesc.Width, backBufferDesc.Height); _texture = backBuffer; // Create the depth buffer if we need it. if (depthFormat != DepthFormat.None) { dxgiFormat = SharpDXHelper.ToFormat(depthFormat); // Allocate a 2-D surface as the depth/stencil buffer. using ( var depthBuffer = new SharpDX.Direct3D11.Texture2D(d3dDevice, new Texture2DDescription() { Format = dxgiFormat, ArraySize = 1, MipLevels = 1, Width = targetSize.X, Height = targetSize.Y, SampleDescription = multisampleDesc, Usage = ResourceUsage.Default, BindFlags = BindFlags.DepthStencil, })) // Create a DepthStencil view on this surface to use on bind. _depthStencilView = new DepthStencilView(d3dDevice, depthBuffer); } }
public void Init(IntPtr windowHandle) { // Factory de interfaces de DirectX Factory factory = new Factory(); // Factory para crear el adaptador a la tarjeta grafica (la primera) Adapter adapter = factory.GetAdapter(0); // Obtengo la salida a monitor primario del adaptador Output monitor = adapter.Outputs[0]; //Obtengo mis posibilidades de salida que soporto que utilicen el formato R8G8B8A8_UNorm ModeDescription[] displayModes = monitor.GetDisplayModeList(swapChainFormat, DisplayModeEnumerationFlags.Interlaced); //Si utilizo VSync, busco la taza de refresco para la resolución deseada que soporta el monitor Rational refreshRate = new Rational(0, 1); //if (VSyncEnabled) foreach (ModeDescription mode in displayModes) if (mode.Width == SettingsManager.Current.ScreenSize.Width && mode.Height == SettingsManager.Current.ScreenSize.Height) { refreshRate = mode.RefreshRate; break; } // Obtengo los datos sobre la tarjeta de memoria AdapterDescription adapterDescription = adapter.Description; VideoCardDescription = adapterDescription.Description; VideoCardMemory = adapterDescription.DedicatedVideoMemory >> 10 >> 10; // En MB DebugManager.LogNotice(VideoCardDescription + " con " + VideoCardMemory + " MB dedicados"); // Creo el device y el devicecontext SharpDX.Direct3D11.Device temp_device; SharpDX.Direct3D.FeatureLevel[] features = new FeatureLevel[] { // Array de Feature Level soportados FeatureLevel.Level_11_0, FeatureLevel.Level_10_1, FeatureLevel.Level_10_0, FeatureLevel.Level_9_3 }; DeviceCreationFlags creationFlags; // Creo al device en modo debug si estoy en modo debug if (DebugManager.DebugMode) creationFlags = DeviceCreationFlags.Debug; else creationFlags = DeviceCreationFlags.None; SampleDescription sampleDescription; // Info de MSAA sampleDescription = new SampleDescription(1, 0); // Creo swapchain SwapChain temp_swapchain; // Descripcion de SwapChain SwapChainDescription swapChainDesc = new SwapChainDescription() { BufferCount = 1, ModeDescription = new ModeDescription(SettingsManager.Current.ScreenSize.Width, SettingsManager.Current.ScreenSize.Height, refreshRate, swapChainFormat), Usage = Usage.RenderTargetOutput, OutputHandle = windowHandle, // Multisampling SampleDescription = sampleDescription, IsWindowed = SettingsManager.Current.IsWindowed, // Sin flags avanzados Flags = SwapChainFlags.None, // Descarto el backbuffer despues de presentarlo SwapEffect = SwapEffect.Discard }; SharpDX.Direct3D11.Device.CreateWithSwapChain(adapter, creationFlags, features, swapChainDesc, out temp_device, out temp_swapchain); DebugManager.LogNotice("DirectX11 Device creado"); DXDevice = temp_device; DXDeviceContext = DXDevice.ImmediateContext; swapChain = temp_swapchain; DebugManager.LogNotice("Feature Level utilizado: " + DXDevice.FeatureLevel.ToString()); // Libero la salida, el adaptador y el factory monitor.Dispose(); adapter.Dispose(); factory.Dispose(); // Puntero al backbuffer Texture2D backBuffer = Texture2D.FromSwapChain<Texture2D>(swapChain, 0); // A partir del puntero creo el render target renderTargetView = new RenderTargetView(DXDevice, backBuffer); // Libero el backBuffer backBuffer.Dispose(); // Descripcion del depth/stencil buffer Texture2DDescription depthBufferDesc = new Texture2DDescription() { Width = SettingsManager.Current.ScreenSize.Width, Height = SettingsManager.Current.ScreenSize.Height, MipLevels = 1, ArraySize = 1, Format = Format.D24_UNorm_S8_UInt, SampleDescription = sampleDescription, Usage = ResourceUsage.Default, BindFlags = BindFlags.DepthStencil, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.None }; // Creo el depth/stencil buffer a partir de la descripcion depthStencilBuffer = new Texture2D(DXDevice, depthBufferDesc); // Y creo el depth/stencil view depthStencilView = new DepthStencilView(DXDevice, depthStencilBuffer); DXDeviceContext.OutputMerger.SetTargets(depthStencilView, renderTargetView); ViewportF viewport = new ViewportF() { X = 0, Y = 0, Width = SettingsManager.Current.ScreenSize.Width, Height = SettingsManager.Current.ScreenSize.Height, MinDepth = 0, MaxDepth = 1 }; DXDeviceContext.Rasterizer.SetViewport(viewport.X, viewport.Y, viewport.Width, viewport.Height, viewport.MinDepth, viewport.MaxDepth); DebugManager.LogNotice("DX11 inicilizado!"); }
public static D3D.Texture2D CreateDepthStencilBuffer(this D3D.Device device, int width, int height, DXGI.SampleDescription sampleDescription, out D3D.DepthStencilView view) { var desc = new D3D.Texture2DDescription { Width = width, Height = height, MipLevels = 1, ArraySize = 1, Format = DXGI.Format.D24_UNorm_S8_UInt, SampleDescription = sampleDescription, Usage = D3D.ResourceUsage.Default, BindFlags = D3D.BindFlags.DepthStencil, CpuAccessFlags = D3D.CpuAccessFlags.None, OptionFlags = D3D.ResourceOptionFlags.None, }; var depthStencilBuffer = new D3D.Texture2D(device, desc); view = new D3D.DepthStencilView(device, depthStencilBuffer); return(depthStencilBuffer); }
public SwapChainDescription CreateSwapChain(int PBufferCount, Usage PUsage, IntPtr PFormHandle, bool PIsWindowed, int PModeDescriptionWidth, int PModeDescriptionHeight, Rational PModeDescriptionRefreshRate, Format PModeDescriptionFormat, int PSampleDescriptionCount, int PSampleDescriptionQuality, SwapChainFlags PSwapChainFlags, SwapEffect PSwapEffect) { this._BufferCount = PBufferCount; this._Usage = PUsage; this._FormHandle = PFormHandle; this._IsWindowed = PIsWindowed; this._ModeDescriptionWidth = PModeDescriptionWidth; this._ModeDescriptionHeight = PModeDescriptionHeight; this._ModeDescriptionRefreshRate = PModeDescriptionRefreshRate; this._ModeDescriptionFormat = PModeDescriptionFormat; this._SampleDescriptionCount = PSampleDescriptionCount; this._SampleDescriptionQuality = PSampleDescriptionQuality; this._SwapChainFlags = PSwapChainFlags; this._SwapEffect = PSwapEffect; _SampleDescription = new SampleDescription(_SampleDescriptionCount, _SampleDescriptionQuality); _ModeDescription = new ModeDescription(_ModeDescriptionWidth, _ModeDescriptionHeight, _ModeDescriptionRefreshRate, _ModeDescriptionFormat); _SwapChainDesc = new SwapChainDescription() { BufferCount = _BufferCount, Usage=_Usage, OutputHandle=_FormHandle, IsWindowed=_IsWindowed, ModeDescription=_ModeDescription, SampleDescription=_SampleDescription, Flags=_SwapChainFlags, SwapEffect=_SwapEffect }; return _SwapChainDesc; }