OPENXR Scol plugin
renderer.cpp
1#include "sOpenXR.h"
2
3#define UNUSED_PARM(x) \
4 { (void)(x); }
5
6#if defined(XR_USE_PLATFORM_WIN32)
7//check opengl
8bool GL_INITIALIZED = false;
9#else
10# define strcpy_s(dest, source) strncpy((dest), (source), sizeof(dest))
11#endif
12
13#if defined(XR_USE_GRAPHICS_API_OPENGL)
14bool check_opengl_version(XrGraphicsRequirementsOpenGLKHR* opengl_reqs)
15{
16 GLint major = GLVersion.major;
17 GLint minor = GLVersion.minor;
18#elif defined(XR_USE_GRAPHICS_API_OPENGL_ES)
19bool check_opengl_version(XrGraphicsRequirementsOpenGLESKHR* opengl_reqs)
20{
21 GLint major = 0;
22 GLint minor = 0;
23 glGetIntegerv(GL_MAJOR_VERSION, &major);
24 glGetIntegerv(GL_MINOR_VERSION, &minor);
25#endif
26
27 const XrVersion desired_opengl_version = XR_MAKE_VERSION(major, minor, 0);
28 if (desired_opengl_version > opengl_reqs->maxApiVersionSupported || desired_opengl_version < opengl_reqs->minApiVersionSupported)
29 {
30 MMechostr(MSKRUNTIME,
31 "[OPENXR]: We want OpenGL %d.%d.%d, but runtime only supports OpenGL %d.%d.%d - %d.%d.%d!\n",
32 XR_VERSION_MAJOR(desired_opengl_version), XR_VERSION_MINOR(desired_opengl_version),
33 XR_VERSION_PATCH(desired_opengl_version),
34 XR_VERSION_MAJOR(opengl_reqs->minApiVersionSupported),
35 XR_VERSION_MINOR(opengl_reqs->minApiVersionSupported),
36 XR_VERSION_PATCH(opengl_reqs->minApiVersionSupported),
37 XR_VERSION_MAJOR(opengl_reqs->maxApiVersionSupported),
38 XR_VERSION_MINOR(opengl_reqs->maxApiVersionSupported),
39 XR_VERSION_PATCH(opengl_reqs->maxApiVersionSupported));
40 return false;
41 }
42 return true;
43}
44
45//Platforms descriptions
46
47#ifdef XR_USE_GRAPHICS_API_OPENGL
48struct OpenGLRenderer : public IRenderer {
49 OpenGLRenderer() { }
50 virtual ~OpenGLRenderer() override
51 {
52 for (auto& frame_buffer : mFramebuffers)
53 {
54 glDeleteFramebuffers(frame_buffer.size(), frame_buffer.data());
55 }
56 mFramebuffers.clear();
57 }
58
59 const XrBaseInStructure* GetBindings() const override { return reinterpret_cast<const XrBaseInStructure*>(&mGraphicsBinding); }
60
61 const char* GetExtension() const override { return XR_KHR_OPENGL_ENABLE_EXTENSION_NAME; }
62
63 bool Setup() override
64 {
65#if defined(XR_USE_PLATFORM_WIN32)
66 if (!GL_INITIALIZED)
67 GL_INITIALIZED = gladLoadGLLoader(getProcAddress) ? true : false;
68
69 if (!GL_INITIALIZED)
70 {
71 MMechostr(MSKRUNTIME, "sOpenXr initialize : Could not load OpenGL, creates a SO3Window first\n");
72 return false;
73 }
74#endif
75
76 // --- Make sure runtime supports the OpenGL extension
77
78 return true;
79 }
80
81 bool Check(XrSystemId systemId, XrInstance instance) override
82 {
83 XrResult result;
84 XrGraphicsRequirementsOpenGLKHR opengl_reqs = { XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR, NULL };
85 PFN_xrGetOpenGLGraphicsRequirementsKHR pfnGetOpenGLGraphicsRequirementsKHR = NULL;
86 result = xrGetInstanceProcAddr(instance, "xrGetOpenGLGraphicsRequirementsKHR", (PFN_xrVoidFunction*)&pfnGetOpenGLGraphicsRequirementsKHR);
87 if (!xr_result(instance, result, "Failed to get OpenGL graphics requirements function!"))
88 return false;
89
90 result = pfnGetOpenGLGraphicsRequirementsKHR(instance, systemId, &opengl_reqs);
91 if (!xr_result(instance, result, "Failed to get OpenGL graphics requirements!"))
92 return false;
93
94 // On OpenGL we never fail this check because the version requirement is not useful.
95 // Other APIs may have more useful requirements.
96 check_opengl_version(&opengl_reqs);
97
98# if defined(XR_USE_PLATFORM_WIN32)
99 mGraphicsBinding = XrGraphicsBindingOpenGLWin32KHR{ XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR };
100 mGraphicsBinding.hDC = wglGetCurrentDC();
101 mGraphicsBinding.hGLRC = wglGetCurrentContext();
102# endif
103
104 MMechostr(MSKRUNTIME, "[OPENXR]: Using OpenGL version: %s\n", glGetString(GL_VERSION));
105 MMechostr(MSKRUNTIME, "[OPENXR]: Using OpenGL Renderer: %s\n", glGetString(GL_RENDERER));
106 return true;
107 }
108
109 bool GetSwapchainFormat(XrInstance instance, XrSession session, int64_t &format) override
110 {
111 XrResult result;
112 uint32_t swapchain_format_count;
113 result = xrEnumerateSwapchainFormats(session, 0, &swapchain_format_count, XR_NULL_HANDLE);
114 if (!xr_result(instance, result, "Failed to get number of supported swapchain formats"))
115 return false;
116
117 MMechostr(MSKRUNTIME, "[OPENXR]: Runtime supports %d swapchain formats\n", swapchain_format_count);
118 std::vector<int64_t> swapchain_formats(swapchain_format_count);
119 result = xrEnumerateSwapchainFormats(session, swapchain_format_count, &swapchain_format_count, swapchain_formats.data());
120 if (!xr_result(instance, result, "Failed to enumerate swapchain formats"))
121 return false;
122
123 // SRGB is usually the best choice. Selection logic should be expanded though.
124 int64_t preferred_swapchain_format = GL_RGBA8; //GL_RGBA16;
125 format = swapchain_formats[0];
126
127 for (auto& swapchain_format : swapchain_formats)
128 {
129 MMechostr(MSKRUNTIME, "[OPENXR]: Supported GL format: %#lx\n", swapchain_format);
130 if (swapchain_format == preferred_swapchain_format)
131 {
132 format = swapchain_format;
133 MMechostr(MSKRUNTIME, "[OPENXR]: Using preferred swapchain format %#lx\n", format);
134 }
135 }
136
137 if (format != preferred_swapchain_format)
138 MMechostr(MSKRUNTIME, "[OPENXR]: Using non preferred swapchain format %#lx\n", format);
139
140 return true;
141 }
142
143 bool CreateSwapchainImage(XrInstance instance, uint32 viewCount, XrSwapchain swapchain, uint32_t pos) override
144 {
145 XrResult result;
146
147 if (mImages.empty())
148 mImages.resize(viewCount);
149
150 if (mFramebuffers.empty())
151 mFramebuffers.resize(viewCount);
152
153
154 uint32_t swapchain_length;
155 result = xrEnumerateSwapchainImages(swapchain, 0, &swapchain_length, XR_NULL_HANDLE);
156 if (!xr_result(instance, result, "Failed to enumerate swapchains"))
157 return false;
158
159 mImages[pos].resize(swapchain_length, { XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR , NULL });
160
161 result = xrEnumerateSwapchainImages(swapchain, swapchain_length, &swapchain_length, (XrSwapchainImageBaseHeader*)mImages[pos].data());
162 if (!xr_result(instance, result, "Failed to enumerate swapchain images"))
163 return false;
164
165 mFramebuffers[pos].resize(mImages[pos].size());
166 glGenFramebuffers(mFramebuffers[pos].size(), mFramebuffers[pos].data());
167
168 return true;
169 }
170
171 void UpdateTextures(SCOL_PTR_TYPE leftTexture, SCOL_PTR_TYPE rightTexture, uint32_t acquiredIndex, int32_t width, int32_t height, uint32_t pos) override
172 {
173 GLenum err;
174 GLuint glid = mImages[pos][acquiredIndex].image;
175 GLint oldfb = 0;
176 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldfb);
177
178 GLuint eyetex = (GLuint)((pos == 0) ? leftTexture : rightTexture);
179
180 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffers[pos][acquiredIndex]);
181 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, eyetex, 0);
182 err = glGetError();
183
184 glBindTexture(GL_TEXTURE_2D, glid);
185 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
186
187 err = glGetError();
188
189 //flip
190 //too slow
191 /*
192 if (!mFovMutable && !mTextureBuffer.empty())
193 {
194 const GLsizei w = (GLsizei)width;
195 const GLsizei h = (GLsizei)height;
196 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, (void*)mTextureBuffer[i]);
197
198 glBindTexture(GL_TEXTURE_2D, glid);
199 for (GLint y = 0; y < h; ++y)
200 {
201 const void* pixels = &mTextureBuffer[i][(h - 1 - y) * w * 4];
202 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
203 }
204 }
205 else
206 {
207 glBindTexture(GL_TEXTURE_2D, glid);
208 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, mProjectionViews[i].subImage.imageRect.extent.width, mProjectionViews[i].subImage.imageRect.extent.height);
209 }
210 */
211
212 glBindTexture(GL_TEXTURE_2D, 0);
213 glBindFramebuffer(GL_FRAMEBUFFER, oldfb);
214 }
215
216private:
217 XrGraphicsBindingOpenGLWin32KHR mGraphicsBinding;
218 std::vector<std::vector<XrSwapchainImageOpenGLKHR> > mImages;
219 std::vector<std::vector<GLuint>> mFramebuffers;
220};
221std::shared_ptr<IRenderer> CreateOpenGLRenderer()
222{
223 return std::make_shared<OpenGLRenderer>();
224}
225#endif
226
227#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
228struct OpenGLESRenderer : public IRenderer {
229 OpenGLESRenderer() { }
230 virtual ~OpenGLESRenderer() override
231 {
232 for (auto& frame_buffer : mFramebuffers)
233 {
234 glDeleteFramebuffers(frame_buffer.size(), frame_buffer.data());
235 }
236 mFramebuffers.clear();
237 }
238
239 const XrBaseInStructure* GetBindings() const override { return reinterpret_cast<const XrBaseInStructure*>(&mGraphicsBinding); }
240
241 const char* GetExtension() const override { return XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME; }
242
243 bool Setup() override
244 {
245#if defined(XR_USE_PLATFORM_WIN32)
246 if (!GL_INITIALIZED)
247 GL_INITIALIZED = gladLoadGLLoader(getProcAddress) ? true : false;
248
249 if (!GL_INITIALIZED)
250 {
251 MMechostr(MSKRUNTIME, "sOpenXr initialize : Could not load OpenGL, creates a SO3Window first\n");
252 return false;
253 }
254#endif
255
256 // --- Make sure runtime supports the OpenGL extension
257
258 return true;
259 }
260
261 bool Check(XrSystemId systemId, XrInstance instance) override
262 {
263 XrResult result;
264 XrGraphicsRequirementsOpenGLESKHR opengl_reqs = { XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR, XR_NULL_HANDLE };
265 PFN_xrGetOpenGLESGraphicsRequirementsKHR pfnGetOpenGLESGraphicsRequirementsKHR = XR_NULL_HANDLE;
266 result = xrGetInstanceProcAddr(instance, "xrGetOpenGLESGraphicsRequirementsKHR", (PFN_xrVoidFunction*)&pfnGetOpenGLESGraphicsRequirementsKHR);
267 if (!xr_result(instance, result, "Failed to get OpenGL graphics requirements function!"))
268 return false;
269
270 result = pfnGetOpenGLESGraphicsRequirementsKHR(instance, systemId, &opengl_reqs);
271 if (!xr_result(instance, result, "Failed to get OpenGL graphics requirements!"))
272 return false;
273
274 // On OpenGL we never fail this check because the version requirement is not useful.
275 // Other APIs may have more useful requirements.
276 check_opengl_version(&opengl_reqs);
277
278# if defined(XR_USE_PLATFORM_ANDROID)
279 if ((eglGetCurrentContext() == EGL_NO_CONTEXT) || (eglGetCurrentSurface(EGL_DRAW) == EGL_NO_SURFACE))
280 return false;
281
282 mGraphicsBinding = XrGraphicsBindingOpenGLESAndroidKHR{ XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR };
283 mGraphicsBinding.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
284 mGraphicsBinding.config = (EGLConfig)0;
285 mGraphicsBinding.context = eglGetCurrentContext();
286# endif
287
288 MMechostr(MSKRUNTIME, "[OPENXR]: Using OpenGL version: %s\n", glGetString(GL_VERSION));
289 MMechostr(MSKRUNTIME, "[OPENXR]: Using OpenGL Renderer: %s\n", glGetString(GL_RENDERER));
290 return true;
291 }
292
293 bool GetSwapchainFormat(XrInstance instance, XrSession session, int64_t &format) override
294 {
295 XrResult result;
296 uint32_t swapchain_format_count;
297 result = xrEnumerateSwapchainFormats(session, 0, &swapchain_format_count, XR_NULL_HANDLE);
298 if (!xr_result(instance, result, "Failed to get number of supported swapchain formats"))
299 return false;
300
301 MMechostr(MSKRUNTIME, "[OPENXR]: Runtime supports %d swapchain formats\n", swapchain_format_count);
302 std::vector<int64_t> swapchain_formats(swapchain_format_count);
303 result = xrEnumerateSwapchainFormats(session, swapchain_format_count, &swapchain_format_count, swapchain_formats.data());
304 if (!xr_result(instance, result, "Failed to enumerate swapchain formats"))
305 return false;
306
307 // SRGB is usually the best choice. Selection logic should be expanded though.
308 int64_t preferred_swapchain_format = GL_RGBA8; //GL_RGBA16;
309 format = swapchain_formats[0];
310
311 for (auto& swapchain_format : swapchain_formats)
312 {
313 MMechostr(MSKRUNTIME, "[OPENXR]: Supported GL format: %#lx\n", swapchain_format);
314 if (swapchain_format == preferred_swapchain_format)
315 {
316 format = swapchain_format;
317 MMechostr(MSKRUNTIME, "[OPENXR]: Using preferred swapchain format %#lx\n", format);
318 }
319 }
320
321 if (format != preferred_swapchain_format)
322 MMechostr(MSKRUNTIME, "[OPENXR]: Using non preferred swapchain format %#lx\n", format);
323
324 return true;
325 }
326
327 bool CreateSwapchainImage(XrInstance instance, uint32 viewCount, XrSwapchain swapchain, uint32_t pos) override
328 {
329 XrResult result;
330
331 if (mImages.empty())
332 mImages.resize(viewCount);
333
334 if (mFramebuffers.empty())
335 mFramebuffers.resize(viewCount);
336
337 uint32_t swapchain_length;
338 result = xrEnumerateSwapchainImages(swapchain, 0, &swapchain_length, XR_NULL_HANDLE);
339 if (!xr_result(instance, result, "Failed to enumerate swapchains"))
340 return false;
341
342 mImages[pos].resize(swapchain_length, { XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR , NULL });
343
344 result = xrEnumerateSwapchainImages(swapchain, swapchain_length, &swapchain_length, (XrSwapchainImageBaseHeader*)mImages[pos].data());
345 if (!xr_result(instance, result, "Failed to enumerate swapchain images"))
346 return false;
347
348 mFramebuffers[pos].resize(mImages[pos].size());
349 glGenFramebuffers(mFramebuffers[pos].size(), mFramebuffers[pos].data());
350
351 return true;
352 }
353
354 void UpdateTextures(SCOL_PTR_TYPE leftTexture, SCOL_PTR_TYPE rightTexture, uint32_t acquiredIndex, int32_t width, int32_t height, uint32_t pos) override
355 {
356 GLenum err;
357 GLuint glid = mImages[pos][acquiredIndex].image;
358 GLint oldfb = 0;
359 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldfb);
360
361 GLuint eyetex = (GLuint)((pos == 0) ? leftTexture : rightTexture);
362
363 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffers[pos][acquiredIndex]);
364 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, eyetex, 0);
365 err = glGetError();
366 if (err != GL_NO_ERROR)
367 return;
368
369 glBindTexture(GL_TEXTURE_2D, glid);
370 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
371
372 err = glGetError();
373 if (err != GL_NO_ERROR)
374 return;
375
376 glBindTexture(GL_TEXTURE_2D, 0);
377 glBindFramebuffer(GL_FRAMEBUFFER, oldfb);
378 }
379
380private:
381#ifdef XR_USE_PLATFORM_ANDROID
382 XrGraphicsBindingOpenGLESAndroidKHR mGraphicsBinding;
383#endif
384
385 std::vector<std::vector<XrSwapchainImageOpenGLESKHR> > mImages;
386 std::vector<std::vector<GLuint>> mFramebuffers;
387};
388std::shared_ptr<IRenderer> CreateOpenGLESRenderer()
389{
390 return std::make_shared<OpenGLESRenderer>();
391}
392#endif
393
394#ifdef XR_USE_GRAPHICS_API_D3D11
395
396IDXGIAdapter1 *d3d_get_adapter(LUID &adapter_luid)
397{
398 // Turn the LUID into a specific graphics device adapter
399 IDXGIAdapter1 *final_adapter = nullptr;
400 IDXGIAdapter1 *curr_adapter = nullptr;
401 IDXGIFactory1 *dxgi_factory;
402 DXGI_ADAPTER_DESC1 adapter_desc;
403
404 CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void **)(&dxgi_factory));
405
406 int curr = 0;
407 while (dxgi_factory->EnumAdapters1(curr++, &curr_adapter) == S_OK)
408 {
409 curr_adapter->GetDesc1(&adapter_desc);
410
411 if (memcmp(&adapter_desc.AdapterLuid, &adapter_luid, sizeof(&adapter_luid)) == 0) {
412 final_adapter = curr_adapter;
413 break;
414 }
415 curr_adapter->Release();
416 curr_adapter = nullptr;
417 }
418 dxgi_factory->Release();
419 return final_adapter;
420}
421
422
423struct D3D11Renderer : public IRenderer {
424 D3D11Renderer()
425 {
426 mDevice = nullptr;
427 }
428
429 virtual ~D3D11Renderer() override
430 {
431 }
432
433 const XrBaseInStructure* GetBindings() const override { return reinterpret_cast<const XrBaseInStructure*>(&mGraphicsBinding); }
434
435 const char* GetExtension() const override { return XR_KHR_D3D11_ENABLE_EXTENSION_NAME; }
436
437 bool Setup() override { return true; }
438
439 bool Check(XrSystemId systemId, XrInstance instance) override
440 {
441 XrResult result;
442
443 PFN_xrGetD3D11GraphicsRequirementsKHR ext_xrGetD3D11GraphicsRequirementsKHR = NULL;
444 result = xrGetInstanceProcAddr(instance, "xrGetD3D11GraphicsRequirementsKHR", (PFN_xrVoidFunction *)(&ext_xrGetD3D11GraphicsRequirementsKHR));
445 if (!xr_result(instance, result, "Failed to get D3D11 graphics requirements function!"))
446 return false;
447
448 XrGraphicsRequirementsD3D11KHR requirement = { XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR };
449 result = ext_xrGetD3D11GraphicsRequirementsKHR(instance, systemId, &requirement);
450 if (!xr_result(instance, result, "Failed to get OpenGL graphics requirements!"))
451 return false;
452
453 //Get SO3 device
454 mDevice = (ID3D11Device*)(void*(__cdecl *)())SCgetExtra("GetRenderDevice");
455 if (mDevice == nullptr)
456 return false;
457
458 mGraphicsBinding = XrGraphicsBindingD3D11KHR{ XR_TYPE_GRAPHICS_BINDING_D3D11_KHR };
459 mGraphicsBinding.device = mDevice;
460 return true;
461 }
462
463 bool GetSwapchainFormat(XrInstance instance, XrSession session, int64_t &format) override
464 {
465 XrResult result;
466 uint32_t swapchain_format_count;
467 result = xrEnumerateSwapchainFormats(session, 0, &swapchain_format_count, XR_NULL_HANDLE);
468 if (!xr_result(instance, result, "Failed to get number of supported swapchain formats"))
469 return false;
470
471 MMechostr(MSKRUNTIME, "[OPENXR]: Runtime supports %d swapchain formats\n", swapchain_format_count);
472 std::vector<int64_t> swapchain_formats(swapchain_format_count);
473 result = xrEnumerateSwapchainFormats(session, swapchain_format_count, &swapchain_format_count, swapchain_formats.data());
474 if (!xr_result(instance, result, "Failed to enumerate swapchain formats"))
475 return false;
476
477 // SRGB is usually the best choice. Selection logic should be expanded though.
478 int64_t preferred_swapchain_format = DXGI_FORMAT_R8G8B8A8_UNORM; //GL_RGBA16;
479 format = swapchain_formats[0];
480
481 for (auto& swapchain_format : swapchain_formats)
482 {
483 MMechostr(MSKRUNTIME, "[OPENXR]: Supported DX format: %#lx\n", swapchain_format);
484 if (swapchain_format == preferred_swapchain_format)
485 {
486 format = swapchain_format;
487 MMechostr(MSKRUNTIME, "[OPENXR]: Using preferred swapchain format %#lx\n", format);
488 }
489 }
490
491 if (format != preferred_swapchain_format)
492 MMechostr(MSKRUNTIME, "[OPENXR]: Using non preferred swapchain format %#lx\n", format);
493
494 return true;
495 }
496
497 bool CreateSwapchainImage(XrInstance instance, uint32 viewCount, XrSwapchain swapchain, uint32_t pos) override
498 {
499 XrResult result;
500
501 if (mImages.empty())
502 mImages.resize(viewCount);
503
504 uint32_t swapchain_length;
505 result = xrEnumerateSwapchainImages(swapchain, 0, &swapchain_length, XR_NULL_HANDLE);
506 if (!xr_result(instance, result, "Failed to enumerate swapchains"))
507 return false;
508
509 mImages[pos].resize(swapchain_length, { XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR , NULL });
510
511 result = xrEnumerateSwapchainImages(swapchain, swapchain_length, &swapchain_length, (XrSwapchainImageBaseHeader*)mImages[pos].data());
512 if (!xr_result(instance, result, "Failed to enumerate swapchain images"))
513 return false;
514
515 return true;
516 }
517
518 void UpdateTextures(SCOL_PTR_TYPE leftTexture, SCOL_PTR_TYPE rightTexture, uint32_t acquiredIndex, int32_t width, int32_t height, uint32_t pos) override
519 {
520 ID3D11DeviceContext* d3DContext = nullptr;
521 mDevice->GetImmediateContext(&d3DContext);
522 d3DContext->CopyResource(mImages[pos][acquiredIndex].texture, (ID3D11Texture2D*)((pos == 0) ? leftTexture : rightTexture));
523 }
524
525private:
526 XrGraphicsBindingD3D11KHR mGraphicsBinding;
527 std::vector<std::vector<XrSwapchainImageD3D11KHR> > mImages;
528 ID3D11Device* mDevice;
529};
530std::shared_ptr<IRenderer> CreateD3D11Renderer()
531{
532 return std::make_shared<D3D11Renderer>();
533}
534#endif
535
536std::shared_ptr<IRenderer> CreateRenderer(RenderSystem rsys)
537{
538#if defined(XR_USE_GRAPHICS_API_OPENGL)
539 if (rsys == XR_OPENGL_RENDERER)
540 return CreateOpenGLRenderer();
541#endif
542
543#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
544 if (rsys == XR_OPENGL_RENDERER)
545 return CreateOpenGLESRenderer();
546#endif
547
548#if defined(XR_USE_GRAPHICS_API_D3D11)
549 if (rsys == XR_DIRECTX11_RENDERER)
550 return CreateD3D11Renderer();
551#endif
552
553 return nullptr;
554}