[dawn][wire] Make sure to release WGPUObjects on Server teardown. - The fuzzer found that if the server was deleted while an async pipeline creation is in flight, the callback would end up being called when the server's weak_ptr is already invalid and as a result, skip calling the callback implementation altogether. This results in the pipeline (if one was returned) being leaked. - This change passes a shared_ptr of the ProcTable to the callback userdatas so that they can clean up any WGPUObjects that are returned from the callbacks if the server is already gone. Bug: 476162309 Change-Id: Ie3bdb6f61a361952f7c7d32e44eb762c5f650f5e Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/289215 Auto-Submit: Loko Kung <lokokung@google.com> Reviewed-by: Kai Ninomiya <kainino@chromium.org> Commit-Queue: Kai Ninomiya <kainino@chromium.org>
diff --git a/generator/templates/dawn/wire/server/ServerBase.h b/generator/templates/dawn/wire/server/ServerBase.h index edded22..0f16f4e29 100644 --- a/generator/templates/dawn/wire/server/ServerBase.h +++ b/generator/templates/dawn/wire/server/ServerBase.h
@@ -28,6 +28,7 @@ #ifndef DAWNWIRE_SERVER_SERVERBASE_AUTOGEN_H_ #define DAWNWIRE_SERVER_SERVERBASE_AUTOGEN_H_ +#include <memory> #include <tuple> #include "dawn/common/Mutex.h" @@ -43,14 +44,14 @@ class ServerBase : public ChunkedCommandHandler, public ObjectIdResolver { public: - ServerBase(const DawnProcTable& procs) : mProcs(procs) {} + ServerBase(const DawnProcTable& procs) : mProcs(std::make_shared<DawnProcTable>(procs)) {} ~ServerBase() override = default; Mutex::AutoLock GetGuard() { return Mutex::AutoLock(&mMutex); } protected: // Proc table may be used by children as well. - DawnProcTable mProcs; + std::shared_ptr<const DawnProcTable> mProcs; // Template functions that implement helpers on KnownObjects. template <typename T> @@ -103,7 +104,7 @@ template <typename T> void Release(T handle) { - (mProcs.*WGPUTraits<T>::Release)(handle); + ((*mProcs).*WGPUTraits<T>::Release)(handle); } void DestroyAllObjects() { //* Release devices first to force completion of any async work.
diff --git a/generator/templates/dawn/wire/server/ServerDoers.cpp b/generator/templates/dawn/wire/server/ServerDoers.cpp index 858afb2..26cb32f 100644 --- a/generator/templates/dawn/wire/server/ServerDoers.cpp +++ b/generator/templates/dawn/wire/server/ServerDoers.cpp
@@ -63,7 +63,7 @@ {{ assert(ret|length == 0) }} {{ assert(not method.returns) }} {% endif %} - mProcs.{{as_varName(type.name, method.name)}}( + mProcs->{{as_varName(type.name, method.name)}}( {%- for member in command.members if not member.is_return_value -%} {{as_varName(member.name)}} {%- if not loop.last -%}, {% endif %}
diff --git a/generator/templates/dawn/wire/server/WGPUTraits.h b/generator/templates/dawn/wire/server/WGPUTraits.h index 5cf1681..1f51f89 100644 --- a/generator/templates/dawn/wire/server/WGPUTraits.h +++ b/generator/templates/dawn/wire/server/WGPUTraits.h
@@ -33,7 +33,9 @@ namespace dawn::wire::server { template <typename T> -struct WGPUTraits; +struct WGPUTraits { + static constexpr auto Release = nullptr; +}; {% for type in by_category["object"] %} {% set cType = as_cType(type.name) %}
diff --git a/src/dawn/wire/server/Server.cpp b/src/dawn/wire/server/Server.cpp index f0faed8..5f76c87 100644 --- a/src/dawn/wire/server/Server.cpp +++ b/src/dawn/wire/server/Server.cpp
@@ -30,7 +30,9 @@ namespace dawn::wire::server { -CallbackUserdata::CallbackUserdata(const std::weak_ptr<Server>& server) : server(server) {} +CallbackUserdata::CallbackUserdata(const std::weak_ptr<Server>& server, + std::shared_ptr<const DawnProcTable>& procs) + : server(server), procs(procs) {} // static std::shared_ptr<Server> Server::Create(const DawnProcTable& procs, @@ -86,7 +88,7 @@ // The Buffer is externally owned so it shouldn't be destroyed when we receive a destroy // message from the client. Add a reference to counterbalance the eventual release. - mProcs.bufferAddRef(buffer); + mProcs->bufferAddRef(buffer); return WireResult::Success; } @@ -110,7 +112,7 @@ // The texture is externally owned so it shouldn't be destroyed when we receive a destroy // message from the client. Add a reference to counterbalance the eventual release. - mProcs.textureAddRef(texture); + mProcs->textureAddRef(texture); return WireResult::Success; } @@ -134,7 +136,7 @@ // The surface is externally owned so it shouldn't be destroyed when we receive a destroy // message from the client. Add a reference to counterbalance the eventual release. - mProcs.surfaceAddRef(surface); + mProcs->surfaceAddRef(surface); return WireResult::Success; } @@ -150,7 +152,7 @@ // The instance is externally owned so it shouldn't be destroyed when we receive a destroy // message from the client. Add a reference to counterbalance the eventual release. - mProcs.instanceAddRef(instance); + mProcs->instanceAddRef(instance); return WireResult::Success; } @@ -184,7 +186,7 @@ // is freed. // Set callback to post warning and other information to client. - mProcs.deviceSetLoggingCallback( + mProcs->deviceSetLoggingCallback( device->handle, {nullptr, [](WGPULoggingType type, WGPUStringView message, void* userdata, void*) { DeviceInfo* info = static_cast<DeviceInfo*>(userdata); @@ -196,7 +198,7 @@ void Server::ClearDeviceCallbacks(WGPUDevice device) { // Un-set the logging callback since we cannot forward them after the server has been destroyed. - mProcs.deviceSetLoggingCallback(device, kEmptyLoggingCallbackInfo); + mProcs->deviceSetLoggingCallback(device, kEmptyLoggingCallbackInfo); } } // namespace dawn::wire::server
diff --git a/src/dawn/wire/server/Server.h b/src/dawn/wire/server/Server.h index 6ded567..c94b4fc 100644 --- a/src/dawn/wire/server/Server.h +++ b/src/dawn/wire/server/Server.h
@@ -67,9 +67,11 @@ // void Server::MyCallbackHandler(MyUserdata* userdata, Other args) { } struct CallbackUserdata { const std::weak_ptr<Server> server; + const std::shared_ptr<const DawnProcTable> procs; CallbackUserdata() = delete; - explicit CallbackUserdata(const std::weak_ptr<Server>& server); + CallbackUserdata(const std::weak_ptr<Server>& server, + std::shared_ptr<const DawnProcTable>& procs); }; template <auto F, typename _ = decltype(F)> @@ -84,13 +86,22 @@ std::unique_ptr<Userdata> data(static_cast<Userdata*>(userdata)); auto server = data->server.lock(); if (!server) { - // Do nothing if the server has already been destroyed. + // If the server is destroyed, release any callback owned results and return. + ( + []<typename T>(const DawnProcTable& procs, T arg) { + if constexpr (WGPUTraits<T>::Release != nullptr) { + if (arg) { + (procs.*WGPUTraits<T>::Release)(arg); + } + } + }(*(data->procs), std::forward<Args>(args)), + ...); return; } // Forward the arguments and the typed userdata to the Server:: member function. { auto serverGuard = server.get()->GetGuard(); - (server.get()->*F)(data.get(), std::forward<decltype(args)>(args)...); + (server.get()->*F)(data.get(), std::forward<Args>(args)...); } server.get()->Flush(); } @@ -191,7 +202,7 @@ template <typename T, typename Enable = std::enable_if<std::is_base_of<CallbackUserdata, T>::value>> std::unique_ptr<T> MakeUserdata() { - return std::unique_ptr<T>(new T(mSelf)); + return std::unique_ptr<T>(new T(mSelf, mProcs)); } template <typename CallbackInfo, @@ -222,11 +233,12 @@ template <typename Struct> class FreeMembers : public Struct { public: - explicit FreeMembers(const DawnProcTable& procs) : Struct({}), mProcs(procs) {} - ~FreeMembers() { (mProcs.*WGPUTraits<Struct>::FreeMembers)(*this); } + explicit FreeMembers(std::shared_ptr<const DawnProcTable>& procs) + : Struct({}), mProcs(procs) {} + ~FreeMembers() { ((*mProcs).*WGPUTraits<Struct>::FreeMembers)(*this); } private: - const DawnProcTable& mProcs; + std::shared_ptr<const DawnProcTable> mProcs; }; void SetForwardingDeviceCallbacks(Known<WGPUDevice> device);
diff --git a/src/dawn/wire/server/ServerAdapter.cpp b/src/dawn/wire/server/ServerAdapter.cpp index 55c012f..15ec388 100644 --- a/src/dawn/wire/server/ServerAdapter.cpp +++ b/src/dawn/wire/server/ServerAdapter.cpp
@@ -72,7 +72,7 @@ }, nullptr, device->info.get()}; - mProcs.adapterRequestDevice( + mProcs->adapterRequestDevice( adapter->handle, &desc, MakeCallbackInfo<WGPURequestDeviceCallbackInfo, &Server::OnRequestDeviceCallback, WGPUCallbackMode_AllowSpontaneous>(userdata.release())); @@ -100,13 +100,13 @@ // Note: We fail the callback here, instead of immediately upon receiving // the request to preserve callback ordering. FreeMembers<WGPUSupportedFeatures> supportedFeatures(mProcs); - mProcs.deviceGetFeatures(device, &supportedFeatures); + mProcs->deviceGetFeatures(device, &supportedFeatures); absl::Span<const WGPUFeatureName> features(supportedFeatures.features, supportedFeatures.featureCount); for (WGPUFeatureName feature : features) { if (!IsFeatureSupported(feature)) { // Release the device. - mProcs.deviceRelease(device); + mProcs->deviceRelease(device); device = nullptr; cmd.status = WGPURequestDeviceStatus_Error; @@ -131,7 +131,7 @@ WGPUResourceTableLimits resourceTableLimits = WGPU_RESOURCE_TABLE_LIMITS_INIT; texelCopyBufferRowAlignmentLimits.chain.next = &resourceTableLimits.chain; - mProcs.deviceGetLimits(device, &limits); + mProcs->deviceGetLimits(device, &limits); cmd.limits = &limits; // Assign the handle and allocated status if the device is created successfully.
diff --git a/src/dawn/wire/server/ServerBuffer.cpp b/src/dawn/wire/server/ServerBuffer.cpp index 9d209fa..ba8e9e0 100644 --- a/src/dawn/wire/server/ServerBuffer.cpp +++ b/src/dawn/wire/server/ServerBuffer.cpp
@@ -118,7 +118,7 @@ userdata->offset = offset; userdata->size = size; - mProcs.bufferMapAsync( + mProcs->bufferMapAsync( buffer->handle, mode, offset, size, MakeCallbackInfo<WGPUBufferMapCallbackInfo, &Server::OnBufferMapAsyncCallback>( userdata.release())); @@ -136,7 +136,7 @@ // Create and register the buffer object. Reserved<WGPUBuffer> buffer; WIRE_TRY(Allocate(&buffer, bufferHandle)); - buffer->handle = mProcs.deviceCreateBuffer(device->handle, descriptor); + buffer->handle = mProcs->deviceCreateBuffer(device->handle, descriptor); buffer->usage = descriptor->usage; buffer->mappedAtCreation = (descriptor->mappedAtCreation != 0u); @@ -178,7 +178,7 @@ writeHandle->SetDataLength(descriptor->size); if (descriptor->mappedAtCreation) { - void* mapping = mProcs.bufferGetMappedRange(buffer->handle, 0, descriptor->size); + void* mapping = mProcs->bufferGetMappedRange(buffer->handle, 0, descriptor->size); if (mapping == nullptr) { DAWN_ASSERT(descriptor->size % 4 != 0); // GetMappedRange can still fail if the buffer's size isn't aligned. @@ -273,7 +273,7 @@ if (isSuccess) { if (isRead) { // Get the serialization size of the message to initialize ReadHandle data. - readData = mProcs.bufferGetConstMappedRange(data->bufferObj, data->offset, data->size); + readData = mProcs->bufferGetConstMappedRange(data->bufferObj, data->offset, data->size); readDataUpdateInfoLength = buffer->readHandle->SizeOfSerializeDataUpdate(data->offset, data->size); cmd.readDataUpdateInfoLength = readDataUpdateInfoLength; @@ -287,7 +287,7 @@ // modified (i.e. we don't want getMappedRange(0, wholeBufferSize) if only a // subset of the buffer is actually mapped) in case the implementation does some // range tracking. - buffer->writeHandle->SetTarget(static_cast<uint8_t*>(mProcs.bufferGetMappedRange( + buffer->writeHandle->SetTarget(static_cast<uint8_t*>(mProcs->bufferGetMappedRange( data->bufferObj, data->offset, data->size)) - data->offset); }
diff --git a/src/dawn/wire/server/ServerDevice.cpp b/src/dawn/wire/server/ServerDevice.cpp index ef51d89..beebcb1 100644 --- a/src/dawn/wire/server/ServerDevice.cpp +++ b/src/dawn/wire/server/ServerDevice.cpp
@@ -73,7 +73,7 @@ userdata->eventManager = eventManager; userdata->future = future; - mProcs.devicePopErrorScope( + mProcs->devicePopErrorScope( device->handle, MakeCallbackInfo<WGPUPopErrorScopeCallbackInfo, &Server::OnDevicePopErrorScope>( userdata.release())); @@ -109,7 +109,7 @@ userdata->future = future; userdata->pipelineObjectID = pipeline.id; - mProcs.deviceCreateComputePipelineAsync( + mProcs->deviceCreateComputePipelineAsync( device->handle, descriptor, MakeCallbackInfo<WGPUCreateComputePipelineAsyncCallbackInfo, &Server::OnCreateComputePipelineAsyncCallback>(userdata.release())); @@ -149,7 +149,7 @@ userdata->future = future; userdata->pipelineObjectID = pipeline.id; - mProcs.deviceCreateRenderPipelineAsync( + mProcs->deviceCreateRenderPipelineAsync( device->handle, descriptor, MakeCallbackInfo<WGPUCreateRenderPipelineAsyncCallbackInfo, &Server::OnCreateRenderPipelineAsyncCallback>(userdata.release()));
diff --git a/src/dawn/wire/server/ServerInstance.cpp b/src/dawn/wire/server/ServerInstance.cpp index ac3f29a..b92b8e7 100644 --- a/src/dawn/wire/server/ServerInstance.cpp +++ b/src/dawn/wire/server/ServerInstance.cpp
@@ -48,7 +48,7 @@ userdata->future = future; userdata->adapterObjectId = adapter.id; - mProcs.instanceRequestAdapter( + mProcs->instanceRequestAdapter( instance->handle, options, MakeCallbackInfo<WGPURequestAdapterCallbackInfo, &Server::OnRequestAdapterCallback, WGPUCallbackMode_AllowSpontaneous>(userdata.release())); @@ -81,7 +81,7 @@ // Query and report the adapter supported features. FreeMembers<WGPUSupportedFeatures> supportedFeatures(mProcs); - mProcs.adapterGetFeatures(adapter, &supportedFeatures); + mProcs->adapterGetFeatures(adapter, &supportedFeatures); cmd.featuresCount = supportedFeatures.featureCount; cmd.features = supportedFeatures.features; @@ -92,7 +92,7 @@ // Query AdapterPropertiesMemoryHeaps if the feature is supported. FreeMembers<WGPUAdapterPropertiesMemoryHeaps> memoryHeapProperties(mProcs); memoryHeapProperties.chain.sType = WGPUSType_AdapterPropertiesMemoryHeaps; - if (mProcs.adapterHasFeature(adapter, WGPUFeatureName_AdapterPropertiesMemoryHeaps)) { + if (mProcs->adapterHasFeature(adapter, WGPUFeatureName_AdapterPropertiesMemoryHeaps)) { *propertiesChain = &memoryHeapProperties.chain; propertiesChain = &(*propertiesChain)->next; } @@ -100,7 +100,7 @@ // Query AdapterPropertiesD3D if the feature is supported. WGPUAdapterPropertiesD3D d3dProperties = {}; d3dProperties.chain.sType = WGPUSType_AdapterPropertiesD3D; - if (mProcs.adapterHasFeature(adapter, WGPUFeatureName_AdapterPropertiesD3D)) { + if (mProcs->adapterHasFeature(adapter, WGPUFeatureName_AdapterPropertiesD3D)) { *propertiesChain = &d3dProperties.chain; propertiesChain = &(*propertiesChain)->next; } @@ -108,7 +108,7 @@ // Query AdapterPropertiesVk if the feature is supported. WGPUAdapterPropertiesVk vkProperties = {}; vkProperties.chain.sType = WGPUSType_AdapterPropertiesVk; - if (mProcs.adapterHasFeature(adapter, WGPUFeatureName_AdapterPropertiesVk)) { + if (mProcs->adapterHasFeature(adapter, WGPUFeatureName_AdapterPropertiesVk)) { *propertiesChain = &vkProperties.chain; propertiesChain = &(*propertiesChain)->next; } @@ -117,7 +117,7 @@ FreeMembers<WGPUAdapterPropertiesSubgroupMatrixConfigs> subgroupMatrixConfigs(mProcs); // WGPUAdapterPropertiesSubgroupMatrixConfigs subgroupMatrixConfigs{}; subgroupMatrixConfigs.chain.sType = WGPUSType_AdapterPropertiesSubgroupMatrixConfigs; - if (mProcs.adapterHasFeature(adapter, WGPUFeatureName_ChromiumExperimentalSubgroupMatrix)) { + if (mProcs->adapterHasFeature(adapter, WGPUFeatureName_ChromiumExperimentalSubgroupMatrix)) { *propertiesChain = &subgroupMatrixConfigs.chain; propertiesChain = &(*propertiesChain)->next; } @@ -131,13 +131,13 @@ WGPUAdapterPropertiesExplicitComputeSubgroupSizeConfigs explicitComputeSubgroupSizeConfigs = {}; explicitComputeSubgroupSizeConfigs.chain.sType = WGPUSType_AdapterPropertiesExplicitComputeSubgroupSizeConfigs; - if (mProcs.adapterHasFeature(adapter, - WGPUFeatureName_ChromiumExperimentalSubgroupSizeControl)) { + if (mProcs->adapterHasFeature(adapter, + WGPUFeatureName_ChromiumExperimentalSubgroupSizeControl)) { *propertiesChain = &explicitComputeSubgroupSizeConfigs.chain; propertiesChain = &(*propertiesChain)->next; } - mProcs.adapterGetInfo(adapter, &info); + mProcs->adapterGetInfo(adapter, &info); cmd.info = &info; // Query and report the adapter limits, including all known extension limits. @@ -152,7 +152,7 @@ WGPU_DAWN_TEXEL_COPY_BUFFER_ROW_ALIGNMENT_LIMITS_INIT; compatLimits.chain.next = &texelCopyBufferRowAlignmentLimits.chain; - mProcs.adapterGetLimits(adapter, &limits); + mProcs->adapterGetLimits(adapter, &limits); cmd.limits = &limits; SerializeCommand(cmd);
diff --git a/src/dawn/wire/server/ServerProgrammableEncoder.cpp b/src/dawn/wire/server/ServerProgrammableEncoder.cpp index a1d8319..af8c6b8 100644 --- a/src/dawn/wire/server/ServerProgrammableEncoder.cpp +++ b/src/dawn/wire/server/ServerProgrammableEncoder.cpp
@@ -36,8 +36,8 @@ uint32_t immediateDataRangeOffsetBytes, const uint8_t* data, size_t size) { - mProcs.renderPassEncoderSetImmediates(renderPassEncoder->handle, immediateDataRangeOffsetBytes, - data, size); + mProcs->renderPassEncoderSetImmediates(renderPassEncoder->handle, immediateDataRangeOffsetBytes, + data, size); return WireResult::Success; } @@ -46,8 +46,8 @@ uint32_t immediateDataRangeOffsetBytes, const uint8_t* data, size_t size) { - mProcs.renderBundleEncoderSetImmediates(renderBundleEncoder->handle, - immediateDataRangeOffsetBytes, data, size); + mProcs->renderBundleEncoderSetImmediates(renderBundleEncoder->handle, + immediateDataRangeOffsetBytes, data, size); return WireResult::Success; } @@ -56,8 +56,8 @@ uint32_t immediateDataRangeOffsetBytes, const uint8_t* data, size_t size) { - mProcs.computePassEncoderSetImmediates(computePassEncoder->handle, - immediateDataRangeOffsetBytes, data, size); + mProcs->computePassEncoderSetImmediates(computePassEncoder->handle, + immediateDataRangeOffsetBytes, data, size); return WireResult::Success; }
diff --git a/src/dawn/wire/server/ServerQueue.cpp b/src/dawn/wire/server/ServerQueue.cpp index bcb8eef..ebe37b7 100644 --- a/src/dawn/wire/server/ServerQueue.cpp +++ b/src/dawn/wire/server/ServerQueue.cpp
@@ -53,7 +53,7 @@ userdata->eventManager = eventManager; userdata->future = future; - mProcs.queueOnSubmittedWorkDone( + mProcs->queueOnSubmittedWorkDone( queue->handle, MakeCallbackInfo<WGPUQueueWorkDoneCallbackInfo, &Server::OnQueueWorkDone>( userdata.release())); return WireResult::Success; @@ -68,8 +68,8 @@ return WireResult::FatalError; } - mProcs.queueWriteBuffer(queue->handle, buffer->handle, bufferOffset, data, - static_cast<size_t>(size)); + mProcs->queueWriteBuffer(queue->handle, buffer->handle, bufferOffset, data, + static_cast<size_t>(size)); return WireResult::Success; } @@ -100,8 +100,8 @@ // it. If so, we can avoid a copy. uint8_t* sourceData = writeHandle->GetSourceData(); if (sourceData) { - mProcs.queueWriteBuffer(queue->handle, buffer->handle, bufferOffset, sourceData, - static_cast<size_t>(size)); + mProcs->queueWriteBuffer(queue->handle, buffer->handle, bufferOffset, sourceData, + static_cast<size_t>(size)); return WireResult::Success; } @@ -121,8 +121,8 @@ return WireResult::FatalError; } - mProcs.queueWriteBuffer(queue->handle, buffer->handle, bufferOffset, backingData.get(), - static_cast<size_t>(size)); + mProcs->queueWriteBuffer(queue->handle, buffer->handle, bufferOffset, backingData.get(), + static_cast<size_t>(size)); return WireResult::Success; } @@ -136,8 +136,8 @@ return WireResult::FatalError; } - mProcs.queueWriteTexture(queue->handle, destination, data, static_cast<size_t>(dataSize), - dataLayout, writeSize); + mProcs->queueWriteTexture(queue->handle, destination, data, static_cast<size_t>(dataSize), + dataLayout, writeSize); return WireResult::Success; } @@ -169,8 +169,8 @@ // it. If so, we can avoid a copy. uint8_t* sourceData = writeHandle->GetSourceData(); if (sourceData) { - mProcs.queueWriteTexture(queue->handle, destination, sourceData, - static_cast<size_t>(dataSize), dataLayout, writeSize); + mProcs->queueWriteTexture(queue->handle, destination, sourceData, + static_cast<size_t>(dataSize), dataLayout, writeSize); return WireResult::Success; } @@ -190,8 +190,8 @@ return WireResult::FatalError; } - mProcs.queueWriteTexture(queue->handle, destination, backingData.get(), - static_cast<size_t>(dataSize), dataLayout, writeSize); + mProcs->queueWriteTexture(queue->handle, destination, backingData.get(), + static_cast<size_t>(dataSize), dataLayout, writeSize); return WireResult::Success; }
diff --git a/src/dawn/wire/server/ServerShaderModule.cpp b/src/dawn/wire/server/ServerShaderModule.cpp index 35439fb..8afa631 100644 --- a/src/dawn/wire/server/ServerShaderModule.cpp +++ b/src/dawn/wire/server/ServerShaderModule.cpp
@@ -38,7 +38,7 @@ userdata->eventManager = eventManager; userdata->future = future; - mProcs.shaderModuleGetCompilationInfo( + mProcs->shaderModuleGetCompilationInfo( shaderModule->handle, MakeCallbackInfo<WGPUCompilationInfoCallbackInfo, &Server::OnShaderModuleGetCompilationInfo>(userdata.release()));
diff --git a/src/dawn/wire/server/ServerSurface.cpp b/src/dawn/wire/server/ServerSurface.cpp index 081fb08..b981358 100644 --- a/src/dawn/wire/server/ServerSurface.cpp +++ b/src/dawn/wire/server/ServerSurface.cpp
@@ -37,7 +37,7 @@ WIRE_TRY(Allocate(&texture, textureHandle, AllocationState::Reserved)); WGPUSurfaceTexture surfaceTexture; - mProcs.surfaceGetCurrentTexture(surface->handle, &surfaceTexture); + mProcs->surfaceGetCurrentTexture(surface->handle, &surfaceTexture); if (surfaceTexture.texture != nullptr) { return FillReservation(texture.id, surfaceTexture.texture); @@ -45,7 +45,8 @@ // The client always assumes that a texture will be associated with the reservation, so // create an error texture on the configured device. WGPUTextureDescriptor desc = WGPU_TEXTURE_DESCRIPTOR_INIT; - WGPUTexture errorTexture = mProcs.deviceCreateErrorTexture(configuredDevice->handle, &desc); + WGPUTexture errorTexture = + mProcs->deviceCreateErrorTexture(configuredDevice->handle, &desc); return FillReservation(texture.id, errorTexture); } }