From eb8c7220801d541bd2e38573d1e053232827712a Mon Sep 17 00:00:00 2001
From: SamGondelman <samuel_gondelman@alumni.brown.edu>
Date: Thu, 9 May 2019 14:11:29 -0700
Subject: [PATCH] fix runtime switch

---
 interface/src/Application.cpp                 |  2 +-
 interface/src/graphics/WorldBox.cpp           |  2 +-
 interface/src/raypick/ParabolaPointer.cpp     | 46 ++++-----
 interface/src/raypick/ParabolaPointer.h       |  5 +-
 .../src/workload/GameWorkloadRenderer.cpp     |  2 +
 .../src/avatars-renderer/Avatar.cpp           | 12 +--
 .../src/avatars-renderer/Avatar.h             |  2 +-
 .../src/RenderableGizmoEntityItem.cpp         |  4 +-
 .../src/RenderableGridEntityItem.cpp          |  4 +-
 .../src/RenderableLineEntityItem.cpp          |  3 +-
 .../src/RenderableModelEntityItem.cpp         |  2 +-
 .../src/RenderablePolyLineEntityItem.cpp      | 38 +++-----
 .../src/RenderablePolyLineEntityItem.h        |  5 +-
 .../src/RenderableShapeEntityItem.cpp         |  2 +-
 .../src/RenderableTextEntityItem.cpp          | 10 +-
 .../procedural/src/procedural/Procedural.cpp  |  1 +
 libraries/render-utils/src/GeometryCache.cpp  | 94 +++++++++----------
 libraries/render-utils/src/GeometryCache.h    | 16 ++--
 libraries/render-utils/src/Model.cpp          |  4 +-
 libraries/render-utils/src/Model.h            |  2 +-
 libraries/render-utils/src/RenderCommonTask.h | 12 +++
 .../render-utils/src/RenderForwardTask.cpp    |  2 +
 libraries/render-utils/src/RenderViewTask.cpp | 15 +--
 libraries/render-utils/src/TextRenderer3D.cpp |  4 +-
 libraries/render-utils/src/TextRenderer3D.h   |  4 +-
 libraries/render-utils/src/forward_grid.slf   | 40 ++++++++
 .../src/forward_grid_translucent.slf          | 41 ++++++++
 .../render-utils/src/forward_parabola.slf     | 18 ++++
 .../render-utils/src/parabola_forward.slv     |  7 --
 .../src/render-utils/forward_grid.slp         |  1 +
 .../render-utils/forward_grid_translucent.slp |  1 +
 .../src/render-utils/forward_parabola.slp     |  1 +
 libraries/render-utils/src/text/Font.cpp      | 36 +++----
 libraries/render-utils/src/text/Font.h        | 14 ++-
 libraries/render/src/render/Args.h            |  4 +
 libraries/shared/src/DisableDeferred.h        | 24 -----
 libraries/shared/src/RenderForward.h          | 24 +++++
 libraries/task/src/task/Task.h                | 10 +-
 38 files changed, 303 insertions(+), 211 deletions(-)
 create mode 100644 libraries/render-utils/src/forward_grid.slf
 create mode 100644 libraries/render-utils/src/forward_grid_translucent.slf
 create mode 100644 libraries/render-utils/src/forward_parabola.slf
 delete mode 100644 libraries/render-utils/src/parabola_forward.slv
 create mode 100644 libraries/render-utils/src/render-utils/forward_grid.slp
 create mode 100644 libraries/render-utils/src/render-utils/forward_grid_translucent.slp
 create mode 100644 libraries/render-utils/src/render-utils/forward_parabola.slp
 delete mode 100644 libraries/shared/src/DisableDeferred.h
 create mode 100644 libraries/shared/src/RenderForward.h

diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 6430792dc4..941b8543a5 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -6722,7 +6722,7 @@ void Application::updateRenderArgs(float deltaTime) {
             }
             appRenderArgs._renderArgs = RenderArgs(_graphicsEngine.getGPUContext(), lodManager->getOctreeSizeScale(),
                 lodManager->getBoundaryLevelAdjust(), lodManager->getLODAngleHalfTan(), RenderArgs::DEFAULT_RENDER_MODE,
-                RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
+                RenderArgs::MONO, RenderArgs::DEFERRED, RenderArgs::RENDER_DEBUG_NONE);
             appRenderArgs._renderArgs._scene = getMain3DScene();
 
             {
diff --git a/interface/src/graphics/WorldBox.cpp b/interface/src/graphics/WorldBox.cpp
index 908055e9c6..a28850207f 100644
--- a/interface/src/graphics/WorldBox.cpp
+++ b/interface/src/graphics/WorldBox.cpp
@@ -22,7 +22,7 @@ namespace render {
             PerformanceTimer perfTimer("worldBox");
 
             auto& batch = *args->_batch;
-            DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
+            DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, false, false, true, args->_renderMethod == Args::RenderMethod::FORWARD);
             WorldBoxRenderData::renderWorldBox(args, batch);
         }
     }
diff --git a/interface/src/raypick/ParabolaPointer.cpp b/interface/src/raypick/ParabolaPointer.cpp
index 389f6ed286..23fc1cb4bd 100644
--- a/interface/src/raypick/ParabolaPointer.cpp
+++ b/interface/src/raypick/ParabolaPointer.cpp
@@ -20,8 +20,7 @@ const float ParabolaPointer::RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_W
 const bool ParabolaPointer::RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_ISVISIBLEINSECONDARYCAMERA { false };
 const bool ParabolaPointer::RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_DRAWINFRONT { false };
 
-gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::_parabolaPipeline { nullptr };
-gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::_transparentParabolaPipeline { nullptr };
+std::map<std::pair<bool, bool>, gpu::PipelinePointer> ParabolaPointer::RenderState::ParabolaRenderItem::_parabolaPipelines;
 
 ParabolaPointer::ParabolaPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, bool hover,
                                  const PointerTriggers& triggers, bool faceAvatar, bool followNormal, float followNormalStrength, bool centerEndY, bool lockEnd, bool distanceScaleEnd,
@@ -401,33 +400,34 @@ void ParabolaPointer::RenderState::ParabolaRenderItem::updateBounds() {
     _bound = AABox(min, max - min);
 }
 
-const gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabolaPipeline() {
-    if (!_parabolaPipeline || !_transparentParabolaPipeline) {
-        {
-            gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::parabola);
-            auto state = std::make_shared<gpu::State>();
+gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabolaPipeline(bool forward) const {
+    if (_parabolaPipelines.empty()) {
+        using namespace shader::render_utils::program;
+
+        static const std::vector<std::tuple<bool, bool, uint32_t>> keys = {
+            std::make_tuple(false, false, parabola), std::make_tuple(false, true, forward_parabola), std::make_tuple(true, false, parabola_translucent)/*, std::make_tuple(true, true, forward_parabola_translucent)*/
+        };
+
+        for (auto& key : keys) {
+            gpu::StatePointer state = gpu::StatePointer(new gpu::State());
             state->setDepthTest(true, true, gpu::LESS_EQUAL);
-            state->setBlendFunction(false,
+            if (std::get<0>(key)) {
+                PrepareStencil::testMask(*state);
+            } else {
+                PrepareStencil::testMaskDrawShape(*state);
+            }
+            state->setBlendFunction(std::get<0>(key),
                 gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
                 gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
-            PrepareStencil::testMaskDrawShape(*state);
             state->setCullMode(gpu::State::CULL_NONE);
-            _parabolaPipeline = gpu::Pipeline::create(program, state);
+
+            _parabolaPipelines[{std::get<0>(key), std::get<1>(key)}] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state);
         }
 
-        {
-            gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::parabola_translucent);
-            auto state = std::make_shared<gpu::State>();
-            state->setDepthTest(true, true, gpu::LESS_EQUAL);
-            state->setBlendFunction(true,
-                gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
-                gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
-            PrepareStencil::testMask(*state);
-            state->setCullMode(gpu::State::CULL_NONE);
-            _transparentParabolaPipeline = gpu::Pipeline::create(program, state);
-        }
+        // The forward opaque/translucent pipelines are the same for now
+        _parabolaPipelines[{ true, true }] = _parabolaPipelines[{ false, true}];
     }
-    return (_parabolaData.color.a < 1.0f ? _transparentParabolaPipeline : _parabolaPipeline);
+    return _parabolaPipelines[{ _parabolaData.color.a < 1.0f, forward }];
 }
 
 void ParabolaPointer::RenderState::ParabolaRenderItem::render(RenderArgs* args) {
@@ -441,7 +441,7 @@ void ParabolaPointer::RenderState::ParabolaRenderItem::render(RenderArgs* args)
     transform.setTranslation(_origin);
     batch.setModelTransform(transform);
 
-    batch.setPipeline(getParabolaPipeline());
+    batch.setPipeline(getParabolaPipeline(args->_renderMethod == render::Args::RenderMethod::FORWARD));
 
     const int MAX_SECTIONS = 100;
     if (glm::length2(_parabolaData.acceleration) < EPSILON) {
diff --git a/interface/src/raypick/ParabolaPointer.h b/interface/src/raypick/ParabolaPointer.h
index d4b705a7d2..94470971e6 100644
--- a/interface/src/raypick/ParabolaPointer.h
+++ b/interface/src/raypick/ParabolaPointer.h
@@ -26,9 +26,8 @@ public:
                                bool isVisibleInSecondaryCamera, bool drawInFront, bool enabled);
             ~ParabolaRenderItem() {}
 
-            static gpu::PipelinePointer _parabolaPipeline;
-            static gpu::PipelinePointer _transparentParabolaPipeline;
-            const gpu::PipelinePointer getParabolaPipeline();
+            static std::map<std::pair<bool, bool>, gpu::PipelinePointer> _parabolaPipelines;
+            gpu::PipelinePointer getParabolaPipeline(bool forward) const;
 
             void render(RenderArgs* args);
             render::Item::Bound& editBound() { return _bound; }
diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp
index a2fb32d396..2bb73999f1 100644
--- a/interface/src/workload/GameWorkloadRenderer.cpp
+++ b/interface/src/workload/GameWorkloadRenderer.cpp
@@ -145,6 +145,7 @@ void GameWorkloadRenderItem::setAllViews(const workload::Views& views) {
 }
 
 const gpu::PipelinePointer GameWorkloadRenderItem::getProxiesPipeline() {
+    // FIXME: this needs a forward pipeline, or to only write to one output
     if (!_drawAllProxiesPipeline) {
         gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::drawWorkloadProxy);
         auto state = std::make_shared<gpu::State>();
@@ -162,6 +163,7 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getProxiesPipeline() {
 
 
 const gpu::PipelinePointer GameWorkloadRenderItem::getViewsPipeline() {
+    // FIXME: this needs a forward pipeline, or to only write to one output
     if (!_drawAllViewsPipeline) {
         gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::drawWorkloadView);
         auto state = std::make_shared<gpu::State>();
diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp
index cb0acd68cb..4a106d0f36 100644
--- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp
+++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp
@@ -779,7 +779,7 @@ void Avatar::render(RenderArgs* renderArgs) {
                 pointerTransform.setTranslation(position);
                 pointerTransform.setRotation(rotation);
                 batch.setModelTransform(pointerTransform);
-                geometryCache->bindSimpleProgram(batch);
+                geometryCache->bindSimpleProgram(batch, false, false, true, false, false, true, renderArgs->_renderMethod == render::Args::FORWARD);
                 geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, laserLength, 0.0f), laserColor, _leftPointerGeometryID);
             }
         }
@@ -803,7 +803,7 @@ void Avatar::render(RenderArgs* renderArgs) {
                 pointerTransform.setTranslation(position);
                 pointerTransform.setRotation(rotation);
                 batch.setModelTransform(pointerTransform);
-                geometryCache->bindSimpleProgram(batch);
+                geometryCache->bindSimpleProgram(batch, false, false, true, false, false, true, renderArgs->_renderMethod == render::Args::FORWARD);
                 geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, laserLength, 0.0f), laserColor, _rightPointerGeometryID);
             }
         }
@@ -829,7 +829,7 @@ void Avatar::render(RenderArgs* renderArgs) {
             auto& frustum = renderArgs->getViewFrustum();
             auto textPosition = getDisplayNamePosition();
             if (frustum.pointIntersectsFrustum(textPosition)) {
-                renderDisplayName(batch, frustum, textPosition);
+                renderDisplayName(batch, frustum, textPosition, renderArgs->_renderMethod == render::Args::FORWARD);
             }
         }
     }
@@ -1034,7 +1034,7 @@ Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& view, const g
     return result;
 }
 
-void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition) const {
+void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition, bool forward) const {
     PROFILE_RANGE_BATCH(batch, __FUNCTION__);
 
     bool shouldShowReceiveStats = showReceiveStats && !isMyAvatar();
@@ -1090,7 +1090,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const
 
         {
             PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderBevelCornersRect");
-            DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, true, true);
+            DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, true, true, true, forward);
             DependencyManager::get<GeometryCache>()->renderBevelCornersRect(batch, left, bottom, width, height,
                 bevelDistance, backgroundColor, _nameRectGeometryID);
         }
@@ -1103,7 +1103,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const
         batch.setModelTransform(textTransform);
         {
             PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderText");
-            renderer->draw(batch, text_x, -text_y, nameUTF8.data(), textColor);
+            renderer->draw(batch, text_x, -text_y, nameUTF8.data(), textColor, glm::vec2(-1.0f), forward);
         }
     }
 }
diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h
index a196c018d2..53f13ef191 100644
--- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h
+++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h
@@ -694,7 +694,7 @@ protected:
     glm::vec3 getDisplayNamePosition() const;
 
     Transform calculateDisplayNameTransform(const ViewFrustum& view, const glm::vec3& textPosition) const;
-    void renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition) const;
+    void renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition, bool forward) const;
     virtual bool shouldRenderHead(const RenderArgs* renderArgs) const;
     virtual void fixupModelsInScene(const render::ScenePointer& scene);
 
diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp
index 1a188ca163..9468fdf3ef 100644
--- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp
@@ -261,15 +261,17 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) {
         Transform transform;
         bool hasTickMarks;
         glm::vec4 tickProperties;
+        bool forward;
         withReadLock([&] {
             transform = _renderTransform;
             hasTickMarks = _ringProperties.getHasTickMarks();
             tickProperties = glm::vec4(_ringProperties.getMajorTickMarksAngle(), _ringProperties.getMajorTickMarksLength(),
                                        _ringProperties.getMinorTickMarksAngle(), _ringProperties.getMinorTickMarksLength());
+            forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
         });
 
         bool wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES;
-        geometryCache->bindSimpleProgram(batch, false, isTransparent(), false, wireframe, true, true, _renderLayer != RenderLayer::WORLD);
+        geometryCache->bindSimpleProgram(batch, false, isTransparent(), false, wireframe, true, true, forward);
 
         batch.setModelTransform(transform);
 
diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp
index f05ba35c79..31969e36fc 100644
--- a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp
@@ -113,11 +113,13 @@ void GridEntityRenderer::doRender(RenderArgs* args) {
     glm::vec4 color;
     glm::vec3 dimensions;
     Transform renderTransform;
+    bool forward;
     withReadLock([&] {
         color = glm::vec4(toGlm(_color), _alpha);
         color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
         dimensions = _dimensions;
         renderTransform = _renderTransform;
+        forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
     });
 
     if (!_visible) {
@@ -153,5 +155,5 @@ void GridEntityRenderer::doRender(RenderArgs* args) {
     DependencyManager::get<GeometryCache>()->renderGrid(*batch, minCorner, maxCorner,
         minorGridRowDivisions, minorGridColDivisions, MINOR_GRID_EDGE,
         majorGridRowDivisions, majorGridColDivisions, MAJOR_GRID_EDGE,
-        color, _geometryId);
+        color, forward, _geometryId);
 }
\ No newline at end of file
diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp
index 9c5424950a..cbe2a98166 100644
--- a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp
@@ -55,7 +55,8 @@ void LineEntityRenderer::doRender(RenderArgs* args) {
     transform.setRotation(modelTransform.getRotation());
     batch.setModelTransform(transform);
     if (_linePoints.size() > 1) {
-        DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
+        DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, false, false, true,
+            _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD);
         DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID);
     }
 }
diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
index bfbbe12ea6..df5b1d91f0 100644
--- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
@@ -1520,7 +1520,7 @@ void ModelEntityRenderer::doRender(RenderArgs* args) {
         model = _model;
     });
     if (model) {
-        model->renderDebugMeshBoxes(batch);
+        model->renderDebugMeshBoxes(batch, args->_renderMethod == Args::RenderMethod::FORWARD);
     }
 #endif
 }
diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp
index 2430643ce2..d7246f9ba5 100644
--- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp
@@ -19,15 +19,12 @@
 #include <PerfStat.h>
 #include <shaders/Shaders.h>
 
-#include <DisableDeferred.h>
-
 #include "paintStroke_Shared.slh"
 
 using namespace render;
 using namespace render::entities;
 
-gpu::PipelinePointer PolyLineEntityRenderer::_pipeline = nullptr;
-gpu::PipelinePointer PolyLineEntityRenderer::_glowPipeline = nullptr;
+std::map<std::pair<render::Args::RenderMethod, bool>, gpu::PipelinePointer> PolyLineEntityRenderer::_pipelines;
 
 static const QUrl DEFAULT_POLYLINE_TEXTURE = PathUtils::resourcesUrl("images/paintStroke.png");
 
@@ -44,29 +41,24 @@ PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity)
     }
 }
 
-void PolyLineEntityRenderer::buildPipeline() {
-    // FIXME: opaque pipeline
-    gpu::ShaderPointer program = gpu::Shader::createProgram(DISABLE_DEFERRED ? shader::entities_renderer::program::paintStroke_forward : shader::entities_renderer::program::paintStroke);
+void PolyLineEntityRenderer::buildPipelines() {
+    // FIXME: opaque pipelines
+
+    static const std::vector<std::pair<render::Args::RenderMethod, bool>> keys = {
+        { render::Args::DEFERRED, false }, { render::Args::DEFERRED, true }, { render::Args::FORWARD, false }, { render::Args::FORWARD, true },
+    };
+
+    for (auto& key : keys) {
+        gpu::ShaderPointer program = gpu::Shader::createProgram(key.first == render::Args::DEFERRED ? shader::entities_renderer::program::paintStroke : shader::entities_renderer::program::paintStroke_forward);
 
-    {
         gpu::StatePointer state = gpu::StatePointer(new gpu::State());
         state->setCullMode(gpu::State::CullMode::CULL_NONE);
-        state->setDepthTest(true, true, gpu::LESS_EQUAL);
+        state->setDepthTest(true, !key.second, gpu::LESS_EQUAL);
         PrepareStencil::testMask(*state);
         state->setBlendFunction(true,
             gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
             gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
-        _pipeline = gpu::Pipeline::create(program, state);
-    }
-    {
-        gpu::StatePointer state = gpu::StatePointer(new gpu::State());
-        state->setCullMode(gpu::State::CullMode::CULL_NONE);
-        state->setDepthTest(true, false, gpu::LESS_EQUAL);
-        PrepareStencil::testMask(*state);
-        state->setBlendFunction(true,
-            gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
-            gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
-        _glowPipeline = gpu::Pipeline::create(program, state);
+        _pipelines[key] = gpu::Pipeline::create(program, state);
     }
 }
 
@@ -299,11 +291,11 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) {
         return;
     }
 
-    if (!_pipeline) {
-        buildPipeline();
+    if (_pipelines.empty()) {
+        buildPipelines();
     }
 
-    batch.setPipeline(_glow ? _glowPipeline : _pipeline);
+    batch.setPipeline(_pipelines[{args->_renderMethod, _glow}]);
     batch.setModelTransform(transform);
     batch.setResourceTexture(0, texture);
     batch.draw(gpu::TRIANGLE_STRIP, (gpu::uint32)(2 * numVertices), 0);
diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h
index 3815b57671..adb30362da 100644
--- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h
+++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h
@@ -37,7 +37,7 @@ protected:
     virtual ShapeKey getShapeKey() override;
     virtual void doRender(RenderArgs* args) override;
 
-    void buildPipeline();
+    static void buildPipelines();
     void updateGeometry();
     void updateData();
 
@@ -58,8 +58,7 @@ protected:
     size_t _numVertices;
     gpu::BufferPointer _polylineDataBuffer;
     gpu::BufferPointer _polylineGeometryBuffer;
-    static gpu::PipelinePointer _pipeline;
-    static gpu::PipelinePointer _glowPipeline;
+    static std::map<std::pair<render::Args::RenderMethod, bool>, gpu::PipelinePointer> _pipelines;
 };
 
 } } // namespace 
diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp
index 2548ae5914..6a0d7b001c 100644
--- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp
@@ -280,7 +280,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
         // FIXME, support instanced multi-shape rendering using multidraw indirect
         outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
         render::ShapePipelinePointer pipeline;
-        if (renderLayer == RenderLayer::WORLD) {
+        if (renderLayer == RenderLayer::WORLD && args->_renderMethod != Args::RenderMethod::FORWARD) {
             pipeline = outColor.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline();
         } else {
             pipeline = outColor.a < 1.0f ? geometryCache->getForwardTransparentShapePipeline() : geometryCache->getForwardOpaqueShapePipeline();
diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp
index 81f367a956..a281c1d097 100644
--- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp
@@ -163,7 +163,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
     Transform modelTransform;
     glm::vec3 dimensions;
     BillboardMode billboardMode;
-    bool layered;
+    bool forward;
     withReadLock([&] {
         modelTransform = _renderTransform;
         dimensions = _dimensions;
@@ -174,7 +174,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
         textColor = EntityRenderer::calculatePulseColor(textColor, _pulseProperties, _created);
         backgroundColor = glm::vec4(_backgroundColor, fadeRatio * _backgroundAlpha);
         backgroundColor = EntityRenderer::calculatePulseColor(backgroundColor, _pulseProperties, _created);
-        layered = _renderLayer != RenderLayer::WORLD;
+        forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD;
     });
 
     // Render background
@@ -187,7 +187,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
     gpu::Batch& batch = *args->_batch;
 
     // FIXME: we need to find a better way of rendering text so we don't have to do this
-    if (layered) {
+    if (forward) {
         DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(args, batch);
     }
 
@@ -199,7 +199,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
     if (backgroundColor.a > 0.0f) {
         batch.setModelTransform(transformToTopLeft);
         auto geometryCache = DependencyManager::get<GeometryCache>();
-        geometryCache->bindSimpleProgram(batch, false, backgroundColor.a < 1.0f, false, false, false, true, layered);
+        geometryCache->bindSimpleProgram(batch, false, backgroundColor.a < 1.0f, false, false, false, true, forward);
         geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID);
     }
 
@@ -210,7 +210,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
         batch.setModelTransform(transformToTopLeft);
 
         glm::vec2 bounds = glm::vec2(dimensions.x - (_leftMargin + _rightMargin), dimensions.y - (_topMargin + _bottomMargin));
-        _textRenderer->draw(batch, _leftMargin / scale, -_topMargin / scale, _text, textColor, bounds / scale, layered);
+        _textRenderer->draw(batch, _leftMargin / scale, -_topMargin / scale, _text, textColor, bounds / scale, forward);
     }
 }
 
diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp
index 9940da0b9a..dbdf9cc7d1 100644
--- a/libraries/procedural/src/procedural/Procedural.cpp
+++ b/libraries/procedural/src/procedural/Procedural.cpp
@@ -288,6 +288,7 @@ void Procedural::prepare(gpu::Batch& batch,
         recompiledShader = true;
     }
 
+    // FIXME: need to handle forward rendering
     batch.setPipeline(recompiledShader ? _proceduralPipelines[key] : pipeline->second);
 
     if (_shaderDirty || _uniformsDirty) {
diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp
index 2e762a0107..7bd6f88d71 100644
--- a/libraries/render-utils/src/GeometryCache.cpp
+++ b/libraries/render-utils/src/GeometryCache.cpp
@@ -37,8 +37,6 @@
 
 #include "DeferredLightingEffect.h"
 
-#include <DisableDeferred.h>
-
 namespace gr {
     using graphics::slot::texture::Texture;
     using graphics::slot::buffer::Buffer;
@@ -115,6 +113,8 @@ static const uint SHAPE_NORMALS_OFFSET = offsetof(GeometryCache::ShapeVertex, no
 static const uint SHAPE_TEXCOORD0_OFFSET = offsetof(GeometryCache::ShapeVertex, uv);
 static const uint SHAPE_TANGENT_OFFSET = offsetof(GeometryCache::ShapeVertex, tangent);
 
+std::map<std::pair<bool, bool>, gpu::PipelinePointer> GeometryCache::_gridPipelines;
+
 void GeometryCache::computeSimpleHullPointListForShape(const int entityShape, const glm::vec3 &entityExtents, QVector<glm::vec3> &outPointList) {
 
     auto geometryCache = DependencyManager::get<GeometryCache>();
@@ -714,11 +714,13 @@ QHash<SimpleProgramKey, gpu::PipelinePointer> GeometryCache::_simplePrograms;
 gpu::ShaderPointer GeometryCache::_simpleShader;
 gpu::ShaderPointer GeometryCache::_transparentShader;
 gpu::ShaderPointer GeometryCache::_unlitShader;
+gpu::ShaderPointer GeometryCache::_simpleFadeShader;
+gpu::ShaderPointer GeometryCache::_unlitFadeShader;
 gpu::ShaderPointer GeometryCache::_forwardSimpleShader;
 gpu::ShaderPointer GeometryCache::_forwardTransparentShader;
 gpu::ShaderPointer GeometryCache::_forwardUnlitShader;
-gpu::ShaderPointer GeometryCache::_simpleFadeShader;
-gpu::ShaderPointer GeometryCache::_unlitFadeShader;
+gpu::ShaderPointer GeometryCache::_forwardSimpleFadeShader;
+gpu::ShaderPointer GeometryCache::_forwardUnlitFadeShader;
 
 render::ShapePipelinePointer GeometryCache::_simpleOpaquePipeline;
 render::ShapePipelinePointer GeometryCache::_simpleTransparentPipeline;
@@ -740,16 +742,13 @@ render::ShapePipelinePointer GeometryCache::shapePipelineFactory(const render::S
     if (key.isFaded()) {
         if (key.isTranslucent()) {
             return _simpleTransparentFadePipeline;
-        }
-        else {
+        } else {
             return _simpleOpaqueFadePipeline;
         }
-    }
-    else {
+    } else {
         if (key.isTranslucent()) {
             return _simpleTransparentPipeline;
-        }
-        else {
+        } else {
             return _simpleOpaquePipeline;
         }
     }
@@ -805,6 +804,8 @@ void GeometryCache::initializeShapePipelines() {
         _simpleTransparentPipeline = getShapePipeline(false, true, true, false);
         _forwardSimpleOpaquePipeline = getShapePipeline(false, false, true, false, false, true);
         _forwardSimpleTransparentPipeline = getShapePipeline(false, true, true, false, false, true);
+
+        // FIXME: these need forward pipelines
         _simpleOpaqueFadePipeline = getFadingShapePipeline(false, false, false, false, false);
         _simpleTransparentFadePipeline = getFadingShapePipeline(false, true, false, false, false);
         _simpleWirePipeline = getShapePipeline(false, false, true, true);
@@ -823,11 +824,11 @@ render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool
 }
 
 render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured, bool transparent, bool culled,
-    bool unlit, bool depthBias) {
+    bool unlit, bool depthBias, bool forward) {
     auto fadeEffect = DependencyManager::get<FadeEffect>();
     auto fadeBatchSetter = fadeEffect->getBatchSetter();
     auto fadeItemSetter = fadeEffect->getItemUniformSetter();
-    return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, culled, unlit, depthBias, true), nullptr,
+    return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, culled, unlit, depthBias, true, true, forward), nullptr,
         [fadeBatchSetter, fadeItemSetter](const render::ShapePipeline& shapePipeline, gpu::Batch& batch, render::Args* args) {
             batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get<TextureCache>()->getWhiteTexture());
             fadeBatchSetter(shapePipeline, batch, args);
@@ -937,7 +938,7 @@ void GeometryCache::renderWireSphere(gpu::Batch& batch, const glm::vec4& color)
 
 void GeometryCache::renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner,
         int majorRows, int majorCols, float majorEdge, int minorRows, int minorCols, float minorEdge,
-        const glm::vec4& color, int id) {
+        const glm::vec4& color, bool forward, int id) {
     Vec2FloatPair majorKey(glm::vec2(majorRows, majorCols), majorEdge);
     Vec2FloatPair minorKey(glm::vec2(minorRows, minorCols), minorEdge);
     Vec2FloatPairPair key(majorKey, minorKey);
@@ -970,7 +971,7 @@ void GeometryCache::renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, co
     }
 
     // Set the grid pipeline
-    useGridPipeline(batch, gridBuffer, color.a < 1.0f);
+    useGridPipeline(batch, gridBuffer, color.a < 1.0f, forward);
 
     static const glm::vec2 MIN_TEX_COORD(0.0f, 0.0f);
     static const glm::vec2 MAX_TEX_COORD(1.0f, 1.0f);
@@ -2038,39 +2039,34 @@ void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend) {
     }
 }
 
-void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bool transparent) {
-    if (!_gridPipelineOpaque || !_gridPipelineTransparent) {
+void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bool transparent, bool forward) {
+    if (_gridPipelines.empty()) {
+        using namespace shader::render_utils::program;
         const float DEPTH_BIAS = 0.001f;
 
-        // FIXME: need forward pipelines
-        {
-            auto program = gpu::Shader::createProgram(shader::render_utils::program::grid);
-            auto state = std::make_shared<gpu::State>();
-            state->setDepthTest(true, true, gpu::LESS_EQUAL);
-            state->setBlendFunction(false,
-                gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
-                gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
-            PrepareStencil::testMaskDrawShape(*state);
-            state->setCullMode(gpu::State::CULL_NONE);
-            state->setDepthBias(DEPTH_BIAS);
-            _gridPipelineOpaque = gpu::Pipeline::create(program, state);
-        }
+        static const std::vector<std::tuple<bool, bool, uint32_t>> keys = {
+            std::make_tuple(false, false, grid), std::make_tuple(false, true, forward_grid), std::make_tuple(true, false, grid_translucent), std::make_tuple(true, true, forward_grid_translucent)
+        };
 
-        {
-            auto program = gpu::Shader::createProgram(shader::render_utils::program::grid_translucent);
-            auto state = std::make_shared<gpu::State>();
+        for (auto& key : keys) {
+            gpu::StatePointer state = gpu::StatePointer(new gpu::State());
             state->setDepthTest(true, true, gpu::LESS_EQUAL);
-            state->setBlendFunction(true,
+            if (std::get<0>(key)) {
+                PrepareStencil::testMask(*state);
+            } else {
+                PrepareStencil::testMaskDrawShape(*state);
+            }
+            state->setBlendFunction(std::get<0>(key),
                 gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
                 gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
-            PrepareStencil::testMask(*state);
             state->setCullMode(gpu::State::CULL_NONE);
             state->setDepthBias(DEPTH_BIAS);
-            _gridPipelineTransparent = gpu::Pipeline::create(program, state);
+
+            _gridPipelines[{std::get<0>(key), std::get<1>(key)}] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state);
         }
     }
 
-    batch.setPipeline(transparent ? _gridPipelineTransparent : _gridPipelineOpaque);
+    batch.setPipeline(_gridPipelines[{ transparent, forward }]);
     batch.setUniformBuffer(0, gridBuffer);
 }
 
@@ -2162,6 +2158,7 @@ void GeometryCache::bindWebBrowserProgram(gpu::Batch& batch, bool transparent) {
 gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent) {
     static std::once_flag once;
     std::call_once(once, [&]() {
+        // FIXME: need a forward pipeline for this
         buildWebShader(shader::render_utils::program::simple_opaque_web_browser, false, _simpleOpaqueWebBrowserShader, _simpleOpaqueWebBrowserPipeline);
         buildWebShader(shader::render_utils::program::simple_transparent_web_browser, true, _simpleTransparentWebBrowserShader, _simpleTransparentWebBrowserPipeline);
     });
@@ -2197,22 +2194,21 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp
             _forwardSimpleShader = gpu::Shader::createProgram(forward_simple_textured);
             _forwardTransparentShader = gpu::Shader::createProgram(forward_simple_textured_transparent);
             _forwardUnlitShader = gpu::Shader::createProgram(forward_simple_textured_unlit);
-            if (DISABLE_DEFERRED) {
-                _simpleShader = _forwardSimpleShader;
-                _transparentShader = _forwardTransparentShader;
-                _unlitShader = _forwardUnlitShader;
-            } else {
-                _simpleShader = gpu::Shader::createProgram(simple_textured);
-                _transparentShader = gpu::Shader::createProgram(simple_transparent_textured);
-                _unlitShader = gpu::Shader::createProgram(simple_textured_unlit);
-            }
+
+            _simpleShader = gpu::Shader::createProgram(simple_textured);
+            _transparentShader = gpu::Shader::createProgram(simple_transparent_textured);
+            _unlitShader = gpu::Shader::createProgram(simple_textured_unlit);
         });
     } else {
         static std::once_flag once;
         std::call_once(once, [&]() {
             using namespace shader::render_utils::program;
-            _simpleFadeShader = gpu::Shader::createProgram(DISABLE_DEFERRED ? forward_simple_textured : simple_textured_fade);
-            _unlitFadeShader = gpu::Shader::createProgram(DISABLE_DEFERRED ? forward_simple_textured_unlit : simple_textured_unlit_fade);
+            // FIXME: these aren't right...
+            _forwardSimpleFadeShader = gpu::Shader::createProgram(forward_simple_textured);
+            _forwardUnlitFadeShader = gpu::Shader::createProgram(forward_simple_textured_unlit);
+
+            _simpleFadeShader = gpu::Shader::createProgram(simple_textured_fade);
+            _unlitFadeShader = gpu::Shader::createProgram(simple_textured_unlit_fade);
         });
     }
 
@@ -2240,8 +2236,8 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp
 
     gpu::ShaderPointer program;
     if (config.isForward()) {
-        program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _forwardUnlitShader) :
-                                       (config.isFading() ? _simpleFadeShader : (config.isTransparent() ? _forwardTransparentShader : _forwardSimpleShader));
+        program = (config.isUnlit()) ? (config.isFading() ? _forwardUnlitFadeShader : _forwardUnlitShader) :
+                                       (config.isFading() ? _forwardSimpleFadeShader : (config.isTransparent() ? _forwardTransparentShader : _forwardSimpleShader));
     } else {
         program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _unlitShader) :
                                        (config.isFading() ? _simpleFadeShader : (config.isTransparent() ? _transparentShader : _simpleShader));
diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h
index 4ff061786a..a42b059a8c 100644
--- a/libraries/render-utils/src/GeometryCache.h
+++ b/libraries/render-utils/src/GeometryCache.h
@@ -266,7 +266,7 @@ public:
     void renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner,
         int majorRows, int majorCols, float majorEdge,
         int minorRows, int minorCols, float minorEdge,
-        const glm::vec4& color, int id);
+        const glm::vec4& color, bool forward, int id);
 
     void renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id);
 
@@ -400,9 +400,8 @@ private:
         glm::vec4 edge;
     };
     using GridBuffer = gpu::BufferView;
-    void useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bool isLayered);
-    gpu::PipelinePointer _gridPipelineOpaque;
-    gpu::PipelinePointer _gridPipelineTransparent;
+    void useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bool transparent, bool forward);
+    static std::map<std::pair<bool, bool>, gpu::PipelinePointer> _gridPipelines;
 
     class BatchItemDetails {
     public:
@@ -460,11 +459,14 @@ private:
     static gpu::ShaderPointer _simpleShader;
     static gpu::ShaderPointer _transparentShader;
     static gpu::ShaderPointer _unlitShader;
+    static gpu::ShaderPointer _simpleFadeShader;
+    static gpu::ShaderPointer _unlitFadeShader;
     static gpu::ShaderPointer _forwardSimpleShader;
     static gpu::ShaderPointer _forwardTransparentShader;
     static gpu::ShaderPointer _forwardUnlitShader;
-    static gpu::ShaderPointer _simpleFadeShader;
-    static gpu::ShaderPointer _unlitFadeShader;
+    static gpu::ShaderPointer _forwardSimpleFadeShader;
+    static gpu::ShaderPointer _forwardUnlitFadeShader;
+
     static render::ShapePipelinePointer _simpleOpaquePipeline;
     static render::ShapePipelinePointer _simpleTransparentPipeline;
     static render::ShapePipelinePointer _forwardSimpleOpaquePipeline;
@@ -483,7 +485,7 @@ private:
     static render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool culled = true,
         bool unlit = false, bool depthBias = false, bool forward = false);
     static render::ShapePipelinePointer getFadingShapePipeline(bool textured = false, bool transparent = false, bool culled = true,
-        bool unlit = false, bool depthBias = false);
+        bool unlit = false, bool depthBias = false, bool forward = false);
 };
 
 #endif // hifi_GeometryCache_h
diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp
index 7d0119a0f2..003a95e46d 100644
--- a/libraries/render-utils/src/Model.cpp
+++ b/libraries/render-utils/src/Model.cpp
@@ -1033,7 +1033,7 @@ void Model::removeFromScene(const render::ScenePointer& scene, render::Transacti
     _renderInfoHasTransparent = false;
 }
 
-void Model::renderDebugMeshBoxes(gpu::Batch& batch) {
+void Model::renderDebugMeshBoxes(gpu::Batch& batch, bool forward) {
     int colorNdx = 0;
     _mutex.lock();
 
@@ -1042,7 +1042,7 @@ void Model::renderDebugMeshBoxes(gpu::Batch& batch) {
     Transform meshToWorld(meshToWorldMatrix);
     batch.setModelTransform(meshToWorld);
 
-    DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, false, true, true);
+    DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, false, true, true, forward);
 
     for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {
         for (auto &partTriangleSet : meshTriangleSets) {
diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h
index 7844e9bc41..7c861a3bc1 100644
--- a/libraries/render-utils/src/Model.h
+++ b/libraries/render-utils/src/Model.h
@@ -347,7 +347,7 @@ public:
     const QMap<render::ItemID, render::PayloadPointer>& getRenderItems() const { return _modelMeshRenderItemsMap; }
     BlendShapeOperator getModelBlendshapeOperator() const { return _modelBlendshapeOperator; }
 
-    void renderDebugMeshBoxes(gpu::Batch& batch);
+    void renderDebugMeshBoxes(gpu::Batch& batch, bool forward);
 
     int getResourceDownloadAttempts() { return _renderWatcher.getResourceDownloadAttempts(); }
     int getResourceDownloadAttemptsRemaining() { return _renderWatcher.getResourceDownloadAttemptsRemaining(); }
diff --git a/libraries/render-utils/src/RenderCommonTask.h b/libraries/render-utils/src/RenderCommonTask.h
index b43a10aa7b..4f72600d34 100644
--- a/libraries/render-utils/src/RenderCommonTask.h
+++ b/libraries/render-utils/src/RenderCommonTask.h
@@ -137,4 +137,16 @@ public:
     void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output);
 };
 
+class SetRenderMethod {
+public:
+    using JobModel = render::Job::Model<SetRenderMethod>;
+
+    SetRenderMethod(render::Args::RenderMethod method) : _method(method) {}
+
+    void run(const render::RenderContextPointer& renderContext) { renderContext->args->_renderMethod = _method; }
+
+protected:
+    render::Args::RenderMethod _method;
+};
+
 #endif // hifi_RenderDeferredTask_h
diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp
index 5e30308a05..de55f3f4ff 100755
--- a/libraries/render-utils/src/RenderForwardTask.cpp
+++ b/libraries/render-utils/src/RenderForwardTask.cpp
@@ -48,6 +48,8 @@ using namespace render;
 extern void initForwardPipelines(ShapePlumber& plumber);
 
 void RenderForwardTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
+    task.addJob<SetRenderMethod>("SetRenderMethodTask", render::Args::FORWARD);
+
     // Prepare the ShapePipelines
     auto fadeEffect = DependencyManager::get<FadeEffect>();
     ShapePlumberPointer shapePlumber = std::make_shared<ShapePlumber>();
diff --git a/libraries/render-utils/src/RenderViewTask.cpp b/libraries/render-utils/src/RenderViewTask.cpp
index a38769165b..ffaecedb0b 100644
--- a/libraries/render-utils/src/RenderViewTask.cpp
+++ b/libraries/render-utils/src/RenderViewTask.cpp
@@ -11,12 +11,15 @@
 #include "RenderViewTask.h"
 
 #include "RenderShadowTask.h"
+#include "RenderCommonTask.h"
 #include "RenderDeferredTask.h"
 #include "RenderForwardTask.h"
 
-#include <DisableDeferred.h>
+#include <RenderForward.h>
 
 void RenderShadowsAndDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, uint8_t tagBits, uint8_t tagMask) {
+    task.addJob<SetRenderMethod>("SetRenderMethodTask", render::Args::DEFERRED);
+
     const auto items = input.getN<DeferredForwardSwitchJob::Input>(0);
     const auto lightingModel = input.getN<DeferredForwardSwitchJob::Input>(1);
     const auto lightingStageFramesAndZones = input.getN<DeferredForwardSwitchJob::Input>(2);
@@ -31,9 +34,9 @@ void RenderShadowsAndDeferredTask::build(JobModel& task, const render::Varying&
 }
 
 void DeferredForwardSwitchJob::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, uint8_t tagBits, uint8_t tagMask) {
-    task.addBranch<RenderShadowsAndDeferredTask>("RenderShadowsAndDeferredTask", 0, input, cullFunctor, tagBits, tagMask);
+    task.addBranch<RenderShadowsAndDeferredTask>("RenderShadowsAndDeferredTask", RENDER_FORWARD ? 1 : 0, input, cullFunctor, tagBits, tagMask);
 
-    task.addBranch<RenderForwardTask>("RenderForwardTask", 1, input);
+    task.addBranch<RenderForwardTask>("RenderForwardTask", RENDER_FORWARD ? 0 : 1, input);
 }
 
 void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, uint8_t tagBits, uint8_t tagMask) {
@@ -45,11 +48,11 @@ void RenderViewTask::build(JobModel& task, const render::Varying& input, render:
     // Assemble the lighting stages current frames
     const auto lightingStageFramesAndZones = task.addJob<AssembleLightingStageTask>("AssembleStages", items);
 
-    if (!DISABLE_DEFERRED) {
+#ifndef Q_OS_ANDROID
         const auto deferredForwardIn = DeferredForwardSwitchJob::Input(items, lightingModel, lightingStageFramesAndZones).asVarying();
         task.addJob<DeferredForwardSwitchJob>("DeferredForwardSwitch", deferredForwardIn, cullFunctor, tagBits, tagMask);
-    } else {
+#else
         const auto renderInput = RenderForwardTask::Input(items, lightingModel, lightingStageFramesAndZones).asVarying();
         task.addJob<RenderForwardTask>("RenderForwardTask", renderInput);
-    }
+#endif
 }
diff --git a/libraries/render-utils/src/TextRenderer3D.cpp b/libraries/render-utils/src/TextRenderer3D.cpp
index 8ef0dc0d73..d3ea20273e 100644
--- a/libraries/render-utils/src/TextRenderer3D.cpp
+++ b/libraries/render-utils/src/TextRenderer3D.cpp
@@ -67,11 +67,11 @@ float TextRenderer3D::getFontSize() const {
 }
 
 void TextRenderer3D::draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color,
-                         const glm::vec2& bounds, bool layered) {
+                         const glm::vec2& bounds, bool forward) {
     // The font does all the OpenGL work
     if (_font) {
         _color = color;
-        _font->drawString(batch, _drawInfo, str, _color, _effectType, { x, y }, bounds, layered);
+        _font->drawString(batch, _drawInfo, str, _color, _effectType, { x, y }, bounds, forward);
     }
 }
 
diff --git a/libraries/render-utils/src/TextRenderer3D.h b/libraries/render-utils/src/TextRenderer3D.h
index 6c91411e1d..ce4dd9f9e5 100644
--- a/libraries/render-utils/src/TextRenderer3D.h
+++ b/libraries/render-utils/src/TextRenderer3D.h
@@ -38,8 +38,8 @@ public:
     glm::vec2 computeExtent(const QString& str) const;
     float getFontSize() const; // Pixel size
     
-    void draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color = glm::vec4(1.0f),
-              const glm::vec2& bounds = glm::vec2(-1.0f), bool layered = false);
+    void draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color,
+              const glm::vec2& bounds, bool forward);
 
 private:
     TextRenderer3D(const char* family, float pointSize, int weight = -1, bool italic = false,
diff --git a/libraries/render-utils/src/forward_grid.slf b/libraries/render-utils/src/forward_grid.slf
new file mode 100644
index 0000000000..e34794bfed
--- /dev/null
+++ b/libraries/render-utils/src/forward_grid.slf
@@ -0,0 +1,40 @@
+<@include gpu/Config.slh@>
+<$VERSION_HEADER$>
+//  Generated on <$_SCRIBE_DATE$>
+//
+//  Created by Sam Gondelman on 5/9/19
+//  Copyright 2019 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 gpu/ShaderConstants.h@>
+<@include gpu/Paint.slh@>
+
+struct Grid {
+    vec4 period;
+    vec4 offset;
+    vec4 edge;
+};
+
+LAYOUT(binding=0) uniform gridBuffer {
+  Grid grid;
+};
+
+layout(location=GPU_ATTR_TEXCOORD0) in vec2 varTexCoord0;
+layout(location=GPU_ATTR_COLOR) in vec4 varColor;
+
+layout(location=0) out vec4 _fragColor0;
+
+void main(void) {
+    float alpha = mix(paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge),
+                      paintGrid(varTexCoord0, grid.offset.xy, grid.period.xy, grid.edge.xy),
+                      float(grid.edge.z == 0.0));
+
+    if (alpha < 0.0001) {
+        discard;
+    }
+
+    _fragColor0 = vec4(varColor.xyz, 1.0);
+}
diff --git a/libraries/render-utils/src/forward_grid_translucent.slf b/libraries/render-utils/src/forward_grid_translucent.slf
new file mode 100644
index 0000000000..df0494a22e
--- /dev/null
+++ b/libraries/render-utils/src/forward_grid_translucent.slf
@@ -0,0 +1,41 @@
+<@include gpu/Config.slh@>
+<$VERSION_HEADER$>
+//  Generated on <$_SCRIBE_DATE$>
+//
+//  Created by Sam Gondelman on 5/9/19
+//  Copyright 2019 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 gpu/ShaderConstants.h@>
+<@include gpu/Paint.slh@>
+
+struct Grid {
+    vec4 period;
+    vec4 offset;
+    vec4 edge;
+};
+
+LAYOUT(binding=0) uniform gridBuffer {
+  Grid grid;
+};
+
+layout(location=GPU_ATTR_TEXCOORD0) in vec2 varTexCoord0;
+layout(location=GPU_ATTR_COLOR) in vec4 varColor;
+
+layout(location=0) out vec4 _fragColor0;
+
+void main(void) {
+    float alpha = mix(paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge),
+                      paintGrid(varTexCoord0, grid.offset.xy, grid.period.xy, grid.edge.xy),
+                      float(grid.edge.z == 0.0));
+    alpha *= varColor.w;
+
+    if (alpha < 0.0001) {
+        discard;
+    }
+
+    _fragColor0 = vec4(varColor.xyz, alpha);
+}
diff --git a/libraries/render-utils/src/forward_parabola.slf b/libraries/render-utils/src/forward_parabola.slf
new file mode 100644
index 0000000000..b0def6db6b
--- /dev/null
+++ b/libraries/render-utils/src/forward_parabola.slf
@@ -0,0 +1,18 @@
+<@include gpu/Config.slh@>
+<$VERSION_HEADER$>
+//  Generated on <$_SCRIBE_DATE$>
+//
+//  Created by Sam Gondelman on 5/9/19
+//  Copyright 2019 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
+//
+
+layout(location=0) in vec4 _color;
+
+layout(location=0) out vec4 _fragColor0;
+
+void main(void) {
+    _fragColor0 = _color;
+}
diff --git a/libraries/render-utils/src/parabola_forward.slv b/libraries/render-utils/src/parabola_forward.slv
deleted file mode 100644
index 4eb1456666..0000000000
--- a/libraries/render-utils/src/parabola_forward.slv
+++ /dev/null
@@ -1,7 +0,0 @@
-layout(location=0) in vec4 _color;
-
-layout(location=0) out vec4 _fragColor0;
-
-void main(void) {
-    _fragColor0 = _color;
-}
\ No newline at end of file
diff --git a/libraries/render-utils/src/render-utils/forward_grid.slp b/libraries/render-utils/src/render-utils/forward_grid.slp
new file mode 100644
index 0000000000..c81b208f63
--- /dev/null
+++ b/libraries/render-utils/src/render-utils/forward_grid.slp
@@ -0,0 +1 @@
+VERTEX standardTransformPNTC
diff --git a/libraries/render-utils/src/render-utils/forward_grid_translucent.slp b/libraries/render-utils/src/render-utils/forward_grid_translucent.slp
new file mode 100644
index 0000000000..c81b208f63
--- /dev/null
+++ b/libraries/render-utils/src/render-utils/forward_grid_translucent.slp
@@ -0,0 +1 @@
+VERTEX standardTransformPNTC
diff --git a/libraries/render-utils/src/render-utils/forward_parabola.slp b/libraries/render-utils/src/render-utils/forward_parabola.slp
new file mode 100644
index 0000000000..ab3f1d4126
--- /dev/null
+++ b/libraries/render-utils/src/render-utils/forward_parabola.slp
@@ -0,0 +1 @@
+VERTEX parabola
diff --git a/libraries/render-utils/src/text/Font.cpp b/libraries/render-utils/src/text/Font.cpp
index 364e24c5ac..c69db5e055 100644
--- a/libraries/render-utils/src/text/Font.cpp
+++ b/libraries/render-utils/src/text/Font.cpp
@@ -13,10 +13,13 @@
 #include "FontFamilies.h"
 #include "../StencilMaskPass.h"
 
-#include "DisableDeferred.h"
-
 static std::mutex fontMutex;
 
+gpu::PipelinePointer Font::_deferredPipeline;
+gpu::PipelinePointer Font::_forwardPipeline;
+gpu::PipelinePointer Font::_transparentPipeline;
+gpu::Stream::FormatPointer Font::_format;
+
 struct TextureVertex {
     glm::vec2 pos;
     glm::vec2 tex;
@@ -218,13 +221,10 @@ void Font::read(QIODevice& in) {
 }
 
 void Font::setupGPU() {
-    if (!_initialized) {
-        _initialized = true;
-
+    if (!_deferredPipeline) {
         // Setup render pipeline
         {
             {
-                gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::forward_sdf_text3D);
                 auto state = std::make_shared<gpu::State>();
                 state->setCullMode(gpu::State::CULL_BACK);
                 state->setDepthTest(true, true, gpu::LESS_EQUAL);
@@ -232,25 +232,11 @@ void Font::setupGPU() {
                     gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
                     gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
                 PrepareStencil::testMaskDrawShape(*state);
-                _layeredPipeline = gpu::Pipeline::create(program, state);
-            }
-
-            if (DISABLE_DEFERRED) {
-                _pipeline = _layeredPipeline;
-            } else {
-                gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D);
-                auto state = std::make_shared<gpu::State>();
-                state->setCullMode(gpu::State::CULL_BACK);
-                state->setDepthTest(true, true, gpu::LESS_EQUAL);
-                state->setBlendFunction(false,
-                    gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
-                    gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
-                PrepareStencil::testMaskDrawShape(*state);
-                _pipeline = gpu::Pipeline::create(program, state);
+                _deferredPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D), state);
+                _forwardPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(shader::render_utils::program::forward_sdf_text3D), state);
             }
 
             {
-                gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D_transparent);
                 auto state = std::make_shared<gpu::State>();
                 state->setCullMode(gpu::State::CULL_BACK);
                 state->setDepthTest(true, true, gpu::LESS_EQUAL);
@@ -258,7 +244,7 @@ void Font::setupGPU() {
                     gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
                     gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
                 PrepareStencil::testMask(*state);
-                _transparentPipeline = gpu::Pipeline::create(program, state);
+                _transparentPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D_transparent), state);
             }
         }
 
@@ -363,7 +349,7 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm
 }
 
 void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString& str, const glm::vec4& color,
-                      EffectType effectType, const glm::vec2& origin, const glm::vec2& bounds, bool layered) {
+                      EffectType effectType, const glm::vec2& origin, const glm::vec2& bounds, bool forward) {
     if (str == "") {
         return;
     }
@@ -390,7 +376,7 @@ void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString
     }
     // need the gamma corrected color here
 
-    batch.setPipeline(color.a < 1.0f ? _transparentPipeline : (layered ? _layeredPipeline : _pipeline));
+    batch.setPipeline(color.a < 1.0f ? _transparentPipeline : (forward ? _forwardPipeline : _deferredPipeline));
     batch.setInputFormat(_format);
     batch.setInputBuffer(0, drawInfo.verticesBuffer, 0, _format->getChannels().at(0)._stride);
     batch.setResourceTexture(render_utils::slot::texture::TextFont, _texture);
diff --git a/libraries/render-utils/src/text/Font.h b/libraries/render-utils/src/text/Font.h
index 28af5bac43..893ab59981 100644
--- a/libraries/render-utils/src/text/Font.h
+++ b/libraries/render-utils/src/text/Font.h
@@ -46,7 +46,7 @@ public:
     // Render string to batch
     void drawString(gpu::Batch& batch, DrawInfo& drawInfo, const QString& str,
         const glm::vec4& color, EffectType effectType, 
-        const glm::vec2& origin, const glm::vec2& bound, bool layered);
+        const glm::vec2& origin, const glm::vec2& bound, bool forward);
 
     static Pointer load(const QString& family);
 
@@ -77,15 +77,13 @@ private:
     float _descent = 0.0f;
     float _spaceWidth = 0.0f;
 
-    bool _initialized = false;
-
-    // gpu structures
-    gpu::PipelinePointer _pipeline;
-    gpu::PipelinePointer _layeredPipeline;
-    gpu::PipelinePointer _transparentPipeline;
     gpu::TexturePointer _texture;
-    gpu::Stream::FormatPointer _format;
     gpu::BufferStreamPointer _stream;
+
+    static gpu::PipelinePointer _deferredPipeline;
+    static gpu::PipelinePointer _forwardPipeline;
+    static gpu::PipelinePointer _transparentPipeline;
+    static gpu::Stream::FormatPointer _format;
 };
 
 #endif
diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h
index 953a0b8223..7821692a60 100644
--- a/libraries/render/src/render/Args.h
+++ b/libraries/render/src/render/Args.h
@@ -64,6 +64,7 @@ namespace render {
     public:
         enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, MIRROR_RENDER_MODE, SECONDARY_CAMERA_RENDER_MODE };
         enum DisplayMode { MONO, STEREO_MONITOR, STEREO_HMD };
+        enum RenderMethod { DEFERRED, FORWARD };
         enum DebugFlags {
             RENDER_DEBUG_NONE = 0,
             RENDER_DEBUG_HULLS = 1
@@ -77,6 +78,7 @@ namespace render {
             float lodAngleHalfTan = 0.1f,
             RenderMode renderMode = DEFAULT_RENDER_MODE,
             DisplayMode displayMode = MONO,
+            RenderMethod renderMethod = DEFERRED,
             DebugFlags debugFlags = RENDER_DEBUG_NONE,
             gpu::Batch* batch = nullptr) :
             _context(context),
@@ -86,6 +88,7 @@ namespace render {
             _lodAngleHalfTanSq(lodAngleHalfTan * lodAngleHalfTan),
             _renderMode(renderMode),
             _displayMode(displayMode),
+            _renderMethod(renderMethod),
             _debugFlags(debugFlags),
             _batch(batch) {
         }
@@ -117,6 +120,7 @@ namespace render {
 
         RenderMode _renderMode { DEFAULT_RENDER_MODE };
         DisplayMode _displayMode { MONO };
+        RenderMethod _renderMethod { DEFERRED };
         DebugFlags _debugFlags { RENDER_DEBUG_NONE };
         gpu::Batch* _batch = nullptr;
 
diff --git a/libraries/shared/src/DisableDeferred.h b/libraries/shared/src/DisableDeferred.h
deleted file mode 100644
index 9a1f9be117..0000000000
--- a/libraries/shared/src/DisableDeferred.h
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-//  Created by Sam Gondelman on 3/7/19.
-//  Copyright 2019 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_DisableDeferred_h
-#define hifi_DisableDeferred_h
-
-#include <QString>
-#include <QProcess>
-
-#if defined(USE_GLES)
-static bool DISABLE_DEFERRED = true;
-#else
-static const QString RENDER_FORWARD{ "HIFI_RENDER_FORWARD" };
-static bool DISABLE_DEFERRED = QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD);
-#endif
-
-
-#endif // hifi_DisableDeferred_h
-
diff --git a/libraries/shared/src/RenderForward.h b/libraries/shared/src/RenderForward.h
new file mode 100644
index 0000000000..e6fdef255b
--- /dev/null
+++ b/libraries/shared/src/RenderForward.h
@@ -0,0 +1,24 @@
+//
+//  Created by Sam Gondelman on 3/7/19.
+//  Copyright 2019 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_RenderForward_h
+#define hifi_RenderForward_h
+
+#include <QString>
+#include <QProcess>
+
+#if defined(USE_GLES)
+// This isn't necessary since android forces the forward renderer, but just in case
+static bool RENDER_FORWARD = true;
+#else
+static const QString RENDER_FORWARD_STRING { "HIFI_RENDER_FORWARD" };
+static bool RENDER_FORWARD = QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD_STRING);
+#endif
+
+
+#endif // hifi_RenderForward_h
\ No newline at end of file
diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h
index 87fb21d59b..cdc279ff36 100644
--- a/libraries/task/src/task/Task.h
+++ b/libraries/task/src/task/Task.h
@@ -460,7 +460,7 @@ public:
         void applyConfiguration() override {
             TimeProfiler probe("configure::" + JobConcept::getName());
             jobConfigure(_data, *std::static_pointer_cast<C>(Concept::_config));
-            for (auto& branch : _branches) {
+            for (auto& branch : SwitchConcept::_branches) {
                 branch.second.applyConfiguration();
             }
         }
@@ -468,13 +468,9 @@ public:
         void run(const ContextPointer& jobContext) override {
             auto config = std::static_pointer_cast<C>(Concept::_config);
             if (config->isEnabled()) {
-                auto jobsIt = _branches.find(config->getBranch());
-                if (jobsIt != _branches.end()) {
+                auto jobsIt = SwitchConcept::_branches.find(config->getBranch());
+                if (jobsIt != SwitchConcept::_branches.end()) {
                     jobsIt->second.run(jobContext);
-                    if (jobContext->taskFlow.doAbortTask()) {
-                        jobContext->taskFlow.reset();
-                        return;
-                    }
                 }
             }
         }