/// <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="texture">The texture to be loaded into the bitmap.</param>
        public static GDI.Bitmap LoadBitmapFromMemoryMappedTexture(MemoryMappedTexture <int> texture)
        {
            texture.EnsureNotNullOrDisposed(nameof(texture));

            var width  = texture.Width;
            var height = texture.Height;

            // Create and lock bitmap so it can be accessed for texture loading
            var resultBitmap = new GDI.Bitmap(width, height);
            var bitmapData   = resultBitmap.LockBits(
                new GDI.Rectangle(0, 0, resultBitmap.Width, resultBitmap.Height),
                ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

            try
            {
                SeeingSharpUtil.CopyMemory(
                    texture.Pointer, bitmapData.Scan0, texture.SizeInBytes);
            }
            finally
            {
                resultBitmap.UnlockBits(bitmapData);
            }

            return(resultBitmap);
        }
Пример #2
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);
        }
Пример #3
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);
            }
        }
Пример #4
0
 internal RenderPassDumpEntry(string dumpKey, Size size)
 {
     this.Key     = dumpKey;
     _bufferColor = new MemoryMappedTexture <int>(size);
 }
Пример #5
0
            public static D3D11.ID3D11Texture2D LoadTexture2DFromMappedTexture(EngineDevice device, MemoryMappedTexture <int> mappedTexture, bool generateMiplevels)
            {
                // Create the texture
                var dataRectangle = new D3D11.SubresourceData(
                    mappedTexture.Pointer,
                    mappedTexture.Width * 4);

                D3D11.ID3D11Texture2D result;
                if (generateMiplevels)
                {
                    result = device.DeviceD3D11_1.CreateTexture2D(new D3D11.Texture2DDescription
                    {
                        Width             = mappedTexture.Width,
                        Height            = mappedTexture.Height,
                        ArraySize         = 1,
                        BindFlags         = D3D11.BindFlags.ShaderResource | D3D11.BindFlags.RenderTarget,
                        Usage             = D3D11.ResourceUsage.Default,
                        CpuAccessFlags    = D3D11.CpuAccessFlags.None,
                        Format            = DEFAULT_TEXTURE_FORMAT,
                        MipLevels         = 0,
                        OptionFlags       = D3D11.ResourceOptionFlags.None | D3D11.ResourceOptionFlags.GenerateMips,
                        SampleDescription = new SampleDescription(1, 0)
                    },
                                                                  new D3D11.SubresourceData[]
                    {
                        dataRectangle, dataRectangle, dataRectangle, dataRectangle,
                        dataRectangle, dataRectangle, dataRectangle, dataRectangle,
                        dataRectangle, dataRectangle, dataRectangle, dataRectangle
                    });

                    // Auto generate miplevels
                    using (var shaderResourceView = device.DeviceD3D11_1.CreateShaderResourceView(result))
                    {
                        device.DeviceImmediateContextD3D11.GenerateMips(shaderResourceView);
                    }
                }
                else
                {
                    result = device.DeviceD3D11_1.CreateTexture2D(new D3D11.Texture2DDescription
                    {
                        Width             = mappedTexture.Width,
                        Height            = mappedTexture.Height,
                        ArraySize         = 1,
                        BindFlags         = D3D11.BindFlags.ShaderResource,
                        Usage             = D3D11.ResourceUsage.Default,
                        CpuAccessFlags    = D3D11.CpuAccessFlags.None,
                        Format            = DEFAULT_TEXTURE_FORMAT,
                        MipLevels         = 1,
                        OptionFlags       = D3D11.ResourceOptionFlags.None,
                        SampleDescription = new SampleDescription(1, 0)
                    },
                                                                  new D3D11.SubresourceData[] { dataRectangle });
                }

                return(result);
            }
        /// <summary>
        /// Queries for the ObjectId at the given location.
        /// </summary>
        /// <param name="texture">The uploaded texture.</param>
        /// <param name="xPos">The x position where to start.</param>
        /// <param name="yPos">The y position where to start.</param>
        public static unsafe float QueryForObjectId(this MemoryMappedTexture <float> texture, int xPos, int yPos)
        {
            var pixelSize = texture.PixelSize;

            if (xPos < 0)
            {
                throw new ArgumentException("xPos");
            }
            if (xPos >= pixelSize.Width)
            {
                throw new ArgumentException("xPos");
            }
            if (yPos < 0)
            {
                throw new ArgumentException("yPos");
            }
            if (yPos >= pixelSize.Height)
            {
                throw new ArgumentException("yPos");
            }

            // Loop over more pixels to be sure, that we are directly facing one object
            //  => This is needed because of manipulations done by multisampling (=Antialiasing)
            var pointerNative = texture.GetNativePointer();
            var currentX      = xPos;
            var currentY      = yPos;
            var lastObjId     = pointerNative[currentY * pixelSize.Width + currentX];

            for (var loopActQueryStep = 0; loopActQueryStep < s_queryObjectIdSteps.Length; loopActQueryStep++)
            {
                // Calculate current query location
                var currentStep = s_queryObjectIdSteps[loopActQueryStep];
                currentX += currentStep.X;
                currentY += currentStep.Y;

                // Check whether we are still in a valid pixel coordinate
                if (currentX < 0)
                {
                    continue;
                }
                if (currentX >= pixelSize.Width)
                {
                    continue;
                }
                if (currentY < 0)
                {
                    continue;
                }
                if (currentY >= pixelSize.Height)
                {
                    continue;
                }

                // Read current value and compare with last one
                //  (If equal, than at least two pixels are the same => Return this ObjectId)
                var currObjId = pointerNative[currentY * pixelSize.Width + currentX];
                if (EngineMath.EqualsWithTolerance(currObjId, lastObjId))
                {
                    return(currObjId);
                }

                // No match found, continue with next one
                lastObjId = currObjId;
            }

            // No clear match found
            return(0f);
        }