/// <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)); }
private void CreateTexture2DArray(bool compressed, int width, int height, int mipLevel, int arrayIndex, DataBox dataBox) { // We create all array slices at once, but upload them one by one if (arrayIndex == 0) { if (compressed) { GL.CompressedTexImage3D((TextureTarget3d)TextureTarget, mipLevel, (CompressedInternalFormat3D)TextureInternalFormat, width, height, ArraySize, 0, 0, IntPtr.Zero); } else { GL.TexImage3D((TextureTarget3d)TextureTarget, mipLevel, (TextureComponentCount3D)TextureInternalFormat, width, height, ArraySize, 0, TextureFormat, TextureType, IntPtr.Zero); } } if (dataBox.DataPointer != IntPtr.Zero) { if (compressed) { GL.CompressedTexSubImage3D((TextureTarget3d)TextureTarget, mipLevel, 0, 0, arrayIndex, width, height, 1, TextureFormat, dataBox.SlicePitch, dataBox.DataPointer); } else { GL.TexSubImage3D((TextureTarget3d)TextureTarget, mipLevel, 0, 0, arrayIndex, width, height, 1, TextureFormat, TextureType, dataBox.DataPointer); } } }
private void CreateTexture3D(bool compressed, int width, int height, int depth, int mipLevel, DataBox dataBox) { if (compressed) { GL.CompressedTexImage3D((TextureTarget3d)TextureTarget, mipLevel, (CompressedInternalFormat3D)TextureInternalFormat, width, height, depth, 0, dataBox.SlicePitch, dataBox.DataPointer); } else { GL.TexImage3D((TextureTarget3d)TextureTarget, mipLevel, (TextureComponentCount3D)TextureInternalFormat, width, height, depth, 0, TextureFormat, TextureType, dataBox.DataPointer); } }
private void CreateTexture2D(bool compressed, int width, int height, int mipLevel, int arrayIndex, DataBox dataBox) { if (IsMultisample) { throw new InvalidOperationException("Currently if multisampling is on, a renderbuffer will be created (not a texture) in any case and this code will not be reached." + "Therefore if this place is reached, it means something went wrong. Once multisampling has been implemented for OpenGL textures, you can remove this exception."); if (IsRenderbuffer) { #if !XENKO_PLATFORM_IOS // MSAA is not supported on iOS currently because OpenTK doesn't expose "GL.BlitFramebuffer()" on iOS for some reason. GL.RenderbufferStorageMultisample(RenderbufferTarget.Renderbuffer, (int)Description.MultisampleCount, (RenderbufferStorage)TextureInternalFormat, width, height); #endif } else { #if XENKO_GRAPHICS_API_OPENGLES throw new NotSupportedException("Multisample textures are not supported on OpenGL ES."); #else GL.TexImage2DMultisample(TextureTargetMultisample.Texture2DMultisample, (int)Description.MultisampleCount, (TextureComponentCount2D)TextureInternalFormat, width, height, false); #endif } } else { var dataSetTarget = GetTextureTargetForDataSet2D(TextureTarget, arrayIndex); if (compressed) { GL.CompressedTexImage2D(dataSetTarget, mipLevel, (CompressedInternalFormat2D)TextureInternalFormat, width, height, 0, dataBox.SlicePitch, dataBox.DataPointer); } else { GL.TexImage2D(dataSetTarget, mipLevel, (TextureComponentCount2D)TextureInternalFormat, width, height, 0, TextureFormat, TextureType, dataBox.DataPointer); } } }
private void InitializeFromImpl(DataBox[] dataBoxes = null) { if (ParentTexture != null) { CopyParentAttributes(); } if (TextureId == 0) { TextureTarget = GetTextureTarget(Dimension); 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; IsDepthBuffer = ((Description.Flags & TextureFlags.DepthStencil) != 0); if (IsDepthBuffer) { HasStencil = InternalHasStencil(Format); } else { HasStencil = false; } if ((Description.Flags & TextureFlagsCustomResourceId) != 0) { return; } using (var openglContext = GraphicsDevice.UseOpenGLCreationContext()) { TextureTotalSize = ComputeBufferTotalSize(); if (Description.Usage == GraphicsResourceUsage.Staging) { InitializeStagingPixelBufferObject(dataBoxes); return; // TODO: This return causes "GraphicsDevice.RegisterTextureMemoryUsage(SizeInBytes);" not to get entered. Is that okay? } // Depth textures are renderbuffers for now // TODO: PERFORMANCE: Why? I think we should change that so we can sample them directly. // TODO: enable switch // TODO: What does this comment even mean? IsRenderbuffer = !Description.IsShaderResource; // Force to renderbuffer if MSAA is on because we don't support MSAA textures ATM (and they don't exist on OpenGL ES). if (Description.IsMultisample) { // TODO: Ideally the caller of this method should be aware of this "force to renderbuffer", // because the caller won't be able to bind it as a texture. IsRenderbuffer = true; } if (IsRenderbuffer) { CreateRenderbuffer(); return; // TODO: This return causes "GraphicsDevice.RegisterTextureMemoryUsage(SizeInBytes);" not to get entered. Is that okay? } GL.GenTextures(1, out TextureId); GL.BindTexture(TextureTarget, TextureId); SetFilterMode(); if (Description.MipLevels == 0) { throw new NotImplementedException(); } var setSize = TextureSetSize(TextureTarget); for (var arrayIndex = 0; arrayIndex < Description.ArraySize; ++arrayIndex) { int offsetArray = arrayIndex * Description.MipLevels; for (int mipLevel = 0; mipLevel < Description.MipLevels; ++mipLevel) { DataBox dataBox; Int3 dimensions = new Int3(CalculateMipSize(Description.Width, mipLevel), CalculateMipSize(Description.Height, mipLevel), CalculateMipSize(Description.Depth, mipLevel)); if (dataBoxes != null && mipLevel < dataBoxes.Length) { if (setSize > 1 && !compressed && dataBoxes[mipLevel].RowPitch != dimensions.X * TexturePixelSize) { throw new NotSupportedException("Can't upload texture with pitch in glTexImage2D/3D."); } // Might be possible, need to check API better. dataBox = dataBoxes[offsetArray + mipLevel]; } else { dataBox = new DataBox(); } switch (TextureTarget) { case TextureTarget.Texture1D: CreateTexture1D(compressed, dimensions.X, mipLevel, dataBox); break; case TextureTarget.Texture2D: case TextureTarget.TextureCubeMap: CreateTexture2D(compressed, dimensions.X, dimensions.Y, mipLevel, arrayIndex, dataBox); break; case TextureTarget.Texture3D: CreateTexture3D(compressed, dimensions.X, dimensions.Y, dimensions.Z, mipLevel, dataBox); break; case TextureTarget.Texture2DArray: CreateTexture2DArray(compressed, dimensions.X, dimensions.Y, mipLevel, arrayIndex, dataBox); break; } } } GL.BindTexture(TextureTarget, 0); // This unbinds the texture. 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.RegisterTextureMemoryUsage(SizeInBytes); } }
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(); }