/// <summary> /// Creates a new Cube <see cref="Texture" /> from a initial data.. /// </summary> /// <typeparam name="T">Type of a pixel data</typeparam> /// <param name="device">The <see cref="GraphicsDevice" />.</param> /// <param name="size">The size (in pixels) of the top-level faces of the cube texture.</param> /// <param name="format">Describes the format to use.</param> /// <param name="textureData">an array of 6 textures. See remarks</param> /// <param name="textureFlags">The texture flags.</param> /// <param name="usage">The usage.</param> /// <returns>A new instance of Cube <see cref="Texture" /> class.</returns> /// <exception cref="System.ArgumentException">Invalid texture datas. First dimension must be equal to 6;textureData</exception> /// <remarks>The first dimension of mipMapTextures describes the number of array (TextureCube Array), the second is the texture data for a particular cube face.</remarks> public unsafe static Texture NewCube <T>(GraphicsDevice device, int size, PixelFormat format, T[][] textureData, TextureFlags textureFlags = TextureFlags.ShaderResource, GraphicsResourceUsage usage = GraphicsResourceUsage.Immutable) where T : struct { if (textureData.Length != 6) { throw new ArgumentException("Invalid texture datas. First dimension must be equal to 6", "textureData"); } var dataBoxes = new DataBox[6]; dataBoxes[0] = GetDataBox(format, size, size, 1, textureData[0], (IntPtr)Interop.Fixed(textureData[0])); dataBoxes[1] = GetDataBox(format, size, size, 1, textureData[0], (IntPtr)Interop.Fixed(textureData[1])); dataBoxes[2] = GetDataBox(format, size, size, 1, textureData[0], (IntPtr)Interop.Fixed(textureData[2])); dataBoxes[3] = GetDataBox(format, size, size, 1, textureData[0], (IntPtr)Interop.Fixed(textureData[3])); dataBoxes[4] = GetDataBox(format, size, size, 1, textureData[0], (IntPtr)Interop.Fixed(textureData[4])); dataBoxes[5] = GetDataBox(format, size, size, 1, textureData[0], (IntPtr)Interop.Fixed(textureData[5])); return(new Texture(device).InitializeFrom(TextureDescription.NewCube(size, format, textureFlags, usage), dataBoxes)); }
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) { 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 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(); } }
internal void UpdateSubresource(GraphicsResource resource, int subResourceIndex, DataBox databox) { throw new NotImplementedException(); }
private void InitializeFromImpl(DataBox[] dataBoxes = null) { if (ParentTexture != null) { TextureId = ParentTexture.TextureId; // copy parameters TextureInternalFormat = ParentTexture.TextureInternalFormat; TextureFormat = ParentTexture.TextureFormat; TextureType = ParentTexture.TextureType; TextureTarget = ParentTexture.TextureTarget; DepthPitch = ParentTexture.DepthPitch; RowPitch = ParentTexture.RowPitch; IsDepthBuffer = ParentTexture.IsDepthBuffer; HasStencil = ParentTexture.HasStencil; IsRenderbuffer = ParentTexture.IsRenderbuffer; stencilId = ParentTexture.StencilId; pixelBufferObjectId = ParentTexture.PixelBufferObjectId; } if (TextureId == 0) { switch (Dimension) { case TextureDimension.Texture1D: #if !SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGLES if (ArraySize > 1) { throw new PlatformNotSupportedException("Texture1DArray is not implemented under OpenGL"); } TextureTarget = TextureTarget.Texture1D; break; #endif case TextureDimension.Texture2D: TextureTarget = ArraySize > 1 ? TextureTarget.Texture2DArray : TextureTarget.Texture2D; break; case TextureDimension.Texture3D: TextureTarget = TextureTarget.Texture3D; break; case TextureDimension.TextureCube: if (ArraySize > 6) { throw new PlatformNotSupportedException("TextureCubeArray is not implemented under OpenGL"); } TextureTarget = TextureTarget.TextureCubeMap; break; default: throw new ArgumentOutOfRangeException(); } bool compressed; OpenGLConvertExtensions.ConvertPixelFormat(GraphicsDevice, ref textureDescription.Format, out TextureInternalFormat, out TextureFormat, out TextureType, out TexturePixelSize, out compressed); DepthPitch = Description.Width * Description.Height * TexturePixelSize; RowPitch = Description.Width * TexturePixelSize; if ((Description.Flags & TextureFlags.DepthStencil) != 0) { IsDepthBuffer = true; HasStencil = InternalHasStencil(Format); } else { IsDepthBuffer = false; HasStencil = false; } if ((Description.Flags & TextureFlagsCustomResourceId) != 0) { return; } using (var openglContext = GraphicsDevice.UseOpenGLCreationContext()) { // Depth texture are render buffer for now // TODO: enable switch if ((Description.Flags & TextureFlags.DepthStencil) != 0 && (Description.Flags & TextureFlags.ShaderResource) == 0) { RenderbufferStorage depth, stencil; ConvertDepthFormat(GraphicsDevice, Description.Format, out depth, out stencil); GL.GenRenderbuffers(1, out TextureId); GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, TextureId); GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, depth, Width, Height); if (stencil != 0) { // separate stencil GL.GenRenderbuffers(1, out stencilId); GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, stencilId); GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, stencil, Width, Height); } else if (HasStencil) { // depth+stencil in a single texture stencilId = TextureId; } GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, 0); IsRenderbuffer = true; return; } IsRenderbuffer = false; TextureTotalSize = ComputeBufferTotalSize(); if (Description.Usage == GraphicsResourceUsage.Staging) { InitializeStagingPixelBufferObject(dataBoxes); return; } GL.GenTextures(1, out TextureId); GL.BindTexture(TextureTarget, TextureId); // No filtering on depth buffer if ((Description.Flags & (TextureFlags.RenderTarget | TextureFlags.DepthStencil)) != TextureFlags.None) { GL.TexParameter(TextureTarget, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); GL.TexParameter(TextureTarget, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); GL.TexParameter(TextureTarget, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge); GL.TexParameter(TextureTarget, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge); BoundSamplerState = GraphicsDevice.SamplerStates.PointClamp; if (HasStencil) { // depth+stencil in a single texture stencilId = TextureId; } } #if SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGLES else if (Description.MipLevels <= 1) { GL.TexParameter(TextureTarget, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); GL.TexParameter(TextureTarget, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); } #endif #if SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGLES if (!GraphicsDevice.IsOpenGLES2) #endif { GL.TexParameter(TextureTarget, TextureParameterName.TextureBaseLevel, 0); GL.TexParameter(TextureTarget, TextureParameterName.TextureMaxLevel, Description.MipLevels - 1); } if (Description.MipLevels == 0) { throw new NotImplementedException(); } var setSize = TextureSetSize(TextureTarget); for (var arrayIndex = 0; arrayIndex < Description.ArraySize; ++arrayIndex) { var offsetArray = arrayIndex * Description.MipLevels; for (int i = 0; i < Description.MipLevels; ++i) { DataBox dataBox; var width = CalculateMipSize(Description.Width, i); var height = CalculateMipSize(Description.Height, i); var depth = CalculateMipSize(Description.Depth, i); if (dataBoxes != null && i < dataBoxes.Length) { if (setSize > 1 && !compressed && dataBoxes[i].RowPitch != width * TexturePixelSize) { throw new NotSupportedException("Can't upload texture with pitch in glTexImage2D/3D."); } // Might be possible, need to check API better. dataBox = dataBoxes[offsetArray + i]; } else { dataBox = new DataBox(); } switch (TextureTarget) { #if !SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGLES case TextureTarget.Texture1D: if (compressed) { GL.CompressedTexImage1D(TextureTarget, i, TextureInternalFormat, width, 0, dataBox.SlicePitch, dataBox.DataPointer); } else { GL.TexImage1D(TextureTarget, i, TextureInternalFormat, width, 0, TextureFormat, TextureType, dataBox.DataPointer); } break; #endif case TextureTarget.Texture2D: case TextureTarget.TextureCubeMap: { var dataSetTarget = GetTextureTargetForDataSet2D(TextureTarget, arrayIndex); if (compressed) { GL.CompressedTexImage2D(dataSetTarget, i, (CompressedInternalFormat2D)TextureInternalFormat, width, height, 0, dataBox.SlicePitch, dataBox.DataPointer); } else { GL.TexImage2D(dataSetTarget, i, (TextureComponentCount2D)TextureInternalFormat, width, height, 0, TextureFormat, TextureType, dataBox.DataPointer); } break; } case TextureTarget.Texture3D: { if (compressed) { GL.CompressedTexImage3D((TextureTarget3d)TextureTarget, i, (CompressedInternalFormat3D)TextureInternalFormat, width, height, depth, 0, dataBox.SlicePitch, dataBox.DataPointer); } else { GL.TexImage3D((TextureTarget3d)TextureTarget, i, (TextureComponentCount3D)TextureInternalFormat, width, height, depth, 0, TextureFormat, TextureType, dataBox.DataPointer); } break; } case TextureTarget.Texture2DArray: { // We create all array slices at once, but upload them one by one if (arrayIndex == 0) { if (compressed) { GL.CompressedTexImage3D((TextureTarget3d)TextureTarget, i, (CompressedInternalFormat3D)TextureInternalFormat, width, height, ArraySize, 0, 0, IntPtr.Zero); } else { GL.TexImage3D((TextureTarget3d)TextureTarget, i, (TextureComponentCount3D)TextureInternalFormat, width, height, ArraySize, 0, TextureFormat, TextureType, IntPtr.Zero); } } if (dataBox.DataPointer != IntPtr.Zero) { if (compressed) { GL.CompressedTexSubImage3D((TextureTarget3d)TextureTarget, i, 0, 0, arrayIndex, width, height, 1, TextureFormat, dataBox.SlicePitch, dataBox.DataPointer); } else { GL.TexSubImage3D((TextureTarget3d)TextureTarget, i, 0, 0, arrayIndex, width, height, 1, TextureFormat, TextureType, dataBox.DataPointer); } } break; } } } } GL.BindTexture(TextureTarget, 0); if (openglContext.CommandList != null) { // If we messed up with some states of a command list, mark dirty states openglContext.CommandList.boundShaderResourceViews[openglContext.CommandList.activeTexture] = null; } } GraphicsDevice.TextureMemory += (Depth * DepthStride) / (float)0x100000; } }