shader-slang / slang

Making it easier to work with shaders
MIT License
2.07k stars 177 forks source link

glslang error when passing matrices between stages #1553

Closed Dynamitos closed 4 years ago

Dynamitos commented 4 years ago

I'm trying to use slang to cross-compile a .slang shader to SPIR-V for Vulkan using the API. I have identified the problem to a struct which contains two 3x3 matrices, which is passed from the vertex to the pixel stage.

[shader("vertex")]
VertexStageOutput vertexMain( //VertexStageOutput contains 2 3x3 matrices
    VertexShaderInput input)
{

The slang compilation works with no problem, but when it is passed to glslang it gives the following error: glslang: ERROR: shaders/lib/StaticMeshVertexInput.slang:201: 'layout' : matrix or packing qualifiers can only be used on a uniform or buffer

After a bit of debugging and looking through the slang-dump, i found these lines:

layout(row_major)
layout(location = 5)
out mat3x3 _S19;

layout(row_major)
layout(location = 8)
out mat3x3 _S20;

When removing the row_major qualifier, and rerunning glslangValidator(provided by the Vulkan SDK) manually, it compiles with no problem.

For additional context, here is the C++ code used to generate this:

static SlangSession* session = spCreateSession(NULL);

SlangCompileRequest* request = spCreateCompileRequest(session);
int targetIndex = spAddCodeGenTarget(request, SLANG_SPIRV);
spSetTargetProfile(request, targetIndex, spFindProfile(session, "glsl_vk"));
spSetDumpIntermediates(request, true);
int translationUnitIndex = spAddTranslationUnit(request, SLANG_SOURCE_LANGUAGE_SLANG, "");

for(auto code : createInfo.shaderCode)
{
    spAddTranslationUnitSourceString(
        request,
        translationUnitIndex,
        entryPointName.c_str(),
        code.data()
    );
}
for(auto define : createInfo.defines)
{
    spAddPreprocessorDefine(request, define.key, define.value);
}
spAddSearchPath(request, "shaders/lib/");
spAddSearchPath(request, "shaders/generated/");

spSetGlobalGenericArgs(request, createInfo.typeParameter.size(), createInfo.typeParameter.data());

int entryPointIndex = spAddEntryPoint(request, translationUnitIndex, entryPointName.c_str(), getStageFromShaderType(type));
if(spCompile(request))
{
    char const* diagnostics = spGetDiagnosticOutput(request);
    std::cout << diagnostics << std::endl;
}
tangent-vector commented 4 years ago

Thanks for letting us know about this issue.

The simplest workaround for now would be to not use matrix types in your vertex-to-fragment structure, and instead either use multiple vectors (or an array of vectors).

There are a few other issues around matrix support for the GLSL/SPIR-V targets that are worth noting. In particular, matrixes with integer elements are not supported at this time.

Dynamitos commented 4 years ago

Thanks for the fast response, honestly didnt expect one till monday.

I worked around it using arrays of vectors and replacing direct access with a getter, which constructs a 3x3 matrix in place, so only minimal coding effort was required. As for if this will impact performance, since additional function calls are involved, I'm not sure, but I'm still far away from the point of having to worry about that, so it's definitely no problem for now.

naomipappe commented 3 months ago

As of 29.06.2024 this issue still persists when compiling from slangc to GLSL / SPIRV