有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

手动加载所需的Vulkan实例扩展时的java NullPointerException

我目前正在通过LWJGL使用Vulkan开发一个Win32应用程序,当我运行以下代码时

            String className = "Hello Window App";
            ByteBuffer classNameBuffer = stack.UTF16(className);
            WindowProc defaultWndProc = new WindowProc() {
                public long invoke(long hwnd, int uMsg, long wParam, long lParam) {
                    if (uMsg == User32.WM_DESTROY) {
                        User32.DestroyWindow(hwnd);
                        System.exit(0);
                    } else if (uMsg == User32.WM_PAINT) {
                    } 
                    return User32.DefWindowProc(hwnd, uMsg, wParam, lParam);
                }
            };
            WNDCLASSEX wc = WNDCLASSEX.callocStack(stack);
            wc.cbSize(WNDCLASSEX.SIZEOF);
            wc.hInstance(WindowsLibrary.HINSTANCE);
            wc.lpszClassName(classNameBuffer);
            wc.lpfnWndProc(defaultWndProc);
            User32.RegisterClassEx(wc);
            hwnd = User32.CreateWindowEx(User32.WS_EX_APPWINDOW, className, "Hello Windows App",
                    User32.WS_OVERLAPPEDWINDOW, 100, 100, 640, 480, 0, 0, WindowsLibrary.HINSTANCE, 0);
            if (hwnd == 0) {
                throw new RuntimeException("Unable to create Window");
            }
            User32.ShowWindow(hwnd, User32.SW_SHOW);
            User32.SetCursorPos(0, 0);
            MSG msg = MSG.callocStack(stack);
            //GLFW.glfwInit();
            PointerBuffer ppEnabledLayerNames = null; // We'll add support for validation layers later
            // PointerBuffer windowExtensions = GLFWVulkan.glfwGetRequiredInstanceExtensions();
            PointerBuffer windowExtensions = MemoryUtil.memAllocPointer(2);
            windowExtensions.put(MemoryUtil.memASCII(KHRSurface.VK_KHR_SURFACE_EXTENSION_NAME));
            windowExtensions.put(MemoryUtil.memASCII(KHRWin32Surface.VK_KHR_WIN32_SURFACE_EXTENSION_NAME));
            PointerBuffer ppEnabledExtensionNames = windowExtensions;
            VkApplicationInfo value = VkApplicationInfo.mallocStack(stack);
            value.sType(VK11.VK_STRUCTURE_TYPE_APPLICATION_INFO);
            value.pNext(0L);
            value.pApplicationName(stack.UTF8Safe("Game"));
            value.pEngineName(stack.UTF8Safe("engine"));
            value.apiVersion(VK11.VK_MAKE_VERSION(1, 1, 0));
            VkInstanceCreateInfo pCreateInfo = VkInstanceCreateInfo.mallocStack(stack);
            pCreateInfo.sType(VK11.VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
            pCreateInfo.pNext(0L);
            pCreateInfo.flags(0);
            pCreateInfo.pApplicationInfo(value);
            pCreateInfo.ppEnabledLayerNames(ppEnabledLayerNames);
            pCreateInfo.ppEnabledExtensionNames(ppEnabledExtensionNames);
            PointerBuffer pInstance = stack.mallocPointer(1);
            if (VK11.vkCreateInstance(pCreateInfo, null, pInstance) != VK11.VK_SUCCESS) {
            }
            instance = new VkInstance(pInstance.get(0), pCreateInfo);

            VkWin32SurfaceCreateInfoKHR sfc = VkWin32SurfaceCreateInfoKHR.calloc();
            sfc.hinstance(WindowsLibrary.HINSTANCE).hwnd(hwnd)
                    .sType(KHRWin32Surface.VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR).pNext(0).flags(0);
            LongBuffer pSurface = stack.callocLong(1);
            KHRWin32Surface.vkCreateWin32SurfaceKHR(instance, sfc, null, pSurface);
            surface = pSurface.get(0);
            while (User32.GetMessage(msg, 0L, 0, 0) == true) {
                User32.TranslateMessage(msg);
                User32.DispatchMessage(msg);
            }

我得到下面的例外。在加载所需的Vulkan实例扩展时,这似乎是一个错误,因为当我取消对GLFW.glfwInit();PointerBuffer windowExtensions = GLFWVulkan.glfwGetRequiredInstanceExtensions();行的注释,并使用它们来加载所需的扩展时,错误不会发生,窗口和Vulkan实例和曲面创建成功,也许有经验的人可以纠正我在这里做错了什么? 我试图手动加载的这两个扩展是GLFW方法唯一能做的

Exception in thread "main" java.lang.NullPointerException
        at org.lwjgl.system.Checks.check(Checks.java:188)
        at org.lwjgl.vulkan.KHRWin32Surface.nvkCreateWin32SurfaceKHR(KHRWin32Surface.java:93)
        at org.lwjgl.vulkan.KHRWin32Surface.vkCreateWin32SurfaceKHR(KHRWin32Surface.java:151)
        at win32_test.Win32Window.init(Win32Window.java:96)
        at win32_test.Win32Window.main(Win32Window.java:34)

共 (1) 个答案

  1. # 1 楼答案

    put()两个指针进入windowExtensionsNIO缓冲区后,它的.remaining()值将为0

    每当您将NIO缓冲区作为参数提供给LWJGL 3方法或结构内部时,LWJGL 3将尊重NIO缓冲区的配置/状态,即它的position()limit(),通过在内部使用缓冲区的remaining()方法(即limit - position),查看传递给本机函数的内存区域/数组的有效“长度”(主要通过本机函数签名或结构中的专用count/length参数指定)

    因此,当您将VkInstanceCreateInfo结构上的ppEnabledExtensionNames(...)成员设置为参数(这里我们称之为buffer)时,LWJGL 3将首先查询缓冲区的position()remaining(),然后在PointerBuffer的情况下,将底层C结构的ppEnabledExtensionNames成员设置为baseAddressOf(buffer) + buffer.position() * sizeof(uintptr_t),并将C结构的enabledExtensionCount成员设置为{

    这意味着,LWJGL 3将始终按照NIO缓冲区规范(即作为写/读位置)的预期方式尊重NIO缓冲区的position()

    在您的例子中,由于您使用的是相对NIO Buffer put()方法,您会发现windowExtensionsNIO Buffer的容量为2,限制为2,但位置为2,产生的remaining()为0

    为了修复代码,必须将windowExtensions缓冲区的位置设置为0。这可以通过多种方式实现,例如在放入缓冲区后.flip()使用缓冲区,或者在相对放入后使用绝对.put(index, ...)方法或调用.position(0).rewind()缓冲区