# Changelog * #4708 Fix max_vertex_buffers validation By nical in https://github.com/gfx-rs/wgpu/pull/4708 * #4729 Remove expected failure on AMD/DX12 from msaa example By teoxoy in https://github.com/gfx-rs/wgpu/pull/4729 * #4711 [naga] Add `Literal::I64`, for signed 64-bit integer literals. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4711 * #4736 Bump serde from 1.0.192 to 1.0.193 By dependabot[bot] in https://github.com/gfx-rs/wgpu/pull/4736 * #4735 [naga]: Let `TypeInner::Matrix` hold a `Scalar`, not just a width. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4735 * #4741 [naga] Fix type error in test. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4741 * #4742 [naga]: Make snapshot tests include paths in errors. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4742 * #4723 Test And Normalize Vertex Behavior on All Backends By cwfitzgerald in https://github.com/gfx-rs/wgpu/pull/4723 * #4746 Skip Flaky Test By cwfitzgerald in https://github.com/gfx-rs/wgpu/pull/4746 * #4744 Ensure DeviceLostClosureC callbacks have null-terminated message strings By bradwerth in https://github.com/gfx-rs/wgpu/pull/4744 * #4745 [naga wgsl-in] Test hex float suffix handling corner case. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4745 * #4737 Make the command_encoder_clear_buffer's size an Option<BufferAddress> By nical in https://github.com/gfx-rs/wgpu/pull/4737 * #4701 [naga msl-out] Emit and init `struct` member padding always By ErichDonGubler in https://github.com/gfx-rs/wgpu/pull/4701 * #4701 [naga msl-out] Emit and init `struct` member padding always By ErichDonGubler in https://github.com/gfx-rs/wgpu/pull/4701 * #4701 [naga msl-out] Emit and init `struct` member padding always By ErichDonGubler in https://github.com/gfx-rs/wgpu/pull/4701 * #4701 [naga msl-out] Emit and init `struct` member padding always By ErichDonGubler in https://github.com/gfx-rs/wgpu/pull/4701 * #4733 [naga wgsl-in] Preserve type names in `alias` declarations. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4733 * #4734 [naga] Make compaction preserve named types, even if unused. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4734 * #4752 Logging cleanups in device/global.rs By nical in https://github.com/gfx-rs/wgpu/pull/4752 * #4753 Fix Mac Event Loop By cwfitzgerald in https://github.com/gfx-rs/wgpu/pull/4753 * #4754 wgpu-hal(vk): Add WGPU_ALLOW_NONCOMPLIANT_ADAPTER By i509VCB in https://github.com/gfx-rs/wgpu/pull/4754 * #4748 Allow Tests to Expect Certain Panic or Validation Messages By cwfitzgerald in https://github.com/gfx-rs/wgpu/pull/4748 * #4756 Move to A Single Example Executable By cwfitzgerald in https://github.com/gfx-rs/wgpu/pull/4756 * #4747 [naga wgsl-in] Experimental 64-bit floating-point literals. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4747 * #4747 [naga wgsl-in] Experimental 64-bit floating-point literals. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4747 * #4761 [naga] Make the `example_wgsl` test build without `wgsl-in` feature. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4761 * #4769 Conditionally lift API logging from trace to info level By nical in https://github.com/gfx-rs/wgpu/pull/4769 * #4771 Downgrade some of wgpu_core's logging level from info to trace and debug By nical in https://github.com/gfx-rs/wgpu/pull/4771 * #4760 Rename `ALLOW_NONCOMPLIANT_ADAPTER` to `ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER` By teoxoy in https://github.com/gfx-rs/wgpu/pull/4760 * #4772 Downgrade resource lifetime management log level to trace. By nical in https://github.com/gfx-rs/wgpu/pull/4772 * #4765 Revamp Examples to Match Website By cwfitzgerald in https://github.com/gfx-rs/wgpu/pull/4765 * #4774 Update examples readme files By roffs in https://github.com/gfx-rs/wgpu/pull/4774 * #4781 remove_abandoned fix By gents83 in https://github.com/gfx-rs/wgpu/pull/4781 * #4777 Bump web-sys to 0.3.65 By torokati44 in https://github.com/gfx-rs/wgpu/pull/4777 * #4780 Fixes for Skybox and All Examples By cwfitzgerald in https://github.com/gfx-rs/wgpu/pull/4780 * #4782 Remove resources ONLY when needed inside wgpu and not in user land By gents83 in https://github.com/gfx-rs/wgpu/pull/4782 * #4786 Don't keep a strong ref in storage for destroyed resources By gents83 in https://github.com/gfx-rs/wgpu/pull/4786 * #4795 Fix Arcanization changelog By a1phyr in https://github.com/gfx-rs/wgpu/pull/4795 * #4794 Delete/rename now-unused gpu.rs By exrook in https://github.com/gfx-rs/wgpu/pull/4794 * #4794 Delete/rename now-unused gpu.rs By exrook in https://github.com/gfx-rs/wgpu/pull/4794 * #4573 Support nv12 texture format By xiaopengli89 in https://github.com/gfx-rs/wgpu/pull/4573 * #4789 Bump js-sys from 0.3.65 to 0.3.66 By dependabot[bot] in https://github.com/gfx-rs/wgpu/pull/4789 * #4784 Bump winit from 0.29.3 to 0.29.4 By dependabot[bot] in https://github.com/gfx-rs/wgpu/pull/4784 * #4798 Bump JamesIves/github-pages-deploy-action from 4.4.3 to 4.5.0 By dependabot[bot] in https://github.com/gfx-rs/wgpu/pull/4798 * #4800 Bump web-sys from 0.3.65 to 0.3.66 By dependabot[bot] in https://github.com/gfx-rs/wgpu/pull/4800 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4799 Bump wasm-bindgen-futures from 0.4.38 to 0.4.39 By dependabot[bot] in https://github.com/gfx-rs/wgpu/pull/4799 * #4796 Remove surface extent validation (and thus fix the annoying `Requested size ... is outside of the supported range` warning) By Wumpf in https://github.com/gfx-rs/wgpu/pull/4796 * #4804 Add space to a comment inside make_spirv_raw By ComfyFluffy in https://github.com/gfx-rs/wgpu/pull/4804 * #4803 `features`/`limits` refactors By teoxoy in https://github.com/gfx-rs/wgpu/pull/4803 * #4803 `features`/`limits` refactors By teoxoy in https://github.com/gfx-rs/wgpu/pull/4803 * #4803 `features`/`limits` refactors By teoxoy in https://github.com/gfx-rs/wgpu/pull/4803 * #4803 `features`/`limits` refactors By teoxoy in https://github.com/gfx-rs/wgpu/pull/4803 * #4803 `features`/`limits` refactors By teoxoy in https://github.com/gfx-rs/wgpu/pull/4803 * #4805 [naga] Improve ConstantEvaluatorError::InvalidCastArg message. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4805 * #4801 update deno By crowlKats in https://github.com/gfx-rs/wgpu/pull/4801 * #4806 Fixes and changes to the documentation for increasing clarity By Blatko1 in https://github.com/gfx-rs/wgpu/pull/4806 * #4809 [naga wgsl-in] Use a better span for errors in constructors. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4809 * #4808 [naga wgsl-in] Drop spanless labels from front-end error messages. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4808 * #4822 Fix expected error message By teoxoy in https://github.com/gfx-rs/wgpu/pull/4822 * #4759 Add feature float32-filterable By almarklein in https://github.com/gfx-rs/wgpu/pull/4759 * #4813 Bump core-graphics-types from 0.1.2 to 0.1.3 By dependabot[bot] in https://github.com/gfx-rs/wgpu/pull/4813 Differential Revision: https://phabricator.services.mozilla.com/D195438
507 lines
18 KiB
C++
507 lines
18 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "mozilla/dom/BindingDeclarations.h"
|
|
#include "mozilla/dom/WebGPUBinding.h"
|
|
#include "Adapter.h"
|
|
|
|
#include <algorithm>
|
|
#include "Device.h"
|
|
#include "Instance.h"
|
|
#include "SupportedFeatures.h"
|
|
#include "SupportedLimits.h"
|
|
#include "ipc/WebGPUChild.h"
|
|
#include "mozilla/dom/Promise.h"
|
|
#include "mozilla/webgpu/ffi/wgpu.h"
|
|
|
|
namespace mozilla::webgpu {
|
|
|
|
bool AdapterInfo::WrapObject(JSContext* const cx,
|
|
JS::Handle<JSObject*> givenProto,
|
|
JS::MutableHandle<JSObject*> reflector) {
|
|
return dom::GPUAdapterInfo_Binding::Wrap(cx, this, givenProto, reflector);
|
|
}
|
|
|
|
void AdapterInfo::GetWgpuName(nsString& s) const {
|
|
s = mAboutSupportInfo->name;
|
|
}
|
|
|
|
uint32_t AdapterInfo::WgpuVendor() const { return mAboutSupportInfo->vendor; }
|
|
|
|
uint32_t AdapterInfo::WgpuDevice() const { return mAboutSupportInfo->device; }
|
|
|
|
void AdapterInfo::GetWgpuDeviceType(nsString& s) const {
|
|
switch (mAboutSupportInfo->device_type) {
|
|
case ffi::WGPUDeviceType_Cpu:
|
|
s.AssignLiteral("Cpu");
|
|
return;
|
|
case ffi::WGPUDeviceType_DiscreteGpu:
|
|
s.AssignLiteral("DiscreteGpu");
|
|
return;
|
|
case ffi::WGPUDeviceType_IntegratedGpu:
|
|
s.AssignLiteral("IntegratedGpu");
|
|
return;
|
|
case ffi::WGPUDeviceType_VirtualGpu:
|
|
s.AssignLiteral("VirtualGpu");
|
|
return;
|
|
case ffi::WGPUDeviceType_Other:
|
|
s.AssignLiteral("Other");
|
|
return;
|
|
case ffi::WGPUDeviceType_Sentinel:
|
|
break;
|
|
}
|
|
MOZ_CRASH("Bad `ffi::WGPUDeviceType`");
|
|
}
|
|
|
|
void AdapterInfo::GetWgpuDriver(nsString& s) const {
|
|
s = mAboutSupportInfo->driver;
|
|
}
|
|
|
|
void AdapterInfo::GetWgpuDriverInfo(nsString& s) const {
|
|
s = mAboutSupportInfo->driver_info;
|
|
}
|
|
|
|
void AdapterInfo::GetWgpuBackend(nsString& s) const {
|
|
switch (mAboutSupportInfo->backend) {
|
|
case ffi::WGPUBackend_Empty:
|
|
s.AssignLiteral("Empty");
|
|
return;
|
|
case ffi::WGPUBackend_Vulkan:
|
|
s.AssignLiteral("Vulkan");
|
|
return;
|
|
case ffi::WGPUBackend_Metal:
|
|
s.AssignLiteral("Metal");
|
|
return;
|
|
case ffi::WGPUBackend_Dx12:
|
|
s.AssignLiteral("Dx12");
|
|
return;
|
|
case ffi::WGPUBackend_Dx11:
|
|
s.AssignLiteral("Dx11");
|
|
return;
|
|
case ffi::WGPUBackend_Gl:
|
|
s.AssignLiteral("Gl");
|
|
return;
|
|
case ffi::WGPUBackend_BrowserWebGpu: // This should never happen, because
|
|
// we _are_ the browser.
|
|
case ffi::WGPUBackend_Sentinel:
|
|
break;
|
|
}
|
|
MOZ_CRASH("Bad `ffi::WGPUBackend`");
|
|
}
|
|
|
|
// -
|
|
|
|
GPU_IMPL_CYCLE_COLLECTION(Adapter, mParent, mBridge, mFeatures, mLimits)
|
|
GPU_IMPL_JS_WRAP(Adapter)
|
|
|
|
static Maybe<ffi::WGPUFeatures> ToWGPUFeatures(
|
|
const dom::GPUFeatureName aFeature) {
|
|
switch (aFeature) {
|
|
case dom::GPUFeatureName::Depth_clip_control:
|
|
return Some(WGPUFeatures_DEPTH_CLIP_CONTROL);
|
|
|
|
case dom::GPUFeatureName::Depth32float_stencil8:
|
|
return Some(WGPUFeatures_DEPTH32FLOAT_STENCIL8);
|
|
|
|
case dom::GPUFeatureName::Texture_compression_bc:
|
|
return Some(WGPUFeatures_TEXTURE_COMPRESSION_BC);
|
|
|
|
case dom::GPUFeatureName::Texture_compression_etc2:
|
|
return Some(WGPUFeatures_TEXTURE_COMPRESSION_ETC2);
|
|
|
|
case dom::GPUFeatureName::Texture_compression_astc:
|
|
return Some(WGPUFeatures_TEXTURE_COMPRESSION_ASTC);
|
|
|
|
case dom::GPUFeatureName::Timestamp_query:
|
|
return Some(WGPUFeatures_TIMESTAMP_QUERY);
|
|
|
|
case dom::GPUFeatureName::Indirect_first_instance:
|
|
return Some(WGPUFeatures_INDIRECT_FIRST_INSTANCE);
|
|
|
|
case dom::GPUFeatureName::Shader_f16:
|
|
return Some(WGPUFeatures_SHADER_F16);
|
|
|
|
case dom::GPUFeatureName::Rg11b10ufloat_renderable:
|
|
return Some(WGPUFeatures_RG11B10UFLOAT_RENDERABLE);
|
|
|
|
case dom::GPUFeatureName::Bgra8unorm_storage:
|
|
return Some(WGPUFeatures_BGRA8UNORM_STORAGE);
|
|
|
|
case dom::GPUFeatureName::Float32_filterable:
|
|
return Some(WGPUFeatures_FLOAT32_FILTERABLE);
|
|
|
|
case dom::GPUFeatureName::EndGuard_:
|
|
break;
|
|
}
|
|
MOZ_CRASH("Bad GPUFeatureName.");
|
|
}
|
|
|
|
static Maybe<ffi::WGPUFeatures> MakeFeatureBits(
|
|
const dom::Sequence<dom::GPUFeatureName>& aFeatures) {
|
|
ffi::WGPUFeatures bits = 0;
|
|
for (const auto& feature : aFeatures) {
|
|
const auto bit = ToWGPUFeatures(feature);
|
|
if (!bit) {
|
|
const auto featureStr = dom::GPUFeatureNameValues::GetString(feature);
|
|
(void)featureStr;
|
|
NS_WARNING(
|
|
nsPrintfCString("Requested feature bit for '%s' is not implemented.",
|
|
featureStr.data())
|
|
.get());
|
|
return Nothing();
|
|
}
|
|
bits |= *bit;
|
|
}
|
|
return Some(bits);
|
|
}
|
|
|
|
Adapter::Adapter(Instance* const aParent, WebGPUChild* const aBridge,
|
|
const std::shared_ptr<ffi::WGPUAdapterInformation>& aInfo)
|
|
: ChildOf(aParent),
|
|
mBridge(aBridge),
|
|
mId(aInfo->id),
|
|
mFeatures(new SupportedFeatures(this)),
|
|
mLimits(new SupportedLimits(this, aInfo->limits)),
|
|
mInfo(aInfo) {
|
|
ErrorResult ignoredRv; // It's onerous to plumb this in from outside in this
|
|
// case, and we don't really need to.
|
|
|
|
static const auto FEATURE_BY_BIT = []() {
|
|
auto ret = std::unordered_map<ffi::WGPUFeatures, dom::GPUFeatureName>{};
|
|
|
|
for (const auto feature :
|
|
MakeEnumeratedRange(dom::GPUFeatureName::EndGuard_)) {
|
|
const auto bitForFeature = ToWGPUFeatures(feature);
|
|
if (!bitForFeature) {
|
|
// There are some features that don't have bits.
|
|
continue;
|
|
}
|
|
ret[*bitForFeature] = feature;
|
|
}
|
|
|
|
return ret;
|
|
}();
|
|
|
|
auto remainingFeatureBits = aInfo->features;
|
|
auto bitMask = decltype(remainingFeatureBits){0};
|
|
while (remainingFeatureBits) {
|
|
if (bitMask) {
|
|
bitMask <<= 1;
|
|
} else {
|
|
bitMask = 1;
|
|
}
|
|
const auto bit = remainingFeatureBits & bitMask;
|
|
remainingFeatureBits &= ~bitMask; // Clear bit.
|
|
if (!bit) {
|
|
continue;
|
|
}
|
|
|
|
const auto featureForBit = FEATURE_BY_BIT.find(bit);
|
|
if (featureForBit != FEATURE_BY_BIT.end()) {
|
|
mFeatures->Add(featureForBit->second, ignoredRv);
|
|
} else {
|
|
// We don't recognize that bit, but maybe it's a wpgu-native-only feature.
|
|
}
|
|
}
|
|
}
|
|
|
|
Adapter::~Adapter() { Cleanup(); }
|
|
|
|
void Adapter::Cleanup() {
|
|
if (mValid && mBridge && mBridge->CanSend()) {
|
|
mValid = false;
|
|
mBridge->SendAdapterDrop(mId);
|
|
}
|
|
}
|
|
|
|
const RefPtr<SupportedFeatures>& Adapter::Features() const { return mFeatures; }
|
|
const RefPtr<SupportedLimits>& Adapter::Limits() const { return mLimits; }
|
|
bool Adapter::IsFallbackAdapter() const {
|
|
return mInfo->device_type == ffi::WGPUDeviceType::WGPUDeviceType_Cpu;
|
|
}
|
|
|
|
static std::string_view ToJsKey(const Limit limit) {
|
|
switch (limit) {
|
|
case Limit::MaxTextureDimension1D:
|
|
return "maxTextureDimension1D";
|
|
case Limit::MaxTextureDimension2D:
|
|
return "maxTextureDimension2D";
|
|
case Limit::MaxTextureDimension3D:
|
|
return "maxTextureDimension3D";
|
|
case Limit::MaxTextureArrayLayers:
|
|
return "maxTextureArrayLayers";
|
|
case Limit::MaxBindGroups:
|
|
return "maxBindGroups";
|
|
case Limit::MaxBindGroupsPlusVertexBuffers:
|
|
return "maxBindGroupsPlusVertexBuffers";
|
|
case Limit::MaxBindingsPerBindGroup:
|
|
return "maxBindingsPerBindGroup";
|
|
case Limit::MaxDynamicUniformBuffersPerPipelineLayout:
|
|
return "maxDynamicUniformBuffersPerPipelineLayout";
|
|
case Limit::MaxDynamicStorageBuffersPerPipelineLayout:
|
|
return "maxDynamicStorageBuffersPerPipelineLayout";
|
|
case Limit::MaxSampledTexturesPerShaderStage:
|
|
return "maxSampledTexturesPerShaderStage";
|
|
case Limit::MaxSamplersPerShaderStage:
|
|
return "maxSamplersPerShaderStage";
|
|
case Limit::MaxStorageBuffersPerShaderStage:
|
|
return "maxStorageBuffersPerShaderStage";
|
|
case Limit::MaxStorageTexturesPerShaderStage:
|
|
return "maxStorageTexturesPerShaderStage";
|
|
case Limit::MaxUniformBuffersPerShaderStage:
|
|
return "maxUniformBuffersPerShaderStage";
|
|
case Limit::MaxUniformBufferBindingSize:
|
|
return "maxUniformBufferBindingSize";
|
|
case Limit::MaxStorageBufferBindingSize:
|
|
return "maxStorageBufferBindingSize";
|
|
case Limit::MinUniformBufferOffsetAlignment:
|
|
return "minUniformBufferOffsetAlignment";
|
|
case Limit::MinStorageBufferOffsetAlignment:
|
|
return "minStorageBufferOffsetAlignment";
|
|
case Limit::MaxVertexBuffers:
|
|
return "maxVertexBuffers";
|
|
case Limit::MaxBufferSize:
|
|
return "maxBufferSize";
|
|
case Limit::MaxVertexAttributes:
|
|
return "maxVertexAttributes";
|
|
case Limit::MaxVertexBufferArrayStride:
|
|
return "maxVertexBufferArrayStride";
|
|
case Limit::MaxInterStageShaderComponents:
|
|
return "maxInterStageShaderComponents";
|
|
case Limit::MaxInterStageShaderVariables:
|
|
return "maxInterStageShaderVariables";
|
|
case Limit::MaxColorAttachments:
|
|
return "maxColorAttachments";
|
|
case Limit::MaxColorAttachmentBytesPerSample:
|
|
return "maxColorAttachmentBytesPerSample";
|
|
case Limit::MaxComputeWorkgroupStorageSize:
|
|
return "maxComputeWorkgroupStorageSize";
|
|
case Limit::MaxComputeInvocationsPerWorkgroup:
|
|
return "maxComputeInvocationsPerWorkgroup";
|
|
case Limit::MaxComputeWorkgroupSizeX:
|
|
return "maxComputeWorkgroupSizeX";
|
|
case Limit::MaxComputeWorkgroupSizeY:
|
|
return "maxComputeWorkgroupSizeY";
|
|
case Limit::MaxComputeWorkgroupSizeZ:
|
|
return "maxComputeWorkgroupSizeZ";
|
|
case Limit::MaxComputeWorkgroupsPerDimension:
|
|
return "maxComputeWorkgroupsPerDimension";
|
|
}
|
|
MOZ_CRASH("Bad Limit");
|
|
}
|
|
|
|
// -
|
|
// String helpers
|
|
|
|
static auto ToACString(const nsAString& s) { return NS_ConvertUTF16toUTF8(s); }
|
|
|
|
// -
|
|
// Adapter::RequestDevice
|
|
|
|
already_AddRefed<dom::Promise> Adapter::RequestDevice(
|
|
const dom::GPUDeviceDescriptor& aDesc, ErrorResult& aRv) {
|
|
RefPtr<dom::Promise> promise = dom::Promise::Create(GetParentObject(), aRv);
|
|
if (NS_WARN_IF(aRv.Failed())) {
|
|
return nullptr;
|
|
}
|
|
|
|
ffi::WGPULimits deviceLimits = *mLimits->mFfi;
|
|
for (const auto limit : MakeInclusiveEnumeratedRange(Limit::_LAST)) {
|
|
const auto defaultValue = [&]() -> double {
|
|
switch (limit) {
|
|
// clang-format off
|
|
case Limit::MaxTextureDimension1D: return 8192;
|
|
case Limit::MaxTextureDimension2D: return 8192;
|
|
case Limit::MaxTextureDimension3D: return 2048;
|
|
case Limit::MaxTextureArrayLayers: return 256;
|
|
case Limit::MaxBindGroups: return 4;
|
|
case Limit::MaxBindGroupsPlusVertexBuffers: return 24;
|
|
case Limit::MaxBindingsPerBindGroup: return 1000;
|
|
case Limit::MaxDynamicUniformBuffersPerPipelineLayout: return 8;
|
|
case Limit::MaxDynamicStorageBuffersPerPipelineLayout: return 4;
|
|
case Limit::MaxSampledTexturesPerShaderStage: return 16;
|
|
case Limit::MaxSamplersPerShaderStage: return 16;
|
|
case Limit::MaxStorageBuffersPerShaderStage: return 8;
|
|
case Limit::MaxStorageTexturesPerShaderStage: return 4;
|
|
case Limit::MaxUniformBuffersPerShaderStage: return 12;
|
|
case Limit::MaxUniformBufferBindingSize: return 65536;
|
|
case Limit::MaxStorageBufferBindingSize: return 134217728;
|
|
case Limit::MinUniformBufferOffsetAlignment: return 256;
|
|
case Limit::MinStorageBufferOffsetAlignment: return 256;
|
|
case Limit::MaxVertexBuffers: return 8;
|
|
case Limit::MaxBufferSize: return 268435456;
|
|
case Limit::MaxVertexAttributes: return 16;
|
|
case Limit::MaxVertexBufferArrayStride: return 2048;
|
|
case Limit::MaxInterStageShaderComponents: return 60;
|
|
case Limit::MaxInterStageShaderVariables: return 16;
|
|
case Limit::MaxColorAttachments: return 8;
|
|
case Limit::MaxColorAttachmentBytesPerSample: return 32;
|
|
case Limit::MaxComputeWorkgroupStorageSize: return 16384;
|
|
case Limit::MaxComputeInvocationsPerWorkgroup: return 256;
|
|
case Limit::MaxComputeWorkgroupSizeX: return 256;
|
|
case Limit::MaxComputeWorkgroupSizeY: return 256;
|
|
case Limit::MaxComputeWorkgroupSizeZ: return 64;
|
|
case Limit::MaxComputeWorkgroupsPerDimension: return 65535;
|
|
// clang-format on
|
|
}
|
|
MOZ_CRASH("Bad Limit");
|
|
}();
|
|
SetLimit(&deviceLimits, limit, defaultValue);
|
|
}
|
|
|
|
// -
|
|
|
|
[&]() { // So that we can `return;` instead of `return promise.forget();`.
|
|
if (!mBridge->CanSend()) {
|
|
promise->MaybeRejectWithInvalidStateError(
|
|
"WebGPUChild cannot send, must recreate Adapter");
|
|
return;
|
|
}
|
|
|
|
// -
|
|
// Validate Features
|
|
|
|
for (const auto requested : aDesc.mRequiredFeatures) {
|
|
const bool supported = mFeatures->Features().count(requested);
|
|
if (!supported) {
|
|
const auto fstr = dom::GPUFeatureNameValues::GetString(requested);
|
|
const auto astr = this->LabelOrId();
|
|
nsPrintfCString msg(
|
|
"requestDevice: Feature '%s' requested must be supported by "
|
|
"adapter %s",
|
|
fstr.data(), astr.get());
|
|
promise->MaybeRejectWithTypeError(msg);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// -
|
|
// Validate Limits
|
|
|
|
if (aDesc.mRequiredLimits.WasPassed()) {
|
|
static const auto LIMIT_BY_JS_KEY = []() {
|
|
std::unordered_map<std::string_view, Limit> ret;
|
|
for (const auto limit : MakeInclusiveEnumeratedRange(Limit::_LAST)) {
|
|
const auto jsKeyU8 = ToJsKey(limit);
|
|
ret[jsKeyU8] = limit;
|
|
}
|
|
return ret;
|
|
}();
|
|
|
|
for (const auto& entry : aDesc.mRequiredLimits.Value().Entries()) {
|
|
const auto& keyU16 = entry.mKey;
|
|
const nsCString keyU8 = ToACString(keyU16);
|
|
const auto itr = LIMIT_BY_JS_KEY.find(keyU8.get());
|
|
if (itr == LIMIT_BY_JS_KEY.end()) {
|
|
nsPrintfCString msg("requestDevice: Limit '%s' not recognized.",
|
|
keyU8.get());
|
|
promise->MaybeRejectWithOperationError(msg);
|
|
return;
|
|
}
|
|
|
|
const auto& limit = itr->second;
|
|
uint64_t requestedValue = entry.mValue;
|
|
const auto supportedValue = GetLimit(*mLimits->mFfi, limit);
|
|
if (StringBeginsWith(keyU8, "max"_ns)) {
|
|
if (requestedValue > supportedValue) {
|
|
nsPrintfCString msg(
|
|
"requestDevice: Request for limit '%s' must be <= supported "
|
|
"%s, was %s.",
|
|
keyU8.get(), std::to_string(supportedValue).c_str(),
|
|
std::to_string(requestedValue).c_str());
|
|
promise->MaybeRejectWithOperationError(msg);
|
|
return;
|
|
}
|
|
// Clamp to default if lower than default
|
|
requestedValue =
|
|
std::max(requestedValue, GetLimit(deviceLimits, limit));
|
|
} else {
|
|
MOZ_ASSERT(StringBeginsWith(keyU8, "min"_ns));
|
|
if (requestedValue < supportedValue) {
|
|
nsPrintfCString msg(
|
|
"requestDevice: Request for limit '%s' must be >= supported "
|
|
"%s, was %s.",
|
|
keyU8.get(), std::to_string(supportedValue).c_str(),
|
|
std::to_string(requestedValue).c_str());
|
|
promise->MaybeRejectWithOperationError(msg);
|
|
return;
|
|
}
|
|
if (StringEndsWith(keyU8, "Alignment"_ns)) {
|
|
if (!IsPowerOfTwo(requestedValue)) {
|
|
nsPrintfCString msg(
|
|
"requestDevice: Request for limit '%s' must be a power of "
|
|
"two, "
|
|
"was %s.",
|
|
keyU8.get(), std::to_string(requestedValue).c_str());
|
|
promise->MaybeRejectWithOperationError(msg);
|
|
return;
|
|
}
|
|
}
|
|
/// Clamp to default if higher than default
|
|
requestedValue =
|
|
std::min(requestedValue, GetLimit(deviceLimits, limit));
|
|
}
|
|
|
|
SetLimit(&deviceLimits, limit, requestedValue);
|
|
}
|
|
}
|
|
|
|
// -
|
|
|
|
ffi::WGPUDeviceDescriptor ffiDesc = {};
|
|
ffiDesc.required_features = *MakeFeatureBits(aDesc.mRequiredFeatures);
|
|
ffiDesc.required_limits = deviceLimits;
|
|
auto request = mBridge->AdapterRequestDevice(mId, ffiDesc);
|
|
if (!request) {
|
|
promise->MaybeRejectWithNotSupportedError(
|
|
"Unable to instantiate a Device");
|
|
return;
|
|
}
|
|
RefPtr<Device> device =
|
|
new Device(this, request->mId, ffiDesc.required_limits);
|
|
for (const auto& feature : aDesc.mRequiredFeatures) {
|
|
device->mFeatures->Add(feature, aRv);
|
|
}
|
|
|
|
request->mPromise->Then(
|
|
GetCurrentSerialEventTarget(), __func__,
|
|
[promise, device](bool aSuccess) {
|
|
if (aSuccess) {
|
|
promise->MaybeResolve(device);
|
|
} else {
|
|
// In this path, request->mId has an error entry in the wgpu
|
|
// registry, so let Device::~Device clean things up on both the
|
|
// child and parent side.
|
|
promise->MaybeRejectWithInvalidStateError(
|
|
"Unable to fulfill requested features and limits");
|
|
}
|
|
},
|
|
[promise, device](const ipc::ResponseRejectReason& aReason) {
|
|
// We can't be sure how far along the WebGPUParent got in handling
|
|
// our AdapterRequestDevice message, but we can't communicate with it,
|
|
// so clear up our client state for this Device without trying to
|
|
// communicate with the parent about it.
|
|
device->CleanupUnregisteredInParent();
|
|
promise->MaybeRejectWithNotSupportedError("IPC error");
|
|
});
|
|
}();
|
|
|
|
return promise.forget();
|
|
}
|
|
|
|
// -
|
|
|
|
already_AddRefed<dom::Promise> Adapter::RequestAdapterInfo(
|
|
const dom::Sequence<nsString>& /*aUnmaskHints*/, ErrorResult& aRv) const {
|
|
RefPtr<dom::Promise> promise = dom::Promise::Create(GetParentObject(), aRv);
|
|
if (!promise) return nullptr;
|
|
|
|
auto rai = UniquePtr<AdapterInfo>{new AdapterInfo(mInfo)};
|
|
promise->MaybeResolve(std::move(rai));
|
|
return promise.forget();
|
|
}
|
|
|
|
} // namespace mozilla::webgpu
|