Skip to content
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
2 changes: 2 additions & 0 deletions include/nbl/video/IGPUPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include "nbl/asset/IPipeline.h"
#include "nbl/system/to_string.h"

#include <cstddef>

namespace nbl::video
{

Expand Down
126 changes: 68 additions & 58 deletions src/nbl/video/CVulkanPipelineExecutableInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@ inline void populateExecutableInfoFromVulkan(core::vector<IGPUPipelineBase::SExe

// Enumerate executables
uint32_t executableCount = 0;
vk->vk.vkGetPipelineExecutablePropertiesKHR(vkDevice, &pipelineInfo, &executableCount, nullptr);
if (vk->vk.vkGetPipelineExecutablePropertiesKHR(vkDevice, &pipelineInfo, &executableCount, nullptr) != VK_SUCCESS)
return;

if (executableCount == 0)
return;

core::vector<VkPipelineExecutablePropertiesKHR> properties(executableCount);
for (uint32_t i = 0; i < executableCount; ++i)
properties[i] = {VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR, nullptr};
vk->vk.vkGetPipelineExecutablePropertiesKHR(vkDevice, &pipelineInfo, &executableCount, properties.data());
if (vk->vk.vkGetPipelineExecutablePropertiesKHR(vkDevice, &pipelineInfo, &executableCount, properties.data()) != VK_SUCCESS)
return;

outInfo.resize(executableCount);

Expand All @@ -45,78 +47,84 @@ inline void populateExecutableInfoFromVulkan(core::vector<IGPUPipelineBase::SExe
execInfo.executableIndex = i;

uint32_t statCount = 0;
vk->vk.vkGetPipelineExecutableStatisticsKHR(vkDevice, &execInfo, &statCount, nullptr);
if (vk->vk.vkGetPipelineExecutableStatisticsKHR(vkDevice, &execInfo, &statCount, nullptr) != VK_SUCCESS)
statCount = 0;

if (statCount > 0)
{
core::vector<VkPipelineExecutableStatisticKHR> stats(statCount);
for (uint32_t s = 0; s < statCount; ++s)
stats[s] = {VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR, nullptr};
vk->vk.vkGetPipelineExecutableStatisticsKHR(vkDevice, &execInfo, &statCount, stats.data());
if (vk->vk.vkGetPipelineExecutableStatisticsKHR(vkDevice, &execInfo, &statCount, stats.data()) != VK_SUCCESS)
statCount = 0;

info.structuredStatistics.resize(statCount);

// First pass: format name:value pairs (for the human-readable string) and
// fill structuredStatistics in lockstep so callers can pick whichever view
// they need without re-parsing.
core::vector<std::string> nameValues(statCount);
size_t maxNameValueLen = 0;
for (uint32_t s = 0; s < statCount; ++s)
if (statCount > 0)
{
const auto& stat = stats[s];
auto& outStat = info.structuredStatistics[s];
outStat.name = stat.name;
outStat.description = stat.description;

std::string value;
switch (stat.format)
info.structuredStatistics.resize(statCount);

// First pass: format name:value pairs (for the human-readable string) and
// fill structuredStatistics in lockstep so callers can pick whichever view
// they need without re-parsing.
core::vector<std::string> nameValues(statCount);
size_t maxNameValueLen = 0;
for (uint32_t s = 0; s < statCount; ++s)
{
case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR:
outStat.format = IGPUPipelineBase::SExecutableStatistic::FORMAT::BOOL32;
outStat.value.b32 = stat.value.b32 != VK_FALSE;
value = outStat.value.b32 ? "true" : "false";
break;
case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR:
outStat.format = IGPUPipelineBase::SExecutableStatistic::FORMAT::INT64;
outStat.value.i64 = stat.value.i64;
value = std::to_string(stat.value.i64);
break;
case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR:
outStat.format = IGPUPipelineBase::SExecutableStatistic::FORMAT::UINT64;
outStat.value.u64 = stat.value.u64;
value = std::to_string(stat.value.u64);
break;
case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR:
outStat.format = IGPUPipelineBase::SExecutableStatistic::FORMAT::FLOAT64;
outStat.value.f64 = stat.value.f64;
value = std::to_string(stat.value.f64);
break;
default:
// Unknown format: leave structured value zero, keep raw text marker
value = "<unknown format>";
break;
const auto& stat = stats[s];
auto& outStat = info.structuredStatistics[s];
outStat.name = stat.name;
outStat.description = stat.description;

std::string value;
switch (stat.format)
{
case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR:
outStat.format = IGPUPipelineBase::SExecutableStatistic::FORMAT::BOOL32;
outStat.value.b32 = stat.value.b32 != VK_FALSE;
value = outStat.value.b32 ? "true" : "false";
break;
case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR:
outStat.format = IGPUPipelineBase::SExecutableStatistic::FORMAT::INT64;
outStat.value.i64 = stat.value.i64;
value = std::to_string(stat.value.i64);
break;
case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR:
outStat.format = IGPUPipelineBase::SExecutableStatistic::FORMAT::UINT64;
outStat.value.u64 = stat.value.u64;
value = std::to_string(stat.value.u64);
break;
case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR:
outStat.format = IGPUPipelineBase::SExecutableStatistic::FORMAT::FLOAT64;
outStat.value.f64 = stat.value.f64;
value = std::to_string(stat.value.f64);
break;
default:
// Unknown format: leave structured value zero, keep raw text marker
value = "<unknown format>";
break;
}
nameValues[s] = std::string(stat.name) + ": " + value;
maxNameValueLen = std::max(maxNameValueLen, nameValues[s].size());
}
nameValues[s] = std::string(stat.name) + ": " + value;
maxNameValueLen = std::max(maxNameValueLen, nameValues[s].size());
}

// Second pass: emit with aligned columns (unchanged human-readable format)
std::string& statsStr = info.statistics;
for (uint32_t s = 0; s < statCount; ++s)
{
statsStr += nameValues[s];
statsStr.append(maxNameValueLen - nameValues[s].size() + 4, ' ');
statsStr += "// ";
statsStr += stats[s].description;
statsStr += "\n";
// Second pass: emit with aligned columns (unchanged human-readable format)
std::string& statsStr = info.statistics;
for (uint32_t s = 0; s < statCount; ++s)
{
statsStr += nameValues[s];
statsStr.append(maxNameValueLen - nameValues[s].size() + 4, ' ');
statsStr += "// ";
statsStr += stats[s].description;
statsStr += "\n";
}
}
}

// Internal representations
if (includeInternalRepresentations)
{
uint32_t irCount = 0;
vk->vk.vkGetPipelineExecutableInternalRepresentationsKHR(vkDevice, &execInfo, &irCount, nullptr);
if (vk->vk.vkGetPipelineExecutableInternalRepresentationsKHR(vkDevice, &execInfo, &irCount, nullptr) != VK_SUCCESS)
irCount = 0;

if (irCount > 0)
{
Expand All @@ -125,7 +133,8 @@ inline void populateExecutableInfoFromVulkan(core::vector<IGPUPipelineBase::SExe
irs[r] = {VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR, nullptr};

// First call to get sizes
vk->vk.vkGetPipelineExecutableInternalRepresentationsKHR(vkDevice, &execInfo, &irCount, irs.data());
if (vk->vk.vkGetPipelineExecutableInternalRepresentationsKHR(vkDevice, &execInfo, &irCount, irs.data()) != VK_SUCCESS)
continue;

// Allocate data buffers and second call to get data
core::vector<core::vector<char>> irData(irCount);
Expand All @@ -135,7 +144,8 @@ inline void populateExecutableInfoFromVulkan(core::vector<IGPUPipelineBase::SExe
irs[r].pData = irData[r].data();
}

vk->vk.vkGetPipelineExecutableInternalRepresentationsKHR(vkDevice, &execInfo, &irCount, irs.data());
if (vk->vk.vkGetPipelineExecutableInternalRepresentationsKHR(vkDevice, &execInfo, &irCount, irs.data()) != VK_SUCCESS)
continue;

info.structuredInternalRepresentations.resize(irCount);

Expand Down
Loading