废话不多说,上源码
注释:src\xrt\state_trackers\oxr
//! OpenXR API function @ep{xrCreateSession}
XRAPI_ATTR XrResult XRAPI_CALL
oxr_xrCreateSession(XrInstance instance, const XrSessionCreateInfo *createInfo, XrSession *session);
注释:注意,最后一个参数 XrSession *out_session 是作为输出的 out put param
注释:src\xrt\state_trackers\oxr\oxr_objects.h
#define XRT_CAST_PTR_TO_OXR_HANDLE(HANDLE_TYPE, PTR) ((HANDLE_TYPE)(uint64_t)(uintptr_t)(PTR))
static inline XrSession
oxr_session_to_openxr(struct oxr_session *sess)
{
return XRT_CAST_PTR_TO_OXR_HANDLE(XrSession, sess);
}
注释:src\xrt\state_trackers\oxr\oxr_api_session.c
XrResult
oxr_xrCreateSession(XrInstance instance, const XrSessionCreateInfo *createInfo, XrSession *out_session)
{
OXR_TRACE_MARKER();
XrResult ret;
struct oxr_instance *inst;
struct oxr_session *sess, **link;
struct oxr_logger log;
OXR_VERIFY_INSTANCE_AND_INIT_LOG(&log, instance, inst, "xrCreateSession");
注释:XrSessionCreateInfo 指针往下传递
ret = oxr_verify_XrSessionCreateInfo(&log, inst, createInfo);
if (ret != XR_SUCCESS) {
return ret;
}
注释:将创建的oxr_session指针往下传
ret = oxr_session_create(&log, &inst->system, createInfo, &sess);
if (ret != XR_SUCCESS) {
return ret;
}
注释:参看上面两个函数的注释,这里只是作了一个强制类型转换,
将oxr中的类型强制转换成openxr中对应类型,作为output param输出给openxr
防止编译Warning,并没有具体的赋值操作。
*out_session = oxr_session_to_openxr(sess);
/* Add to session list */
link = &inst->sessions;
while (*link) {
link = &(*link)->next;
}
*link = sess;
return XR_SUCCESS;
}
注释:src\xrt\state_trackers\oxr\oxr_session.c
XrResult
oxr_session_create(struct oxr_logger *log,
struct oxr_system *sys,
const XrSessionCreateInfo *createInfo,
struct oxr_session **out_session)
{
注释:创建一个空的oxr_session指针
struct oxr_session *sess = NULL;
struct xrt_session_info xsi = {0};
const XrSessionCreateInfoOverlayEXTX *overlay_info = OXR_GET_INPUT_FROM_CHAIN(
createInfo, XR_TYPE_SESSION_CREATE_INFO_OVERLAY_EXTX, XrSessionCreateInfoOverlayEXTX);
if (overlay_info) {
xsi.is_overlay = true;
xsi.flags = overlay_info->createFlags;
xsi.z_order = overlay_info->sessionLayersPlacement;
}
/* Try allocating and populating. */
注释:注意上面这行注释,将创建的oxr_session指针往下传递进行内存分配和填充(也就是赋值)
XrResult ret = oxr_session_create_impl(log, sys, createInfo, &xsi, &sess);
if (ret != XR_SUCCESS) {
if (sess != NULL) {
/* clean up allocation first */
XrResult cleanup_result = oxr_handle_destroy(log, &sess->handle);
assert(cleanup_result == XR_SUCCESS);
(void)cleanup_result;
}
return ret;
}
// Init the begin/wait frame semaphore.
os_semaphore_init(&sess->sem, 1);
注释:sess经过oxr_session_create_impl()函数填充之后,再接着进行下面这些数据赋值
可以看到,主要是赋值ipd,帧spew,帧wait_sleep,以及初始状态时间等
sess->active_wait_frames = 0;
os_mutex_init(&sess->active_wait_frames_lock);
sess->ipd_meters = debug_get_num_option_ipd() / 1000.0f;
sess->frame_timing_spew = debug_get_bool_option_frame_timing_spew();
sess->frame_timing_wait_sleep_ms = debug_get_num_option_wait_frame_sleep();
oxr_session_change_state(log, sess, XR_SESSION_STATE_IDLE);
oxr_session_change_state(log, sess, XR_SESSION_STATE_READY);
u_hashmap_int_create(&sess->act_sets_attachments_by_key);
u_hashmap_int_create(&sess->act_attachments_by_key);
注释:赋值给传入进来的*out_session
*out_session = sess;
return ret;
}
接着跟oxr_session_create_impl(log, sys, createInfo, &xsi, &sess)函数,看看到底对 sess 作了哪些数据填充
注释:src\xrt\state_trackers\oxr\oxr_session.c
/* Just the allocation and populate part, so we can use early-returns to
* simplify code flow and avoid weird if/else */
static XrResult
oxr_session_create_impl(struct oxr_logger *log,
struct oxr_system *sys,
const XrSessionCreateInfo *createInfo,
const struct xrt_session_info *xsi,
struct oxr_session **out_session)
{
...
#ifdef XR_USE_GRAPHICS_API_VULKAN
...
OXR_SESSION_ALLOCATE(log, sys, *out_session);
OXR_ALLOCATE_NATIVE_COMPOSITOR(log, xsi, *out_session);
注释:这个函数里用不同的宏定义了不同的平台渲染方式
monado runtime使用的是vulkan,所以只关注宏 XR_USE_GRAPHICS_API_VULKAN
传进来的*out_session接着往下传递
return oxr_session_populate_vk(log, sys, vulkan, *out_session);
}
#endif
...
}
注释:src\xrt\state_trackers\oxr\oxr_objects.h
XrResult
oxr_session_populate_vk(struct oxr_logger *log,
struct oxr_system *sys,
XrGraphicsBindingVulkanKHR const *next,
struct oxr_session *sess)
{
struct xrt_compositor_native *xcn = sess->xcn;
struct xrt_compositor_vk *xcvk = xrt_gfx_vk_provider_create( //
xcn, //
next->instance, //
vkGetInstanceProcAddr, //
next->physicalDevice, //
next->device, //
sess->sys->vk.timeline_semaphore_enabled, //
next->queueFamilyIndex, //
next->queueIndex); //
if (xcvk == NULL) {
return oxr_error(log, XR_ERROR_INITIALIZATION_FAILED, "Failed to create an vk client compositor");
}
注释:这里对sess的成员,一个compositor和create_swapchain赋值
compositor 结构体指针
create_swapchain 函数指针
sess->compositor = &xcvk->base;
sess->create_swapchain = oxr_swapchain_vk_create;
return XR_SUCCESS;
}
注释:compositor由xrt_gfx_vk_provider_create()创建的xrt_compositor_vk指针的成员xcvk->base赋值接下来,先跟函数xrt_gfx_vk_provider_create(),回头再来跟oxr_swapchain_vk_create
注释:src\xrt\compositor\client\comp_vk_glue.c
struct xrt_compositor_vk *
xrt_gfx_vk_provider_create(struct xrt_compositor_native *xcn,
VkInstance instance,
PFN_vkGetInstanceProcAddr get_instance_proc_addr,
VkPhysicalDevice physical_device,
VkDevice device,
bool timeline_semaphore_enabled,
uint32_t queue_family_index,
uint32_t queue_index)
{
struct client_vk_compositor *vcc = client_vk_compositor_create( //
xcn, //
instance, //
get_instance_proc_addr, //
physical_device, //
device, //
timeline_semaphore_enabled, //
queue_family_index, //
queue_index); //
注释:这里就是上一段代码中获取到的返回值
在源码中可以很清晰的看到,vcc的base成员就是下面的xrt_compositor结构体
return &vcc->base;
}
注释:src\xrt\include\xrt\xrt_compositor.h
struct xrt_compositor_vk
{
//! @public Base
struct xrt_compositor base;
};
注释:再接着看client_vk_compositor_create()函数
注释:重头戏来了
src\xrt\compositor\client\comp_vk_client.c
struct client_vk_compositor *
client_vk_compositor_create(struct xrt_compositor_native *xcn,
VkInstance instance,
PFN_vkGetInstanceProcAddr getProc,
VkPhysicalDevice physicalDevice,
VkDevice device,
bool timeline_semaphore_enabled,
uint32_t queueFamilyIndex,
uint32_t queueIndex)
{
COMP_TRACE_MARKER();
xrt_result_t xret;
VkResult ret;
struct client_vk_compositor *c = U_TYPED_CALLOC(struct client_vk_compositor);
c->base.base.create_swapchain = client_vk_swapchain_create;
c->base.base.begin_session = client_vk_compositor_begin_session;
c->base.base.end_session = client_vk_compositor_end_session;
c->base.base.wait_frame = client_vk_compositor_wait_frame;
c->base.base.begin_frame = client_vk_compositor_begin_frame;
c->base.base.discard_frame = client_vk_compositor_discard_frame;
c->base.base.layer_begin = client_vk_compositor_layer_begin;
c->base.base.layer_stereo_projection = client_vk_compositor_layer_stereo_projection;
c->base.base.layer_stereo_projection_depth = client_vk_compositor_layer_stereo_projection_depth;
c->base.base.layer_quad = client_vk_compositor_layer_quad;
c->base.base.layer_cube = client_vk_compositor_layer_cube;
c->base.base.layer_cylinder = client_vk_compositor_layer_cylinder;
c->base.base.layer_equirect1 = client_vk_compositor_layer_equirect1;
c->base.base.layer_equirect2 = client_vk_compositor_layer_equirect2;
c->base.base.layer_commit = client_vk_compositor_layer_commit;
c->base.base.destroy = client_vk_compositor_destroy;
c->base.base.poll_events = client_vk_compositor_poll_events;
c->xcn = xcn;
// passthrough our formats from the native compositor to the client
for (uint32_t i = 0; i < xcn->base.info.format_count; i++) {
c->base.base.info.formats[i] = xcn->base.info.formats[i];
}
c->base.base.info.format_count = xcn->base.info.format_count;
// Default to info.
enum u_logging_level log_level = U_LOGGING_INFO;
ret = vk_init_from_given( //
&c->vk, // vk_bundle
getProc, // vkGetInstanceProcAddr
instance, // instance
physicalDevice, // physical_device
device, // device
queueFamilyIndex, // queue_family_index
queueIndex, // queue_index
timeline_semaphore_enabled, // timeline_semaphore_enabled
log_level); // log_level
if (ret != VK_SUCCESS) {
goto err_free;
}
ret = vk_init_mutex(&c->vk);
if (ret != VK_SUCCESS) {
goto err_free;
}
#ifdef VK_KHR_timeline_semaphore
if (c->vk.features.timeline_semaphore) {
xret = setup_semaphore(c);
if (xret != XRT_SUCCESS) {
goto err_mutex;
}
}
#endif
return c;
err_mutex:
vk_deinit_mutex(&c->vk);
err_free:
free(c);
return NULL;
}
可以看到这两句:
c->base.base.create_swapchain = client_vk_swapchain_create;
c->base.base.begin_session = client_vk_compositor_begin_session;
先看看swap_chain:
直接点击client_vk_swapchain_create()就能跳转到其完整实现:
注释:src\xrt\compositor\client\comp_vk_client.c
static xrt_result_t
client_vk_swapchain_create(struct xrt_compositor *xc,
const struct xrt_swapchain_create_info *info,
struct xrt_swapchain **out_xsc)
{
COMP_TRACE_MARKER();
struct client_vk_compositor *c = client_vk_compositor(xc);
struct vk_bundle *vk = &c->vk;
VkCommandBuffer cmd_buffer;
VkResult ret;
xrt_result_t xret;
struct xrt_swapchain_native *xscn = NULL; // Has to be NULL.
xret = xrt_comp_native_create_swapchain(c->xcn, info, &xscn);
if (xret != XRT_SUCCESS) {
return xret;
}
assert(xscn != NULL);
struct xrt_swapchain *xsc = &xscn->base;
ret = vk_init_cmd_buffer(vk, &cmd_buffer);
if (ret != VK_SUCCESS) {
return XRT_ERROR_VULKAN;
}
VkAccessFlags barrier_access_mask = vk_csci_get_barrier_access_mask(info->bits);
VkImageLayout barrier_optimal_layout = vk_csci_get_barrier_optimal_layout(info->format);
VkImageAspectFlags barrier_aspect_mask = vk_csci_get_barrier_aspect_mask(info->format);
VkImageSubresourceRange subresource_range = {
.aspectMask = barrier_aspect_mask,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
};
struct client_vk_swapchain *sc = U_TYPED_CALLOC(struct client_vk_swapchain);
sc->base.base.destroy = client_vk_swapchain_destroy;
sc->base.base.acquire_image = client_vk_swapchain_acquire_image;
sc->base.base.wait_image = client_vk_swapchain_wait_image;
sc->base.base.release_image = client_vk_swapchain_release_image;
sc->base.base.reference.count = 1;
sc->base.base.image_count = xsc->image_count; // Fetch the number of images from the native swapchain.
sc->c = c;
sc->xscn = xscn;
for (uint32_t i = 0; i < xsc->image_count; i++) {
ret = vk_create_image_from_native(vk, info, &xscn->images[i], &sc->base.images[i], &sc->mems[i]);
if (ret != VK_SUCCESS) {
return XRT_ERROR_VULKAN;
}
/*
* This is only to please the validation layer, that may or may
* not be a bug in the validation layer. That may or may not be
* fixed in the future version of the validation layer.
*/
vk_set_image_layout( //
vk, // vk_bundle
cmd_buffer, // cmd_buffer
sc->base.images[i], // image
0, // src_access_mask
barrier_access_mask, // dst_access_mask
VK_IMAGE_LAYOUT_UNDEFINED, // old_layout
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // new_layout
subresource_range); // subresource_range
}
ret = vk_submit_cmd_buffer(vk, cmd_buffer);
if (ret != VK_SUCCESS) {
return XRT_ERROR_FAILED_TO_SUBMIT_VULKAN_COMMANDS;
}
// Prerecord command buffers for swapchain image ownership/layout transitions
for (uint32_t i = 0; i < xsc->image_count; i++) {
ret = vk_init_cmd_buffer(vk, &sc->acquire[i]);
if (ret != VK_SUCCESS) {
return XRT_ERROR_VULKAN;
}
ret = vk_init_cmd_buffer(vk, &sc->release[i]);
if (ret != VK_SUCCESS) {
return XRT_ERROR_VULKAN;
}
VkImageSubresourceRange subresource_range = {
.aspectMask = barrier_aspect_mask,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
};
VkImageMemoryBarrier acquire = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = 0,
.dstAccessMask = barrier_access_mask,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = barrier_optimal_layout,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = sc->base.images[i],
.subresourceRange = subresource_range,
};
VkImageMemoryBarrier release = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = barrier_access_mask,
.dstAccessMask = 0,
.oldLayout = barrier_optimal_layout,
.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
.srcQueueFamilyIndex = vk->queue_family_index,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL,
.image = sc->base.images[i],
.subresourceRange = subresource_range,
};
//! @todo less conservative pipeline stage masks based on usage
vk->vkCmdPipelineBarrier( //
sc->acquire[i], // commandBuffer
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // srcStageMask
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // dstStageMask
0, // dependencyFlags
0, // memoryBarrierCount
NULL, // pMemoryBarriers
0, // bufferMemoryBarrierCount
NULL, // pBufferMemoryBarriers
1, // imageMemoryBarrierCount
&acquire); // pImageMemoryBarriers
vk->vkCmdPipelineBarrier( //
sc->release[i], // commandBuffer
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // srcStageMask
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, // dstStageMask
0, // dependencyFlags
0, // memoryBarrierCount
NULL, // pMemoryBarriers
0, // bufferMemoryBarrierCount
NULL, // pBufferMemoryBarriers
1, // imageMemoryBarrierCount
&release); // pImageMemoryBarriers
ret = vk->vkEndCommandBuffer(sc->acquire[i]);
if (ret != VK_SUCCESS) {
VK_ERROR(vk, "vkEndCommandBuffer: %s", vk_result_string(ret));
return XRT_ERROR_VULKAN;
}
ret = vk->vkEndCommandBuffer(sc->release[i]);
if (ret != VK_SUCCESS) {
VK_ERROR(vk, "vkEndCommandBuffer: %s", vk_result_string(ret));
return XRT_ERROR_VULKAN;
}
}
注释:swapchain创建完成,在此返回output输出
*out_xsc = &sc->base.base;
return XRT_SUCCESS;
}
swapchain在此创建完成,并在最后作为output param输出,一路返回
xrSession则需要继续跟函数client_vk_compositor_begin_session
注释:src\xrt\compositor\client\comp_vk_client.c
static xrt_result_t
client_vk_compositor_begin_session(struct xrt_compositor *xc, enum xrt_view_type type)
{
COMP_TRACE_MARKER();
struct client_vk_compositor *c = client_vk_compositor(xc);
// Pipe down call into native compositor.
return xrt_comp_begin_session(&c->xcn->base, type);
}
注释:src\xrt\include\xrt\xrt_compositor.h
/*!
* @copydoc xrt_compositor::begin_session
*
* Helper for calling through the function pointer.
*
* @public @memberof xrt_compositor
*/
static inline xrt_result_t
xrt_comp_begin_session(struct xrt_compositor *xc, enum xrt_view_type view_type)
{
return xc->begin_session(xc, view_type);
}
注释:点击begin_session,会跳转到其声明的地方,是xrt_compositor结构体中的函数指针
src\xrt\include\xrt\xrt_compositor.h
struct xrt_compositor{
...
/*!
* See xrBeginSession.
*/
xrt_result_t (*begin_session)(struct xrt_compositor *xc, enum xrt_view_type view_type);
...
}
注释:需要接着跟踪begin_session被赋值的地方
begin_session赋值在这里:
注释:src/xrt/compositor/main/comp_compositor.c
xrt_compositor_native的xrt_compositor的begin_session函数指针
在xrt_gfx_provider_create_system方法中被赋值
注意看下面函数体里面的c->base.base.base.begin_session
xrt_result_t
xrt_gfx_provider_create_system(struct xrt_device *xdev, struct xrt_system_compositor **out_xsysc)
{
struct comp_compositor *c = U_TYPED_CALLOC(struct comp_compositor);
c->base.base.base.begin_session = compositor_begin_session;
c->base.base.base.end_session = compositor_end_session;
c->base.base.base.predict_frame = compositor_predict_frame;
c->base.base.base.mark_frame = compositor_mark_frame;
c->base.base.base.begin_frame = compositor_begin_frame;
c->base.base.base.discard_frame = compositor_discard_frame;
c->base.base.base.layer_commit = compositor_layer_commit;
c->base.base.base.poll_events = compositor_poll_events;
c->base.base.base.destroy = compositor_destroy;
c->frame.waited.id = -1;
c->frame.rendering.id = -1;
c->xdev = xdev;
...
...
return comp_multi_create_system_compositor(&c->base.base, sys_info, out_xsysc);
}
到此,compositor_begin_seesion也就是xrSession的创建过程也完成。