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

[Impeller] Report pipeline creation feedback to logs and traces. #43227

Merged
merged 1 commit into from
Jun 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions impeller/base/timing.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace impeller {

using MillisecondsF = std::chrono::duration<float, std::milli>;
using SecondsF = std::chrono::duration<float>;
using Clock = std::chrono::high_resolution_clock;
using TimePoint = std::chrono::time_point<std::chrono::high_resolution_clock>;
Expand Down
92 changes: 77 additions & 15 deletions impeller/renderer/backend/vulkan/capabilities_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ bool CapabilitiesVK::AreValidationsEnabled() const {
return enable_validations_;
}

std::optional<std::vector<std::string>> CapabilitiesVK::GetRequiredLayers()
std::optional<std::vector<std::string>> CapabilitiesVK::GetEnabledLayers()
const {
std::vector<std::string> required;

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

std::optional<std::vector<std::string>>
CapabilitiesVK::GetRequiredInstanceExtensions() const {
CapabilitiesVK::GetEnabledInstanceExtensions() const {
std::vector<std::string> required;

if (!HasExtension("VK_KHR_surface")) {
Expand Down Expand Up @@ -150,9 +150,29 @@ CapabilitiesVK::GetRequiredInstanceExtensions() const {
return required;
}

std::optional<std::vector<std::string>>
CapabilitiesVK::GetRequiredDeviceExtensions(
const vk::PhysicalDevice& physical_device) const {
static const char* GetDeviceExtensionName(OptionalDeviceExtensionVK ext) {
switch (ext) {
case OptionalDeviceExtensionVK::kEXTPipelineCreationFeedback:
return VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME;
case OptionalDeviceExtensionVK::kLast:
return "Unknown";
}
return "Unknown";
}

static void IterateOptionalDeviceExtensions(
const std::function<void(OptionalDeviceExtensionVK)>& it) {
if (!it) {
return;
}
for (size_t i = 0;
i < static_cast<uint32_t>(OptionalDeviceExtensionVK::kLast); i++) {
it(static_cast<OptionalDeviceExtensionVK>(i));
}
}

static std::optional<std::set<std::string>> GetSupportedDeviceExtensions(
const vk::PhysicalDevice& physical_device) {
auto device_extensions = physical_device.enumerateDeviceExtensionProperties();
if (device_extensions.result != vk::Result::eSuccess) {
return std::nullopt;
Expand All @@ -161,21 +181,42 @@ CapabilitiesVK::GetRequiredDeviceExtensions(
std::set<std::string> exts;
for (const auto& device_extension : device_extensions.value) {
exts.insert(device_extension.extensionName);
};

return exts;
}

std::optional<std::vector<std::string>>
CapabilitiesVK::GetEnabledDeviceExtensions(
const vk::PhysicalDevice& physical_device) const {
auto exts = GetSupportedDeviceExtensions(physical_device);

if (!exts.has_value()) {
return std::nullopt;
}

std::vector<std::string> required;
std::vector<std::string> enabled;

if (exts.find("VK_KHR_swapchain") == exts.end()) {
if (exts->find("VK_KHR_swapchain") == exts->end()) {
VALIDATION_LOG << "Device does not support the swapchain extension.";
return std::nullopt;
}
required.push_back("VK_KHR_swapchain");
enabled.push_back("VK_KHR_swapchain");

// Required for non-conformant implementations like MoltenVK.
if (exts.find("VK_KHR_portability_subset") != exts.end()) {
required.push_back("VK_KHR_portability_subset");
if (exts->find("VK_KHR_portability_subset") != exts->end()) {
enabled.push_back("VK_KHR_portability_subset");
}
return required;

// Enable all optional extensions if the device supports it.
IterateOptionalDeviceExtensions([&](auto ext) {
auto ext_name = GetDeviceExtensionName(ext);
if (exts->find(ext_name) != exts->end()) {
enabled.push_back(ext_name);
}
});

return enabled;
}

static bool HasSuitableColorFormat(const vk::PhysicalDevice& device,
Expand Down Expand Up @@ -227,7 +268,7 @@ static bool HasRequiredQueues(const vk::PhysicalDevice& physical_device) {
}

std::optional<vk::PhysicalDeviceFeatures>
CapabilitiesVK::GetRequiredDeviceFeatures(
CapabilitiesVK::GetEnabledDeviceFeatures(
const vk::PhysicalDevice& device) const {
if (!PhysicalDeviceSupportsRequiredFormats(device)) {
VALIDATION_LOG << "Device doesn't support the required formats.";
Expand All @@ -244,7 +285,7 @@ CapabilitiesVK::GetRequiredDeviceFeatures(
return std::nullopt;
}

if (!GetRequiredDeviceExtensions(device).has_value()) {
if (!GetEnabledDeviceExtensions(device).has_value()) {
VALIDATION_LOG << "Device doesn't support the required queues.";
return std::nullopt;
}
Expand Down Expand Up @@ -282,7 +323,7 @@ void CapabilitiesVK::SetOffscreenFormat(PixelFormat pixel_format) const {
color_format_ = pixel_format;
}

bool CapabilitiesVK::SetDevice(const vk::PhysicalDevice& device) {
bool CapabilitiesVK::SetPhysicalDevice(const vk::PhysicalDevice& device) {
if (HasSuitableDepthStencilFormat(device, vk::Format::eS8Uint)) {
depth_stencil_format_ = PixelFormat::kS8UInt;
} else if (HasSuitableDepthStencilFormat(device,
Expand All @@ -307,6 +348,21 @@ bool CapabilitiesVK::SetDevice(const vk::PhysicalDevice& device) {
.supportedOperations &
vk::SubgroupFeatureFlagBits::eArithmetic);

// Determine the optional device extensions this physical device supports.
{
optional_device_extensions_.clear();
auto exts = GetSupportedDeviceExtensions(device);
if (!exts.has_value()) {
return false;
}
IterateOptionalDeviceExtensions([&](auto ext) {
auto ext_name = GetDeviceExtensionName(ext);
if (exts->find(ext_name) != exts->end()) {
optional_device_extensions_.insert(ext);
}
});
}

return true;
}

Expand Down Expand Up @@ -348,7 +404,7 @@ bool CapabilitiesVK::SupportsCompute() const {

// |Capabilities|
bool CapabilitiesVK::SupportsComputeSubgroups() const {
// Set by |SetDevice|.
// Set by |SetPhysicalDevice|.
return supports_compute_subgroups_;
}

Expand Down Expand Up @@ -381,4 +437,10 @@ CapabilitiesVK::GetPhysicalDeviceProperties() const {
return device_properties_;
}

bool CapabilitiesVK::HasOptionalDeviceExtension(
OptionalDeviceExtensionVK extension) const {
return optional_device_extensions_.find(extension) !=
optional_device_extensions_.end();
}

} // namespace impeller
20 changes: 15 additions & 5 deletions impeller/renderer/backend/vulkan/capabilities_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ namespace impeller {

class ContextVK;

enum class OptionalDeviceExtensionVK : uint32_t {
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_pipeline_creation_feedback.html
kEXTPipelineCreationFeedback,
kLast,
};

//------------------------------------------------------------------------------
/// @brief The Vulkan layers and extensions wrangler.
///
Expand All @@ -32,17 +38,20 @@ class CapabilitiesVK final : public Capabilities,

bool AreValidationsEnabled() const;

std::optional<std::vector<std::string>> GetRequiredLayers() const;
bool HasOptionalDeviceExtension(OptionalDeviceExtensionVK extension) const;

std::optional<std::vector<std::string>> GetEnabledLayers() const;

std::optional<std::vector<std::string>> GetRequiredInstanceExtensions() const;
std::optional<std::vector<std::string>> GetEnabledInstanceExtensions() const;

std::optional<std::vector<std::string>> GetRequiredDeviceExtensions(
std::optional<std::vector<std::string>> GetEnabledDeviceExtensions(
const vk::PhysicalDevice& physical_device) const;

std::optional<vk::PhysicalDeviceFeatures> GetRequiredDeviceFeatures(
std::optional<vk::PhysicalDeviceFeatures> GetEnabledDeviceFeatures(
const vk::PhysicalDevice& physical_device) const;

[[nodiscard]] bool SetDevice(const vk::PhysicalDevice& physical_device);
[[nodiscard]] bool SetPhysicalDevice(
const vk::PhysicalDevice& physical_device);

const vk::PhysicalDeviceProperties& GetPhysicalDeviceProperties() const;

Expand Down Expand Up @@ -90,6 +99,7 @@ class CapabilitiesVK final : public Capabilities,
private:
const bool enable_validations_;
std::map<std::string, std::set<std::string>> exts_;
std::set<OptionalDeviceExtensionVK> optional_device_extensions_;
mutable PixelFormat color_format_ = PixelFormat::kUnknown;
PixelFormat depth_stencil_format_ = PixelFormat::kUnknown;
vk::PhysicalDeviceProperties device_properties_;
Expand Down
18 changes: 9 additions & 9 deletions impeller/renderer/backend/vulkan/context_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ static std::optional<vk::PhysicalDevice> PickPhysicalDevice(
const CapabilitiesVK& caps,
const vk::Instance& instance) {
for (const auto& device : instance.enumeratePhysicalDevices().value) {
if (caps.GetRequiredDeviceFeatures(device).has_value()) {
if (caps.GetEnabledDeviceFeatures(device).has_value()) {
return device;
}
}
Expand Down Expand Up @@ -140,8 +140,8 @@ void ContextVK::Setup(Settings settings) {

gHasValidationLayers = caps->AreValidationsEnabled();

auto enabled_layers = caps->GetRequiredLayers();
auto enabled_extensions = caps->GetRequiredInstanceExtensions();
auto enabled_layers = caps->GetEnabledLayers();
auto enabled_extensions = caps->GetEnabledInstanceExtensions();

if (!enabled_layers.has_value() || !enabled_extensions.has_value()) {
VALIDATION_LOG << "Device has insufficient capabilities.";
Expand Down Expand Up @@ -268,7 +268,7 @@ void ContextVK::Setup(Settings settings) {
/// Create the logical device.
///
auto enabled_device_extensions =
caps->GetRequiredDeviceExtensions(device_holder->physical_device);
caps->GetEnabledDeviceExtensions(device_holder->physical_device);
if (!enabled_device_extensions.has_value()) {
// This shouldn't happen since we already did device selection. But doesn't
// hurt to check again.
Expand All @@ -283,9 +283,9 @@ void ContextVK::Setup(Settings settings) {
const auto queue_create_infos = GetQueueCreateInfos(
{graphics_queue.value(), compute_queue.value(), transfer_queue.value()});

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

device_info.setQueueCreateInfos(queue_create_infos);
device_info.setPEnabledExtensionNames(enabled_device_extensions_c);
device_info.setPEnabledFeatures(&required_features.value());
device_info.setPEnabledFeatures(&enabled_features.value());
// Device layers are deprecated and ignored.

{
Expand All @@ -308,7 +308,7 @@ void ContextVK::Setup(Settings settings) {
device_holder->device = std::move(device_result.value);
}

if (!caps->SetDevice(device_holder->physical_device)) {
if (!caps->SetPhysicalDevice(device_holder->physical_device)) {
VALIDATION_LOG << "Capabilities could not be updated.";
return;
}
Expand Down
4 changes: 4 additions & 0 deletions impeller/renderer/backend/vulkan/pipeline_cache_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,8 @@ void PipelineCacheVK::PersistCacheToDisk() const {
}
}

const CapabilitiesVK* PipelineCacheVK::GetCapabilities() const {
return CapabilitiesVK::Cast(caps_.get());
}

} // namespace impeller
2 changes: 2 additions & 0 deletions impeller/renderer/backend/vulkan/pipeline_cache_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class PipelineCacheVK {

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

const CapabilitiesVK* GetCapabilities() const;

void PersistCacheToDisk() const;

private:
Expand Down
Loading