Skip to content
Open
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
10 changes: 4 additions & 6 deletions include/nbl/asset/IPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ namespace nbl::asset
Vulkan supports multiple types of pipelines:
- graphics pipeline
- compute pipeline
- TODO: Raytracing
- raytracing pipeline
*/
class IPipelineBase
{
public:
// TODO: tbf these shouldn't even be laying around in `nbl::asset`, we should probably move to `nbl::video::IGPUPipelineBase`
enum class CreationFlags : uint64_t
enum class CreationFlags : uint64_t
{
NONE = 0, // disallowed in maintanance5
DISABLE_OPTIMIZATIONS = 1 << 0,
Expand All @@ -47,10 +47,8 @@ class IPipelineBase
// This is for NV-raytracing extension. Now this is done via IDeferredOperation
//DEFER_COMPILE_NV = 1<<5,

// We use Renderdoc to take care of this for us,
// we won't be parsing the statistics and internal representation ourselves.
//CAPTURE_STATISTICS = 1<<6,
//CAPTURE_INTERNAL_REPRESENTATIONS = 1<<7,
CAPTURE_STATISTICS = 1<<6,
CAPTURE_INTERNAL_REPRESENTATIONS = 1<<7,

// Will soon be deprecated due to
// https://github.com/Devsh-Graphics-Programming/Nabla/issues/854
Expand Down
2 changes: 2 additions & 0 deletions include/nbl/asset/IRayTracingPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class IRayTracingPipelineBase : public virtual core::IReferenceCounted
NO_NULL_MISS_SHADERS = 1<<16,
NO_NULL_INTERSECTION_SHADERS = 1<<17,
ALLOW_MOTION = 1<<20,
CAPTURE_STATISTICS = base_flag(CAPTURE_STATISTICS),
CAPTURE_INTERNAL_REPRESENTATIONS = base_flag(CAPTURE_INTERNAL_REPRESENTATIONS),
};
#undef base_flag

Expand Down
2 changes: 2 additions & 0 deletions include/nbl/video/CVulkanRayTracingPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class CVulkanRayTracingPipeline final : public IGPURayTracingPipeline

inline VkPipeline getInternalObject() const { return m_vkPipeline; }

void populateExecutableInfo(bool includeInternalRepresentations);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add it as a pure virtual protected function in IGPUPipeline


virtual const SShaderGroupHandle& getRaygen() const override;
virtual std::span<const SShaderGroupHandle> getMissHandles() const override;
virtual std::span<const SShaderGroupHandle> getHitHandles() const override;
Expand Down
2 changes: 2 additions & 0 deletions include/nbl/video/IGPUComputePipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class IGPUComputePipeline : public IGPUPipeline<asset::IComputePipeline<const IG
DISPATCH_BASE = 1<<4,
FAIL_ON_PIPELINE_COMPILE_REQUIRED = base_flag(FAIL_ON_PIPELINE_COMPILE_REQUIRED),
EARLY_RETURN_ON_FAILURE = base_flag(EARLY_RETURN_ON_FAILURE),
CAPTURE_STATISTICS = base_flag(CAPTURE_STATISTICS),
CAPTURE_INTERNAL_REPRESENTATIONS = base_flag(CAPTURE_INTERNAL_REPRESENTATIONS),
// Not Supported Yet
//CREATE_LIBRARY = base_flag(CREATE_LIBRARY),
// Not Supported Yet
Expand Down
2 changes: 2 additions & 0 deletions include/nbl/video/IGPUGraphicsPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class IGPUGraphicsPipeline : public IGPUPipeline<asset::IGraphicsPipeline<const
VIEW_INDEX_FROM_DEVICE_INDEX = 1<<3,
FAIL_ON_PIPELINE_COMPILE_REQUIRED = base_flag(FAIL_ON_PIPELINE_COMPILE_REQUIRED),
EARLY_RETURN_ON_FAILURE = base_flag(EARLY_RETURN_ON_FAILURE),
CAPTURE_STATISTICS = base_flag(CAPTURE_STATISTICS),
CAPTURE_INTERNAL_REPRESENTATIONS = base_flag(CAPTURE_INTERNAL_REPRESENTATIONS),
};
#undef base_flag

Expand Down
63 changes: 63 additions & 0 deletions include/nbl/video/IGPUPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "nbl/video/SPipelineCreationParams.h"
#include "nbl/asset/ICPUPipeline.h"
#include "nbl/asset/IPipeline.h"
#include "nbl/system/to_string.h"

namespace nbl::video
{
Expand Down Expand Up @@ -127,6 +128,21 @@ class IGPUPipelineBase {

using SShaderEntryMap = SShaderSpecInfo::entry_map_t;

// Per-executable info from VK_KHR_pipeline_executable_properties
struct SExecutableInfo
{
std::string name;
std::string description;
core::bitflag<hlsl::ShaderStage> stages = hlsl::ShaderStage::ESS_UNKNOWN;
uint32_t subgroupSize = 0;
std::string statistics;
std::string internalRepresentations;
};

inline std::span<const SExecutableInfo> getExecutableInfo() const { return m_executableInfo; }

protected:
core::vector<SExecutableInfo> m_executableInfo;
};

// Common Base class for pipelines
Expand All @@ -146,4 +162,51 @@ class IGPUPipeline : public IBackendObject, public PipelineNonBackendObjectBase,

}

namespace nbl::system::impl
{

template<>
struct to_string_helper<video::IGPUPipelineBase::SExecutableInfo>
{
static std::string __call(const video::IGPUPipelineBase::SExecutableInfo& info)
{
std::string result;
result += "======== ";
result += info.name;
result += " ========\n";
result += info.description;
result += "\nSubgroup Size: ";
result += std::to_string(info.subgroupSize);
if (!info.statistics.empty())
{
result += "\n";
result += info.statistics;
}
if (!info.internalRepresentations.empty())
{
result += "\n";
result += info.internalRepresentations;
}
return result;
}
};

// Another version for core::vector?
template<>
struct to_string_helper<std::span<const video::IGPUPipelineBase::SExecutableInfo>>
{
static std::string __call(const std::span<const video::IGPUPipelineBase::SExecutableInfo>& infos)
{
std::string result;
for (const auto& info : infos)
{
result += to_string_helper<video::IGPUPipelineBase::SExecutableInfo>::__call(info);
result += "\n";
}
return result;
}
};

}

#endif
15 changes: 15 additions & 0 deletions include/nbl/video/ILogicalDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "nbl/video/IGPUCommandBuffer.h"
#include "nbl/video/CThreadSafeQueueAdapter.h"
#include "nbl/video/CJITIncludeLoader.h"
#include "nbl/system/to_string.h"

#include "git_info.h"
#define NBL_LOG_FUNCTION m_logger.log
Expand Down Expand Up @@ -1273,6 +1274,20 @@ class NBL_API2 ILogicalDevice : public core::IReferenceCounted, public IDeviceMe
return {};
}

// CAPTURE_STATISTICS and CAPTURE_INTERNAL_REPRESENTATIONS require pipelineExecutableInfo feature
constexpr auto CaptureStatsFlag = CreationParams::FLAGS::CAPTURE_STATISTICS;
constexpr auto CaptureIRFlag = CreationParams::FLAGS::CAPTURE_INTERNAL_REPRESENTATIONS;
if (ci.getFlags().hasFlags(CaptureStatsFlag) && !getEnabledFeatures().pipelineExecutableInfo)
{
NBL_LOG_ERROR("CAPTURE_STATISTICS flag requires `pipelineExecutableInfo` feature (params[%d])", i);
return {};
}
if (ci.getFlags().hasFlags(CaptureIRFlag) && !getEnabledFeatures().pipelineExecutableInfo)
{
NBL_LOG_ERROR("CAPTURE_INTERNAL_REPRESENTATIONS flag requires `pipelineExecutableInfo` feature (params[%d])", i);
return {};
}

retval += validation;
}
return retval;
Expand Down
7 changes: 7 additions & 0 deletions src/nbl/video/CVulkanComputePipeline.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "nbl/video/CVulkanComputePipeline.h"

#include "nbl/video/CVulkanLogicalDevice.h"
#include "nbl/video/CVulkanPipelineExecutableInfo.h"

namespace nbl::video
{
Expand All @@ -12,6 +13,12 @@ CVulkanComputePipeline::~CVulkanComputePipeline()
vk->vk.vkDestroyPipeline(vulkanDevice->getInternalObject(), m_pipeline, nullptr);
}

void CVulkanComputePipeline::populateExecutableInfo(bool includeInternalRepresentations)
{
const CVulkanLogicalDevice* vulkanDevice = static_cast<const CVulkanLogicalDevice*>(getOriginDevice());
populateExecutableInfoFromVulkan(m_executableInfo, vulkanDevice->getFunctionTable(), vulkanDevice->getInternalObject(), m_pipeline, includeInternalRepresentations);
}

void CVulkanComputePipeline::setObjectDebugName(const char* label) const
{
IBackendObject::setObjectDebugName(label);
Expand Down
4 changes: 3 additions & 1 deletion src/nbl/video/CVulkanComputePipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ class CVulkanComputePipeline final : public IGPUComputePipeline
inline const void* getNativeHandle() const override { return &m_pipeline; }

inline VkPipeline getInternalObject() const { return m_pipeline; }


void populateExecutableInfo(bool includeInternalRepresentations);

void setObjectDebugName(const char* label) const override;

private:
Expand Down
7 changes: 7 additions & 0 deletions src/nbl/video/CVulkanGraphicsPipeline.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
#include "nbl/video/CVulkanGraphicsPipeline.h"

#include "nbl/video/CVulkanLogicalDevice.h"
#include "CVulkanPipelineExecutableInfo.h"

namespace nbl::video
{

void CVulkanGraphicsPipeline::populateExecutableInfo(bool includeInternalRepresentations)
{
const CVulkanLogicalDevice* vulkanDevice = static_cast<const CVulkanLogicalDevice*>(getOriginDevice());
populateExecutableInfoFromVulkan(m_executableInfo, vulkanDevice->getFunctionTable(), vulkanDevice->getInternalObject(), m_vkPipeline, includeInternalRepresentations);
}

CVulkanGraphicsPipeline::~CVulkanGraphicsPipeline()
{
const CVulkanLogicalDevice* vulkanDevice = static_cast<const CVulkanLogicalDevice*>(getOriginDevice());
Expand Down
2 changes: 2 additions & 0 deletions src/nbl/video/CVulkanGraphicsPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class CVulkanGraphicsPipeline final : public IGPUGraphicsPipeline

inline VkPipeline getInternalObject() const {return m_vkPipeline;}

void populateExecutableInfo(bool includeInternalRepresentations);

private:
~CVulkanGraphicsPipeline();

Expand Down
28 changes: 25 additions & 3 deletions src/nbl/video/CVulkanLogicalDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1190,9 +1190,16 @@ void CVulkanLogicalDevice::createComputePipelines_impl(
const VkPipeline vk_pipeline = vk_pipelines[i];
// break the lifetime cause of the aliasing
std::uninitialized_default_construct_n(output+i,1);
output[i] = core::make_smart_refctd_ptr<CVulkanComputePipeline>(
auto pipeline = core::make_smart_refctd_ptr<CVulkanComputePipeline>(
info,vk_pipeline
);
if (info.flags.hasFlags(IGPUComputePipeline::SCreationParams::FLAGS::CAPTURE_STATISTICS))
{
pipeline->populateExecutableInfo(info.flags.hasFlags(IGPUComputePipeline::SCreationParams::FLAGS::CAPTURE_INTERNAL_REPRESENTATIONS));
if (pipeline->getExecutableInfo().empty())
m_logger.log("Driver returned 0 executables for pipeline created with CAPTURE_STATISTICS flag. This pipeline type may not be supported by the driver's VK_KHR_pipeline_executable_properties implementation.", system::ILogger::ELL_WARNING);
}
Comment on lines +1196 to +1201

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's shared validation of pipeline creation parameters we do in ILogicalDevice, put that there

output[i] = std::move(pipeline);
debugNameBuilder.str("");
const auto& specInfo = createInfos[i].shader;
debugNameBuilder << specInfo.shader->getFilepathHint() << "(" << specInfo.entryPoint << "," << hlsl::ShaderStage::ESS_COMPUTE << ")\n";
Expand Down Expand Up @@ -1446,7 +1453,14 @@ void CVulkanLogicalDevice::createGraphicsPipelines_impl(
const VkPipeline vk_pipeline = vk_pipelines[i];
// break the lifetime cause of the aliasing
std::uninitialized_default_construct_n(output+i,1);
output[i] = core::make_smart_refctd_ptr<CVulkanGraphicsPipeline>(createInfos[i],vk_pipeline);
auto pipeline = core::make_smart_refctd_ptr<CVulkanGraphicsPipeline>(createInfos[i],vk_pipeline);
if (createInfo.flags.hasFlags(IGPUGraphicsPipeline::SCreationParams::FLAGS::CAPTURE_STATISTICS))
{
pipeline->populateExecutableInfo(createInfo.flags.hasFlags(IGPUGraphicsPipeline::SCreationParams::FLAGS::CAPTURE_INTERNAL_REPRESENTATIONS));
if (pipeline->getExecutableInfo().empty())
m_logger.log("Driver returned 0 executables for pipeline created with CAPTURE_STATISTICS flag. This pipeline type may not be supported by the driver's VK_KHR_pipeline_executable_properties implementation.", system::ILogger::ELL_WARNING);
}
output[i] = std::move(pipeline);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not call into populateExecutableInfo from the constructors ?

debugNameBuilder.str("");
auto buildDebugName = [&](const IGPUPipelineBase::SShaderSpecInfo& spec, hlsl::ShaderStage stage)
{
Expand Down Expand Up @@ -1651,11 +1665,19 @@ void CVulkanLogicalDevice::createRayTracingPipelines_impl(
const auto success = m_devf.vk.vkGetRayTracingShaderGroupHandlesKHR(m_vkdev, vk_pipeline, 0, handleCount, dataSize, shaderGroupHandles->data()) == VK_SUCCESS;
assert(success);

output[i] = core::make_smart_refctd_ptr<CVulkanRayTracingPipeline>(
auto pipeline = core::make_smart_refctd_ptr<CVulkanRayTracingPipeline>(
createInfos[i],
vk_pipeline,
std::move(shaderGroupHandles)
);

if (info.cached.flags.hasFlags(IGPURayTracingPipeline::SCreationParams::FLAGS::CAPTURE_STATISTICS))
{
pipeline->populateExecutableInfo(info.cached.flags.hasFlags(IGPURayTracingPipeline::SCreationParams::FLAGS::CAPTURE_INTERNAL_REPRESENTATIONS));
if (pipeline->getExecutableInfo().empty())
m_logger.log("Driver returned 0 executables for pipeline created with CAPTURE_STATISTICS flag. This pipeline type may not be supported by the driver's VK_KHR_pipeline_executable_properties implementation.", system::ILogger::ELL_WARNING);
}
output[i] = std::move(pipeline);
}
}
else
Expand Down
Loading
Loading