diff options
Diffstat (limited to 'dom/webgpu')
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> |