зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1710679 - Implement WebGPU render bundles r=webidl,jgilbert,smaug
Differential Revision: https://phabricator.services.mozilla.com/D114878
This commit is contained in:
Родитель
ed3c20ccb5
Коммит
cee0219fda
|
@ -52,8 +52,10 @@ class ComputePassEncoder final : public ObjectBase,
|
|||
nsTArray<RefPtr<const ComputePipeline>> mUsedPipelines;
|
||||
|
||||
public:
|
||||
// programmable pass encoder
|
||||
void SetBindGroup(uint32_t aSlot, const BindGroup& aBindGroup,
|
||||
const dom::Sequence<uint32_t>& aDynamicOffsets);
|
||||
// self
|
||||
void SetPipeline(const ComputePipeline& aPipeline);
|
||||
void Dispatch(uint32_t x, uint32_t y, uint32_t z);
|
||||
void DispatchIndirect(const Buffer& aIndirectBuffer,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "Buffer.h"
|
||||
#include "ComputePipeline.h"
|
||||
#include "Queue.h"
|
||||
#include "RenderBundleEncoder.h"
|
||||
#include "RenderPipeline.h"
|
||||
#include "Sampler.h"
|
||||
#include "Texture.h"
|
||||
|
@ -166,6 +167,13 @@ already_AddRefed<CommandEncoder> Device::CreateCommandEncoder(
|
|||
return encoder.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<RenderBundleEncoder> Device::CreateRenderBundleEncoder(
|
||||
const dom::GPURenderBundleEncoderDescriptor& aDesc) {
|
||||
RefPtr<RenderBundleEncoder> encoder =
|
||||
new RenderBundleEncoder(this, mBridge, aDesc);
|
||||
return encoder.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<BindGroupLayout> Device::CreateBindGroupLayout(
|
||||
const dom::GPUBindGroupLayoutDescriptor& aDesc) {
|
||||
RawId id = mBridge->DeviceCreateBindGroupLayout(mId, aDesc);
|
||||
|
|
|
@ -119,6 +119,8 @@ class Device final : public DOMEventTargetHelper {
|
|||
|
||||
already_AddRefed<CommandEncoder> CreateCommandEncoder(
|
||||
const dom::GPUCommandEncoderDescriptor& aDesc);
|
||||
already_AddRefed<RenderBundleEncoder> CreateRenderBundleEncoder(
|
||||
const dom::GPURenderBundleEncoderDescriptor& aDesc);
|
||||
|
||||
already_AddRefed<BindGroupLayout> CreateBindGroupLayout(
|
||||
const dom::GPUBindGroupLayoutDescriptor& aDesc);
|
||||
|
|
|
@ -7,14 +7,34 @@
|
|||
#include "RenderBundle.h"
|
||||
|
||||
#include "Device.h"
|
||||
#include "ipc/WebGPUChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace webgpu {
|
||||
|
||||
RenderBundle::~RenderBundle() = default;
|
||||
|
||||
GPU_IMPL_CYCLE_COLLECTION(RenderBundle, mParent)
|
||||
GPU_IMPL_JS_WRAP(RenderBundle)
|
||||
|
||||
RenderBundle::RenderBundle(Device* const aParent, RawId aId)
|
||||
: ChildOf(aParent), mId(aId) {
|
||||
// If we happened to finish an encoder twice, the second
|
||||
// bundle should be invalid.
|
||||
if (!mId) {
|
||||
mValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
RenderBundle::~RenderBundle() { Cleanup(); }
|
||||
|
||||
void RenderBundle::Cleanup() {
|
||||
if (mValid && mParent) {
|
||||
mValid = false;
|
||||
auto bridge = mParent->GetBridge();
|
||||
if (bridge && bridge->IsOpen()) {
|
||||
bridge->SendRenderBundleDestroy(mId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -19,10 +19,13 @@ class RenderBundle final : public ObjectBase, public ChildOf<Device> {
|
|||
GPU_DECL_CYCLE_COLLECTION(RenderBundle)
|
||||
GPU_DECL_JS_WRAP(RenderBundle)
|
||||
|
||||
RenderBundle(Device* const aParent, RawId aId);
|
||||
|
||||
const RawId mId;
|
||||
|
||||
private:
|
||||
RenderBundle() = delete;
|
||||
virtual ~RenderBundle();
|
||||
void Cleanup() {}
|
||||
void Cleanup();
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
|
|
|
@ -6,13 +6,163 @@
|
|||
#include "mozilla/dom/WebGPUBinding.h"
|
||||
#include "RenderBundleEncoder.h"
|
||||
|
||||
#include "BindGroup.h"
|
||||
#include "Buffer.h"
|
||||
#include "RenderBundle.h"
|
||||
#include "RenderPipeline.h"
|
||||
#include "ipc/WebGPUChild.h"
|
||||
#include "mozilla/webgpu/ffi/wgpu.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace webgpu {
|
||||
|
||||
GPU_IMPL_CYCLE_COLLECTION(RenderBundleEncoder, mParent)
|
||||
GPU_IMPL_CYCLE_COLLECTION(RenderBundleEncoder, mParent, mUsedBindGroups,
|
||||
mUsedBuffers, mUsedPipelines, mUsedTextureViews)
|
||||
GPU_IMPL_JS_WRAP(RenderBundleEncoder)
|
||||
|
||||
ffi::WGPURenderBundleEncoder* ScopedFfiBundleTraits::empty() { return nullptr; }
|
||||
|
||||
void ScopedFfiBundleTraits::release(ffi::WGPURenderBundleEncoder* raw) {
|
||||
if (raw) {
|
||||
ffi::wgpu_render_bundle_encoder_destroy(raw);
|
||||
}
|
||||
}
|
||||
|
||||
ffi::WGPURenderBundleEncoder* CreateRenderBundleEncoder(
|
||||
RawId aDeviceId, const dom::GPURenderBundleEncoderDescriptor& aDesc) {
|
||||
ffi::WGPURenderBundleEncoderDescriptor desc = {};
|
||||
desc.sample_count = aDesc.mSampleCount;
|
||||
|
||||
nsCString label;
|
||||
if (aDesc.mLabel.WasPassed()) {
|
||||
LossyCopyUTF16toASCII(aDesc.mLabel.Value(), label);
|
||||
desc.label = label.get();
|
||||
}
|
||||
|
||||
ffi::WGPUTextureFormat depthStencilFormat = ffi::WGPUTextureFormat_Sentinel;
|
||||
if (aDesc.mDepthStencilFormat.WasPassed()) {
|
||||
WebGPUChild::ConvertTextureFormatRef(aDesc.mDepthStencilFormat.Value(),
|
||||
depthStencilFormat);
|
||||
desc.depth_stencil_format = &depthStencilFormat;
|
||||
}
|
||||
|
||||
std::vector<ffi::WGPUTextureFormat> colorFormats = {};
|
||||
for (const auto i : IntegerRange(aDesc.mColorFormats.Length())) {
|
||||
ffi::WGPUTextureFormat format = ffi::WGPUTextureFormat_Sentinel;
|
||||
WebGPUChild::ConvertTextureFormatRef(aDesc.mColorFormats[i], format);
|
||||
colorFormats.push_back(format);
|
||||
}
|
||||
|
||||
desc.color_formats = colorFormats.data();
|
||||
desc.color_formats_length = colorFormats.size();
|
||||
|
||||
return ffi::wgpu_device_create_render_bundle_encoder(aDeviceId, &desc);
|
||||
}
|
||||
|
||||
RenderBundleEncoder::RenderBundleEncoder(
|
||||
Device* const aParent, WebGPUChild* const aBridge,
|
||||
const dom::GPURenderBundleEncoderDescriptor& aDesc)
|
||||
: ChildOf(aParent),
|
||||
mEncoder(CreateRenderBundleEncoder(aParent->mId, aDesc)) {}
|
||||
|
||||
RenderBundleEncoder::~RenderBundleEncoder() { Cleanup(); }
|
||||
|
||||
void RenderBundleEncoder::Cleanup() {
|
||||
if (mValid) {
|
||||
mValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderBundleEncoder::SetBindGroup(
|
||||
uint32_t aSlot, const BindGroup& aBindGroup,
|
||||
const dom::Sequence<uint32_t>& aDynamicOffsets) {
|
||||
if (mValid) {
|
||||
mUsedBindGroups.AppendElement(&aBindGroup);
|
||||
ffi::wgpu_render_bundle_set_bind_group(mEncoder, aSlot, aBindGroup.mId,
|
||||
aDynamicOffsets.Elements(),
|
||||
aDynamicOffsets.Length());
|
||||
}
|
||||
}
|
||||
|
||||
void RenderBundleEncoder::SetPipeline(const RenderPipeline& aPipeline) {
|
||||
if (mValid) {
|
||||
mUsedPipelines.AppendElement(&aPipeline);
|
||||
ffi::wgpu_render_bundle_set_pipeline(mEncoder, aPipeline.mId);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderBundleEncoder::SetIndexBuffer(
|
||||
const Buffer& aBuffer, const dom::GPUIndexFormat& aIndexFormat,
|
||||
uint64_t aOffset, uint64_t aSize) {
|
||||
if (mValid) {
|
||||
mUsedBuffers.AppendElement(&aBuffer);
|
||||
const auto iformat = aIndexFormat == dom::GPUIndexFormat::Uint32
|
||||
? ffi::WGPUIndexFormat_Uint32
|
||||
: ffi::WGPUIndexFormat_Uint16;
|
||||
ffi::wgpu_render_bundle_set_index_buffer(mEncoder, aBuffer.mId, iformat,
|
||||
aOffset, aSize);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderBundleEncoder::SetVertexBuffer(uint32_t aSlot, const Buffer& aBuffer,
|
||||
uint64_t aOffset, uint64_t aSize) {
|
||||
if (mValid) {
|
||||
mUsedBuffers.AppendElement(&aBuffer);
|
||||
ffi::wgpu_render_bundle_set_vertex_buffer(mEncoder, aSlot, aBuffer.mId,
|
||||
aOffset, aSize);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderBundleEncoder::Draw(uint32_t aVertexCount, uint32_t aInstanceCount,
|
||||
uint32_t aFirstVertex, uint32_t aFirstInstance) {
|
||||
if (mValid) {
|
||||
ffi::wgpu_render_bundle_draw(mEncoder, aVertexCount, aInstanceCount,
|
||||
aFirstVertex, aFirstInstance);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderBundleEncoder::DrawIndexed(uint32_t aIndexCount,
|
||||
uint32_t aInstanceCount,
|
||||
uint32_t aFirstIndex, int32_t aBaseVertex,
|
||||
uint32_t aFirstInstance) {
|
||||
if (mValid) {
|
||||
ffi::wgpu_render_bundle_draw_indexed(mEncoder, aIndexCount, aInstanceCount,
|
||||
aFirstIndex, aBaseVertex,
|
||||
aFirstInstance);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderBundleEncoder::DrawIndirect(const Buffer& aIndirectBuffer,
|
||||
uint64_t aIndirectOffset) {
|
||||
if (mValid) {
|
||||
ffi::wgpu_render_bundle_draw_indirect(mEncoder, aIndirectBuffer.mId,
|
||||
aIndirectOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderBundleEncoder::DrawIndexedIndirect(const Buffer& aIndirectBuffer,
|
||||
uint64_t aIndirectOffset) {
|
||||
if (mValid) {
|
||||
ffi::wgpu_render_bundle_draw_indexed_indirect(mEncoder, aIndirectBuffer.mId,
|
||||
aIndirectOffset);
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<RenderBundle> RenderBundleEncoder::Finish(
|
||||
const dom::GPURenderBundleDescriptor& aDesc) {
|
||||
RawId id = 0;
|
||||
if (mValid) {
|
||||
mValid = false;
|
||||
auto bridge = mParent->GetBridge();
|
||||
if (bridge && bridge->IsOpen()) {
|
||||
auto* encoder = mEncoder.forget();
|
||||
MOZ_ASSERT(encoder);
|
||||
id = bridge->RenderBundleEncoderFinish(*encoder, mParent->mId, aDesc);
|
||||
}
|
||||
}
|
||||
RefPtr<RenderBundle> bundle = new RenderBundle(mParent, id);
|
||||
return bundle.forget();
|
||||
}
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -6,26 +6,66 @@
|
|||
#ifndef GPU_RenderBundleEncoder_H_
|
||||
#define GPU_RenderBundleEncoder_H_
|
||||
|
||||
#include "mozilla/Scoped.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "ObjectModel.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace webgpu {
|
||||
namespace ffi {
|
||||
struct WGPURenderBundleEncoder;
|
||||
} // namespace ffi
|
||||
|
||||
class Device;
|
||||
class RenderBundle;
|
||||
|
||||
struct ScopedFfiBundleTraits {
|
||||
typedef ffi::WGPURenderBundleEncoder* type;
|
||||
static type empty();
|
||||
static void release(type raw);
|
||||
};
|
||||
|
||||
class RenderBundleEncoder final : public ObjectBase, public ChildOf<Device> {
|
||||
public:
|
||||
GPU_DECL_CYCLE_COLLECTION(RenderBundleEncoder)
|
||||
GPU_DECL_JS_WRAP(RenderBundleEncoder)
|
||||
|
||||
RenderBundleEncoder() = delete;
|
||||
RenderBundleEncoder(Device* const aParent, WebGPUChild* const aBridge,
|
||||
const dom::GPURenderBundleEncoderDescriptor& aDesc);
|
||||
|
||||
private:
|
||||
~RenderBundleEncoder() = default;
|
||||
void Cleanup() {}
|
||||
~RenderBundleEncoder();
|
||||
void Cleanup();
|
||||
|
||||
Scoped<ScopedFfiBundleTraits> mEncoder;
|
||||
// keep all the used objects alive while the encoder is finished
|
||||
nsTArray<RefPtr<const BindGroup>> mUsedBindGroups;
|
||||
nsTArray<RefPtr<const Buffer>> mUsedBuffers;
|
||||
nsTArray<RefPtr<const RenderPipeline>> mUsedPipelines;
|
||||
nsTArray<RefPtr<const TextureView>> mUsedTextureViews;
|
||||
|
||||
public:
|
||||
// programmable pass encoder
|
||||
void SetBindGroup(uint32_t aSlot, const BindGroup& aBindGroup,
|
||||
const dom::Sequence<uint32_t>& aDynamicOffsets);
|
||||
// render encoder base
|
||||
void SetPipeline(const RenderPipeline& aPipeline);
|
||||
void SetIndexBuffer(const Buffer& aBuffer,
|
||||
const dom::GPUIndexFormat& aIndexFormat, uint64_t aOffset,
|
||||
uint64_t aSize);
|
||||
void SetVertexBuffer(uint32_t aSlot, const Buffer& aBuffer, uint64_t aOffset,
|
||||
uint64_t aSize);
|
||||
void Draw(uint32_t aVertexCount, uint32_t aInstanceCount,
|
||||
uint32_t aFirstVertex, uint32_t aFirstInstance);
|
||||
void DrawIndexed(uint32_t aIndexCount, uint32_t aInstanceCount,
|
||||
uint32_t aFirstIndex, int32_t aBaseVertex,
|
||||
uint32_t aFirstInstance);
|
||||
void DrawIndirect(const Buffer& aIndirectBuffer, uint64_t aIndirectOffset);
|
||||
void DrawIndexedIndirect(const Buffer& aIndirectBuffer,
|
||||
uint64_t aIndirectOffset);
|
||||
// self
|
||||
already_AddRefed<RenderBundle> Finish(
|
||||
const dom::GPURenderBundleDescriptor& aDesc);
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "RenderPassEncoder.h"
|
||||
#include "BindGroup.h"
|
||||
#include "CommandEncoder.h"
|
||||
#include "RenderBundle.h"
|
||||
#include "RenderPipeline.h"
|
||||
#include "mozilla/webgpu/ffi/wgpu.h"
|
||||
|
||||
|
@ -14,7 +15,8 @@ namespace mozilla {
|
|||
namespace webgpu {
|
||||
|
||||
GPU_IMPL_CYCLE_COLLECTION(RenderPassEncoder, mParent, mUsedBindGroups,
|
||||
mUsedBuffers, mUsedPipelines, mUsedTextureViews)
|
||||
mUsedBuffers, mUsedPipelines, mUsedTextureViews,
|
||||
mUsedRenderBundles)
|
||||
GPU_IMPL_JS_WRAP(RenderPassEncoder)
|
||||
|
||||
ffi::WGPURenderPass* ScopedFfiRenderTraits::empty() { return nullptr; }
|
||||
|
@ -248,6 +250,19 @@ void RenderPassEncoder::SetStencilReference(uint32_t reference) {
|
|||
}
|
||||
}
|
||||
|
||||
void RenderPassEncoder::ExecuteBundles(
|
||||
const dom::Sequence<OwningNonNull<RenderBundle>>& aBundles) {
|
||||
if (mValid) {
|
||||
nsTArray<ffi::WGPURenderBundleId> renderBundles(aBundles.Length());
|
||||
for (const auto& bundle : aBundles) {
|
||||
mUsedRenderBundles.AppendElement(bundle);
|
||||
renderBundles.AppendElement(bundle->mId);
|
||||
}
|
||||
ffi::wgpu_render_pass_execute_bundles(mPass, renderBundles.Elements(),
|
||||
renderBundles.Length());
|
||||
}
|
||||
}
|
||||
|
||||
void RenderPassEncoder::EndPass(ErrorResult& aRv) {
|
||||
if (mValid) {
|
||||
mValid = false;
|
||||
|
|
|
@ -60,10 +60,13 @@ class RenderPassEncoder final : public ObjectBase,
|
|||
nsTArray<RefPtr<const Buffer>> mUsedBuffers;
|
||||
nsTArray<RefPtr<const RenderPipeline>> mUsedPipelines;
|
||||
nsTArray<RefPtr<const TextureView>> mUsedTextureViews;
|
||||
nsTArray<RefPtr<const RenderBundle>> mUsedRenderBundles;
|
||||
|
||||
public:
|
||||
// programmable pass encoder
|
||||
void SetBindGroup(uint32_t aSlot, const BindGroup& aBindGroup,
|
||||
const dom::Sequence<uint32_t>& aDynamicOffsets);
|
||||
// render encoder base
|
||||
void SetPipeline(const RenderPipeline& aPipeline);
|
||||
void SetIndexBuffer(const Buffer& aBuffer,
|
||||
const dom::GPUIndexFormat& aIndexFormat, uint64_t aOffset,
|
||||
|
@ -78,11 +81,14 @@ class RenderPassEncoder final : public ObjectBase,
|
|||
void DrawIndirect(const Buffer& aIndirectBuffer, uint64_t aIndirectOffset);
|
||||
void DrawIndexedIndirect(const Buffer& aIndirectBuffer,
|
||||
uint64_t aIndirectOffset);
|
||||
// self
|
||||
void SetViewport(float x, float y, float width, float height, float minDepth,
|
||||
float maxDepth);
|
||||
void SetScissorRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
|
||||
void SetBlendConstant(const dom::DoubleSequenceOrGPUColorDict& color);
|
||||
void SetStencilReference(uint32_t reference);
|
||||
void ExecuteBundles(
|
||||
const dom::Sequence<OwningNonNull<RenderBundle>>& aBundles);
|
||||
void EndPass(ErrorResult& aRv);
|
||||
};
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ parent:
|
|||
async CommandEncoderFinish(RawId selfId, RawId deviceId, GPUCommandBufferDescriptor desc);
|
||||
async CommandEncoderDestroy(RawId selfId);
|
||||
async CommandBufferDestroy(RawId selfId);
|
||||
async RenderBundleDestroy(RawId selfId);
|
||||
async QueueSubmit(RawId selfId, RawId aDeviceId, RawId[] commandBuffers);
|
||||
async QueueWriteAction(RawId selfId, RawId aDeviceId, ByteBuf buf, Shmem shmem);
|
||||
|
||||
|
|
|
@ -153,6 +153,11 @@ static ffi::WGPUTextureFormat ConvertTextureFormat(
|
|||
MOZ_CRASH("unexpected texture format enum");
|
||||
}
|
||||
|
||||
void WebGPUChild::ConvertTextureFormatRef(const dom::GPUTextureFormat& aInput,
|
||||
ffi::WGPUTextureFormat& aOutput) {
|
||||
aOutput = ConvertTextureFormat(aInput);
|
||||
}
|
||||
|
||||
static ffi::WGPUClient* initialize() {
|
||||
ffi::WGPUInfrastructure infra = ffi::wgpu_client_new();
|
||||
return infra.client;
|
||||
|
@ -394,6 +399,27 @@ RawId WebGPUChild::CommandEncoderFinish(
|
|||
return aSelfId;
|
||||
}
|
||||
|
||||
RawId WebGPUChild::RenderBundleEncoderFinish(
|
||||
ffi::WGPURenderBundleEncoder& aEncoder, RawId aDeviceId,
|
||||
const dom::GPURenderBundleDescriptor& aDesc) {
|
||||
ffi::WGPURenderBundleDescriptor desc = {};
|
||||
nsCString label;
|
||||
if (aDesc.mLabel.WasPassed()) {
|
||||
LossyCopyUTF16toASCII(aDesc.mLabel.Value(), label);
|
||||
desc.label = label.get();
|
||||
}
|
||||
|
||||
ipc::ByteBuf bb;
|
||||
RawId id = ffi::wgpu_client_create_render_bundle(
|
||||
mClient, &aEncoder, aDeviceId, &desc, ToFFI(&bb));
|
||||
|
||||
if (!SendDeviceAction(aDeviceId, std::move(bb))) {
|
||||
MOZ_CRASH("IPC failure");
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
RawId WebGPUChild::DeviceCreateBindGroupLayout(
|
||||
RawId aSelfId, const dom::GPUBindGroupLayoutDescriptor& aDesc) {
|
||||
struct OptionalData {
|
||||
|
|
|
@ -56,6 +56,9 @@ class WebGPUChild final : public PWebGPUChild, public SupportsWeakPtr {
|
|||
RawId aSelfId, const dom::GPUCommandEncoderDescriptor& aDesc);
|
||||
RawId CommandEncoderFinish(RawId aSelfId, RawId aDeviceId,
|
||||
const dom::GPUCommandBufferDescriptor& aDesc);
|
||||
RawId RenderBundleEncoderFinish(ffi::WGPURenderBundleEncoder& aEncoder,
|
||||
RawId aDeviceId,
|
||||
const dom::GPURenderBundleDescriptor& aDesc);
|
||||
RawId DeviceCreateBindGroupLayout(
|
||||
RawId aSelfId, const dom::GPUBindGroupLayoutDescriptor& aDesc);
|
||||
RawId DeviceCreatePipelineLayout(
|
||||
|
@ -81,6 +84,9 @@ class WebGPUChild final : public PWebGPUChild, public SupportsWeakPtr {
|
|||
void RegisterDevice(RawId aId, Device* aDevice);
|
||||
void UnregisterDevice(RawId aId);
|
||||
|
||||
static void ConvertTextureFormatRef(const dom::GPUTextureFormat& aInput,
|
||||
ffi::WGPUTextureFormat& aOutput);
|
||||
|
||||
private:
|
||||
virtual ~WebGPUChild();
|
||||
|
||||
|
|
|
@ -408,6 +408,11 @@ ipc::IPCResult WebGPUParent::RecvCommandBufferDestroy(RawId aSelfId) {
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
ipc::IPCResult WebGPUParent::RecvRenderBundleDestroy(RawId aSelfId) {
|
||||
ffi::wgpu_server_render_bundle_drop(mContext, aSelfId);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
ipc::IPCResult WebGPUParent::RecvQueueSubmit(
|
||||
RawId aSelfId, RawId aDeviceId, const nsTArray<RawId>& aCommandBuffers) {
|
||||
ErrorBuffer error;
|
||||
|
|
|
@ -45,6 +45,7 @@ class WebGPUParent final : public PWebGPUParent {
|
|||
const dom::GPUCommandBufferDescriptor& aDesc);
|
||||
ipc::IPCResult RecvCommandEncoderDestroy(RawId aSelfId);
|
||||
ipc::IPCResult RecvCommandBufferDestroy(RawId aSelfId);
|
||||
ipc::IPCResult RecvRenderBundleDestroy(RawId aSelfId);
|
||||
ipc::IPCResult RecvQueueSubmit(RawId aSelfId, RawId aDeviceId,
|
||||
const nsTArray<RawId>& aCommandBuffers);
|
||||
ipc::IPCResult RecvQueueWriteAction(RawId aSelfId, RawId aDeviceId,
|
||||
|
|
|
@ -14,6 +14,11 @@ const func = async function() {
|
|||
const adapter = await navigator.gpu.requestAdapter();
|
||||
const device = await adapter.requestDevice();
|
||||
|
||||
const bundleEncoder = device.createRenderBundleEncoder({
|
||||
colorFormats: [swapChainFormat],
|
||||
});
|
||||
const bundle = bundleEncoder.finish({});
|
||||
|
||||
const texture = device.createTexture({
|
||||
size: { width: 100, height: 100, depth: 1 },
|
||||
format: "rgba8unorm",
|
||||
|
@ -29,8 +34,10 @@ const func = async function() {
|
|||
storeOp: "store",
|
||||
}],
|
||||
});
|
||||
pass.executeBundles([bundle]);
|
||||
pass.endPass();
|
||||
const command_buffer = encoder.finish();
|
||||
|
||||
device.queue.submit([command_buffer]);
|
||||
ok(command_buffer !== undefined, 'command_buffer !== undefined');
|
||||
};
|
||||
|
|
|
@ -170,8 +170,8 @@ interface GPUDevice: EventTarget {
|
|||
|
||||
[NewObject]
|
||||
GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor = {});
|
||||
//[NewObject]
|
||||
//GPURenderBundleEncoder createRenderBundleEncoder(GPURenderBundleEncoderDescriptor descriptor);
|
||||
[NewObject]
|
||||
GPURenderBundleEncoder createRenderBundleEncoder(GPURenderBundleEncoderDescriptor descriptor);
|
||||
//[NewObject]
|
||||
//GPUQuerySet createQuerySet(GPUQuerySetDescriptor descriptor);
|
||||
};
|
||||
|
@ -1019,7 +1019,7 @@ interface GPURenderPassEncoder {
|
|||
|
||||
//void writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex);
|
||||
|
||||
//void executeBundles(sequence<GPURenderBundle> bundles);
|
||||
void executeBundles(sequence<GPURenderBundle> bundles);
|
||||
|
||||
[Throws]
|
||||
void endPass();
|
||||
|
@ -1074,12 +1074,11 @@ dictionary GPURenderBundleEncoderDescriptor : GPUObjectDescriptorBase {
|
|||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=Window]
|
||||
interface GPURenderBundleEncoder {
|
||||
//GPURenderBundle finish(optional GPURenderBundleDescriptor descriptor = {});
|
||||
GPURenderBundle finish(optional GPURenderBundleDescriptor descriptor = {});
|
||||
};
|
||||
GPURenderBundleEncoder includes GPUObjectBase;
|
||||
//TODO
|
||||
//GPURenderBundleEncoder includes GPUProgrammablePassEncoder;
|
||||
//GPURenderBundleEncoder includes GPURenderEncoderBase;
|
||||
GPURenderBundleEncoder includes GPUProgrammablePassEncoder;
|
||||
GPURenderBundleEncoder includes GPURenderEncoderBase;
|
||||
|
||||
// ****************************************************************************
|
||||
// OTHER (Query, Queue, SwapChain, Device)
|
||||
|
|
|
@ -1303,7 +1303,7 @@ pub mod bundle_ffi {
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_render_pass_bundle_indexed_indirect(
|
||||
pub extern "C" fn wgpu_render_bundle_draw_indexed_indirect(
|
||||
bundle: &mut RenderBundleEncoder,
|
||||
buffer_id: id::BufferId,
|
||||
offset: BufferAddress,
|
||||
|
|
|
@ -2339,7 +2339,7 @@ pub mod render_ffi {
|
|||
/// This function is unsafe as there is no guarantee that the given pointer is
|
||||
/// valid for `render_bundle_ids_length` elements.
|
||||
#[no_mangle]
|
||||
pub unsafe fn wgpu_render_pass_execute_bundles(
|
||||
pub unsafe extern "C" fn wgpu_render_pass_execute_bundles(
|
||||
pass: &mut RenderPass,
|
||||
render_bundle_ids: *const id::RenderBundleId,
|
||||
render_bundle_ids_length: usize,
|
||||
|
|
|
@ -40,6 +40,7 @@ exclude = [
|
|||
"BufferDescriptor_RawString" = "BufferDescriptor"
|
||||
"CommandBufferDescriptor_RawString" = "CommandBufferDescriptor"
|
||||
"CommandEncoderDescriptor_RawString" = "CommandEncoderDescriptor"
|
||||
"RenderBundleDescriptor_RawString" = "RenderBundleDescriptor"
|
||||
"DeviceDescriptor_RawString" = "DeviceDescriptor"
|
||||
"TextureDescriptor_RawString" = "TextureDescriptor"
|
||||
"SamplerDescriptor_RawString" = "SamplerDescriptor"
|
||||
|
|
|
@ -256,6 +256,15 @@ pub struct TextureViewDescriptor<'a> {
|
|||
array_layer_count: Option<NonZeroU32>,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct RenderBundleEncoderDescriptor<'a> {
|
||||
label: RawString,
|
||||
color_formats: *const wgt::TextureFormat,
|
||||
color_formats_length: usize,
|
||||
depth_stencil_format: Option<&'a wgt::TextureFormat>,
|
||||
sample_count: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct IdentityHub {
|
||||
adapters: IdentityManager,
|
||||
|
@ -603,6 +612,54 @@ pub extern "C" fn wgpu_client_create_command_encoder(
|
|||
id
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_device_create_render_bundle_encoder(
|
||||
device_id: id::DeviceId,
|
||||
desc: &RenderBundleEncoderDescriptor,
|
||||
) -> *mut wgc::command::RenderBundleEncoder {
|
||||
let descriptor = wgc::command::RenderBundleEncoderDescriptor {
|
||||
label: cow_label(&desc.label),
|
||||
color_formats: Cow::Borrowed(make_slice(desc.color_formats, desc.color_formats_length)),
|
||||
depth_stencil_format: desc.depth_stencil_format.cloned(),
|
||||
sample_count: desc.sample_count,
|
||||
};
|
||||
match wgc::command::RenderBundleEncoder::new(&descriptor, device_id, None) {
|
||||
Ok(encoder) => Box::into_raw(Box::new(encoder)),
|
||||
Err(e) => panic!("Error in Device::create_render_bundle_encoder: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wgpu_render_bundle_encoder_destroy(
|
||||
pass: *mut wgc::command::RenderBundleEncoder,
|
||||
) {
|
||||
// The RB encoder is just a boxed Rust struct, it doesn't have any API primitives
|
||||
// associated with it right now, but in the future it will.
|
||||
let _ = Box::from_raw(pass);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wgpu_client_create_render_bundle(
|
||||
client: &Client,
|
||||
encoder: *mut wgc::command::RenderBundleEncoder,
|
||||
device_id: id::DeviceId,
|
||||
desc: &wgt::RenderBundleDescriptor<RawString>,
|
||||
bb: &mut ByteBuf,
|
||||
) -> id::RenderBundleId {
|
||||
let backend = device_id.backend();
|
||||
let id = client
|
||||
.identities
|
||||
.lock()
|
||||
.select(backend)
|
||||
.render_bundles
|
||||
.alloc(backend);
|
||||
|
||||
let action =
|
||||
DeviceAction::CreateRenderBundle(id, *Box::from_raw(encoder), desc.map_label(cow_label));
|
||||
*bb = make_byte_buf(&action);
|
||||
id
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ComputePassDescriptor {
|
||||
pub label: RawString,
|
||||
|
@ -1004,6 +1061,17 @@ pub unsafe extern "C" fn wgpu_render_pass_set_index_buffer(
|
|||
pass.set_index_buffer(buffer, index_format, offset, size);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wgpu_render_bundle_set_index_buffer(
|
||||
encoder: &mut wgc::command::RenderBundleEncoder,
|
||||
buffer: wgc::id::BufferId,
|
||||
index_format: wgt::IndexFormat,
|
||||
offset: wgt::BufferAddress,
|
||||
size: Option<wgt::BufferSize>,
|
||||
) {
|
||||
encoder.set_index_buffer(buffer, index_format, offset, size);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wgpu_queue_write_buffer(
|
||||
dst: id::BufferId,
|
||||
|
|
|
@ -110,8 +110,8 @@ enum DeviceAction<'a> {
|
|||
),
|
||||
CreateRenderBundle(
|
||||
id::RenderBundleId,
|
||||
wgc::command::RenderBundleEncoderDescriptor<'a>,
|
||||
wgc::command::BasePass<wgc::command::RenderCommand>,
|
||||
wgc::command::RenderBundleEncoder,
|
||||
wgc::command::RenderBundleDescriptor<'a>,
|
||||
),
|
||||
CreateCommandEncoder(
|
||||
id::CommandEncoderId,
|
||||
|
|
|
@ -332,8 +332,11 @@ impl GlobalExt for Global {
|
|||
error_buf.init(err);
|
||||
}
|
||||
}
|
||||
DeviceAction::CreateRenderBundle(_id, desc, _base) => {
|
||||
wgc::command::RenderBundleEncoder::new(&desc, self_id, None).unwrap();
|
||||
DeviceAction::CreateRenderBundle(id, encoder, desc) => {
|
||||
let (_, error) = self.render_bundle_encoder_finish::<B>(encoder, &desc, id);
|
||||
if let Some(err) = error {
|
||||
error_buf.init(err);
|
||||
}
|
||||
}
|
||||
DeviceAction::CreateCommandEncoder(id, desc) => {
|
||||
let (_, error) = self.device_create_command_encoder::<B>(self_id, &desc, id);
|
||||
|
@ -522,15 +525,16 @@ pub extern "C" fn wgpu_server_encoder_drop(global: &Global, self_id: id::Command
|
|||
gfx_select!(self_id => global.command_encoder_drop(self_id));
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe as there is no guarantee that the given pointer is
|
||||
/// valid for `byte_length` elements.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_server_command_buffer_drop(global: &Global, self_id: id::CommandBufferId) {
|
||||
gfx_select!(self_id => global.command_buffer_drop(self_id));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_server_render_bundle_drop(global: &Global, self_id: id::RenderBundleId) {
|
||||
gfx_select!(self_id => global.render_bundle_drop(self_id));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wgpu_server_encoder_copy_texture_to_buffer(
|
||||
global: &Global,
|
||||
|
|
Загрузка…
Ссылка в новой задаче