What is the difference between the vkDevice constructor and vkCreateDevice?

Started by bcbradle, April 26, 2017, 04:01:46

Previous topic - Next topic

bcbradle

vkCreateDevice according to the spec takes a VkDevice* for pDevice, which is a handle (64 bits)-- specifically it is a dispatchable type handle, so it is actually a pointer.

I would imagine that the PointerBuffer pDevice argument of vkCreateDevice in lwjgl is just a single element buffer that contains this pointer.

what vkCreateDevice actually does is create a device and stores the "pointer" (handle) for it at the location you specified with pDevice (itself a pointer to the 8 bytes of free memory that you will use to store it).

But maybe I'm wrong, because the constructor of vkDevice says it "Creates a VkDevice instance for the specified native handle"

How is it possible that you can specify a native handle with VkDevice's constructor when you can't do that with vkCreateDevice? Are they doing something different? What do I not know, or what do I misunderstand here?

spasi

The VkDevice class wraps a VkDevice handle. The javadoc says "VkDevice instance" with a link to the class itself, so I guess a more explicit wording would be: "Creates a VkDevice class instance for the specified native VkDevice handle". It simply wraps a handle returned by vkCreateDevice, it doesn't create anything. Example code:

try (MemoryStack stack = stackPush()) {
    PointerBuffer pp = stack.callocPointer(1);

    vkCreateDevice(physicalDevice, pCreateInfo, pAllocator, pp);
    // omitted: error handling
    VkDevice device = new VkDevice(pp.get(0), physicalDevice, pCreateInfo);
}


You then use the wrapped VkDevice in Vulkan functions that dispatch on a VkDevice handle (i.e. the first parameter is a VkDevice).

Why are dispatchable handles wrapped in Java classes and non-dispatchable are simple longs? Because LWJGL stores Vulkan capabilities and function pointers in dispatchable handle instances. The function pointers are used when calling any Vulkan function. This is equivalent to GLCapabilities in OpenGL, which is stored in thread-local storage. It is another design decision that makes Vulkan more efficient than OpenGL; by requiring that all* functions have a dispatchable handle as their first parameter, calling them has less overhead (both in LWJGL and in the driver).

* bootstrapping functions, like vkEnumerateInstance*Properties and vkCreateInstance, are exceptions to this rule.