Skip to content

Unable to mix string literal shader and filesystem shader #314

@sbrkopac

Description

@sbrkopac

Describe the bug
I moved the vert_PushConstants.spv into a string literal. When loading up the vertex shader as a string literal but leaving the fragment shader loading from the filesystem, VSG seems to lose the fragment shader. I think this is due to VSG converting the fragment shader to SPIRV and not the vertex shader.

To Reproduce

std::string vert_PushConstants = R"(#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(push_constant) uniform PushConstants {
    mat4 projection;
    mat4 modelview;
} pc;

layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 2) in vec2 inTexCoord;

layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec2 fragTexCoord;

out gl_PerVertex {
    vec4 gl_Position;
};

void main() {
    gl_Position = (pc.projection * pc.modelview) * vec4(inPosition, 1.0);
    fragColor = inColor;
    fragTexCoord = inTexCoord;
}
)";

auto dataPath = std::filesystem::current_path() / "data";

// set up search paths and load shaders
vsg::Paths searchPaths = { dataPath.string() };

 // set up search paths and load shaders
vsg::ref_ptr<vsg::ShaderStage> vertexShader = vsg::ShaderStage::create(VK_SHADER_STAGE_VERTEX_BIT, "main", vert_PushConstants);
vsg::ref_ptr<vsg::ShaderStage> fragmentShader = vsg::ShaderStage::read(VK_SHADER_STAGE_FRAGMENT_BIT, "main", vsg::findFile("shaders/frag_PushConstants.spv", searchPaths));
if (!vertexShader || !fragmentShader)
{
    log->error("Could not create shaders.");
}

Expected behavior
I would expect that the program would compile as it does when loading both from the filesystem

Screenshots



Vertex Shader:

   1: #version 450
   2: #extension GL_ARB_separate_shader_objects : enable
   3:
   4: layout(push_constant) uniform PushConstants {
   5:     mat4 projection;
   6:     mat4 modelview;
   7: } pc;
   8:
   9: layout(location = 0) in vec3 inPosition;
  10: layout(location = 1) in vec3 inColor;
  11: layout(location = 2) in vec2 inTexCoord;
  12:
  13: layout(location = 0) out vec3 fragColor;
  14: layout(location = 1) out vec2 fragTexCoord;
  15:
  16: out gl_PerVertex {
  17:     vec4 gl_Position;
  18: };
  19:
  20: void main() {
  21:     gl_Position = (pc.projection * pc.modelview) * vec4(inPosition, 1.0);
  22:     fragColor = inColor;
  23:     fragTexCoord = inTexCoord;
  24: }


Fragment Shader:


Warning: Program failed to link.
glslang info log:
ERROR: Linking fragment stage: Missing entry point: Each stage requires one entry point
glslang debug info log:
--------

Desktop (please complete the following information):

  • OS: Win10
  • VSDK: 1.2.182.0
  • Visual Studio 2019

Additional context
I worked around the problem by duplicating how VSG loads a shader from the filesystem:

template<typename T>
bool read(T& buffer, const std::string& input)
{
    using value_type = typename T::value_type;
    size_t valueSize = sizeof(value_type);
    size_t bufferSize = (input.size() + valueSize) / valueSize;

    buffer.resize(bufferSize);

    std::istringstream stream(input);
    stream.read(reinterpret_cast<char*>(buffer.data()), input.size());

    return true;
}

And then I was able to do the following:

vsg::ShaderModule::SPIRV spirv_vert_PushConstants; read(spirv_vert_PushConstants, vert_PushConstants);
vsg::ref_ptr<vsg::ShaderStage> vertexShader = vsg::ShaderStage::create(VK_SHADER_STAGE_VERTEX_BIT, "main", vert_PushConstants, spirv_vert_PushConstants);
vsg::ref_ptr<vsg::ShaderStage> fragmentShader = vsg::ShaderStage::read(VK_SHADER_STAGE_FRAGMENT_BIT, "main", vsg::findFile("shaders/frag_PushConstants.spv", searchPaths));

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions