예제 #1
0
        public unsafe Span <T> AsSpan <T>(ID3D11Texture2D resource, int mipSlice, int arraySlice) where T : unmanaged
        {
            resource.CalculateSubResourceIndex(mipSlice, arraySlice, out int mipSize);
            Span <byte> source = new Span <byte>(DataPointer.ToPointer(), mipSize * RowPitch);

            return(MemoryMarshal.Cast <byte, T>(source));
        }
예제 #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Direct2DOverlayRenderer"/> class.
        /// </summary>
        internal Direct2DOverlayRenderer(EngineDevice device, D3D11.ID3D11Texture2D renderTarget3D, int viewWidth, int viewHeight, DpiScaling dpiScaling, bool forceInit)
        {
            _device         = device;
            _renderTarget3D = renderTarget3D;

            this.CreateResources(viewWidth, viewHeight, dpiScaling, forceInit);
        }
예제 #3
0
        /// <summary>
        /// Loads the target texture int a staging texture.
        /// </summary>
        private void CopyTextureToStagingResource(D3D11.ID3D11Texture2D textureToUpload)
        {
            // Prepare needed textures
            if (_copyHelperTextureStaging == null)
            {
                _copyHelperTextureStaging = GraphicsHelper.Internals.CreateStagingTexture(_device, _width, _height, _format);
                if (_isMultisampled)
                {
                    _copyHelperTextureStandard = GraphicsHelper.Internals.CreateTexture(_device, _width, _height, _format);
                }
            }

            // Copy contents of the texture
            //  .. execute a ResolveSubresource before if the source texture is multisampled
            if (_isMultisampled)
            {
                _device.DeviceImmediateContextD3D11.ResolveSubresource(
                    _copyHelperTextureStandard, 0,
                    textureToUpload, 0,
                    _format);
                _device.DeviceImmediateContextD3D11.CopyResource(
                    _copyHelperTextureStaging,
                    _copyHelperTextureStandard);
            }
            else
            {
                _device.DeviceImmediateContextD3D11.CopyResource(
                    _copyHelperTextureStaging, textureToUpload);
            }
        }
예제 #4
0
        /// <summary>
        /// Gets the handle that can be used for resource sharing.
        /// </summary>
        /// <param name="texture">The texture to be shared.</param>
        private IntPtr GetSharedHandle(D3D11.ID3D11Texture2D texture)
        {
            texture.EnsureNotNull(nameof(texture));

            using (var resource = texture.QueryInterface <IDXGIResource>())
            {
                return(resource.SharedHandle);
            }
        }
예제 #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="RenderTargetViewDescription"/> struct.
        /// </summary>
        /// <param name="texture"></param>
        /// <param name="viewDimension"></param>
        /// <param name="format"></param>
        /// <param name="mipSlice"></param>
        /// <param name="firstArraySlice"></param>
        /// <param name="arraySize"></param>
        /// <param name="planeSlice"></param>
        public RenderTargetViewDescription1(
            ID3D11Texture2D texture,
            RenderTargetViewDimension viewDimension,
            Format format       = Format.Unknown,
            int mipSlice        = 0,
            int firstArraySlice = 0,
            int arraySize       = -1,
            int planeSlice      = 0)
            : this()
        {
            ViewDimension = viewDimension;
            if (format == Format.Unknown ||
                (-1 == arraySize && (RenderTargetViewDimension.Texture2DArray == viewDimension || RenderTargetViewDimension.Texture2DMultisampledArray == viewDimension)))
            {
                var textureDesc = texture.Description;
                if (format == Format.Unknown)
                {
                    format = textureDesc.Format;
                }
                if (-1 == arraySize)
                {
                    arraySize = textureDesc.ArraySize - firstArraySlice;
                }
            }
            Format = format;
            switch (viewDimension)
            {
            case RenderTargetViewDimension.Texture2D:
                Texture2D.MipSlice   = mipSlice;
                Texture2D.PlaneSlice = planeSlice;
                break;

            case RenderTargetViewDimension.Texture2DArray:
                Texture2DArray.MipSlice        = mipSlice;
                Texture2DArray.FirstArraySlice = firstArraySlice;
                Texture2DArray.ArraySize       = arraySize;
                Texture2DArray.PlaneSlice      = planeSlice;
                break;

            case RenderTargetViewDimension.Texture2DMultisampled:
                break;

            case RenderTargetViewDimension.Texture2DMultisampledArray:
                Texture2DMSArray.FirstArraySlice = firstArraySlice;
                Texture2DMSArray.ArraySize       = arraySize;
                break;

            default:
                break;
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="DepthStencilViewDescription"/> struct.
        /// </summary>
        /// <param name="texture"></param>
        /// <param name="viewDimension"></param>
        /// <param name="format"></param>
        /// <param name="mipSlice"></param>
        /// <param name="firstArraySlice"></param>
        /// <param name="arraySize"></param>
        public DepthStencilViewDescription(
            ID3D11Texture2D texture,
            DepthStencilViewDimension viewDimension,
            Format format               = Format.Unknown,
            int mipSlice                = 0,
            int firstArraySlice         = 0,
            int arraySize               = -1,
            DepthStencilViewFlags flags = DepthStencilViewFlags.None) : this()
        {
            ViewDimension = viewDimension;
            Flags         = flags;

            if (format == Format.Unknown ||
                (-1 == arraySize && (DepthStencilViewDimension.Texture2DArray == viewDimension || DepthStencilViewDimension.Texture2DMultisampledArray == viewDimension)))
            {
                var textureDesc = texture.Description;
                if (format == Format.Unknown)
                {
                    format = textureDesc.Format;
                }
                if (arraySize == -1)
                {
                    arraySize = textureDesc.ArraySize - firstArraySlice;
                }
            }
            Format = format;
            switch (viewDimension)
            {
            case DepthStencilViewDimension.Texture2D:
                Texture2D.MipSlice = mipSlice;
                break;

            case DepthStencilViewDimension.Texture2DArray:
                Texture2DArray.MipSlice        = mipSlice;
                Texture2DArray.FirstArraySlice = firstArraySlice;
                Texture2DArray.ArraySize       = arraySize;
                break;

            case DepthStencilViewDimension.Texture2DMultisampled:
                break;

            case DepthStencilViewDimension.Texture2DMultisampledArray:
                Texture2DMSArray.FirstArraySlice = firstArraySlice;
                Texture2DMSArray.ArraySize       = arraySize;
                break;

            default:
                break;
            }
        }
예제 #7
0
        /// <summary>
        /// Upload a texture from the graphics hardware.
        /// </summary>
        /// <param name="textureToUpload">The texture to be uploaded.</param>
        internal MemoryMappedTexture <T> UploadToMemoryMappedTexture <T>(D3D11.ID3D11Texture2D textureToUpload)
            where T : unmanaged
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException(nameof(TextureUploader));
            }

            var result = new MemoryMappedTexture <T>(
                new Size(_width, _height));

            this.UploadToMemoryMappedTexture(textureToUpload, result);
            return(result);
        }
예제 #8
0
        /// <summary>
        /// Loads a bitmap from the given texture. Be careful: The texture must have CPU read access and this only matches for staging textures.
        /// </summary>
        /// <param name="device">The device on which the texture is created.</param>
        /// <param name="stagingTexture">The texture to be loaded into the bitmap.</param>
        /// <param name="targetBitmap">The target bitmap to write all contents to.</param>
        /// <param name="pixelWidth">With of the bitmap in pixels.</param>
        /// <param name="pixelHeight">Height of the bitmap in pixels.</param>
        /// <param name="lockTimeout">Timeout for locking the target bitmap.</param>
        internal static void LoadBitmapFromStagingTexture(EngineDevice device, D3D11.ID3D11Texture2D stagingTexture, WriteableBitmap targetBitmap, int pixelWidth, int pixelHeight, TimeSpan lockTimeout)
        {
            device.EnsureNotNull(nameof(device));
            stagingTexture.EnsureNotNull(nameof(stagingTexture));
            targetBitmap.EnsureNotNull(nameof(targetBitmap));

            var textureDesc = stagingTexture.Description;

            pixelWidth.EnsureEqualComparable(textureDesc.Width, $"{nameof(textureDesc)}.{nameof(textureDesc.Width)}");
            pixelHeight.EnsureEqualComparable(textureDesc.Height, $"{nameof(textureDesc)}.{nameof(textureDesc.Height)}");

            // Prepare target bitmap
            var dataBox = device.Internals.DeviceImmediateContextD3D11.Map(stagingTexture, 0, D3D11.MapMode.Read, D3D11.MapFlags.None);

            try
            {
                if (!targetBitmap.TryLock(new Duration(lockTimeout)))
                {
                    return;
                }

                try
                {
                    // Copy data row by row
                    //  => Rows from data source may have more pixels because driver changes the size of textures
                    var rowPitch = (uint)(pixelWidth * 4);
                    for (var loopRow = 0; loopRow < pixelHeight; loopRow++)
                    {
                        var rowPitchSource      = dataBox.RowPitch;
                        var rowPitchDestination = pixelWidth * 4;
                        SeeingSharpUtil.CopyMemory(
                            dataBox.DataPointer + loopRow * rowPitchSource,
                            targetBitmap.BackBuffer + loopRow * rowPitchDestination,
                            rowPitch);
                    }
                }
                finally
                {
                    targetBitmap.AddDirtyRect(new Int32Rect(0, 0, pixelWidth, pixelHeight));
                    targetBitmap.Unlock();
                }
            }
            finally
            {
                device.Internals.DeviceImmediateContextD3D11.Unmap(stagingTexture, 0);
            }
        }
        /// <summary>
        /// Loads a bitmap from the given texture. Be careful: The texture must have CPU read access and this only matches for staging textures.
        /// </summary>
        /// <param name="device">The device on which the texture is created.</param>
        /// <param name="stagingTexture">The texture to be loaded into the bitmap.</param>
        /// <param name="width">The width of the texture.</param>
        /// <param name="height">The height of the texture.</param>
        internal static GDI.Bitmap LoadBitmapFromStagingTexture(EngineDevice device, D3D11.ID3D11Texture2D stagingTexture, int width, int height)
        {
            device.EnsureNotNull(nameof(device));
            stagingTexture.EnsureNotNull(nameof(stagingTexture));
            width.EnsurePositiveOrZero(nameof(width));
            height.EnsurePositiveOrZero(nameof(height));

            //Prepare target bitmap
            var resultBitmap = new GDI.Bitmap(width, height);
            var dataBox      = device.Internals.DeviceImmediateContextD3D11.Map(stagingTexture, 0, D3D11.MapMode.Read, D3D11.MapFlags.None);

            try
            {
                //Lock bitmap so it can be accessed for texture loading
                var bitmapData = resultBitmap.LockBits(
                    new GDI.Rectangle(0, 0, resultBitmap.Width, resultBitmap.Height),
                    ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

                try
                {
                    //Copy data row by row
                    // => Rows form data source may have more pixels because driver changes the size of textures
                    var rowPitch = (uint)(width * 4);

                    for (var loopRow = 0; loopRow < height; loopRow++)
                    {
                        // Copy bitmap data
                        var rowPitchSource      = dataBox.RowPitch;
                        var rowPitchDestination = width * 4;
                        SeeingSharpUtil.CopyMemory(
                            dataBox.DataPointer + loopRow * rowPitchSource,
                            bitmapData.Scan0 + loopRow * rowPitchDestination,
                            rowPitch);
                    }
                }
                finally
                {
                    resultBitmap.UnlockBits(bitmapData);
                }
            }
            finally
            {
                device.Internals.DeviceImmediateContextD3D11.Unmap(stagingTexture, 0);
            }
            return(resultBitmap);
        }
예제 #10
0
        /// <summary>
        /// Gets the format for sharing.
        /// </summary>
        /// <param name="texture">The texture to get the format for.</param>
        private static D3D9.Format TranslateFormat(D3D11.ID3D11Texture2D texture)
        {
            switch (texture.Description.Format)
            {
            case Format.R10G10B10A2_UNorm:
                return(D3D9.Format.A2B10G10R10);

            case Format.R16G16B16A16_Float:
                return(D3D9.Format.A16B16G16R16F);

            case Format.B8G8R8A8_UNorm:
                return(D3D9.Format.A8R8G8B8);

            default:
                return(D3D9.Format.Unknown);
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="UnorderedAccessViewDescription1"/> struct.
        /// </summary>
        /// <param name="texture"></param>
        /// <param name="viewDimension"></param>
        /// <param name="format"></param>
        /// <param name="mipSlice"></param>
        /// <param name="firstArraySlice"></param>
        /// <param name="arraySize"></param>
        /// <param name="planeSlice"></param>
        public UnorderedAccessViewDescription1(
            ID3D11Texture2D texture,
            UnorderedAccessViewDimension viewDimension,
            Format format       = Format.Unknown,
            int mipSlice        = 0,
            int firstArraySlice = 0,
            int arraySize       = -1,
            int planeSlice      = 0) : this()
        {
            ViewDimension = viewDimension;

            if (format == Format.Unknown ||
                (-1 == arraySize && (viewDimension == UnorderedAccessViewDimension.Texture2DArray)))
            {
                var textureDesc = texture.Description;
                if (format == Format.Unknown)
                {
                    format = textureDesc.Format;
                }
                if (arraySize == -1)
                {
                    arraySize = textureDesc.ArraySize - firstArraySlice;
                }
            }
            Format = format;
            switch (viewDimension)
            {
            case UnorderedAccessViewDimension.Texture2D:
                Texture2D.MipSlice   = mipSlice;
                Texture2D.PlaneSlice = planeSlice;
                break;

            case UnorderedAccessViewDimension.Texture2DArray:
                Texture2DArray.MipSlice        = mipSlice;
                Texture2DArray.FirstArraySlice = firstArraySlice;
                Texture2DArray.ArraySize       = arraySize;
                Texture2DArray.PlaneSlice      = planeSlice;
                break;
            }
        }
예제 #12
0
        /// <summary>
        /// Upload a texture from the graphics hardware.
        /// </summary>
        /// <param name="textureToUpload">The texture to be uploaded.</param>
        /// <param name="targetFloatBuffer">The target buffer to which to copy all data.</param>
        internal unsafe void UploadToMemoryMappedTexture <T>(D3D11.ID3D11Texture2D textureToUpload, MemoryMappedTexture <T> targetFloatBuffer)
            where T : unmanaged
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException(nameof(TextureUploader));
            }
            this.EnsureNotNullOrDisposed(nameof(targetFloatBuffer));

            // Check input texture
            var textureDesc = textureToUpload.Description;

            if (textureDesc.Width != _width)
            {
                throw new SeeingSharpGraphicsException($"Invalid texture: Width does not match (given: {textureDesc.Width}, expected: {_width})!");
            }
            if (textureDesc.Height != _height)
            {
                throw new SeeingSharpGraphicsException($"Invalid texture: Height does not match (given: {textureDesc.Height}, expected: {_height})!");
            }
            if (textureDesc.Format != _format)
            {
                throw new SeeingSharpGraphicsException($"Invalid texture: Format does not match (given: {textureDesc.Format}, expected: {_format})!");
            }
            if (GraphicsHelper.IsMultisampled(textureDesc) != _isMultisampled)
            {
                throw new SeeingSharpGraphicsException($"Invalid texture: Multisampling does not match (given: {GraphicsHelper.IsMultisampled(textureDesc)}, expected: {_isMultisampled})!");
            }

            // Check source and destination size
            var targetPixelSize = targetFloatBuffer.PixelSize;

            if (targetPixelSize.Width != _width)
            {
                throw new SeeingSharpGraphicsException("The width of the textures during texture upload does not match!");
            }
            if (targetPixelSize.Height != _height)
            {
                throw new SeeingSharpGraphicsException("The height of the textures during texture upload does not match!");
            }

            // Check format compatibility
            var textureFormatByteSize = FormatHelper.SizeOfInBytes(_format);

            if (textureFormatByteSize != sizeof(T))
            {
                throw new SeeingSharpGraphicsException(
                          "Format of the texture to upload and the destination buffer does not match " +
                          $"(source: {_format} / {textureFormatByteSize} bytes, target: {typeof(T).Name} / {sizeof(T)} bytes)!");
            }

            // Upload the texture
            this.CopyTextureToStagingResource(textureToUpload);

            // Read the data into the .Net data block
            var dataBox = _device.DeviceImmediateContextD3D11.Map(
                _copyHelperTextureStaging, 0, D3D11.MapMode.Read, D3D11.MapFlags.None);

            try
            {
                var rowPitchSource      = dataBox.RowPitch;
                var rowPitchDestination = targetFloatBuffer.Width * sizeof(T);
                if (rowPitchSource > 0 && rowPitchDestination > 0)
                {
                    for (var loopY = 0; loopY < _height; loopY++)
                    {
                        SeeingSharpUtil.CopyMemory(
                            dataBox.DataPointer + loopY * rowPitchSource,
                            targetFloatBuffer.Pointer + loopY * rowPitchDestination,
                            (uint)rowPitchDestination);
                    }
                }
                else
                {
                    throw new SeeingSharpGraphicsException($"Invalid row pitch (source: {rowPitchSource}, destination: {rowPitchDestination})!");
                }
            }
            finally
            {
                _device.DeviceImmediateContextD3D11.Unmap(_copyHelperTextureStaging, 0);
            }
        }
예제 #13
0
 public unsafe Span <T> AsSpan <T>(ID3D11Texture2D resource, int mipSlice, int arraySlice)
 {
     resource.CalculateSubResourceIndex(mipSlice, arraySlice, out int mipSize);
     return(new Span <T>(DataPointer.ToPointer(), mipSize * RowPitch));
 }
예제 #14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ShaderResourceViewDescription1"/> struct.
        /// </summary>
        /// <param name="texture"></param>
        /// <param name="viewDimension"></param>
        /// <param name="format"></param>
        /// <param name="mostDetailedMip"></param>
        /// <param name="mipLevels"></param>
        /// <param name="firstArraySlice"></param>
        /// <param name="arraySize"></param>
        /// <param name="planeSlice"></param>
        public ShaderResourceViewDescription1(
            ID3D11Texture2D texture,
            ShaderResourceViewDimension viewDimension,
            Format format       = Format.Unknown,
            int mostDetailedMip = 0,
            int mipLevels       = -1,
            int firstArraySlice = 0,
            int arraySize       = -1,
            int planeSlice      = 0)
            : this()
        {
            ViewDimension = viewDimension;
            if (format == Format.Unknown ||
                (mipLevels == -1 && viewDimension != ShaderResourceViewDimension.Texture2DMultisampled && viewDimension != ShaderResourceViewDimension.Texture2DMultisampledArray) ||
                (arraySize == -1 && (ShaderResourceViewDimension.Texture2DArray == viewDimension || ShaderResourceViewDimension.Texture2DMultisampledArray == viewDimension || ShaderResourceViewDimension.TextureCubeArray == viewDimension)))
            {
                var textureDesc = texture.Description;
                if (format == Format.Unknown)
                {
                    format = textureDesc.Format;
                }
                if (-1 == mipLevels)
                {
                    mipLevels = textureDesc.MipLevels - mostDetailedMip;
                }
                if (-1 == arraySize)
                {
                    arraySize = textureDesc.ArraySize - firstArraySlice;
                    if (viewDimension == ShaderResourceViewDimension.TextureCubeArray)
                    {
                        arraySize /= 6;
                    }
                }
            }
            Format = format;
            switch (viewDimension)
            {
            case ShaderResourceViewDimension.Texture2D:
                Texture2D.MostDetailedMip = mostDetailedMip;
                Texture2D.MipLevels       = mipLevels;
                Texture2D.PlaneSlice      = planeSlice;
                break;

            case ShaderResourceViewDimension.Texture2DArray:
                Texture2DArray.MostDetailedMip = mostDetailedMip;
                Texture2DArray.MipLevels       = mipLevels;
                Texture2DArray.FirstArraySlice = firstArraySlice;
                Texture2DArray.ArraySize       = arraySize;
                Texture2DArray.PlaneSlice      = planeSlice;
                break;

            case ShaderResourceViewDimension.Texture2DMultisampled:
                break;

            case ShaderResourceViewDimension.Texture2DMultisampledArray:
                Texture2DMSArray.FirstArraySlice = firstArraySlice;
                Texture2DMSArray.ArraySize       = arraySize;
                break;

            case ShaderResourceViewDimension.TextureCube:
                TextureCube.MostDetailedMip = mostDetailedMip;
                TextureCube.MipLevels       = mipLevels;
                break;

            case ShaderResourceViewDimension.TextureCubeArray:
                TextureCubeArray.MostDetailedMip  = mostDetailedMip;
                TextureCubeArray.MipLevels        = mipLevels;
                TextureCubeArray.First2DArrayFace = firstArraySlice;
                TextureCubeArray.NumCubes         = arraySize;
                break;

            default:
                break;
            }
        }
예제 #15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Direct2DOverlayRenderer"/> class.
 /// </summary>
 public Direct2DOverlayRenderer(EngineDevice device, D3D11.ID3D11Texture2D renderTarget3D, int viewWidth, int viewHeight, DpiScaling dpiScaling)
     : this(device, renderTarget3D, viewWidth, viewHeight, dpiScaling, false)
 {
 }
예제 #16
0
        internal static TextureUploader ConstructUsingPropertiesFromTexture(EngineDevice device, D3D11.ID3D11Texture2D texture)
        {
            var textureDesc = texture.Description;

            return(new TextureUploader(
                       device,
                       textureDesc.Width, textureDesc.Height, textureDesc.Format,
                       GraphicsHelper.IsMultisampled(textureDesc)));
        }
예제 #17
0
            /// <summary>
            /// Create a new DepthBuffer view to bind the given depth buffer to the rendering device.
            /// </summary>
            /// <param name="device">The device on which to create the view.</param>
            /// <param name="depthBuffer">The target resource.</param>
            public static D3D11.ID3D11DepthStencilView CreateDepthBufferView(EngineDevice device, D3D11.ID3D11Texture2D depthBuffer)
            {
                device.EnsureNotNull(nameof(device));
                depthBuffer.EnsureNotNullOrDisposed(nameof(depthBuffer));

                return(device.DeviceD3D11_1.CreateDepthStencilView(depthBuffer));
            }
예제 #18
0
 /// <summary>
 /// Is the given texture sharable?
 /// </summary>
 /// <param name="textureToCheck">The checker to check.</param>
 private static bool IsShareable(D3D11.ID3D11Texture2D textureToCheck)
 {
     return((textureToCheck.Description.OptionFlags & D3D11.ResourceOptionFlags.Shared) != 0);
 }