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

Commit f5ac545

Browse files
authored
[Impeller] Report pipeline creation feedback to logs and traces. (#43227)
Piping the feedback to logs is disabled by default but can be enabled by patching the source for now. If reading from logs gets to be useful, we can move it behind a flag. In traces, enabled by default, pipeline cache hits and misses will be shown via counters. The time taken to create a pipeline variant is already covered by existing traces. This patch also sets up infrastructure in the impeller::CapabilitiesVK to quickly enable optional device extensions. Pipeline feedback will only be reported if the device supports `VK_EXT_pipeline_creation_feedback`. Example of logs: ``` E/flutter ( 2011): >>>>>> E/flutter ( 2011): Pipeline 'GaussianBlurAlphaDecal Pipeline' Time: 48.60ms Cache Hit: 0 Base Accel: 0 Thread: 481449901232 E/flutter ( 2011): Stage 1: Time: 12.91ms Cache Hit: 0 Base Accel: 0 Thread: 481449901232 E/flutter ( 2011): Stage 2: Time: 15.10ms Cache Hit: 0 Base Accel: 0 Thread: 481449901232 E/flutter ( 2011): <<<<<< ```
1 parent de489e3 commit f5ac545

File tree

7 files changed

+222
-30
lines changed

7 files changed

+222
-30
lines changed

impeller/base/timing.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
namespace impeller {
1010

11+
using MillisecondsF = std::chrono::duration<float, std::milli>;
1112
using SecondsF = std::chrono::duration<float>;
1213
using Clock = std::chrono::high_resolution_clock;
1314
using TimePoint = std::chrono::time_point<std::chrono::high_resolution_clock>;

impeller/renderer/backend/vulkan/capabilities_vk.cc

Lines changed: 77 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ bool CapabilitiesVK::AreValidationsEnabled() const {
5454
return enable_validations_;
5555
}
5656

57-
std::optional<std::vector<std::string>> CapabilitiesVK::GetRequiredLayers()
57+
std::optional<std::vector<std::string>> CapabilitiesVK::GetEnabledLayers()
5858
const {
5959
std::vector<std::string> required;
6060

@@ -71,7 +71,7 @@ std::optional<std::vector<std::string>> CapabilitiesVK::GetRequiredLayers()
7171
}
7272

7373
std::optional<std::vector<std::string>>
74-
CapabilitiesVK::GetRequiredInstanceExtensions() const {
74+
CapabilitiesVK::GetEnabledInstanceExtensions() const {
7575
std::vector<std::string> required;
7676

7777
if (!HasExtension("VK_KHR_surface")) {
@@ -150,9 +150,29 @@ CapabilitiesVK::GetRequiredInstanceExtensions() const {
150150
return required;
151151
}
152152

153-
std::optional<std::vector<std::string>>
154-
CapabilitiesVK::GetRequiredDeviceExtensions(
155-
const vk::PhysicalDevice& physical_device) const {
153+
static const char* GetDeviceExtensionName(OptionalDeviceExtensionVK ext) {
154+
switch (ext) {
155+
case OptionalDeviceExtensionVK::kEXTPipelineCreationFeedback:
156+
return VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME;
157+
case OptionalDeviceExtensionVK::kLast:
158+
return "Unknown";
159+
}
160+
return "Unknown";
161+
}
162+
163+
static void IterateOptionalDeviceExtensions(
164+
const std::function<void(OptionalDeviceExtensionVK)>& it) {
165+
if (!it) {
166+
return;
167+
}
168+
for (size_t i = 0;
169+
i < static_cast<uint32_t>(OptionalDeviceExtensionVK::kLast); i++) {
170+
it(static_cast<OptionalDeviceExtensionVK>(i));
171+
}
172+
}
173+
174+
static std::optional<std::set<std::string>> GetSupportedDeviceExtensions(
175+
const vk::PhysicalDevice& physical_device) {
156176
auto device_extensions = physical_device.enumerateDeviceExtensionProperties();
157177
if (device_extensions.result != vk::Result::eSuccess) {
158178
return std::nullopt;
@@ -161,21 +181,42 @@ CapabilitiesVK::GetRequiredDeviceExtensions(
161181
std::set<std::string> exts;
162182
for (const auto& device_extension : device_extensions.value) {
163183
exts.insert(device_extension.extensionName);
184+
};
185+
186+
return exts;
187+
}
188+
189+
std::optional<std::vector<std::string>>
190+
CapabilitiesVK::GetEnabledDeviceExtensions(
191+
const vk::PhysicalDevice& physical_device) const {
192+
auto exts = GetSupportedDeviceExtensions(physical_device);
193+
194+
if (!exts.has_value()) {
195+
return std::nullopt;
164196
}
165197

166-
std::vector<std::string> required;
198+
std::vector<std::string> enabled;
167199

168-
if (exts.find("VK_KHR_swapchain") == exts.end()) {
200+
if (exts->find("VK_KHR_swapchain") == exts->end()) {
169201
VALIDATION_LOG << "Device does not support the swapchain extension.";
170202
return std::nullopt;
171203
}
172-
required.push_back("VK_KHR_swapchain");
204+
enabled.push_back("VK_KHR_swapchain");
173205

174206
// Required for non-conformant implementations like MoltenVK.
175-
if (exts.find("VK_KHR_portability_subset") != exts.end()) {
176-
required.push_back("VK_KHR_portability_subset");
207+
if (exts->find("VK_KHR_portability_subset") != exts->end()) {
208+
enabled.push_back("VK_KHR_portability_subset");
177209
}
178-
return required;
210+
211+
// Enable all optional extensions if the device supports it.
212+
IterateOptionalDeviceExtensions([&](auto ext) {
213+
auto ext_name = GetDeviceExtensionName(ext);
214+
if (exts->find(ext_name) != exts->end()) {
215+
enabled.push_back(ext_name);
216+
}
217+
});
218+
219+
return enabled;
179220
}
180221

181222
static bool HasSuitableColorFormat(const vk::PhysicalDevice& device,
@@ -227,7 +268,7 @@ static bool HasRequiredQueues(const vk::PhysicalDevice& physical_device) {
227268
}
228269

229270
std::optional<vk::PhysicalDeviceFeatures>
230-
CapabilitiesVK::GetRequiredDeviceFeatures(
271+
CapabilitiesVK::GetEnabledDeviceFeatures(
231272
const vk::PhysicalDevice& device) const {
232273
if (!PhysicalDeviceSupportsRequiredFormats(device)) {
233274
VALIDATION_LOG << "Device doesn't support the required formats.";
@@ -244,7 +285,7 @@ CapabilitiesVK::GetRequiredDeviceFeatures(
244285
return std::nullopt;
245286
}
246287

247-
if (!GetRequiredDeviceExtensions(device).has_value()) {
288+
if (!GetEnabledDeviceExtensions(device).has_value()) {
248289
VALIDATION_LOG << "Device doesn't support the required queues.";
249290
return std::nullopt;
250291
}
@@ -282,7 +323,7 @@ void CapabilitiesVK::SetOffscreenFormat(PixelFormat pixel_format) const {
282323
color_format_ = pixel_format;
283324
}
284325

285-
bool CapabilitiesVK::SetDevice(const vk::PhysicalDevice& device) {
326+
bool CapabilitiesVK::SetPhysicalDevice(const vk::PhysicalDevice& device) {
286327
if (HasSuitableDepthStencilFormat(device, vk::Format::eS8Uint)) {
287328
depth_stencil_format_ = PixelFormat::kS8UInt;
288329
} else if (HasSuitableDepthStencilFormat(device,
@@ -307,6 +348,21 @@ bool CapabilitiesVK::SetDevice(const vk::PhysicalDevice& device) {
307348
.supportedOperations &
308349
vk::SubgroupFeatureFlagBits::eArithmetic);
309350

351+
// Determine the optional device extensions this physical device supports.
352+
{
353+
optional_device_extensions_.clear();
354+
auto exts = GetSupportedDeviceExtensions(device);
355+
if (!exts.has_value()) {
356+
return false;
357+
}
358+
IterateOptionalDeviceExtensions([&](auto ext) {
359+
auto ext_name = GetDeviceExtensionName(ext);
360+
if (exts->find(ext_name) != exts->end()) {
361+
optional_device_extensions_.insert(ext);
362+
}
363+
});
364+
}
365+
310366
return true;
311367
}
312368

@@ -348,7 +404,7 @@ bool CapabilitiesVK::SupportsCompute() const {
348404

349405
// |Capabilities|
350406
bool CapabilitiesVK::SupportsComputeSubgroups() const {
351-
// Set by |SetDevice|.
407+
// Set by |SetPhysicalDevice|.
352408
return supports_compute_subgroups_;
353409
}
354410

@@ -381,4 +437,10 @@ CapabilitiesVK::GetPhysicalDeviceProperties() const {
381437
return device_properties_;
382438
}
383439

440+
bool CapabilitiesVK::HasOptionalDeviceExtension(
441+
OptionalDeviceExtensionVK extension) const {
442+
return optional_device_extensions_.find(extension) !=
443+
optional_device_extensions_.end();
444+
}
445+
384446
} // namespace impeller

impeller/renderer/backend/vulkan/capabilities_vk.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ namespace impeller {
1818

1919
class ContextVK;
2020

21+
enum class OptionalDeviceExtensionVK : uint32_t {
22+
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_pipeline_creation_feedback.html
23+
kEXTPipelineCreationFeedback,
24+
kLast,
25+
};
26+
2127
//------------------------------------------------------------------------------
2228
/// @brief The Vulkan layers and extensions wrangler.
2329
///
@@ -32,17 +38,20 @@ class CapabilitiesVK final : public Capabilities,
3238

3339
bool AreValidationsEnabled() const;
3440

35-
std::optional<std::vector<std::string>> GetRequiredLayers() const;
41+
bool HasOptionalDeviceExtension(OptionalDeviceExtensionVK extension) const;
42+
43+
std::optional<std::vector<std::string>> GetEnabledLayers() const;
3644

37-
std::optional<std::vector<std::string>> GetRequiredInstanceExtensions() const;
45+
std::optional<std::vector<std::string>> GetEnabledInstanceExtensions() const;
3846

39-
std::optional<std::vector<std::string>> GetRequiredDeviceExtensions(
47+
std::optional<std::vector<std::string>> GetEnabledDeviceExtensions(
4048
const vk::PhysicalDevice& physical_device) const;
4149

42-
std::optional<vk::PhysicalDeviceFeatures> GetRequiredDeviceFeatures(
50+
std::optional<vk::PhysicalDeviceFeatures> GetEnabledDeviceFeatures(
4351
const vk::PhysicalDevice& physical_device) const;
4452

45-
[[nodiscard]] bool SetDevice(const vk::PhysicalDevice& physical_device);
53+
[[nodiscard]] bool SetPhysicalDevice(
54+
const vk::PhysicalDevice& physical_device);
4655

4756
const vk::PhysicalDeviceProperties& GetPhysicalDeviceProperties() const;
4857

@@ -90,6 +99,7 @@ class CapabilitiesVK final : public Capabilities,
9099
private:
91100
const bool enable_validations_;
92101
std::map<std::string, std::set<std::string>> exts_;
102+
std::set<OptionalDeviceExtensionVK> optional_device_extensions_;
93103
mutable PixelFormat color_format_ = PixelFormat::kUnknown;
94104
PixelFormat depth_stencil_format_ = PixelFormat::kUnknown;
95105
vk::PhysicalDeviceProperties device_properties_;

impeller/renderer/backend/vulkan/context_vk.cc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ static std::optional<vk::PhysicalDevice> PickPhysicalDevice(
4848
const CapabilitiesVK& caps,
4949
const vk::Instance& instance) {
5050
for (const auto& device : instance.enumeratePhysicalDevices().value) {
51-
if (caps.GetRequiredDeviceFeatures(device).has_value()) {
51+
if (caps.GetEnabledDeviceFeatures(device).has_value()) {
5252
return device;
5353
}
5454
}
@@ -149,8 +149,8 @@ void ContextVK::Setup(Settings settings) {
149149

150150
gHasValidationLayers = caps->AreValidationsEnabled();
151151

152-
auto enabled_layers = caps->GetRequiredLayers();
153-
auto enabled_extensions = caps->GetRequiredInstanceExtensions();
152+
auto enabled_layers = caps->GetEnabledLayers();
153+
auto enabled_extensions = caps->GetEnabledInstanceExtensions();
154154

155155
if (!enabled_layers.has_value() || !enabled_extensions.has_value()) {
156156
VALIDATION_LOG << "Device has insufficient capabilities.";
@@ -277,7 +277,7 @@ void ContextVK::Setup(Settings settings) {
277277
/// Create the logical device.
278278
///
279279
auto enabled_device_extensions =
280-
caps->GetRequiredDeviceExtensions(device_holder->physical_device);
280+
caps->GetEnabledDeviceExtensions(device_holder->physical_device);
281281
if (!enabled_device_extensions.has_value()) {
282282
// This shouldn't happen since we already did device selection. But doesn't
283283
// hurt to check again.
@@ -292,9 +292,9 @@ void ContextVK::Setup(Settings settings) {
292292
const auto queue_create_infos = GetQueueCreateInfos(
293293
{graphics_queue.value(), compute_queue.value(), transfer_queue.value()});
294294

295-
const auto required_features =
296-
caps->GetRequiredDeviceFeatures(device_holder->physical_device);
297-
if (!required_features.has_value()) {
295+
const auto enabled_features =
296+
caps->GetEnabledDeviceFeatures(device_holder->physical_device);
297+
if (!enabled_features.has_value()) {
298298
// This shouldn't happen since the device can't be picked if this was not
299299
// true. But doesn't hurt to check.
300300
return;
@@ -304,7 +304,7 @@ void ContextVK::Setup(Settings settings) {
304304

305305
device_info.setQueueCreateInfos(queue_create_infos);
306306
device_info.setPEnabledExtensionNames(enabled_device_extensions_c);
307-
device_info.setPEnabledFeatures(&required_features.value());
307+
device_info.setPEnabledFeatures(&enabled_features.value());
308308
// Device layers are deprecated and ignored.
309309

310310
{
@@ -317,7 +317,7 @@ void ContextVK::Setup(Settings settings) {
317317
device_holder->device = std::move(device_result.value);
318318
}
319319

320-
if (!caps->SetDevice(device_holder->physical_device)) {
320+
if (!caps->SetPhysicalDevice(device_holder->physical_device)) {
321321
VALIDATION_LOG << "Capabilities could not be updated.";
322322
return;
323323
}

impeller/renderer/backend/vulkan/pipeline_cache_vk.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,4 +186,8 @@ void PipelineCacheVK::PersistCacheToDisk() const {
186186
}
187187
}
188188

189+
const CapabilitiesVK* PipelineCacheVK::GetCapabilities() const {
190+
return CapabilitiesVK::Cast(caps_.get());
191+
}
192+
189193
} // namespace impeller

impeller/renderer/backend/vulkan/pipeline_cache_vk.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class PipelineCacheVK {
3131

3232
vk::UniquePipeline CreatePipeline(const vk::ComputePipelineCreateInfo& info);
3333

34+
const CapabilitiesVK* GetCapabilities() const;
35+
3436
void PersistCacheToDisk() const;
3537

3638
private:

0 commit comments

Comments
 (0)