blob: 14b60261f1fa4da400c8ca137cbec954b56a2e0a [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/video_effects/calculators/in_place_copy_calculator_webgpu.h"
#include "third_party/abseil-cpp/absl/status/status.h"
#include "third_party/mediapipe/src/mediapipe/framework/calculator_context.h"
#include "third_party/mediapipe/src/mediapipe/framework/calculator_contract.h"
#include "third_party/mediapipe/src/mediapipe/framework/calculator_registry.h"
#include "third_party/mediapipe/src/mediapipe/framework/packet.h"
#include "third_party/mediapipe/src/mediapipe/gpu/gpu_buffer.h"
#include "third_party/mediapipe/src/mediapipe/gpu/webgpu/webgpu_service.h"
#include "third_party/mediapipe/src/mediapipe/gpu/webgpu/webgpu_texture_view.h"
namespace video_effects {
InPlaceCopyCalculatorWebGpu::InPlaceCopyCalculatorWebGpu() = default;
InPlaceCopyCalculatorWebGpu::~InPlaceCopyCalculatorWebGpu() = default;
absl::Status InPlaceCopyCalculatorWebGpu::GetContract(
mediapipe::CalculatorContract* cc) {
cc->UseService(mediapipe::kWebGpuService);
cc->Inputs().Tag(kInputStreamTag).Set<mediapipe::GpuBuffer>();
cc->Inputs().Tag(kOutputInputStreamTag).Set<mediapipe::GpuBuffer>();
cc->Outputs().Tag(kOutputStreamTag).Set<mediapipe::GpuBuffer>();
return absl::OkStatus();
}
absl::Status InPlaceCopyCalculatorWebGpu::Open(
mediapipe::CalculatorContext* cc) {
wgpu::Device device =
cc->Service(mediapipe::kWebGpuService).GetObject().device();
if (!device) {
return absl::InternalError(
"Failed to obtain the WebGPU device from the service!");
}
return absl::OkStatus();
}
absl::Status InPlaceCopyCalculatorWebGpu::Process(
mediapipe::CalculatorContext* cc) {
wgpu::Device device =
cc->Service(mediapipe::kWebGpuService).GetObject().device();
if (!device) {
return absl::InternalError(
"Failed to obtain the WebGPU device from the service!");
}
mediapipe::Packet& input_packet = cc->Inputs().Tag(kInputStreamTag).Value();
auto input_buffer = input_packet.Get<mediapipe::GpuBuffer>();
auto input_texture_view =
input_buffer.GetReadView<mediapipe::WebGpuTextureView>();
mediapipe::Packet& output_packet =
cc->Inputs().Tag(kOutputInputStreamTag).Value();
auto output_buffer = output_packet.Get<mediapipe::GpuBuffer>();
auto output_texture_view =
output_buffer.GetWriteView<mediapipe::WebGpuTextureView>();
if (input_buffer.width() != output_buffer.width() ||
input_buffer.height() != output_buffer.height()) {
return absl::InternalError(
"Mismatching dimensions of input and output buffers");
}
wgpu::CommandEncoder command_encoder = device.CreateCommandEncoder();
wgpu::TexelCopyTextureInfo source = {.texture = input_texture_view.texture()};
wgpu::TexelCopyTextureInfo destination = {.texture =
output_texture_view.texture()};
wgpu::Extent3D extent = {
.width = static_cast<uint32_t>(input_buffer.width()),
.height = static_cast<uint32_t>(input_buffer.height()),
.depthOrArrayLayers = 1};
command_encoder.CopyTextureToTexture(&source, &destination, &extent);
wgpu::CommandBufferDescriptor command_buffer_descriptor = {
.label = "InPlaceCopyCalculator",
};
wgpu::CommandBuffer command_buffer =
command_encoder.Finish(&command_buffer_descriptor);
device.GetQueue().Submit(1, &command_buffer);
cc->Outputs().Tag(kOutputStreamTag).AddPacket(output_packet);
return absl::OkStatus();
}
absl::Status InPlaceCopyCalculatorWebGpu::Close(
mediapipe::CalculatorContext* cc) {
return absl::OkStatus();
}
REGISTER_CALCULATOR(InPlaceCopyCalculatorWebGpu)
} // namespace video_effects