Main Menu

Recent posts

#91
Hmm, you're right. I was convinced I had introduced the suggested lines one by one and that was the point it started working but I must have made a mistake. Thanks.

Just for my understanding, most OpenXR LWJGL stuff is created with a
Thing.create();
but the XrActionSuggestedBinding.Buffer is created with a
new Thing.Buffer(BufferUtils.createByteBuffer(Thing.SIZEOF));
. Why the difference? Is it because XrActionSuggestedBinding.Buffer is an array?
#92
Hey Richtea,

Both ways to initialize XrActionSuggestedBinding are equivalent. The allocated memory is zero-initialized either way, so ChatGPT is not helpful here. The difference is that the first way uses a GC-managed ByteBuffer as the backing memory (created with ByteBuffer.allocateDirect), whereas the second way uses memory allocated with calloc, which must be explicitly freed to avoid a memory leak. Recommended reading: Memory management in LWJGL

Afaict, the second way works because you added .type(XR10.XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING). It is missing from the original code.
#93
I asked chatgpt and it suggested I change it to this

XrActionSuggestedBinding.Buffer suggestedBindingsBuffer = XrActionSuggestedBinding.calloc(1)
        .action(action.address())
        .binding(xClickPathBuffer.get());

XrInteractionProfileSuggestedBinding xrInteractionProfileSuggestedBinding = XrInteractionProfileSuggestedBinding.calloc()
        .type(XR10.XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING)
        .next(NULL)
        .interactionProfile(oculusProfilePath.get())
        .suggestedBindings(suggestedBindingsBuffer);

withResponseCodeLogging("xrSuggestInteractionProfileBindings", XR10.xrSuggestInteractionProfileBindings(xrInstance, xrInteractionProfileSuggestedBinding));


Which works! Which freaks me out slightly. I think the actual change that was needed (which was a part of the changes chatpt suggested) was that I shouldn't be doing

XrActionSuggestedBinding.Buffer suggestedBindingsBuffer = new XrActionSuggestedBinding.Buffer(BufferUtils.createByteBuffer(XrActionSuggestedBinding.SIZEOF));


But should be doing

XrActionSuggestedBinding.Buffer suggestedBindingsBuffer = XrActionSuggestedBinding.calloc(1)


It seems like quite a useful explanation so here is why chatgpt said the working version is better

QuoteIn Java, when working with LWJGL bindings, it's usually safer and more convenient to use the calloc methods provided by the LWJGL data structures. This method allocates and initializes the buffer for you, which can help avoid issues with uninitialized fields or incorrectly-sized buffers.

In contrast, BufferUtils.createByteBuffer just allocates a block of memory and gives you a ByteBuffer pointing to it. When you pass this to new XrActionSuggestedBinding.Buffer, it creates a view of this memory as XrActionSuggestedBinding structures, but it doesn't initialize them. This can lead to issues if the memory isn't correctly initialized.

By using XrActionSuggestedBinding.calloc(1), you're asking LWJGL to allocate memory for one XrActionSuggestedBinding and initialize it to zero. This is typically what you want when creating new structures to pass to LWJGL functions.
#94
I am (having previously upgraded it to OpenVR http://forum.lwjgl.org/index.php?topic=7198.0) now planning on upgrading JMonkeyengine to OpenXR; we've got a fair way (The XR session boots and displays something somewhat sensible to the headset) but at the action set phase I'm getting an error I don't understand.

I've been following the example code at https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#_action_overview and I'm getting error code -1. Which I believe is XR_ERROR_VALIDATION_FAILURE, The function usage was invalid in some way. This happens when I call xrSuggestInteractionProfileBindings.

The Khronis example uses a XrActionSuggestedBinding but I'm using a XrActionSuggestedBinding.Buffer, but that seems to be what the LWJGL XrInteractionProfileSuggestedBinding wants me to do

This is the suggest actions code I'm running. Is there anything obvious I'm doing wrong?

    public void registerActions(){

        XrActionSetCreateInfo actionSetCreate = XrActionSetCreateInfo.create();
        actionSetCreate.actionSetName(stringToByte("test"));
        actionSetCreate.localizedActionSetName(stringToByte("testTranslation"));
        actionSetCreate.priority(0);

        PointerBuffer actionSetPointer = BufferUtils.createPointerBuffer(1);
        withResponseCodeLogging("Create action set", XR10.xrCreateActionSet(xrInstance, actionSetCreate, actionSetPointer));
        actionSetCreate.close();

        XrActionSet actionSet = new XrActionSet(actionSetPointer.get(), xrInstance);
        activeActionSet = actionSet;

        XrActionCreateInfo xrActionCreateInfo = XrActionCreateInfo.create();
        xrActionCreateInfo.actionName(stringToByte("teleport"));
        xrActionCreateInfo.actionType(ActionType.BOOLEAN.getOpenXrOption());
        xrActionCreateInfo.localizedActionName(stringToByte("teleportTranslated"));
        PointerBuffer actionPointer = BufferUtils.createPointerBuffer(1);
        withResponseCodeLogging("xrStringToPath", XR10.xrCreateAction(actionSet, xrActionCreateInfo, actionPointer));
        XrAction action = new XrAction(actionPointer.get(), actionSet);
        teleportAction = action;

        xrActionCreateInfo.close();

        LongBuffer oculusProfilePath = BufferUtils.createLongBuffer(1);
        withResponseCodeLogging("xrStringToPath", XR10.xrStringToPath(xrInstance, "/interaction_profiles/oculus/touch_controller", oculusProfilePath));

        //XrcAtionSuggestedBinding suggestedBinding = XrActionSuggestedBinding.create();
        LongBuffer xClickPathBuffer = BufferUtils.createLongBuffer(1);
        withResponseCodeLogging("xrStringToPath",XR10.xrStringToPath(xrInstance,"/user/hand/left/input/x/click", xClickPathBuffer));

        XrActionSuggestedBinding.Buffer suggestedBindingsBuffer = new XrActionSuggestedBinding.Buffer(BufferUtils.createByteBuffer(XrActionSuggestedBinding.SIZEOF));

        suggestedBindingsBuffer.action(action);
        suggestedBindingsBuffer.binding(xClickPathBuffer.get());

        XrInteractionProfileSuggestedBinding xrInteractionProfileSuggestedBinding = XrInteractionProfileSuggestedBinding.create();
        xrInteractionProfileSuggestedBinding.suggestedBindings(suggestedBindingsBuffer);
        xrInteractionProfileSuggestedBinding.interactionProfile(oculusProfilePath.get());

        //the below is the line returning the error code
        withResponseCodeLogging("xrSuggestInteractionProfileBindings", XR10.xrSuggestInteractionProfileBindings(xrInstance, xrInteractionProfileSuggestedBinding));

        actionSetPointer.rewind();
        XrSessionActionSetsAttachInfo actionSetsAttachInfo = XrSessionActionSetsAttachInfo.create();
        actionSetsAttachInfo.actionSets(actionSetPointer);

        withResponseCodeLogging("xrAttachSessionActionSets", XR10.xrAttachSessionActionSets(xrSession, actionSetsAttachInfo));
    }

    private static ByteBuffer stringToByte(String str){
        byte[] strBytes = str.getBytes(StandardCharsets.UTF_8);
        byte[] nullTerminatedBytes = new byte[strBytes.length + 1];
        System.arraycopy(strBytes, 0, nullTerminatedBytes, 0, strBytes.length);
        nullTerminatedBytes[nullTerminatedBytes.length - 1] = 0;  // add null terminator
        ByteBuffer buffer = BufferUtils.createByteBuffer(nullTerminatedBytes.length);
        buffer.put(nullTerminatedBytes);
        buffer.rewind();
        return buffer;
    }

    private static void withResponseCodeLogging(String eventText, int errorCode){
        //error code 0 is ultra common and means all is well. Don't flood the logs with it
        if (errorCode != 0){
            CallResponseCode fullErrorDetails = CallResponseCode.getResponseCode(errorCode);
            if (fullErrorDetails.isAnErrorCondition()){
                logger.warning(fullErrorDetails.getFormattedErrorMessage() + " Occurred during  " + eventText);
            }else{
                if (logger.isLoggable(Level.FINE)){
                    logger.info(fullErrorDetails.getFormattedErrorMessage() + " Occurred during " + eventText);
                }
            }
        }
    }
#95
I am trying to load obj file with Assimp but I am stumbling on problem. For some reasons file reading fail and i don't understand why.

public RawModel loadToVAO(String resourcePath) {
         AIScene scene = Assimp.aiImportFileFromMemory(
                  ByteBuffer.wrap(resourcePath.getBytes()) ,
                  Assimp.aiProcess_JoinIdenticalVertices | Assimp.aiProcess_Triangulate | Assimp.aiProcess_FixInfacingNormals,
                  "obj"
          );
          if (scene == null) {
                 throw new RuntimeException(String.format("Could not load %s", resourcePath));
             }
         int vaoID = createVAO();
         System.out.println(Assimp.aiGetErrorString());
           PointerBuffer buffer = scene.mMeshes();
           IntBuffer indices;
           /*ArrayList<Float> positions=new ArrayList<Float>(),texCoords=new ArrayList<Float>(), normals=new ArrayList<Float>();
           ArrayList<Integer>indices=new ArrayList<Integer>();*/
          
               AIMesh mesh = AIMesh.create(buffer.get(0));
              
               AIVector3D.Buffer vectors = mesh.mVertices();
               FloatBuffer positions = BufferUtils.createFloatBuffer(vectors.limit());
             

              for(int i = 0; i < vectors.limit(); i++)
              {
                  AIVector3D vector = vectors.get(i);

                  positions.put(vector.x());
                  positions.put(vector.y());
                  positions.put(vector.z());
              }

              AIVector3D.Buffer coords = mesh.mTextureCoords(0);
              FloatBuffer texCoords = BufferUtils.createFloatBuffer(coords.limit());

              for(int i= 0; i < coords.limit(); i++)
              {
                  AIVector3D coord = coords.get(i);

                  texCoords.put(coords.x());
                  texCoords.put(coords.y());
              }

              AIVector3D.Buffer norms = mesh.mNormals();
              FloatBuffer normals = BufferUtils.createFloatBuffer(norms.limit());
              for(int i = 0; i < norms.limit(); i++)
              {
                  AIVector3D norm = norms.get(i);

                  normals.put(norm.x());
                  normals.put(norm.y());
                  normals.put(norm.z());
              }
             
              AIFace.Buffer inds = mesh.mFaces();
              indices = inds.mIndices();
              bindIndicesBuffer(indices);
              storeDataInAttributeList(0,3,positions);
            storeDataInAttributeList(1,2,texCoords);
            storeDataInAttributeList(2,3,normals);
            unbindVAO();
#96
Bug Reports / RFE / Re: [IDEA] need help for compi...
Last post by MassDrive - April 28, 2023, 06:51:46

For other arch I mean gcc's long list  ;D  :

aarch64*-*-*
alpha*-*-*
amdgcn-*-amdhsa
amd64-*-solaris2*
arc-*-elf32
arc-linux-uclibc
arm-*-eabi
avr
Blackfin
cris
DOS
epiphany-*-elf
ft32-*-elf
*-*-freebsd*
h8300-hms
hppa*-hp-hpux*
hppa*-hp-hpux10
hppa*-hp-hpux11
*-*-linux-gnu
i?86-*-linux*
i?86-*-solaris2*
ia64-*-linux
ia64-*-hpux*
*-ibm-aix*
iq2000-*-elf
loongarch
lm32-*-elf
lm32-*-uclinux
m32c-*-elf
m32r-*-elf
m68k-*-*
m68k-*-uclinux
microblaze-*-elf
mips-*-*
moxie-*-elf
msp430-*-elf
nds32le-*-elf
nds32be-*-elf
nvptx-*-none
or1k-*-elf
or1k-*-linux
powerpc*-*-*
powerpc-*-darwin*
powerpc-*-elf
powerpc*-*-linux-gnu*
powerpc-*-netbsd*
powerpc-*-eabisim
powerpc-*-eabi
powerpcle-*-elf
powerpcle-*-eabisim
powerpcle-*-eabi
riscv32-*-elf
riscv32-*-linux
riscv64-*-elf
riscv64-*-linux
rl78-*-elf
rx-*-elf
s390-*-linux*
s390x-*-linux*
s390x-ibm-tpf*
*-*-solaris2*
sparc*-*-*
sparc-sun-solaris2*
sparc-*-linux*
sparc64-*-solaris2*
sparcv9-*-solaris2*
c6x-*-*
visium-*-elf
*-*-vxworks*
x86_64-*-*, amd64-*-*
x86_64-*-solaris2*
xtensa*-*-elf
xtensa*-*-linux*
Microsoft Windows
*-*-cygwin
*-*-mingw32
OS/2
Older systems
#97
Bug Reports / RFE / [IDEA] need help for compiling...
Last post by MassDrive - April 28, 2023, 06:14:15
Hi, guys:

I have a question:
How to compile our library that targeting to other native systems like MIPS or others?
I have GCC and llvm for the specific arch.
In our "getting start" guide, we learned how to compile the JAVA part, but lack of instruction of how to compile the binary dependency part.
#98
Vulkan / Re: Logical device creation pr...
Last post by Adro - April 13, 2023, 20:07:02
Solved! It was an issue on the code for selecting the proper physical device. I was cleaning the properties even when selected it. This didn't occur on other computers because the bug affected non-discrete GPUs.
#99
Vulkan / Re: Logical device creation pr...
Last post by Adro - April 12, 2023, 18:47:10
Thanks for your quick answer, Spasi.

Here is the code for saving properties, extensions, features, memory and queue family information:

try(MemoryStack stack = MemoryStack.stackPush()) {
            
            IntBuffer bufInt = stack.callocInt(1);
            
            //Properties
            vkPhysicalDeviceProperties = VkPhysicalDeviceProperties.calloc();
            vkGetPhysicalDeviceProperties(vkPhysicalDevice, vkPhysicalDeviceProperties);
            
            //Features
            vkPhysicalDeviceFeatures = VkPhysicalDeviceFeatures.calloc();
            vkGetPhysicalDeviceFeatures(vkPhysicalDevice, vkPhysicalDeviceFeatures);
            
            //Queue Family Properties
            vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice,bufInt, null);
            Logger.debug("On physical device creation, it supports {} queue families", bufInt.get(0));
            vkQueueFamilyProperties = VkQueueFamilyProperties.calloc(bufInt.get(0));
            vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, bufInt, 
                    vkQueueFamilyProperties);
            
            //Device extensions
            VkUtils.vkCheck(vkEnumerateDeviceExtensionProperties(vkPhysicalDevice,(String) null,bufInt,null), 
                    "Cannot retrieve one of the physical devices number of extensions");
            vkDeviceExtensionProperties = VkExtensionProperties.calloc(bufInt.get(0));
            VkUtils.vkCheck(vkEnumerateDeviceExtensionProperties(vkPhysicalDevice,(String) null, bufInt, 
                    vkDeviceExtensionProperties), 
                    "Cannot retrieve one of the physical devices extensions");
            
            //Memory properties
            vkPhysicalDeviceMemoryProperties = VkPhysicalDeviceMemoryProperties.calloc();
            vkGetPhysicalDeviceMemoryProperties(vkPhysicalDevice, vkPhysicalDeviceMemoryProperties);


I think on the retrieving of queue family properties everything is fine.
#100
Vulkan / Re: Logical device creation pr...
Last post by spasi - April 12, 2023, 16:49:50
Hey Adro,

Looks like uninitialized memory to me. Have you verified that all Vulkan calls up to vkGetPhysicalDeviceQueueFamilyProperties haven't produced any errors? Does the large number go away if you zero-fill the queueFamilyProperties buffer before passing it to vkGetPhysicalDeviceQueueFamilyProperties?