Article

Understanding Color-Renderable Pixel Format Sizes

Know the size limits of pixel formats used by color render targets in iOS and tvOS GPUs.

Overview

A color render target is a texture used as an output destination for color data generated by a render pass. Pixel formats that can be assigned to these color render targets are known as color-renderable pixel formats.

The storage size of each pixel format is determined by the sum of its components. For example, the storage size of BGRA8Unorm is 32 bits per pixel (four 8-bit components), and the storage size of BGR5A1Unorm is 16 bits per pixel (three 5-bit components and one 1-bit component). When multiple render targets are used in a single render pass, the combined storage size for that render pass is equal to the combined size of the pixel formats used by the render targets in that pass.

In iOS and tvOS GPUs, the storage size of color render targets is interpreted differently in tile memory than it is in system memory, according to the color-renderable pixel format that you assign to the target. Because tile memory has a limited size, the combined size of all color render targets in an individual render pass must fit within the tile memory size limit, as shown in Table 1.

Table 1

Maximum number and size of color render targets for each iOS and tvOS GPU

iOS/tvOS GPU

Maximum number of color render targets

Maximum combined size of color render targets

A7

Four per render pass

128 bits per pixel

A8, A9, A10

Eight per render pass

256 bits per pixel

A11

Eight per render pass

512 bits per pixel

In macOS GPUs, you can use up to eight color render targets per render pass with any color-renderable pixel format. Because macOS GPUs don't have tile memory, they don't have a combined size limit for their color render targets.

Pixel Format Size Conversion in Tile Memory

In A7 through A10 GPUs, some color-renderable pixel formats are temporarily expanded to a floating-point representation when stored in tile memory. Therefore, these pixel formats occupy more space in tile memory than they do in system memory, as shown in Table 2 and Table 3.

In A11 GPUs, pixel format conversion occurs on each load and store from tile memory to temporary registers in the shader core. Therefore, most pixel formats occupy the same size in tile memory as they do in system memory. However, there are still a few exceptions, as shown in Table 4.

Table 2

A7 storage sizes, per pixel

Pixel format

Size in system memory (in bits)

Non-MSAA size in tile memory (in bits)

MSAA size in tile memory (in bits)

R8Unorm

R8Unorm_sRGB

R8Snorm

R8Uint

R8Sint

8

32

32

R16Unorm

R16Snorm

R16Uint

R16Sint

R16Float

16

32

32

RG8Unorm

RG8Unorm_sRGB

RG8Snorm

RG8Uint

RG8Sint

16

32

32

B5G6R5Unorm

A1BGR5Unorm

ABGR4Unorm

BGR5A1Unorm

16

32

32

RGBA8Unorm_sRGB

RGBA8Snorm

BGRA8Unorm_sRGB

32

32

64

RGB10A2Unorm

BGR10A2Unorm

32

64

64

RG11B10Float

RGB9E5Float

32

64

64

Table 3

A8, A9, and A10 storage sizes, per pixel

Pixel format

Size in system memory (in bits)

Non-MSAA size in tile memory (in bits)

MSAA size in tile memory (in bits)

R8Unorm

R8Unorm_sRGB

R8Snorm

R8Uint

R8Sint

8

32

32

R16Unorm

R16Snorm

R16Uint

R16Sint

R16Float

16

32

32

RG8Unorm

RG8Unorm_sRGB

RG8Snorm

RG8Uint

RG8Sint

16

32

32

B5G6R5Unorm

A1BGR5Unorm

ABGR4Unorm

BGR5A1Unorm

16

64

64

RGBA8Unorm

RGBA8Unorm_sRGB

RGBA8Snorm

BGRA8Unorm

BGRA8Unorm_sRGB

32

32

64

RGB10A2Unorm

BGR10A2Unorm

32

64

64

RG11B10Float

RGB9E5Float

32

64

64

BGR10_XR

BGR10_XR_sRGB

32

64

64

Table 4

A11 storage sizes, per pixel

Pixel format

Size in system memory (in bits)

Non-MSAA size in tile memory (in bits)

MSAA size in tile memory (in bits)

B5G6R5Unorm

A1BGR5Unorm

ABGR4Unorm

BGR5A1Unorm

16

64

64

BGR10A2Unorm

32

64

64

BGR10_XR

BGR10_XR_sRGB

32

48

48

Knowing the storage sizes is particularly important if you're implementing rendering techniques that use multiple color render targets. For example, you might implement a deferred lighting algorithm that uses four color render targets with different pixel formats:

let gBufferDescriptor = MTLRenderPipelineDescriptor()
gBufferDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm // Albedo data and main drawable
gBufferDescriptor.colorAttachments[1].pixelFormat = .bgra8Unorm // Surface normal data
gBufferDescriptor.colorAttachments[2].pixelFormat = .r16Float   // Linear depth data
gBufferDescriptor.colorAttachments[3].pixelFormat = .r16Float   // Light data
gBufferDescriptor.sampleCount = 4

In this render target configuration, the combined storage size in system memory is 96 bits per pixel (32+32+16+16). For comparison, the combined MSAA storage sizes in tile memory for the GPUs are:

  • A7 GPUs: 128 bits per pixel (32+32+32+32)

  • A8 through A10 GPUs: 192 bits per pixel (64+64+32+32)

  • A11 GPUs: 96 bits per pixel (32+32+16+16)

See Also

Working with Textures

Creating and Sampling Textures

Load image data into a texture and apply it to a quadrangle.

Optimizing Texture Data

Optimize a texture’s data to improve GPU or CPU access.

Improving Filtering Quality and Sampling Performance

Provide multiple levels of detail for your textures by using mipmaps.

Managing Texture Memory

Take direct control of memory allocation for texture data by using sparse textures.

protocol MTLTexture

A resource that holds formatted image data.

class MTLTextureDescriptor

An object that you use to configure new Metal texture objects.

class MTKTextureLoader

An object that decodes common image formats into Metal textures for use in your app.

class MTLSharedTextureHandle

A texture handle that can be shared across process address space boundaries.

enum MTLPixelFormat

The data formats that describe the organization and characteristics of individual pixels in a texture.