diff --git a/apps/example/src/Triangle/HelloTriangle.tsx b/apps/example/src/Triangle/HelloTriangle.tsx
index ca753b82..715da40a 100644
--- a/apps/example/src/Triangle/HelloTriangle.tsx
+++ b/apps/example/src/Triangle/HelloTriangle.tsx
@@ -25,7 +25,7 @@ export function HelloTriangle() {
context.configure({
device,
format: presentationFormat,
- alphaMode: "opaque",
+ alphaMode: "premultiplied",
});
const pipeline = device.createRenderPipeline({
@@ -79,7 +79,8 @@ export function HelloTriangle() {
return (
-
+
+
);
}
@@ -88,7 +89,4 @@ const style = StyleSheet.create({
container: {
flex: 1,
},
- webgpu: {
- flex: 1,
- },
});
diff --git a/apps/example/src/Triangle/triangle.ts b/apps/example/src/Triangle/triangle.ts
index 3981386b..f4f6bc98 100644
--- a/apps/example/src/Triangle/triangle.ts
+++ b/apps/example/src/Triangle/triangle.ts
@@ -14,4 +14,4 @@ fn main(
export const redFragWGSL = `@fragment
fn main() -> @location(0) vec4f {
return vec4(1.0, 0.0, 0.0, 1.0);
-}`;
+}`;
\ No newline at end of file
diff --git a/packages/webgpu/cpp/rnwgpu/api/Convertors.h b/packages/webgpu/cpp/rnwgpu/api/Convertors.h
index e35ea6f3..537e3a7b 100644
--- a/packages/webgpu/cpp/rnwgpu/api/Convertors.h
+++ b/packages/webgpu/cpp/rnwgpu/api/Convertors.h
@@ -280,15 +280,6 @@ class Convertor {
Convert(out.label, in.label);
}
- // [[nodiscard]] bool Convert(wgpu::CanvasConfiguration &out,
- // const GPUCanvasConfiguration &in) {
- // return Convert(out.device, in.device) && Convert(out.format, in.format)
- // &&
- // Convert(out.usage, in.usage) && Convert(out.viewFormats,
- // in.viewFormats) && Convert(out.colorSpace, in.colorSpace) &&
- // Convert(out.alphaMode, in.alphaMode);
- // }
-
[[nodiscard]] bool Convert(wgpu::Color &out, const GPUColor &in) {
return Convert(out.r, in.r) && Convert(out.g, in.g) &&
Convert(out.b, in.b) && Convert(out.a, in.a);
diff --git a/packages/webgpu/cpp/rnwgpu/api/GPUCanvasContext.cpp b/packages/webgpu/cpp/rnwgpu/api/GPUCanvasContext.cpp
index 48e9ff08..e76f1622 100644
--- a/packages/webgpu/cpp/rnwgpu/api/GPUCanvasContext.cpp
+++ b/packages/webgpu/cpp/rnwgpu/api/GPUCanvasContext.cpp
@@ -16,12 +16,13 @@ void GPUCanvasContext::configure(
throw std::runtime_error("Error with SurfaceConfiguration");
}
}
- if (!conv(surfaceConfiguration.format, configuration->format)) {
- throw std::runtime_error("Error with SurfaceConfiguration");
- }
- if (!conv(surfaceConfiguration.usage, configuration->usage)) {
- throw std::runtime_error("Error with SurfaceConfiguration");
+ if (!conv(surfaceConfiguration.usage, configuration->usage) || !conv(surfaceConfiguration.format, configuration->format)) {
+ throw std::runtime_error("Error with SurfaceConfiguration");
}
+
+#ifdef __APPLE__
+ surfaceConfiguration.alphaMode = configuration->alphaMode;
+#endif
_surfaceInfo->configure(surfaceConfiguration);
}
diff --git a/packages/webgpu/cpp/rnwgpu/api/descriptors/GPUCanvasConfiguration.h b/packages/webgpu/cpp/rnwgpu/api/descriptors/GPUCanvasConfiguration.h
index 22af9c68..b4ba407c 100644
--- a/packages/webgpu/cpp/rnwgpu/api/descriptors/GPUCanvasConfiguration.h
+++ b/packages/webgpu/cpp/rnwgpu/api/descriptors/GPUCanvasConfiguration.h
@@ -21,6 +21,7 @@ struct GPUCanvasConfiguration {
std::optional usage; // GPUTextureUsageFlags
std::optional>
viewFormats; // Iterable
+ wgpu::CompositeAlphaMode alphaMode = wgpu::CompositeAlphaMode::Opaque;
};
} // namespace rnwgpu
@@ -58,6 +59,12 @@ struct JSIConverter> {
prop,
false);
}
+ if (value.hasProperty(runtime, "alphaMode")) {
+ auto prop = value.getProperty(runtime, "alphaMode").asString(runtime).utf8(runtime);
+ if (prop == "premultiplied") {
+ result->alphaMode = wgpu::CompositeAlphaMode::Premultiplied;
+ }
+ }
}
return result;
diff --git a/packages/webgpu/src/__tests__/Alpha.spec.ts b/packages/webgpu/src/__tests__/Alpha.spec.ts
new file mode 100644
index 00000000..bc83e934
--- /dev/null
+++ b/packages/webgpu/src/__tests__/Alpha.spec.ts
@@ -0,0 +1,28 @@
+import { checkImage, client, encodeImage } from "./setup";
+
+describe("Alpha", () => {
+ it("Premultiplied Color", async () => {
+ const result = await client.eval(({ device, ctx, canvas }) => {
+ const commandEncoder = device.createCommandEncoder();
+ const textureView = ctx.getCurrentTexture().createView();
+ const alpha = 0.5;
+ const renderPassDescriptor: GPURenderPassDescriptor = {
+ colorAttachments: [
+ {
+ view: textureView,
+ clearValue: [0.3 * alpha, 0.6 * alpha, 1 * alpha, alpha],
+ loadOp: "clear",
+ storeOp: "store",
+ },
+ ],
+ };
+
+ const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
+ passEncoder.end();
+ device.queue.submit([commandEncoder.finish()]);
+ return canvas.getImageData();
+ });
+ const image = encodeImage(result);
+ checkImage(image, "snapshots/semi-opaque-cyan.png");
+ });
+});
diff --git a/packages/webgpu/src/__tests__/snapshots/semi-opaque-cyan.png b/packages/webgpu/src/__tests__/snapshots/semi-opaque-cyan.png
new file mode 100644
index 00000000..e05b04c3
Binary files /dev/null and b/packages/webgpu/src/__tests__/snapshots/semi-opaque-cyan.png differ