tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RenderBundleEncoder.cpp (8385B)


      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/. */
      5 
      6 #include "RenderBundleEncoder.h"
      7 
      8 #include "BindGroup.h"
      9 #include "Buffer.h"
     10 #include "RenderBundle.h"
     11 #include "RenderPipeline.h"
     12 #include "Utility.h"
     13 #include "ipc/WebGPUChild.h"
     14 #include "mozilla/dom/WebGPUBinding.h"
     15 #include "mozilla/webgpu/ffi/wgpu.h"
     16 
     17 namespace mozilla::webgpu {
     18 
     19 GPU_IMPL_CYCLE_COLLECTION(RenderBundleEncoder, mParent, mUsedBindGroups,
     20                          mUsedBuffers, mUsedPipelines)
     21 GPU_IMPL_JS_WRAP(RenderBundleEncoder)
     22 
     23 void ffiWGPURenderBundleEncoderDeleter::operator()(
     24    ffi::WGPURenderBundleEncoder* raw) {
     25  if (raw) {
     26    ffi::wgpu_render_bundle_encoder_destroy(raw);
     27  }
     28 }
     29 
     30 ffi::WGPURenderBundleEncoder* CreateRenderBundleEncoder(
     31    RawId aDeviceId, const dom::GPURenderBundleEncoderDescriptor& aDesc,
     32    WebGPUChild* const aChild) {
     33  ffi::WGPURenderBundleEncoderDescriptor desc = {};
     34  desc.sample_count = aDesc.mSampleCount;
     35 
     36  webgpu::StringHelper label(aDesc.mLabel);
     37  desc.label = label.Get();
     38 
     39  ffi::WGPUTextureFormat depthStencilFormat = {ffi::WGPUTextureFormat_Sentinel};
     40  if (aDesc.mDepthStencilFormat.WasPassed()) {
     41    depthStencilFormat =
     42        ConvertTextureFormat(aDesc.mDepthStencilFormat.Value());
     43    desc.depth_stencil_format = &depthStencilFormat;
     44  }
     45 
     46  std::vector<ffi::WGPUTextureFormat> colorFormats = {};
     47  for (const auto i : IntegerRange(aDesc.mColorFormats.Length())) {
     48    ffi::WGPUTextureFormat format = {ffi::WGPUTextureFormat_Sentinel};
     49    format = ConvertTextureFormat(aDesc.mColorFormats[i]);
     50    colorFormats.push_back(format);
     51  }
     52 
     53  desc.color_formats = {colorFormats.data(), colorFormats.size()};
     54 
     55  auto* bundle = ffi::wgpu_device_create_render_bundle_encoder(
     56      aChild->GetClient(), aDeviceId, &desc);
     57 
     58  return bundle;
     59 }
     60 
     61 RenderBundleEncoder::RenderBundleEncoder(
     62    Device* const aParent, RawId aId,
     63    const dom::GPURenderBundleEncoderDescriptor& aDesc)
     64    : ObjectBase(aParent->GetChild(), aId,
     65                 ffi::wgpu_client_drop_render_bundle_encoder),
     66      ChildOf(aParent),
     67      mEncoder(CreateRenderBundleEncoder(aParent->GetId(), aDesc,
     68                                         aParent->GetChild())) {
     69  mValid = !!mEncoder;
     70 }
     71 
     72 RenderBundleEncoder::~RenderBundleEncoder() = default;
     73 
     74 void RenderBundleEncoder::SetBindGroup(uint32_t aSlot,
     75                                       BindGroup* const aBindGroup,
     76                                       const uint32_t* aDynamicOffsets,
     77                                       size_t aDynamicOffsetsLength) {
     78  RawId bindGroup = 0;
     79  if (aBindGroup) {
     80    mUsedBindGroups.AppendElement(aBindGroup);
     81    mUsedCanvasContexts.AppendElements(aBindGroup->GetCanvasContexts());
     82    bindGroup = aBindGroup->GetId();
     83  }
     84  ffi::wgpu_render_bundle_set_bind_group(
     85      mEncoder.get(), aSlot, bindGroup, aDynamicOffsets, aDynamicOffsetsLength);
     86 }
     87 
     88 void RenderBundleEncoder::SetBindGroup(
     89    uint32_t aSlot, BindGroup* const aBindGroup,
     90    const dom::Sequence<uint32_t>& aDynamicOffsets, ErrorResult& aRv) {
     91  if (!mValid) {
     92    return;
     93  }
     94  this->SetBindGroup(aSlot, aBindGroup, aDynamicOffsets.Elements(),
     95                     aDynamicOffsets.Length());
     96 }
     97 
     98 void RenderBundleEncoder::SetBindGroup(
     99    uint32_t aSlot, BindGroup* const aBindGroup,
    100    const dom::Uint32Array& aDynamicOffsetsData,
    101    uint64_t aDynamicOffsetsDataStart, uint64_t aDynamicOffsetsDataLength,
    102    ErrorResult& aRv) {
    103  if (!mValid) {
    104    return;
    105  }
    106 
    107  auto dynamicOffsets =
    108      GetDynamicOffsetsFromArray(aDynamicOffsetsData, aDynamicOffsetsDataStart,
    109                                 aDynamicOffsetsDataLength, aRv);
    110 
    111  if (dynamicOffsets.isSome()) {
    112    this->SetBindGroup(aSlot, aBindGroup, dynamicOffsets->Elements(),
    113                       dynamicOffsets->Length());
    114  }
    115 }
    116 
    117 void RenderBundleEncoder::SetPipeline(const RenderPipeline& aPipeline) {
    118  if (!mValid) {
    119    return;
    120  }
    121  mUsedPipelines.AppendElement(&aPipeline);
    122  ffi::wgpu_render_bundle_set_pipeline(mEncoder.get(), aPipeline.GetId());
    123 }
    124 
    125 void RenderBundleEncoder::SetIndexBuffer(
    126    const Buffer& aBuffer, const dom::GPUIndexFormat& aIndexFormat,
    127    uint64_t aOffset, const dom::Optional<uint64_t>& aSize) {
    128  if (!mValid) {
    129    return;
    130  }
    131  mUsedBuffers.AppendElement(&aBuffer);
    132  const auto iformat = aIndexFormat == dom::GPUIndexFormat::Uint32
    133                           ? ffi::WGPUIndexFormat_Uint32
    134                           : ffi::WGPUIndexFormat_Uint16;
    135  const uint64_t* sizeRef = aSize.WasPassed() ? &aSize.Value() : nullptr;
    136  ffi::wgpu_render_bundle_set_index_buffer(mEncoder.get(), aBuffer.GetId(),
    137                                           iformat, aOffset, sizeRef);
    138 }
    139 
    140 void RenderBundleEncoder::SetVertexBuffer(
    141    uint32_t aSlot, const Buffer& aBuffer, uint64_t aOffset,
    142    const dom::Optional<uint64_t>& aSize) {
    143  if (!mValid) {
    144    return;
    145  }
    146  mUsedBuffers.AppendElement(&aBuffer);
    147  const uint64_t* sizeRef = aSize.WasPassed() ? &aSize.Value() : nullptr;
    148  ffi::wgpu_render_bundle_set_vertex_buffer(mEncoder.get(), aSlot,
    149                                            aBuffer.GetId(), aOffset, sizeRef);
    150 }
    151 
    152 void RenderBundleEncoder::Draw(uint32_t aVertexCount, uint32_t aInstanceCount,
    153                               uint32_t aFirstVertex, uint32_t aFirstInstance) {
    154  if (!mValid) {
    155    return;
    156  }
    157  ffi::wgpu_render_bundle_draw(mEncoder.get(), aVertexCount, aInstanceCount,
    158                               aFirstVertex, aFirstInstance);
    159 }
    160 
    161 void RenderBundleEncoder::DrawIndexed(uint32_t aIndexCount,
    162                                      uint32_t aInstanceCount,
    163                                      uint32_t aFirstIndex, int32_t aBaseVertex,
    164                                      uint32_t aFirstInstance) {
    165  if (!mValid) {
    166    return;
    167  }
    168  ffi::wgpu_render_bundle_draw_indexed(mEncoder.get(), aIndexCount,
    169                                       aInstanceCount, aFirstIndex, aBaseVertex,
    170                                       aFirstInstance);
    171 }
    172 
    173 void RenderBundleEncoder::DrawIndirect(const Buffer& aIndirectBuffer,
    174                                       uint64_t aIndirectOffset) {
    175  if (!mValid) {
    176    return;
    177  }
    178  mUsedBuffers.AppendElement(&aIndirectBuffer);
    179  ffi::wgpu_render_bundle_draw_indirect(mEncoder.get(), aIndirectBuffer.GetId(),
    180                                        aIndirectOffset);
    181 }
    182 
    183 void RenderBundleEncoder::DrawIndexedIndirect(const Buffer& aIndirectBuffer,
    184                                              uint64_t aIndirectOffset) {
    185  if (!mValid) {
    186    return;
    187  }
    188  mUsedBuffers.AppendElement(&aIndirectBuffer);
    189  ffi::wgpu_render_bundle_draw_indexed_indirect(
    190      mEncoder.get(), aIndirectBuffer.GetId(), aIndirectOffset);
    191 }
    192 
    193 void RenderBundleEncoder::PushDebugGroup(const nsAString& aString) {
    194  if (!mValid) {
    195    return;
    196  }
    197  const NS_ConvertUTF16toUTF8 utf8(aString);
    198  ffi::wgpu_render_bundle_push_debug_group(mEncoder.get(), utf8.get());
    199 }
    200 void RenderBundleEncoder::PopDebugGroup() {
    201  if (!mValid) {
    202    return;
    203  }
    204  ffi::wgpu_render_bundle_pop_debug_group(mEncoder.get());
    205 }
    206 void RenderBundleEncoder::InsertDebugMarker(const nsAString& aString) {
    207  if (!mValid) {
    208    return;
    209  }
    210  const NS_ConvertUTF16toUTF8 utf8(aString);
    211  ffi::wgpu_render_bundle_insert_debug_marker(mEncoder.get(), utf8.get());
    212 }
    213 
    214 already_AddRefed<RenderBundle> RenderBundleEncoder::Finish(
    215    const dom::GPURenderBundleDescriptor& aDesc) {
    216  RawId deviceId = mParent->GetId();
    217 
    218  ffi::WGPURenderBundleDescriptor desc = {};
    219  webgpu::StringHelper label(aDesc.mLabel);
    220  desc.label = label.Get();
    221 
    222  RawId id;
    223  if (mValid) {
    224    id = ffi::wgpu_client_create_render_bundle(GetClient(), deviceId,
    225                                               mEncoder.get(), &desc);
    226 
    227  } else {
    228    id = ffi::wgpu_client_create_render_bundle_error(GetClient(), deviceId,
    229                                                     label.Get());
    230  }
    231 
    232  mValid = false;
    233  mEncoder.release();
    234  mUsedBindGroups.Clear();
    235  mUsedBuffers.Clear();
    236  mUsedPipelines.Clear();
    237 
    238  auto canvasContexts = mUsedCanvasContexts.Clone();
    239  RefPtr<RenderBundle> bundle =
    240      new RenderBundle(mParent, id, std::move(canvasContexts));
    241  return bundle.forget();
    242 }
    243 
    244 }  // namespace mozilla::webgpu