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:
parent
ab206d6378
commit
3b006f4fe2
19 changed files with 307 additions and 24 deletions
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue