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)); }
/// <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); }
/// <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); } }
/// <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); } }
/// <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; } }
/// <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); }
/// <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); }
/// <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; } }
/// <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); } }
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)); }
/// <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; } }
/// <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) { }
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))); }
/// <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)); }
/// <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); }