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

Shanq bindings don't support non-matrix types #64

Open
idg10 opened this issue Feb 17, 2021 · 0 comments
Open

Shanq bindings don't support non-matrix types #64

idg10 opened this issue Feb 17, 2021 · 0 comments

Comments

@idg10
Copy link

idg10 commented Feb 17, 2021

The UniformBuffers example in the SharpVk-Samples repo defines this type to enable the application to pass arguments into the shaders:

private struct UniformBufferObject
{
    public mat4 Model;
    public mat4 View;
    public mat4 Proj;
};

This works but if you try to extend it by adding an additional field of type float, it goes wrong. There's no runtime error, but the shader ends up picking up data from the wrong offset within this structure.

This turns out to be because the code in ShanqQueryExecutor that works through all the fields in all the bindings only emits the offset of the field if the field is of a matrix type:

foreach (var field in type.GetFieldsByOffset())
{
expressionVisitor.AddBinding(field, Tuple.Create(uniformVariableId, fieldIndex));
if (this.vectorLibrary.IsMatrixType(field.FieldType))
{
//HACK Should adapt to different matrix formats
file.AddAnnotationStatement(Op.OpMemberDecorate, structureTypeId, fieldIndex, Decoration.ColMajor);
file.AddAnnotationStatement(Op.OpMemberDecorate, structureTypeId, fieldIndex, Decoration.Offset, Marshal.OffsetOf(type, field.Name).ToInt32());
file.AddAnnotationStatement(Op.OpMemberDecorate, structureTypeId, fieldIndex, Decoration.MatrixStride, 16);
}
fieldIndex++;
}

So if you add, say, a float field, the GPU ends up thinking it needs to look at offset 0.

As a quick hack I just added this else to the if in that loop:

else
{
    file.AddAnnotationStatement(Op.OpMemberDecorate, structureTypeId, fieldIndex, Decoration.Offset, Marshal.OffsetOf(type, field.Name).ToInt32());
}

(or you could just move the relevant line out of the if I suppose, but I was trying to not to spread changes out across too much code).

With that in place, you can now do something like this:

private struct UniformBufferObject
{
    public mat4 Model;
    public mat4 View;
    public mat4 Proj;
    public float Level;
};

and then access this from, e.g. a vertex shader:

from input in shanq.GetInput<Vertex>()
from ubo in shanq.GetBinding<UniformBufferObject>(0)
let transform = ubo.Proj * ubo.View * ubo.Model
select new VertexOutput
{
    Position = transform * new vec4(input.Position, 0, 1),
    Colour = input.Colour * ubo.Level
});

This seems to work. But if there's some reason only matrix types should be used here, then the query exector should probably have an else branch there throwing an exception to say that other types are not supported.

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

1 participant