Bug 1710679 - Implement WebGPU render bundles r=webidl,jgilbert,smaug

Differential Revision: https://phabricator.services.mozilla.com/D114878
This commit is contained in:
Dzmitry Malyshau 2021-05-26 20:30:45 +00:00
Родитель ed3c20ccb5
Коммит cee0219fda
22 изменённых файлов: 390 добавлений и 26 удалений

Просмотреть файл

@ -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,