#[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
*Srgbtexture 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.0is 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 above1.0drive brighter-than-SDR output on HDR displays.
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.
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:
ExtendedSrgbLinearif the format isTextureFormat::Rgba16Floatand the surface supports it for that format,- otherwise
Srgb, if the surface supports it for the format.
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
ExtendedSrgbfor 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’skCGColorSpaceExtendedDisplayP3). Not available on Vulkan or DX12, neither of which has an encoded-extended-Display-P3 swapchain color space.
Implementations§
Source§impl SurfaceColorSpace
impl SurfaceColorSpace
Sourcepub const fn to_color_spaces(self) -> Option<SurfaceColorSpaces>
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).
Sourcepub const fn is_hdr(self) -> bool
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
impl Clone for SurfaceColorSpace
Source§fn clone(&self) -> SurfaceColorSpace
fn clone(&self) -> SurfaceColorSpace
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for SurfaceColorSpace
impl Debug for SurfaceColorSpace
Source§impl Default for SurfaceColorSpace
impl Default for SurfaceColorSpace
Source§fn default() -> SurfaceColorSpace
fn default() -> SurfaceColorSpace
Source§impl<'de> Deserialize<'de> for SurfaceColorSpace
impl<'de> Deserialize<'de> for SurfaceColorSpace
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<SurfaceColorSpace, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<SurfaceColorSpace, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
Source§impl Hash for SurfaceColorSpace
impl Hash for SurfaceColorSpace
Source§impl PartialEq for SurfaceColorSpace
impl PartialEq for SurfaceColorSpace
Source§impl Serialize for SurfaceColorSpace
impl Serialize for SurfaceColorSpace
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
impl Copy for SurfaceColorSpace
impl Eq for SurfaceColorSpace
impl StructuralPartialEq for SurfaceColorSpace
Auto Trait Implementations§
impl Freeze for SurfaceColorSpace
impl RefUnwindSafe for SurfaceColorSpace
impl Send for SurfaceColorSpace
impl Sync for SurfaceColorSpace
impl Unpin for SurfaceColorSpace
impl UnwindSafe for SurfaceColorSpace
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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