#parse("main/Header.vm") package com.nativelibs4java.opencl; import com.nativelibs4java.util.EnumValue; import com.nativelibs4java.util.EnumValues; import com.nativelibs4java.opencl.library.OpenCLLibrary; import com.nativelibs4java.util.IOUtils; import com.nativelibs4java.util.NIOUtils; import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; import static com.nativelibs4java.opencl.library.IOpenCLLibrary.*; import org.bridj.*; import static org.bridj.Pointer.*; import java.io.IOException; import java.nio.*; import static com.nativelibs4java.opencl.JavaCL.*; import static com.nativelibs4java.util.NIOUtils.*; import java.util.*; import static com.nativelibs4java.opencl.CLException.*; import org.bridj.ValuedEnum; import java.util.logging.Level; import java.util.logging.Logger; class ByteOrderHack { public static final boolean hackEnabled = "1".equals(System.getenv("JAVACL_GUESS_ENDIANNESS")) || "true".equals(System.getProperty("javacl.guessEndianness")); public static ByteOrder guessByteOrderNeededForBuffers(CLDevice device) { CLPlatform platform = device.getPlatform(); PlatformUtils.PlatformKind knownPlatform = PlatformUtils.guessPlatformKind(platform); if (!hackEnabled || knownPlatform != PlatformUtils.PlatformKind.AMDApp) return device.getByteOrder(); else return checkByteOrderNeededForBuffers(device); } public static ByteOrder checkByteOrderNeededForBuffers(CLDevice device) { CLContext context = JavaCL.createContext((Map)null, device); CLQueue queue = context.createDefaultQueue(); try { int n = 16; String testValueStr = "123456789f";//.101112f"; float testValue = Float.parseFloat(testValueStr); final int BIG_INDEX = 0, LITTLE_INDEX = 1; Pointer<Float> inPtr = Pointer.allocateFloats(n); inPtr.order(ByteOrder.BIG_ENDIAN).set(BIG_INDEX, testValue); inPtr.order(ByteOrder.LITTLE_ENDIAN).set(LITTLE_INDEX, testValue); CLBuffer<Float> inOut = context.createFloatBuffer(CLMem.Usage.InputOutput, inPtr); CLBuffer<Integer> success = context.createIntBuffer(CLMem.Usage.Output, n); String src = "__kernel void compare_endiannesses(__global float *inout, __global int *success) {\n" + "size_t i = get_global_id(0);\n" + "success[i] = (inout[i] == " + testValueStr + ");\n" + "inout[i] = " + testValueStr + ";\n" + "}"; CLKernel test = context.createProgram(src).createKernel("compare_endiannesses"); test.setArgs(inOut, success); test.enqueueNDRange(queue, new int[] { n }, new int[] { 1 }); Pointer<Integer> successPtr = Pointer.allocateInts(n); success.read(queue, successPtr, true); Pointer<Float> outPtr = Pointer.allocateFloats(n); inOut.read(queue, outPtr, true); boolean bigOk = successPtr.get(BIG_INDEX) != 0; boolean littleOk = successPtr.get(LITTLE_INDEX) != 0; int index, otherIndex; ByteOrder order, otherOrder; if (bigOk) { order = ByteOrder.BIG_ENDIAN; index = BIG_INDEX; otherOrder = ByteOrder.LITTLE_ENDIAN; otherIndex = LITTLE_INDEX; } else { order = ByteOrder.LITTLE_ENDIAN; index = LITTLE_INDEX; otherOrder = ByteOrder.BIG_ENDIAN; otherIndex = BIG_INDEX; } float value = outPtr.order(order).get(index); float otherValue = outPtr.order(otherOrder).get(otherIndex); if (JavaCL.debug) System.out.println("[" + device + "] Endianness test: bigOk = " + bigOk + ", littleOk = " + littleOk + "; value = " + value + ", otherValue = " + otherValue); if (!(bigOk ^ littleOk)) throw new RuntimeException("[" + device + "] Endianness check failed, kernel recognized both endiannesses..."); { if (value != testValue || otherValue == testValue) throw new RuntimeException("[" + device + "] Endianness double-check failed, expected " + testValue + " and found " + value + " instead for endianness " + order + " (otherValue = " + otherValue + " for " + otherOrder + ")"); return order; } } catch (Throwable ex) { throw new RuntimeException("[" + device + "] Endianness check failed: " + ex, ex); } finally { queue.release(); context.release(); } } }