GameTechDev / SPIRV-Cross

An experimental ISPC backend for SPIRV-Cross
Apache License 2.0
60 stars 7 forks source link

Error: Can't convert from type "varying int32" to type "uniform int32" for assignment operator #4

Closed emoon closed 6 years ago

emoon commented 6 years ago

Give the following code

struct Container
{
    uint ptr0;
};

struct OutputData
{
    uint ptr0;
};

#undef groupshared
#define groupshared static

groupshared uint g_mainBucket[1];

StructuredBuffer<Container> g_buffer0 : register(t2);
RWStructuredBuffer<OutputData> g_buffer1 : register(u0);

[numthreads(1, 1, 1)]
void csEntry(
    uint groupIdx : SV_GroupID,
    uint localIdx : SV_GroupThreadID)
{
    uint index = g_mainBucket[localIdx.x];
    g_buffer1[0].ptr0 = g_buffer0[index].ptr0;
}

Compiling this (using DXC) with dxc -E csEntry -T cs_6_0 -spirv file.hlsl -Fo shader.spv and then using SPIRV-Cross.exe --ispc shader.spv --output output.ispc Results in the following file (slightly cut down to make it smaller)

//////////////////////////////
// This ISPC kernel is autogenerated by spirv-cross.
// 09/24/18 17:10:39
//////////////////////////////
//

#include "spirvcross_stdlib.ispc"

//////////////////////////////
// Work Group
//////////////////////////////
static uniform int3 gl_WorkGroupSize = {1, 1, 1};

//////////////////////////////
// Resources
//////////////////////////////
struct Container
{
    int ptr0;
};

struct OutputData
{
    int ptr0;
};

struct type_StructuredBuffer_Container
{
    struct Container _m0[];
};

struct type_RWStructuredBuffer_OutputData
{
    struct OutputData _m0[];
};

//////////////////////////////
// Shader Code
//////////////////////////////
static SPIRV_INLINE void temp_ispc_main( uniform struct type_RWStructuredBuffer_OutputData& g_buffer1,  uniform struct type_StructuredBuffer_Container& g_buffer0, varying int3 gl_LocalInvocationID, uniform int3 gl_WorkGroupID)
{
    varying int g_mainBucket[1] = { 0u };
    varying int _33 = g_mainBucket[gl_LocalInvocationID.x];
    varying int _35 = g_buffer0._m0[_33].ptr0;
    g_buffer1._m0[0u].ptr0 = _35;
}

export void temp_dispatch_single(uniform int work_group_ID[3], uniform int work_groups[3],  uniform struct type_RWStructuredBuffer_OutputData& g_buffer1,  uniform struct type_StructuredBuffer_Container& g_buffer0)
{
    uniform int3 gl_NumWorkGroups = int3(work_groups[0], work_groups[1], work_groups[2]);
    uniform int3 gl_WorkGroupID = int3(work_group_ID[0], work_group_ID[1], work_group_ID[2]);

    // Vectorise the workgroup
    foreach(lx = 0 ... gl_WorkGroupSize.x)
    {
        varying int3 gl_LocalInvocationID = int3(lx, 0, 0);
        varying int3 gl_GlobalInvocationID = gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID;
        varying int gl_LocalInvocationIndex = gl_LocalInvocationID.z * gl_WorkGroupSize.x * gl_WorkGroupSize.y + gl_LocalInvocationID.y * gl_WorkGroupSize.x + gl_LocalInvocationID.x;

        temp_ispc_main( g_buffer1,  g_buffer0, gl_LocalInvocationID, gl_WorkGroupID);
    }
}

This results in the following error

output.ispc:50:30: Error: Can't convert from type "varying int32" to type "uniform int32" for assignment operator.
    g_buffer1._m0[0u].ptr0 = _35;
jonckennedy commented 6 years ago

2 issues here.

  1. It doesn't properly support groupshared data. It has made the data a varying when it should actually be a uniform array that is indexed by a varying.

  2. g_buffer1[0].ptr0 = g_buffer0[index].ptr0; is also an issue as 0u is a uniform literal when it actually needs to be a varying. I'll have to think how to work around that as the varying dependancy chain could be a bit complex.