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); }
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)); }
internal void UpdateSubresource(GraphicsResource resource, int subResourceIndex, DataBox databox, ResourceRegion region) { NullHelper.ToImplement(); }
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"); } } }
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(); } }
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); }
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)); }
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"); } } }
internal void UpdateSubresource(GraphicsResource resource, int subResourceIndex, DataBox databox, ResourceRegion region) { throw new NotImplementedException(); }
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); } }
/// <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); } } } }