| 270 | } |
| 271 | |
| 272 | void NativeXr::BeginFrame() |
| 273 | { |
| 274 | assert(m_engineImpl != nullptr); |
| 275 | assert(m_session != nullptr); |
| 276 | assert(m_frame == nullptr); |
| 277 | |
| 278 | bool shouldEndSession{}; |
| 279 | bool shouldRestartSession{}; |
| 280 | m_frame = m_session->GetNextFrame(shouldEndSession, shouldRestartSession, [this](void* texturePointer){ |
| 281 | auto texPtr = reinterpret_cast<uintptr_t>(texturePointer); |
| 282 | auto it = m_texturesToFrameBuffers.find(texPtr); |
| 283 | if (it != m_texturesToFrameBuffers.end()) |
| 284 | { |
| 285 | m_texturesToFrameBuffers.erase(it); |
| 286 | } |
| 287 | }); |
| 288 | |
| 289 | // Ending a session outside of calls to EndSession() is currently not supported. |
| 290 | assert(!shouldEndSession); |
| 291 | assert(m_frame != nullptr); |
| 292 | |
| 293 | m_activeFrameBuffers.reserve(m_frame->Views.size()); |
| 294 | for (const auto& view : m_frame->Views) |
| 295 | { |
| 296 | auto colorTexPtr = reinterpret_cast<uintptr_t>(view.ColorTexturePointer); |
| 297 | |
| 298 | auto it = m_texturesToFrameBuffers.find(colorTexPtr); |
| 299 | if (it == m_texturesToFrameBuffers.end() || it->second.get()->Width != view.ColorTextureSize.Width || it->second.get()->Height != view.ColorTextureSize.Height) |
| 300 | { |
| 301 | // if a texture width or height is 0, bgfx will assert (can't create 0 sized texture). Asserting here instead of deeper in bgfx rendering |
| 302 | assert(view.ColorTextureSize.Width); |
| 303 | assert(view.ColorTextureSize.Height); |
| 304 | assert(view.ColorTextureSize.Width == view.DepthTextureSize.Width); |
| 305 | assert(view.ColorTextureSize.Height == view.DepthTextureSize.Height); |
| 306 | |
| 307 | // Create textures with the desired size. It will be freed and replaced with overrideInternal call |
| 308 | // This is mandatory as overrideInternal do not update texture size. |
| 309 | // And size is used for determining viewport when rendering to texture. |
| 310 | auto colorTextureFormat = XrTextureFormatToBgfxFormat(view.ColorTextureFormat); |
| 311 | auto colorTex = bgfx::createTexture2D(static_cast<uint16_t>(view.ColorTextureSize.Width), static_cast<uint16_t>(view.ColorTextureSize.Height), false, 1, colorTextureFormat, BGFX_TEXTURE_RT); |
| 312 | |
| 313 | auto depthTextureFormat = XrTextureFormatToBgfxFormat(view.DepthTextureFormat); |
| 314 | auto depthTex = bgfx::createTexture2D(static_cast<uint16_t>(view.DepthTextureSize.Width), static_cast<uint16_t>(view.DepthTextureSize.Height), false, 1, depthTextureFormat, BGFX_TEXTURE_RT); |
| 315 | |
| 316 | // Force BGFX to create the texture now, which is necessary in order to use overrideInternal. |
| 317 | bgfx::frame(); |
| 318 | |
| 319 | bgfx::overrideInternal(colorTex, colorTexPtr); |
| 320 | bgfx::overrideInternal(depthTex, reinterpret_cast<uintptr_t>(view.DepthTexturePointer)); |
| 321 | |
| 322 | std::array<bgfx::Attachment, 2> attachments{}; |
| 323 | attachments[0].init(colorTex); |
| 324 | attachments[1].init(depthTex); |
| 325 | auto frameBuffer = bgfx::createFrameBuffer(static_cast<uint8_t>(attachments.size()), attachments.data(), false); |
| 326 | |
| 327 | auto fbPtr = m_engineImpl->GetFrameBufferManager().CreateNew( |
| 328 | frameBuffer, |
| 329 | static_cast<uint16_t>(view.ColorTextureSize.Width), |
nothing calls this directly
no test coverage detected