Textures
Textures are device resources used as the source and destination of texture information. Textures can be created with a variety of options, controlling how individual instances are permitted to be used.
Format
Texture data is stored in one of a number of formats, specified by the TextureDescription.Format field.
Type and Dimensions
Textures can be 1D, 2D, or 3D. This is controlled by TextureDescription.Type. The actual dimensions of the Texture are controlled by TextureDescription.Width, TextureDescription.Height, and TextureDescription.Depth. For any particular type of Texture (1D, 2D, 3D), the dimensions must be valid. For example, a 1D Texture cannot have a Height or Depth greater than 1. A 2D Texture cannot have a depth value greater than 1.
Array Layers
1D and 2D textures can have multiple array layers. 3D textures (TextureType.Texture3D) cannot. To control the number of array layers, set TextureDescription.ArrayLayers.
Multisamples
2D Textures can be multisampled Textures. 1D and 3D textures cannot. This is specified by TextureDescription.SampleCount. The maximum sample count is limited by the specific GraphicsDevice being used. Use the GetSampleCountLimit method to get the maximum sample count for a given PixelFormat. Generally, 2 through 8 samples are commonly-supported. Higher values are rarely supported, but often unnecessary.
Mipmaps
Non-multisampled textures can have multiple mipmap levels. This is specified by TextureDescription.MipLevels.
As Shader Resources
In order to be read in a shader, a Texture needs to be created with the TextureUsage.Sampled flag. Additionally, the dimension of the Texture object must match what is used in the shader program. For example, an HLSL Texture2D must be matched with a 2D non-multisampled Texture object.
To bind a Texture to a shader program, a TextureView resource must be created. This TextureView can be used in a ResourceSet to make the Texture available to the shader.
Textures can also be written to in shaders, if they were created using the TextureUsage.Storage flag.
As Framebuffer Targets
Textures can be used as Framebuffer targets. To use a Texture as a color target, it must have been created with the TextureUsage.RenderTarget flag. To use a Texture as a depth target, it must have been created with the TextureUsage.DepthStencil flag.
Updating a Texture
Texture data is uploaded from CPU memory using the GraphicsDevice.UpdateTexture method. This method can be used to upload the data for a subregion of a single mipmap level and array layer. Multiple calls should be used to fully upload all of the mipmap levels and array layers for a Texture, as appropriate.
Staging Textures
Although GraphicsDevice.UpdateTexture can always be used to update a Texture object, it is more efficient to first upload the data into an intermediate "Staging Texture", and then schedule a copy from that resource into the Texture you wish to render with. A "Staging Texture" is simply a Texture created with the TextureUsage.Staging usage flag.
Staging Textures can be "mapped" into a CPU-visible data range. This allows you to write directly into a region specifically prepared by the GPU driver to transfer texture data. After the data has been mapped and unmapped (see GraphicsDevice.Map and GraphicsDevice.Unmap), you should then schedule a copy using CommandList.CopyTexture.
Reading back Texture data
A Staging Texture is also needed to read back texture data from the GPU. A Texture should be mapped using MapMode.Read or MapMode.ReadWrite.
Initial Texture Data
Before a Texture is populated (using UpdateTexture, CopyTexture, or by drawing into it), its contents are undefined. It is not meaningful to copy this data back into a CPU buffer or manipulate it in any way. Some backends may default-initialize a Texture to a certain value in some cases (commonly transparent black, or all zeroes), but this behavior cannot be relied on.