fune/dom/webgpu/ipc/WebGPUChild.cpp
Dzmitry Malyshau 8f74799ba5 Bug 1676916 - Implicit bind group layouts in WebGPU r=jgilbert,webidl,smaug
This change updates and enables Naga to get the
SPIRV shaders parsed, validated, and reflected back into
implicit bind group layouts.
WebGPU examples heavily rely on the implicit layouts now,
and the PR also updates the WebIDL to make that possible.
With the change, we are able to run most of the examples again!

Differential Revision: https://phabricator.services.mozilla.com/D96850
2020-11-13 14:15:49 +00:00

644 lines
22 KiB
C++

/* -*- Mode: C++; tab-width: 20; 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 "WebGPUChild.h"
#include "mozilla/dom/WebGPUBinding.h"
#include "mozilla/webgpu/ffi/wgpu.h"
namespace mozilla {
namespace webgpu {
NS_IMPL_CYCLE_COLLECTION(WebGPUChild)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGPUChild, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGPUChild, Release)
static ffi::WGPUClient* initialize() {
ffi::WGPUInfrastructure infra = ffi::wgpu_client_new();
return infra.client;
}
WebGPUChild::WebGPUChild() : mClient(initialize()), mIPCOpen(false) {}
WebGPUChild::~WebGPUChild() {
if (mClient) {
ffi::wgpu_client_delete(mClient);
}
}
RefPtr<RawIdPromise> WebGPUChild::InstanceRequestAdapter(
const dom::GPURequestAdapterOptions& aOptions) {
const int max_ids = 10;
RawId ids[max_ids] = {0};
unsigned long count =
ffi::wgpu_client_make_adapter_ids(mClient, ids, max_ids);
nsTArray<RawId> sharedIds(count);
for (unsigned long i = 0; i != count; ++i) {
sharedIds.AppendElement(ids[i]);
}
return SendInstanceRequestAdapter(aOptions, sharedIds)
->Then(
GetCurrentSerialEventTarget(), __func__,
[](const RawId& aId) {
return aId == 0 ? RawIdPromise::CreateAndReject(Nothing(), __func__)
: RawIdPromise::CreateAndResolve(aId, __func__);
},
[](const ipc::ResponseRejectReason& aReason) {
return RawIdPromise::CreateAndReject(Some(aReason), __func__);
});
}
Maybe<RawId> WebGPUChild::AdapterRequestDevice(
RawId aSelfId, const dom::GPUDeviceDescriptor& aDesc) {
RawId id = ffi::wgpu_client_make_device_id(mClient, aSelfId);
if (SendAdapterRequestDevice(aSelfId, aDesc, id)) {
return Some(id);
}
ffi::wgpu_client_kill_device_id(mClient, id);
return Nothing();
}
RawId WebGPUChild::DeviceCreateBuffer(RawId aSelfId,
const dom::GPUBufferDescriptor& aDesc) {
ffi::WGPUBufferDescriptor desc = {};
nsCString label;
if (aDesc.mLabel.WasPassed()) {
LossyCopyUTF16toASCII(aDesc.mLabel.Value(), label);
desc.label = label.get();
}
desc.size = aDesc.mSize;
desc.usage = aDesc.mUsage;
desc.mapped_at_creation = aDesc.mMappedAtCreation;
ByteBuf bb;
RawId id =
ffi::wgpu_client_create_buffer(mClient, aSelfId, &desc, ToFFI(&bb));
if (!SendDeviceAction(aSelfId, std::move(bb))) {
MOZ_CRASH("IPC failure");
}
return id;
}
RawId WebGPUChild::DeviceCreateTexture(RawId aSelfId,
const dom::GPUTextureDescriptor& aDesc) {
ffi::WGPUTextureDescriptor desc = {};
nsCString label;
if (aDesc.mLabel.WasPassed()) {
LossyCopyUTF16toASCII(aDesc.mLabel.Value(), label);
desc.label = label.get();
}
if (aDesc.mSize.IsRangeEnforcedUnsignedLongSequence()) {
const auto& seq = aDesc.mSize.GetAsRangeEnforcedUnsignedLongSequence();
desc.size.width = seq.Length() > 0 ? seq[0] : 1;
desc.size.height = seq.Length() > 1 ? seq[1] : 1;
desc.size.depth = seq.Length() > 2 ? seq[2] : 1;
} else if (aDesc.mSize.IsGPUExtent3DDict()) {
const auto& dict = aDesc.mSize.GetAsGPUExtent3DDict();
desc.size.width = dict.mWidth;
desc.size.height = dict.mHeight;
desc.size.depth = dict.mDepth;
} else {
MOZ_CRASH("Unexpected union");
}
desc.mip_level_count = aDesc.mMipLevelCount;
desc.sample_count = aDesc.mSampleCount;
desc.dimension = ffi::WGPUTextureDimension(aDesc.mDimension);
desc.format = ffi::WGPUTextureFormat(aDesc.mFormat);
desc.usage = aDesc.mUsage;
ByteBuf bb;
RawId id =
ffi::wgpu_client_create_texture(mClient, aSelfId, &desc, ToFFI(&bb));
if (!SendDeviceAction(aSelfId, std::move(bb))) {
MOZ_CRASH("IPC failure");
}
return id;
}
RawId WebGPUChild::TextureCreateView(
RawId aSelfId, const dom::GPUTextureViewDescriptor& aDesc) {
ffi::WGPUTextureViewDescriptor desc = {};
nsCString label;
if (aDesc.mLabel.WasPassed()) {
LossyCopyUTF16toASCII(aDesc.mLabel.Value(), label);
desc.label = label.get();
}
ffi::WGPUTextureFormat format = ffi::WGPUTextureFormat_Sentinel;
if (aDesc.mFormat.WasPassed()) {
format = ffi::WGPUTextureFormat(aDesc.mFormat.Value());
desc.format = &format;
}
ffi::WGPUTextureViewDimension dimension =
ffi::WGPUTextureViewDimension_Sentinel;
if (aDesc.mDimension.WasPassed()) {
dimension = ffi::WGPUTextureViewDimension(aDesc.mDimension.Value());
desc.dimension = &dimension;
}
desc.aspect = ffi::WGPUTextureAspect(aDesc.mAspect);
desc.base_mip_level = aDesc.mBaseMipLevel;
desc.level_count =
aDesc.mMipLevelCount.WasPassed() ? aDesc.mMipLevelCount.Value() : 0;
desc.base_array_layer = aDesc.mBaseArrayLayer;
desc.array_layer_count =
aDesc.mArrayLayerCount.WasPassed() ? aDesc.mArrayLayerCount.Value() : 0;
ByteBuf bb;
RawId id =
ffi::wgpu_client_create_texture_view(mClient, aSelfId, &desc, ToFFI(&bb));
if (!SendTextureAction(aSelfId, std::move(bb))) {
MOZ_CRASH("IPC failure");
}
return id;
}
RawId WebGPUChild::DeviceCreateSampler(RawId aSelfId,
const dom::GPUSamplerDescriptor& aDesc) {
ffi::WGPUSamplerDescriptor desc = {};
nsCString label;
if (aDesc.mLabel.WasPassed()) {
LossyCopyUTF16toASCII(aDesc.mLabel.Value(), label);
desc.label = label.get();
}
desc.address_modes[0] = ffi::WGPUAddressMode(aDesc.mAddressModeU);
desc.address_modes[1] = ffi::WGPUAddressMode(aDesc.mAddressModeV);
desc.address_modes[2] = ffi::WGPUAddressMode(aDesc.mAddressModeW);
desc.mag_filter = ffi::WGPUFilterMode(aDesc.mMagFilter);
desc.min_filter = ffi::WGPUFilterMode(aDesc.mMinFilter);
desc.mipmap_filter = ffi::WGPUFilterMode(aDesc.mMipmapFilter);
desc.lod_min_clamp = aDesc.mLodMinClamp;
desc.lod_max_clamp = aDesc.mLodMaxClamp;
ffi::WGPUCompareFunction comparison = ffi::WGPUCompareFunction_Sentinel;
if (aDesc.mCompare.WasPassed()) {
comparison = ffi::WGPUCompareFunction(aDesc.mCompare.Value());
desc.compare = &comparison;
}
ByteBuf bb;
RawId id =
ffi::wgpu_client_create_sampler(mClient, aSelfId, &desc, ToFFI(&bb));
if (!SendDeviceAction(aSelfId, std::move(bb))) {
MOZ_CRASH("IPC failure");
}
return id;
}
RawId WebGPUChild::DeviceCreateCommandEncoder(
RawId aSelfId, const dom::GPUCommandEncoderDescriptor& aDesc) {
ffi::WGPUCommandEncoderDescriptor desc = {};
nsCString label;
if (aDesc.mLabel.WasPassed()) {
LossyCopyUTF16toASCII(aDesc.mLabel.Value(), label);
desc.label = label.get();
}
ByteBuf bb;
RawId id = ffi::wgpu_client_create_command_encoder(mClient, aSelfId, &desc,
ToFFI(&bb));
if (!SendDeviceAction(aSelfId, std::move(bb))) {
MOZ_CRASH("IPC failure");
}
return id;
}
RawId WebGPUChild::CommandEncoderFinish(
RawId aSelfId, const dom::GPUCommandBufferDescriptor& aDesc) {
if (!SendCommandEncoderFinish(aSelfId, aDesc)) {
MOZ_CRASH("IPC failure");
}
// 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`.
return aSelfId;
}
RawId WebGPUChild::DeviceCreateBindGroupLayout(
RawId aSelfId, const dom::GPUBindGroupLayoutDescriptor& aDesc) {
struct OptionalData {
ffi::WGPUTextureViewDimension dim;
ffi::WGPUTextureComponentType type;
ffi::WGPUTextureFormat format;
};
nsTArray<OptionalData> optional(aDesc.mEntries.Length());
for (const auto& entry : aDesc.mEntries) {
OptionalData data = {};
if (entry.mViewDimension.WasPassed()) {
data.dim = ffi::WGPUTextureViewDimension(entry.mViewDimension.Value());
}
if (entry.mTextureComponentType.WasPassed()) {
data.type =
ffi::WGPUTextureComponentType(entry.mTextureComponentType.Value());
}
if (entry.mStorageTextureFormat.WasPassed()) {
data.format = ffi::WGPUTextureFormat(entry.mStorageTextureFormat.Value());
}
optional.AppendElement(data);
}
nsTArray<ffi::WGPUBindGroupLayoutEntry> entries(aDesc.mEntries.Length());
for (size_t i = 0; i < aDesc.mEntries.Length(); ++i) {
const auto& entry = aDesc.mEntries[i];
ffi::WGPUBindGroupLayoutEntry e = {};
e.binding = entry.mBinding;
e.visibility = entry.mVisibility;
e.ty = ffi::WGPURawBindingType(entry.mType);
e.multisampled = entry.mMultisampled;
e.has_dynamic_offset = entry.mHasDynamicOffset;
if (entry.mViewDimension.WasPassed()) {
e.view_dimension = &optional[i].dim;
}
if (entry.mTextureComponentType.WasPassed()) {
e.texture_component_type = &optional[i].type;
}
if (entry.mStorageTextureFormat.WasPassed()) {
e.storage_texture_format = &optional[i].format;
}
entries.AppendElement(e);
}
ffi::WGPUBindGroupLayoutDescriptor desc = {};
nsCString label;
if (aDesc.mLabel.WasPassed()) {
LossyCopyUTF16toASCII(aDesc.mLabel.Value(), label);
desc.label = label.get();
}
desc.entries = entries.Elements();
desc.entries_length = entries.Length();
ByteBuf bb;
RawId id = ffi::wgpu_client_create_bind_group_layout(mClient, aSelfId, &desc,
ToFFI(&bb));
if (!SendDeviceAction(aSelfId, std::move(bb))) {
MOZ_CRASH("IPC failure");
}
return id;
}
RawId WebGPUChild::DeviceCreatePipelineLayout(
RawId aSelfId, const dom::GPUPipelineLayoutDescriptor& aDesc) {
nsTArray<ffi::WGPUBindGroupLayoutId> bindGroupLayouts(
aDesc.mBindGroupLayouts.Length());
for (const auto& layout : aDesc.mBindGroupLayouts) {
bindGroupLayouts.AppendElement(layout->mId);
}
ffi::WGPUPipelineLayoutDescriptor desc = {};
nsCString label;
if (aDesc.mLabel.WasPassed()) {
LossyCopyUTF16toASCII(aDesc.mLabel.Value(), label);
desc.label = label.get();
}
desc.bind_group_layouts = bindGroupLayouts.Elements();
desc.bind_group_layouts_length = bindGroupLayouts.Length();
ByteBuf bb;
RawId id = ffi::wgpu_client_create_pipeline_layout(mClient, aSelfId, &desc,
ToFFI(&bb));
if (!SendDeviceAction(aSelfId, std::move(bb))) {
MOZ_CRASH("IPC failure");
}
return id;
}
RawId WebGPUChild::DeviceCreateBindGroup(
RawId aSelfId, const dom::GPUBindGroupDescriptor& aDesc) {
nsTArray<ffi::WGPUBindGroupEntry> entries(aDesc.mEntries.Length());
for (const auto& entry : aDesc.mEntries) {
ffi::WGPUBindGroupEntry e = {};
e.binding = entry.mBinding;
if (entry.mResource.IsGPUBufferBinding()) {
const auto& bufBinding = entry.mResource.GetAsGPUBufferBinding();
e.buffer = bufBinding.mBuffer->mId;
e.offset = bufBinding.mOffset;
e.size = bufBinding.mSize.WasPassed() ? bufBinding.mSize.Value() : 0;
}
if (entry.mResource.IsGPUTextureView()) {
e.texture_view = entry.mResource.GetAsGPUTextureView()->mId;
}
if (entry.mResource.IsGPUSampler()) {
e.sampler = entry.mResource.GetAsGPUSampler()->mId;
}
entries.AppendElement(e);
}
ffi::WGPUBindGroupDescriptor desc = {};
nsCString label;
if (aDesc.mLabel.WasPassed()) {
LossyCopyUTF16toASCII(aDesc.mLabel.Value(), label);
desc.label = label.get();
}
desc.layout = aDesc.mLayout->mId;
desc.entries = entries.Elements();
desc.entries_length = entries.Length();
ByteBuf bb;
RawId id =
ffi::wgpu_client_create_bind_group(mClient, aSelfId, &desc, ToFFI(&bb));
if (!SendDeviceAction(aSelfId, std::move(bb))) {
MOZ_CRASH("IPC failure");
}
return id;
}
RawId WebGPUChild::DeviceCreateShaderModule(
RawId aSelfId, const dom::GPUShaderModuleDescriptor& aDesc) {
ffi::WGPUShaderModuleDescriptor desc = {};
nsCString wgsl;
if (aDesc.mCode.IsString()) {
LossyCopyUTF16toASCII(aDesc.mCode.GetAsString(), wgsl);
desc.wgsl_chars = wgsl.get();
} else {
const auto& code = aDesc.mCode.GetAsUint32Array();
code.ComputeState();
desc.spirv_words = code.Data();
desc.spirv_words_length = code.Length();
}
ByteBuf bb;
RawId id = ffi::wgpu_client_create_shader_module(mClient, aSelfId, &desc,
ToFFI(&bb));
if (!SendDeviceAction(aSelfId, std::move(bb))) {
MOZ_CRASH("IPC failure");
}
return id;
}
RawId WebGPUChild::DeviceCreateComputePipeline(
RawId aSelfId, const dom::GPUComputePipelineDescriptor& aDesc,
nsTArray<RawId>* const aImplicitBindGroupLayoutIds) {
ffi::WGPUComputePipelineDescriptor desc = {};
nsCString label, entryPoint;
if (aDesc.mLabel.WasPassed()) {
LossyCopyUTF16toASCII(aDesc.mLabel.Value(), label);
desc.label = label.get();
}
if (aDesc.mLayout.WasPassed()) {
desc.layout = aDesc.mLayout.Value().mId;
}
desc.compute_stage.module = aDesc.mComputeStage.mModule->mId;
LossyCopyUTF16toASCII(aDesc.mComputeStage.mEntryPoint, entryPoint);
desc.compute_stage.entry_point = entryPoint.get();
ByteBuf bb;
RawId implicit_bgl_ids[WGPUMAX_BIND_GROUPS] = {};
RawId id = ffi::wgpu_client_create_compute_pipeline(
mClient, aSelfId, &desc, ToFFI(&bb), implicit_bgl_ids);
for (const auto& cur : implicit_bgl_ids) {
if (!cur) break;
aImplicitBindGroupLayoutIds->AppendElement(cur);
}
if (!SendDeviceAction(aSelfId, std::move(bb))) {
MOZ_CRASH("IPC failure");
}
return id;
}
static ffi::WGPURasterizationStateDescriptor ConvertRasterizationDescriptor(
const dom::GPURasterizationStateDescriptor& aDesc) {
ffi::WGPURasterizationStateDescriptor desc = {};
desc.front_face = ffi::WGPUFrontFace(aDesc.mFrontFace);
desc.cull_mode = ffi::WGPUCullMode(aDesc.mCullMode);
desc.depth_bias = aDesc.mDepthBias;
desc.depth_bias_slope_scale = aDesc.mDepthBiasSlopeScale;
desc.depth_bias_clamp = aDesc.mDepthBiasClamp;
return desc;
}
static ffi::WGPUBlendDescriptor ConvertBlendDescriptor(
const dom::GPUBlendDescriptor& aDesc) {
ffi::WGPUBlendDescriptor desc = {};
desc.src_factor = ffi::WGPUBlendFactor(aDesc.mSrcFactor);
desc.dst_factor = ffi::WGPUBlendFactor(aDesc.mDstFactor);
desc.operation = ffi::WGPUBlendOperation(aDesc.mOperation);
return desc;
}
static ffi::WGPUColorStateDescriptor ConvertColorDescriptor(
const dom::GPUColorStateDescriptor& aDesc) {
ffi::WGPUColorStateDescriptor desc = {};
desc.format = ffi::WGPUTextureFormat(aDesc.mFormat);
desc.alpha_blend = ConvertBlendDescriptor(aDesc.mAlphaBlend);
desc.color_blend = ConvertBlendDescriptor(aDesc.mColorBlend);
desc.write_mask = aDesc.mWriteMask;
return desc;
}
static ffi::WGPUCompareFunction ConvertCompareFunction(
const dom::GPUCompareFunction& aCompare) {
// Value of 0 = Undefined is reserved on the C side for "null" semantics.
return ffi::WGPUCompareFunction(static_cast<uint8_t>(aCompare) + 1);
}
static ffi::WGPUStencilStateFaceDescriptor ConvertStencilFaceDescriptor(
const dom::GPUStencilStateFaceDescriptor& aDesc) {
ffi::WGPUStencilStateFaceDescriptor desc = {};
desc.compare = ConvertCompareFunction(aDesc.mCompare);
desc.fail_op = ffi::WGPUStencilOperation(aDesc.mFailOp);
desc.depth_fail_op = ffi::WGPUStencilOperation(aDesc.mDepthFailOp);
desc.pass_op = ffi::WGPUStencilOperation(aDesc.mPassOp);
return desc;
}
static ffi::WGPUDepthStencilStateDescriptor ConvertDepthStencilDescriptor(
const dom::GPUDepthStencilStateDescriptor& aDesc) {
ffi::WGPUDepthStencilStateDescriptor desc = {};
desc.format = ffi::WGPUTextureFormat(aDesc.mFormat);
desc.depth_write_enabled = aDesc.mDepthWriteEnabled;
desc.depth_compare = ConvertCompareFunction(aDesc.mDepthCompare);
desc.stencil.front = ConvertStencilFaceDescriptor(aDesc.mStencilFront);
desc.stencil.back = ConvertStencilFaceDescriptor(aDesc.mStencilBack);
desc.stencil.read_mask = aDesc.mStencilReadMask;
desc.stencil.write_mask = aDesc.mStencilWriteMask;
return desc;
}
RawId WebGPUChild::DeviceCreateRenderPipeline(
RawId aSelfId, const dom::GPURenderPipelineDescriptor& aDesc,
nsTArray<RawId>* const aImplicitBindGroupLayoutIds) {
ffi::WGPURenderPipelineDescriptor desc = {};
nsCString label, vsEntry, fsEntry;
ffi::WGPUProgrammableStageDescriptor vertexStage = {};
ffi::WGPUProgrammableStageDescriptor fragmentStage = {};
if (aDesc.mLabel.WasPassed()) {
LossyCopyUTF16toASCII(aDesc.mLabel.Value(), label);
desc.label = label.get();
}
if (aDesc.mLayout.WasPassed()) {
desc.layout = aDesc.mLayout.Value().mId;
}
vertexStage.module = aDesc.mVertexStage.mModule->mId;
LossyCopyUTF16toASCII(aDesc.mVertexStage.mEntryPoint, vsEntry);
vertexStage.entry_point = vsEntry.get();
desc.vertex_stage = &vertexStage;
if (aDesc.mFragmentStage.WasPassed()) {
const auto& stage = aDesc.mFragmentStage.Value();
fragmentStage.module = stage.mModule->mId;
LossyCopyUTF16toASCII(stage.mEntryPoint, fsEntry);
fragmentStage.entry_point = fsEntry.get();
desc.fragment_stage = &fragmentStage;
}
desc.primitive_topology =
ffi::WGPUPrimitiveTopology(aDesc.mPrimitiveTopology);
const auto rasterization =
ConvertRasterizationDescriptor(aDesc.mRasterizationState);
desc.rasterization_state = &rasterization;
nsTArray<ffi::WGPUColorStateDescriptor> colorStates;
for (const auto& colorState : aDesc.mColorStates) {
colorStates.AppendElement(ConvertColorDescriptor(colorState));
}
desc.color_states = colorStates.Elements();
desc.color_states_length = colorStates.Length();
ffi::WGPUDepthStencilStateDescriptor depthStencilState = {};
if (aDesc.mDepthStencilState.WasPassed()) {
depthStencilState =
ConvertDepthStencilDescriptor(aDesc.mDepthStencilState.Value());
desc.depth_stencil_state = &depthStencilState;
}
desc.vertex_state.index_format =
ffi::WGPUIndexFormat(aDesc.mVertexState.mIndexFormat);
nsTArray<ffi::WGPUVertexBufferDescriptor> vertexBuffers;
nsTArray<ffi::WGPUVertexAttributeDescriptor> vertexAttributes;
for (const auto& vertex_desc : aDesc.mVertexState.mVertexBuffers) {
ffi::WGPUVertexBufferDescriptor vb_desc = {};
if (!vertex_desc.IsNull()) {
const auto& vd = vertex_desc.Value();
vb_desc.stride = vd.mArrayStride;
vb_desc.step_mode = ffi::WGPUInputStepMode(vd.mStepMode);
// Note: we are setting the length but not the pointer
vb_desc.attributes_length = vd.mAttributes.Length();
for (const auto& vat : vd.mAttributes) {
ffi::WGPUVertexAttributeDescriptor ad = {};
ad.offset = vat.mOffset;
ad.format = ffi::WGPUVertexFormat(vat.mFormat);
ad.shader_location = vat.mShaderLocation;
vertexAttributes.AppendElement(ad);
}
}
vertexBuffers.AppendElement(vb_desc);
}
// Now patch up all the pointers to attribute lists.
size_t numAttributes = 0;
for (auto& vb_desc : vertexBuffers) {
vb_desc.attributes = vertexAttributes.Elements() + numAttributes;
numAttributes += vb_desc.attributes_length;
}
desc.vertex_state.vertex_buffers = vertexBuffers.Elements();
desc.vertex_state.vertex_buffers_length = vertexBuffers.Length();
desc.sample_count = aDesc.mSampleCount;
desc.sample_mask = aDesc.mSampleMask;
desc.alpha_to_coverage_enabled = aDesc.mAlphaToCoverageEnabled;
ByteBuf bb;
RawId implicit_bgl_ids[WGPUMAX_BIND_GROUPS] = {};
RawId id = ffi::wgpu_client_create_render_pipeline(
mClient, aSelfId, &desc, ToFFI(&bb), implicit_bgl_ids);
for (const auto& cur : implicit_bgl_ids) {
if (!cur) break;
aImplicitBindGroupLayoutIds->AppendElement(cur);
}
if (!SendDeviceAction(aSelfId, std::move(bb))) {
MOZ_CRASH("IPC failure");
}
return id;
}
ipc::IPCResult WebGPUChild::RecvDropAction(const ipc::ByteBuf& aByteBuf) {
const auto* byteBuf = ToFFI(&aByteBuf);
ffi::wgpu_client_drop_action(mClient, byteBuf);
return IPC_OK();
}
ipc::IPCResult WebGPUChild::RecvFreeAdapter(RawId id) {
ffi::wgpu_client_kill_adapter_id(mClient, id);
return IPC_OK();
}
ipc::IPCResult WebGPUChild::RecvFreeDevice(RawId id) {
ffi::wgpu_client_kill_device_id(mClient, id);
return IPC_OK();
}
ipc::IPCResult WebGPUChild::RecvFreePipelineLayout(RawId id) {
ffi::wgpu_client_kill_pipeline_layout_id(mClient, id);
return IPC_OK();
}
ipc::IPCResult WebGPUChild::RecvFreeShaderModule(RawId id) {
ffi::wgpu_client_kill_shader_module_id(mClient, id);
return IPC_OK();
}
ipc::IPCResult WebGPUChild::RecvFreeBindGroupLayout(RawId id) {
ffi::wgpu_client_kill_bind_group_layout_id(mClient, id);
return IPC_OK();
}
ipc::IPCResult WebGPUChild::RecvFreeBindGroup(RawId id) {
ffi::wgpu_client_kill_bind_group_id(mClient, id);
return IPC_OK();
}
ipc::IPCResult WebGPUChild::RecvFreeCommandBuffer(RawId id) {
ffi::wgpu_client_kill_encoder_id(mClient, id);
return IPC_OK();
}
ipc::IPCResult WebGPUChild::RecvFreeRenderPipeline(RawId id) {
ffi::wgpu_client_kill_render_pipeline_id(mClient, id);
return IPC_OK();
}
ipc::IPCResult WebGPUChild::RecvFreeComputePipeline(RawId id) {
ffi::wgpu_client_kill_compute_pipeline_id(mClient, id);
return IPC_OK();
}
ipc::IPCResult WebGPUChild::RecvFreeBuffer(RawId id) {
ffi::wgpu_client_kill_buffer_id(mClient, id);
return IPC_OK();
}
ipc::IPCResult WebGPUChild::RecvFreeTexture(RawId id) {
ffi::wgpu_client_kill_texture_id(mClient, id);
return IPC_OK();
}
ipc::IPCResult WebGPUChild::RecvFreeTextureView(RawId id) {
ffi::wgpu_client_kill_texture_view_id(mClient, id);
return IPC_OK();
}
ipc::IPCResult WebGPUChild::RecvFreeSampler(RawId id) {
ffi::wgpu_client_kill_sampler_id(mClient, id);
return IPC_OK();
}
void WebGPUChild::DeviceCreateSwapChain(RawId aSelfId,
const RGBDescriptor& aRgbDesc,
size_t maxBufferCount,
wr::ExternalImageId aExternalImageId) {
RawId queueId = aSelfId; // TODO: multiple queues
nsTArray<RawId> bufferIds(maxBufferCount);
for (size_t i = 0; i < maxBufferCount; ++i) {
bufferIds.AppendElement(ffi::wgpu_client_make_buffer_id(mClient, aSelfId));
}
SendDeviceCreateSwapChain(aSelfId, queueId, aRgbDesc, bufferIds,
aExternalImageId);
}
void WebGPUChild::SwapChainPresent(wr::ExternalImageId aExternalImageId,
RawId aTextureId) {
// Hack: the function expects `DeviceId`, but it only uses it for `backend()`
// selection.
RawId encoderId = ffi::wgpu_client_make_encoder_id(mClient, aTextureId);
SendSwapChainPresent(aExternalImageId, aTextureId, encoderId);
}
} // namespace webgpu
} // namespace mozilla