Allow using custom Rect2i for rendering with OpenXR

This commit is contained in:
devloglogan 2024-09-20 15:57:19 -05:00
parent 4364ed6ccd
commit e7f6b7ea0b
25 changed files with 215 additions and 19 deletions

View file

@ -2171,6 +2171,14 @@ void OpenXRAPI::_set_render_state_multiplier(double p_render_target_size_multipl
openxr_api->render_state.render_target_size_multiplier = p_render_target_size_multiplier;
}
void OpenXRAPI::_set_render_state_render_region(const Rect2i &p_render_region) {
ERR_NOT_ON_RENDER_THREAD;
OpenXRAPI *openxr_api = OpenXRAPI::get_singleton();
ERR_FAIL_NULL(openxr_api);
openxr_api->render_state.render_region = p_render_region;
}
bool OpenXRAPI::process() {
ERR_FAIL_COND_V(instance == XR_NULL_HANDLE, false);
@ -2403,6 +2411,12 @@ Size2i OpenXRAPI::get_velocity_target_size() {
return velocity_target_size;
}
const XrCompositionLayerProjection *OpenXRAPI::get_projection_layer() const {
ERR_NOT_ON_RENDER_THREAD_V(nullptr);
return &render_state.projection_layer;
}
void OpenXRAPI::post_draw_viewport(RID p_render_target) {
// Must be called from rendering thread!
ERR_NOT_ON_RENDER_THREAD;
@ -2436,6 +2450,23 @@ void OpenXRAPI::end_frame() {
}
}
Rect2i new_render_region = (render_state.render_region != Rect2i()) ? render_state.render_region : Rect2i(Point2i(0, 0), render_state.main_swapchain_size);
for (uint32_t i = 0; i < render_state.view_count; i++) {
render_state.projection_views[i].subImage.imageRect.offset.x = new_render_region.position.x;
render_state.projection_views[i].subImage.imageRect.offset.y = new_render_region.position.y;
render_state.projection_views[i].subImage.imageRect.extent.width = new_render_region.size.width;
render_state.projection_views[i].subImage.imageRect.extent.height = new_render_region.size.height;
}
if (render_state.submit_depth_buffer && OpenXRCompositionLayerDepthExtension::get_singleton()->is_available() && render_state.depth_views) {
for (uint32_t i = 0; i < render_state.view_count; i++) {
render_state.depth_views[i].subImage.imageRect.offset.x = new_render_region.position.x;
render_state.depth_views[i].subImage.imageRect.offset.y = new_render_region.position.y;
render_state.depth_views[i].subImage.imageRect.extent.width = new_render_region.size.width;
render_state.depth_views[i].subImage.imageRect.extent.height = new_render_region.size.height;
}
}
// must have:
// - should_render set to true
// - a valid view pose for projection_views[eye].pose to submit layer
@ -2500,14 +2531,10 @@ void OpenXRAPI::end_frame() {
layer_flags |= XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
}
XrCompositionLayerProjection projection_layer = {
XR_TYPE_COMPOSITION_LAYER_PROJECTION, // type
nullptr, // next
layer_flags, // layerFlags
render_state.play_space, // space
render_state.view_count, // viewCount
render_state.projection_views, // views
};
render_state.projection_layer.layerFlags = layer_flags;
render_state.projection_layer.space = render_state.play_space;
render_state.projection_layer.viewCount = render_state.view_count;
render_state.projection_layer.views = render_state.projection_views;
if (projection_views_extensions.size() > 0) {
for (uint32_t v = 0; v < render_state.view_count; v++) {
@ -2522,7 +2549,7 @@ void OpenXRAPI::end_frame() {
}
}
ordered_layers_list.push_back({ (const XrCompositionLayerBaseHeader *)&projection_layer, 0 });
ordered_layers_list.push_back({ (const XrCompositionLayerBaseHeader *)&render_state.projection_layer, 0 });
// Sort our layers.
ordered_layers_list.sort_custom<OrderedCompositionLayer>();
@ -2584,6 +2611,15 @@ void OpenXRAPI::set_render_target_size_multiplier(double multiplier) {
set_render_state_multiplier(multiplier);
}
Rect2i OpenXRAPI::get_render_region() const {
return render_region;
}
void OpenXRAPI::set_render_region(const Rect2i &p_render_region) {
render_region = p_render_region;
set_render_state_render_region(p_render_region);
}
bool OpenXRAPI::is_foveation_supported() const {
OpenXRFBFoveationExtension *fov_ext = OpenXRFBFoveationExtension::get_singleton();
return fov_ext != nullptr && fov_ext->is_enabled();