/// <summary> /// Binds the implementation. This is called the first time an unbound state is set to the device or manually by the user in order to /// create the underlying state ahead of time (best practice). Once called the state properties are read-only. /// </summary> public override void BindSamplerState() { if (!base.IsBound) { D3D.SamplerDescription desc = new D3D.SamplerDescription(); desc.AddressU = D3D10Helper.ToD3DTextureAddressMode(base.AddressU); desc.AddressV = D3D10Helper.ToD3DTextureAddressMode(base.AddressV); desc.AddressW = D3D10Helper.ToD3DTextureAddressMode(base.AddressW); desc.Filter = D3D10Helper.ToD3DFilter(base.Filter); //Force 1-16 range. if (base.MaxAnisotropy < 1) { base.MaxAnisotropy = 1; } else if (base.MaxAnisotropy > 16) { base.MaxAnisotropy = 16; } desc.MaximumAnisotropy = base.MaxAnisotropy; desc.MipLodBias = base.MipMapLevelOfDetailBias; //Set defaults desc.MinimumLod = 0f; desc.MaximumLod = float.MaxValue; desc.BorderColor = new SlimDX.Color4(0, 0, 0, 0); desc.ComparisonFunction = D3D.Comparison.Never; _ss = D3D.SamplerState.FromDescription(_graphicsDevice, desc); base.IsBound = true; //Add to tracker _renderer.Resources.AddTrackedObject(_ss.ComPointer, this); } }
/// <summary> /// Binds the implementation. This is called the first time an unbound state is set to the device or manually by the user in order to /// create the underlying state ahead of time (best practice). Once called the state properties are read-only. /// </summary> public override void BindBlendState() { if (!base.IsBound) { D3D.BlendStateDescription desc = new D3D.BlendStateDescription(); desc.AlphaBlendOperation = D3D10Helper.ToD3DBlendOperation(base.AlphaBlendFunction); desc.SourceAlphaBlend = D3D10Helper.ToD3DBlendOption(base.AlphaSourceBlend); desc.DestinationAlphaBlend = D3D10Helper.ToD3DBlendOption(base.AlphaDestinationBlend); desc.BlendOperation = D3D10Helper.ToD3DBlendOperation(base.ColorBlendFunction); desc.SourceBlend = D3D10Helper.ToD3DBlendOption(base.ColorSourceBlend); desc.DestinationBlend = D3D10Helper.ToD3DBlendOption(base.ColorDestinationBlend); for (int i = 0; i < 8; i++) { desc.SetBlendEnable((uint)i, this.GetBlendEnable(i)); desc.SetWriteMask((uint)i, (D3D.ColorWriteMaskFlags) this.GetWriteChannels(i)); } _bs = D3D.BlendState.FromDescription(_graphicsDevice, desc); base.IsBound = true; //Add the SlimDX object to the tracker _renderer.Resources.AddTrackedObject(_bs.ComPointer, this); } }
private void CreateViews() { _backBuffer = D3D.Resource.FromSwapChain <D3D.Texture2D>(_swapChain, 0); _renderTargetView = new D3D.RenderTargetView(_graphicsDevice, _backBuffer); //Add resources to tracker _renderer.Resources.AddTrackedObject(_backBuffer.ComPointer, this); _renderer.Resources.AddTrackedObject(_renderTargetView.ComPointer, this); if (_presentParams.DepthStencilFormat != DepthFormat.None) { D3D.Texture2DDescription depthBufferDesc = new D3D.Texture2DDescription { ArraySize = 1, BindFlags = D3D.BindFlags.DepthStencil, CpuAccessFlags = D3D.CpuAccessFlags.None, Format = D3D10Helper.ToD3DDepthFormat(_presentParams.DepthStencilFormat), Height = _presentParams.BackBufferHeight, Width = _presentParams.BackBufferWidth, MipLevels = 1, OptionFlags = D3D.ResourceOptionFlags.None, SampleDescription = _backBuffer.Description.SampleDescription, Usage = D3D.ResourceUsage.Default }; using (var depthBuffer = new D3D.Texture2D(_graphicsDevice, depthBufferDesc)) { _depthStencilView = new D3D.DepthStencilView(_graphicsDevice, depthBuffer); //Add resource to tracker _renderer.Resources.AddTrackedObject(_depthStencilView.ComPointer, this); } } }
/// <summary> /// Resizes the backbuffer. /// </summary> /// <param name="width">Width of the back buffer</param> /// <param name="height">Height of the back buffer</param> public override void Resize(int width, int height) { //Do not resize if the dimensions have not changed if (_presentParams.BackBufferHeight == height && _presentParams.BackBufferWidth == width) { return; } _resetting = true; _presentParams.BackBufferWidth = width; _presentParams.BackBufferHeight = height; //If resizing in full screen, resize the target/front buffer otherwise bad things seem to happen if (_isFullScreen) { DXGI.ModeDescription modeDesc = new DXGI.ModeDescription(); modeDesc.Format = D3D10Helper.ToD3DSurfaceFormat(_presentParams.BackBufferFormat); modeDesc.Width = width; modeDesc.Height = height; modeDesc.RefreshRate = new SDX.Rational(0, 0); _swapChain.ResizeTarget(modeDesc); } //Resize the swap chain back buffer DestroyViews(); _swapChain.ResizeBuffers(1, width, height, D3D10Helper.ToD3DSurfaceFormat(_presentParams.BackBufferFormat), DXGI.SwapChainFlags.AllowModeSwitch); CreateViews(); _resetting = false; }
/// <summary> /// Reads data from the index buffer into the array. /// </summary> /// <typeparam name="T">The type of data in the index buffer - int or short.</typeparam> /// <param name="data">Array to write the data to</param> /// <param name="startIndex">Starting index in the array at which to start writing to</param> /// <param name="elementCount">Number of indices to read</param> /// <param name="offsetInBytes">Offset from the start of the index buffer at which to start copying from</param> /// <remarks>See implementors for exceptions that may occur.</remarks> public override void GetData <T>(T[] data, int startIndex, int elementCount, int offsetInBytes) { if (_buffer == null || _buffer.Disposed) { throw new ObjectDisposedException(GetType().Name); } //Throws null or out of range exception D3D10Helper.CheckArrayBounds(data, startIndex, elementCount); int numBytes = MemoryHelper.SizeOf <T>(); int ibSize = base.IndexCount * ((base.IndexFormat == IndexFormat.SixteenBits) ? 2 : 4); int dataSize = elementCount * numBytes; if (offsetInBytes < 0 || offsetInBytes > ibSize) { throw new ArgumentOutOfRangeException("offsetInBytes", "Byte offset is out of range."); } if ((offsetInBytes + dataSize) > ibSize) { throw new ArgumentOutOfRangeException("data", "Byte offset and the number of elements to read will cause a buffer overflow."); } CreateStaging(); try { //If we're reading from the entire VB just copy the whole thing if (offsetInBytes == 0 && startIndex == 0 && dataSize == ibSize) { _graphicsDevice.CopyResource(_buffer, _staging); } else { D3D.ResourceRegion region = new D3D.ResourceRegion(); region.Left = offsetInBytes; region.Right = offsetInBytes + dataSize; region.Front = region.Top = 0; region.Back = region.Bottom = 1; _graphicsDevice.CopySubresourceRegion(_buffer, 0, region, _staging, 0, offsetInBytes, 0, 0); } using (SDX.DataStream ds = _staging.Map(D3D.MapMode.Read, D3D.MapFlags.None)) { ds.Position = offsetInBytes; ds.ReadRange <T>(data, startIndex, elementCount); _staging.Unmap(); } } catch (Exception e) { throw new TeslaException("Error reading from D3D10 Buffer.", e); } }
/// <summary> /// Toggles the swap chain to full screen mode. /// </summary> public override void ToggleFullScreen() { _resetting = true; _isFullScreen = !_isFullScreen; _swapChain.IsFullScreen = _isFullScreen; //Resize targets if (_isFullScreen) { DXGI.ModeDescription modeDesc = new DXGI.ModeDescription(); modeDesc.Format = D3D10Helper.ToD3DSurfaceFormat(_presentParams.BackBufferFormat); modeDesc.Width = _presentParams.BackBufferWidth; modeDesc.Height = _presentParams.BackBufferHeight; modeDesc.RefreshRate = new SDX.Rational(0, 0); _swapChain.ResizeTarget(modeDesc); } _resetting = false; }
/// <summary> /// Binds the implementation. This is called the first time an unbound state is set to the device or manually by the user in order to /// create the underlying state ahead of time (best practice). Once called the state properties are read-only. /// </summary> public override void BindDepthStencilState() { if (!base.IsBound) { D3D.DepthStencilStateDescription desc = new D3D.DepthStencilStateDescription(); desc.DepthWriteMask = (base.DepthWriteEnable) ? D3D.DepthWriteMask.All : D3D.DepthWriteMask.Zero; desc.DepthComparison = D3D10Helper.ToD3DComparison(base.DepthFunction); desc.IsDepthEnabled = base.DepthEnable; desc.IsStencilEnabled = base.StencilEnable; desc.StencilWriteMask = (byte)base.StencilWriteMask; desc.StencilReadMask = (byte)base.StencilReadMask; //Set front facing stencil op D3D.DepthStencilOperationDescription opDesc = new D3D.DepthStencilOperationDescription(); opDesc.Comparison = D3D10Helper.ToD3DComparison(base.StencilFunction); opDesc.DepthFailOperation = D3D10Helper.ToD3DStencilOperation(base.StencilDepthFail); opDesc.FailOperation = D3D10Helper.ToD3DStencilOperation(base.StencilFail); opDesc.PassOperation = D3D10Helper.ToD3DStencilOperation(base.StencilPass); desc.FrontFace = opDesc; D3D.DepthStencilOperationDescription ccwopDesc = new D3D.DepthStencilOperationDescription(); //Set back facing stencil op if enabled, otherwise enforced defaults if (base.TwoSidedStencilEnable) { ccwopDesc.Comparison = D3D10Helper.ToD3DComparison(base.CounterClockwiseStencilFunction); ccwopDesc.DepthFailOperation = D3D10Helper.ToD3DStencilOperation(base.CounterClockwiseStencilDepthFail); ccwopDesc.FailOperation = D3D10Helper.ToD3DStencilOperation(base.CounterClockwiseStencilFail); ccwopDesc.PassOperation = D3D10Helper.ToD3DStencilOperation(base.CounterClockwiseStencilPass); } else { ccwopDesc.Comparison = D3D.Comparison.Always; ccwopDesc.DepthFailOperation = D3D.StencilOperation.Keep; ccwopDesc.FailOperation = D3D.StencilOperation.Keep; ccwopDesc.PassOperation = D3D.StencilOperation.Keep; } desc.BackFace = ccwopDesc; _ds = D3D.DepthStencilState.FromDescription(_graphicsDevice, desc); base.IsBound = true; _renderer.Resources.AddTrackedObject(_ds.ComPointer, this); } }
private void CreateStaging() { if (_staging == null) { D3D.Texture1DDescription desc = new D3D.Texture1DDescription(); desc.ArraySize = 1; desc.BindFlags = D3D.BindFlags.None; desc.CpuAccessFlags = D3D.CpuAccessFlags.Write | D3D.CpuAccessFlags.Read; desc.Format = D3D10Helper.ToD3DSurfaceFormat(base.Format); desc.Width = base.Width; desc.MipLevels = _mipCount; desc.Usage = D3D.ResourceUsage.Staging; _staging = new D3D.Texture1D(_graphicsDevice, desc); //Add to tracker _renderer.Resources.AddTrackedObject(_staging.ComPointer, this); } }
/// <summary> /// Sets the swapchain's backbuffer as the active render target and clears it. /// </summary> /// <param name="options">Clear option flags defining which buffer to clear.</param> /// <param name="color">Color to clear the color buffer to</param> /// <param name="depth">Depth value to clear the depth buffer to</param> /// <param name="stencil">Stencil value to clear the stencil buffer to</param> public override void Clear(ClearOptions options, Color color, float depth, int stencil) { if (_resetting) { return; } SlimDX.Color4 sc; D3D10Helper.Convert(ref color, out sc); _renderer.TargetManager.SetActiveSwapChain(this); if (_depthStencilView != null) { _graphicsDevice.OutputMerger.SetTargets(_depthStencilView, _renderTargetView); if (((options & ClearOptions.Depth) == ClearOptions.Depth) && ((options & ClearOptions.Stencil) == ClearOptions.Stencil)) { _graphicsDevice.ClearDepthStencilView(_depthStencilView, D3D.DepthStencilClearFlags.Depth | D3D.DepthStencilClearFlags.Stencil, depth, (byte)stencil); } else if ((options & ClearOptions.Depth) == ClearOptions.Depth) { _graphicsDevice.ClearDepthStencilView(_depthStencilView, D3D.DepthStencilClearFlags.Depth, depth, (byte)stencil); } else if ((options & ClearOptions.Stencil) == ClearOptions.Stencil) { _graphicsDevice.ClearDepthStencilView(_depthStencilView, D3D.DepthStencilClearFlags.Stencil, depth, (byte)stencil); } if ((options & ClearOptions.Target) == ClearOptions.Target) { _graphicsDevice.ClearRenderTargetView(_renderTargetView, sc); } } else { _graphicsDevice.OutputMerger.SetTargets(_renderTargetView); if ((options & ClearOptions.Target) == ClearOptions.Target) { _graphicsDevice.ClearRenderTargetView(_renderTargetView, sc); } } }
/// <summary> /// Binds the implementation. This is called the first time an unbound state is set to the device or manually by the user in order to /// create the underlying state ahead of time (best practice). Once called the state properties are read-only. /// </summary> public override void BindRasterizerState() { if (!base.IsBound) { D3D.RasterizerStateDescription desc = new D3D.RasterizerStateDescription(); desc.CullMode = D3D10Helper.ToD3DCullMode(base.Cull); desc.FillMode = D3D10Helper.ToD3DFillMode(base.Fill); desc.IsMultisampleEnabled = base.EnableMultiSampleAntiAlias; desc.SlopeScaledDepthBias = base.SlopeScaledDepthBias; desc.DepthBias = base.DepthBias; desc.DepthBiasClamp = 100.0f; //TODO: Whats a good number here? desc.IsFrontCounterclockwise = (base.VertexWinding == VertexWinding.CounterClockwise) ? true : false; desc.IsScissorEnabled = base.EnableScissorTest; desc.IsAntialiasedLineEnabled = base.EnableMultiSampleAntiAlias; _rs = D3D.RasterizerState.FromDescription(_graphicsDevice, desc); base.IsBound = true; //Add to tracker _renderer.Resources.AddTrackedObject(_rs.ComPointer, this); } }
/// <summary> /// Sets the data from the texture. /// </summary> /// <typeparam name="T">Type of data in the array</typeparam> /// <param name="data">The array of data</param> /// <param name="mipLevel">Mip map level to read from</param> /// <param name="left">Right-most width position in the texture at which to acess. (0 or greater)</param> /// <param name="right">Right-most width position in the texture at which to acess. (width or less)</param> /// <param name="top">Top-most height position in the texture at which to acess. (0 or greater)</param> /// <param name="bottom">Bottom-most height position in the texture at which to acess. (height or less)</param> /// <param name="front">Front-most depth position in the texture at which to acess. (0 or greater)</param> /// <param name="back">Back-most depth position in the texture at which to acess. (depth or less)</param> /// <param name="startIndex">Starting index in the array to start reading from.</param> /// <param name="elementCount">Number of elements to write.</param> /// <exception cref="System.ArgumentException">Thrown if the format byte size of the type to write and the texture do not match, the subimage /// dimensions are invalid, or if the total size to write and the total size in the texture do not match</exception> /// <exception cref="Tesla.Core.TeslaException">Thrown if there was an error writing to the texture.</exception> public override void SetData <T>(T[] data, int mipLevel, int left, int right, int top, int bottom, int front, int back, int startIndex, int elementCount) { if (_texture3D == null || _texture3D.Disposed) { throw new ObjectDisposedException(GetType().Name); } if (mipLevel < 0 || mipLevel >= _mipCount) { throw new ArgumentOutOfRangeException("mipLevel", String.Format("Mip level is out of range. Must be between 0 and {0}.", _mipCount.ToString())); } //Throws null or out of range exception D3D10Helper.CheckArrayBounds(data, startIndex, elementCount); int formatSize = D3D10Helper.FormatSize(base.Format); int elemSize = MemoryHelper.SizeOf <T>(); CheckSizes(formatSize, elemSize); //Calc subresource dimensions int width = (int)MathHelper.Max(1, base.Width >> mipLevel); int height = (int)MathHelper.Max(1, base.Height >> mipLevel); int depth = (int)MathHelper.Max(1, base.Depth >> mipLevel); //Ensure box dimensions CheckBox(left, right, top, bottom, front, back, ref width, ref height, ref depth); CheckTotalSize(base.Format, ref formatSize, ref width, ref height, ref depth, elemSize, elementCount); //Create staging for non-dynamic textures if (_usage == D3D.ResourceUsage.Default) { CreateStaging(); } try { if (_usage == D3D.ResourceUsage.Default) { SDX.DataBox dataBox = _staging.Map(mipLevel, D3D.MapMode.Write, D3D.MapFlags.None); SDX.DataStream ds = dataBox.Data; int row = left; int col = top; int slice = front; int rowPitch = dataBox.RowPitch; int slicePitch = dataBox.SlicePitch; int index = startIndex; int count = elementCount; //Compute the actual number of elements based on the format size and the element size we're copying the bytes into int actWidth = (int)MathHelper.Floor(width * (formatSize / elemSize)); //Go slice by slice for (int k = slice; k < back; k++) { //Go row by row for (int i = row; i < bottom; i++) { //Set the position ds.Position = (k * slicePitch) + (i * rowPitch) + (col * formatSize); //Break if we've run out of elements or on the very last row that isn't complete if (count <= 0) { break; } else if (count < actWidth) { ds.WriteRange <T>(data, index, count); break; } //Otherwise, copy the whole row and increment/decrement the index and count ds.WriteRange <T>(data, index, actWidth); index += actWidth; count -= actWidth; } } _staging.Unmap(mipLevel); //Do resource copy if (base.Format == SurfaceFormat.DXT1 || base.Format == SurfaceFormat.DXT3 || base.Format == SurfaceFormat.DXT5) { _graphicsDevice.CopyResource(_staging, _texture3D); } else { D3D.ResourceRegion region = new D3D.ResourceRegion(); region.Left = col; region.Right = right; region.Top = row; region.Bottom = bottom; region.Front = slice; region.Back = back; _graphicsDevice.CopySubresourceRegion(_staging, mipLevel, region, _texture3D, mipLevel, col, row, slice); } } else { SDX.DataBox dataBox = _texture3D.Map(mipLevel, D3D.MapMode.Write, D3D.MapFlags.None); SDX.DataStream ds = dataBox.Data; int row = left; int col = top; int slice = front; int rowPitch = dataBox.RowPitch; int slicePitch = dataBox.SlicePitch; int index = startIndex; int count = elementCount; //Compute the actual number of elements based on the format size and the element size we're copying the bytes into int actWidth = (int)MathHelper.Floor(width * (formatSize / elemSize)); //Go slice by slice for (int k = slice; k < back; k++) { //Go row by row for (int i = row; i < bottom; i++) { //Set the position ds.Position = (k * slicePitch) + (i * rowPitch) + (col * formatSize); //Break if we've run out of elements or on the very last row that isn't complete if (count <= 0) { break; } else if (count < actWidth) { ds.WriteRange <T>(data, index, count); break; } //Otherwise, copy the whole row and increment/decrement the index and count ds.WriteRange <T>(data, index, actWidth); index += actWidth; count -= actWidth; } } _texture3D.Unmap(mipLevel); } } catch (Exception e) { throw new TeslaException("Error writing to D3D10 Texture3D.", e); } }
/// <summary> /// Gets the back buffer data. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="subimage">The rectangle representing the sub-image. Null value means to grab the whole back buffer.</param> /// <param name="data">The data.</param> /// <param name="startIndex">The starting index in the array.</param> /// <param name="elementCount">The number of eleemnts to read</param> public override void GetBackBufferData <T>(Rectangle?subimage, T[] data, int startIndex, int elementCount) { if (_backBuffer.Disposed) { throw new ObjectDisposedException(GetType().Name); } //Throws null or out of range exception D3D10Helper.CheckArrayBounds(data, startIndex, elementCount); //Calc subresource dimensions int width = _presentParams.BackBufferWidth; int height = _presentParams.BackBufferHeight; //Get the dimensions, if its null we copy the whole texture Rectangle rect; if (subimage.HasValue) { rect = subimage.Value; CheckRectangle(rect, width, height); } else { rect = new Rectangle(0, 0, width, height); } if (elementCount > rect.Width * rect.Height) { throw new ArgumentOutOfRangeException("elementCount", "Number of elements to read is larger than contained in the specified subimage."); } //Create staging CreateStaging(); try { int row = rect.Y; int col = rect.X; int rectWidth = rect.Width; int rectHeight = rect.Height; //Do resource copy if (row == 0 && col == 0 && rectWidth == width && rectHeight == height) { _graphicsDevice.CopyResource(_backBuffer, _staging); } else { D3D.ResourceRegion region = new D3D.ResourceRegion(); region.Left = col; region.Right = col + rectWidth; region.Top = row; region.Bottom = row + rectHeight; region.Front = 0; region.Back = 1; _graphicsDevice.CopySubresourceRegion(_backBuffer, 0, region, _staging, 0, col, row, 0); } SDX.DataRectangle dataRect = _staging.Map(0, D3D.MapMode.Read, D3D.MapFlags.None); SDX.DataStream ds = dataRect.Data; int elemSize = MemoryHelper.SizeOf <T>(); int formatSize = D3D10Helper.FormatSize(_presentParams.BackBufferFormat); int pitch = dataRect.Pitch; int index = startIndex; int count = elementCount; //Compute the actual number of elements based on the format size and the element size we're copying the bytes into int actWidth = (int)MathHelper.Floor(rectWidth * (formatSize / elemSize)); //Go row by row for (int i = row; i < height; i++) { //Set the position ds.Position = (i * pitch) + (col * formatSize); //Break if we've run out of elements or on the very last row that isn't complete if (count <= 0) { break; } else if (count < actWidth) { ds.ReadRange <T>(data, index, count); break; } //Otherwise, copy the whole row and increment/decrement the index and count ds.ReadRange <T>(data, index, actWidth); index += actWidth; count -= actWidth; } _staging.Unmap(0); } catch (Exception e) { throw new TeslaException("Error reading from D3D10 Texture2D.", e); } }
/// <summary> /// Sets the data to the texture. /// </summary> /// <typeparam name="T">Type of data in the array.</typeparam> /// <param name="data">Array of data.</param> /// <param name="mipLevel">Mip map level to access.</param> /// <param name="subimage">Rectangle representing a sub-image of the 2D texture to write to, if null the whole image is written to.</param> /// <param name="startIndex">Starting index in the array to start reading from.</param> /// <param name="elementCount">Number of elements to write.</param> /// <exception cref="System.ArgumentException">Thrown if the format byte size of the type to write and the texture do not match, the subimage /// dimensions are invalid, or if the total size to write and the total size in the texture do not match</exception> /// <exception cref="Tesla.Core.TeslaException">Thrown if there was an error writing to the texture.</exception> public override void SetData <T>(T[] data, int mipLevel, Math.Rectangle?subimage, int startIndex, int elementCount) { if (_texture2D == null || _texture2D.Disposed) { throw new ObjectDisposedException(GetType().Name); } if (mipLevel < 0 || mipLevel >= _mipCount) { throw new ArgumentOutOfRangeException("mipLevel", String.Format("Mip level is out of range. Must be between 0 and {0}.", _mipCount.ToString())); } //Throws null or out of range exception D3D10Helper.CheckArrayBounds(data, startIndex, elementCount); int formatSize = D3D10Helper.FormatSize(base.Format); SurfaceFormat format = base.Format; int elemSize = MemoryHelper.SizeOf <T>(); CheckSizes(formatSize, elemSize); //Calc subresource dimensions int width = (int)MathHelper.Max(1, base.Width >> mipLevel); int height = (int)MathHelper.Max(1, base.Height >> mipLevel); //Get the dimensions, if its null we copy the whole texture Rectangle rect; if (subimage.HasValue) { rect = subimage.Value; CheckRectangle(rect, ref width, ref height); } else { rect = new Rectangle(0, 0, width, height); } CheckTotalSize(base.Format, ref formatSize, ref width, ref height, elemSize, elementCount); //Create staging for non-dynamic textures if (_usage == D3D.ResourceUsage.Default) { CreateStaging(); } try { if (_usage == D3D.ResourceUsage.Default) { SDX.DataRectangle dataRect = _staging.Map(mipLevel, D3D.MapMode.Write, D3D.MapFlags.None); SDX.DataStream ds = dataRect.Data; int row = rect.Y; int col = rect.X; int pitch = dataRect.Pitch; int index = startIndex; int count = elementCount; //Compute the actual number of elements based on the format size and the element size we're copying the bytes into int actWidth = (int)MathHelper.Floor(width * (formatSize / elemSize)); //Go row by row for (int i = row; i < height; i++) { //Set the position ds.Position = (i * pitch) + (col * formatSize); //Break if we've run out of elements or on the very last row that isn't complete if (count <= 0) { break; } else if (count < actWidth) { ds.WriteRange <T>(data, index, count); break; } //Otherwise, copy the whole row and increment/decrement the index and count ds.WriteRange <T>(data, index, actWidth); index += actWidth; count -= actWidth; } _staging.Unmap(mipLevel); //Do resource copy if (format == SurfaceFormat.DXT1 || format == SurfaceFormat.DXT3 || format == SurfaceFormat.DXT5) { _graphicsDevice.CopyResource(_staging, _texture2D); } else { D3D.ResourceRegion region = new D3D.ResourceRegion(); region.Left = col; region.Right = col + width; region.Top = row; region.Bottom = row + height; region.Front = 0; region.Back = 1; _graphicsDevice.CopySubresourceRegion(_staging, mipLevel, region, _texture2D, mipLevel, col, row, 0); } } else { SDX.DataRectangle dataRect = _texture2D.Map(mipLevel, D3D.MapMode.WriteDiscard, D3D.MapFlags.None); SDX.DataStream ds = dataRect.Data; int row = rect.Y; int col = rect.X; int pitch = dataRect.Pitch; int index = startIndex; int count = elementCount; //Compute the actual number of elements based on the format size and the element size we're copying the bytes into int actWidth = (int)MathHelper.Floor(width * (formatSize / elemSize)); //Go row by row for (int i = row; i < height; i++) { //Set the position ds.Position = (i * pitch) + (col * formatSize); //Break if we've run out of elements or on the very last row that isn't complete if (count <= 0) { break; } else if (count < actWidth) { ds.WriteRange <T>(data, index, count); break; } //Otherwise, copy the whole row and increment/decrement the index and count ds.WriteRange <T>(data, index, actWidth); index += actWidth; count -= actWidth; } _texture2D.Unmap(mipLevel); } } catch (Exception e) { throw new TeslaException("Error writing to D3D10 Texture2D.", e); } }
/// <summary> /// Creates a new instance of <see cref="D3D10TextureCubeImplementation"/>. /// </summary> /// <param name="renderer">The D3D10 renderer.</param> /// <param name="size">The size (width/height) of each cube face.</param> /// <param name="genMipMaps">True if a mipmap chain should be generated or not.</param> /// <param name="format">The surface format.</param> /// <param name="depthFormat">The depth-stencil format.</param> /// <param name="multiSampleCount">The number of sample locations for multisampling</param> /// <param name="usage">Sets the render target's behavior.</param> internal D3D10TextureCubeImplementation(D3D10Renderer renderer, int size, bool genMipMaps, SurfaceFormat format, DepthFormat depthFormat, int multiSampleCount, RenderTargetUsage usage) : base(size, format, depthFormat, multiSampleCount, usage) { _renderer = renderer; _graphicsDevice = _renderer.GraphicsDevice; if (!renderer.Adapter.QueryRenderTargetFormat(format, depthFormat, multiSampleCount)) { throw new ArgumentException("Format combination not supported."); } D3D.Texture2DDescription desc2D = new D3D.Texture2DDescription(); desc2D.ArraySize = 6; desc2D.BindFlags = D3D.BindFlags.ShaderResource | D3D.BindFlags.RenderTarget; desc2D.CpuAccessFlags = D3D.CpuAccessFlags.None; desc2D.Format = D3D10Helper.ToD3DSurfaceFormat(format); desc2D.Height = size; desc2D.Width = size; desc2D.Usage = D3D.ResourceUsage.Default; if (genMipMaps) { desc2D.OptionFlags = D3D.ResourceOptionFlags.GenerateMipMaps | D3D.ResourceOptionFlags.TextureCube; } else { desc2D.OptionFlags = D3D.ResourceOptionFlags.TextureCube; } desc2D.MipLevels = (genMipMaps) ? 0 : 1; if (multiSampleCount > 1) { desc2D.SampleDescription = new SlimDX.DXGI.SampleDescription(multiSampleCount, 0); } else { desc2D.SampleDescription = new DXGI.SampleDescription(1, 0); } //Create the resources _texture2D = new D3D.Texture2D(_graphicsDevice, desc2D); _shaderResourceView = new D3D.ShaderResourceView(_graphicsDevice, _texture2D); _renderTargetView = new D3D.RenderTargetView[6]; //Add to tracker _renderer.Resources.AddTrackedObject(_texture2D.ComPointer, this); _renderer.Resources.AddTrackedObject(_shaderResourceView.ComPointer, this); //Setup each render target view for each face for (int i = 0; i < 6; i++) { D3D.RenderTargetViewDescription rtDesc = new D3D.RenderTargetViewDescription(); rtDesc.ArraySize = 1; rtDesc.FirstArraySlice = i; if (multiSampleCount > 1) { rtDesc.Dimension = D3D.RenderTargetViewDimension.Texture2DMultisampledArray; } else { rtDesc.Dimension = D3D.RenderTargetViewDimension.Texture2DArray; } rtDesc.Format = desc2D.Format; _renderTargetView[i] = new D3D.RenderTargetView(_graphicsDevice, _texture2D, rtDesc); _graphicsDevice.ClearRenderTargetView(_renderTargetView[i], new SDX.Color4(1.0f, 0, 0, 0)); _renderer.Resources.AddTrackedObject(_renderTargetView[i].ComPointer, this); } _mipCount = _texture2D.Description.MipLevels; if (depthFormat != DepthFormat.None) { D3D.Texture2DDescription dbdesc = new D3D.Texture2DDescription(); dbdesc.ArraySize = 6; dbdesc.BindFlags = D3D.BindFlags.DepthStencil; dbdesc.CpuAccessFlags = D3D.CpuAccessFlags.None; dbdesc.Format = D3D10Helper.ToD3DDepthFormat(depthFormat); dbdesc.Height = size; dbdesc.Width = size; dbdesc.Usage = D3D.ResourceUsage.Default; dbdesc.OptionFlags = D3D.ResourceOptionFlags.None; dbdesc.MipLevels = 1; if (multiSampleCount > 1) { dbdesc.SampleDescription = new SlimDX.DXGI.SampleDescription(multiSampleCount, 0); } else { dbdesc.SampleDescription = new SlimDX.DXGI.SampleDescription(1, 0); } using (D3D.Texture2D depthBuffer = new D3D.Texture2D(_graphicsDevice, dbdesc)) { _depthStencilView = new D3D.DepthStencilView(_graphicsDevice, depthBuffer); if (depthFormat == Tesla.Graphics.DepthFormat.Depth24Stencil8) { _graphicsDevice.ClearDepthStencilView(_depthStencilView, D3D.DepthStencilClearFlags.Depth | D3D.DepthStencilClearFlags.Stencil, 1.0f, 0); } else { _graphicsDevice.ClearDepthStencilView(_depthStencilView, D3D.DepthStencilClearFlags.Depth, 1.0f, 0); } //Add to tracker _renderer.Resources.AddTrackedObject(_depthStencilView.ComPointer, this); } } }
/// <summary> /// Creates a new instance of <see cref="D3D10TextureCubeImplementation"/>. /// </summary> /// <param name="renderer">D3D10 renderer</param> /// <param name="size">The size (width/height) of each cube face.</param> /// <param name="genMipMaps">True if mip levels should be generated.</param> /// <param name="format">The surface format.</param> /// <param name="data">The initial data for the first mip level.</param> /// <exception cref="System.ArgumentException">Thrown if the data buffery array does not correspond to a valid cube map (6 faces, all the same size)</exception> /// <exception cref="Tesla.Core.TeslaException">Thrown if there was an error writing to the texture.</exception> internal D3D10TextureCubeImplementation(D3D10Renderer renderer, int size, bool genMipMaps, SurfaceFormat format, DataBuffer[] data) : base(size, format) { //Set the common properties _renderer = renderer; _graphicsDevice = _renderer.GraphicsDevice; //Do we want to generate mip maps, and do we have the data to do so? (if not, cancel mip map generation) bool canGenMipmaps = (genMipMaps && (data != null)); //Setup texture description D3D.Texture2DDescription descTex = new D3D.Texture2DDescription(); descTex.ArraySize = 6; descTex.Width = size; descTex.Height = size; descTex.Usage = _usage = D3D.ResourceUsage.Default; descTex.CpuAccessFlags = D3D.CpuAccessFlags.None; descTex.Format = D3D10Helper.ToD3DSurfaceFormat(format); descTex.SampleDescription = new DXGI.SampleDescription(1, 0); descTex.MipLevels = (genMipMaps) ? 0 : 1; //Set mip map generation params if (canGenMipmaps) { descTex.BindFlags = D3D.BindFlags.ShaderResource | D3D.BindFlags.RenderTarget; descTex.OptionFlags = D3D.ResourceOptionFlags.GenerateMipMaps | D3D.ResourceOptionFlags.TextureCube; } else { descTex.BindFlags = D3D.BindFlags.ShaderResource; descTex.OptionFlags = D3D.ResourceOptionFlags.TextureCube; } //Create the texture and shader view _texture2D = new D3D.Texture2D(_graphicsDevice, descTex); _shaderResourceView = new D3D.ShaderResourceView(_graphicsDevice, _texture2D); //Add to tracker _renderer.Resources.AddTrackedObject(_texture2D.ComPointer, this); _renderer.Resources.AddTrackedObject(_shaderResourceView.ComPointer, this); //Set the final mip count _mipCount = _texture2D.Description.MipLevels; //Now set the initial data if its present if (data != null) { if (data.Length != 6) { Dispose(); throw new ArgumentException("Initial data array must have six data buffers, one for each cube face."); } int num = data[0].Length; for (int i = 1; i < 6; i++) { if (data[i].Length != num) { Dispose(); throw new ArgumentException("All data buffers must be of same length"); } } try { for (int i = 0; i < 6; i++) { DataBuffer db = data[i]; this.SetData <byte>((CubeMapFace)i, db.ByteDataCopy, 0, null, 0, db.ElementSizeInBytes * db.Length); } if (genMipMaps) { _graphicsDevice.GenerateMips(_shaderResourceView); } //Dispose of the staging texture if (_staging != null) { _staging.Dispose(); _staging = null; } } catch (Exception e) { Dispose(); throw new TeslaException("Error setting Texture data.", e); } } }
/// <summary> /// Sets the data from the array to the texture. /// </summary> /// <typeparam name="T">Type of data in the array.</typeparam> /// <param name="data">Array of data</param> /// <param name="mipLevel">Mip map level to access</param> /// <param name="left">The left-most position in the 1D texture at which to access.</param> /// <param name="right">The right-most position in the 1D texture at which to acess.</param> /// <param name="startIndex">Starting index in the array to start reading from.</param> /// <param name="elementCount">Number of elements to write.</param> public override void SetData <T>(T[] data, int mipLevel, int left, int right, int startIndex, int elementCount) { if (_texture1D.Disposed) { throw new ObjectDisposedException(GetType().Name); } if (mipLevel < 0 || mipLevel >= _mipCount) { throw new ArgumentOutOfRangeException("mipLevel", String.Format("Mip level is out of range. Must be between 0 and {0}.", _mipCount.ToString())); } //Throws null or out of range exception D3D10Helper.CheckArrayBounds(data, startIndex, elementCount); SurfaceFormat format = base.Format; int formatSize = D3D10Helper.FormatSize(format); int elemSize = MemoryHelper.SizeOf <T>(); CheckSizes(formatSize, elemSize); //Calc subresource dimensions int width = (int)MathHelper.Max(1, base.Width >> mipLevel); //Check the line CheckLine(ref width, left, right); CheckTotalSize(format, ref formatSize, ref width, elemSize, elementCount); //Create staging if (_usage == D3D.ResourceUsage.Default) { CreateStaging(); } try { if (_usage == D3D.ResourceUsage.Default) { SDX.DataStream ds = _staging.Map(mipLevel, D3D.MapMode.Write, D3D.MapFlags.None); //Compute the actual number of elements based on the format size and the element size we're copying the bytes into int actWidth = (int)MathHelper.Floor(width * (formatSize / elemSize)); //Read data ds.Position = left * formatSize; ds.WriteRange <T>(data, startIndex, actWidth); _staging.Unmap(mipLevel); //Copy from the staging to texture if (format == SurfaceFormat.DXT1 || format == SurfaceFormat.DXT3 || format == SurfaceFormat.DXT5) { _graphicsDevice.CopyResource(_staging, _texture1D); } else { D3D.ResourceRegion region = new D3D.ResourceRegion(); region.Left = left; region.Right = right; region.Top = 0; region.Bottom = 1; region.Front = 0; region.Back = 1; _graphicsDevice.CopySubresourceRegion(_staging, mipLevel, region, _texture1D, mipLevel, left, 0, 0); } } else { SDX.DataStream ds = _texture1D.Map(mipLevel, D3D.MapMode.WriteDiscard, D3D.MapFlags.None); //Compute the actual number of elements based on the format size and the element size we're copying the bytes into int actWidth = (int)MathHelper.Floor(width * (formatSize / elemSize)); //Read data ds.Position = left * formatSize; ds.WriteRange <T>(data, startIndex, actWidth); _texture1D.Unmap(mipLevel); } } catch (Exception e) { throw new TeslaException("Error writing to D3D10 Texture1D.", e); } }
/// <summary> /// Writes data from the array to the index buffer. /// </summary> /// <typeparam name="T">The type of data in the index buffer - int or short.</typeparam> /// <param name="data">Array to copy the data from</param> /// <param name="startIndex">Starting index in the array at which to start copying from</param> /// <param name="elementCount">Number of indices to write</param> /// <param name="offsetInBytes">Offset from the start of the index buffer at which to start writing at</param> /// <param name="writeOptions">Write options, used only if this is a dynamic buffer. None, discard, no overwrite</param> /// <remarks>See implementors for exceptions that may occur.</remarks> public override void SetData <T>(T[] data, int startIndex, int elementCount, int offsetInBytes, DataWriteOptions writeOptions) { if (_buffer == null || _buffer.Disposed) { throw new ObjectDisposedException(GetType().Name); } //Throws null or out of range exception D3D10Helper.CheckArrayBounds(data, startIndex, elementCount); int numBytes = MemoryHelper.SizeOf <T>(); int ibSize = base.IndexCount * ((base.IndexFormat == IndexFormat.SixteenBits) ? 2 : 4); int dataSize = elementCount * numBytes; if (offsetInBytes < 0 || offsetInBytes > ibSize) { throw new ArgumentOutOfRangeException("offsetInBytes", "Byte offset is out of range."); } if ((offsetInBytes + dataSize) > ibSize) { throw new ArgumentOutOfRangeException("data", "Byte offset and the number of elements to write will cause a buffer overflow."); } bool usesStaging = false; if (base.BufferUsage == ResourceUsage.Static || writeOptions == DataWriteOptions.None) { CreateStaging(); usesStaging = true; } try { if (usesStaging) { using (SDX.DataStream ds = _staging.Map(D3D.MapMode.Write, D3D.MapFlags.None)) { ds.Position = offsetInBytes; ds.WriteRange <T>(data, startIndex, elementCount); _staging.Unmap(); //If we're writing to the entire IB just copy the whole thing if (offsetInBytes == 0 && startIndex == 0 && dataSize == ibSize) { _graphicsDevice.CopyResource(_staging, _buffer); } else { D3D.ResourceRegion region = new D3D.ResourceRegion(); region.Left = offsetInBytes; region.Right = offsetInBytes + dataSize; region.Front = region.Top = 0; region.Back = region.Bottom = 1; _graphicsDevice.CopySubresourceRegion(_staging, 0, region, _buffer, 0, offsetInBytes, 0, 0); } } } else { D3D.MapMode mode = (writeOptions == DataWriteOptions.Discard) ? D3D.MapMode.WriteDiscard : D3D.MapMode.WriteNoOverwrite; using (SDX.DataStream ds = _buffer.Map(mode, D3D.MapFlags.None)) { ds.Position = offsetInBytes; ds.WriteRange <T>(data, startIndex, elementCount); _buffer.Unmap(); } } } catch (Exception e) { throw new TeslaException("Error writing to D3D10 Buffer.", e); } }
/// <summary> /// Creates a new instance of <see cref="D3D10Texture2DImplementation"/>, for Texture2D. /// </summary> /// <param name="renderer">The D3D10 renderer.</param> /// <param name="width">The texture width in pixels.</param> /// <param name="height">The texture height in pixels.</param> /// <param name="genMipMaps">True if a mipmap chain should be generated or not.</param> /// <param name="format">The surface format.</param> /// <param name="data">The data to initialize the first mip map level.</param> /// <exception cref="Tesla.Core.TeslaException">Thrown if there was an error writing to the texture.</exception> internal D3D10Texture2DImplementation(D3D10Renderer renderer, int width, int height, bool genMipMaps, SurfaceFormat format, DataBuffer data) : base(width, height, format) { //Set common properties _renderer = renderer; _graphicsDevice = _renderer.GraphicsDevice; //Do we want to generate mip maps, and do we have the data to do so? (if not, cancel mip map generation) bool canGenMipmaps = (genMipMaps && (data != null)); //Setup texture description D3D.Texture2DDescription descTex = new D3D.Texture2DDescription(); descTex.ArraySize = 1; descTex.Width = width; descTex.Height = height; descTex.Usage = _usage = D3D.ResourceUsage.Default; descTex.CpuAccessFlags = D3D.CpuAccessFlags.None; descTex.Format = D3D10Helper.ToD3DSurfaceFormat(format); descTex.SampleDescription = new DXGI.SampleDescription(1, 0); //Default sample desc descTex.MipLevels = (genMipMaps) ? 0 : 1; //Set mip map generation params if (canGenMipmaps) { descTex.BindFlags = D3D.BindFlags.ShaderResource | D3D.BindFlags.RenderTarget; descTex.OptionFlags = D3D.ResourceOptionFlags.GenerateMipMaps; } else { descTex.BindFlags = D3D.BindFlags.ShaderResource; descTex.OptionFlags = D3D.ResourceOptionFlags.None; } //Create the texture and shader view _texture2D = new D3D.Texture2D(_graphicsDevice, descTex); _shaderResourceView = new D3D.ShaderResourceView(_graphicsDevice, _texture2D); //Add to tracker _renderer.Resources.AddTrackedObject(_texture2D.ComPointer, this); _renderer.Resources.AddTrackedObject(_shaderResourceView.ComPointer, this); //Set the final mip count _mipCount = _texture2D.Description.MipLevels; //Now set the initial data if its present if (data != null) { try { this.SetData <byte>(data.ByteDataCopy, 0, null, 0, data.ElementSizeInBytes * data.Length); if (genMipMaps) { _graphicsDevice.GenerateMips(_shaderResourceView); } //Dispose of the staging texture if (_staging != null) { _staging.Dispose(); _staging = null; } } catch (Exception e) { Dispose(); throw new TeslaException("Error setting Texture data.", e); } } }
/// <summary> /// Creates a new instance of <see cref="D3D10Texture2DImplementation"/>, for RenderTarget2D. /// </summary> /// <param name="renderer">The D3D10 renderer.</param> /// <param name="width">The texture width in pixels.</param> /// <param name="height">The texture height in pixels.</param> /// <param name="genMipMaps">True if a mipmap chain should be generated or not.</param> /// <param name="format">The surface format.</param> /// <param name="depthFormat">The depth-stencil format.</param> /// <param name="multiSampleCount">The multisample count.</param> /// <param name="usage">The target usage.</param> /// <exception cref="System.ArgumentException">Thrown if the formats are invalid to be used in a render target.</exception> internal D3D10Texture2DImplementation(D3D10Renderer renderer, int width, int height, bool genMipMaps, SurfaceFormat format, DepthFormat depthFormat, int multiSampleCount, RenderTargetUsage usage) : base(width, height, format, depthFormat, multiSampleCount, usage) { _renderer = renderer; _graphicsDevice = _renderer.GraphicsDevice; if (!renderer.Adapter.QueryRenderTargetFormat(format, depthFormat, multiSampleCount)) { throw new ArgumentException("Format combination not supported."); } D3D.Texture2DDescription desc2D = new D3D.Texture2DDescription(); desc2D.ArraySize = 1; desc2D.BindFlags = D3D.BindFlags.ShaderResource | D3D.BindFlags.RenderTarget; desc2D.CpuAccessFlags = D3D.CpuAccessFlags.None; desc2D.Format = D3D10Helper.ToD3DSurfaceFormat(format); desc2D.Height = height; desc2D.Width = width; desc2D.Usage = _usage = D3D.ResourceUsage.Default; if (genMipMaps) { desc2D.OptionFlags = D3D.ResourceOptionFlags.GenerateMipMaps; } else { desc2D.OptionFlags = D3D.ResourceOptionFlags.None; } desc2D.MipLevels = (genMipMaps) ? 0 : 1; if (multiSampleCount > 1) { desc2D.SampleDescription = new SlimDX.DXGI.SampleDescription(multiSampleCount, 0); } else { desc2D.SampleDescription = new DXGI.SampleDescription(1, 0); } _texture2D = new D3D.Texture2D(_graphicsDevice, desc2D); _shaderResourceView = new D3D.ShaderResourceView(_graphicsDevice, _texture2D); _renderTargetView = new D3D.RenderTargetView(_graphicsDevice, _texture2D); _graphicsDevice.ClearRenderTargetView(_renderTargetView, new SDX.Color4(1.0f, 0, 0, 0)); //Add to tracker _renderer.Resources.AddTrackedObject(_texture2D.ComPointer, this); _renderer.Resources.AddTrackedObject(_shaderResourceView.ComPointer, this); _renderer.Resources.AddTrackedObject(_renderTargetView.ComPointer, this); _mipCount = _texture2D.Description.MipLevels; if (depthFormat != DepthFormat.None) { D3D.Texture2DDescription dbdesc = new D3D.Texture2DDescription(); dbdesc.ArraySize = 1; dbdesc.BindFlags = D3D.BindFlags.DepthStencil; dbdesc.CpuAccessFlags = D3D.CpuAccessFlags.None; dbdesc.Format = D3D10Helper.ToD3DDepthFormat(depthFormat); dbdesc.Height = height; dbdesc.Width = width; dbdesc.Usage = D3D.ResourceUsage.Default; dbdesc.OptionFlags = D3D.ResourceOptionFlags.None; dbdesc.MipLevels = 1; if (multiSampleCount > 1) { dbdesc.SampleDescription = new SlimDX.DXGI.SampleDescription(multiSampleCount, 0); } else { dbdesc.SampleDescription = new SlimDX.DXGI.SampleDescription(1, 0); } using (D3D.Texture2D depthBuffer = new D3D.Texture2D(_graphicsDevice, dbdesc)) { _depthStencilView = new D3D.DepthStencilView(_graphicsDevice, depthBuffer); if (depthFormat == Tesla.Graphics.DepthFormat.Depth24Stencil8) { _graphicsDevice.ClearDepthStencilView(_depthStencilView, D3D.DepthStencilClearFlags.Depth | D3D.DepthStencilClearFlags.Stencil, 1.0f, 0); } else { _graphicsDevice.ClearDepthStencilView(_depthStencilView, D3D.DepthStencilClearFlags.Depth, 1.0f, 0); } //Add to tracker _renderer.Resources.AddTrackedObject(_depthStencilView.ComPointer, this); } } }
/// <summary> /// Gets the data from the vertex buffer and copies it into specified array. /// </summary> /// <typeparam name="T">The type of data in the vertex buffer.</typeparam> /// <param name="data">Array to copy contents to from the vertex buffer into</param> /// <param name="startIndex">Index of the element in the array at each to start writing to</param> /// <param name="elementCount">Number of elements to copy</param> /// <param name="offsetInBytes">Offset in bytes from the beginning of the vertex buffer to the data.</param> /// <param name="vertexStride">Size of an element in bytes</param> /// <exception cref="System.ObjectDisposedException">Thrown if Dispose() has been called.</exception> /// <exception cref="System.InvalidOperationException">Thrown if the write options are incompatible with the resource usage of the buffer.</exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown if the data's vertex stride is too small, the offset in bytes is out of range, /// or the byte offset and number of elements to read will cause overflow.</exception> /// <exception cref="Tesla.Core.TeslaException">Thrown if there was an error reading from the buffer.</exception> public override void GetData <T>(T[] data, int startIndex, int elementCount, int offsetInBytes, int vertexStride) { if (_buffer == null || _buffer.Disposed) { throw new ObjectDisposedException(GetType().Name); } //Check if array bounds are out of range D3D10Helper.CheckArrayBounds(data, startIndex, elementCount); VertexDeclaration vertexDecl = base.VertexDeclaration; int vertexCount = base.VertexCount; int vbSize = vertexCount * vertexDecl.VertexStride; int elemSize = MemoryHelper.SizeOf <T>(); int dataSize = elementCount * elemSize; int vertexStep = vertexStride; if (vertexStride != 0) { vertexStep -= elemSize; if (vertexStep < 0) { throw new ArgumentException("vertexStride", "Vertex stride is too small for requested data size."); } //If we get this far, we need to make sure the actual bytes we're going to look at matches up, //since we can grab specific parts of a vertex and not the whole thing if (elementCount > 1) { dataSize = ((elementCount - 1) * vertexStep) + dataSize; } } //Prevent overflow out of range errors if ((offsetInBytes < 0) || (offsetInBytes > vbSize)) { throw new ArgumentOutOfRangeException("offsetInBytes", "Byte offset is out of range."); } if ((offsetInBytes + dataSize) > vbSize) { throw new ArgumentOutOfRangeException("data", "Byte offset and elements to read will cause in buffer overflow."); } //Create scratch buffer, if it hasn't been created already CreateStaging(); try { //If we're reading from the entire VB just copy the whole thing if (offsetInBytes == 0 && startIndex == 0 && vertexCount == data.Length) { _graphicsDevice.CopyResource(_buffer, _staging); } else { D3D.ResourceRegion region = new D3D.ResourceRegion(); region.Left = offsetInBytes; region.Right = offsetInBytes + dataSize; region.Front = region.Top = 0; region.Back = region.Bottom = 1; _graphicsDevice.CopySubresourceRegion(_buffer, 0, region, _staging, 0, offsetInBytes, 0, 0); } using (SDX.DataStream ds = _staging.Map(D3D.MapMode.Read, D3D.MapFlags.None)) { //If the step is zero, that means we're dealing with the entire vertex and not a subset of it if (vertexStep == 0) { ds.Position = offsetInBytes; ds.ReadRange <T>(data, startIndex, elementCount); } else { ds.Position = offsetInBytes; int count = elementCount - 1; int index = startIndex; data[index++] = ds.Read <T>(); while (count > 0) { ds.Position += vertexStep; data[index] = ds.Read <T>(); count--; index++; } } _staging.Unmap(); } } catch (Exception e) { throw new TeslaException("Error reading from D3D10 Buffer.", e); } }
private void CreateSwapChain(IntPtr windowHandle, PresentationParameters presentParams) { DXGI.Format surfaceFormat = D3D10Helper.ToD3DSurfaceFormat(presentParams.BackBufferFormat); switch (presentParams.PresentInterval) { case PresentInterval.Immediate: _interval = 0; break; case PresentInterval.One: _interval = 1; break; case PresentInterval.Two: _interval = 2; break; } DXGI.SampleDescription sampleDesc = new DXGI.SampleDescription(1, 0); bool msEnabled = false; if (presentParams.MultiSampleCount > 1) { sampleDesc.Count = presentParams.MultiSampleCount; int q = _graphicsDevice.CheckMultisampleQualityLevels(surfaceFormat, presentParams.MultiSampleCount); if (presentParams.MultiSampleQuality < q) { sampleDesc.Quality = presentParams.MultiSampleQuality; } else { sampleDesc.Quality = q - 1; } msEnabled = true; } DXGI.SwapEffect swap; if (presentParams.RenderTargetUsage == RenderTargetUsage.PlatformDefault) { if (msEnabled) { swap = DXGI.SwapEffect.Discard; } else { swap = DXGI.SwapEffect.Sequential; } } else if (presentParams.RenderTargetUsage == RenderTargetUsage.DiscardContents) { swap = DXGI.SwapEffect.Discard; } else { swap = DXGI.SwapEffect.Sequential; } DXGI.ModeDescription modeDesc = new DXGI.ModeDescription(presentParams.BackBufferWidth, presentParams.BackBufferHeight, new SDX.Rational(60, 1), surfaceFormat); modeDesc.Scaling = DXGI.DisplayModeScaling.Stretched; _swapChain = new DXGI.SwapChain(_factory, _graphicsDevice, new DXGI.SwapChainDescription { BufferCount = 1, Flags = DXGI.SwapChainFlags.AllowModeSwitch, IsWindowed = true, ModeDescription = modeDesc, OutputHandle = windowHandle, SampleDescription = sampleDesc, SwapEffect = swap, Usage = DXGI.Usage.RenderTargetOutput }); //Add to tracker _renderer.Resources.AddTrackedObject(_swapChain.ComPointer, this); _factory.SetWindowAssociation(windowHandle, DXGI.WindowAssociationFlags.IgnoreAll | DXGI.WindowAssociationFlags.IgnoreAltEnter); }
/// <summary> /// Sets the vertex data from an array source. /// </summary> /// <typeparam name="T">The type of data in the vertex buffer.</typeparam> /// <param name="data">Array that holds the vertex data</param> /// <param name="startIndex">Starting index of the element in the array at which to start copying from</param> /// <param name="elementCount">Number of elements to copy from the array</param> /// <param name="offsetInBytes">Offset in bytes from the beginning of the vertex buffer to the data.</param> /// <param name="vertexStride">Size of an element in bytes.</param> /// <param name="writeOptions">Writing options for the vertex buffer. None, discard, or no overwrite.</param> /// <exception cref="System.ObjectDisposedException">Thrown if Dispose() has been called.</exception> /// <exception cref="System.InvalidOperationException">Thrown if the write options are incompatible with the resource usage of the buffer.</exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown if the data's vertex stride is too small, the offset in bytes is out of range, /// or the byte offset and number of elements to write will cause overflow.</exception> /// <exception cref="Tesla.Core.TeslaException">Thrown if there was an error writing to the buffer.</exception> public override void SetData <T>(T[] data, int startIndex, int elementCount, int offsetInBytes, int vertexStride, DataWriteOptions writeOptions) { if (_buffer == null || _buffer.Disposed) { throw new ObjectDisposedException(GetType().Name); } //Throw an error if an invalid write options is specified if (base.BufferUsage == ResourceUsage.Static && writeOptions != DataWriteOptions.None) { throw new InvalidOperationException("Can only specify write options other than DataWriteOptions.None for dynamic vertex buffers."); } //Check if array bounds are out of range D3D10Helper.CheckArrayBounds(data, startIndex, elementCount); VertexDeclaration vertexDecl = base.VertexDeclaration; int vertexCount = base.VertexCount; int vbSize = vertexCount * vertexDecl.VertexStride; int elemSize = MemoryHelper.SizeOf <T>(); int dataSize = elementCount * elemSize; int vertexStep = vertexStride; if (vertexStride != 0) { vertexStep -= elemSize; if (vertexStep < 0) { throw new ArgumentOutOfRangeException("vertexStride", "Vertex stride is too small for requested data size."); } //If we get this far, we need to make sure the actual bytes we're going to look at matches up, //since we can grab specific parts of a vertex and not the whole thing if (elementCount > 1) { dataSize = ((elementCount - 1) * vertexStep) + dataSize; } } //Prevent overflow out of range errors if ((offsetInBytes < 0) || (offsetInBytes > vbSize)) { throw new ArgumentOutOfRangeException("offsetInbytes", "Byte offset is out of range."); } if ((offsetInBytes + dataSize) > vbSize) { throw new ArgumentOutOfRangeException("data", "Byte offset and elements to write will cause in buffer overflow."); } //Create scratch buffer, if it hasn't been created already bool usesStaging = false; if (base.BufferUsage == ResourceUsage.Static || writeOptions == DataWriteOptions.None) { CreateStaging(); usesStaging = true; } try { if (usesStaging) { //If we're not going to be writing the entire vertex structure, we need to first //copy the contents of the affected vertex data into the staging buffer if (vertexStep != vertexStride) { //If we're going to be working with all the verts, no need to copy a subresource region if (offsetInBytes == 0 && startIndex == 0 && vertexCount == data.Length) { _graphicsDevice.CopyResource(_buffer, _staging); } else { D3D.ResourceRegion region = new D3D.ResourceRegion(); region.Left = offsetInBytes; region.Right = offsetInBytes + dataSize; region.Front = region.Top = 0; region.Back = region.Bottom = 1; _graphicsDevice.CopySubresourceRegion(_buffer, 0, region, _staging, 0, offsetInBytes, 0, 0); } } using (SDX.DataStream ds = _staging.Map(D3D.MapMode.Read, D3D.MapFlags.None)) { //If the step is zero, that means we're dealing with the entire vertex and not a subset of it if (vertexStep == 0) { ds.Position = offsetInBytes; ds.WriteRange <T>(data, startIndex, elementCount); } else { ds.Position = offsetInBytes; int count = elementCount - 1; int index = startIndex; ds.Write <T>(data[index++]); while (count > 0) { ds.Position += vertexStep; ds.Write <T>(data[index]); count--; index++; } } _staging.Unmap(); //If we're writing to the entire VB just copy the whole thing if (offsetInBytes == 0 && startIndex == 0 && dataSize == vbSize) { _graphicsDevice.CopyResource(_staging, _buffer); } else { D3D.ResourceRegion region = new D3D.ResourceRegion(); region.Left = offsetInBytes; region.Right = offsetInBytes + dataSize; region.Front = region.Top = 0; region.Back = region.Bottom = 1; _graphicsDevice.CopySubresourceRegion(_staging, 0, region, _buffer, 0, offsetInBytes, 0, 0); } } //Dynamic vertex buffers only } else { D3D.MapMode mode = (writeOptions == DataWriteOptions.Discard) ? D3D.MapMode.WriteDiscard : D3D.MapMode.WriteNoOverwrite; using (SDX.DataStream ds = _buffer.Map(mode, D3D.MapFlags.None)) { //If the step is zero, that means we're dealing with the entire vertex and not a subset of it if (vertexStep == 0) { ds.Position = offsetInBytes; ds.WriteRange <T>(data, startIndex, elementCount); } else { ds.Position = offsetInBytes; int count = elementCount - 1; int index = startIndex; ds.Write <T>(data[index++]); while (count > 0) { ds.Position += vertexStep; ds.Write <T>(data[index]); count--; index++; } } _buffer.Unmap(); } } } catch (Exception e) { throw new TeslaException("Error reading from D3D10 Buffer.", e); } }