renderer_vulkan: Add setting to log pipeline statistics

Use VK_KHR_pipeline_executable_properties when enabled and available to
log statistics about the pipeline cache in a game.

For example, this is on Turing GPUs when generating a pipeline cache
from Super Smash Bros. Ultimate:

Average pipeline statistics
==========================================
Code size:       6433.167
Register count:    32.939

More advanced results could be presented, at the moment it's just an
average of all 3D and compute pipelines.
This commit is contained in:
ReinUsesLisp 2021-07-27 19:15:32 -03:00
parent ab206d6378
commit 3b006f4fe2
19 changed files with 307 additions and 24 deletions

View file

@ -526,6 +526,17 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
SetNext(next, workgroup_layout);
}
VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR executable_properties;
if (khr_pipeline_executable_properties) {
LOG_INFO(Render_Vulkan, "Enabling shader feedback, expect slower shader build times");
executable_properties = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR,
.pNext = nullptr,
.pipelineExecutableInfo = VK_TRUE,
};
SetNext(next, executable_properties);
}
if (!ext_depth_range_unrestricted) {
LOG_INFO(Render_Vulkan, "Device doesn't support depth range unrestricted");
}
@ -824,6 +835,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
bool has_khr_shader_float16_int8{};
bool has_khr_workgroup_memory_explicit_layout{};
bool has_khr_pipeline_executable_properties{};
bool has_ext_subgroup_size_control{};
bool has_ext_transform_feedback{};
bool has_ext_custom_border_color{};
@ -878,6 +890,10 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
test(nv_device_diagnostics_config, VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME,
true);
}
if (Settings::values.renderer_shader_feedback) {
test(has_khr_pipeline_executable_properties,
VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME, false);
}
}
VkPhysicalDeviceFeatures2KHR features{};
features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
@ -1033,6 +1049,19 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
khr_workgroup_memory_explicit_layout = true;
}
}
if (has_khr_pipeline_executable_properties) {
VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR executable_properties;
executable_properties.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR;
executable_properties.pNext = nullptr;
features.pNext = &executable_properties;
physical.GetFeatures2KHR(features);
if (executable_properties.pipelineExecutableInfo) {
extensions.push_back(VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME);
khr_pipeline_executable_properties = true;
}
}
if (khr_push_descriptor) {
VkPhysicalDevicePushDescriptorPropertiesKHR push_descriptor;
push_descriptor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR;

View file

@ -214,6 +214,11 @@ public:
return khr_push_descriptor;
}
/// Returns true if VK_KHR_pipeline_executable_properties is enabled.
bool IsKhrPipelineEexecutablePropertiesEnabled() const {
return khr_pipeline_executable_properties;
}
/// Returns true if the device supports VK_KHR_workgroup_memory_explicit_layout.
bool IsKhrWorkgroupMemoryExplicitLayoutSupported() const {
return khr_workgroup_memory_explicit_layout;
@ -378,6 +383,7 @@ private:
bool khr_spirv_1_4{}; ///< Support for VK_KHR_spirv_1_4.
bool khr_workgroup_memory_explicit_layout{}; ///< Support for explicit workgroup layouts.
bool khr_push_descriptor{}; ///< Support for VK_KHR_push_descritor.
bool khr_pipeline_executable_properties{}; ///< Support for executable properties.
bool ext_index_type_uint8{}; ///< Support for VK_EXT_index_type_uint8.
bool ext_sampler_filter_minmax{}; ///< Support for VK_EXT_sampler_filter_minmax.
bool ext_depth_range_unrestricted{}; ///< Support for VK_EXT_depth_range_unrestricted.

View file

@ -181,6 +181,8 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkGetMemoryWin32HandleKHR);
#endif
X(vkGetQueryPoolResults);
X(vkGetPipelineExecutablePropertiesKHR);
X(vkGetPipelineExecutableStatisticsKHR);
X(vkGetSemaphoreCounterValueKHR);
X(vkMapMemory);
X(vkQueueSubmit);
@ -809,6 +811,42 @@ VkMemoryRequirements Device::GetImageMemoryRequirements(VkImage image) const noe
return requirements;
}
std::vector<VkPipelineExecutablePropertiesKHR> Device::GetPipelineExecutablePropertiesKHR(
VkPipeline pipeline) const {
const VkPipelineInfoKHR info{
.sType = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR,
.pNext = nullptr,
.pipeline = pipeline,
};
u32 num{};
dld->vkGetPipelineExecutablePropertiesKHR(handle, &info, &num, nullptr);
std::vector<VkPipelineExecutablePropertiesKHR> properties(num);
for (auto& property : properties) {
property.sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR;
}
Check(dld->vkGetPipelineExecutablePropertiesKHR(handle, &info, &num, properties.data()));
return properties;
}
std::vector<VkPipelineExecutableStatisticKHR> Device::GetPipelineExecutableStatisticsKHR(
VkPipeline pipeline, u32 executable_index) const {
const VkPipelineExecutableInfoKHR executable_info{
.sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR,
.pNext = nullptr,
.pipeline = pipeline,
.executableIndex = executable_index,
};
u32 num{};
dld->vkGetPipelineExecutableStatisticsKHR(handle, &executable_info, &num, nullptr);
std::vector<VkPipelineExecutableStatisticKHR> statistics(num);
for (auto& statistic : statistics) {
statistic.sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR;
}
Check(dld->vkGetPipelineExecutableStatisticsKHR(handle, &executable_info, &num,
statistics.data()));
return statistics;
}
void Device::UpdateDescriptorSets(Span<VkWriteDescriptorSet> writes,
Span<VkCopyDescriptorSet> copies) const noexcept {
dld->vkUpdateDescriptorSets(handle, writes.size(), writes.data(), copies.size(), copies.data());

View file

@ -295,6 +295,8 @@ struct DeviceDispatch : InstanceDispatch {
#ifdef _WIN32
PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR{};
#endif
PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR{};
PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR{};
PFN_vkGetQueryPoolResults vkGetQueryPoolResults{};
PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR{};
PFN_vkMapMemory vkMapMemory{};
@ -879,6 +881,12 @@ public:
VkMemoryRequirements GetImageMemoryRequirements(VkImage image) const noexcept;
std::vector<VkPipelineExecutablePropertiesKHR> GetPipelineExecutablePropertiesKHR(
VkPipeline pipeline) const;
std::vector<VkPipelineExecutableStatisticKHR> GetPipelineExecutableStatisticsKHR(
VkPipeline pipeline, u32 executable_index) const;
void UpdateDescriptorSets(Span<VkWriteDescriptorSet> writes,
Span<VkCopyDescriptorSet> copies) const noexcept;