SurfaceColorSpace

Enum SurfaceColorSpace 

Source
#[repr(C)]
pub enum SurfaceColorSpace { Auto = 0, Srgb = 1, ExtendedSrgbLinear = 2, DisplayP3 = 3, Bt2100Pq = 4, Bt2100Hlg = 5, ExtendedSrgb = 6, ExtendedDisplayP3 = 7, }
Expand description

The color space in which the presentation engine interprets the values written to a surface texture.

A color space defines the primaries, white point, and transfer function of the output signal (see the Terminology section below), following the same convention as CSS predefined color spaces and VkColorSpaceKHR. It does not change the texel format of the surface; it changes how the compositor / display pipeline interprets those texels.

Support is queried via SurfaceCapabilities, which reports a set of SurfaceColorSpaces for every supported texture format. Selecting a color space other than Srgb is how an application opts a surface into high-dynamic-range (HDR) or wide-color-gamut output on platforms that support it.

New to HDR? The wgpu crate’s top-level docs include a color space and HDR primer covering the concepts and the steps to get HDR output on screen.

§Terminology

Each variant is described by four properties:

  • Primaries (the gamut): the chromaticities of the red, green, and blue that color values address, and so the range of colors that can be expressed. BT.709 (the sRGB / HDTV primaries) is the standard-gamut set; Display P3 and BT.2020 are progressively wider.
  • White point: the chromaticity produced by equal red, green, and blue. Every color space here uses D65, the standard daylight white.
  • Transfer function (the OETF): how stored values map to light, such as the sRGB transfer function, a linear transfer, or an HDR transfer function like PQ or HLG. Your shader applies this encoding transfer function; the display applies the inverse (the EOTF). Except for writes to an *Srgb texture format (where the hardware applies the sRGB encoding for you), wgpu does not encode for you: the values your shader writes to the surface texture must already be in whatever encoding the chosen color space expects (linear for a linear transfer). The HDR surface example shows the encoder each variant expects.
  • Dynamic range: standard dynamic range (SDR), where 1.0 is reference (SDR) white and values outside 0.0..=1.0 are clamped, or high dynamic range (HDR), where (1.0, 1.0, 1.0) is SDR reference white and values above 1.0 drive brighter-than-SDR output on HDR displays.

CIE 1931 chromaticity diagram with sRGB, Display-P3 and BT.2020 gamut trianglesThe red, green and blue primaries of sRGB/BT.709, Display-P3 and BT.2020 plotted as nested triangles inside the CIE 1931 spectral locus, sharing the D65 white point. A wider triangle can express more colors.

00.20.40.600.20.40.60.8 CIE x CIE y D65 sRGB / BT.709 Display-P3 BT.2020

The primaries of each color space form a triangle on the CIE 1931 chromaticity diagram; colors inside it are expressible, colors outside are not. Srgb uses the BT.709 gamut; DisplayP3 and Bt2100Pq’s BT.2020 are progressively wider. All share the D65 white point.

SDR vs HDR value range number lineA number line: 0.0 black, 0 to 1 is the SDR range, 1.0 is SDR reference white, values above 1.0 are HDR headroom up to the display’s peak.0.01.0peakSDR rangeHDR headroom (> 1.0)blackSDR reference whitedisplay peakSDR clamps at 1.0. HDR drives values above 1.0, up to the display’s headroom.

0.0 is black and 1.0 is SDR reference white. Srgb and DisplayP3 clamp above 1.0; the extended-range and HDR color spaces drive values above 1.0 as brighter-than-SDR output, up to the display’s headroom (query it via DisplayHdrInfo::tone_map_headroom).

§Extended-range variants: linear vs encoded

The extended-range color spaces come in two forms that share a range but differ in transfer: ExtendedSrgbLinear carries a linear signal, while ExtendedSrgb and ExtendedDisplayP3 carry the sRGB-encoded (gamma) signal: the sRGB transfer function is applied as usual and then continued to values above 1.0 (brighter than SDR white) and below 0.0 (colors outside the base gamut). Pick by whether the values your shader writes to the surface texture are linear or encoded; confusing the two is the most common HDR setup mistake.

§Web (WebGPU) backend

Browsers do not expose these named color spaces directly. A WebGPU canvas is configured with a colorSpace (only "srgb" or "display-p3") plus a separate toneMapping mode ("standard" or "extended"), so on the web wgpu offers only the combinations that pair can produce: Srgb and DisplayP3 with standard tone mapping, plus their extended-range HDR forms ExtendedSrgb and ExtendedDisplayP3 with extended tone mapping. There is no linear-transfer canvas color space, so ExtendedSrgbLinear (scRGB) is native-only, and Bt2100Pq and Bt2100Hlg are unavailable (browsers expose no PQ or HLG canvas signaling).

Variants§

§

Auto = 0

Let the backend choose a color space, reproducing wgpu’s historical behavior:

Apart from the linear ExtendedSrgbLinear above (which fp16 surfaces have historically used and which needs no extra encoding), Auto never resolves to a wide-gamut or HDR color space, since those would change how the application must encode its output. If a format is only available in such color spaces (which some drivers report when the OS is in HDR mode), configuring it with Auto fails validation; such formats are listed in SurfaceCapabilities::format_capabilities but excluded from SurfaceCapabilities::formats.

On the browser WebGPU backend, Auto always keeps the canvas defaults (sRGB with standard tone mapping), even for TextureFormat::Rgba16Float; request ExtendedSrgb explicitly for HDR canvas output (ExtendedSrgbLinear is native-only).

§

Srgb = 1

The sRGB color space: BT.709 primaries, D65 white point, sRGB transfer function, standard dynamic range.

Values outside of 0.0..=1.0 (after format encoding) are clamped by the display pipeline.

This is what every backend produces today for non-Rgba16Float formats and is supported everywhere.

Note that the transfer function is applied by the format, not this color space choice: an *Srgb format applies sRGB encoding on write, while writes to a non-*Srgb format are interpreted as already sRGB-encoded.

§

ExtendedSrgbLinear = 2

Extended linear sRGB, also known as scRGB (the linear encoding of IEC 61966-2-2): BT.709 primaries, D65 white point, linear transfer function, extended dynamic range. Typically used with TextureFormat::Rgba16Float.

The linear counterpart to the sRGB-encoded ExtendedSrgb (IEC 61966-2-2 defines both); pick this one if the values your shader writes to the surface texture are linear.

This corresponds to Vulkan’s VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT, Metal’s extended dynamic range (EDR), and DXGI’s DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709.

  • Supported on: native only (Vulkan, Metal, DX12). Not available on the browser WebGPU backend, which cannot express a linear-transfer canvas color space; use ExtendedSrgb for HDR canvas output on the web.
  • Also known as: scRGB.
§

DisplayP3 = 3

The Display P3 color space: P3 primaries, D65 white point, sRGB transfer function, standard dynamic range.

A wide-gamut SDR color space covering roughly 25% more area than sRGB in the CIE chromaticity diagram. It uses the wide P3 primaries of theatrical DCI-P3, but with the D65 white point and the sRGB transfer function (not DCI’s white point and 2.6 gamma).

Like Srgb, this is standard dynamic range (values outside 0.0..=1.0 are clamped). For wide-gamut HDR that keeps the P3 primaries but extends the range, use ExtendedDisplayP3.

  • Supported on: Vulkan (where the driver exposes it), Metal, and the browser WebGPU backend (canvas color space "display-p3"). Not reported on DX12.
§

Bt2100Pq = 4

BT.2100 perceptual quantization (HDR10): BT.2020/2100 primaries, D65 white point, SMPTE ST 2084 perceptual quantizer (PQ) transfer function, high dynamic range.

Texel values are interpreted as a PQ-encoded signal whose encoded range, 0.0..=1.0, maps to absolute luminance from 0 to 10,000 nits. The values your shader writes to the surface texture must already be in the BT.2020 gamut and PQ-encoded into that 0.0..=1.0 range; the HDR surface example shows how. The format is non-sRGB, typically TextureFormat::Rgb10a2Unorm.

Commonly known as HDR10 — though that term additionally implies static ST 2086 / MaxCLL mastering metadata, which wgpu does not set; this configures only the PQ color space.

  • Supported on: Vulkan (where the driver exposes it), DX12 (on Rgb10a2Unorm), and Metal. Unavailable on the browser WebGPU backend (no PQ canvas signaling).
§

Bt2100Hlg = 5

BT.2100 hybrid log-gamma: BT.2020/2100 primaries, D65 white point, HLG (ARIB STD-B67) transfer function, high dynamic range.

A relative-luminance HDR signal, primarily used for broadcast content. The values your shader writes to the surface texture must already be in the BT.2020 gamut and HLG-encoded into 0.0..=1.0; the HDR surface example shows how. The format is non-sRGB, typically TextureFormat::Rgb10a2Unorm.

Unlike Bt2100Pq’s PQ, the HLG signal is relative: 1.0 maps to the display’s nominal peak luminance rather than a fixed absolute level. BT.2100 defines its reference OOTF at a nominal peak of 1000 cd/m² (system gamma 1.2); the HDR surface example normalizes its absolute-nit test pattern onto that 1000-nit nominal peak.

  • Supported on: Vulkan (where the driver exposes it) and Metal. Unavailable on DX12 and the browser WebGPU backend (no HLG canvas signaling).
§

ExtendedSrgb = 6

Extended-range sRGB (encoded): BT.709 primaries, D65 white point, the nonlinear sRGB transfer function extended beyond 0.0..=1.0, extended dynamic range.

The sRGB-encoded sibling of ExtendedSrgbLinear: the signal is sRGB-encoded (gamma), not linear. Typically used with TextureFormat::Rgba16Float.

If the values your shader writes to the surface texture are linear, you want ExtendedSrgbLinear (scRGB) instead; confusing the two is the most common HDR setup mistake. See the HDR surface example for the encoder.

This is the “encoded extended range” sRGB used by browser WebGPU (canvas color space "srgb" with "extended" tone mapping). It corresponds to Vulkan’s VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT and Metal’s kCGColorSpaceExtendedSRGB.

  • Supported on: Vulkan (where the driver exposes it), Metal, and the browser WebGPU backend. Not available on DX12, which has no encoded-extended-sRGB swapchain color space.
§

ExtendedDisplayP3 = 7

Extended-range Display-P3 (encoded): P3 primaries, D65 white point, the nonlinear sRGB transfer function extended beyond 0.0..=1.0, extended dynamic range.

The wide-gamut (P3) analogue of ExtendedSrgb, and the HDR counterpart to the SDR-only DisplayP3: it keeps the P3 primaries but extends the encoded range for HDR. Like ExtendedSrgb the signal is sRGB-encoded (gamma), not linear. Typically used with TextureFormat::Rgba16Float.

  • Supported on: Metal and the browser WebGPU backend (canvas color space "display-p3" with "extended" tone mapping; Metal’s kCGColorSpaceExtendedDisplayP3). Not available on Vulkan or DX12, neither of which has an encoded-extended-Display-P3 swapchain color space.

Implementations§

Source§

impl SurfaceColorSpace

Source

pub const fn to_color_spaces(self) -> Option<SurfaceColorSpaces>

Returns the SurfaceColorSpaces flag set holding just this color space, or None for Auto (which maps to no specific flag).

Source

pub const fn is_hdr(self) -> bool

Whether this is a high-dynamic-range color space: one that drives values above SDR white (1.0) as brighter-than-white output.

true for the extended-range and PQ/HLG spaces; false for the SDR ones (Srgb and the wide-gamut-but-SDR DisplayP3). Auto is false: it defers to the backend and is the SDR-safe default, so check the resolved color space if you need certainty.

Use this to branch after picking a color space from SurfaceCapabilities: an HDR result is the one whose highlights you scale by DisplayHdrInfo::tone_map_headroom.

Trait Implementations§

Source§

impl Clone for SurfaceColorSpace

Source§

fn clone(&self) -> SurfaceColorSpace

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SurfaceColorSpace

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for SurfaceColorSpace

Source§

fn default() -> SurfaceColorSpace

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for SurfaceColorSpace

Source§

fn deserialize<__D>( __deserializer: __D, ) -> Result<SurfaceColorSpace, <__D as Deserializer<'de>>::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Hash for SurfaceColorSpace

Source§

fn hash<__H>(&self, state: &mut __H)
where __H: Hasher,

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for SurfaceColorSpace

Source§

fn eq(&self, other: &SurfaceColorSpace) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for SurfaceColorSpace

Source§

fn serialize<__S>( &self, __serializer: __S, ) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl Copy for SurfaceColorSpace

Source§

impl Eq for SurfaceColorSpace

Source§

impl StructuralPartialEq for SurfaceColorSpace

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> AsAny for T
where T: 'static,

Source§

fn as_any(&self) -> &(dyn Any + 'static)

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

impl<T> Downcast<T> for T

§

fn downcast(&self) -> &T

§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> Upcast<T> for T

§

fn upcast(&self) -> Option<&T>

§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CommonTraits for T
where T: AsAny + Any + Debug + WasmNotSendSync,

Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,