Skip to content

Commit 6ae1cae

Browse files
committed
Merge pull request godotengine#109431 from dsnopek/openxr-composition-layer-safe-multithreaded-rendering
Make `OpenXRCompositionLayer` and its children safe for multithreaded rendering
2 parents 8aebfb7 + 093d191 commit 6ae1cae

13 files changed

+781
-542
lines changed

modules/openxr/extensions/openxr_composition_layer_extension.cpp

Lines changed: 295 additions & 145 deletions
Large diffs are not rendered by default.

modules/openxr/extensions/openxr_composition_layer_extension.h

Lines changed: 175 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -43,63 +43,36 @@ typedef XrResult(XRAPI_PTR *PFN_xrCreateSwapchainAndroidSurfaceKHR)(XrSession se
4343
#endif
4444

4545
class JavaObject;
46-
class OpenXRViewportCompositionLayerProvider;
4746

4847
// This extension provides access to composition layers for displaying 2D content through the XR compositor.
4948

49+
#define OPENXR_LAYER_FUNC1(m_name, m_arg1) \
50+
void _composition_layer_##m_name##_rt(RID p_layer, m_arg1 p1) { \
51+
CompositionLayer *layer = composition_layer_owner.get_or_null(p_layer); \
52+
ERR_FAIL_NULL(layer); \
53+
layer->m_name(p1); \
54+
} \
55+
void composition_layer_##m_name(RID p_layer, m_arg1 p1) { \
56+
RenderingServer::get_singleton()->call_on_render_thread(callable_mp(this, &OpenXRCompositionLayerExtension::_composition_layer_##m_name##_rt).bind(p_layer, p1)); \
57+
}
58+
59+
#define OPENXR_LAYER_FUNC2(m_name, m_arg1, m_arg2) \
60+
void _composition_layer_##m_name##_rt(RID p_layer, m_arg1 p1, m_arg2 p2) { \
61+
CompositionLayer *layer = composition_layer_owner.get_or_null(p_layer); \
62+
ERR_FAIL_NULL(layer); \
63+
layer->m_name(p1, p2); \
64+
} \
65+
void composition_layer_##m_name(RID p_layer, m_arg1 p1, m_arg2 p2) { \
66+
RenderingServer::get_singleton()->call_on_render_thread(callable_mp(this, &OpenXRCompositionLayerExtension::_composition_layer_##m_name##_rt).bind(p_layer, p1, p2)); \
67+
}
68+
5069
// OpenXRCompositionLayerExtension enables the extensions related to this functionality
5170
class OpenXRCompositionLayerExtension : public OpenXRExtensionWrapper {
5271
GDCLASS(OpenXRCompositionLayerExtension, OpenXRExtensionWrapper);
5372

5473
protected:
5574
static void _bind_methods() {}
5675

57-
public:
58-
static OpenXRCompositionLayerExtension *get_singleton();
59-
60-
OpenXRCompositionLayerExtension();
61-
virtual ~OpenXRCompositionLayerExtension() override;
62-
63-
virtual HashMap<String, bool *> get_requested_extensions() override;
64-
virtual void on_instance_created(const XrInstance p_instance) override;
65-
virtual void on_session_created(const XrSession p_session) override;
66-
virtual void on_session_destroyed() override;
67-
virtual void on_pre_render() override;
68-
69-
virtual int get_composition_layer_count() override;
70-
virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) override;
71-
virtual int get_composition_layer_order(int p_index) override;
72-
73-
void register_viewport_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer);
74-
void unregister_viewport_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer);
75-
76-
bool is_available(XrStructureType p_which);
77-
bool is_android_surface_swapchain_available() { return android_surface_ext_available; }
78-
79-
#ifdef ANDROID_ENABLED
80-
bool create_android_surface_swapchain(XrSwapchainCreateInfo *p_info, XrSwapchain *r_swapchain, jobject *r_surface);
81-
void free_android_surface_swapchain(XrSwapchain p_swapchain);
82-
#endif
83-
84-
private:
85-
static OpenXRCompositionLayerExtension *singleton;
86-
87-
Vector<OpenXRViewportCompositionLayerProvider *> composition_layers;
88-
89-
bool cylinder_ext_available = false;
90-
bool equirect_ext_available = false;
91-
bool android_surface_ext_available = false;
92-
93-
#ifdef ANDROID_ENABLED
94-
Vector<XrSwapchain> android_surface_swapchain_free_queue;
95-
void free_queued_android_surface_swapchains();
96-
97-
EXT_PROTO_XRRESULT_FUNC1(xrDestroySwapchain, (XrSwapchain), swapchain)
98-
EXT_PROTO_XRRESULT_FUNC4(xrCreateSwapchainAndroidSurfaceKHR, (XrSession), session, (const XrSwapchainCreateInfo *), info, (XrSwapchain *), swapchain, (jobject *), surface)
99-
#endif
100-
};
101-
102-
class OpenXRViewportCompositionLayerProvider {
10376
public:
10477
// Must be identical to Filter enum definition in OpenXRCompositionLayer.
10578
enum Filter {
@@ -146,79 +119,177 @@ class OpenXRViewportCompositionLayerProvider {
146119
Swizzle alpha_swizzle = Swizzle::SWIZZLE_ALPHA;
147120
float max_anisotropy = 1.0;
148121
Color border_color = { 0.0, 0.0, 0.0, 0.0 };
149-
bool dirty = false;
150122
};
151123

152-
private:
153-
XrCompositionLayerBaseHeader *composition_layer = nullptr;
154-
int sort_order = 1;
155-
bool alpha_blend = false;
156-
Dictionary extension_property_values;
157-
bool extension_property_values_changed = true;
158-
159-
struct {
160-
RID viewport;
161-
Size2i viewport_size;
162-
OpenXRAPI::OpenXRSwapChainInfo swapchain_info;
163-
bool static_image = false;
164-
bool swapchain_protected_content = false;
165-
} subviewport;
166-
167-
#ifdef ANDROID_ENABLED
168-
struct {
169-
XrSwapchain swapchain = XR_NULL_HANDLE;
170-
Ref<JavaObject> surface;
171-
} android_surface;
172-
#endif
124+
static OpenXRCompositionLayerExtension *get_singleton();
173125

174-
bool use_android_surface = false;
175-
bool protected_content = false;
176-
Size2i swapchain_size;
126+
OpenXRCompositionLayerExtension();
127+
virtual ~OpenXRCompositionLayerExtension() override;
177128

178-
OpenXRAPI *openxr_api = nullptr;
179-
OpenXRCompositionLayerExtension *composition_layer_extension = nullptr;
129+
virtual HashMap<String, bool *> get_requested_extensions() override;
130+
virtual void on_instance_created(const XrInstance p_instance) override;
131+
virtual void on_session_created(const XrSession p_session) override;
132+
virtual void on_session_destroyed() override;
133+
virtual void on_pre_render() override;
180134

181-
// Only for SubViewports.
182-
bool update_and_acquire_swapchain(bool p_static_image);
183-
RID get_current_swapchain_texture();
135+
virtual int get_composition_layer_count() override;
136+
virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) override;
137+
virtual int get_composition_layer_order(int p_index) override;
184138

185-
void update_swapchain_sub_image(XrSwapchainSubImage &r_swapchain_sub_image);
186-
void free_swapchain();
139+
// The data on p_openxr_layer will be copied - there is no need to keep it valid after this call.
140+
RID composition_layer_create(XrCompositionLayerBaseHeader *p_openxr_layer);
141+
void composition_layer_free(RID p_layer);
142+
143+
void composition_layer_register(RID p_layer);
144+
void composition_layer_unregister(RID p_layer);
145+
146+
OPENXR_LAYER_FUNC2(set_viewport, RID, const Size2i &);
147+
OPENXR_LAYER_FUNC2(set_use_android_surface, bool, const Size2i &);
148+
OPENXR_LAYER_FUNC1(set_sort_order, int);
149+
OPENXR_LAYER_FUNC1(set_alpha_blend, bool);
150+
OPENXR_LAYER_FUNC1(set_transform, const Transform3D &);
151+
OPENXR_LAYER_FUNC1(set_protected_content, bool);
152+
OPENXR_LAYER_FUNC1(set_extension_property_values, Dictionary);
153+
154+
OPENXR_LAYER_FUNC1(set_min_filter, Filter);
155+
OPENXR_LAYER_FUNC1(set_mag_filter, Filter);
156+
OPENXR_LAYER_FUNC1(set_mipmap_mode, MipmapMode);
157+
OPENXR_LAYER_FUNC1(set_horizontal_wrap, Wrap);
158+
OPENXR_LAYER_FUNC1(set_vertical_wrap, Wrap);
159+
OPENXR_LAYER_FUNC1(set_red_swizzle, Swizzle);
160+
OPENXR_LAYER_FUNC1(set_blue_swizzle, Swizzle);
161+
OPENXR_LAYER_FUNC1(set_green_swizzle, Swizzle);
162+
OPENXR_LAYER_FUNC1(set_alpha_swizzle, Swizzle);
163+
OPENXR_LAYER_FUNC1(set_max_anisotropy, float);
164+
OPENXR_LAYER_FUNC1(set_border_color, const Color &);
165+
166+
OPENXR_LAYER_FUNC1(set_quad_size, const Size2 &);
167+
168+
OPENXR_LAYER_FUNC1(set_cylinder_radius, float);
169+
OPENXR_LAYER_FUNC1(set_cylinder_aspect_ratio, float);
170+
OPENXR_LAYER_FUNC1(set_cylinder_central_angle, float);
171+
172+
OPENXR_LAYER_FUNC1(set_equirect_radius, float);
173+
OPENXR_LAYER_FUNC1(set_equirect_central_horizontal_angle, float);
174+
OPENXR_LAYER_FUNC1(set_equirect_upper_vertical_angle, float);
175+
OPENXR_LAYER_FUNC1(set_equirect_lower_vertical_angle, float);
176+
177+
Ref<JavaObject> composition_layer_get_android_surface(RID p_layer);
187178

188-
SwapchainState swapchain_state;
179+
bool is_available(XrStructureType p_which);
180+
bool is_android_surface_swapchain_available() { return android_surface_ext_available; }
189181

190-
#ifdef ANDROID_ENABLED
191-
void create_android_surface();
192-
#endif
182+
private:
183+
static OpenXRCompositionLayerExtension *singleton;
193184

194-
public:
195-
XrStructureType get_openxr_type() { return composition_layer->type; }
185+
bool cylinder_ext_available = false;
186+
bool equirect_ext_available = false;
187+
bool android_surface_ext_available = false;
196188

197-
void set_sort_order(int p_sort_order) { sort_order = p_sort_order; }
198-
int get_sort_order() const { return sort_order; }
189+
void _composition_layer_free_rt(RID p_layer);
190+
void _composition_layer_register_rt(RID p_layer);
191+
void _composition_layer_unregister_rt(RID p_layer);
199192

200-
void set_alpha_blend(bool p_alpha_blend);
201-
bool get_alpha_blend() const { return alpha_blend; }
193+
#ifdef ANDROID_ENABLED
194+
bool create_android_surface_swapchain(XrSwapchainCreateInfo *p_info, XrSwapchain *r_swapchain, jobject *r_surface);
202195

203-
void set_viewport(RID p_viewport, Size2i p_size);
204-
RID get_viewport() const { return subviewport.viewport; }
196+
EXT_PROTO_XRRESULT_FUNC1(xrDestroySwapchain, (XrSwapchain), swapchain)
197+
EXT_PROTO_XRRESULT_FUNC4(xrCreateSwapchainAndroidSurfaceKHR, (XrSession), session, (const XrSwapchainCreateInfo *), info, (XrSwapchain *), swapchain, (jobject *), surface)
198+
#endif
205199

206-
void set_use_android_surface(bool p_enable, Size2i p_size);
207-
bool get_use_android_surface() const { return use_android_surface; }
200+
struct CompositionLayer {
201+
union {
202+
XrCompositionLayerBaseHeader composition_layer;
203+
XrCompositionLayerQuad composition_layer_quad;
204+
XrCompositionLayerCylinderKHR composition_layer_cylinder;
205+
XrCompositionLayerEquirect2KHR composition_layer_equirect;
206+
};
207+
208+
int sort_order = 1;
209+
bool alpha_blend = false;
210+
Dictionary extension_property_values;
211+
bool extension_property_values_changed = true;
212+
213+
struct {
214+
RID viewport;
215+
Size2i viewport_size;
216+
OpenXRAPI::OpenXRSwapChainInfo swapchain_info;
217+
bool static_image = false;
218+
bool swapchain_protected_content = false;
219+
} subviewport;
208220

209-
void set_protected_content(bool p_protected_content) { protected_content = p_protected_content; }
210-
bool is_protected_content() const { return protected_content; }
221+
#ifdef ANDROID_ENABLED
222+
struct {
223+
XrSwapchain swapchain = XR_NULL_HANDLE;
224+
Ref<JavaObject> surface;
225+
} android_surface;
226+
#endif
211227

212-
Ref<JavaObject> get_android_surface();
228+
bool use_android_surface = false;
229+
bool protected_content = false;
230+
Size2i swapchain_size;
231+
232+
SwapchainState swapchain_state;
233+
bool swapchain_state_is_dirty = false;
234+
235+
void set_viewport(RID p_viewport, const Size2i &p_size);
236+
void set_use_android_surface(bool p_use_android_surface, const Size2i &p_size);
237+
238+
void set_sort_order(int p_sort_order) { sort_order = p_sort_order; }
239+
void set_alpha_blend(bool p_alpha_blend);
240+
void set_protected_content(bool p_protected_content) { protected_content = p_protected_content; }
241+
void set_transform(const Transform3D &p_transform);
242+
void set_extension_property_values(const Dictionary &p_extension_property_values);
243+
244+
void set_min_filter(Filter p_mode);
245+
void set_mag_filter(Filter p_mode);
246+
void set_mipmap_mode(MipmapMode p_mode);
247+
void set_horizontal_wrap(Wrap p_mode);
248+
void set_vertical_wrap(Wrap p_mode);
249+
void set_red_swizzle(Swizzle p_mode);
250+
void set_green_swizzle(Swizzle p_mode);
251+
void set_blue_swizzle(Swizzle p_mode);
252+
void set_alpha_swizzle(Swizzle p_mode);
253+
void set_max_anisotropy(float p_value);
254+
void set_border_color(const Color &p_color);
255+
256+
void set_quad_size(const Size2 &p_size);
257+
258+
void set_cylinder_radius(float p_radius);
259+
void set_cylinder_aspect_ratio(float p_aspect_ratio);
260+
void set_cylinder_central_angle(float p_central_angle);
261+
262+
void set_equirect_radius(float p_radius);
263+
void set_equirect_central_horizontal_angle(float p_angle);
264+
void set_equirect_upper_vertical_angle(float p_angle);
265+
void set_equirect_lower_vertical_angle(float p_angle);
266+
267+
Ref<JavaObject> get_android_surface();
268+
void on_pre_render();
269+
XrCompositionLayerBaseHeader *get_composition_layer();
270+
void free();
271+
272+
private:
273+
void update_swapchain_state();
274+
void update_swapchain_sub_image(XrSwapchainSubImage &r_subimage);
275+
bool update_and_acquire_swapchain(bool p_static_image);
276+
RID get_current_swapchain_texture();
277+
void free_swapchain();
213278

214-
void set_extension_property_values(const Dictionary &p_property_values);
279+
#ifdef ANDROID_ENABLED
280+
void create_android_surface();
281+
#endif
282+
};
215283

216-
void on_pre_render();
217-
XrCompositionLayerBaseHeader *get_composition_layer();
284+
Mutex composition_layer_mutex;
285+
RID_Owner<CompositionLayer, true> composition_layer_owner;
286+
LocalVector<CompositionLayer *> registered_composition_layers;
287+
};
218288

219-
void update_swapchain_state();
220-
SwapchainState *get_swapchain_state();
289+
VARIANT_ENUM_CAST(OpenXRCompositionLayerExtension::Filter);
290+
VARIANT_ENUM_CAST(OpenXRCompositionLayerExtension::MipmapMode);
291+
VARIANT_ENUM_CAST(OpenXRCompositionLayerExtension::Wrap);
292+
VARIANT_ENUM_CAST(OpenXRCompositionLayerExtension::Swizzle);
221293

222-
OpenXRViewportCompositionLayerProvider(XrCompositionLayerBaseHeader *p_composition_layer);
223-
~OpenXRViewportCompositionLayerProvider();
224-
};
294+
#undef OPENXR_LAYER_FUNC1
295+
#undef OPENXR_LAYER_FUNC2

0 commit comments

Comments
 (0)