Repository: LWJGL/lwjgl3

Issue #560: Multiple calls to clCompileProgram/clLinkProgram cause crash
Created: 2020-05-21T20:03:20Z
Environment

LWJGL version: 3.2.1
LWJGL build #: release
Java version: 1.8
Platform: Windows x64
Module: opencl

Description
We are using the OpenCL bindings to build and run OpenCL kernels. Instead of using the one-step clBuildProgram() call, we are using the two-step process where we call clCompileProgram() followed by clLinkProgram() to build our kernel. If we do this twice in a row, we get a crash on the second clLinkProgram call. I am attaching an isolated test case and a crash log. One very odd feature of this bug is that it seems to be affected by the Java stack. If I add random int variables, the crash will trigger/not-trigger. So you may need to add/remove random int variables depending on your system. I have tried it on four different OpenCL devices across two different Windows systems and found this bug to occur on all.
package org.test;

import org.junit.Test;
import org.lwjgl.PointerBuffer;
import org.lwjgl.system.MemoryStack;

import java.nio.IntBuffer;

import static org.lwjgl.opencl.CL10.*;
import static org.lwjgl.opencl.CL12.clCompileProgram;
import static org.lwjgl.opencl.CL12.clLinkProgram;
import static org.lwjgl.system.MemoryStack.stackPush;

public class CompileLinkBugTest
{
    @Test
    public void compileLinkBug()
    {
        try (MemoryStack stack = stackPush()) {
            PointerBuffer platforms = stack.mallocPointer(1);
            clGetPlatformIDs(platforms, (int[]) null);
            long platformPtr = platforms.get(0);

            PointerBuffer devices = stack.mallocPointer(1);
            clGetDeviceIDs(platformPtr, CL_DEVICE_TYPE_ALL, devices, (int[]) null);
            long devicePtr = devices.get(0);

            IntBuffer errcode_ret = stack.callocInt(1);

            PointerBuffer propeties = null;
            long contextPtr = clCreateContext(propeties, devicePtr, null, 0, errcode_ret);

            createProgramPtr(contextPtr, devicePtr, "__kernel void a() { return; }");
            createProgramPtr(contextPtr, devicePtr, "__kernel void b() { return; }");
        }
    }

    private long createProgramPtr(long contextPtr, long devicePtr, String src)
    {
        try (MemoryStack stack = stackPush()) {
            //int a = 0;  // NOTE - you may need to uncomment this to trigger crash
            if (contextPtr == 0) {
                throw new RuntimeException("Device is not loaded.");
            }
            long ptr = clCreateProgramWithSource(contextPtr, src, null);

            PointerBuffer deviceList = stack.pointers(devicePtr);

            clCompileProgram(ptr, deviceList, "-cl-std=CL2.0", null, null, null, 0);
            ptr = clLinkProgram(contextPtr, deviceList, "", ptr, null, 0);
            if (ptr == 0) {
                throw new RuntimeException("CL Linking failed\n");
            }
            return ptr;
        }
    }
}

hs_err_pid17432.log
Tested on:
Name: AMD Accelerated Parallel Processing 
Vendor: Advanced Micro Devices, Inc. 
Version: OpenCL 2.1 AMD-APP (2906.10) 
     Name: Ellesmere 
     Vendor: Advanced Micro Devices, Inc. 
     Version: OpenCL 2.0 AMD-APP (2906.10) 
     Device type: GPU

Name: NVIDIA CUDA 
Vendor: NVIDIA Corporation 
Version: OpenCL 1.2 CUDA 10.2.108 
     Name: Quadro M2000M 
     Vendor: NVIDIA Corporation 
     Version: OpenCL 1.2 CUDA 
     Device type: GPU

Name: Intel(R) OpenCL 
Vendor: Intel(R) Corporation 
Version: OpenCL 2.0  
     Name: Intel(R) HD Graphics P530 
     Vendor: Intel(R) Corporation 
     Version: OpenCL 2.0  
     Device type: GPU

     Name: Intel(R) Xeon(R) CPU E3-1535M v5 @ 2.90GHz 
     Vendor: Intel(R) Corporation 
     Version: OpenCL 2.0 (Build 10) 
     Device type: CPU

Duplicate issue #561: Missing errcode_ret pararmeter for clLinkProgram.
Created: 2020-05-22T13:14:32Z
The Javadoc for LWJGL's clLinkProgram mentions a errcode_ret value for obtaining the error code when the program fails to link.

Otherwise clLinkProgram returns a NULL program object with an appropriate error in errcode_ret.

However there is no parameter for IntBuffer/int[] errcode_ret in the LWJGL API call. The OpenCL specification for clLinkProgram shows that there is a parameter for obtaining the errcode but this isn't exposed in the API clLinkProgram(..., cl_int *errcode_ret). A quick look through the javadoc and I also see clCreateSubDevices has this same issue.

Closing comment (2020-05-22T14:51:07Z): Duplicates #560. The fix is coming soon.