Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit fa44648

Browse files
authored
[Impeller] Removed last ivars to raw vk::Device's. (#42215)
Removes the last ivars that hold onto a `Device` directly. This have recently been the cause of crashes, so the safer thing is to remove them all. For the Allocator and the Sampler library, removing the device ivars is likely just a precaution since they should have only been accessed from the raster thread and killed before the Device. The fence waiter however was potentially accessing the device from a separate thread, so that was much more risky and likely to cause crashes. Testing: The existing `impeller_unittests` verify this is setup correctly. [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent 9bcf529 commit fa44648

File tree

10 files changed

+123
-85
lines changed

10 files changed

+123
-85
lines changed

impeller/renderer/backend/vulkan/allocator_vk.cc

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,20 @@ namespace impeller {
1717
AllocatorVK::AllocatorVK(std::weak_ptr<Context> context,
1818
uint32_t vulkan_api_version,
1919
const vk::PhysicalDevice& physical_device,
20-
const vk::Device& logical_device,
20+
const std::shared_ptr<DeviceHolder>& device_holder,
2121
const vk::Instance& instance,
2222
PFN_vkGetInstanceProcAddr get_instance_proc_address,
2323
PFN_vkGetDeviceProcAddr get_device_proc_address)
24-
: context_(std::move(context)), device_(logical_device) {
24+
: context_(std::move(context)), device_holder_(device_holder) {
2525
vk_ = fml::MakeRefCounted<vulkan::VulkanProcTable>(get_instance_proc_address);
2626

2727
auto instance_handle = vulkan::VulkanHandle<VkInstance>(instance);
2828
if (!vk_->SetupInstanceProcAddresses(instance_handle)) {
2929
return;
3030
}
3131

32-
auto device_handle = vulkan::VulkanHandle<VkDevice>(logical_device);
32+
auto device_handle =
33+
vulkan::VulkanHandle<VkDevice>(device_holder->GetDevice());
3334
if (!vk_->SetupDeviceProcAddresses(device_handle)) {
3435
return;
3536
}
@@ -78,7 +79,7 @@ AllocatorVK::AllocatorVK(std::weak_ptr<Context> context,
7879
VmaAllocatorCreateInfo allocator_info = {};
7980
allocator_info.vulkanApiVersion = vulkan_api_version;
8081
allocator_info.physicalDevice = physical_device;
81-
allocator_info.device = logical_device;
82+
allocator_info.device = device_holder->GetDevice();
8283
allocator_info.instance = instance;
8384
allocator_info.pVulkanFunctions = &proc_table;
8485

@@ -333,10 +334,15 @@ std::shared_ptr<Texture> AllocatorVK::OnCreateTexture(
333334
if (!IsValid()) {
334335
return nullptr;
335336
}
336-
auto source = std::make_shared<AllocatedTextureSourceVK>(desc, //
337-
allocator_, //
338-
device_ //
339-
);
337+
auto device_holder = device_holder_.lock();
338+
if (!device_holder) {
339+
return nullptr;
340+
}
341+
auto source =
342+
std::make_shared<AllocatedTextureSourceVK>(desc, //
343+
allocator_, //
344+
device_holder->GetDevice() //
345+
);
340346
if (!source->IsValid()) {
341347
return nullptr;
342348
}

impeller/renderer/backend/vulkan/allocator_vk.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "impeller/core/allocator.h"
1111
#include "impeller/renderer/backend/vulkan/context_vk.h"
1212
#include "impeller/renderer/backend/vulkan/device_buffer_vk.h"
13+
#include "impeller/renderer/backend/vulkan/device_holder.h"
1314
#include "impeller/renderer/backend/vulkan/vk.h"
1415

1516
#include <memory>
@@ -27,14 +28,14 @@ class AllocatorVK final : public Allocator {
2728
fml::RefPtr<vulkan::VulkanProcTable> vk_;
2829
VmaAllocator allocator_ = {};
2930
std::weak_ptr<Context> context_;
30-
vk::Device device_;
31+
std::weak_ptr<DeviceHolder> device_holder_;
3132
ISize max_texture_size_;
3233
bool is_valid_ = false;
3334

3435
AllocatorVK(std::weak_ptr<Context> context,
3536
uint32_t vulkan_api_version,
3637
const vk::PhysicalDevice& physical_device,
37-
const vk::Device& logical_device,
38+
const std::shared_ptr<DeviceHolder>& device_holder,
3839
const vk::Instance& instance,
3940
PFN_vkGetInstanceProcAddr get_instance_proc_address,
4041
PFN_vkGetDeviceProcAddr get_device_proc_address);

impeller/renderer/backend/vulkan/blit_command_vk_unittests.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ namespace testing {
1313
TEST(BlitCommandVkTest, BlitCopyTextureToTextureCommandVK) {
1414
auto context = CreateMockVulkanContext();
1515
auto pool = CommandPoolVK::GetThreadLocal(context.get());
16-
CommandEncoderVK encoder(context, context->GetGraphicsQueue(), pool,
16+
CommandEncoderVK encoder(context->GetDeviceHolder(),
17+
context->GetGraphicsQueue(), pool,
1718
context->GetFenceWaiter());
1819
BlitCopyTextureToTextureCommandVK cmd;
1920
cmd.source = context->GetResourceAllocator()->CreateTexture({
@@ -31,7 +32,8 @@ TEST(BlitCommandVkTest, BlitCopyTextureToTextureCommandVK) {
3132
TEST(BlitCommandVkTest, BlitCopyTextureToBufferCommandVK) {
3233
auto context = CreateMockVulkanContext();
3334
auto pool = CommandPoolVK::GetThreadLocal(context.get());
34-
CommandEncoderVK encoder(context, context->GetGraphicsQueue(), pool,
35+
CommandEncoderVK encoder(context->GetDeviceHolder(),
36+
context->GetGraphicsQueue(), pool,
3537
context->GetFenceWaiter());
3638
BlitCopyTextureToBufferCommandVK cmd;
3739
cmd.source = context->GetResourceAllocator()->CreateTexture({
@@ -49,7 +51,8 @@ TEST(BlitCommandVkTest, BlitCopyTextureToBufferCommandVK) {
4951
TEST(BlitCommandVkTest, BlitGenerateMipmapCommandVK) {
5052
auto context = CreateMockVulkanContext();
5153
auto pool = CommandPoolVK::GetThreadLocal(context.get());
52-
CommandEncoderVK encoder(context, context->GetGraphicsQueue(), pool,
54+
CommandEncoderVK encoder(context->GetDeviceHolder(),
55+
context->GetGraphicsQueue(), pool,
5356
context->GetFenceWaiter());
5457
BlitGenerateMipmapCommandVK cmd;
5558
cmd.texture = context->GetResourceAllocator()->CreateTexture({

impeller/renderer/backend/vulkan/command_pool_vk.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ CommandPoolVK::CommandPoolVK(const ContextVK* context)
7878
return;
7979
}
8080

81-
device_holder_ = context->weak_from_this();
81+
device_holder_ = context->GetDeviceHolder();
8282
graphics_pool_ = std::move(pool.value);
8383
is_valid_ = true;
8484
}

impeller/renderer/backend/vulkan/context_vk.cc

Lines changed: 56 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ uint64_t CalculateHash(void* ptr) {
107107
ContextVK::ContextVK() : hash_(CalculateHash(this)) {}
108108

109109
ContextVK::~ContextVK() {
110-
if (device_) {
111-
[[maybe_unused]] auto result = device_->waitIdle();
110+
if (device_holder_->device) {
111+
[[maybe_unused]] auto result = device_holder_->device->waitIdle();
112112
}
113113
CommandPoolVK::ClearAllPools(this);
114114
}
@@ -191,14 +191,17 @@ void ContextVK::Setup(Settings settings) {
191191
instance_info.setPApplicationInfo(&application_info);
192192
instance_info.setFlags(instance_flags);
193193

194-
auto instance = vk::createInstanceUnique(instance_info);
195-
if (instance.result != vk::Result::eSuccess) {
196-
VALIDATION_LOG << "Could not create Vulkan instance: "
197-
<< vk::to_string(instance.result);
198-
return;
194+
auto device_holder = std::make_shared<DeviceHolderImpl>();
195+
{
196+
auto instance = vk::createInstanceUnique(instance_info);
197+
if (instance.result != vk::Result::eSuccess) {
198+
VALIDATION_LOG << "Could not create Vulkan instance: "
199+
<< vk::to_string(instance.result);
200+
return;
201+
}
202+
device_holder->instance = std::move(instance.value);
199203
}
200-
201-
dispatcher.init(instance.value.get());
204+
dispatcher.init(device_holder->instance.get());
202205

203206
//----------------------------------------------------------------------------
204207
/// Setup the debug report.
@@ -207,7 +210,7 @@ void ContextVK::Setup(Settings settings) {
207210
/// initialization issues.
208211
///
209212
auto debug_report =
210-
std::make_unique<DebugReportVK>(*caps, instance.value.get());
213+
std::make_unique<DebugReportVK>(*caps, device_holder->instance.get());
211214

212215
if (!debug_report->IsValid()) {
213216
VALIDATION_LOG << "Could not setup debug report.";
@@ -217,21 +220,25 @@ void ContextVK::Setup(Settings settings) {
217220
//----------------------------------------------------------------------------
218221
/// Pick the physical device.
219222
///
220-
auto physical_device = PickPhysicalDevice(*caps, instance.value.get());
221-
if (!physical_device.has_value()) {
222-
VALIDATION_LOG << "No valid Vulkan device found.";
223-
return;
223+
{
224+
auto physical_device =
225+
PickPhysicalDevice(*caps, device_holder->instance.get());
226+
if (!physical_device.has_value()) {
227+
VALIDATION_LOG << "No valid Vulkan device found.";
228+
return;
229+
}
230+
device_holder->physical_device = std::move(physical_device.value());
224231
}
225232

226233
//----------------------------------------------------------------------------
227234
/// Pick device queues.
228235
///
229236
auto graphics_queue =
230-
PickQueue(physical_device.value(), vk::QueueFlagBits::eGraphics);
237+
PickQueue(device_holder->physical_device, vk::QueueFlagBits::eGraphics);
231238
auto transfer_queue =
232-
PickQueue(physical_device.value(), vk::QueueFlagBits::eTransfer);
239+
PickQueue(device_holder->physical_device, vk::QueueFlagBits::eTransfer);
233240
auto compute_queue =
234-
PickQueue(physical_device.value(), vk::QueueFlagBits::eCompute);
241+
PickQueue(device_holder->physical_device, vk::QueueFlagBits::eCompute);
235242

236243
if (!graphics_queue.has_value()) {
237244
VALIDATION_LOG << "Could not pick graphics queue.";
@@ -250,7 +257,7 @@ void ContextVK::Setup(Settings settings) {
250257
/// Create the logical device.
251258
///
252259
auto enabled_device_extensions =
253-
caps->GetRequiredDeviceExtensions(physical_device.value());
260+
caps->GetRequiredDeviceExtensions(device_holder->physical_device);
254261
if (!enabled_device_extensions.has_value()) {
255262
// This shouldn't happen since we already did device selection. But doesn't
256263
// hurt to check again.
@@ -266,7 +273,7 @@ void ContextVK::Setup(Settings settings) {
266273
{graphics_queue.value(), compute_queue.value(), transfer_queue.value()});
267274

268275
const auto required_features =
269-
caps->GetRequiredDeviceFeatures(physical_device.value());
276+
caps->GetRequiredDeviceFeatures(device_holder->physical_device);
270277
if (!required_features.has_value()) {
271278
// This shouldn't happen since the device can't be picked if this was not
272279
// true. But doesn't hurt to check.
@@ -280,17 +287,17 @@ void ContextVK::Setup(Settings settings) {
280287
device_info.setPEnabledFeatures(&required_features.value());
281288
// Device layers are deprecated and ignored.
282289

283-
auto device_result = physical_device->createDeviceUnique(device_info);
284-
if (device_result.result != vk::Result::eSuccess) {
285-
VALIDATION_LOG << "Could not create logical device.";
286-
return;
290+
{
291+
auto device_result =
292+
device_holder->physical_device.createDeviceUnique(device_info);
293+
if (device_result.result != vk::Result::eSuccess) {
294+
VALIDATION_LOG << "Could not create logical device.";
295+
return;
296+
}
297+
device_holder->device = std::move(device_result.value);
287298
}
288-
device_ = std::move(device_result.value);
289-
// This makes sure that the device is deleted at the proper time if there is
290-
// an error.
291-
fml::ScopedCleanupClosure device_resetter([this]() { device_.reset(); });
292299

293-
if (!caps->SetDevice(physical_device.value())) {
300+
if (!caps->SetDevice(device_holder->physical_device)) {
294301
VALIDATION_LOG << "Capabilities could not be updated.";
295302
return;
296303
}
@@ -301,9 +308,9 @@ void ContextVK::Setup(Settings settings) {
301308
auto allocator = std::shared_ptr<AllocatorVK>(new AllocatorVK(
302309
weak_from_this(), //
303310
application_info.apiVersion, //
304-
physical_device.value(), //
305-
device_.get(), //
306-
instance.value.get(), //
311+
device_holder->physical_device, //
312+
device_holder, //
313+
device_holder->instance.get(), //
307314
dispatcher.vkGetInstanceProcAddr, //
308315
dispatcher.vkGetDeviceProcAddr //
309316
));
@@ -317,7 +324,7 @@ void ContextVK::Setup(Settings settings) {
317324
/// Setup the pipeline library.
318325
///
319326
auto pipeline_library = std::shared_ptr<PipelineLibraryVK>(
320-
new PipelineLibraryVK(shared_from_this(), //
327+
new PipelineLibraryVK(device_holder, //
321328
caps, //
322329
std::move(settings.cache_directory), //
323330
worker_task_runner_ //
@@ -329,10 +336,10 @@ void ContextVK::Setup(Settings settings) {
329336
}
330337

331338
auto sampler_library =
332-
std::shared_ptr<SamplerLibraryVK>(new SamplerLibraryVK(device_.get()));
339+
std::shared_ptr<SamplerLibraryVK>(new SamplerLibraryVK(device_holder));
333340

334341
auto shader_library = std::shared_ptr<ShaderLibraryVK>(
335-
new ShaderLibraryVK(weak_from_this(), //
342+
new ShaderLibraryVK(device_holder, //
336343
settings.shader_libraries_data) //
337344
);
338345

@@ -345,7 +352,7 @@ void ContextVK::Setup(Settings settings) {
345352
/// Create the fence waiter.
346353
///
347354
auto fence_waiter =
348-
std::shared_ptr<FenceWaiterVK>(new FenceWaiterVK(device_.get()));
355+
std::shared_ptr<FenceWaiterVK>(new FenceWaiterVK(device_holder));
349356
if (!fence_waiter->IsValid()) {
350357
VALIDATION_LOG << "Could not create fence waiter.";
351358
return;
@@ -354,27 +361,25 @@ void ContextVK::Setup(Settings settings) {
354361
//----------------------------------------------------------------------------
355362
/// Fetch the queues.
356363
///
357-
QueuesVK queues(device_.get(), //
358-
graphics_queue.value(), //
359-
compute_queue.value(), //
360-
transfer_queue.value() //
364+
QueuesVK queues(device_holder->device.get(), //
365+
graphics_queue.value(), //
366+
compute_queue.value(), //
367+
transfer_queue.value() //
361368
);
362369
if (!queues.IsValid()) {
363370
VALIDATION_LOG << "Could not fetch device queues.";
364371
return;
365372
}
366373

367374
VkPhysicalDeviceProperties physical_device_properties;
368-
dispatcher.vkGetPhysicalDeviceProperties(physical_device.value(),
375+
dispatcher.vkGetPhysicalDeviceProperties(device_holder->physical_device,
369376
&physical_device_properties);
370377

371378
//----------------------------------------------------------------------------
372379
/// All done!
373380
///
374-
instance_ = std::move(instance.value);
381+
device_holder_ = std::move(device_holder);
375382
debug_report_ = std::move(debug_report);
376-
physical_device_ = physical_device.value();
377-
device_resetter.Release();
378383
allocator_ = std::move(allocator);
379384
shader_library_ = std::move(shader_library);
380385
sampler_library_ = std::move(sampler_library);
@@ -389,7 +394,7 @@ void ContextVK::Setup(Settings settings) {
389394
/// Label all the relevant objects. This happens after setup so that the debug
390395
/// messengers have had a chance to be setup.
391396
///
392-
SetDebugName(GetDevice(), device_.get(), "ImpellerDevice");
397+
SetDebugName(GetDevice(), device_holder_->device.get(), "ImpellerDevice");
393398
}
394399

395400
// |Context|
@@ -429,11 +434,11 @@ std::shared_ptr<CommandBuffer> ContextVK::CreateCommandBuffer() const {
429434
}
430435

431436
vk::Instance ContextVK::GetInstance() const {
432-
return *instance_;
437+
return *device_holder_->instance;
433438
}
434439

435440
const vk::Device& ContextVK::GetDevice() const {
436-
return device_.get();
441+
return device_holder_->device.get();
437442
}
438443

439444
const std::shared_ptr<fml::ConcurrentTaskRunner>
@@ -454,12 +459,13 @@ std::unique_ptr<Surface> ContextVK::AcquireNextSurface() {
454459

455460
vk::UniqueSurfaceKHR ContextVK::CreateAndroidSurface(
456461
ANativeWindow* window) const {
457-
if (!instance_) {
462+
if (!device_holder_->instance) {
458463
return vk::UniqueSurfaceKHR{VK_NULL_HANDLE};
459464
}
460465

461466
auto create_info = vk::AndroidSurfaceCreateInfoKHR().setWindow(window);
462-
auto surface_res = instance_->createAndroidSurfaceKHRUnique(create_info);
467+
auto surface_res =
468+
device_holder_->instance->createAndroidSurfaceKHRUnique(create_info);
463469

464470
if (surface_res.result != vk::Result::eSuccess) {
465471
VALIDATION_LOG << "Could not create Android surface, error: "
@@ -491,7 +497,7 @@ const std::shared_ptr<QueueVK>& ContextVK::GetGraphicsQueue() const {
491497
}
492498

493499
vk::PhysicalDevice ContextVK::GetPhysicalDevice() const {
494-
return physical_device_;
500+
return device_holder_->physical_device;
495501
}
496502

497503
std::shared_ptr<FenceWaiterVK> ContextVK::GetFenceWaiter() const {
@@ -505,7 +511,7 @@ std::unique_ptr<CommandEncoderVK> ContextVK::CreateGraphicsCommandEncoder()
505511
return nullptr;
506512
}
507513
auto encoder = std::unique_ptr<CommandEncoderVK>(new CommandEncoderVK(
508-
weak_from_this(), //
514+
device_holder_, //
509515
queues_.graphics_queue, //
510516
tls_pool, //
511517
fence_waiter_ //

0 commit comments

Comments
 (0)