Пример #1
0
        internal void UpdateSubresource(GraphicsResource resource, int subResourceIndex, DataBox databox)
        {
            ResourceRegion region;
            var            texture = resource as Texture;

            if (texture != null)
            {
                region = new ResourceRegion(0, 0, 0, texture.Width, texture.Height, texture.Depth);
            }
            else
            {
                var buffer = resource as Buffer;
                if (buffer != null)
                {
                    region = new ResourceRegion(0, 0, 0, buffer.SizeInBytes, 1, 1);
                }
                else
                {
                    throw new InvalidOperationException("Unknown resource type");
                }
            }

            UpdateSubresource(resource, subResourceIndex, databox, region);
        }
Пример #2
0
 internal unsafe void UpdateSubresource(GraphicsResource resource, int subResourceIndex, DataBox databox, ResourceRegion region)
 {
     if (resource == null)
     {
         throw new ArgumentNullException("resource");
     }
     NativeDeviceContext.UpdateSubresource(*(SharpDX.DataBox *)Interop.Cast(ref databox), resource.NativeResource, subResourceIndex, *(SharpDX.Direct3D11.ResourceRegion *)Interop.Cast(ref region));
 }
Пример #3
0
 internal void UpdateSubresource(GraphicsResource resource, int subResourceIndex, DataBox databox, ResourceRegion region)
 {
     NullHelper.ToImplement();
 }
Пример #4
0
        internal void UpdateSubresource(GraphicsResource resource, int subResourceIndex, DataBox databox, ResourceRegion region)
        {
            var texture = resource as Texture;

            if (texture != null)
            {
                var width  = region.Right - region.Left;
                var height = region.Bottom - region.Top;
                var depth  = region.Back - region.Front;

                ResourceDescription resourceDescription;
                switch (texture.Dimension)
                {
                case TextureDimension.Texture1D:
                    resourceDescription = ResourceDescription.Texture1D((SharpDX.DXGI.Format)texture.Format, width, 1, 1);
                    break;

                case TextureDimension.Texture2D:
                case TextureDimension.TextureCube:
                    resourceDescription = ResourceDescription.Texture2D((SharpDX.DXGI.Format)texture.Format, width, height, 1, 1);
                    break;

                case TextureDimension.Texture3D:
                    resourceDescription = ResourceDescription.Texture3D((SharpDX.DXGI.Format)texture.Format, width, height, (short)depth, 1);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                // TODO D3D12 allocate in upload heap (placed resources?)
                var nativeUploadTexture = NativeDevice.CreateCommittedResource(new HeapProperties(CpuPageProperty.WriteBack, MemoryPool.L0), HeapFlags.None,
                                                                               resourceDescription,
                                                                               ResourceStates.GenericRead);


                GraphicsDevice.TemporaryResources.Enqueue(new KeyValuePair <long, Pageable>(GraphicsDevice.NextFenceValue, nativeUploadTexture));

                nativeUploadTexture.WriteToSubresource(0, null, databox.DataPointer, databox.RowPitch, databox.SlicePitch);

                var parentResource = resource.ParentResource ?? resource;

                // Trigger copy
                NativeCommandList.ResourceBarrierTransition(resource.NativeResource, parentResource.NativeResourceState, ResourceStates.CopyDestination);
                NativeCommandList.CopyTextureRegion(new TextureCopyLocation(resource.NativeResource, subResourceIndex), region.Left, region.Top, region.Front, new TextureCopyLocation(nativeUploadTexture, 0), null);
                NativeCommandList.ResourceBarrierTransition(resource.NativeResource, ResourceStates.CopyDestination, parentResource.NativeResourceState);
            }
            else
            {
                var buffer = resource as Buffer;
                if (buffer != null)
                {
                    SharpDX.Direct3D12.Resource uploadResource;
                    int uploadOffset;
                    var uploadSize   = region.Right - region.Left;
                    var uploadMemory = GraphicsDevice.AllocateUploadBuffer(region.Right - region.Left, out uploadResource, out uploadOffset);

                    Utilities.CopyMemory(uploadMemory, databox.DataPointer, uploadSize);

                    NativeCommandList.ResourceBarrierTransition(resource.NativeResource, resource.NativeResourceState, ResourceStates.CopyDestination);
                    NativeCommandList.CopyBufferRegion(resource.NativeResource, region.Left, uploadResource, uploadOffset, uploadSize);
                    NativeCommandList.ResourceBarrierTransition(resource.NativeResource, ResourceStates.CopyDestination, resource.NativeResourceState);
                }
                else
                {
                    throw new InvalidOperationException("Unknown resource type");
                }
            }
        }
Пример #5
0
        internal void UpdateSubresource(GraphicsResource resource, int subResourceIndex, DataBox databox, ResourceRegion region)
        {
            var texture = resource as Texture;

            if (texture != null)
            {
                if (texture.Dimension != TextureDimension.Texture2D)
                {
                    throw new NotImplementedException();
                }

                var width  = region.Right - region.Left;
                var height = region.Bottom - region.Top;

                // TODO D3D12 allocate in upload heap (placed resources?)
                var nativeUploadTexture = NativeDevice.CreateCommittedResource(new HeapProperties(CpuPageProperty.WriteBack, MemoryPool.L0), HeapFlags.None,
                                                                               ResourceDescription.Texture2D((SharpDX.DXGI.Format)texture.Format, width, height),
                                                                               ResourceStates.GenericRead);

                GraphicsDevice.TemporaryResources.Enqueue(new KeyValuePair <long, Pageable>(GraphicsDevice.NextFenceValue, nativeUploadTexture));

                nativeUploadTexture.WriteToSubresource(0, null, databox.DataPointer, databox.RowPitch, databox.SlicePitch);

                var parentResource = resource.ParentResource ?? resource;

                // Trigger copy
                NativeCommandList.ResourceBarrierTransition(resource.NativeResource, parentResource.NativeResourceState, ResourceStates.CopyDestination);
                NativeCommandList.CopyTextureRegion(new TextureCopyLocation(resource.NativeResource, subResourceIndex), region.Left, region.Top, region.Front, new TextureCopyLocation(nativeUploadTexture, 0), null);
                NativeCommandList.ResourceBarrierTransition(resource.NativeResource, ResourceStates.CopyDestination, parentResource.NativeResourceState);
            }
            else
            {
                throw new NotImplementedException();
            }
        }
Пример #6
0
        public void CopyRegion(GraphicsResource source, int sourceSubresource, ResourceRegion? sourecRegion, GraphicsResource destination, int destinationSubResource, int dstX = 0, int dstY = 0, int dstZ = 0)
        {
            if (source == null) throw new ArgumentNullException("source");
            if (destination == null) throw new ArgumentNullException("destination");

            var nullableSharpDxRegion = new SharpDX.Direct3D11.ResourceRegion?();

            if (sourecRegion.HasValue)
            {
                var value = sourecRegion.Value;
                nullableSharpDxRegion = new SharpDX.Direct3D11.ResourceRegion(value.Left, value.Top, value.Front, value.Right, value.Bottom, value.Back);
            }

            NativeDeviceContext.CopySubresourceRegion(source.NativeResource, sourceSubresource, nullableSharpDxRegion, destination.NativeResource, destinationSubResource, dstX, dstY, dstZ);
        }
Пример #7
0
 internal unsafe void UpdateSubresource(GraphicsResource resource, int subResourceIndex, DataBox databox, ResourceRegion region)
 {
     if (resource == null) throw new ArgumentNullException("resource");
     NativeDeviceContext.UpdateSubresource(*(SharpDX.DataBox*)Interop.Cast(ref databox), resource.NativeResource, subResourceIndex, *(SharpDX.Direct3D11.ResourceRegion*)Interop.Cast(ref region));
 }
Пример #8
0
        internal void UpdateSubresource(GraphicsResource resource, int subResourceIndex, DataBox databox, ResourceRegion region)
        {
            var texture = resource as Texture;
            if (texture != null)
            {
                var width = region.Right - region.Left;
                var height = region.Bottom - region.Top;
                var depth = region.Back - region.Front;

                ResourceDescription resourceDescription;
                switch (texture.Dimension)
                {
                    case TextureDimension.Texture1D:
                        resourceDescription = ResourceDescription.Texture1D((SharpDX.DXGI.Format)texture.Format, width, 1, 1);
                        break;
                    case TextureDimension.Texture2D:
                    case TextureDimension.TextureCube:
                        resourceDescription = ResourceDescription.Texture2D((SharpDX.DXGI.Format)texture.Format, width, height, 1, 1);
                        break;
                    case TextureDimension.Texture3D:
                        resourceDescription = ResourceDescription.Texture3D((SharpDX.DXGI.Format)texture.Format, width, height, (short)depth, 1);
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }

                // TODO D3D12 allocate in upload heap (placed resources?)
                var nativeUploadTexture = NativeDevice.CreateCommittedResource(new HeapProperties(CpuPageProperty.WriteBack, MemoryPool.L0), HeapFlags.None,
                    resourceDescription,
                    ResourceStates.GenericRead);


                GraphicsDevice.TemporaryResources.Enqueue(new KeyValuePair<long, Pageable>(GraphicsDevice.NextFenceValue, nativeUploadTexture));

                nativeUploadTexture.WriteToSubresource(0, null, databox.DataPointer, databox.RowPitch, databox.SlicePitch);

                var parentResource = resource.ParentResource ?? resource;

                // Trigger copy
                NativeCommandList.ResourceBarrierTransition(resource.NativeResource, parentResource.NativeResourceState, ResourceStates.CopyDestination);
                NativeCommandList.CopyTextureRegion(new TextureCopyLocation(resource.NativeResource, subResourceIndex), region.Left, region.Top, region.Front, new TextureCopyLocation(nativeUploadTexture, 0), null);
                NativeCommandList.ResourceBarrierTransition(resource.NativeResource, ResourceStates.CopyDestination, parentResource.NativeResourceState);
            }
            else
            {
                var buffer = resource as Buffer;
                if (buffer != null)
                {
                    SharpDX.Direct3D12.Resource uploadResource;
                    int uploadOffset;
                    var uploadSize = region.Right - region.Left;
                    var uploadMemory = GraphicsDevice.AllocateUploadBuffer(region.Right - region.Left, out uploadResource, out uploadOffset);

                    Utilities.CopyMemory(uploadMemory, databox.DataPointer, uploadSize);

                    NativeCommandList.ResourceBarrierTransition(resource.NativeResource, resource.NativeResourceState, ResourceStates.CopyDestination);
                    NativeCommandList.CopyBufferRegion(resource.NativeResource, region.Left, uploadResource, uploadOffset, uploadSize);
                    NativeCommandList.ResourceBarrierTransition(resource.NativeResource, ResourceStates.CopyDestination, resource.NativeResourceState);
                }
                else
                {
                    throw new InvalidOperationException("Unknown resource type");
                }
            }
        }
Пример #9
0
 internal void UpdateSubresource(GraphicsResource resource, int subResourceIndex, DataBox databox, ResourceRegion region)
 {
     throw new NotImplementedException();
 }
Пример #10
0
        internal void UpdateSubresource(GraphicsResource resource, int subResourceIndex, DataBox databox)
        {
            ResourceRegion region;
            var texture = resource as Texture;
            if (texture != null)
            {
                region = new ResourceRegion(0, 0, 0, texture.Width, texture.Height, texture.Depth);
            }
            else
            {
                var buffer = resource as Buffer;
                if (buffer != null)
                {
                    region = new ResourceRegion(0, 0, 0, buffer.SizeInBytes, 1, 1);
                }
                else
                {
                    throw new InvalidOperationException("Unknown resource type");
                }
            }

            UpdateSubresource(resource, subResourceIndex, databox, region);
        }
Пример #11
0
        public void CopyRegion(GraphicsResource source, int sourceSubresource, ResourceRegion? sourceRegion, GraphicsResource destination, int destinationSubResource, int dstX = 0, int dstY = 0, int dstZ = 0)
        {
            if (source is Texture && destination is Texture)
            {
                if (((Texture)source).Usage == GraphicsResourceUsage.Staging || ((Texture)destination).Usage == GraphicsResourceUsage.Staging)
                {
                    throw new NotImplementedException("Copy region of staging resources is not supported yet");
                }

                NativeCommandList.CopyTextureRegion(
                    new TextureCopyLocation(destination.NativeResource, sourceSubresource),
                    dstX, dstY, dstZ,
                    new TextureCopyLocation(source.NativeResource, sourceSubresource),
                    sourceRegion.HasValue
                        ? (SharpDX.Direct3D12.ResourceRegion?)new SharpDX.Direct3D12.ResourceRegion
                        {
                            Left = sourceRegion.Value.Left,
                            Top = sourceRegion.Value.Top,
                            Front = sourceRegion.Value.Front,
                            Right = sourceRegion.Value.Right,
                            Bottom = sourceRegion.Value.Bottom,
                            Back = sourceRegion.Value.Back
                        }
                        : null);
            }
            else if (source is Buffer && destination is Buffer)
            {
                NativeCommandList.CopyBufferRegion(destination.NativeResource, dstX,
                    source.NativeResource, sourceRegion?.Left ?? 0, sourceRegion.HasValue ? sourceRegion.Value.Right - sourceRegion.Value.Left : ((Buffer)source).SizeInBytes);
            }
        }
 internal void UpdateSubresource(GraphicsResource resource, int subResourceIndex, DataBox databox, ResourceRegion region)
 {
     throw new NotImplementedException();
 }
        /// <summary>
        /// Copy a region of a <see cref="GraphicsResource"/> into another.
        /// </summary>
        /// <param name="source">The source from which to copy the data</param>
        /// <param name="regionSource">The region of the source <see cref="GraphicsResource"/> to copy.</param>
        /// <param name="destination">The destination into which to copy the data</param>
        /// <remarks>This might alter some states such as currently bound texture.</remarks>
        public void CopyRegion(GraphicsResource source, int sourceSubresource, ResourceRegion? regionSource, GraphicsResource destination, int destinationSubResource, int dstX = 0, int dstY = 0, int dstZ = 0)
        {
#if DEBUG
            GraphicsDevice.EnsureContextActive();
#endif
            var sourceTexture = source as Texture;
            var destTexture = destination as Texture;

            if (sourceTexture == null || destTexture == null)
            {
                throw Internal.Refactor.NewNotImplementedException("Copy is only implemented for Texture objects.");
            }

            // Get parent texture
            if (sourceTexture.ParentTexture != null)
                sourceTexture = sourceTexture.ParentTexture;
            if (destTexture.ParentTexture != null)
                destTexture = sourceTexture.ParentTexture;

            var sourceWidth = Texture.CalculateMipSize(sourceTexture.Description.Width, sourceSubresource % sourceTexture.MipLevels);
            var sourceHeight = Texture.CalculateMipSize(sourceTexture.Description.Height, sourceSubresource % sourceTexture.MipLevels);
            var sourceDepth = Texture.CalculateMipSize(sourceTexture.Description.Depth, sourceSubresource % sourceTexture.MipLevels);

            var sourceRegion = regionSource.HasValue ? regionSource.Value : new ResourceRegion(0, 0, 0, sourceWidth, sourceHeight, sourceDepth);
            var sourceRectangle = new Rectangle(sourceRegion.Left, sourceRegion.Top, sourceRegion.Right - sourceRegion.Left, sourceRegion.Bottom - sourceRegion.Top);

            if (sourceRectangle.Width == 0 || sourceRectangle.Height == 0)
                return;


            if (destTexture.Description.Usage == GraphicsResourceUsage.Staging)
            {
                if (sourceTexture.Description.Usage == GraphicsResourceUsage.Staging)
                {
                    // Staging => Staging
                    if (sourceRegion.Left != 0 || sourceRegion.Top != 0 || sourceRegion.Front != 0
                        || sourceRegion.Right != sourceWidth || sourceRegion.Bottom != sourceHeight || sourceRegion.Back != sourceDepth)
                    {
                        throw new NotSupportedException("ReadPixels from staging texture to staging texture only support full copy of subresource");
                    }

#if SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGLES
                    if (GraphicsDevice.IsOpenGLES2)
                    {
                        Utilities.CopyMemory(destTexture.StagingData + destTexture.ComputeBufferOffset(destinationSubResource, 0),
                            sourceTexture.StagingData + sourceTexture.ComputeBufferOffset(sourceSubresource, 0),
                            destTexture.ComputeSubresourceSize(destinationSubResource));
                    }
                    else
#endif
                    {
                        GL.BindBuffer(BufferTarget.CopyReadBuffer, sourceTexture.PixelBufferObjectId);
                        GL.BindBuffer(BufferTarget.CopyWriteBuffer, destTexture.PixelBufferObjectId);
                        GL.CopyBufferSubData(BufferTarget.CopyReadBuffer, BufferTarget.CopyWriteBuffer,
                            (IntPtr)sourceTexture.ComputeBufferOffset(sourceSubresource, 0),
                            (IntPtr)destTexture.ComputeBufferOffset(destinationSubResource, 0),
                            (IntPtr)destTexture.ComputeSubresourceSize(destinationSubResource));
                    }
                }
                else
                {
                    // GPU => Staging
                    if (dstX != 0 || dstY != 0 || dstZ != 0)
                        throw new NotSupportedException("ReadPixels from staging texture using non-zero destination is not supported");

                    GL.Viewport(0, 0, sourceWidth, sourceHeight);

                    var isDepthBuffer = Texture.InternalIsDepthStencilFormat(sourceTexture.Format);

                    GL.BindFramebuffer(FramebufferTarget.Framebuffer, isDepthBuffer ? GraphicsDevice.CopyDepthSourceFBO : GraphicsDevice.CopyColorSourceFBO);
                    var attachmentType = FramebufferAttachment.ColorAttachment0;

                    for (int depthSlice = sourceRegion.Front; depthSlice < sourceRegion.Back; ++depthSlice)
                    {
                        attachmentType = GraphicsDevice.UpdateFBO(FramebufferTarget.Framebuffer, new GraphicsDevice.FBOTexture(sourceTexture, sourceSubresource / sourceTexture.MipLevels + depthSlice, sourceSubresource % sourceTexture.MipLevels));

#if SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGLES
                        if (GraphicsDevice.IsOpenGLES2)
                        {
                            var format = destTexture.TextureFormat;
                            var type = destTexture.TextureType;

                            var srcFormat = sourceTexture.Description.Format;
                            var destFormat = destTexture.Description.Format;

                            if (srcFormat == destFormat && destFormat.SizeInBytes() == 4)   // in this case we just want to copy the data we don't care about format conversion. 
                            {                                                               // RGBA/Unsigned-byte is always a working combination whatever is the internal format (sRGB, etc...)
                                format = PixelFormatGl.Rgba;
                                type = PixelType.UnsignedByte;
                            }

                            GL.ReadPixels(sourceRectangle.Left, sourceRectangle.Top, sourceRectangle.Width, sourceRectangle.Height, format, type, destTexture.StagingData + destTexture.ComputeBufferOffset(destinationSubResource, depthSlice));
                        }
                        else
#endif
                        {
                            GL.BindBuffer(BufferTarget.PixelPackBuffer, destTexture.PixelBufferObjectId);
                            GL.ReadPixels(sourceRectangle.Left, sourceRectangle.Top, sourceRectangle.Width, sourceRectangle.Height, destTexture.TextureFormat, destTexture.TextureType, (IntPtr)destTexture.ComputeBufferOffset(destinationSubResource, depthSlice));
                            GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);

                            destTexture.PixelBufferFrame = GraphicsDevice.FrameCounter;
                        }
                    }

                    // Unbind attachment
                    GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, attachmentType, TextureTarget2d.Texture2D, 0, 0);

                    // Restore FBO and viewport
                    GL.BindFramebuffer(FramebufferTarget.Framebuffer, boundFBO);
                    GL.Viewport((int)viewports[0].X, (int)viewports[0].Y, (int)viewports[0].Width, (int)viewports[0].Height);
                }
                return;
            }

            // GPU => GPU
            {
                var isDepthBuffer = Texture.InternalIsDepthStencilFormat(sourceTexture.Format);

                // Use our temporary mutable FBO
                GL.BindFramebuffer(FramebufferTarget.Framebuffer, isDepthBuffer ? GraphicsDevice.CopyDepthSourceFBO : GraphicsDevice.CopyColorSourceFBO);

                var attachmentType = FramebufferAttachment.ColorAttachment0;

                if (activeTexture != 0)
                {
                    activeTexture = 0;
                    GL.ActiveTexture(TextureUnit.Texture0);
                }

                GL.Viewport(0, 0, sourceWidth, sourceHeight);

                GL.BindTexture(destTexture.TextureTarget, destTexture.TextureId);

                for (int depthSlice = sourceRegion.Front; depthSlice < sourceRegion.Back; ++depthSlice)
                {
                    // Note: In practice, either it's a 2D texture array and its arrayslice can be non zero, or it's a 3D texture and it's depthslice can be non-zero, but not both at the same time
                    attachmentType = GraphicsDevice.UpdateFBO(FramebufferTarget.Framebuffer, new GraphicsDevice.FBOTexture(sourceTexture, sourceSubresource / sourceTexture.MipLevels + depthSlice, sourceSubresource % sourceTexture.MipLevels));

                    var arraySlice = destinationSubResource / destTexture.MipLevels;
                    var mipLevel = destinationSubResource % destTexture.MipLevels;

                    switch (destTexture.TextureTarget)
                    {
#if !SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGLES
                        case TextureTarget.Texture1D:
                            GL.CopyTexSubImage1D(TextureTarget2d.Texture1D, mipLevel, dstX, sourceRectangle.Left, sourceRectangle.Top, sourceRectangle.Width);
                            break;
#endif
                        case TextureTarget.Texture2D:
                            GL.CopyTexSubImage2D(TextureTarget2d.Texture2D, mipLevel, dstX, dstY, sourceRectangle.Left, sourceRectangle.Top, sourceRectangle.Width, sourceRectangle.Height);
                            break;
                        case TextureTarget.Texture2DArray:
                            GL.CopyTexSubImage3D(TextureTarget3d.Texture2DArray, mipLevel, dstX, dstY, arraySlice, sourceRectangle.Left, sourceRectangle.Top, sourceRectangle.Width, sourceRectangle.Height);
                            break;
                        case TextureTarget.Texture3D:
                            GL.CopyTexSubImage3D(TextureTarget3d.Texture3D, mipLevel, dstX, dstY, depthSlice, sourceRectangle.Left, sourceRectangle.Top, sourceRectangle.Width, sourceRectangle.Height);
                            break;
                        case TextureTarget.TextureCubeMap:
                            GL.CopyTexSubImage2D(Texture.GetTextureTargetForDataSet2D(destTexture.TextureTarget, arraySlice), mipLevel, dstX, dstY, sourceRectangle.Left, sourceRectangle.Top, sourceRectangle.Width, sourceRectangle.Height);
                            break;
                        default:
                            throw new NotSupportedException("Invalid texture target: " + destTexture.TextureTarget);
                    }
                }

                // Unbind texture and force it to be set again next draw call
                GL.BindTexture(destTexture.TextureTarget, 0);
                boundShaderResourceViews[0] = null;

                // Unbind attachment
                GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, attachmentType, TextureTarget2d.Texture2D, 0, 0);

                // Restore FBO and viewport
                GL.BindFramebuffer(FramebufferTarget.Framebuffer, boundFBO);
                GL.Viewport((int)viewports[0].X, (int)viewports[0].Y, (int)viewports[0].Width, (int)viewports[0].Height);
            }
        }
        internal void UpdateSubresource(GraphicsResource resource, int subResourceIndex, DataBox databox, ResourceRegion region)
        {
#if DEBUG
            GraphicsDevice.EnsureContextActive();
#endif
            var texture = resource as Texture;

            if (texture != null)
            {
                var width = region.Right - region.Left;
                var height = region.Bottom - region.Top;

                // determine the opengl read Unpack Alignment
                var packAlignment = 0;
                if ((databox.RowPitch & 1) != 0)
                {
                    if (databox.RowPitch == width)
                        packAlignment = 1;
                }
                else if ((databox.RowPitch & 2) != 0)
                {
                    var diff = databox.RowPitch - width;
                    if (diff >= 0 && diff < 2)
                        packAlignment = 2;
                }
                else if ((databox.RowPitch & 4) != 0)
                {
                    var diff = databox.RowPitch - width;
                    if (diff >= 0 && diff < 4)
                        packAlignment = 4;
                }
                else if ((databox.RowPitch & 8) != 0)
                {
                    var diff = databox.RowPitch - width;
                    if (diff >= 0 && diff < 8)
                        packAlignment = 8;
                }
                else if (databox.RowPitch == width)
                {
                    packAlignment = 4;
                }
                if (packAlignment == 0)
                    Internal.Refactor.ThrowNotImplementedException("The data box RowPitch is not compatible with the region width. This requires additional copy to be implemented.");

                // change the Unpack Alignment
                int previousPackAlignment;
                GL.GetInteger(GetPName.UnpackAlignment, out previousPackAlignment);
                GL.PixelStore(PixelStoreParameter.UnpackAlignment, packAlignment);

                if (activeTexture != 0)
                {
                    activeTexture = 0;
                    GL.ActiveTexture(TextureUnit.Texture0);
                }

                // Update the texture region
                GL.BindTexture(texture.TextureTarget, texture.TextureId);
                GL.TexSubImage2D((TextureTarget2d)texture.TextureTarget, subResourceIndex, region.Left, region.Top, width, height, texture.TextureFormat, texture.TextureType, databox.DataPointer);
                boundShaderResourceViews[0] = null; // bound active texture 0 has changed

                // reset the Unpack Alignment
                GL.PixelStore(PixelStoreParameter.UnpackAlignment, previousPackAlignment);
            }
            else
            {
                var buffer = resource as Buffer;
                if (buffer != null)
                {
                    if (!GraphicsDevice.HasTextureBuffers && buffer.BufferId == 0)
                    {
                        if (activeTexture != 0)
                        {
                            activeTexture = 0;
                            GL.ActiveTexture(TextureUnit.Texture0);
                        }

                        // On platforms where it's not supported, we use a texture instead of a buffer
                        GL.BindTexture(buffer.TextureTarget, buffer.TextureId);
                        boundShaderResourceViews[0] = null; // bound active texture 0 has changed

                        buffer.UpdateTextureSubresource(databox.DataPointer, 0, region.Left, region.Right - region.Left);
                    }
                    else
                    {
                        GL.BindBuffer(buffer.BufferTarget, buffer.BufferId);
                        if (region.Left == 0 && region.Right == buffer.SizeInBytes)
                            GL.BufferData(buffer.BufferTarget, (IntPtr)region.Right, databox.DataPointer, buffer.BufferUsageHint);
                        else
                            GL.BufferSubData(buffer.BufferTarget, (IntPtr)region.Left, (IntPtr)(region.Right - region.Left), databox.DataPointer);
                        GL.BindBuffer(buffer.BufferTarget, 0);
                    }
                }
            }
        }