Skip to content

Commit e11059c

Browse files
authored
fix(🪐): high bit depth for onscreen surfaces (#409)
1 parent 4fdc44e commit e11059c

20 files changed

Lines changed: 331 additions & 26 deletions

File tree

apps/docs/app/(content)/api/layout.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export default function Layout({ children }: { children: ReactNode }) {
1414
<DocsLayout
1515
tree={apiSource.getPageTree()}
1616
{...sideBarOptions()}
17+
searchToggle={{ enabled: false }}
1718
sidebar={docsLayoutSidebarOptions()}
1819
containerProps={{
1920
className: `${docsLayoutContainerClassName} ${apiReferenceSidebarWidthClassName}`,

apps/docs/app/(home)/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export default function HomePage() {
4747
}`}
4848
>
4949
Powered by Dawn.<br />
50-
Runs on iOS, Android, macOS, visionOS, and Web.
50+
Built for iOS, Android, macOS, visionOS, and Web.
5151
</p>
5252
<div className="pointer-events-auto mt-10 flex flex-wrap items-center justify-center gap-3">
5353
<Link

apps/docs/content/api/gpu-device-extensions.mdx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,21 @@ device.queue.copyExternalImageToTexture(
121121
);
122122
bitmap.close();
123123
```
124+
125+
## getPreferredHighBitDepthCanvasFormat
126+
127+
Returns the canvas texture format most likely to reach the display with more than 8 bits per channel on the current platform: `"rgba16float"` on iOS, `"rgb10a2unorm"` on Android.
128+
Unlike `getPreferredCanvasFormat()`, this helper is not part of the WebGPU standard, so it is exported as a regular function instead of a `navigator.gpu` method.
129+
130+
```tsx twoslash
131+
import type { RNCanvasContext } from "react-native-webgpu";
132+
import { getPreferredHighBitDepthCanvasFormat } from "react-native-webgpu";
133+
declare const context: RNCanvasContext;
134+
declare const device: GPUDevice;
135+
// ---cut---
136+
const format = getPreferredHighBitDepthCanvasFormat();
137+
context.configure({ device, format, alphaMode: "opaque" });
138+
```
139+
140+
The values you write stay sRGB-encoded exactly like on an 8-bit canvas: this is about precision, not HDR (no extended range).
141+
See [High bit depth](/docs/getting-started/native-api#high-bit-depth) for the platform details and banding comparison.

apps/docs/content/docs/getting-started/native-api.mdx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,25 @@ device.queue.copyExternalImageToTexture(
5757

5858
See [`copyExternalImageToTexture`](https://developer.mozilla.org/en-US/docs/Web/API/GPUQueue/copyExternalImageToTexture) on MDN.
5959

60+
## High bit depth
61+
62+
By default a canvas is configured with an 8-bit format (`bgra8unorm` or `rgba8unorm`, the value returned by `navigator.gpu.getPreferredCanvasFormat()` depending on the platform).
63+
With only 256 levels per channel, subtle gradients quantize into visible bands, especially in dark tones and on OLED displays.
64+
65+
To configure the canvas with a higher-precision format, use `getPreferredHighBitDepthCanvasFormat()` (currently it will return `rgba16float` on iOS and `rgb10a2unorm` on Android):
66+
67+
```tsx twoslash
68+
import type { RNCanvasContext } from "react-native-webgpu";
69+
import { getPreferredHighBitDepthCanvasFormat } from "react-native-webgpu";
70+
declare const context: RNCanvasContext;
71+
declare const device: GPUDevice;
72+
// ---cut---
73+
// "rgba16float" on iOS, "rgb10a2unorm" on Android
74+
const format = getPreferredHighBitDepthCanvasFormat();
75+
76+
context.configure({ device, format, alphaMode: "opaque" });
77+
```
78+
6079
## Native textures
6180

6281
Beyond the standard API, react-native-webgpu exposes Dawn's native surface interop so you can sample camera and video frames with zero copies through the CPU:

apps/docs/next-env.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/// <reference types="next" />
22
/// <reference types="next/image-types/global" />
3-
import "./.next/dev/types/routes.d.ts";
3+
import "./.next/types/routes.d.ts";
44

55
// NOTE: This file should not be edited
66
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

apps/docs/tsconfig.tsbuildinfo

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

apps/example/ios/Podfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,7 +1924,7 @@ PODS:
19241924
- ReactCommon/turbomodule/core
19251925
- SocketRocket
19261926
- Yoga
1927-
- react-native-webgpu (0.5.15):
1927+
- react-native-webgpu (0.0.0):
19281928
- boost
19291929
- DoubleConversion
19301930
- fast_float
@@ -3074,7 +3074,7 @@ SPEC CHECKSUMS:
30743074
React-microtasksnativemodule: 75b6604b667d297292345302cc5bfb6b6aeccc1b
30753075
react-native-safe-area-context: c00143b4823773bba23f2f19f85663ae89ceb460
30763076
react-native-skia: fc73e9bdc46ebb420a98c9c2be29fee80f565e79
3077-
react-native-webgpu: 7a604a7936a2e3fdc93bd48813bcba0165ada8cc
3077+
react-native-webgpu: 3eb051bebe030f328725fc318a147599c4628e4e
30783078
React-NativeModulesApple: 879fbdc5dcff7136abceb7880fe8a2022a1bd7c3
30793079
React-oscompat: 93b5535ea7f7dff46aaee4f78309a70979bdde9d
30803080
React-perflogger: 5536d2df3d18fe0920263466f7b46a56351c0510

apps/example/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"react-native-vision-camera": "5.0.10",
4242
"react-native-vision-camera-worklets": "5.0.10",
4343
"react-native-web": "^0.21.2",
44-
"react-native-webgpu": "*",
44+
"react-native-webgpu": "workspace:*",
4545
"react-native-worklets": "0.8.3",
4646
"teapot": "^1.0.0",
4747
"three": "0.184.0",

apps/example/src/App.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import { StorageBufferVertices } from "./StorageBufferVertices";
3939
import { SharedTextureMemory } from "./SharedTextureMemory";
4040
import { ImportExternalTexture } from "./ImportExternalTexture";
4141
import { VisionCamera } from "./VisionCamera";
42+
import { SixteenBitTextures } from "./SixteenBitTextures";
4243

4344
// The two lines below are needed by three.js
4445
import "fast-text-encoding";
@@ -109,6 +110,10 @@ function App() {
109110
component={ImportExternalTexture}
110111
/>
111112
<Stack.Screen name="VisionCamera" component={VisionCamera} />
113+
<Stack.Screen
114+
name="SixteenBitTextures"
115+
component={SixteenBitTextures}
116+
/>
112117
</Stack.Navigator>
113118
</NavigationContainer>
114119
</GestureHandlerRootView>

apps/example/src/Home.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ export const examples = [
139139
screen: "VisionCamera",
140140
title: "📷 VisionCamera integration",
141141
},
142+
{
143+
screen: "SixteenBitTextures",
144+
title: "🎨 16bits Textures",
145+
},
142146
];
143147

144148
const styles = StyleSheet.create({

0 commit comments

Comments
 (0)