1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/dom/WebGPUBinding.h"
7 #include "RenderBundleEncoder.h"
11 #include "RenderBundle.h"
12 #include "RenderPipeline.h"
14 #include "ipc/WebGPUChild.h"
15 #include "mozilla/webgpu/ffi/wgpu.h"
17 namespace mozilla::webgpu
{
19 GPU_IMPL_CYCLE_COLLECTION(RenderBundleEncoder
, mParent
, mUsedBindGroups
,
20 mUsedBuffers
, mUsedPipelines
, mUsedTextureViews
)
21 GPU_IMPL_JS_WRAP(RenderBundleEncoder
)
23 void ffiWGPURenderBundleEncoderDeleter::operator()(
24 ffi::WGPURenderBundleEncoder
* raw
) {
26 ffi::wgpu_render_bundle_encoder_destroy(raw
);
30 ffi::WGPURenderBundleEncoder
* CreateRenderBundleEncoder(
31 RawId aDeviceId
, const dom::GPURenderBundleEncoderDescriptor
& aDesc
,
32 WebGPUChild
* const aBridge
) {
33 if (!aBridge
->CanSend()) {
37 ffi::WGPURenderBundleEncoderDescriptor desc
= {};
38 desc
.sample_count
= aDesc
.mSampleCount
;
40 webgpu::StringHelper
label(aDesc
.mLabel
);
41 desc
.label
= label
.Get();
43 ffi::WGPUTextureFormat depthStencilFormat
= {ffi::WGPUTextureFormat_Sentinel
};
44 if (aDesc
.mDepthStencilFormat
.WasPassed()) {
46 ConvertTextureFormat(aDesc
.mDepthStencilFormat
.Value());
47 desc
.depth_stencil_format
= &depthStencilFormat
;
50 std::vector
<ffi::WGPUTextureFormat
> colorFormats
= {};
51 for (const auto i
: IntegerRange(aDesc
.mColorFormats
.Length())) {
52 ffi::WGPUTextureFormat format
= {ffi::WGPUTextureFormat_Sentinel
};
53 format
= ConvertTextureFormat(aDesc
.mColorFormats
[i
]);
54 colorFormats
.push_back(format
);
57 desc
.color_formats
= colorFormats
.data();
58 desc
.color_formats_length
= colorFormats
.size();
60 ipc::ByteBuf failureAction
;
61 auto* bundle
= ffi::wgpu_device_create_render_bundle_encoder(
62 aDeviceId
, &desc
, ToFFI(&failureAction
));
63 // Report an error only if the operation failed.
65 aBridge
->SendDeviceAction(aDeviceId
, std::move(failureAction
));
70 RenderBundleEncoder::RenderBundleEncoder(
71 Device
* const aParent
, WebGPUChild
* const aBridge
,
72 const dom::GPURenderBundleEncoderDescriptor
& aDesc
)
74 mEncoder(CreateRenderBundleEncoder(aParent
->mId
, aDesc
, aBridge
)) {
75 mValid
= mEncoder
.get() != nullptr;
78 RenderBundleEncoder::~RenderBundleEncoder() { Cleanup(); }
80 void RenderBundleEncoder::Cleanup() {
86 void RenderBundleEncoder::SetBindGroup(
87 uint32_t aSlot
, const BindGroup
& aBindGroup
,
88 const dom::Sequence
<uint32_t>& aDynamicOffsets
) {
90 mUsedBindGroups
.AppendElement(&aBindGroup
);
91 ffi::wgpu_render_bundle_set_bind_group(
92 mEncoder
.get(), aSlot
, aBindGroup
.mId
, aDynamicOffsets
.Elements(),
93 aDynamicOffsets
.Length());
97 void RenderBundleEncoder::SetPipeline(const RenderPipeline
& aPipeline
) {
99 mUsedPipelines
.AppendElement(&aPipeline
);
100 ffi::wgpu_render_bundle_set_pipeline(mEncoder
.get(), aPipeline
.mId
);
104 void RenderBundleEncoder::SetIndexBuffer(
105 const Buffer
& aBuffer
, const dom::GPUIndexFormat
& aIndexFormat
,
106 uint64_t aOffset
, uint64_t aSize
) {
108 mUsedBuffers
.AppendElement(&aBuffer
);
109 const auto iformat
= aIndexFormat
== dom::GPUIndexFormat::Uint32
110 ? ffi::WGPUIndexFormat_Uint32
111 : ffi::WGPUIndexFormat_Uint16
;
112 ffi::wgpu_render_bundle_set_index_buffer(mEncoder
.get(), aBuffer
.mId
,
113 iformat
, aOffset
, aSize
);
117 void RenderBundleEncoder::SetVertexBuffer(uint32_t aSlot
, const Buffer
& aBuffer
,
118 uint64_t aOffset
, uint64_t aSize
) {
120 mUsedBuffers
.AppendElement(&aBuffer
);
121 ffi::wgpu_render_bundle_set_vertex_buffer(mEncoder
.get(), aSlot
,
122 aBuffer
.mId
, aOffset
, aSize
);
126 void RenderBundleEncoder::Draw(uint32_t aVertexCount
, uint32_t aInstanceCount
,
127 uint32_t aFirstVertex
, uint32_t aFirstInstance
) {
129 ffi::wgpu_render_bundle_draw(mEncoder
.get(), aVertexCount
, aInstanceCount
,
130 aFirstVertex
, aFirstInstance
);
134 void RenderBundleEncoder::DrawIndexed(uint32_t aIndexCount
,
135 uint32_t aInstanceCount
,
136 uint32_t aFirstIndex
, int32_t aBaseVertex
,
137 uint32_t aFirstInstance
) {
139 ffi::wgpu_render_bundle_draw_indexed(mEncoder
.get(), aIndexCount
,
140 aInstanceCount
, aFirstIndex
,
141 aBaseVertex
, aFirstInstance
);
145 void RenderBundleEncoder::DrawIndirect(const Buffer
& aIndirectBuffer
,
146 uint64_t aIndirectOffset
) {
148 ffi::wgpu_render_bundle_draw_indirect(mEncoder
.get(), aIndirectBuffer
.mId
,
153 void RenderBundleEncoder::DrawIndexedIndirect(const Buffer
& aIndirectBuffer
,
154 uint64_t aIndirectOffset
) {
156 ffi::wgpu_render_bundle_draw_indexed_indirect(
157 mEncoder
.get(), aIndirectBuffer
.mId
, aIndirectOffset
);
161 void RenderBundleEncoder::PushDebugGroup(const nsAString
& aString
) {
163 const NS_ConvertUTF16toUTF8
utf8(aString
);
164 ffi::wgpu_render_bundle_push_debug_group(mEncoder
.get(), utf8
.get());
167 void RenderBundleEncoder::PopDebugGroup() {
169 ffi::wgpu_render_bundle_pop_debug_group(mEncoder
.get());
172 void RenderBundleEncoder::InsertDebugMarker(const nsAString
& aString
) {
174 const NS_ConvertUTF16toUTF8
utf8(aString
);
175 ffi::wgpu_render_bundle_insert_debug_marker(mEncoder
.get(), utf8
.get());
179 already_AddRefed
<RenderBundle
> RenderBundleEncoder::Finish(
180 const dom::GPURenderBundleDescriptor
& aDesc
) {
181 RawId deviceId
= mParent
->mId
;
182 auto bridge
= mParent
->GetBridge();
183 MOZ_RELEASE_ASSERT(bridge
);
185 ffi::WGPURenderBundleDescriptor desc
= {};
186 webgpu::StringHelper
label(aDesc
.mLabel
);
187 desc
.label
= label
.Get();
194 auto* encoder
= mEncoder
.release();
195 id
= ffi::wgpu_client_create_render_bundle(bridge
->GetClient(), encoder
,
196 deviceId
, &desc
, ToFFI(&bb
));
199 id
= ffi::wgpu_client_create_render_bundle_error(
200 bridge
->GetClient(), deviceId
, label
.Get(), ToFFI(&bb
));
203 if (bridge
->CanSend()) {
204 bridge
->SendDeviceAction(deviceId
, std::move(bb
));
207 RefPtr
<RenderBundle
> bundle
= new RenderBundle(mParent
, id
);
208 return bundle
.forget();
211 } // namespace mozilla::webgpu