LWJGL / lwjgl3

LWJGL is a Java library that enables cross-platform access to popular native APIs useful in the development of graphics (OpenGL, Vulkan, bgfx), audio (OpenAL, Opus), parallel computing (OpenCL, CUDA) and XR (OpenVR, LibOVR, OpenXR) applications.
https://www.lwjgl.org
BSD 3-Clause "New" or "Revised" License
4.67k stars 629 forks source link

Sometimes FMOD returns FMOD_ERR_INVALID_PARAM when window does not have focus on Windows #940

Closed soundasleep closed 8 months ago

soundasleep commented 8 months ago

Version

3.3.3

Platform

Windows x64

JDK

OpenJDK 64-Bit Server VM v16.0.2+7-67 by Oracle Corporation

Module

FMOD or LWJGL

Bug description

Hello! I'm trying to integrate FMOD into my libgdx game and it's mostly going really well, except I've come across a weird and difficult to reproduce error where FMOD is returning FMOD_ERR_INVALID_PARAM sometimes. It seems to only occur when the application does not have focus, and it's extremely difficult to reproduce, so I'm wondering if it's a memory thing.

This is essentially the code I'm using:

public static void main(String[] arg) {
    try (MemoryStack stack = MemoryStack.stackPush()) {
        try (MyFMODImpl fmod = new MyFMODImpl(stack)) {
            // the game runs in here, using fmod
        }
    }
}

And MyFMODImpl, where I create single FMOD_VECTOR instances that I then set and reuse on every method call (since it's called every frame):

public class MyFMODImpl {
    /** pointer to FMODStudio::System */
    private final long address;

    /** fixed instances, updated from Vector3 */
    private final FMOD_3D_ATTRIBUTES fmod3dAttributes;
    private final FMOD_VECTOR v_listenerPosition;
    private final FMOD_VECTOR v_listenerVelocity;
    private final FMOD_VECTOR v_attenuation;

    /** single instances that represent constant instances */
    public final FMOD_VECTOR V_ZERO;
    public final FMOD_VECTOR V_FORWARD_IS_NEGATIVE_Z;
    public final FMOD_VECTOR V_UP_IS_POSITIVE_Y;

    public MyFMODImpl(MemoryStack stack) {
        PointerBuffer buf = fmodStudioSystemCreate(stack); //
        this.address = buf.get(0);

        // create a new 3D attributes and vectors (long-lasting)
        v_listenerPosition = FMOD_VECTOR.malloc(stack);
        v_listenerVelocity = FMOD_VECTOR.malloc(stack);
        V_ZERO = FMOD_VECTOR.malloc(stack);
        setFmodVector(V_ZERO, CommonFMODVectors.V_ZERO);
        V_FORWARD_IS_NEGATIVE_Z = FMOD_VECTOR.malloc(stack);
        setFmodVector(V_FORWARD_IS_NEGATIVE_Z, CommonFMODVectors.V_FORWARD_IS_NEGATIVE_Z);
        V_UP_IS_POSITIVE_Y = FMOD_VECTOR.malloc(stack);
        setFmodVector(V_UP_IS_POSITIVE_Y, CommonFMODVectors.V_UP_IS_POSITIVE_Y);
        v_attenuation = FMOD_VECTOR.malloc(stack);
        setFmodVector(v_attenuation, CommonFMODVectors.V_ZERO);

        fmod3dAttributes = FMOD_3D_ATTRIBUTES.malloc(stack)
        setListenerAttributes(0, VECTOR_3_ZERO, VECTOR_3_ZERO, null);
    }

    private PointerBuffer fmodStudioSystemCreate(MemoryStack stack) {
        PointerBuffer buf = stack.mallocPointer(1);
        check(FMODStudio.FMOD_Studio_System_Create(buf /* out */, FMOD.FMOD_VERSION));
        return buf;
    }

    public static void setFmodVector(FMOD_VECTOR out, Vector3 in) {
        out.set(in.x, in.y, in.z);
    }

    public static void check(int result) {
        if (result == FMOD.FMOD_ERR_INVALID_PARAM) throw new RuntimeException("FMOD_ERR_INVALID_PARAM");
        if (result != FMOD.FMOD_OK) throw new RuntimeException();
    }

    public void setListenerAttributes(int listenerId, Vector3 position, Vector3 velocity) {     
        setFmodVector(v_listenerPosition, position);
        setFmodVector(v_listenerVelocity, velocity);
        fmod3dAttributes.position$().set(v_listenerPosition);
        fmod3dAttributes.velocity().set(v_listenerVelocity);
        fmod3dAttributes.forward().set(V_FORWARD_IS_NEGATIVE_Z);
        fmod3dAttributes.up().set(V_UP_IS_POSITIVE_Y);

        // this is where the crash occurs!      
        check(FMODStudio.FMOD_Studio_System_SetListenerAttributes(address, listenerId, fmod3dAttributes, null));
    }
}

I've tried just ignoring the FMOD_ERR_INVALID_PARAM but once it happens, it's constantly happening.

I've also tried reinitialising all of the vectors on the first FMOD_ERR_INVALID_PARAM but it still fails.

Am I using MemoryStack correctly? Is there anything about switching context on Windows that could cause my malloc'd vectors to become invalid? Could it be a bug in FMOD? Could it be a Hotspot or JVM thing? Thank you 🙏

Stacktrace or crash log output

No response

soundasleep commented 8 months ago

OK, the FMOD_ERR_INVALID_PARAM can occur when the window is focused, too. So I'm not sure what's going on 😢

soundasleep commented 8 months ago

I think I worked it out... a misbehaving int was being used for listenerID so sometimes I was trying to set the properties for listenerID = 1 when I only have a single listener. (see FMOD_Studio_System_GetNumListeners)