From c0859ffd4caf3e44deddba8f91583d2dfa4e70e1 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 20 Jul 2015 14:33:10 -0700 Subject: [PATCH 1/5] Removing some dead forward declarations --- interface/src/Application.cpp | 26 ++------------------------ interface/src/ui/ApplicationOverlay.h | 2 -- libraries/ui/src/OffscreenUi.cpp | 1 - 3 files changed, 2 insertions(+), 27 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ce156354fb..24b20a830e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -9,11 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include +#include "Application.h" -#include -#include -#include +#include #include #include @@ -92,7 +90,6 @@ #include #include -#include "Application.h" #include "AudioClient.h" #include "DiscoverabilityManager.h" #include "GLCanvas.h" @@ -766,25 +763,6 @@ void Application::initializeGL() { } #endif - qCDebug(interfaceapp) << "GL Version: " << QString((const char*) glGetString(GL_VERSION)); - qCDebug(interfaceapp) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION)); - qCDebug(interfaceapp) << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR)); - qCDebug(interfaceapp) << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER)); - - #ifdef WIN32 - GLenum err = glewInit(); - if (GLEW_OK != err) { - /* Problem: glewInit failed, something is seriously wrong. */ - qCDebug(interfaceapp, "Error: %s\n", glewGetErrorString(err)); - } - qCDebug(interfaceapp, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION)); - - if (wglewGetExtension("WGL_EXT_swap_control")) { - int swapInterval = wglGetSwapIntervalEXT(); - qCDebug(interfaceapp, "V-Sync is %s\n", (swapInterval > 0 ? "ON" : "OFF")); - } - #endif - #if defined(Q_OS_LINUX) // TODO: Write the correct code for Linux... /* if (wglewGetExtension("WGL_EXT_swap_control")) { diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 92485fba82..532fea23dc 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -13,7 +13,6 @@ #define hifi_ApplicationOverlay_h #include -class QOpenGLFramebufferObject; // Handles the drawing of the overlays to the screen // TODO, move divide up the rendering, displaying and input handling @@ -50,7 +49,6 @@ private: gpu::TexturePointer _overlayDepthTexture; gpu::TexturePointer _overlayColorTexture; gpu::FramebufferPointer _overlayFramebuffer; - }; #endif // hifi_ApplicationOverlay_h diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 916cdf8659..d581f12473 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -9,7 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "OffscreenUi.h" -#include #include #include #include From 94d57a2e43bcb6c1d3f8810e9221b43b45cca140 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 20 Jul 2015 16:51:01 -0700 Subject: [PATCH 2/5] fixing missing glew init --- interface/src/Application.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 24b20a830e..096859e723 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -763,6 +763,20 @@ void Application::initializeGL() { } #endif +#ifdef WIN32 + GLenum err = glewInit(); + if (GLEW_OK != err) { + /* Problem: glewInit failed, something is seriously wrong. */ + qCDebug(interfaceapp, "Error: %s\n", glewGetErrorString(err)); + } + qCDebug(interfaceapp, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION)); + + if (wglewGetExtension("WGL_EXT_swap_control")) { + int swapInterval = wglGetSwapIntervalEXT(); + qCDebug(interfaceapp, "V-Sync is %s\n", (swapInterval > 0 ? "ON" : "OFF")); + } +#endif + #if defined(Q_OS_LINUX) // TODO: Write the correct code for Linux... /* if (wglewGetExtension("WGL_EXT_swap_control")) { From c3a2b72c139a77d01162925a538c9fafb5279260 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 20 Jul 2015 17:26:26 -0700 Subject: [PATCH 3/5] Breaking framebuffer ops out of texture cache --- interface/src/Application.cpp | 22 ++- interface/src/Application.h | 1 - interface/src/devices/OculusManager.cpp | 5 +- libraries/gpu/src/gpu/Framebuffer.h | 44 +++--- libraries/gpu/src/gpu/Texture.cpp | 2 +- .../src/DeferredLightingEffect.cpp | 34 ++--- .../render-utils/src/FramebufferCache.cpp | 112 ++++++++++++++ libraries/render-utils/src/FramebufferCache.h | 59 +++++++ libraries/render-utils/src/TextureCache.cpp | 144 +----------------- libraries/render-utils/src/TextureCache.h | 49 ------ 10 files changed, 236 insertions(+), 236 deletions(-) create mode 100644 libraries/render-utils/src/FramebufferCache.cpp create mode 100644 libraries/render-utils/src/FramebufferCache.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 096859e723..0ee15246e7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -85,6 +86,7 @@ #include #include #include +#include #include #include #include @@ -263,6 +265,8 @@ bool setupEssentials(int& argc, char** argv) { auto audioScope = DependencyManager::set(); auto deferredLightingEffect = DependencyManager::set(); auto textureCache = DependencyManager::set(); + auto framebufferCache = DependencyManager::set(); + auto animationCache = DependencyManager::set(); auto ddeFaceTracker = DependencyManager::set(); auto modelBlender = DependencyManager::set(); @@ -730,6 +734,7 @@ Application::~Application() { DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); + DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); @@ -889,6 +894,8 @@ void Application::paintGL() { PerformanceWarning warn(showWarnings, "Application::paintGL()"); resizeGL(); + glEnable(GL_LINE_SMOOTH); + { PerformanceTimer perfTimer("renderOverlay"); @@ -899,7 +906,6 @@ void Application::paintGL() { _applicationOverlay.renderOverlay(&renderArgs); } - glEnable(GL_LINE_SMOOTH); if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || _myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, _myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN); @@ -976,7 +982,7 @@ void Application::paintGL() { { gpu::Batch batch; - auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); + auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); batch.setFramebuffer(primaryFbo); // clear the normal and specular buffers batch.clearFramebuffer( @@ -987,7 +993,7 @@ void Application::paintGL() { vec4(vec3(0), 1), 1.0, 0.0); // Viewport is assigned to the size of the framebuffer - QSize size = DependencyManager::get()->getFrameBufferSize(); + QSize size = DependencyManager::get()->getFrameBufferSize(); renderArgs._viewport = glm::ivec4(0, 0, size.width(), size.height()); batch.setViewportTransform(renderArgs._viewport); renderArgs._context->render(batch); @@ -1003,7 +1009,7 @@ void Application::paintGL() { { auto geometryCache = DependencyManager::get(); - auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); + auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); gpu::Batch batch; batch.blit(primaryFbo, glm::ivec4(0, 0, _renderResolution.x, _renderResolution.y), nullptr, glm::ivec4(0, 0, _glWidget->getDeviceSize().width(), _glWidget->getDeviceSize().height())); @@ -1077,7 +1083,7 @@ void Application::resizeGL() { if (_renderResolution != toGlm(renderSize)) { _renderResolution = toGlm(renderSize); - DependencyManager::get()->setFrameBufferSize(renderSize); + DependencyManager::get()->setFrameBufferSize(renderSize); updateProjectionMatrix(); } @@ -2997,7 +3003,7 @@ PickRay Application::computePickRay(float x, float y) const { } QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) { - auto primaryFramebuffer = DependencyManager::get()->getPrimaryFramebuffer(); + auto primaryFramebuffer = DependencyManager::get()->getPrimaryFramebuffer(); glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer)); // clear the alpha channel so the background is transparent @@ -3475,11 +3481,11 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi // set the bounds of rear mirror view gpu::Vec4i viewport; if (billboard) { - QSize size = DependencyManager::get()->getFrameBufferSize(); + QSize size = DependencyManager::get()->getFrameBufferSize(); viewport = gpu::Vec4i(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); } else { // if not rendering the billboard, the region is in device independent coordinates; must convert to device - QSize size = DependencyManager::get()->getFrameBufferSize(); + QSize size = DependencyManager::get()->getFrameBufferSize(); float ratio = (float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale(); int x = region.x() * ratio, y = region.y() * ratio, width = region.width() * ratio, height = region.height() * ratio; viewport = gpu::Vec4i(x, size.height() - y - height, width, height); diff --git a/interface/src/Application.h b/interface/src/Application.h index 2f18104f86..05d06d6272 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -34,7 +34,6 @@ #include #include #include -#include #include #include diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 9395584a66..9a9ec63e3b 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -644,7 +645,7 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const return; } - auto primaryFBO = DependencyManager::get()->getPrimaryFramebuffer(); + auto primaryFBO = DependencyManager::get()->getPrimaryFramebuffer(); glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFBO)); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -704,7 +705,7 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const _activeEye = ovrEye_Count; gpu::FramebufferPointer finalFbo; - finalFbo = DependencyManager::get()->getPrimaryFramebuffer(); + finalFbo = DependencyManager::get()->getPrimaryFramebuffer(); glBindFramebuffer(GL_FRAMEBUFFER, 0); // restore our normal viewport diff --git a/libraries/gpu/src/gpu/Framebuffer.h b/libraries/gpu/src/gpu/Framebuffer.h index 50f42ed4fb..5a1504d25c 100755 --- a/libraries/gpu/src/gpu/Framebuffer.h +++ b/libraries/gpu/src/gpu/Framebuffer.h @@ -1,19 +1,21 @@ -// -// Framebuffer.h -// libraries/gpu/src/gpu -// -// Created by Sam Gateau on 4/12/2015. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -#ifndef hifi_gpu_Framebuffer_h -#define hifi_gpu_Framebuffer_h - -#include "Texture.h" +// +// Framebuffer.h +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 4/12/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_gpu_Framebuffer_h +#define hifi_gpu_Framebuffer_h + +#include "Texture.h" #include +class QImage; + namespace gpu { typedef Element Format; @@ -130,7 +132,9 @@ public: void resize( uint16 width, uint16 height, uint16 samples = 1 ); static const uint32 MAX_NUM_RENDER_BUFFERS = 8; - static uint32 getMaxNumRenderBuffers() { return MAX_NUM_RENDER_BUFFERS; } + static uint32 getMaxNumRenderBuffers() { return MAX_NUM_RENDER_BUFFERS; } + + void getImage(QImage* result) const; protected: SwapchainPointer _swapchain; @@ -151,10 +155,10 @@ protected: // Non exposed Framebuffer(const Framebuffer& framebuffer) {} Framebuffer() {} - - // This shouldn't be used by anything else than the Backend class with the proper casting. - mutable GPUObject* _gpuObject = NULL; - void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } + + // This shouldn't be used by anything else than the Backend class with the proper casting. + mutable GPUObject* _gpuObject = NULL; + void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } GPUObject* getGPUObject() const { return _gpuObject; } friend class Backend; }; @@ -162,4 +166,4 @@ typedef std::shared_ptr FramebufferPointer; } -#endif \ No newline at end of file +#endif diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 69c00336f1..8a55603cb7 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -10,7 +10,7 @@ // #include "Texture.h" -#include + #include #include diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 582864991a..4f7121b7a7 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -23,6 +23,7 @@ #include "GeometryCache.h" #include "RenderUtil.h" #include "TextureCache.h" +#include "FramebufferCache.h" #include "simple_vert.h" @@ -215,8 +216,6 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu } void DeferredLightingEffect::prepare(RenderArgs* args) { - - auto textureCache = DependencyManager::get(); gpu::Batch batch; // clear the normal and specular buffers @@ -232,25 +231,23 @@ void DeferredLightingEffect::render(RenderArgs* args) { gpu::Batch batch; // perform deferred lighting, rendering to free fbo - auto textureCache = DependencyManager::get(); + auto framebufferCache = DependencyManager::get(); - QSize framebufferSize = textureCache->getFrameBufferSize(); + QSize framebufferSize = framebufferCache->getFrameBufferSize(); // binding the first framebuffer - auto freeFBO = DependencyManager::get()->getSecondaryFramebuffer(); + auto freeFBO = framebufferCache->getSecondaryFramebuffer(); batch.setFramebuffer(freeFBO); batch.setViewportTransform(args->_viewport); batch.clearColorFramebuffer(freeFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); - batch.setResourceTexture(0, textureCache->getPrimaryColorTexture()); - - batch.setResourceTexture(1, textureCache->getPrimaryNormalTexture()); - - batch.setResourceTexture(2, textureCache->getPrimarySpecularTexture()); - - batch.setResourceTexture(3, textureCache->getPrimaryDepthTexture()); + auto primaryFramebuffer = framebufferCache->getPrimaryFramebuffer(); + for (int i = 0; i < 3; ++i) { + batch.setResourceTexture(i, primaryFramebuffer->getRenderBuffer(i)); + } + batch.setResourceTexture(3, primaryFramebuffer->getDepthStencilBuffer()); float sMin = args->_viewport.x / (float)framebufferSize.width(); float sWidth = args->_viewport.z / (float)framebufferSize.width(); @@ -267,7 +264,7 @@ void DeferredLightingEffect::render(RenderArgs* args) { const LightLocations* locations = &_directionalLightLocations; bool shadowsEnabled = _viewState->getShadowsEnabled(); if (shadowsEnabled) { - batch.setResourceTexture(4, textureCache->getShadowFramebuffer()->getDepthStencilBuffer()); + batch.setResourceTexture(4, framebufferCache->getShadowFramebuffer()->getDepthStencilBuffer()); program = _directionalLightShadowMap; locations = &_directionalLightShadowMapLocations; @@ -294,7 +291,7 @@ void DeferredLightingEffect::render(RenderArgs* args) { } batch.setPipeline(program); } - batch._glUniform1f(locations->shadowScale, 1.0f / textureCache->getShadowFramebuffer()->getWidth()); + batch._glUniform1f(locations->shadowScale, 1.0f / framebufferCache->getShadowFramebuffer()->getWidth()); } else { if (useSkyboxCubemap) { @@ -537,12 +534,12 @@ void DeferredLightingEffect::render(RenderArgs* args) { void DeferredLightingEffect::copyBack(RenderArgs* args) { gpu::Batch batch; - auto textureCache = DependencyManager::get(); - QSize framebufferSize = textureCache->getFrameBufferSize(); + auto framebufferCache = DependencyManager::get(); + QSize framebufferSize = framebufferCache->getFrameBufferSize(); - auto freeFBO = DependencyManager::get()->getSecondaryFramebuffer(); + auto freeFBO = framebufferCache->getSecondaryFramebuffer(); - batch.setFramebuffer(textureCache->getPrimaryFramebuffer()); + batch.setFramebuffer(framebufferCache->getPrimaryFramebuffer()); batch.setPipeline(_blitLightBuffer); batch.setResourceTexture(0, freeFBO->getRenderBuffer(0)); @@ -564,7 +561,6 @@ void DeferredLightingEffect::copyBack(RenderArgs* args) { batch.draw(gpu::TRIANGLE_STRIP, 4); - args->_context->syncCache(); args->_context->render(batch); } diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp new file mode 100644 index 0000000000..c699da2e81 --- /dev/null +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -0,0 +1,112 @@ +// +// FramebufferCache.cpp +// interface/src/renderer +// +// Created by Andrzej Kapolka on 8/6/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "FramebufferCache.h" + +#include + +#include + +#include +#include +#include +#include +#include "RenderUtilsLogging.h" + +static QQueue _cachedFramebuffers; + +FramebufferCache::FramebufferCache() { +} + +FramebufferCache::~FramebufferCache() { + _cachedFramebuffers.clear(); +} + +void FramebufferCache::setFrameBufferSize(QSize frameBufferSize) { + //If the size changed, we need to delete our FBOs + if (_frameBufferSize != frameBufferSize) { + _frameBufferSize = frameBufferSize; + _primaryFramebuffer.reset(); + } +} + +void FramebufferCache::createPrimaryFramebuffer() { + _primaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); + + static auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + static auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); + + auto width = _frameBufferSize.width(); + auto height = _frameBufferSize.height(); + + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + auto colorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); + auto normalTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); + auto specularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); + + _primaryFramebuffer->setRenderBuffer(0, colorTexture); + _primaryFramebuffer->setRenderBuffer(1, normalTexture); + _primaryFramebuffer->setRenderBuffer(2, specularTexture); + + + auto depthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler)); + _primaryFramebuffer->setDepthStencilBuffer(depthTexture, depthFormat); +} + +gpu::FramebufferPointer FramebufferCache::getPrimaryFramebuffer() { + if (!_primaryFramebuffer) { + createPrimaryFramebuffer(); + } + return _primaryFramebuffer; +} + +void FramebufferCache::setPrimaryDrawBuffers(gpu::Batch& batch, bool color, bool normal, bool specular) { + GLenum buffers[3]; + int bufferCount = 0; + if (color) { + buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; + } + if (normal) { + buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; + } + if (specular) { + buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; + } + batch._glDrawBuffers(bufferCount, buffers); +} + + +gpu::FramebufferPointer FramebufferCache::getFramebuffer() { + if (_cachedFramebuffers.isEmpty()) { + _cachedFramebuffers.push_back(gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, _frameBufferSize.width(), _frameBufferSize.height()))); + } + gpu::FramebufferPointer result = _cachedFramebuffers.front(); + _cachedFramebuffers.pop_front(); + return result; +} + + +void FramebufferCache::releaseFramebuffer(const gpu::FramebufferPointer& framebuffer) { + _cachedFramebuffers.push_back(framebuffer); +} + +gpu::FramebufferPointer FramebufferCache::getSecondaryFramebuffer() { + static auto _secondaryFramebuffer = getFramebuffer(); + return _secondaryFramebuffer; +} + +gpu::FramebufferPointer FramebufferCache::getShadowFramebuffer() { + if (!_shadowFramebuffer) { + const int SHADOW_MAP_SIZE = 2048; + _shadowFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(SHADOW_MAP_SIZE)); + } + return _shadowFramebuffer; +} diff --git a/libraries/render-utils/src/FramebufferCache.h b/libraries/render-utils/src/FramebufferCache.h new file mode 100644 index 0000000000..e756286ccd --- /dev/null +++ b/libraries/render-utils/src/FramebufferCache.h @@ -0,0 +1,59 @@ +// +// Created by Bradley Austin Davis on 2015/07/20 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_FramebufferCache_h +#define hifi_FramebufferCache_h + +#include + +#include +#include + +namespace gpu { +class Batch; +} + +/// Stores cached textures, including render-to-texture targets. +class FramebufferCache : public Dependency { + SINGLETON_DEPENDENCY + +public: + /// Sets the desired texture resolution for the framebuffer objects. + void setFrameBufferSize(QSize frameBufferSize); + const QSize& getFrameBufferSize() const { return _frameBufferSize; } + + /// Returns a pointer to the primary framebuffer object. This render target includes a depth component, and is + /// used for scene rendering. + gpu::FramebufferPointer getPrimaryFramebuffer(); + + gpu::FramebufferPointer getSecondaryFramebuffer(); + + /// Returns the framebuffer object used to render shadow maps; + gpu::FramebufferPointer getShadowFramebuffer(); + + /// Enables or disables draw buffers on the primary framebuffer. Note: the primary framebuffer must be bound. + void setPrimaryDrawBuffers(gpu::Batch& batch, bool color, bool normal = false, bool specular = false); + + /// Returns a free framebuffer with a single color attachment for temp or intra-frame operations + gpu::FramebufferPointer getFramebuffer(); + // TODO add sync functionality to the release, so we don't reuse a framebuffer being read from + /// Releases a free framebuffer back for reuse + void releaseFramebuffer(const gpu::FramebufferPointer& framebuffer); + +private: + FramebufferCache(); + virtual ~FramebufferCache(); + + void createPrimaryFramebuffer(); + + gpu::FramebufferPointer _primaryFramebuffer; + gpu::FramebufferPointer _shadowFramebuffer; + QSize _frameBufferSize{ 100, 100 }; +}; + +#endif // hifi_FramebufferCache_h diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index 910cf3386b..8f08be2b1d 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -9,6 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "TextureCache.h" + +#include + +#include +#include + #include #include #include @@ -19,21 +26,10 @@ #include #include -#include -#include #include "RenderUtilsLogging.h" -#include "TextureCache.h" - -#include - -TextureCache::TextureCache() : - _permutationNormalTexture(0), - _whiteTexture(0), - _blueTexture(0), - _frameBufferSize(100, 100) -{ +TextureCache::TextureCache() { const qint64 TEXTURE_DEFAULT_UNUSED_MAX_SIZE = DEFAULT_UNUSED_MAX_SIZE; setUnusedResourceCacheSize(TEXTURE_DEFAULT_UNUSED_MAX_SIZE); } @@ -41,23 +37,6 @@ TextureCache::TextureCache() : TextureCache::~TextureCache() { } -void TextureCache::setFrameBufferSize(QSize frameBufferSize) { - //If the size changed, we need to delete our FBOs - if (_frameBufferSize != frameBufferSize) { - _frameBufferSize = frameBufferSize; - - _primaryFramebuffer.reset(); - _primaryDepthTexture.reset(); - _primaryColorTexture.reset(); - _primaryNormalTexture.reset(); - _primarySpecularTexture.reset(); - - _secondaryFramebuffer.reset(); - - _tertiaryFramebuffer.reset(); - } -} - // use fixed table of permutations. Could also make ordered list programmatically // and then shuffle algorithm. For testing, this ensures consistent behavior in each run. // this list taken from Ken Perlin's Improved Noise reference implementation (orig. in Java) at @@ -175,113 +154,6 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, TextureType type return texture; } -void TextureCache::createPrimaryFramebuffer() { - _primaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); - - auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); - auto width = _frameBufferSize.width(); - auto height = _frameBufferSize.height(); - - auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); - _primaryColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); - _primaryNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); - _primarySpecularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); - - _primaryFramebuffer->setRenderBuffer(0, _primaryColorTexture); - _primaryFramebuffer->setRenderBuffer(1, _primaryNormalTexture); - _primaryFramebuffer->setRenderBuffer(2, _primarySpecularTexture); - - - auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); - _primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler)); - - _primaryFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); -} - -gpu::FramebufferPointer TextureCache::getPrimaryFramebuffer() { - if (!_primaryFramebuffer) { - createPrimaryFramebuffer(); - } - return _primaryFramebuffer; -} - -gpu::TexturePointer TextureCache::getPrimaryDepthTexture() { - if (!_primaryDepthTexture) { - createPrimaryFramebuffer(); - } - return _primaryDepthTexture; -} - -gpu::TexturePointer TextureCache::getPrimaryColorTexture() { - if (!_primaryColorTexture) { - createPrimaryFramebuffer(); - } - return _primaryColorTexture; -} - -gpu::TexturePointer TextureCache::getPrimaryNormalTexture() { - if (!_primaryNormalTexture) { - createPrimaryFramebuffer(); - } - return _primaryNormalTexture; -} - -gpu::TexturePointer TextureCache::getPrimarySpecularTexture() { - if (!_primarySpecularTexture) { - createPrimaryFramebuffer(); - } - return _primarySpecularTexture; -} - -GLuint TextureCache::getPrimaryDepthTextureID() { - return gpu::GLBackend::getTextureID(getPrimaryDepthTexture()); -} - -void TextureCache::setPrimaryDrawBuffers(bool color, bool normal, bool specular) { - gpu::Batch batch; - setPrimaryDrawBuffers(batch, color, normal, specular); - gpu::GLBackend::renderBatch(batch); -} - -void TextureCache::setPrimaryDrawBuffers(gpu::Batch& batch, bool color, bool normal, bool specular) { - GLenum buffers[3]; - int bufferCount = 0; - if (color) { - buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; - } - if (normal) { - buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; - } - if (specular) { - buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; - } - batch._glDrawBuffers(bufferCount, buffers); -} - -gpu::FramebufferPointer TextureCache::getSecondaryFramebuffer() { - if (!_secondaryFramebuffer) { - _secondaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, _frameBufferSize.width(), _frameBufferSize.height())); - } - return _secondaryFramebuffer; -} - -gpu::FramebufferPointer TextureCache::getTertiaryFramebuffer() { - if (!_tertiaryFramebuffer) { - _tertiaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, _frameBufferSize.width(), _frameBufferSize.height())); - } - return _tertiaryFramebuffer; -} - -gpu::FramebufferPointer TextureCache::getShadowFramebuffer() { - if (!_shadowFramebuffer) { - const int SHADOW_MAP_SIZE = 2048; - _shadowFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(SHADOW_MAP_SIZE)); - - _shadowTexture = _shadowFramebuffer->getDepthStencilBuffer(); - } - return _shadowFramebuffer; -} - /// Returns a texture version of an image file gpu::TexturePointer TextureCache::getImageTexture(const QString& path) { QImage image = QImage(path).mirrored(false, true); diff --git a/libraries/render-utils/src/TextureCache.h b/libraries/render-utils/src/TextureCache.h index 6b4fff4f6b..8f60382e9b 100644 --- a/libraries/render-utils/src/TextureCache.h +++ b/libraries/render-utils/src/TextureCache.h @@ -13,8 +13,6 @@ #define hifi_TextureCache_h #include -#include - #include #include @@ -39,10 +37,6 @@ class TextureCache : public ResourceCache, public Dependency { SINGLETON_DEPENDENCY public: - /// Sets the desired texture resolution for the framebuffer objects. - void setFrameBufferSize(QSize frameBufferSize); - const QSize& getFrameBufferSize() const { return _frameBufferSize; } - /// Returns the ID of the permutation/normal texture used for Perlin noise shader programs. This texture /// has two lines: the first, a set of random numbers in [0, 255] to be used as permutation offsets, and /// the second, a set of random unit vectors to be used as noise gradients. @@ -67,33 +61,6 @@ public: NetworkTexturePointer getTexture(const QUrl& url, TextureType type = DEFAULT_TEXTURE, bool dilatable = false, const QByteArray& content = QByteArray()); - /// Returns a pointer to the primary framebuffer object. This render target includes a depth component, and is - /// used for scene rendering. - gpu::FramebufferPointer getPrimaryFramebuffer(); - - gpu::TexturePointer getPrimaryDepthTexture(); - gpu::TexturePointer getPrimaryColorTexture(); - gpu::TexturePointer getPrimaryNormalTexture(); - gpu::TexturePointer getPrimarySpecularTexture(); - - /// Returns the ID of the primary framebuffer object's depth texture. This contains the Z buffer used in rendering. - uint32_t getPrimaryDepthTextureID(); - - /// Enables or disables draw buffers on the primary framebuffer. Note: the primary framebuffer must be bound. - void setPrimaryDrawBuffers(bool color, bool normal = false, bool specular = false); - void setPrimaryDrawBuffers(gpu::Batch& batch, bool color, bool normal = false, bool specular = false); - - /// Returns a pointer to the secondary framebuffer object, used as an additional render target when performing full - /// screen effects. - gpu::FramebufferPointer getSecondaryFramebuffer(); - - /// Returns a pointer to the tertiary framebuffer object, used as an additional render target when performing full - /// screen effects. - gpu::FramebufferPointer getTertiaryFramebuffer(); - - /// Returns the framebuffer object used to render shadow maps; - gpu::FramebufferPointer getShadowFramebuffer(); - protected: virtual QSharedPointer createResource(const QUrl& url, @@ -110,23 +77,7 @@ private: gpu::TexturePointer _blueTexture; gpu::TexturePointer _blackTexture; - QHash > _dilatableNetworkTextures; - - gpu::TexturePointer _primaryDepthTexture; - gpu::TexturePointer _primaryColorTexture; - gpu::TexturePointer _primaryNormalTexture; - gpu::TexturePointer _primarySpecularTexture; - gpu::FramebufferPointer _primaryFramebuffer; - void createPrimaryFramebuffer(); - - gpu::FramebufferPointer _secondaryFramebuffer; - gpu::FramebufferPointer _tertiaryFramebuffer; - - gpu::FramebufferPointer _shadowFramebuffer; - gpu::TexturePointer _shadowTexture; - - QSize _frameBufferSize; }; /// A simple object wrapper for an OpenGL texture. From 9596452c32e567ed00a702fcc01803274dcc3198 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Wed, 22 Jul 2015 08:07:44 -0400 Subject: [PATCH 4/5] Trying to fix oculus rendering --- interface/src/ui/ApplicationCompositor.cpp | 4 +- interface/src/ui/ApplicationOverlay.h | 1 + .../src/DeferredLightingEffect.cpp | 27 ++++---- .../render-utils/src/FramebufferCache.cpp | 61 ++++++++++++++----- libraries/render-utils/src/FramebufferCache.h | 10 ++- 5 files changed, 73 insertions(+), 30 deletions(-) diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 943d958cff..afdeb7b94e 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -270,8 +270,8 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int gpu::Batch batch; geometryCache->useSimpleDrawPipeline(batch); - batch._glDisable(GL_DEPTH_TEST); - batch._glDisable(GL_CULL_FACE); + //batch._glDisable(GL_DEPTH_TEST); + //batch._glDisable(GL_CULL_FACE); //batch._glBindTexture(GL_TEXTURE_2D, texture); //batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 532fea23dc..ae09aa0b10 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -49,6 +49,7 @@ private: gpu::TexturePointer _overlayDepthTexture; gpu::TexturePointer _overlayColorTexture; gpu::FramebufferPointer _overlayFramebuffer; + }; #endif // hifi_ApplicationOverlay_h diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 26d12ef0ce..e6f2b520c7 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -227,6 +227,8 @@ void DeferredLightingEffect::prepare(RenderArgs* args) { args->_context->render(batch); } +gpu::FramebufferPointer _copyFBO; + void DeferredLightingEffect::render(RenderArgs* args) { gpu::Batch batch; @@ -236,18 +238,20 @@ void DeferredLightingEffect::render(RenderArgs* args) { QSize framebufferSize = framebufferCache->getFrameBufferSize(); // binding the first framebuffer - auto freeFBO = framebufferCache->getSecondaryFramebuffer(); - batch.setFramebuffer(freeFBO); + _copyFBO = framebufferCache->getFramebuffer(); + batch.setFramebuffer(_copyFBO); batch.setViewportTransform(args->_viewport); - batch.clearColorFramebuffer(freeFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); + batch.clearColorFramebuffer(_copyFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); - auto primaryFramebuffer = framebufferCache->getPrimaryFramebuffer(); - for (int i = 0; i < 3; ++i) { - batch.setResourceTexture(i, primaryFramebuffer->getRenderBuffer(i)); - } - batch.setResourceTexture(3, primaryFramebuffer->getDepthStencilBuffer()); + batch.setResourceTexture(0, framebufferCache->getPrimaryColorTexture()); + + batch.setResourceTexture(1, framebufferCache->getPrimaryNormalTexture()); + + batch.setResourceTexture(2, framebufferCache->getPrimarySpecularTexture()); + + batch.setResourceTexture(3, framebufferCache->getPrimaryDepthTexture()); float sMin = args->_viewport.x / (float)framebufferSize.width(); float sWidth = args->_viewport.z / (float)framebufferSize.width(); @@ -532,17 +536,16 @@ void DeferredLightingEffect::render(RenderArgs* args) { // End of the Lighting pass } + void DeferredLightingEffect::copyBack(RenderArgs* args) { gpu::Batch batch; auto framebufferCache = DependencyManager::get(); QSize framebufferSize = framebufferCache->getFrameBufferSize(); - auto freeFBO = framebufferCache->getSecondaryFramebuffer(); - batch.setFramebuffer(framebufferCache->getPrimaryFramebuffer()); batch.setPipeline(_blitLightBuffer); - batch.setResourceTexture(0, freeFBO->getRenderBuffer(0)); + batch.setResourceTexture(0, _copyFBO->getRenderBuffer(0)); batch.setProjectionTransform(glm::mat4()); batch.setViewTransform(Transform()); @@ -561,8 +564,10 @@ void DeferredLightingEffect::copyBack(RenderArgs* args) { batch.draw(gpu::TRIANGLE_STRIP, 4); + args->_context->syncCache(); args->_context->render(batch); + framebufferCache->releaseFramebuffer(_copyFBO); } void DeferredLightingEffect::setupTransparent(RenderArgs* args, int lightBufferUnit) { diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp index c699da2e81..ba724d05e8 100644 --- a/libraries/render-utils/src/FramebufferCache.cpp +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -35,30 +35,34 @@ void FramebufferCache::setFrameBufferSize(QSize frameBufferSize) { if (_frameBufferSize != frameBufferSize) { _frameBufferSize = frameBufferSize; _primaryFramebuffer.reset(); + _primaryDepthTexture.reset(); + _primaryColorTexture.reset(); + _primaryNormalTexture.reset(); + _primarySpecularTexture.reset(); } } void FramebufferCache::createPrimaryFramebuffer() { _primaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); - static auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); - static auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); - + auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); auto width = _frameBufferSize.width(); auto height = _frameBufferSize.height(); auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); - auto colorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); - auto normalTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); - auto specularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); + _primaryColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); + _primaryNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); + _primarySpecularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); - _primaryFramebuffer->setRenderBuffer(0, colorTexture); - _primaryFramebuffer->setRenderBuffer(1, normalTexture); - _primaryFramebuffer->setRenderBuffer(2, specularTexture); + _primaryFramebuffer->setRenderBuffer(0, _primaryColorTexture); + _primaryFramebuffer->setRenderBuffer(1, _primaryNormalTexture); + _primaryFramebuffer->setRenderBuffer(2, _primarySpecularTexture); - auto depthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler)); - _primaryFramebuffer->setDepthStencilBuffer(depthTexture, depthFormat); + auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); + _primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler)); + + _primaryFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); } gpu::FramebufferPointer FramebufferCache::getPrimaryFramebuffer() { @@ -68,6 +72,36 @@ gpu::FramebufferPointer FramebufferCache::getPrimaryFramebuffer() { return _primaryFramebuffer; } + + +gpu::TexturePointer FramebufferCache::getPrimaryDepthTexture() { + if (!_primaryDepthTexture) { + createPrimaryFramebuffer(); + } + return _primaryDepthTexture; +} + +gpu::TexturePointer FramebufferCache::getPrimaryColorTexture() { + if (!_primaryColorTexture) { + createPrimaryFramebuffer(); + } + return _primaryColorTexture; +} + +gpu::TexturePointer FramebufferCache::getPrimaryNormalTexture() { + if (!_primaryNormalTexture) { + createPrimaryFramebuffer(); + } + return _primaryNormalTexture; +} + +gpu::TexturePointer FramebufferCache::getPrimarySpecularTexture() { + if (!_primarySpecularTexture) { + createPrimaryFramebuffer(); + } + return _primarySpecularTexture; +} + void FramebufferCache::setPrimaryDrawBuffers(gpu::Batch& batch, bool color, bool normal, bool specular) { GLenum buffers[3]; int bufferCount = 0; @@ -98,11 +132,6 @@ void FramebufferCache::releaseFramebuffer(const gpu::FramebufferPointer& framebu _cachedFramebuffers.push_back(framebuffer); } -gpu::FramebufferPointer FramebufferCache::getSecondaryFramebuffer() { - static auto _secondaryFramebuffer = getFramebuffer(); - return _secondaryFramebuffer; -} - gpu::FramebufferPointer FramebufferCache::getShadowFramebuffer() { if (!_shadowFramebuffer) { const int SHADOW_MAP_SIZE = 2048; diff --git a/libraries/render-utils/src/FramebufferCache.h b/libraries/render-utils/src/FramebufferCache.h index e756286ccd..348c4818f9 100644 --- a/libraries/render-utils/src/FramebufferCache.h +++ b/libraries/render-utils/src/FramebufferCache.h @@ -31,7 +31,10 @@ public: /// used for scene rendering. gpu::FramebufferPointer getPrimaryFramebuffer(); - gpu::FramebufferPointer getSecondaryFramebuffer(); + gpu::TexturePointer getPrimaryDepthTexture(); + gpu::TexturePointer getPrimaryColorTexture(); + gpu::TexturePointer getPrimaryNormalTexture(); + gpu::TexturePointer getPrimarySpecularTexture(); /// Returns the framebuffer object used to render shadow maps; gpu::FramebufferPointer getShadowFramebuffer(); @@ -52,6 +55,11 @@ private: void createPrimaryFramebuffer(); gpu::FramebufferPointer _primaryFramebuffer; + gpu::TexturePointer _primaryDepthTexture; + gpu::TexturePointer _primaryColorTexture; + gpu::TexturePointer _primaryNormalTexture; + gpu::TexturePointer _primarySpecularTexture; + gpu::FramebufferPointer _shadowFramebuffer; QSize _frameBufferSize{ 100, 100 }; }; From 2f13488f116ba358c2236105e3b93ea6e1eae6ac Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Wed, 22 Jul 2015 11:28:36 -0400 Subject: [PATCH 5/5] Fixing FBO bug on resizing windows --- interface/src/Application.cpp | 3 +-- libraries/render-utils/src/FramebufferCache.cpp | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d78c63b5d0..742517998f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -893,8 +893,6 @@ void Application::paintGL() { PerformanceWarning warn(showWarnings, "Application::paintGL()"); resizeGL(); - glEnable(GL_LINE_SMOOTH); - { PerformanceTimer perfTimer("renderOverlay"); @@ -905,6 +903,7 @@ void Application::paintGL() { _applicationOverlay.renderOverlay(&renderArgs); } + glEnable(GL_LINE_SMOOTH); if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || _myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, _myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN); diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp index ba724d05e8..8e16eeec62 100644 --- a/libraries/render-utils/src/FramebufferCache.cpp +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -39,6 +39,7 @@ void FramebufferCache::setFrameBufferSize(QSize frameBufferSize) { _primaryColorTexture.reset(); _primaryNormalTexture.reset(); _primarySpecularTexture.reset(); + _cachedFramebuffers.clear(); } } @@ -129,7 +130,9 @@ gpu::FramebufferPointer FramebufferCache::getFramebuffer() { void FramebufferCache::releaseFramebuffer(const gpu::FramebufferPointer& framebuffer) { - _cachedFramebuffers.push_back(framebuffer); + if (QSize(framebuffer->getSize().x, framebuffer->getSize().y) == _frameBufferSize) { + _cachedFramebuffers.push_back(framebuffer); + } } gpu::FramebufferPointer FramebufferCache::getShadowFramebuffer() {