Bug 1857841 - pt 3. Add a new page kind named "fresh" r=glandium
[gecko.git] / dom / webgpu / RenderBundleEncoder.cpp
blob54ebf12d6400a1b1adf99cadb0695a6aa5410b52
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"
9 #include "BindGroup.h"
10 #include "Buffer.h"
11 #include "RenderBundle.h"
12 #include "RenderPipeline.h"
13 #include "Utility.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) {
25 if (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()) {
34 return nullptr;
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()) {
45 depthStencilFormat =
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.
64 if (!bundle) {
65 aBridge->SendDeviceAction(aDeviceId, std::move(failureAction));
67 return bundle;
70 RenderBundleEncoder::RenderBundleEncoder(
71 Device* const aParent, WebGPUChild* const aBridge,
72 const dom::GPURenderBundleEncoderDescriptor& aDesc)
73 : ChildOf(aParent),
74 mEncoder(CreateRenderBundleEncoder(aParent->mId, aDesc, aBridge)) {
75 mValid = mEncoder.get() != nullptr;
78 RenderBundleEncoder::~RenderBundleEncoder() { Cleanup(); }
80 void RenderBundleEncoder::Cleanup() {
81 if (mValid) {
82 mValid = false;
86 void RenderBundleEncoder::SetBindGroup(
87 uint32_t aSlot, const BindGroup& aBindGroup,
88 const dom::Sequence<uint32_t>& aDynamicOffsets) {
89 if (mValid) {
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) {
98 if (mValid) {
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) {
107 if (mValid) {
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) {
119 if (mValid) {
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) {
128 if (mValid) {
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) {
138 if (mValid) {
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) {
147 if (mValid) {
148 ffi::wgpu_render_bundle_draw_indirect(mEncoder.get(), aIndirectBuffer.mId,
149 aIndirectOffset);
153 void RenderBundleEncoder::DrawIndexedIndirect(const Buffer& aIndirectBuffer,
154 uint64_t aIndirectOffset) {
155 if (mValid) {
156 ffi::wgpu_render_bundle_draw_indexed_indirect(
157 mEncoder.get(), aIndirectBuffer.mId, aIndirectOffset);
161 void RenderBundleEncoder::PushDebugGroup(const nsAString& aString) {
162 if (mValid) {
163 const NS_ConvertUTF16toUTF8 utf8(aString);
164 ffi::wgpu_render_bundle_push_debug_group(mEncoder.get(), utf8.get());
167 void RenderBundleEncoder::PopDebugGroup() {
168 if (mValid) {
169 ffi::wgpu_render_bundle_pop_debug_group(mEncoder.get());
172 void RenderBundleEncoder::InsertDebugMarker(const nsAString& aString) {
173 if (mValid) {
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();
189 ipc::ByteBuf bb;
190 RawId id;
191 if (mValid) {
192 mValid = false;
194 auto* encoder = mEncoder.release();
195 id = ffi::wgpu_client_create_render_bundle(bridge->GetClient(), encoder,
196 deviceId, &desc, ToFFI(&bb));
198 } else {
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