Coder Social home page Coder Social logo

Comments (9)

csyonghe avatar csyonghe commented on June 12, 2024

It appears to be a data stride / layout issue. I recommend double check the address computation in the generated glsl code and look for how strides are calculated. I suspect something like indexAddress is having a 16 bytes stride instead of 12, or somewhere inside Vertex we are following a different layout than what the data is assumed.

from slang.

csyonghe avatar csyonghe commented on June 12, 2024

In this particular case, it is worth checking the stride for InstanceInfo and Material.
Make sure instInfo.materialID is at least correct.

from slang.

mklefrancois avatar mklefrancois commented on June 12, 2024

I'm using emit-spirv-directly, do you suggest using `SpirV-cross' to generate the GLSL code? In case the stride is different, isn't there a flag in SpirV to do things the same way as GLSL?

Tomorrow I will check if instInfo.materialID contains the right values.

from slang.

csyonghe avatar csyonghe commented on June 12, 2024

Yes, the easiest way is to use spirv-cross to generate glsl and examine the pointer offset.

from slang.

mklefrancois avatar mklefrancois commented on June 12, 2024

I tested spriv-cross on the output, but it generated an error.

SPIRV-Cross threw an exception: VariablePointers capability is not supported in GLSL.

I decided to use -target glsl and not using -emit-spirv-directly . This is generating the same visual error, but I could extract the GLSL code for it.

Here is the GLSL layouts from the Slang output

layout(buffer_reference, buffer_reference_align = 16, std430) readonly buffer BufferPointer_Material_0_3
{ _735 _data; };

layout(buffer_reference, buffer_reference_align = 16, std430) readonly buffer BufferPointer_InstanceInfo_0_4
{ layout(row_major) _753 _data; };

layout(buffer_reference, buffer_reference_align = 16, std430) readonly buffer BufferPointer_PrimMeshInfoSlang_0_8
{ _771 _data; };

layout(buffer_reference, buffer_reference_align = 16, std430) readonly buffer BufferPointer_Vertex_0_5
{ _779 _data; };

layout(buffer_reference, buffer_reference_align = 16, std430) readonly buffer BufferPointer_S6_7
{ uvec3 _data; };

and some structs

layout(buffer_reference, std430) buffer _779
{
    vec3 position_1;
    vec3 normal_0;
    vec2 t_0;
};

layout(buffer_reference, std430) buffer _735
{
    vec3 albedo_0;
    float roughness_0;
    float metallic_0;
};

In the original GLSL code, no buffer_reference_align were defined, so I compiled the GLSL shader to SpirV and spriv-cross back to see how it looks.

Here are the layouts from the working GLSL

layout(buffer_reference, buffer_reference_align = 16, scalar) readonly buffer Vertices
{
    _807 v[];
};

layout(buffer_reference, buffer_reference_align = 4, scalar) readonly buffer Indices
{
    uvec3 i[];
};

layout(buffer_reference, scalar) buffer _807
{
    vec3 position;
    vec3 normal;
    vec2 t;
};

layout(buffer_reference, buffer_reference_align = 16, std430) readonly buffer PrimMeshInfos
{
    _1025 i[];
};

layout(buffer_reference, std430) buffer _1025
{
    uint64_t vertexAddress;
    uint64_t indexAddress;
};

layout(buffer_reference, buffer_reference_align = 4, scalar) readonly buffer Materials
{
    _1129 m[];
};

layout(buffer_reference, buffer_reference_align = 4, scalar) readonly buffer InstanceInfos
{
    _1177 i[];
};

layout(buffer_reference, std430) buffer _1177
{
    mat4 transform;
    int materialID;
};

layout(buffer_reference, std430) buffer _1129
{
    vec3 albedo;
    float roughness;
    float metallic;
};

I can see two things

  • buffer_reference_align = 4 : sometimes it is 4 instead of 16
  • scalar : uses scalar instead of std430, but the -force-glsl-scalar-layout was set when compiling

But the biggest difference is how the data get retrieve

This is the GLSL (spirv-cross from original GLSL)

    Vertices vertices = Vertices(pinfo.vertexAddress);
    Indices indices = Indices(pinfo.indexAddress);
    vec3 barycentrics = vec3((1.0 - barycentricCoords.x) - barycentricCoords.y, barycentricCoords.x, barycentricCoords.y);
    uvec3 triangleIndex = indices.i[primitiveID];
    _807 _851;
    _851.position = vertices.v[triangleIndex.x].position;
    _851.normal = vertices.v[triangleIndex.x].normal;
    _851.t = vertices.v[triangleIndex.x].t;
    _807 v0 = _851;
    _807 _858;
    _858.position = vertices.v[triangleIndex.y].position;
    _858.normal = vertices.v[triangleIndex.y].normal;
    _858.t = vertices.v[triangleIndex.y].t;
    _807 v1 = _858;
    _807 _865;
    _865.position = vertices.v[triangleIndex.z].position;
    _865.normal = vertices.v[triangleIndex.z].normal;
    _865.t = vertices.v[triangleIndex.z].t;
    _807 v2 = _865;
    vec3 pos0 = v0.position;
    vec3 pos1 = v1.position;
    vec3 pos2 = v2.position;

And this is how Slang does it. Note the arithmetic instead of data access.

    float _S9 = barycentricCoords_0.x;
    float _S10 = barycentricCoords_0.y;
    float _S11 = (1.0 - _S9) - _S10;
    uint64_t _S12 = uint64_t(sceneDesc_0._data[0].primInfoAddress_0);
    BufferPointer_PrimMeshInfoSlang_0_8 _S13 = BufferPointer_PrimMeshInfoSlang_0_8(_S12 + uint64_t(int64_t(16 * meshID_0)));
    _771 _848;
    _848.vertexAddress_0._data.position_1 = _S13._data.vertexAddress_0._data.position_1;
    _848.vertexAddress_0._data.normal_0 = _S13._data.vertexAddress_0._data.normal_0;
    _848.vertexAddress_0._data.t_0 = _S13._data.vertexAddress_0._data.t_0;
    _848.indexAddress_0._data = _S13._data.indexAddress_0._data;
    _771 _S14 = _848;
    uint64_t _S15 = uint64_t(_S14.indexAddress_0);
    BufferPointer_S6_7 _S16 = BufferPointer_S6_7(_S15 + uint64_t(int64_t(12 * primitiveID_0)));
    uvec3 _S17 = _S16._data;
    int _S18 = int(_S17.x);
    uint64_t _S19 = uint64_t(_S14.vertexAddress_0);
    BufferPointer_Vertex_0_5 _S20 = BufferPointer_Vertex_0_5(_S19 + uint64_t(int64_t(32 * _S18)));
    _779 _923;
    _923.position_1 = _S20._data.position_1;
    _923.normal_0 = _S20._data.normal_0;
    _923.t_0 = _S20._data.t_0;
    _779 _S21 = _923;
    int _S22 = int(_S17.y);
    uint64_t _S23 = uint64_t(_S14.vertexAddress_0);
    BufferPointer_Vertex_0_5 _S24 = BufferPointer_Vertex_0_5(_S23 + uint64_t(int64_t(32 * _S22)));
    _779 _958;
    _958.position_1 = _S24._data.position_1;
    _958.normal_0 = _S24._data.normal_0;
    _958.t_0 = _S24._data.t_0;
    _779 _S25 = _958;
    int _S26 = int(_S17.z);
    uint64_t _S27 = uint64_t(_S14.vertexAddress_0);
    BufferPointer_Vertex_0_5 _S28 = BufferPointer_Vertex_0_5(_S27 + uint64_t(int64_t(32 * _S26)));
    _779 _993;
    _993.position_1 = _S28._data.position_1;
    _993.normal_0 = _S28._data.normal_0;
    _993.t_0 = _S28._data.t_0;
    _779 _S29 = _993;
    vec3 pos0_0 = _S21.position_1;
    vec3 pos1_0 = _S25.position_1;
    vec3 pos2_0 = _S29.position_1;

It is unclear whether the scalar would solve the issue, as there is a disagreement between stride and alignment. While modifying all structs to be aligned to 16 is possible, it is not always feasible or recommended due to padding constraints. For instance, the indices are packed as uvec3, and changing this would require modifying the data access method.

from slang.

csyonghe avatar csyonghe commented on June 12, 2024

Alignments can be explicitly specified in ConstBufferPointer type as ConstBufferPointer<T, alignment>.
Perhaps try explicitly specify the alignments to 4 in the shader code?

from slang.

mklefrancois avatar mklefrancois commented on June 12, 2024

I tried, by doing the following

    ConstBufferPointer<Material, 4> materialAddress;

But I can see two layouts spitting out for the material, one with an alignment of 4 and one with 16

layout(buffer_reference, std430, buffer_reference_align = 4) readonly buffer BufferPointer_Material_0_3
{
    Material_0 _data;
};

layout(buffer_reference, std430, buffer_reference_align = 16) readonly buffer BufferPointer_Material_0_9
{
    Material_0 _data;
};

and unfortunately, it is using the wrong one

        BufferPointer_Material_0_9 _S66 = (BufferPointer_Material_0_9((_S65 + uint64_t(20 * _S60.materialID_0))));

from slang.

csyonghe avatar csyonghe commented on June 12, 2024

I am adding true/complete pointer support to SPIRV, and will take care of this issue along the way.

from slang.

csyonghe avatar csyonghe commented on June 12, 2024

General pointer type (T*) is now supported.

Currently this is only support on the direct-to-spirv backend. GLSL backend to come.

from slang.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.