shader-slang / slang

Making it easier to work with shaders
MIT License
2.07k stars 177 forks source link

`GetAttributeAtVertex` is not correctly implemented for SPIRV. #4319

Closed chaoticbob closed 3 months ago

chaoticbob commented 3 months ago

This may be related to or is a duplicate of issues #4315, but the validation errors are different.

The shader below is producing SPIR-V that's the following validation error when compiled with Slang:

VUID-VkShaderModuleCreateInfo-pCode-08737(ERROR / SPEC): msgNum: -1520283006 - Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-08737 ] | MessageID = 0xa5625282 | vkCreateShaderModule(): pCreateInfo->pCode (spirv-val produced an error):
The Base <id> '19[%19]' in OpAccessChain instruction must be a pointer.
  %addr = OpAccessChain %_ptr_Input_T %19 %uint_0
. The Vulkan spec states: If pCode is a pointer to SPIR-V code, pCode must adhere to the validation rules described by the Validation Rules within a Module section of the SPIR-V Environment appendix (https://vulkan.lunarg.com/doc/view/1.3.280.0/windows/1.3-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-08737)
    Objects: 0

%19 is the result id of an OpLoad for VertexIndex in this struct:

struct PSInput {
    float4               PositionCS  : SV_POSITION;
    nointerpolation uint VertexIndex : VERTEX_INDEX;
    float3               Bary        : SV_BARYCENTRICS;
};

Slang compilation command:

slangc -target spirv -lang slang -profile ps_6_3 -entry psmain -fvk-use-scalar-layout 119_mesh_shader_vertex_bary_psmain.slang -o 119_mesh_shader_vertex_bary_psmain.spv

The SPIR-V produced by DXC cause the validation error.

Shader Code:


#if defined(__SLANG__)
[UnscopedEnum]
#endif
enum DrawFunc {
    DRAW_FUNC_POSITION  = 0,
    DRAW_FUNC_TEX_COORD = 1,
    DRAW_FUNC_NORMAL    = 2,
    DRAW_FUNC_PHONG     = 3,
};

struct SceneProperties {
    float4x4 InstanceM;
    float4x4 CameraVP;
    float3   EyePosition;
    uint     DrawFunc;
    float3   LightPosition;
};

[[vk::binding(0)]] ConstantBuffer<SceneProperties> Scene : register(b0);

[[vk::binding(1)]] StructuredBuffer<float3>  Positions            : register(t1);
[[vk::binding(2)]] StructuredBuffer<float2>  TexCoords            : register(t2);
[[vk::binding(3)]] StructuredBuffer<float3>  Normals              : register(t3);

struct PSInput {
    float4               PositionCS  : SV_POSITION;
    nointerpolation uint VertexIndex : VERTEX_INDEX;
    float3               Bary        : SV_BARYCENTRICS;
};

[shader("pixel")]
float4 psmain(PSInput input) : SV_TARGET
{
    // Get triangle's vertex indices
    uint vIdx0 = GetAttributeAtVertex(input.VertexIndex, 0);
    uint vIdx1 = GetAttributeAtVertex(input.VertexIndex, 1);
    uint vIdx2 = GetAttributeAtVertex(input.VertexIndex, 2);

    // Interpolate position using barycentrics
    float3 position0 = Positions[vIdx0];
    float3 position1 = Positions[vIdx1];
    float3 position2 = Positions[vIdx2];
    float3 position   = (position0 * input.Bary.x) + (position1 * input.Bary.y) + (position2 * input.Bary.z);
    position = mul(Scene.InstanceM, float4(position, 1.0)).xyz;

    // Interpolate tex coord using barycentrics
    float2 texCoord0 = TexCoords[vIdx0];
    float2 texCoord1 = TexCoords[vIdx1];
    float2 texCoord2 = TexCoords[vIdx2];
    float2 texCoord  = (texCoord0 * input.Bary.x) + (texCoord1 * input.Bary.y) + (texCoord2 * input.Bary.z);

    // Interpolate normal using barycentrics
    float3 normal0 = Normals[vIdx0];
    float3 normal1 = Normals[vIdx1];
    float3 normal2 = Normals[vIdx2];
    float3 normal   = (normal0 * input.Bary.x) + (normal1 * input.Bary.y) + (normal2 * input.Bary.z);
    normal = mul(Scene.InstanceM, float4(normal, 0.0)).xyz;

    float3 color = position;
    if (Scene.DrawFunc == DRAW_FUNC_TEX_COORD) {
        color = float3(texCoord, 0.0);
    }
    else if (Scene.DrawFunc == DRAW_FUNC_NORMAL) {
        color = normal;
    }
    else if (Scene.DrawFunc == DRAW_FUNC_PHONG) {
        float3 V = normalize(Scene.EyePosition - position);
        float3 L = normalize(Scene.LightPosition - position);
        float3 H = normalize(V + L);
        float3 N = normalize(normal);
        float  NoL = saturate(dot(N, L));
        float  NoH = saturate(dot(N, H));

        float d = NoL;
        float s = pow(NoH, 50.0);
        float a = 0.335;

        color = float3(1.000, 0.766, 0.326) * (s + d + a);
    }

    return float4(color, 1);
}
csyonghe commented 3 months ago

The problem is that GetAttributeAtVertex isn't implemented correctly. Will need to add new IR mechanisms to plumb the true global var declaration through.