Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compiler is optimizing unreferenced parameter in CompilerGLSL::type_to_array_glsl and causing linking issues #2338

Open
ArturSchuetz opened this issue Jun 9, 2024 · 6 comments

Comments

@ArturSchuetz
Copy link

ArturSchuetz commented Jun 9, 2024

in file spirv_glsl.cpp you have a definition of this function:

string CompilerGLSL::type_to_array_glsl(const SPIRType &type, uint32_t)
{

as you can see, the second parameter is unnamed and unused. This is causing problems if I try to use this function from outside the library:

59>------ Build started: Project: VulkanRenderDevice, Configuration: Debug x64 ------
57>spirv_cross_c.cpp
58>main.cpp
57>spirv-cross-c.vcxproj -> F:\Projects\long-bow-engine\build\Debug\spirv-cross-cd.lib
58>spirv-cross.vcxproj -> F:\Projects\long-bow-engine\build\Debug\spirv-cross.exe
59>   Creating library F:/Projects/long-bow-engine/build/Debug/VulkanRenderDeviced.lib and object F:/Projects/long-bow-engine/build/Debug/VulkanRenderDeviced.exp
59>BowVulkanShaderProgram.obj : error LNK2001: unresolved external symbol "protected: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl spirv_cross::CompilerGLSL::type_to_array_glsl(struct spirv_cross::SPIRType const &)" (?type_to_array_glsl@CompilerGLSL@spirv_cross@@MEAA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBUSPIRType@2@@Z)
59>F:\Projects\long-bow-engine\build\Debug\VulkanRenderDeviced.dll : fatal error LNK1120: 1 unresolved externals
59>Done building project "VulkanRenderDevice.vcxproj" -- FAILED.

As you can see my compiler is trying to link this function which does not exist:
spirv_cross::CompilerGLSL::type_to_array_glsl(struct spirv_cross::SPIRType const &)

I fixed it for me by declaring and defning a second function, which takes only one parameter:

spirv_glsl.hpp:

virtual std::string type_to_array_glsl(const SPIRType &type);
virtual std::string type_to_array_glsl(const SPIRType &type, uint32_t variable_id);

spirv_glsl.cpp:

string CompilerGLSL::type_to_array_glsl(const SPIRType &type)
{
	return type_to_array_glsl(type, 0);
}

string CompilerGLSL::type_to_array_glsl(const SPIRType &type, uint32_t)
{
@cdavis5e
Copy link
Contributor

Are you sure you declared that method correctly in your own sources? Where is that reference to std::string CompilerGLSL::type_to_array_glsl(const SPIRType &) coming from? Are you attempting to override it?

@ArturSchuetz
Copy link
Author

This is how I used it in my own sources:

#include <spirv_cross/spirv_cross.hpp>
#include <spirv_cross/spirv_glsl.hpp>

ShaderVertexAttributeMap VulkanShaderProgram::FindVertexAttributes(const std::vector<uint32_t> &program)
{
    spirv_cross::CompilerGLSL compiler(program);
    spirv_cross::ShaderResources resources = compiler.get_shader_resources();

    ShaderVertexAttributeMap vertexAttributes;

    LOG_TRACE("Shader Resources: %zu stage inputs found", resources.stage_inputs.size());
    for (const auto &resource : resources.stage_inputs)
    {
        const spirv_cross::SPIRType &type = compiler.get_type(resource.type_id);
        std::string name = compiler.get_name(resource.id);
        uint32_t location = compiler.get_decoration(resource.id, spv::DecorationLocation);

        if (name.empty())
        {
            name = resource.name;
        }

        if (name.rfind("gl_", 0) == 0) // Skip built-in attributes
        {
            continue;
        }

        ShaderVertexAttributeType attributeType = VulkanTypeConverter::ToShaderVertexAttributeType(type);

        LOG_TRACE("\tResource ID: %u, \tName: %s, \tLocation: %d", resource.id, name.c_str(), location);
        vertexAttributes.insert(
            std::make_pair(name, std::make_shared<ShaderVertexAttribute>(location, attributeType, type.vecsize)));
    }
    return vertexAttributes;
}

the first Line of code here already caused this linker error spirv_cross::CompilerGLSL compiler(program);

I am compiling a DLL on Windows with Visual Studio v143 and ISO C++ 17 Standard

@HansKristian-Work
Copy link
Contributor

I have no idea what is going on here. MSVC is built in CI and it links fine there. There are no uses of type_to_array_glsl with one argument in the code base.

@ArturSchuetz
Copy link
Author

I am also quite confused because this method is never called even after I was able to successfully build and run it. But my compiler does not let me build it without this workaround.

@HansKristian-Work
Copy link
Contributor

HansKristian-Work commented Jun 11, 2024

If there is a rational explanation for this, I can consider it, but I won't add a random hack like this without understanding the root cause. Does this reproduce when building SPIRV-Cross as-is?

@ArturSchuetz
Copy link
Author

ArturSchuetz commented Jun 11, 2024

I will investigate this further. I actually used dumpbin to see if the symbol is exported and it actually is, which confuses me even more.
symbols.txt

I don’t expect you to add hacky code. I just wanted to point out that I encountered the problem because it took me a day just to figure out why my compiler is giving me a linker error even though everything seems to be correct.

I just don't understand why my compiler is expecting spirv_cross::CompilerGLSL::type_to_array_glsl(struct spirv_cross::SPIRType const &) instead of spirv_cross::CompilerGLSL::type_to_array_glsl(struct spirv_cross::SPIRType const &, uint32_t). I see that it could be some compiler optimizations because the second parameter is never used and omitted completely by the compiler.

I am actually building my Project using CMake and added the SPIRV-Cross as a submodule into my Project, which could be one factor, which causes this problem. If other people encounter the same problem, at least there is already a quick solution. But I try to look into it and try to understand this linker error.

Building SPIRV-Cross as-is does not causes any problems.
Building my Project, and only including the headers works too.

#include <spirv_cross/spirv_cross.hpp>
#include <spirv_cross/spirv_glsl.hpp>

Only after adding this line of code spirv_cross::CompilerGLSL compiler(program); I get this linker error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants