Bug 1732219 - Add API for fetching the preview image. r=geckoview-reviewers,agi,mconley
[gecko.git] / dom / webgpu / CommandEncoder.cpp
blob64c78bd11f8698ae0d9bb89dc1bb604a19505892
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/dom/WebGPUBinding.h"
7 #include "CommandEncoder.h"
9 #include "CommandBuffer.h"
10 #include "Buffer.h"
11 #include "ComputePassEncoder.h"
12 #include "Device.h"
13 #include "RenderPassEncoder.h"
14 #include "mozilla/dom/HTMLCanvasElement.h"
15 #include "mozilla/webgpu/ffi/wgpu.h"
16 #include "ipc/WebGPUChild.h"
18 namespace mozilla {
19 namespace webgpu {
21 GPU_IMPL_CYCLE_COLLECTION(CommandEncoder, mParent, mBridge)
22 GPU_IMPL_JS_WRAP(CommandEncoder)
24 void CommandEncoder::ConvertTextureDataLayoutToFFI(
25 const dom::GPUImageDataLayout& aLayout,
26 ffi::WGPUImageDataLayout* aLayoutFFI) {
27 *aLayoutFFI = {};
28 aLayoutFFI->offset = aLayout.mOffset;
29 aLayoutFFI->bytes_per_row = aLayout.mBytesPerRow;
30 aLayoutFFI->rows_per_image = aLayout.mRowsPerImage;
33 void CommandEncoder::ConvertTextureCopyViewToFFI(
34 const dom::GPUImageCopyTexture& aCopy,
35 ffi::WGPUImageCopyTexture* aViewFFI) {
36 *aViewFFI = {};
37 aViewFFI->texture = aCopy.mTexture->mId;
38 aViewFFI->mip_level = aCopy.mMipLevel;
39 if (aCopy.mOrigin.WasPassed()) {
40 const auto& origin = aCopy.mOrigin.Value();
41 if (origin.IsRangeEnforcedUnsignedLongSequence()) {
42 const auto& seq = origin.GetAsRangeEnforcedUnsignedLongSequence();
43 aViewFFI->origin.x = seq.Length() > 0 ? seq[0] : 0;
44 aViewFFI->origin.y = seq.Length() > 1 ? seq[1] : 0;
45 aViewFFI->origin.z = seq.Length() > 2 ? seq[2] : 0;
46 } else if (origin.IsGPUOrigin3DDict()) {
47 const auto& dict = origin.GetAsGPUOrigin3DDict();
48 aViewFFI->origin.x = dict.mX;
49 aViewFFI->origin.y = dict.mY;
50 aViewFFI->origin.z = dict.mZ;
51 } else {
52 MOZ_CRASH("Unexpected origin type");
57 void CommandEncoder::ConvertExtent3DToFFI(const dom::GPUExtent3D& aExtent,
58 ffi::WGPUExtent3d* aExtentFFI) {
59 *aExtentFFI = {};
60 if (aExtent.IsRangeEnforcedUnsignedLongSequence()) {
61 const auto& seq = aExtent.GetAsRangeEnforcedUnsignedLongSequence();
62 aExtentFFI->width = seq.Length() > 0 ? seq[0] : 0;
63 aExtentFFI->height = seq.Length() > 1 ? seq[1] : 0;
64 aExtentFFI->depth_or_array_layers = seq.Length() > 2 ? seq[2] : 0;
65 } else if (aExtent.IsGPUExtent3DDict()) {
66 const auto& dict = aExtent.GetAsGPUExtent3DDict();
67 aExtentFFI->width = dict.mWidth;
68 aExtentFFI->height = dict.mHeight;
69 aExtentFFI->depth_or_array_layers = dict.mDepthOrArrayLayers;
70 } else {
71 MOZ_CRASH("Unexptected extent type");
75 static ffi::WGPUImageCopyBuffer ConvertBufferCopyView(
76 const dom::GPUImageCopyBuffer& aCopy) {
77 ffi::WGPUImageCopyBuffer view = {};
78 view.buffer = aCopy.mBuffer->mId;
79 CommandEncoder::ConvertTextureDataLayoutToFFI(aCopy, &view.layout);
80 return view;
83 static ffi::WGPUImageCopyTexture ConvertTextureCopyView(
84 const dom::GPUImageCopyTexture& aCopy) {
85 ffi::WGPUImageCopyTexture view = {};
86 CommandEncoder::ConvertTextureCopyViewToFFI(aCopy, &view);
87 return view;
90 static ffi::WGPUExtent3d ConvertExtent(const dom::GPUExtent3D& aExtent) {
91 ffi::WGPUExtent3d extent = {};
92 CommandEncoder::ConvertExtent3DToFFI(aExtent, &extent);
93 return extent;
96 CommandEncoder::CommandEncoder(Device* const aParent,
97 WebGPUChild* const aBridge, RawId aId)
98 : ChildOf(aParent), mId(aId), mBridge(aBridge) {}
100 CommandEncoder::~CommandEncoder() { Cleanup(); }
102 void CommandEncoder::Cleanup() {
103 if (mValid && mParent) {
104 mValid = false;
105 auto bridge = mParent->GetBridge();
106 if (bridge && bridge->IsOpen()) {
107 bridge->SendCommandEncoderDestroy(mId);
112 void CommandEncoder::CopyBufferToBuffer(const Buffer& aSource,
113 BufferAddress aSourceOffset,
114 const Buffer& aDestination,
115 BufferAddress aDestinationOffset,
116 BufferAddress aSize) {
117 if (mValid) {
118 ipc::ByteBuf bb;
119 ffi::wgpu_command_encoder_copy_buffer_to_buffer(
120 aSource.mId, aSourceOffset, aDestination.mId, aDestinationOffset, aSize,
121 ToFFI(&bb));
122 mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(bb));
126 void CommandEncoder::CopyBufferToTexture(
127 const dom::GPUImageCopyBuffer& aSource,
128 const dom::GPUImageCopyTexture& aDestination,
129 const dom::GPUExtent3D& aCopySize) {
130 if (mValid) {
131 ipc::ByteBuf bb;
132 ffi::wgpu_command_encoder_copy_buffer_to_texture(
133 ConvertBufferCopyView(aSource), ConvertTextureCopyView(aDestination),
134 ConvertExtent(aCopySize), ToFFI(&bb));
135 mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(bb));
137 const auto& targetCanvas = aDestination.mTexture->mTargetCanvasElement;
138 if (targetCanvas) {
139 mTargetCanvases.AppendElement(targetCanvas);
143 void CommandEncoder::CopyTextureToBuffer(
144 const dom::GPUImageCopyTexture& aSource,
145 const dom::GPUImageCopyBuffer& aDestination,
146 const dom::GPUExtent3D& aCopySize) {
147 if (mValid) {
148 ipc::ByteBuf bb;
149 ffi::wgpu_command_encoder_copy_texture_to_buffer(
150 ConvertTextureCopyView(aSource), ConvertBufferCopyView(aDestination),
151 ConvertExtent(aCopySize), ToFFI(&bb));
152 mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(bb));
155 void CommandEncoder::CopyTextureToTexture(
156 const dom::GPUImageCopyTexture& aSource,
157 const dom::GPUImageCopyTexture& aDestination,
158 const dom::GPUExtent3D& aCopySize) {
159 if (mValid) {
160 ipc::ByteBuf bb;
161 ffi::wgpu_command_encoder_copy_texture_to_texture(
162 ConvertTextureCopyView(aSource), ConvertTextureCopyView(aDestination),
163 ConvertExtent(aCopySize), ToFFI(&bb));
164 mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(bb));
166 const auto& targetCanvas = aDestination.mTexture->mTargetCanvasElement;
167 if (targetCanvas) {
168 mTargetCanvases.AppendElement(targetCanvas);
173 already_AddRefed<ComputePassEncoder> CommandEncoder::BeginComputePass(
174 const dom::GPUComputePassDescriptor& aDesc) {
175 RefPtr<ComputePassEncoder> pass = new ComputePassEncoder(this, aDesc);
176 return pass.forget();
179 already_AddRefed<RenderPassEncoder> CommandEncoder::BeginRenderPass(
180 const dom::GPURenderPassDescriptor& aDesc) {
181 for (const auto& at : aDesc.mColorAttachments) {
182 auto* targetCanvasElement = at.mView->GetTargetCanvasElement();
183 if (targetCanvasElement) {
184 mTargetCanvases.AppendElement(targetCanvasElement);
186 if (at.mResolveTarget.WasPassed()) {
187 targetCanvasElement = at.mResolveTarget.Value().GetTargetCanvasElement();
188 mTargetCanvases.AppendElement(targetCanvasElement);
192 RefPtr<RenderPassEncoder> pass = new RenderPassEncoder(this, aDesc);
193 return pass.forget();
196 void CommandEncoder::EndComputePass(ffi::WGPUComputePass& aPass,
197 ErrorResult& aRv) {
198 if (!mValid) {
199 return aRv.ThrowInvalidStateError("Command encoder is not valid");
202 ipc::ByteBuf byteBuf;
203 ffi::wgpu_compute_pass_finish(&aPass, ToFFI(&byteBuf));
204 mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(byteBuf));
207 void CommandEncoder::EndRenderPass(ffi::WGPURenderPass& aPass,
208 ErrorResult& aRv) {
209 if (!mValid) {
210 return aRv.ThrowInvalidStateError("Command encoder is not valid");
213 ipc::ByteBuf byteBuf;
214 ffi::wgpu_render_pass_finish(&aPass, ToFFI(&byteBuf));
215 mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(byteBuf));
218 already_AddRefed<CommandBuffer> CommandEncoder::Finish(
219 const dom::GPUCommandBufferDescriptor& aDesc) {
220 RawId id = 0;
221 if (mValid) {
222 mValid = false;
223 id = mBridge->CommandEncoderFinish(mId, mParent->mId, aDesc);
225 RefPtr<CommandBuffer> comb =
226 new CommandBuffer(mParent, id, std::move(mTargetCanvases));
227 return comb.forget();
230 } // namespace webgpu
231 } // namespace mozilla