summaryrefslogtreecommitdiffstats
path: root/dom/webgpu
diff options
context:
space:
mode:
Diffstat (limited to 'dom/webgpu')
-rw-r--r--dom/webgpu/BindGroup.cpp20
-rw-r--r--dom/webgpu/BindGroupLayout.cpp18
-rw-r--r--dom/webgpu/Buffer.cpp18
-rw-r--r--dom/webgpu/Buffer.h2
-rw-r--r--dom/webgpu/CanvasContext.cpp18
-rw-r--r--dom/webgpu/CommandEncoder.cpp27
-rw-r--r--dom/webgpu/CompilationInfo.cpp15
-rw-r--r--dom/webgpu/CompilationMessage.cpp8
-rw-r--r--dom/webgpu/CompilationMessage.h8
-rw-r--r--dom/webgpu/ComputePipeline.cpp29
-rw-r--r--dom/webgpu/Instance.cpp2
-rw-r--r--dom/webgpu/ObjectModel.h40
-rw-r--r--dom/webgpu/PipelineLayout.cpp20
-rw-r--r--dom/webgpu/RenderBundle.cpp19
-rw-r--r--dom/webgpu/RenderPipeline.cpp33
-rw-r--r--dom/webgpu/Sampler.cpp20
-rw-r--r--dom/webgpu/ShaderModule.cpp20
-rw-r--r--dom/webgpu/Texture.cpp18
-rw-r--r--dom/webgpu/Texture.h2
-rw-r--r--dom/webgpu/TextureView.cpp20
-rw-r--r--dom/webgpu/ipc/WebGPUChild.cpp2
-rw-r--r--dom/webgpu/ipc/WebGPUChild.h2
-rw-r--r--dom/webgpu/ipc/WebGPUParent.cpp1
-rw-r--r--dom/webgpu/ipc/WebGPUSerialize.h2
-rw-r--r--dom/webgpu/mochitest/mochitest-no-pref.toml1
-rw-r--r--dom/webgpu/mochitest/mochitest.toml63
-rw-r--r--dom/webgpu/mochitest/test_compilation_message_pos.html58
27 files changed, 311 insertions, 175 deletions
diff --git a/dom/webgpu/BindGroup.cpp b/dom/webgpu/BindGroup.cpp
index 7ae5b8c3bb..b3cd3d9d5e 100644
--- a/dom/webgpu/BindGroup.cpp
+++ b/dom/webgpu/BindGroup.cpp
@@ -22,13 +22,21 @@ BindGroup::BindGroup(Device* const aParent, RawId aId)
BindGroup::~BindGroup() { Cleanup(); }
void BindGroup::Cleanup() {
- if (mValid && mParent) {
- mValid = false;
- auto bridge = mParent->GetBridge();
- if (bridge && bridge->IsOpen()) {
- bridge->SendBindGroupDrop(mId);
- }
+ if (!mValid) {
+ return;
}
+ mValid = false;
+
+ auto bridge = mParent->GetBridge();
+ if (!bridge) {
+ return;
+ }
+
+ if (bridge->CanSend()) {
+ bridge->SendBindGroupDrop(mId);
+ }
+
+ wgpu_client_free_bind_group_id(bridge->GetClient(), mId);
}
} // namespace mozilla::webgpu
diff --git a/dom/webgpu/BindGroupLayout.cpp b/dom/webgpu/BindGroupLayout.cpp
index cb5035b308..b447b63496 100644
--- a/dom/webgpu/BindGroupLayout.cpp
+++ b/dom/webgpu/BindGroupLayout.cpp
@@ -22,12 +22,22 @@ BindGroupLayout::BindGroupLayout(Device* const aParent, RawId aId, bool aOwning)
BindGroupLayout::~BindGroupLayout() { Cleanup(); }
void BindGroupLayout::Cleanup() {
- if (mValid && mParent) {
- mValid = false;
- auto bridge = mParent->GetBridge();
- if (mOwning && bridge && bridge->IsOpen()) {
+ if (!mValid) {
+ return;
+ }
+ mValid = false;
+
+ auto bridge = mParent->GetBridge();
+ if (!bridge) {
+ return;
+ }
+
+ if (mOwning) {
+ if (bridge->CanSend()) {
bridge->SendBindGroupLayoutDrop(mId);
}
+
+ wgpu_client_free_bind_group_layout_id(bridge->GetClient(), mId);
}
}
diff --git a/dom/webgpu/Buffer.cpp b/dom/webgpu/Buffer.cpp
index b7b689a9a0..3bd1353e69 100644
--- a/dom/webgpu/Buffer.cpp
+++ b/dom/webgpu/Buffer.cpp
@@ -24,7 +24,7 @@ GPU_IMPL_JS_WRAP(Buffer)
NS_IMPL_CYCLE_COLLECTION_CLASS(Buffer)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Buffer)
- tmp->Drop();
+ tmp->Cleanup();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@@ -51,7 +51,7 @@ Buffer::Buffer(Device* const aParent, RawId aId, BufferAddress aSize,
}
Buffer::~Buffer() {
- Drop();
+ Cleanup();
mozilla::DropJSObjects(this);
}
@@ -136,11 +136,10 @@ already_AddRefed<Buffer> Buffer::Create(Device* aDevice, RawId aDeviceId,
return buffer.forget();
}
-void Buffer::Drop() {
+void Buffer::Cleanup() {
if (!mValid) {
return;
}
-
mValid = false;
AbortMapRequest();
@@ -158,9 +157,16 @@ void Buffer::Drop() {
GetDevice().UntrackBuffer(this);
- if (GetDevice().IsBridgeAlive()) {
- GetDevice().GetBridge()->SendBufferDrop(mId);
+ auto bridge = GetDevice().GetBridge();
+ if (!bridge) {
+ return;
}
+
+ if (bridge->CanSend()) {
+ bridge->SendBufferDrop(mId);
+ }
+
+ wgpu_client_free_buffer_id(bridge->GetClient(), mId);
}
void Buffer::SetMapped(BufferAddress aOffset, BufferAddress aSize,
diff --git a/dom/webgpu/Buffer.h b/dom/webgpu/Buffer.h
index 2f809a4768..fa3881f38a 100644
--- a/dom/webgpu/Buffer.h
+++ b/dom/webgpu/Buffer.h
@@ -69,7 +69,7 @@ class Buffer final : public ObjectBase, public ChildOf<Device> {
ipc::WritableSharedMemoryMapping&& aShmem);
virtual ~Buffer();
Device& GetDevice() { return *mParent; }
- void Drop();
+ void Cleanup();
void UnmapArrayBuffers(JSContext* aCx, ErrorResult& aRv);
void RejectMapRequest(dom::Promise* aPromise, nsACString& message);
void AbortMapRequest();
diff --git a/dom/webgpu/CanvasContext.cpp b/dom/webgpu/CanvasContext.cpp
index 49f34196c4..46633d9160 100644
--- a/dom/webgpu/CanvasContext.cpp
+++ b/dom/webgpu/CanvasContext.cpp
@@ -10,6 +10,7 @@
#include "nsDisplayList.h"
#include "mozilla/dom/HTMLCanvasElement.h"
#include "mozilla/gfx/CanvasManagerChild.h"
+#include "mozilla/gfx/gfxVars.h"
#include "mozilla/layers/CanvasRenderer.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/ImageDataSerializer.h"
@@ -125,6 +126,17 @@ void CanvasContext::Configure(const dom::GPUCanvasConfiguration& aConfig) {
mUseExternalTextureInSwapChain =
wgpu_client_use_external_texture_in_swapChain(
aConfig.mDevice->mId, ConvertTextureFormat(aConfig.mFormat));
+ if (!gfx::gfxVars::AllowWebGPUPresentWithoutReadback()) {
+ mUseExternalTextureInSwapChain = false;
+ }
+#ifdef XP_WIN
+ // When WebRender does not use hardware acceleration, disable external texture
+ // in swap chain. Since compositor device might not exist.
+ if (gfx::gfxVars::UseSoftwareWebRender() &&
+ !gfx::gfxVars::AllowSoftwareWebRenderD3D11()) {
+ mUseExternalTextureInSwapChain = false;
+ }
+#endif
mTexture = aConfig.mDevice->InitSwapChain(
mConfig.get(), mRemoteTextureOwnerId.ref(),
mUseExternalTextureInSwapChain, mGfxFormat, mCanvasSize);
@@ -143,7 +155,7 @@ void CanvasContext::Configure(const dom::GPUCanvasConfiguration& aConfig) {
}
void CanvasContext::Unconfigure() {
- if (mBridge && mBridge->IsOpen() && mRemoteTextureOwnerId) {
+ if (mBridge && mBridge->CanSend() && mRemoteTextureOwnerId) {
mBridge->SendSwapChainDrop(
*mRemoteTextureOwnerId,
layers::ToRemoteTextureTxnType(mFwdTransactionTracker),
@@ -213,7 +225,7 @@ void CanvasContext::MaybeQueueSwapChainPresent() {
Maybe<layers::SurfaceDescriptor> CanvasContext::SwapChainPresent() {
mPendingSwapChainPresent = false;
- if (!mBridge || !mBridge->IsOpen() || mRemoteTextureOwnerId.isNothing() ||
+ if (!mBridge || !mBridge->CanSend() || mRemoteTextureOwnerId.isNothing() ||
!mTexture) {
return Nothing();
}
@@ -325,7 +337,7 @@ already_AddRefed<mozilla::gfx::SourceSurface> CanvasContext::GetSurfaceSnapshot(
return nullptr;
}
- if (!mBridge || !mBridge->IsOpen() || mRemoteTextureOwnerId.isNothing()) {
+ if (!mBridge || !mBridge->CanSend() || mRemoteTextureOwnerId.isNothing()) {
return nullptr;
}
diff --git a/dom/webgpu/CommandEncoder.cpp b/dom/webgpu/CommandEncoder.cpp
index f254c9d8b9..3775f63555 100644
--- a/dom/webgpu/CommandEncoder.cpp
+++ b/dom/webgpu/CommandEncoder.cpp
@@ -85,9 +85,16 @@ void CommandEncoder::Cleanup() {
return;
}
mValid = false;
- if (mBridge->IsOpen()) {
+
+ if (!mBridge) {
+ return;
+ }
+
+ if (mBridge->CanSend()) {
mBridge->SendCommandEncoderDrop(mId);
}
+
+ wgpu_client_free_command_encoder_id(mBridge->GetClient(), mId);
}
void CommandEncoder::TrackPresentationContext(CanvasContext* aTargetContext) {
@@ -103,7 +110,7 @@ void CommandEncoder::CopyBufferToBuffer(const Buffer& aSource,
const Buffer& aDestination,
BufferAddress aDestinationOffset,
BufferAddress aSize) {
- if (!mBridge->IsOpen()) {
+ if (!mBridge->CanSend()) {
return;
}
@@ -118,7 +125,7 @@ void CommandEncoder::CopyBufferToTexture(
const dom::GPUImageCopyBuffer& aSource,
const dom::GPUImageCopyTexture& aDestination,
const dom::GPUExtent3D& aCopySize) {
- if (!mBridge->IsOpen()) {
+ if (!mBridge->CanSend()) {
return;
}
@@ -136,7 +143,7 @@ void CommandEncoder::CopyTextureToBuffer(
const dom::GPUImageCopyTexture& aSource,
const dom::GPUImageCopyBuffer& aDestination,
const dom::GPUExtent3D& aCopySize) {
- if (!mBridge->IsOpen()) {
+ if (!mBridge->CanSend()) {
return;
}
@@ -152,7 +159,7 @@ void CommandEncoder::CopyTextureToTexture(
const dom::GPUImageCopyTexture& aSource,
const dom::GPUImageCopyTexture& aDestination,
const dom::GPUExtent3D& aCopySize) {
- if (!mBridge->IsOpen()) {
+ if (!mBridge->CanSend()) {
return;
}
@@ -181,7 +188,7 @@ void CommandEncoder::ClearBuffer(const Buffer& aBuffer, const uint64_t aOffset,
}
void CommandEncoder::PushDebugGroup(const nsAString& aString) {
- if (!mBridge->IsOpen()) {
+ if (!mBridge->CanSend()) {
return;
}
@@ -191,7 +198,7 @@ void CommandEncoder::PushDebugGroup(const nsAString& aString) {
mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(bb));
}
void CommandEncoder::PopDebugGroup() {
- if (!mBridge->IsOpen()) {
+ if (!mBridge->CanSend()) {
return;
}
@@ -200,7 +207,7 @@ void CommandEncoder::PopDebugGroup() {
mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(bb));
}
void CommandEncoder::InsertDebugMarker(const nsAString& aString) {
- if (!mBridge->IsOpen()) {
+ if (!mBridge->CanSend()) {
return;
}
@@ -230,7 +237,7 @@ already_AddRefed<RenderPassEncoder> CommandEncoder::BeginRenderPass(
}
void CommandEncoder::EndComputePass(ffi::WGPURecordedComputePass& aPass) {
- if (!mBridge->IsOpen()) {
+ if (!mBridge->CanSend()) {
return;
}
@@ -240,7 +247,7 @@ void CommandEncoder::EndComputePass(ffi::WGPURecordedComputePass& aPass) {
}
void CommandEncoder::EndRenderPass(ffi::WGPURecordedRenderPass& aPass) {
- if (!mBridge->IsOpen()) {
+ if (!mBridge->CanSend()) {
return;
}
diff --git a/dom/webgpu/CompilationInfo.cpp b/dom/webgpu/CompilationInfo.cpp
index 0d46db2e59..995fb17c1a 100644
--- a/dom/webgpu/CompilationInfo.cpp
+++ b/dom/webgpu/CompilationInfo.cpp
@@ -18,8 +18,21 @@ CompilationInfo::CompilationInfo(Device* const aParent) : ChildOf(aParent) {}
void CompilationInfo::SetMessages(
nsTArray<mozilla::webgpu::WebGPUCompilationMessage>& aMessages) {
for (auto& msg : aMessages) {
+ auto messageType = dom::GPUCompilationMessageType::Error;
+ switch (msg.messageType) {
+ case WebGPUCompilationMessageType::Error:
+ messageType = dom::GPUCompilationMessageType::Error;
+ break;
+ case WebGPUCompilationMessageType::Warning:
+ messageType = dom::GPUCompilationMessageType::Warning;
+ break;
+ case WebGPUCompilationMessageType::Info:
+ messageType = dom::GPUCompilationMessageType::Info;
+ break;
+ }
mMessages.AppendElement(MakeAndAddRef<mozilla::webgpu::CompilationMessage>(
- mParent, msg.lineNum, msg.linePos, msg.offset, std::move(msg.message)));
+ mParent, messageType, msg.lineNum, msg.linePos, msg.offset, msg.length,
+ std::move(msg.message)));
}
}
diff --git a/dom/webgpu/CompilationMessage.cpp b/dom/webgpu/CompilationMessage.cpp
index 1463ec408e..7aa4d01622 100644
--- a/dom/webgpu/CompilationMessage.cpp
+++ b/dom/webgpu/CompilationMessage.cpp
@@ -12,13 +12,17 @@ namespace mozilla::webgpu {
GPU_IMPL_CYCLE_COLLECTION(CompilationMessage, mParent)
GPU_IMPL_JS_WRAP(CompilationMessage)
-CompilationMessage::CompilationMessage(Device* const aParent, uint64_t aLineNum,
- uint64_t aLinePos, uint64_t aOffset,
+CompilationMessage::CompilationMessage(Device* const aParent,
+ dom::GPUCompilationMessageType aType,
+ uint64_t aLineNum, uint64_t aLinePos,
+ uint64_t aOffset, uint64_t aLength,
nsString&& aMessage)
: ChildOf(aParent),
+ mType(aType),
mLineNum(aLineNum),
mLinePos(aLinePos),
mOffset(aOffset),
+ mLength(aLength),
mMessage(std::move(aMessage)) {}
} // namespace mozilla::webgpu
diff --git a/dom/webgpu/CompilationMessage.h b/dom/webgpu/CompilationMessage.h
index bac786dec6..d5f252f26a 100644
--- a/dom/webgpu/CompilationMessage.h
+++ b/dom/webgpu/CompilationMessage.h
@@ -18,7 +18,7 @@ namespace webgpu {
class CompilationInfo;
class CompilationMessage final : public nsWrapperCache, public ChildOf<Device> {
- dom::GPUCompilationMessageType mType = dom::GPUCompilationMessageType::Error;
+ dom::GPUCompilationMessageType mType;
uint64_t mLineNum = 0;
uint64_t mLinePos = 0;
uint64_t mOffset = 0;
@@ -29,8 +29,10 @@ class CompilationMessage final : public nsWrapperCache, public ChildOf<Device> {
GPU_DECL_CYCLE_COLLECTION(CompilationMessage)
GPU_DECL_JS_WRAP(CompilationMessage)
- explicit CompilationMessage(Device* const aParent, uint64_t aLineNum,
- uint64_t aLinePos, uint64_t aOffset,
+ explicit CompilationMessage(Device* const aParent,
+ dom::GPUCompilationMessageType aType,
+ uint64_t aLineNum, uint64_t aLinePos,
+ uint64_t aOffset, uint64_t aLength,
nsString&& aMessage);
void GetMessage(dom::DOMString& aMessage) {
diff --git a/dom/webgpu/ComputePipeline.cpp b/dom/webgpu/ComputePipeline.cpp
index ca50c5583a..ecd43289f3 100644
--- a/dom/webgpu/ComputePipeline.cpp
+++ b/dom/webgpu/ComputePipeline.cpp
@@ -27,17 +27,28 @@ ComputePipeline::ComputePipeline(Device* const aParent, RawId aId,
ComputePipeline::~ComputePipeline() { Cleanup(); }
void ComputePipeline::Cleanup() {
- if (mValid && mParent) {
- mValid = false;
- auto bridge = mParent->GetBridge();
- if (bridge && bridge->IsOpen()) {
- bridge->SendComputePipelineDrop(mId);
- if (mImplicitPipelineLayoutId) {
- bridge->SendImplicitLayoutDrop(mImplicitPipelineLayoutId,
- mImplicitBindGroupLayoutIds);
- }
+ if (mValid) {
+ return;
+ }
+ mValid = false;
+
+ auto bridge = mParent->GetBridge();
+ if (bridge->CanSend()) {
+ bridge->SendComputePipelineDrop(mId);
+ if (mImplicitPipelineLayoutId) {
+ bridge->SendImplicitLayoutDrop(mImplicitPipelineLayoutId,
+ mImplicitBindGroupLayoutIds);
}
}
+
+ if (mImplicitPipelineLayoutId) {
+ wgpu_client_free_pipeline_layout_id(bridge->GetClient(),
+ mImplicitPipelineLayoutId);
+ }
+
+ for (const auto& id : mImplicitBindGroupLayoutIds) {
+ wgpu_client_free_bind_group_layout_id(bridge->GetClient(), id);
+ }
}
already_AddRefed<BindGroupLayout> ComputePipeline::GetBindGroupLayout(
diff --git a/dom/webgpu/Instance.cpp b/dom/webgpu/Instance.cpp
index 4bf58b7fa8..30a82cbb26 100644
--- a/dom/webgpu/Instance.cpp
+++ b/dom/webgpu/Instance.cpp
@@ -90,7 +90,7 @@ already_AddRefed<dom::Promise> Instance::RequestAdapter(
auto* const canvasManager = gfx::CanvasManagerChild::Get();
if (!canvasManager) {
promise->MaybeRejectWithInvalidStateError(
- "Failed to create CanavasManagerChild");
+ "Failed to create CanvasManagerChild");
return promise.forget();
}
diff --git a/dom/webgpu/ObjectModel.h b/dom/webgpu/ObjectModel.h
index 59e154bd44..72a6d848d3 100644
--- a/dom/webgpu/ObjectModel.h
+++ b/dom/webgpu/ObjectModel.h
@@ -26,28 +26,38 @@ class ChildOf {
nsIGlobalObject* GetParentObject() const;
};
+/// Most WebGPU DOM objects inherit from this class.
+///
+/// mValid should only be used in the destruction steps in Cleanup() to check
+/// whether they have already run. This is because the destruction steps can be
+/// triggered by either the object's destructor or the cycle collector
+/// attempting to break a cycle. As a result, all methods accessible from JS can
+/// assume that mValid is true.
+///
+/// Similarly, pointers to the device and the IPDL actor (bridge) can be assumed
+/// to be non-null whenever the object is accessible from JS but not during
+/// cleanup as they might have been snatched by cycle collection.
+///
+/// The general pattern is that all objects should implement Cleanup more or
+/// less the same way. Cleanup should be the only function sending the
+/// corresponding Drop message and cleanup should *never* be called by anything
+/// other than the object destructor or the cycle collector.
+///
+/// These rules guarantee that:
+/// - The Drop message is called only once and that no other IPC message
+/// referring
+/// to the same object is send after Drop.
+/// - Any method outside of the destruction sequence can assume the pointers are
+/// non-null. They only have to check that the IPDL actor can send messages
+/// using `WebGPUChild::CanSend()`.
class ObjectBase : public nsWrapperCache {
protected:
virtual ~ObjectBase() = default;
- // False if this object is definitely invalid.
- //
- // See WebGPU ยง3.2, "Invalid Internal Objects & Contagious Invalidity".
- //
- // There could also be state in the GPU process indicating that our
- // counterpart object there is invalid; certain GPU process operations will
- // report an error back to use if we try to use it. But if it's useful to know
- // whether the object is "definitely invalid", this should suffice.
+ /// False during the destruction sequence of the object.
bool mValid = true;
public:
- // Return true if this WebGPU object may be valid.
- //
- // This is used by methods that want to know whether somebody other than
- // `this` is valid. Generally, WebGPU object methods check `this->mValid`
- // directly.
- bool IsValid() const { return mValid; }
-
void GetLabel(nsAString& aValue) const;
void SetLabel(const nsAString& aLabel);
diff --git a/dom/webgpu/PipelineLayout.cpp b/dom/webgpu/PipelineLayout.cpp
index 716be9c74a..5aa12dff21 100644
--- a/dom/webgpu/PipelineLayout.cpp
+++ b/dom/webgpu/PipelineLayout.cpp
@@ -22,13 +22,21 @@ PipelineLayout::PipelineLayout(Device* const aParent, RawId aId)
PipelineLayout::~PipelineLayout() { Cleanup(); }
void PipelineLayout::Cleanup() {
- if (mValid && mParent) {
- mValid = false;
- auto bridge = mParent->GetBridge();
- if (bridge && bridge->IsOpen()) {
- bridge->SendPipelineLayoutDrop(mId);
- }
+ if (!mValid) {
+ return;
}
+ mValid = false;
+
+ auto bridge = mParent->GetBridge();
+ if (!bridge) {
+ return;
+ }
+
+ if (bridge->CanSend()) {
+ bridge->SendPipelineLayoutDrop(mId);
+ }
+
+ wgpu_client_free_pipeline_layout_id(bridge->GetClient(), mId);
}
} // namespace mozilla::webgpu
diff --git a/dom/webgpu/RenderBundle.cpp b/dom/webgpu/RenderBundle.cpp
index a60d8d5f8e..dc3bd8cabb 100644
--- a/dom/webgpu/RenderBundle.cpp
+++ b/dom/webgpu/RenderBundle.cpp
@@ -23,13 +23,20 @@ RenderBundle::RenderBundle(Device* const aParent, RawId aId)
RenderBundle::~RenderBundle() { Cleanup(); }
void RenderBundle::Cleanup() {
- if (mValid && mParent) {
- mValid = false;
- auto bridge = mParent->GetBridge();
- if (bridge && bridge->IsOpen()) {
- bridge->SendRenderBundleDrop(mId);
- }
+ if (!mValid) {
+ return;
}
+ mValid = false;
+
+ auto bridge = mParent->GetBridge();
+ if (!bridge) {
+ return;
+ }
+
+ if (bridge->CanSend()) {
+ bridge->SendRenderBundleDrop(mId);
+ }
+ wgpu_client_free_render_bundle_id(bridge->GetClient(), mId);
}
} // namespace mozilla::webgpu
diff --git a/dom/webgpu/RenderPipeline.cpp b/dom/webgpu/RenderPipeline.cpp
index 78e13d31ef..aa9ffcdf9a 100644
--- a/dom/webgpu/RenderPipeline.cpp
+++ b/dom/webgpu/RenderPipeline.cpp
@@ -27,17 +27,32 @@ RenderPipeline::RenderPipeline(Device* const aParent, RawId aId,
RenderPipeline::~RenderPipeline() { Cleanup(); }
void RenderPipeline::Cleanup() {
- if (mValid && mParent) {
- mValid = false;
- auto bridge = mParent->GetBridge();
- if (bridge && bridge->IsOpen()) {
- bridge->SendRenderPipelineDrop(mId);
- if (mImplicitPipelineLayoutId) {
- bridge->SendImplicitLayoutDrop(mImplicitPipelineLayoutId,
- mImplicitBindGroupLayoutIds);
- }
+ if (!mValid) {
+ return;
+ }
+ mValid = false;
+
+ auto bridge = mParent->GetBridge();
+ if (!bridge) {
+ return;
+ }
+
+ if (bridge->CanSend()) {
+ bridge->SendRenderPipelineDrop(mId);
+ if (mImplicitPipelineLayoutId) {
+ bridge->SendImplicitLayoutDrop(mImplicitPipelineLayoutId,
+ mImplicitBindGroupLayoutIds);
}
}
+
+ if (mImplicitPipelineLayoutId) {
+ wgpu_client_free_pipeline_layout_id(bridge->GetClient(),
+ mImplicitPipelineLayoutId);
+ }
+
+ for (const auto& id : mImplicitBindGroupLayoutIds) {
+ wgpu_client_free_bind_group_layout_id(bridge->GetClient(), id);
+ }
}
already_AddRefed<BindGroupLayout> RenderPipeline::GetBindGroupLayout(
diff --git a/dom/webgpu/Sampler.cpp b/dom/webgpu/Sampler.cpp
index 6ee5f3c41f..6abd8ca357 100644
--- a/dom/webgpu/Sampler.cpp
+++ b/dom/webgpu/Sampler.cpp
@@ -22,13 +22,21 @@ Sampler::Sampler(Device* const aParent, RawId aId)
Sampler::~Sampler() { Cleanup(); }
void Sampler::Cleanup() {
- if (mValid && mParent) {
- mValid = false;
- auto bridge = mParent->GetBridge();
- if (bridge && bridge->IsOpen()) {
- bridge->SendSamplerDrop(mId);
- }
+ if (!mValid) {
+ return;
}
+
+ mValid = false;
+ auto bridge = mParent->GetBridge();
+ if (!bridge) {
+ return;
+ }
+
+ if (bridge->CanSend()) {
+ bridge->SendSamplerDrop(mId);
+ }
+
+ wgpu_client_free_sampler_id(bridge->GetClient(), mId);
}
} // namespace mozilla::webgpu
diff --git a/dom/webgpu/ShaderModule.cpp b/dom/webgpu/ShaderModule.cpp
index bd123c8423..fce469a174 100644
--- a/dom/webgpu/ShaderModule.cpp
+++ b/dom/webgpu/ShaderModule.cpp
@@ -25,13 +25,21 @@ ShaderModule::ShaderModule(Device* const aParent, RawId aId,
ShaderModule::~ShaderModule() { Cleanup(); }
void ShaderModule::Cleanup() {
- if (mValid && mParent) {
- mValid = false;
- auto bridge = mParent->GetBridge();
- if (bridge && bridge->IsOpen()) {
- bridge->SendShaderModuleDrop(mId);
- }
+ if (!mValid) {
+ return;
}
+ mValid = false;
+
+ auto bridge = mParent->GetBridge();
+ if (!bridge) {
+ return;
+ }
+
+ if (bridge->CanSend()) {
+ bridge->SendShaderModuleDrop(mId);
+ }
+
+ wgpu_client_free_shader_module_id(bridge->GetClient(), mId);
}
already_AddRefed<dom::Promise> ShaderModule::CompilationInfo(ErrorResult& aRv) {
diff --git a/dom/webgpu/Texture.cpp b/dom/webgpu/Texture.cpp
index c7bc406118..82e17c51c6 100644
--- a/dom/webgpu/Texture.cpp
+++ b/dom/webgpu/Texture.cpp
@@ -46,21 +46,21 @@ Texture::Texture(Device* const aParent, RawId aId,
}
void Texture::Cleanup() {
- if (!mParent) {
+ if (!mValid) {
return;
}
+ mValid = false;
auto bridge = mParent->GetBridge();
- if (bridge && bridge->IsOpen()) {
+ if (!bridge) {
+ return;
+ }
+
+ if (bridge->CanSend()) {
bridge->SendTextureDrop(mId);
}
- // After cleanup is called, no other method should ever be called on the
- // object so we don't have to null-check mParent in other places.
- // This serves the purpose of preventing SendTextureDrop from happening
- // twice. TODO: Does it matter for breaking cycles too? Cleanup is called
- // by the macros that deal with cycle colleciton.
- mParent = nullptr;
+ wgpu_client_free_texture_id(bridge->GetClient(), mId);
}
Texture::~Texture() { Cleanup(); }
@@ -113,7 +113,7 @@ already_AddRefed<TextureView> Texture::CreateView(
void Texture::Destroy() {
auto bridge = mParent->GetBridge();
- if (bridge && bridge->IsOpen()) {
+ if (bridge && bridge->CanSend()) {
bridge->SendTextureDestroy(mId, mParent->GetId());
}
}
diff --git a/dom/webgpu/Texture.h b/dom/webgpu/Texture.h
index e31878f825..12677abe80 100644
--- a/dom/webgpu/Texture.h
+++ b/dom/webgpu/Texture.h
@@ -35,7 +35,7 @@ class Texture final : public ObjectBase, public ChildOf<Device> {
Texture(Device* const aParent, RawId aId,
const dom::GPUTextureDescriptor& aDesc);
- Device* GetParentDevice() { return mParent; }
+ Device* GetDevice() { return mParent; }
const RawId mId;
const dom::GPUTextureFormat mFormat;
const Maybe<uint8_t> mBytesPerBlock;
diff --git a/dom/webgpu/TextureView.cpp b/dom/webgpu/TextureView.cpp
index c36818e9ea..4964de4b7f 100644
--- a/dom/webgpu/TextureView.cpp
+++ b/dom/webgpu/TextureView.cpp
@@ -27,13 +27,21 @@ CanvasContext* TextureView::GetTargetContext() const {
} // namespace webgpu
void TextureView::Cleanup() {
- if (mValid && mParent && mParent->GetParentDevice()) {
- mValid = false;
- auto bridge = mParent->GetParentDevice()->GetBridge();
- if (bridge && bridge->IsOpen()) {
- bridge->SendTextureViewDrop(mId);
- }
+ if (!mValid || !mParent || !mParent->GetDevice()) {
+ return;
}
+ mValid = false;
+
+ auto bridge = mParent->GetDevice()->GetBridge();
+ if (!bridge) {
+ return;
+ }
+
+ if (bridge->CanSend()) {
+ bridge->SendTextureViewDrop(mId);
+ }
+
+ wgpu_client_free_texture_view_id(bridge->GetClient(), mId);
}
} // namespace mozilla::webgpu
diff --git a/dom/webgpu/ipc/WebGPUChild.cpp b/dom/webgpu/ipc/WebGPUChild.cpp
index ab1a100736..d89923a5b9 100644
--- a/dom/webgpu/ipc/WebGPUChild.cpp
+++ b/dom/webgpu/ipc/WebGPUChild.cpp
@@ -226,7 +226,7 @@ void WebGPUChild::RegisterDevice(Device* const aDevice) {
}
void WebGPUChild::UnregisterDevice(RawId aDeviceId) {
- if (IsOpen()) {
+ if (CanSend()) {
SendDeviceDrop(aDeviceId);
}
mDeviceMap.erase(aDeviceId);
diff --git a/dom/webgpu/ipc/WebGPUChild.h b/dom/webgpu/ipc/WebGPUChild.h
index 37525420bd..bb572e5a03 100644
--- a/dom/webgpu/ipc/WebGPUChild.h
+++ b/dom/webgpu/ipc/WebGPUChild.h
@@ -58,8 +58,6 @@ class WebGPUChild final : public PWebGPUChild, public SupportsWeakPtr {
public:
explicit WebGPUChild();
- bool IsOpen() const { return CanSend(); }
-
RefPtr<AdapterPromise> InstanceRequestAdapter(
const dom::GPURequestAdapterOptions& aOptions);
Maybe<DeviceRequest> AdapterRequestDevice(RawId aSelfId,
diff --git a/dom/webgpu/ipc/WebGPUParent.cpp b/dom/webgpu/ipc/WebGPUParent.cpp
index 1c0560d31e..cc1fab90b6 100644
--- a/dom/webgpu/ipc/WebGPUParent.cpp
+++ b/dom/webgpu/ipc/WebGPUParent.cpp
@@ -1532,7 +1532,6 @@ std::shared_ptr<ExternalTexture> WebGPUParent::CreateExternalTexture(
UniquePtr<ExternalTexture> texture =
ExternalTexture::Create(aWidth, aHeight, aFormat, aUsage);
if (!texture) {
- MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return nullptr;
}
diff --git a/dom/webgpu/ipc/WebGPUSerialize.h b/dom/webgpu/ipc/WebGPUSerialize.h
index 03f9ee1676..4296c905f4 100644
--- a/dom/webgpu/ipc/WebGPUSerialize.h
+++ b/dom/webgpu/ipc/WebGPUSerialize.h
@@ -46,7 +46,7 @@ DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::webgpu::PopErrorScopeResult,
resultType, message);
DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::webgpu::WebGPUCompilationMessage,
- message, lineNum, linePos);
+ message, lineNum, linePos, offset, length);
#undef DEFINE_IPC_SERIALIZER_FFI_ENUM
#undef DEFINE_IPC_SERIALIZER_DOM_ENUM
diff --git a/dom/webgpu/mochitest/mochitest-no-pref.toml b/dom/webgpu/mochitest/mochitest-no-pref.toml
index 511b840c0b..ef83071c66 100644
--- a/dom/webgpu/mochitest/mochitest-no-pref.toml
+++ b/dom/webgpu/mochitest/mochitest-no-pref.toml
@@ -1,6 +1,7 @@
[DEFAULT]
subsuite = "webgpu"
run-if = ["release_or_beta"]
+skip-if = ["verify"] # `test-verify` jobs don't guarantee a GPU, so skip them.
# Even if the pref were enabled, WebGPU is only available in secure contexts.
#
diff --git a/dom/webgpu/mochitest/mochitest.toml b/dom/webgpu/mochitest/mochitest.toml
index f32d7a9a86..d83dca2808 100644
--- a/dom/webgpu/mochitest/mochitest.toml
+++ b/dom/webgpu/mochitest/mochitest.toml
@@ -1,6 +1,7 @@
[DEFAULT]
subsuite = "webgpu"
run-if = ["!release_or_beta"]
+skip-if = ["verify"] # `test-verify` jobs don't guarantee a GPU, so skip them.
prefs = [
"dom.webgpu.enabled=true",
"dom.webgpu.workers.enabled=true",
@@ -18,60 +19,26 @@ support-files = [
scheme = "https"
["test_basic_canvas.worker.html"]
-fail-if = [
- "os == 'linux' && os_version == '18.04'",
- "os == 'mac'",
-]
["test_buffer_mapping.html"]
-fail-if = [
- "os == 'linux' && os_version == '18.04'",
- "os == 'mac'",
-]
["test_buffer_mapping_invalid_device.html"]
-fail-if = [
- "os == 'linux' && os_version == '18.04'",
- "os == 'mac'",
-]
["test_command_buffer_creation.html"]
-fail-if = [
- "os == 'linux' && os_version == '18.04'",
- "os == 'mac'",
-]
+
+["test_compilation_message_pos.html"]
["test_context_configure.html"]
-fail-if = [
- "os == 'linux' && os_version == '18.04'",
- "os == 'mac'",
-]
["test_device_creation.html"]
-fail-if = [
- "os == 'linux' && os_version == '18.04'",
- "os == 'mac'",
-]
["test_device_lost.html"]
-fail-if = [
- "os == 'linux' && os_version == '18.04'",
- "os == 'mac'",
-]
["test_double_encoder_finish.html"]
-fail-if = [
- "os == 'linux' && os_version == '18.04'",
- "os == 'mac'",
-]
["test_enabled.html"]
["test_error_scope.html"]
-fail-if = [
- "os == 'linux' && os_version == '18.04'",
- "os == 'mac'",
-]
["test_insecure_context.html"]
# This test checks that WebGPU is not available in insecure contexts.
@@ -80,37 +47,13 @@ scheme = "http"
["test_navigator_gpu_not_replaceable.html"]
["test_queue_copyExternalImageToTexture.html"]
-fail-if = [
- "os == 'linux' && os_version == '18.04'",
- "os == 'mac'",
-]
["test_queue_write.html"]
-fail-if = [
- "os == 'linux' && os_version == '18.04'",
- "os == 'mac'",
-]
["test_queue_write_invalid_device.html"]
-fail-if = [
- "os == 'linux' && os_version == '18.04'",
- "os == 'mac'",
-]
["test_submit_compute_empty.html"]
-fail-if = [
- "os == 'linux' && os_version == '18.04'",
- "os == 'mac'",
-]
["test_submit_render_empty.html"]
-fail-if = [
- "os == 'linux' && os_version == '18.04'",
- "os == 'mac'",
-]
["test_submit_render_empty.worker.html"]
-fail-if = [
- "os == 'linux' && os_version == '18.04'",
- "os == 'mac'",
-]
diff --git a/dom/webgpu/mochitest/test_compilation_message_pos.html b/dom/webgpu/mochitest/test_compilation_message_pos.html
new file mode 100644
index 0000000000..f582cac5c0
--- /dev/null
+++ b/dom/webgpu/mochitest/test_compilation_message_pos.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css" />
+ </head>
+ <body>
+ <script>
+ ok(
+ SpecialPowers.getBoolPref("dom.webgpu.enabled"),
+ "Pref should be enabled."
+ );
+
+ async function testBody() {
+ const adapter = await navigator.gpu.requestAdapter();
+ const device = await adapter.requestDevice();
+
+ device.pushErrorScope("validation");
+ const shaderModule = device.createShaderModule({
+ // `?` is invalid, and we want to see if the offset will be right with the kitten emoji
+ // before it.
+ code: "/*๐Ÿˆ๐Ÿˆ๐Ÿˆ๐Ÿˆ๐Ÿˆ๐Ÿˆ๐Ÿˆ*/?",
+ });
+
+ const error = await device.popErrorScope();
+ ok(error, "expected error from invalid shader");
+ is(error.message, "Shader module creation failed: Parsing error");
+
+ const compilationInfo = await shaderModule.getCompilationInfo();
+ is(compilationInfo.messages.length, 1);
+
+ const { length, lineNum, linePos, message, offset } =
+ compilationInfo.messages[0];
+ is(length, 1);
+ is(lineNum, 1);
+ is(linePos, 19);
+ is(
+ message,
+ `
+Shader '' parsing error: expected global item ('struct', 'const', 'var', 'alias', ';', 'fn') or the end of the file, found '?'
+ โ”Œโ”€ wgsl:1:12
+ โ”‚
+1 โ”‚ /*๐Ÿˆ๐Ÿˆ๐Ÿˆ๐Ÿˆ๐Ÿˆ๐Ÿˆ๐Ÿˆ*/?
+ โ”‚ ^ expected global item ('struct', 'const', 'var', 'alias', ';', 'fn') or the end of the file
+
+`
+ );
+ is(offset, 18);
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ testBody()
+ .catch(e => ok(false, "Unhandled exception " + e))
+ .finally(() => SimpleTest.finish());
+ </script>
+ </body>
+</html>