summaryrefslogtreecommitdiffstats
path: root/dom/webgpu/CommandEncoder.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /dom/webgpu/CommandEncoder.cpp
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/webgpu/CommandEncoder.cpp')
-rw-r--r--dom/webgpu/CommandEncoder.cpp270
1 files changed, 270 insertions, 0 deletions
diff --git a/dom/webgpu/CommandEncoder.cpp b/dom/webgpu/CommandEncoder.cpp
new file mode 100644
index 0000000000..15d95401d4
--- /dev/null
+++ b/dom/webgpu/CommandEncoder.cpp
@@ -0,0 +1,270 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/WebGPUBinding.h"
+#include "CommandEncoder.h"
+
+#include "CommandBuffer.h"
+#include "Buffer.h"
+#include "ComputePassEncoder.h"
+#include "Device.h"
+#include "RenderPassEncoder.h"
+#include "Utility.h"
+#include "mozilla/webgpu/CanvasContext.h"
+#include "mozilla/webgpu/ffi/wgpu.h"
+#include "ipc/WebGPUChild.h"
+
+namespace mozilla::webgpu {
+
+GPU_IMPL_CYCLE_COLLECTION(CommandEncoder, mParent, mBridge)
+GPU_IMPL_JS_WRAP(CommandEncoder)
+
+void CommandEncoder::ConvertTextureDataLayoutToFFI(
+ const dom::GPUImageDataLayout& aLayout,
+ ffi::WGPUImageDataLayout* aLayoutFFI) {
+ *aLayoutFFI = {};
+ aLayoutFFI->offset = aLayout.mOffset;
+
+ if (aLayout.mBytesPerRow.WasPassed()) {
+ aLayoutFFI->bytes_per_row = &aLayout.mBytesPerRow.Value();
+ } else {
+ aLayoutFFI->bytes_per_row = nullptr;
+ }
+
+ if (aLayout.mRowsPerImage.WasPassed()) {
+ aLayoutFFI->rows_per_image = &aLayout.mRowsPerImage.Value();
+ } else {
+ aLayoutFFI->rows_per_image = nullptr;
+ }
+}
+
+void CommandEncoder::ConvertTextureCopyViewToFFI(
+ const dom::GPUImageCopyTexture& aCopy,
+ ffi::WGPUImageCopyTexture* aViewFFI) {
+ *aViewFFI = {};
+ aViewFFI->texture = aCopy.mTexture->mId;
+ aViewFFI->mip_level = aCopy.mMipLevel;
+ if (aCopy.mOrigin.WasPassed()) {
+ const auto& origin = aCopy.mOrigin.Value();
+ if (origin.IsRangeEnforcedUnsignedLongSequence()) {
+ const auto& seq = origin.GetAsRangeEnforcedUnsignedLongSequence();
+ aViewFFI->origin.x = seq.Length() > 0 ? seq[0] : 0;
+ aViewFFI->origin.y = seq.Length() > 1 ? seq[1] : 0;
+ aViewFFI->origin.z = seq.Length() > 2 ? seq[2] : 0;
+ } else if (origin.IsGPUOrigin3DDict()) {
+ const auto& dict = origin.GetAsGPUOrigin3DDict();
+ aViewFFI->origin.x = dict.mX;
+ aViewFFI->origin.y = dict.mY;
+ aViewFFI->origin.z = dict.mZ;
+ } else {
+ MOZ_CRASH("Unexpected origin type");
+ }
+ }
+}
+
+static ffi::WGPUImageCopyTexture ConvertTextureCopyView(
+ const dom::GPUImageCopyTexture& aCopy) {
+ ffi::WGPUImageCopyTexture view = {};
+ CommandEncoder::ConvertTextureCopyViewToFFI(aCopy, &view);
+ return view;
+}
+
+CommandEncoder::CommandEncoder(Device* const aParent,
+ WebGPUChild* const aBridge, RawId aId)
+ : ChildOf(aParent), mId(aId), mBridge(aBridge) {
+ MOZ_RELEASE_ASSERT(aId);
+}
+
+CommandEncoder::~CommandEncoder() { Cleanup(); }
+
+void CommandEncoder::Cleanup() {
+ if (!mValid) {
+ return;
+ }
+ mValid = false;
+ if (mBridge->IsOpen()) {
+ mBridge->SendCommandEncoderDrop(mId);
+ }
+}
+
+void CommandEncoder::CopyBufferToBuffer(const Buffer& aSource,
+ BufferAddress aSourceOffset,
+ const Buffer& aDestination,
+ BufferAddress aDestinationOffset,
+ BufferAddress aSize) {
+ if (!mBridge->IsOpen()) {
+ return;
+ }
+
+ ipc::ByteBuf bb;
+ ffi::wgpu_command_encoder_copy_buffer_to_buffer(
+ aSource.mId, aSourceOffset, aDestination.mId, aDestinationOffset, aSize,
+ ToFFI(&bb));
+ mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(bb));
+}
+
+void CommandEncoder::CopyBufferToTexture(
+ const dom::GPUImageCopyBuffer& aSource,
+ const dom::GPUImageCopyTexture& aDestination,
+ const dom::GPUExtent3D& aCopySize) {
+ if (!mBridge->IsOpen()) {
+ return;
+ }
+
+ ipc::ByteBuf bb;
+ ffi::WGPUImageDataLayout src_layout = {};
+ CommandEncoder::ConvertTextureDataLayoutToFFI(aSource, &src_layout);
+ ffi::wgpu_command_encoder_copy_buffer_to_texture(
+ aSource.mBuffer->mId, &src_layout, ConvertTextureCopyView(aDestination),
+ ConvertExtent(aCopySize), ToFFI(&bb));
+ mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(bb));
+
+ const auto& targetContext = aDestination.mTexture->mTargetContext;
+ if (targetContext) {
+ mTargetContexts.AppendElement(targetContext);
+ }
+}
+void CommandEncoder::CopyTextureToBuffer(
+ const dom::GPUImageCopyTexture& aSource,
+ const dom::GPUImageCopyBuffer& aDestination,
+ const dom::GPUExtent3D& aCopySize) {
+ if (!mBridge->IsOpen()) {
+ return;
+ }
+
+ ipc::ByteBuf bb;
+ ffi::WGPUImageDataLayout dstLayout = {};
+ CommandEncoder::ConvertTextureDataLayoutToFFI(aDestination, &dstLayout);
+ ffi::wgpu_command_encoder_copy_texture_to_buffer(
+ ConvertTextureCopyView(aSource), aDestination.mBuffer->mId, &dstLayout,
+ ConvertExtent(aCopySize), ToFFI(&bb));
+ mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(bb));
+}
+void CommandEncoder::CopyTextureToTexture(
+ const dom::GPUImageCopyTexture& aSource,
+ const dom::GPUImageCopyTexture& aDestination,
+ const dom::GPUExtent3D& aCopySize) {
+ if (!mBridge->IsOpen()) {
+ return;
+ }
+
+ ipc::ByteBuf bb;
+ ffi::wgpu_command_encoder_copy_texture_to_texture(
+ ConvertTextureCopyView(aSource), ConvertTextureCopyView(aDestination),
+ ConvertExtent(aCopySize), ToFFI(&bb));
+ mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(bb));
+
+ const auto& targetContext = aDestination.mTexture->mTargetContext;
+ if (targetContext) {
+ mTargetContexts.AppendElement(targetContext);
+ }
+}
+
+void CommandEncoder::ClearBuffer(const Buffer& aBuffer, const uint64_t aOffset,
+ const dom::Optional<uint64_t>& aSize) {
+ uint64_t sizeVal = 0xdeaddead;
+ uint64_t* size = nullptr;
+ if (aSize.WasPassed()) {
+ sizeVal = aSize.Value();
+ size = &sizeVal;
+ }
+
+ ipc::ByteBuf bb;
+ ffi::wgpu_command_encoder_clear_buffer(aBuffer.mId, aOffset, size,
+ ToFFI(&bb));
+ mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(bb));
+}
+
+void CommandEncoder::PushDebugGroup(const nsAString& aString) {
+ if (!mBridge->IsOpen()) {
+ return;
+ }
+
+ ipc::ByteBuf bb;
+ NS_ConvertUTF16toUTF8 marker(aString);
+ ffi::wgpu_command_encoder_push_debug_group(&marker, ToFFI(&bb));
+ mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(bb));
+}
+void CommandEncoder::PopDebugGroup() {
+ if (!mBridge->IsOpen()) {
+ return;
+ }
+
+ ipc::ByteBuf bb;
+ ffi::wgpu_command_encoder_pop_debug_group(ToFFI(&bb));
+ mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(bb));
+}
+void CommandEncoder::InsertDebugMarker(const nsAString& aString) {
+ if (!mBridge->IsOpen()) {
+ return;
+ }
+
+ ipc::ByteBuf bb;
+ NS_ConvertUTF16toUTF8 marker(aString);
+ ffi::wgpu_command_encoder_insert_debug_marker(&marker, ToFFI(&bb));
+ mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(bb));
+}
+
+already_AddRefed<ComputePassEncoder> CommandEncoder::BeginComputePass(
+ const dom::GPUComputePassDescriptor& aDesc) {
+ RefPtr<ComputePassEncoder> pass = new ComputePassEncoder(this, aDesc);
+ return pass.forget();
+}
+
+already_AddRefed<RenderPassEncoder> CommandEncoder::BeginRenderPass(
+ const dom::GPURenderPassDescriptor& aDesc) {
+ for (const auto& at : aDesc.mColorAttachments) {
+ auto* targetContext = at.mView->GetTargetContext();
+ if (targetContext) {
+ mTargetContexts.AppendElement(targetContext);
+ }
+ if (at.mResolveTarget.WasPassed()) {
+ targetContext = at.mResolveTarget.Value().GetTargetContext();
+ mTargetContexts.AppendElement(targetContext);
+ }
+ }
+
+ RefPtr<RenderPassEncoder> pass = new RenderPassEncoder(this, aDesc);
+ return pass.forget();
+}
+
+void CommandEncoder::EndComputePass(ffi::WGPUComputePass& aPass) {
+ if (!mBridge->IsOpen()) {
+ return;
+ }
+
+ ipc::ByteBuf byteBuf;
+ ffi::wgpu_compute_pass_finish(&aPass, ToFFI(&byteBuf));
+ mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(byteBuf));
+}
+
+void CommandEncoder::EndRenderPass(ffi::WGPURenderPass& aPass) {
+ if (!mBridge->IsOpen()) {
+ return;
+ }
+
+ ipc::ByteBuf byteBuf;
+ ffi::wgpu_render_pass_finish(&aPass, ToFFI(&byteBuf));
+ mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(byteBuf));
+}
+
+already_AddRefed<CommandBuffer> CommandEncoder::Finish(
+ const dom::GPUCommandBufferDescriptor& aDesc) {
+ // We rely on knowledge that `CommandEncoderId` == `CommandBufferId`
+ // TODO: refactor this to truly behave as if the encoder is being finished,
+ // and a new command buffer ID is being created from it. Resolve the ID
+ // type aliasing at the place that introduces it: `wgpu-core`.
+ RawId deviceId = mParent->mId;
+ if (mBridge->CanSend()) {
+ mBridge->SendCommandEncoderFinish(mId, deviceId, aDesc);
+ }
+
+ RefPtr<CommandEncoder> me(this);
+ RefPtr<CommandBuffer> comb = new CommandBuffer(
+ mParent, mId, std::move(mTargetContexts), std::move(me));
+ return comb.forget();
+}
+
+} // namespace mozilla::webgpu