OpenGL compute shader behaviour
19:34 17 Jan 2026

My OpenGL shader code seems to work on my other device, but doesn't work on my device. The other device has an Intel(R) UHD Graphics GPU while my device has an AMD Radeon HD 7570M. Both machines are Windows 10.
Here are the two shader files I have problems with, the first calculates wall intersections for raycasting, the other renders the walls. What can I do to make the shader code work on my device?

#version 430 core 

layout(local_size_x = 256, local_size_y = 1) in;

// Helper: 2D cross product
float cross2(vec2 a, vec2 b) {
    return a.x * b.y - a.y * b.x;
}

// Ray–segment intersection
bool raySegmentIntersect(vec2 rayOrigin, vec2 rayDir, vec2 segA, vec2 segB, out vec2 intersection) {
    vec2 v1 = rayOrigin - segA;
    vec2 v2 = segB - segA;
    vec2 v3 = vec2(-rayDir.y, rayDir.x); // Perpendicular to ray

    float denom = dot(v2, v3);
    if (abs(denom) < 1e-6) {
        return false; // Parallel, no intersection
    }

    float t1 = cross2(v2, v1) / denom; // Distance along the ray
    float t2 = dot(v1, v3) / denom;    // Position along the segment

    if (t1 >= 0.0 && t2 >= 0.0 && t2 <= 1.0) {
        intersection = rayOrigin + t1 * rayDir;
        return true;
    }

    return false;
}

struct columnData {
    vec4 texCoord;
    ivec2 wallRange;
    int texture;
};

struct lineData {
    vec2 p1;
    vec2 p2;
    int texture;
};

layout(std430, binding = 0) buffer lineBuf {
    lineData lines[];
};

layout(std430, binding = 1) buffer columnBuf {
    columnData columns[];
};

layout(std430, binding = 2) buffer depthBufferBuf {
    float depthBuffer[];
};

uniform uint numLines;       // Number of lines on the map
uniform vec2 lookDir;        // Look direction of our player (normalized)
uniform vec2 camera;         // Camera plane vector
uniform vec2 playerPos;      // Position of the player
uniform int WINDOW_WIDTH;
uniform int WINDOW_HEIGHT;
uniform float texWidth;
uniform float texHeight;

void main() {
    int x = int(gl_GlobalInvocationID.x);

    if (x >= WINDOW_WIDTH){
        return;
    }

    // Normalized screen x in range [-1, 1]
    float cameraX = (2.0 * x) / float(WINDOW_WIDTH) - 1.0;

    // Ray direction
    vec2 ray = normalize(lookDir + camera * cameraX);

    // Find closest intersection
    float closestDistSq = 1e30;
    int closestLineIndex = -1;
    vec2 closestIntersection = vec2(0.0);

    for (int i = 0; i < numLines; i++) {
        lineData line = lines[i];

        vec2 intersectionP;
        vec2 segA = line.p1;
        vec2 segB = line.p2;

        if (raySegmentIntersect(playerPos, ray, segA, segB, intersectionP)) {
            vec2 diff = intersectionP - playerPos;
            float newDistSq = dot(diff, diff);

            if (newDistSq < closestDistSq) {
                closestDistSq = newDistSq;
                closestLineIndex = i;
                closestIntersection = intersectionP;
            }
        }
    }

    // If no hit, just clear column (e.g., black)
    if (closestLineIndex == -1) {
        columns[x].wallRange = ivec2(0, 0);         // (0, 0) indicates no collision
        columns[x].texture = 0;
        return;
    }
    
    lineData curLine = lines[closestLineIndex];

    // True distance to wall
    float dist = sqrt(closestDistSq);
    float perpWallDist = dist * dot(ray, normalize(lookDir)); // ensure lookDir is normalized

    // Store the distance in a depth buffer
    depthBuffer[x] = dist;

    // Avoid division by zero
    if (perpWallDist < 1e-4) {
        perpWallDist = 1e-4;
    }

    // Wall height on screen
    float lineHeight = float(WINDOW_HEIGHT) / perpWallDist;

    float startDraw = float(WINDOW_HEIGHT) / 2.0 - lineHeight / 2.0;
    float endDraw   = float(WINDOW_HEIGHT) / 2.0 + lineHeight / 2.0;

    uint yStart = uint(max(startDraw, 0.0));
    uint yEnd   = uint(min(endDraw, float(WINDOW_HEIGHT - 1)));

    columns[x].wallRange = ivec2(yStart, yEnd);

    int curTexture = curLine.texture;
    columns[x].texture = curTexture;

    // Compute texture X coordinate (0..1) along the wall
    vec2 wallStart = curLine.p1;
    vec2 wallEnd   = curLine.p2;
    vec2 wallDir   = wallEnd - wallStart;
    vec2 hitDiff   = closestIntersection - wallStart;

    // Fraction along the segment using projection
    float texX = dot(hitDiff, wallDir) / dot(wallDir, wallDir);
    texX = clamp(texX, 0.0, 1.0) * float(texWidth);

    // Vertical texture mapping
    float stepY = float(texHeight) / lineHeight;
    float texY  = (float(yStart) - startDraw) * stepY;

    columns[x].texCoord = vec4(texX, 0, texY, stepY);
}
#version 430 core 

layout(local_size_x = 256, local_size_y = 1) in;

struct columnData {
    vec4 texCoord;
    ivec2 wallRange;
    int texture;
};

layout(std430, binding = 0) buffer columnBuf {
    columnData columns[];
};

layout(binding = 0, rgba8) writeonly uniform image2D outImage;  // Output image

// UNIFORMS
uniform sampler2D textures[9];
uniform int WINDOW_WIDTH;
uniform int WINDOW_HEIGHT;
uniform float texWidth;
uniform float texHeight;

void main() {
    int x = int(gl_GlobalInvocationID.x);

    if (x >= WINDOW_WIDTH || x >= xRange){
        return;
    }

    columnData curColumn = columns[x];

    vec2 wall = curColumn.wallRange;
    bool noCollision = wall.x == 0 && wall.y == 0;

    if (noCollision){
        return;
    }

    float texX = curColumn.texCoord.x;
    float texY = curColumn.texCoord.z;
    float stepY = curColumn.texCoord.w;

    // The texture of the current column
    int textureIdx = curColumn.texture;

    for (int y = int(wall.x); y < int(wall.y); y++){
        texX = clamp(texX, 0, texWidth - 1);
        texY = clamp(texY, 0, texHeight - 1);
        float normalizedX = texX / texWidth;
        float normalizedY = texY / texHeight;

        vec4 color = texture(textures[int(textureIdx)], vec2(normalizedX, normalizedY));

        imageStore(outImage, ivec2(int(x), int(y)), color);

        texY += stepY;
    }
}
c++ opengl gpu glsl