Glavnokoman / vuh

Vulkan compute for people
https://glavnokoman.github.io/vuh
MIT License
346 stars 34 forks source link

EXC_BAD_INSTRUCTION on .toHost() #50

Closed Bambofy closed 4 years ago

Bambofy commented 4 years ago

Trying to copy from a vuh::Array to host vector after running a program causes a EXC_BAD_INSTRUCTION exception. OS X.

Image:

Screenshot 2020-06-02 at 21 47 33

Sample code:


    std::vector<float> m_positionsCache;
    std::vector<float> m_outPositionsCache;
    std::vector<Entity*>& FindInCircle(Vector2& center, float radius)
    {
        auto instance = vuh::Instance();
        auto device = instance.devices().at(0);

        m_positionsCache.clear();        
        m_outPositionsCache.clear();

        for (auto iter = m_entities.begin(); iter != m_entities.end(); iter++)
        {
            Vector2& position = iter->GetComponent<Vector2>("Position");
            m_positionsCache.push_back(position.x);
            m_positionsCache.push_back(position.y);

            m_outPositionsCache.push_back(-1.0f);
            m_outPositionsCache.push_back(-1.0f);

            index++;
        }

        using SpecializationConstants = vuh::typelist<uint32_t,uint32_t,uint32_t>;
        struct PushConstants {
            uint32_t numberOfElements;
        };

        uint32_t num = m_positionsCache.size();

        auto inArray = vuh::Array<float>(device, m_positionsCache);
        auto outArray = vuh::Array<float>(device, m_outPositionsCache);

        auto program = vuh::Program<SpecializationConstants, PushConstants>(device, "a.spv");
        program.grid(128);
        program.spec(128, 1, 1);
        program({
            num
        }, inArray, outArray);

        outArray.toHost(m_outPositionsCache.begin());
    }

Sample spv

#version 440

layout (local_size_x_id = 0) in;
layout (local_size_y_id = 1) in;
layout (local_size_z_id = 2) in;

layout (push_constant) uniform SearchParameters {
    uint numberOfElements;
} searchParameters;

// INDEX
// X
// Y
// INDEX...

layout (binding = 0) buffer lay0 { float inElementPositions[]; };
layout (binding = 1) buffer lay1 { float outElementPositions[]; };

void main(void)
{
    if (gl_GlobalInvocationID.x >= searchParameters.numberOfElements)
    {
        return;
    }

    outElementPositions[gl_GlobalInvocationID.x] = inElementPositions[gl_GlobalInvocationID.x];
}
Bambofy commented 4 years ago

update

When running this program:

        auto instance = vuh::Instance();
        auto device = instance.devices().at(0);

        std::vector<float> inputHostData = std::vector<float>(1000, 100.0f);
        std::vector<float> outputHostData = std::vector<float>(1000, -1.0f);

        auto inputDeviceData = vuh::Array<float>(device, inputHostData);
        auto outDeviceData = vuh::Array<float>(device, outputHostData);

        using Specs = vuh::typelist<uint32_t, uint32_t, uint32_t>;
        struct Params {
            uint32_t numberOfElements;
        };
        auto program = vuh::Program<Specs, Params>(device, "a.spv");
        program.grid(128, 1, 1);
        program.spec(128, 1, 1);
        program.bind({ 1000 }, inputDeviceData, outDeviceData);
        program.run();

        outDeviceData.toHost(outputHostData.begin());

        std::cout << "Complete" << std::endl;

it prints an EXC_BAD_INSTRUCT on the last std::cout line. However, the outputHostData array actually contains the correct data!

Here is the vulkan information for this Macbook Air: osx_gpu.txt

Bambofy commented 4 years ago

Ok i found a fix!

You have to put a return statement at the end of the function, or else you get a EXC_BAD_INSTRUCTION.