| Flutter Impeller |

context_vk.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/renderer/backend/vulkan/context_vk.h"
6
7 #ifdef FML_OS_ANDROID
8 #include <pthread.h>
9 #include <sys/resource.h>
10 #include <sys/time.h>
11 #endif // FML_OS_ANDROID
12
13 #include <map>
14 #include <memory>
15 #include <optional>
16 #include <string>
17 #include <vector>
18
19 #include "flutter/fml/cpu_affinity.h"
20 #include "flutter/fml/trace_event.h"
21 #include "impeller/base/validation.h"
22 #include "impeller/renderer/backend/vulkan/allocator_vk.h"
23 #include "impeller/renderer/backend/vulkan/capabilities_vk.h"
24 #include "impeller/renderer/backend/vulkan/command_buffer_vk.h"
25 #include "impeller/renderer/backend/vulkan/command_encoder_vk.h"
26 #include "impeller/renderer/backend/vulkan/command_pool_vk.h"
27 #include "impeller/renderer/backend/vulkan/debug_report_vk.h"
28 #include "impeller/renderer/backend/vulkan/fence_waiter_vk.h"
29 #include "impeller/renderer/backend/vulkan/resource_manager_vk.h"
30 #include "impeller/renderer/backend/vulkan/surface_context_vk.h"
31 #include "impeller/renderer/capabilities.h"
32
33 VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
34
35 namespace impeller {
36
37 // TODO(csg): Fix this after caps are reworked.
38 static bool gHasValidationLayers = false;
39
40 bool HasValidationLayers() {
41 return gHasValidationLayers;
42 }
43
44 static std::optional<vk::PhysicalDevice> PickPhysicalDevice(
45 const CapabilitiesVK& caps,
46 const vk::Instance& instance) {
47 for (const auto& device : instance.enumeratePhysicalDevices().value) {
48 if (caps.GetEnabledDeviceFeatures(device).has_value()) {
49 return device;
50 }
51 }
52 return std::nullopt;
53 }
54
55 static std::vector<vk::DeviceQueueCreateInfo> GetQueueCreateInfos(
56 std::initializer_list<QueueIndexVK> queues) {
57 std::map<size_t /* family */, size_t /* index */> family_index_map;
58 for (const auto& queue : queues) {
59 family_index_map[queue.family] = 0;
60 }
61 for (const auto& queue : queues) {
62 auto value = family_index_map[queue.family];
63 family_index_map[queue.family] = std::max(value, queue.index);
64 }
65
66 static float kQueuePriority = 1.0f;
67 std::vector<vk::DeviceQueueCreateInfo> infos;
68 for (const auto& item : family_index_map) {
69 vk::DeviceQueueCreateInfo info;
70 info.setQueueFamilyIndex(item.first);
71 info.setQueueCount(item.second + 1);
72 info.setQueuePriorities(kQueuePriority);
73 infos.push_back(info);
74 }
75 return infos;
76 }
77
78 static std::optional<QueueIndexVK> PickQueue(const vk::PhysicalDevice& device,
79 vk::QueueFlagBits flags) {
80 // This can be modified to ensure that dedicated queues are returned for each
81 // queue type depending on support.
82 const auto families = device.getQueueFamilyProperties();
83 for (size_t i = 0u; i < families.size(); i++) {
84 if (!(families[i].queueFlags & flags)) {
85 continue;
86 }
87 return QueueIndexVK{.family = i, .index = 0};
88 }
89 return std::nullopt;
90 }
91
92 std::shared_ptr<ContextVK> ContextVK::Create(Settings settings) {
93 auto context = std::shared_ptr<ContextVK>(new ContextVK());
94 context->Setup(std::move(settings));
95 if (!context->IsValid()) {
96 return nullptr;
97 }
98 return context;
99 }
100
101 namespace {
102 thread_local uint64_t tls_context_count = 0;
103 uint64_t CalculateHash(void* ptr) {
104 // You could make a context once per nanosecond for 584 years on one thread
105 // before this overflows.
106 return ++tls_context_count;
107 }
108 } // namespace
109
110 ContextVK::ContextVK() : hash_(CalculateHash(this)) {}
111
112 ContextVK::~ContextVK() {
113 if (device_holder_ && device_holder_->device) {
114 [[maybe_unused]] auto result = device_holder_->device->waitIdle();
115 }
116 CommandPoolRecyclerVK::DestroyThreadLocalPools(this);
117 }
118
119 Context::BackendType ContextVK::GetBackendType() const {
120 return Context::BackendType::kVulkan;
121 }
122
123 void ContextVK::Setup(Settings settings) {
124 TRACE_EVENT0("impeller", "ContextVK::Setup");
125
126 if (!settings.proc_address_callback) {
127 return;
128 }
129
130 raster_message_loop_ = fml::ConcurrentMessageLoop::Create(
131 std::min(4u, std::thread::hardware_concurrency()));
132 raster_message_loop_->PostTaskToAllWorkers([]() {
133 // Currently we only use the worker task pool for small parts of a frame
134 // workload, if this changes this setting may need to be adjusted.
135 fml::RequestAffinity(fml::CpuAffinity::kNotPerformance);
136 #ifdef FML_OS_ANDROID
137 if (::setpriority(PRIO_PROCESS, gettid(), -5) != 0) {
138 FML_LOG(ERROR) << "Failed to set Workers task runner priority";
139 }
140 #endif // FML_OS_ANDROID
141 });
142
143 auto& dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER;
144 dispatcher.init(settings.proc_address_callback);
145
146 // Enable Vulkan validation if either:
147 // 1. The user has explicitly enabled it.
148 // 2. We are in a combination of debug mode, and running on Android.
149 // (It's possible 2 is overly conservative and we can simplify this)
150 auto enable_validation = settings.enable_validation;
151
152 #if defined(FML_OS_ANDROID) && !defined(NDEBUG)
153 enable_validation = true;
154 #endif
155
156 auto caps =
157 std::shared_ptr<CapabilitiesVK>(new CapabilitiesVK(enable_validation));
158
159 if (!caps->IsValid()) {
160 VALIDATION_LOG << "Could not determine device capabilities.";
161 return;
162 }
163
164 gHasValidationLayers = caps->AreValidationsEnabled();
165
166 auto enabled_layers = caps->GetEnabledLayers();
167 auto enabled_extensions = caps->GetEnabledInstanceExtensions();
168
169 if (!enabled_layers.has_value() || !enabled_extensions.has_value()) {
170 VALIDATION_LOG << "Device has insufficient capabilities.";
171 return;
172 }
173
174 vk::InstanceCreateFlags instance_flags = {};
175
176 if (std::find(enabled_extensions.value().begin(),
177 enabled_extensions.value().end(),
178 "VK_KHR_portability_enumeration") !=
179 enabled_extensions.value().end()) {
180 instance_flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR;
181 }
182
183 std::vector<const char*> enabled_layers_c;
184 std::vector<const char*> enabled_extensions_c;
185
186 for (const auto& layer : enabled_layers.value()) {
187 enabled_layers_c.push_back(layer.c_str());
188 }
189
190 for (const auto& ext : enabled_extensions.value()) {
191 enabled_extensions_c.push_back(ext.c_str());
192 }
193
194 vk::ApplicationInfo application_info;
195 application_info.setApplicationVersion(VK_API_VERSION_1_0);
196 application_info.setApiVersion(VK_API_VERSION_1_1);
197 application_info.setEngineVersion(VK_API_VERSION_1_0);
198 application_info.setPEngineName("Impeller");
199 application_info.setPApplicationName("Impeller");
200
201 vk::StructureChain<vk::InstanceCreateInfo, vk::ValidationFeaturesEXT>
202 instance_chain;
203
204 if (!caps->AreValidationsEnabled()) {
205 instance_chain.unlink<vk::ValidationFeaturesEXT>();
206 }
207
208 std::vector<vk::ValidationFeatureEnableEXT> enabled_validations = {
209 vk::ValidationFeatureEnableEXT::eSynchronizationValidation,
210 };
211
212 auto validation = instance_chain.get<vk::ValidationFeaturesEXT>();
213 validation.setEnabledValidationFeatures(enabled_validations);
214
215 auto instance_info = instance_chain.get<vk::InstanceCreateInfo>();
216 instance_info.setPEnabledLayerNames(enabled_layers_c);
217 instance_info.setPEnabledExtensionNames(enabled_extensions_c);
218 instance_info.setPApplicationInfo(&application_info);
219 instance_info.setFlags(instance_flags);
220
221 auto device_holder = std::make_shared<DeviceHolderImpl>();
222 {
223 auto instance = vk::createInstanceUnique(instance_info);
224 if (instance.result != vk::Result::eSuccess) {
225 VALIDATION_LOG << "Could not create Vulkan instance: "
226 << vk::to_string(instance.result);
227 return;
228 }
229 device_holder->instance = std::move(instance.value);
230 }
231 dispatcher.init(device_holder->instance.get());
232
233 //----------------------------------------------------------------------------
234 /// Setup the debug report.
235 ///
236 /// Do this as early as possible since we could use the debug report from
237 /// initialization issues.
238 ///
239 auto debug_report =
240 std::make_unique<DebugReportVK>(*caps, device_holder->instance.get());
241
242 if (!debug_report->IsValid()) {
243 VALIDATION_LOG << "Could not set up debug report.";
244 return;
245 }
246
247 //----------------------------------------------------------------------------
248 /// Pick the physical device.
249 ///
250 {
251 auto physical_device =
252 PickPhysicalDevice(*caps, device_holder->instance.get());
253 if (!physical_device.has_value()) {
254 VALIDATION_LOG << "No valid Vulkan device found.";
255 return;
256 }
257 device_holder->physical_device = physical_device.value();
258 }
259
260 //----------------------------------------------------------------------------
261 /// Pick device queues.
262 ///
263 auto graphics_queue =
264 PickQueue(device_holder->physical_device, vk::QueueFlagBits::eGraphics);
265 auto transfer_queue =
266 PickQueue(device_holder->physical_device, vk::QueueFlagBits::eTransfer);
267 auto compute_queue =
268 PickQueue(device_holder->physical_device, vk::QueueFlagBits::eCompute);
269
270 if (!graphics_queue.has_value()) {
271 VALIDATION_LOG << "Could not pick graphics queue.";
272 return;
273 }
274 if (!transfer_queue.has_value()) {
275 FML_LOG(INFO) << "Dedicated transfer queue not avialable.";
276 transfer_queue = graphics_queue.value();
277 }
278 if (!compute_queue.has_value()) {
279 VALIDATION_LOG << "Could not pick compute queue.";
280 return;
281 }
282
283 //----------------------------------------------------------------------------
284 /// Create the logical device.
285 ///
286 auto enabled_device_extensions =
287 caps->GetEnabledDeviceExtensions(device_holder->physical_device);
288 if (!enabled_device_extensions.has_value()) {
289 // This shouldn't happen since we already did device selection. But
290 // doesn't hurt to check again.
291 return;
292 }
293
294 std::vector<const char*> enabled_device_extensions_c;
295 for (const auto& ext : enabled_device_extensions.value()) {
296 enabled_device_extensions_c.push_back(ext.c_str());
297 }
298
299 const auto queue_create_infos = GetQueueCreateInfos(
300 {graphics_queue.value(), compute_queue.value(), transfer_queue.value()});
301
302 const auto enabled_features =
303 caps->GetEnabledDeviceFeatures(device_holder->physical_device);
304 if (!enabled_features.has_value()) {
305 // This shouldn't happen since the device can't be picked if this was not
306 // true. But doesn't hurt to check.
307 return;
308 }
309
310 vk::DeviceCreateInfo device_info;
311
312 device_info.setQueueCreateInfos(queue_create_infos);
313 device_info.setPEnabledExtensionNames(enabled_device_extensions_c);
314 device_info.setPEnabledFeatures(&enabled_features.value());
315 // Device layers are deprecated and ignored.
316
317 {
318 auto device_result =
319 device_holder->physical_device.createDeviceUnique(device_info);
320 if (device_result.result != vk::Result::eSuccess) {
321 VALIDATION_LOG << "Could not create logical device.";
322 return;
323 }
324 device_holder->device = std::move(device_result.value);
325 }
326
327 if (!caps->SetPhysicalDevice(device_holder->physical_device)) {
328 VALIDATION_LOG << "Capabilities could not be updated.";
329 return;
330 }
331
332 //----------------------------------------------------------------------------
333 /// Create the allocator.
334 ///
335 auto allocator = std::shared_ptr<AllocatorVK>(new AllocatorVK(
336 weak_from_this(), //
337 application_info.apiVersion, //
338 device_holder->physical_device, //
339 device_holder, //
340 device_holder->instance.get(), //
341 *caps //
342 ));
343
344 if (!allocator->IsValid()) {
345 VALIDATION_LOG << "Could not create memory allocator.";
346 return;
347 }
348
349 //----------------------------------------------------------------------------
350 /// Setup the pipeline library.
351 ///
352 auto pipeline_library = std::shared_ptr<PipelineLibraryVK>(
353 new PipelineLibraryVK(device_holder, //
354 caps, //
355 std::move(settings.cache_directory), //
356 raster_message_loop_->GetTaskRunner() //
357 ));
358
359 if (!pipeline_library->IsValid()) {
360 VALIDATION_LOG << "Could not create pipeline library.";
361 return;
362 }
363
364 auto sampler_library =
365 std::shared_ptr<SamplerLibraryVK>(new SamplerLibraryVK(device_holder));
366
367 auto shader_library = std::shared_ptr<ShaderLibraryVK>(
368 new ShaderLibraryVK(device_holder, //
369 settings.shader_libraries_data) //
370 );
371
372 if (!shader_library->IsValid()) {
373 VALIDATION_LOG << "Could not create shader library.";
374 return;
375 }
376
377 //----------------------------------------------------------------------------
378 /// Create the fence waiter.
379 ///
380 auto fence_waiter =
381 std::shared_ptr<FenceWaiterVK>(new FenceWaiterVK(device_holder));
382
383 //----------------------------------------------------------------------------
384 /// Create the resource manager and command pool recycler.
385 ///
386 auto resource_manager = ResourceManagerVK::Create();
387 if (!resource_manager) {
388 VALIDATION_LOG << "Could not create resource manager.";
389 return;
390 }
391
392 auto command_pool_recycler =
393 std::make_shared<CommandPoolRecyclerVK>(weak_from_this());
394 if (!command_pool_recycler) {
395 VALIDATION_LOG << "Could not create command pool recycler.";
396 return;
397 }
398
399 //----------------------------------------------------------------------------
400 /// Fetch the queues.
401 ///
402 QueuesVK queues(device_holder->device.get(), //
403 graphics_queue.value(), //
404 compute_queue.value(), //
405 transfer_queue.value() //
406 );
407 if (!queues.IsValid()) {
408 VALIDATION_LOG << "Could not fetch device queues.";
409 return;
410 }
411
412 VkPhysicalDeviceProperties physical_device_properties;
413 dispatcher.vkGetPhysicalDeviceProperties(device_holder->physical_device,
414 &physical_device_properties);
415
416 //----------------------------------------------------------------------------
417 /// All done!
418 ///
419 device_holder_ = std::move(device_holder);
420 debug_report_ = std::move(debug_report);
421 allocator_ = std::move(allocator);
422 shader_library_ = std::move(shader_library);
423 sampler_library_ = std::move(sampler_library);
424 pipeline_library_ = std::move(pipeline_library);
425 queues_ = std::move(queues);
426 device_capabilities_ = std::move(caps);
427 fence_waiter_ = std::move(fence_waiter);
428 resource_manager_ = std::move(resource_manager);
429 command_pool_recycler_ = std::move(command_pool_recycler);
430 device_name_ = std::string(physical_device_properties.deviceName);
431 is_valid_ = true;
432
433 //----------------------------------------------------------------------------
434 /// Label all the relevant objects. This happens after setup so that the
435 /// debug messengers have had a chance to be set up.
436 ///
437 SetDebugName(GetDevice(), device_holder_->device.get(), "ImpellerDevice");
438 }
439
440 void ContextVK::SetOffscreenFormat(PixelFormat pixel_format) {
441 CapabilitiesVK::Cast(*device_capabilities_).SetOffscreenFormat(pixel_format);
442 }
443
444 // |Context|
445 std::string ContextVK::DescribeGpuModel() const {
446 return device_name_;
447 }
448
449 bool ContextVK::IsValid() const {
450 return is_valid_;
451 }
452
453 std::shared_ptr<Allocator> ContextVK::GetResourceAllocator() const {
454 return allocator_;
455 }
456
457 std::shared_ptr<ShaderLibrary> ContextVK::GetShaderLibrary() const {
458 return shader_library_;
459 }
460
461 std::shared_ptr<SamplerLibrary> ContextVK::GetSamplerLibrary() const {
462 return sampler_library_;
463 }
464
465 std::shared_ptr<PipelineLibrary> ContextVK::GetPipelineLibrary() const {
466 return pipeline_library_;
467 }
468
469 std::shared_ptr<CommandBuffer> ContextVK::CreateCommandBuffer() const {
470 return std::shared_ptr<CommandBufferVK>(
471 new CommandBufferVK(shared_from_this(), //
472 CreateGraphicsCommandEncoderFactory()) //
473 );
474 }
475
476 vk::Instance ContextVK::GetInstance() const {
477 return *device_holder_->instance;
478 }
479
480 const vk::Device& ContextVK::GetDevice() const {
481 return device_holder_->device.get();
482 }
483
484 const std::shared_ptr<fml::ConcurrentTaskRunner>
485 ContextVK::GetConcurrentWorkerTaskRunner() const {
486 return raster_message_loop_->GetTaskRunner();
487 }
488
489 void ContextVK::Shutdown() {
490 // There are multiple objects, for example |CommandPoolVK|, that in their
491 // destructors make a strong reference to |ContextVK|. Resetting these shared
492 // pointers ensures that cleanup happens in a correct order.
493 //
494 // tl;dr: Without it, we get thread::join failures on shutdown.
495 fence_waiter_.reset();
496 resource_manager_.reset();
497
498 raster_message_loop_->Terminate();
499 }
500
501 std::shared_ptr<SurfaceContextVK> ContextVK::CreateSurfaceContext() {
502 return std::make_shared<SurfaceContextVK>(shared_from_this());
503 }
504
505 const std::shared_ptr<const Capabilities>& ContextVK::GetCapabilities() const {
506 return device_capabilities_;
507 }
508
509 const std::shared_ptr<QueueVK>& ContextVK::GetGraphicsQueue() const {
510 return queues_.graphics_queue;
511 }
512
513 vk::PhysicalDevice ContextVK::GetPhysicalDevice() const {
514 return device_holder_->physical_device;
515 }
516
517 std::shared_ptr<FenceWaiterVK> ContextVK::GetFenceWaiter() const {
518 return fence_waiter_;
519 }
520
521 std::shared_ptr<ResourceManagerVK> ContextVK::GetResourceManager() const {
522 return resource_manager_;
523 }
524
525 std::shared_ptr<CommandPoolRecyclerVK> ContextVK::GetCommandPoolRecycler()
526 const {
527 return command_pool_recycler_;
528 }
529
530 std::unique_ptr<CommandEncoderFactoryVK>
531 ContextVK::CreateGraphicsCommandEncoderFactory() const {
532 return std::make_unique<CommandEncoderFactoryVK>(weak_from_this());
533 }
534
535 } // namespace impeller
impeller::ContextVK::GetCapabilities
const std::shared_ptr< const Capabilities > & GetCapabilities() const override
Get the capabilities of Impeller context. All optionally supported feature of the platform,...
Definition: context_vk.cc:505
impeller::ContextVK::GetConcurrentWorkerTaskRunner
const std::shared_ptr< fml::ConcurrentTaskRunner > GetConcurrentWorkerTaskRunner() const
Definition: context_vk.cc:485
fence_waiter_vk.h
impeller::CapabilitiesVK::SetOffscreenFormat
void SetOffscreenFormat(PixelFormat pixel_format) const
Definition: capabilities_vk.cc:337
impeller::ResourceManagerVK::Create
static std::shared_ptr< ResourceManagerVK > Create()
Creates a shared resource manager (a dedicated thread).
Definition: resource_manager_vk.cc:14
impeller::QueueIndexVK
Definition: queue_vk.h:15
allocator_vk.h
impeller::gHasValidationLayers
static bool gHasValidationLayers
Definition: context_vk.cc:38
impeller::CommandPoolRecyclerVK::DestroyThreadLocalPools
static void DestroyThreadLocalPools(const ContextVK *context)
Clean up resources held by all per-thread command pools associated with the given context.
Definition: command_pool_vk.cc:244
impeller::Context::BackendType
BackendType
Definition: context.h:49
impeller::ContextVK::IsValid
bool IsValid() const override
Determines if a context is valid. If the caller ever receives an invalid context, they must discard i...
Definition: context_vk.cc:449
impeller::ContextVK::GetInstance
vk::Instance GetInstance() const
Definition: context_vk.cc:476
impeller::PickPhysicalDevice
static std::optional< vk::PhysicalDevice > PickPhysicalDevice(const CapabilitiesVK &caps, const vk::Instance &instance)
Definition: context_vk.cc:44
command_encoder_vk.h
impeller::ContextVK::GetPhysicalDevice
vk::PhysicalDevice GetPhysicalDevice() const
Definition: context_vk.cc:513
impeller::ContextVK::GetResourceAllocator
std::shared_ptr< Allocator > GetResourceAllocator() const override
Returns the allocator used to create textures and buffers on the device.
Definition: context_vk.cc:453
impeller::ContextVK::GetBackendType
BackendType GetBackendType() const override
Get the graphics backend of an Impeller context.
Definition: context_vk.cc:119
impeller::ContextVK::CreateCommandBuffer
std::shared_ptr< CommandBuffer > CreateCommandBuffer() const override
Create a new command buffer. Command buffers can be used to encode graphics, blit,...
Definition: context_vk.cc:469
surface_context_vk.h
validation.h
impeller::GetQueueCreateInfos
static std::vector< vk::DeviceQueueCreateInfo > GetQueueCreateInfos(std::initializer_list< QueueIndexVK > queues)
Definition: context_vk.cc:55
capabilities_vk.h
command_pool_vk.h
impeller::ContextVK::Settings
Definition: context_vk.h:40
command_buffer_vk.h
impeller::ContextVK::CreateSurfaceContext
std::shared_ptr< SurfaceContextVK > CreateSurfaceContext()
Definition: context_vk.cc:501
debug_report_vk.h
impeller::ContextVK::GetShaderLibrary
std::shared_ptr< ShaderLibrary > GetShaderLibrary() const override
Returns the library of shaders used to specify the programmable stages of a pipeline.
Definition: context_vk.cc:457
impeller::ContextVK::GetGraphicsQueue
const std::shared_ptr< QueueVK > & GetGraphicsQueue() const
Definition: context_vk.cc:509
impeller::QueuesVK::graphics_queue
std::shared_ptr< QueueVK > graphics_queue
Definition: queue_vk.h:58
impeller::CapabilitiesVK::GetEnabledDeviceFeatures
std::optional< vk::PhysicalDeviceFeatures > GetEnabledDeviceFeatures(const vk::PhysicalDevice &physical_device) const
Definition: capabilities_vk.cc:286
capabilities.h
impeller::ContextVK::Create
static std::shared_ptr< ContextVK > Create(Settings settings)
Definition: context_vk.cc:92
impeller::CapabilitiesVK
The Vulkan layers and extensions wrangler.
Definition: capabilities_vk.h:30
impeller::CommandBufferVK
Definition: command_buffer_vk.h:18
impeller::ContextVK::SetDebugName
bool SetDebugName(T handle, std::string_view label) const
Definition: context_vk.h:96
impeller::ContextVK::GetCommandPoolRecycler
std::shared_ptr< CommandPoolRecyclerVK > GetCommandPoolRecycler() const
Definition: context_vk.cc:525
impeller::ContextVK
Definition: context_vk.h:36
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:60
impeller::Context::BackendType::kVulkan
@ kVulkan
resource_manager_vk.h
impeller::ContextVK::~ContextVK
~ContextVK() override
Definition: context_vk.cc:112
impeller::ContextVK::GetSamplerLibrary
std::shared_ptr< SamplerLibrary > GetSamplerLibrary() const override
Returns the library of combined image samplers used in shaders.
Definition: context_vk.cc:461
impeller::ContextVK::GetDevice
const vk::Device & GetDevice() const
Definition: context_vk.cc:480
impeller::BackendCast< CapabilitiesVK, Capabilities >::Cast
static CapabilitiesVK & Cast(Capabilities &base)
Definition: backend_cast.h:14
impeller::ContextVK::GetResourceManager
std::shared_ptr< ResourceManagerVK > GetResourceManager() const
Definition: context_vk.cc:521
impeller::PickQueue
static std::optional< QueueIndexVK > PickQueue(const vk::PhysicalDevice &device, vk::QueueFlagBits flags)
Definition: context_vk.cc:78
impeller::ContextVK::GetPipelineLibrary
std::shared_ptr< PipelineLibrary > GetPipelineLibrary() const override
Returns the library of pipelines used by render or compute commands.
Definition: context_vk.cc:465
impeller::ContextVK::DescribeGpuModel
std::string DescribeGpuModel() const override
Definition: context_vk.cc:445
impeller::ContextVK::GetFenceWaiter
std::shared_ptr< FenceWaiterVK > GetFenceWaiter() const
Definition: context_vk.cc:517
impeller::QueueIndexVK::family
size_t family
Definition: queue_vk.h:16
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:94
impeller::ContextVK::SetOffscreenFormat
void SetOffscreenFormat(PixelFormat pixel_format)
Definition: context_vk.cc:440
context_vk.h
impeller::HasValidationLayers
bool HasValidationLayers()
Definition: context_vk.cc:40
impeller::ContextVK::Shutdown
void Shutdown() override
Force all pending asynchronous work to finish. This is achieved by deleting all owned concurrent mess...
Definition: context_vk.cc:489
impeller
Definition: aiks_context.cc:10