void PluginContainerProxy::releaseSceneTexture(const gpu::TexturePointer& texture) { Q_ASSERT(QThread::currentThread() == qApp->thread()); auto& framebufferMap = qApp->_lockedFramebufferMap; Q_ASSERT(framebufferMap.contains(texture)); auto framebufferPointer = framebufferMap[texture]; framebufferMap.remove(texture); auto framebufferCache = DependencyManager::get<FramebufferCache>(); framebufferCache->releaseFramebuffer(framebufferPointer); }
void vkeGameRendererDynamic::initFramebuffer(uint32_t inWidth, uint32_t inHeight){ /*---------------------------------------------------------- Create the framebuffer ----------------------------------------------------------*/ VulkanDC *dc = VulkanDC::Get(); VulkanDC::Device *device = dc->getDefaultDevice(); VulkanDC::Device::Queue *queue = dc->getDefaultQueue(); const VkFormat depthFmt = VK_FORMAT_D24_UNORM_S8_UINT; const VkFormat colorFmt = VK_FORMAT_R8G8B8A8_UNORM; /* If framebuffers already exist, release them. */ if (m_framebuffers[0] != VK_NULL_HANDLE){ releaseFramebuffer(); } /* Update the frame dimensions. */ m_width = inWidth; m_height = inHeight; /* Specify usage for the frame buffer attachments. */ VkImageUsageFlagBits gBufferFlags = (VkImageUsageFlagBits)(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); VkImageUsageFlagBits sBufferFlags = (VkImageUsageFlagBits)(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); /* Create the depth attachment image and image view. */ m_depth_attachment.format = depthFmt; imageCreateAndBind(&m_depth_attachment.image, &m_depth_attachment.memory, depthFmt, VK_IMAGE_TYPE_2D, m_width, m_height, 1, 1, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, getSamples()); imageViewCreate(&m_depth_attachment.view, m_depth_attachment.image, VK_IMAGE_VIEW_TYPE_2D, depthFmt); /* Create the color attachment image and image view. */ m_color_attachment.format = colorFmt; imageCreateAndBind(&m_color_attachment.image, &m_color_attachment.memory, colorFmt, VK_IMAGE_TYPE_2D, m_width, m_height, 1, 1, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, gBufferFlags, VK_IMAGE_TILING_OPTIMAL, getSamples()); imageViewCreate(&m_color_attachment.view, m_color_attachment.image, VK_IMAGE_VIEW_TYPE_2D, colorFmt); /* Create the resolve attachment image and image view. */ for (uint32_t i = 0; i < 2; ++i){ m_resolve_attachment[i].format = colorFmt; imageCreateAndBind(&m_resolve_attachment[i].image, &m_resolve_attachment[i].memory, colorFmt, VK_IMAGE_TYPE_2D, m_width, m_height, 1, 1, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, gBufferFlags, VK_IMAGE_TILING_OPTIMAL, VK_SAMPLE_COUNT_1_BIT); imageViewCreate(&m_resolve_attachment[i].view, m_resolve_attachment[i].image, VK_IMAGE_VIEW_TYPE_2D, colorFmt); } /* Put the image views into a temporary array to pass to the framebuffer create info struct. */ /* Setup the framebuffer create info struct. */ for (uint32_t i = 0; i < 2; ++i){ VkImageView views[] = { m_color_attachment.view, m_depth_attachment.view, m_resolve_attachment[i].view }; VkFramebufferCreateInfo fbInfo = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO }; fbInfo.renderPass = m_render_pass; fbInfo.attachmentCount = 3; fbInfo.pAttachments = views; fbInfo.width = m_width; fbInfo.height = m_height; fbInfo.layers = 1; /* Create 2 framebuffers for ping pong. */ VKA_CHECK_ERROR(vkCreateFramebuffer(device->getVKDevice(), &fbInfo, NULL, &m_framebuffers[i]), "Could not create framebuffer.\n"); } }
void GraphicsEngine::render_performFrame() { // Some plugins process message events, allowing paintGL to be called reentrantly. _renderFrameCount++; auto lastPaintBegin = usecTimestampNow(); PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount); PerformanceTimer perfTimer("paintGL"); DisplayPluginPointer displayPlugin; { PROFILE_RANGE(render, "/getActiveDisplayPlugin"); displayPlugin = qApp->getActiveDisplayPlugin(); } { PROFILE_RANGE(render, "/pluginBeginFrameRender"); // If a display plugin loses it's underlying support, it // needs to be able to signal us to not use it if (!displayPlugin->beginFrameRender(_renderFrameCount)) { QMetaObject::invokeMethod(qApp, "updateDisplayMode"); return; } } RenderArgs renderArgs; glm::mat4 HMDSensorPose; glm::mat4 eyeToWorld; glm::mat4 sensorToWorld; ViewFrustum viewFrustum; bool isStereo; glm::mat4 stereoEyeOffsets[2]; glm::mat4 stereoEyeProjections[2]; { QMutexLocker viewLocker(&_renderArgsMutex); renderArgs = _appRenderArgs._renderArgs; // don't render if there is no context. if (!_appRenderArgs._renderArgs._context) { return; } HMDSensorPose = _appRenderArgs._headPose; eyeToWorld = _appRenderArgs._eyeToWorld; sensorToWorld = _appRenderArgs._sensorToWorld; isStereo = _appRenderArgs._isStereo; for_each_eye([&](Eye eye) { stereoEyeOffsets[eye] = _appRenderArgs._eyeOffsets[eye]; stereoEyeProjections[eye] = _appRenderArgs._eyeProjections[eye]; }); viewFrustum = _appRenderArgs._renderArgs.getViewFrustum(); } { PROFILE_RANGE(render, "/gpuContextReset"); getGPUContext()->beginFrame(_appRenderArgs._view, HMDSensorPose); // Reset the gpu::Context Stages // Back to the default framebuffer; gpu::doInBatch("Application_render::gpuContextReset", getGPUContext(), [&](gpu::Batch& batch) { batch.resetStages(); }); if (isStereo) { renderArgs._context->enableStereo(true); renderArgs._context->setStereoProjections(stereoEyeProjections); renderArgs._context->setStereoViews(stereoEyeOffsets); } } gpu::FramebufferPointer finalFramebuffer; QSize finalFramebufferSize; { PROFILE_RANGE(render, "/getOutputFramebuffer"); // Primary rendering pass auto framebufferCache = DependencyManager::get<FramebufferCache>(); finalFramebufferSize = framebufferCache->getFrameBufferSize(); // Final framebuffer that will be handed to the display-plugin finalFramebuffer = framebufferCache->getFramebuffer(); } if (!_programsCompiled.load()) { gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { batch.setFramebuffer(finalFramebuffer); batch.enableSkybox(true); batch.enableStereo(isStereo); batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() }); _splashScreen->render(batch, viewFrustum); }); } else { { PROFILE_RANGE(render, "/renderOverlay"); PerformanceTimer perfTimer("renderOverlay"); // NOTE: There is no batch associated with this renderArgs // the ApplicationOverlay class assumes it's viewport is setup to be the device size renderArgs._viewport = glm::ivec4(0, 0, qApp->getDeviceSize()); qApp->getApplicationOverlay().renderOverlay(&renderArgs); } { PROFILE_RANGE(render, "/updateCompositor"); qApp->getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld); } { PROFILE_RANGE(render, "/runRenderFrame"); renderArgs._hudOperator = displayPlugin->getHUDOperator(); renderArgs._hudTexture = qApp->getApplicationOverlay().getOverlayTexture(); renderArgs._blitFramebuffer = finalFramebuffer; render_runRenderFrame(&renderArgs); } } auto frame = getGPUContext()->endFrame(); frame->frameIndex = _renderFrameCount; frame->framebuffer = finalFramebuffer; frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) { auto frameBufferCache = DependencyManager::get<FramebufferCache>(); if (frameBufferCache) { frameBufferCache->releaseFramebuffer(framebuffer); } }; // deliver final scene rendering commands to the display plugin { PROFILE_RANGE(render, "/pluginOutput"); PerformanceTimer perfTimer("pluginOutput"); _renderLoopCounter.increment(); displayPlugin->submitFrame(frame); } // Reset the framebuffer and stereo state renderArgs._blitFramebuffer.reset(); renderArgs._context->enableStereo(false); #if !defined(DISABLE_QML) { auto stats = Stats::getInstance(); if (stats) { stats->setRenderDetails(renderArgs._details); } } #endif uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin; _frameTimingsScriptingInterface.addValue(lastPaintDuration); }