problem creating plugin / shader without texture

113 views
Skip to first unread message

Luka Juric

unread,
Jul 5, 2021, 4:58:35 PM7/5/21
to vsg-users : VulkanSceneGraph Developer Discussion Group
Hi All,

More questions came up on my way to understanding VSG.:
Sorry in advance, the questions are rather noobish because I'm new relatively new to C++ and CG programming with Vulkan

1. The Plugin

I tried to write a ReaderWriter, which only implements the reading, like this:

class TestPlugin : vsg::ReaderWriter{
public:
    TestPlugin();

    virtual vsg::ref_ptr<vsg::Object> read(const vsg::Path& /*filename*/, vsg::ref_ptr<const vsg::Options> = {}) const;
    virtual vsg::ref_ptr<vsg::Object> read(std::istream& /*fin*/, vsg::ref_ptr<const vsg::Options> = {}) const;
};

vsg::ref_ptr<vsg::Object> TestPlugin::read(const vsg::Path& filename, vsg::ref_ptr<const vsg::Options> options) const
{
    //implementation one
}

vsg::ref_ptr<vsg::Object> TestPlugin::read(std::istream& stream, vsg::ref_ptr<const vsg::Options> options) const
{
    //implementation two
}

But I can't seem to figure out where to specify which file extension actually corresponds to the plugin (like supportsExtension() in OSG).
Also how do I add it to the options? I tried it like this:

TestPlugin* myPlugin = new TestPlugin;
auto options = vsg::Options::create();
options->readerWriters.push_back(static_cast<vsg::ref_ptr<vsg::ReaderWriter>>(myPlugin));

but it tells me 'type cast': conversion from 'R *' to 'T *' exists, but is inaccessible.   
when I change the inheritence from
class TestPlugin : vsg::ReaderWriter
to
class TestPlugin : public vsg::ReaderWriter
I get a linking error.


2. the vsgdraw example / shaders in VSG

The following problem contains much text, but is also rather simple.
I tried to modify the vsgdraw example to not use a texture, but just one gray-scale float-color per vertex. So I started building a basic shader for that, using the given shaders in vsgExamples, but I noticed the following:
the source code uses the vert_PushConstants.spv and frag_PushConstants.spv. I assumed they are compiled from shader_PushConstants.frag and shader_PushConstants.vert,
but if I compile the exact same sources to the spv format myself (using vsgconv) and use them, I get an access violation error in VSG, not with the given spv's tho.
Also the compiled files differ by a fraction of a KB, so i assume they stem from a slightly different source, which I would need to have an example of how to structure own shaders to use in VSG.

Here is the shader source code for what I tried to do:
Vertex:

#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 float inColor;

layout(location = 0) out float fragColor;

out gl_PerVertex {
    vec4 gl_Position;
};

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


Fragment:
#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(location = 0) in float fragColor;

void main() {
    outColor = vec4(vec3(fragColor),1.0f);
}


The source code is basically the vsgdraw example, but i removed the descriptors
for the texture since I don't use one:

auto pipelineLayout = vsg::PipelineLayout::create(vsg::DescriptorSetLayouts{ }, pushConstantRanges);

also I modified the bindings and attributes to only use the vert position (vsg::vec3Array) + color (vsg::floatArray) which I pass with the BindVertexBuffers.
I get an error when I try to add my source as an attachment, so I'll add it as a comment on this thread. The code is even shorter than the vsgdraw example, but I really can't figure it out.
I assume that I didn't set up the pipeline correctly.

Thank you all very much in advance,

Luke
Message has been deleted

Luka Juric

unread,
Jul 5, 2021, 5:01:07 PM7/5/21
to vsg-users : VulkanSceneGraph Developer Discussion Group
#include <iostream>
#include <vsg/all.h>


int main(int argc, char** argv)
{
    // set up defaults and read command line arguments to override them
    vsg::CommandLine arguments(&argc, argv);

    auto windowTraits = vsg::WindowTraits::create();
    windowTraits->debugLayer = arguments.read({ "--debug", "-d" });
    windowTraits->apiDumpLayer = arguments.read({ "--api", "-a" });
    arguments.read({ "--window", "-w" }, windowTraits->width, windowTraits->height);

    if (arguments.errors()) return arguments.writeErrorMessages(std::cerr);

    // set up search paths to SPIRV shaders and textures
    vsg::Paths searchPaths = vsg::getEnvPaths("VSG_FILE_PATH");

    // load shaders
    vsg::ref_ptr<vsg::ShaderStage> vertexShader = vsg::ShaderStage::read(VK_SHADER_STAGE_VERTEX_BIT, "main", "C:/myshader_vert.spv");
    vsg::ref_ptr<vsg::ShaderStage> fragmentShader = vsg::ShaderStage::read(VK_SHADER_STAGE_FRAGMENT_BIT, "main", "C:/myshader_frag.spv");
    if (!vertexShader || !fragmentShader)
    {
        std::cout << "Could not create shaders." << std::endl;
        return 1;
    }


    vsg::PushConstantRanges pushConstantRanges{
        {VK_SHADER_STAGE_VERTEX_BIT, 0, 128} // projection view, and model matrices, actual push constant calls autoaatically provided by the VSG's DispatchTraversal
    };

    vsg::VertexInputState::Bindings vertexBindingsDescriptions{
        VkVertexInputBindingDescription{0, sizeof(vsg::vec3), VK_VERTEX_INPUT_RATE_VERTEX}, // vertex data
        VkVertexInputBindingDescription{1, sizeof(float), VK_VERTEX_INPUT_RATE_VERTEX}, // grayscale colour data
    };

    vsg::VertexInputState::Attributes vertexAttributeDescriptions{
        VkVertexInputAttributeDescription{0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0}, // vertex data
        VkVertexInputAttributeDescription{1, 1, VK_FORMAT_R32_SFLOAT, 0}  // grayscale colour data
    };


    vsg::GraphicsPipelineStates pipelineStates{
        vsg::VertexInputState::create(vertexBindingsDescriptions, vertexAttributeDescriptions),
        vsg::InputAssemblyState::create(),
        vsg::RasterizationState::create(),
        vsg::MultisampleState::create(),
        vsg::ColorBlendState::create(),
        vsg::DepthStencilState::create() };


    auto pipelineLayout = vsg::PipelineLayout::create(vsg::DescriptorSetLayouts{ }, pushConstantRanges);
    auto graphicsPipeline = vsg::GraphicsPipeline::create(pipelineLayout, vsg::ShaderStages{ vertexShader, fragmentShader }, pipelineStates);
    auto bindGraphicsPipeline = vsg::BindGraphicsPipeline::create(graphicsPipeline);

    // create StateGroup as the root of the scene/command graph to hold the GraphicsProgram
    auto scenegraph = vsg::StateGroup::create();
    scenegraph->add(bindGraphicsPipeline);

    // set up model transformation node
    auto transform = vsg::MatrixTransform::create(); // VK_SHADER_STAGE_VERTEX_BIT

    // add transform to root of the scene graph
    scenegraph->addChild(transform);

    // set up vertex and index arrays
    auto vertices = vsg::vec3Array::create(
        { {-0.5f, -0.5f, 0.0f},
         {0.5f, -0.5f, 0.0f},
         {0.5f, 0.5f, 0.0f},
         {-0.5f, 0.5f, 0.0f}}); // VK_FORMAT_R32G32B32_SFLOAT, VK_VERTEX_INPUT_RATE_INSTANCE, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_SHARING_MODE_EXCLUSIVE

    auto grayscale_colors = vsg::floatArray::create(
        { 0.1f, 0.5f, 1.0f, 0.3f });

    auto indices = vsg::ushortArray::create(
        { 0, 1, 2,
         2, 3, 0 }); // VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_SHARING_MODE_EXCLUSIVE

    // setup geometry
    auto drawCommands = vsg::Commands::create();
    drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{ vertices, grayscale_colors }));
    drawCommands->addChild(vsg::BindIndexBuffer::create(indices));
    drawCommands->addChild(vsg::DrawIndexed::create(6, 1, 0, 0, 0));

    // add drawCommands to transform
    transform->addChild(drawCommands);

    // create the viewer and assign window(s) to it
    auto viewer = vsg::Viewer::create();

    auto window = vsg::Window::create(windowTraits);
    if (!window)
    {
        std::cout << "Could not create windows." << std::endl;
        return 1;
    }

    viewer->addWindow(window);

    // camera related details
    auto viewport = vsg::ViewportState::create(0, 0, window->extent2D().width, window->extent2D().height);
    auto perspective = vsg::Perspective::create(60.0, static_cast<double>(window->extent2D().width) / static_cast<double>(window->extent2D().height), 0.1, 10.0);
    auto lookAt = vsg::LookAt::create(vsg::dvec3(1.0, 1.0, 1.0), vsg::dvec3(0.0, 0.0, 0.0), vsg::dvec3(0.0, 0.0, 1.0));
    auto camera = vsg::Camera::create(perspective, lookAt, viewport);

    auto commandGraph = vsg::createCommandGraphForView(window, camera, scenegraph);
    viewer->assignRecordAndSubmitTaskAndPresentation({ commandGraph });

    // compile the Vulkan objects
    viewer->compile();

    // assign a CloseHandler to the Viewer to respond to pressing Escape or press the window close button
    viewer->addEventHandlers({ vsg::CloseHandler::create(viewer) });

    // main frame loop
    while (viewer->advanceToNextFrame())
    {
        // pass any events into EventHandlers assigned to the Viewer
        viewer->handleEvents();

        // animate the transform
        float time = std::chrono::duration<float, std::chrono::seconds::period>(viewer->getFrameStamp()->time - viewer->start_point()).count();
        transform->setMatrix(vsg::rotate(time * vsg::radians(90.0f), vsg::vec3(0.0f, 0.0, 1.0f)));

        viewer->update();

        viewer->recordAndSubmit();

        viewer->present();
    }

    // clean up done automatically thanks to ref_ptr<>
    return 0;

Robert Osfield

unread,
Jul 5, 2021, 5:46:30 PM7/5/21
to vsg-...@googlegroups.com
Hi Like,

I'm only on my laptop briefly so a quick reply.

For item 1. In C++ you can't cast a C pointer to smart pointer so the compiler is saving you from a memory management mess.

To help with robust dynamic memory management the VSG provide vsg::Inherit template class that implements members functions such as T::create(..) for you, returning a ref_ptr<T> so you do:

{
  auto group = vsg::Group::create();  // group will be a vsg::ref_ptr<vsg::Group> with a ref count of 1.
} // ref_ptr<> will destruct the group automatically for you unless you add another ref to it.

There is much more to smart pointers besides this, but hopefully it will help you along the way.

Cheers,
Robert.

Luka Juric

unread,
Jul 6, 2021, 2:38:48 PM7/6/21
to vsg-users : VulkanSceneGraph Developer Discussion Group
Thank you very much Robert,

Apparently there is an issue with ShaderStage::create / vsgconv, if I compile my shaders with them, VSG breaks.
If I compile them with glslangValidator and use  ShaderStage::read, it works just fine. Nothing wrong with removing the descriptors & sampler for the texture.
I created an issue in the VSG github.

Cheers,
Luka.
Reply all
Reply to author
Forward
0 new messages