/// <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;
        }
Ejemplo n.º 5
0
        /// <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;
 }
Ejemplo n.º 7
0
        /// <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);
                }
            }
        }
Ejemplo n.º 10
0
        /// <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);
            }
        }
Ejemplo n.º 11
0
        /// <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);
            }
        }
Ejemplo n.º 13
0
        /// <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);
            }
        }
Ejemplo n.º 14
0
        /// <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);
                }
            }
        }
Ejemplo n.º 15
0
        /// <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);
            }
        }
Ejemplo n.º 17
0
        /// <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);
            }
        }
Ejemplo n.º 18
0
        /// <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);
                }
            }
        }
Ejemplo n.º 19
0
        /// <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);
            }
        }