Open PierreEVEN opened 5 days ago
Maybe you should use getBindingSpace()
like this:
metadata->isParameterLocationUsed(
static_cast<SlangParameterCategory>(parameter->getCategory()),
parameter->getBindingSpace(), // <==== THIS ONE
parameter->getBindingIndex(),
b_is_used);
If you dump the reflection JSON file, it may help you to debug it.
slangc.exe -reflection-json myShader.json myShader.slang
It would help to have a complete reproducer for this issue, so that somebody on the Slang dev team can debug it.
In principle the IMetaData::isParameterLocationUsed
API should work for things like push constants, but to my knowledge this scenario has not been tested before. Thus it is entirely possible that this is a bug in the Slang implementation, but it is also possible that there is some issue in the application code.
Sure ! I've made a short simplified example : (it will fail if 'pc' is not detected as used) (I don't know what kind of format you would prefer for a reproducer)
slang shader :
struct PushConsts
{
float3 data;
};
[[vk::push_constant]] PushConsts pc;
[shader("fragment")]
float3 fragment()
{
return pc.data;
}
c++ code : (tested with msvc / cpp17 / latest slang version)
#include <filesystem>
#include <iostream>
#include <optional>
#include <string>
#include "slang-com-ptr.h"
#include "slang.h"
std::optional<std::string> test_is_parameter_location_used(const std::filesystem::path& module_path)
{
Slang::ComPtr<slang::IBlob> diagnostics;
// CREATE GLOBAL SESSION
Slang::ComPtr<slang::IGlobalSession> global_session;
if (SLANG_FAILED(slang::createGlobalSession(global_session.writeRef())))
return "Failed to create global slang compiler session";
// CREATE SESSION
slang::SessionDesc sessionDesc;
slang::TargetDesc targetDesc;
targetDesc.format = SLANG_SPIRV;
targetDesc.profile = global_session->findProfile("spirv_1_5");
if (targetDesc.profile == SLANG_PROFILE_UNKNOWN)
return "Failed to find slang profile 'spirv_1_5'";
sessionDesc.targets = &targetDesc;
sessionDesc.targetCount = 1;
Slang::ComPtr<slang::ISession> session;
if (SLANG_FAILED(global_session->createSession(sessionDesc, session.writeRef())))
return "Failed to create slang compiler session";
// LOAD EXAMPLE MODULE FROM PATH 'module_path'
slang::IModule* module = session->loadModule(module_path.string().c_str(), diagnostics.writeRef());
if (diagnostics)
return static_cast<const char*>(diagnostics->getBufferPointer());
// ITERATE OVER ENTRY POINTS
for (SlangInt32 ep_i = 0; ep_i < module->getDefinedEntryPointCount(); ++ep_i)
{
Slang::ComPtr<slang::IEntryPoint> entry_point;
if (SLANG_FAILED(module->getDefinedEntryPoint(ep_i, entry_point.writeRef())))
return "Failed to get entry point";
// CREATE COMPOSITE COMPONENT TYPE
std::vector<slang::IComponentType*> components{entry_point};
Slang::ComPtr<slang::IComponentType> program;
if (SLANG_FAILED(
session->createCompositeComponentType(components.data(), components.size(), program.writeRef())))
return "Failed to create stage program";
// LINK PROGRAM
Slang::ComPtr<slang::IComponentType> linked_program;
program->link(linked_program.writeRef(), diagnostics.writeRef());
if (diagnostics)
return static_cast<const char*>(diagnostics->getBufferPointer());
// GET REFLECTION DATA
slang::IMetadata* metadata;
linked_program->getEntryPointMetadata(0, 0, &metadata, diagnostics.writeRef());
if (diagnostics)
return static_cast<const char*>(diagnostics->getBufferPointer());
// ITERATE OVER PARAMETERS
slang::ProgramLayout* shaderReflection = linked_program->getLayout();
for (unsigned par_i = 0; par_i < shaderReflection->getParameterCount(); par_i++)
{
slang::VariableLayoutReflection* parameter = shaderReflection->getParameterByIndex(par_i);
if (parameter->getCategory() == slang::PushConstantBuffer)
{
bool b_is_used = true;
metadata->isParameterLocationUsed(
static_cast<SlangParameterCategory>(parameter->getCategory()),
0,
parameter->getBindingIndex(),
b_is_used);
// In this example, all push constant are used so it should never be false
if (!b_is_used)
return "Error !!!! Push constant parameter '" +
std::string(parameter->getName()) +
"' is not marked as used by the current entry point '" +
entry_point->getFunctionReflection()->getName() +
"' while it should be !";
}
}
}
return {};
}
int main(int argc, char** argv)
{
if (argc != 2) {
std::cerr << "expected slang shader path \n";
return -1;
}
//std::filesystem::path file_path = std::filesystem::path(__FILE__).parent_path() / "test_shader.slang";
std::filesystem::path file_path = argv[1];
if (const auto error = test_is_parameter_location_used(file_path))
{
std::cerr << "ERROR : " << *error << "\n";
return -1;
}
std::cout << "success !!!\n";
}
Hi,
I would like to know if a push constant buffer is used by a given entry point.
I was initially using the hlsl syntax to declare my push constants:
With available reflection functions, the only way I found to know if a given parameter is used is :
which doesn't works as it always return false.
I'm not sure that
isParameterLocationUsed()
is expected to works with push constants, but it's the only available method so I guess there is something missing.here is the full shader : playground-link
And how I use the reflection Api :