JCoronado User Manual 3.0.0-SNAPSHOT
The
jcoronado package provides a very thin layer over the
Vulkan API that intends to provide some degree of
memory and type safety. The intention of the package is to make Vulkan feel like a
Java API, without sacrificing
performance. Internally, the package uses the excellent
LWJGL3 Vulkan bindings, and adds a thin layer of
immutable types and interfaces.
The
jcoronado package currently targets
Vulkan 1.4 and up. Some optional device features
are required by the package.
The package requires the synchronization2 feature to be available and enabled. This
is necessary to avoid having a lot of branching code paths around queue submission
and render passes.
The com.io7m.jcoronado.utility.allocation_tracker module provides a simple
implementation of the VulkanHostAllocatorType interface that simply delegates an existing
allocator (such as jemalloc) but also tracks the current amount of memory allocated for
every allocation type.
Simply instantiate a VulkanHostAllocatorTracker instance and use it anywhere the API
accepts a VulkanHostAllocatorType.
The
com.io7m.jcoronado.utility.swapchain module provides a utility for managing the
swapchain
correctly.
Swapchain management is notoriously difficult, with many pitfalls and sharp edges.
The
JCSwapchainManager class provides a class for correctly creating swapchains, automatically
recreating them if they become suboptimal or out-of-date, and acquiring and presenting
images.
The class requires the use of the
VK_EXT_swapchain_maintenance1
device extension to fix serious design flaws in the original
VK_KHR_swapchainAPI.
Briefly, create a swapchain:
Acquire images in the rendering loop:
When an image is acquired or presented, the current swapchain may be detected as being
suboptimal or out-of-date.
When this happens, a new swapchain is created internally and the old one is (eventually)
deleted.
On many operating systems, dragging a window's resize box can result in a flurry of
updates that will result in
hundreds of swapchain instances being created and deleted. For best results, disable
rendering during window
resize events. As an example, when using
GLFW:
By avoiding rendering during window resizes, we effectively avoid creating and destroying
swapchains for the
intermediate window sizes. When the window eventually stops resizing, the next acquisition
will detect the new
extent reported by the supplier, and a suitable swapchain will automatically be created
for the final size.
The com.io7m.jcoronado.utility.command_pools module provides a convenient and correct
utility to manage command pools and buffers.
The command buffer API in Vulkan is fairly poorly designed in the sense that a command
buffer has a complex
lifecycle that doesn't really work well with the standard try-with-resources resource
management. A command buffer is allocated, populated with commands, and is then submitted
to a queue for
execution. A command buffer should not be touched until the execution has completed
on the GPU, so it therefore
makes sense for command buffers to implement AutoCloseable so that the reference to the
command buffer can be discarded after submission. This would work well except that,
despite being allocated from a
pool, command buffers still need to be individually deallocated, and deallocation
is only safe after the command
buffer has finished executing.
The VulkanCommandPoolHandler utility creates a command pool for each frame-in-flight, and
tracks command buffers that are allocated from each pool. At the start of each frame,
the respective command pool
is reset and all command buffers allocated from that pool are automatically deallocated.
The utility depends on
the fact that if there are F frames in flight, and the current frame number is
N, then it is safe to deallocate command buffers from frame
M = N - F.
The
com.io7m.jcoronado.utility.prometheus module provides a server component that
exposes
Prometheus metrics. This can be used, along
with an appropriate Prometheus client, to get a real-time view of all Vulkan resources
used by an application.
Objects must be registered with the server to appear in metrics. Objects will automatically
be deregistered when
closed.
An example of the metrics output:
The Java API is documented in the included
JavaDoc.