From bc59be12efc5d9249d90dc67ff0cb64e6222e7ab Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 13 Dec 2016 19:16:08 -0500 Subject: [PATCH] create flagged forward render task --- interface/src/Application.cpp | 9 +- .../render-utils/src/RenderForwardTask.cpp | 250 ++++++++++++++++++ .../render-utils/src/RenderForwardTask.h | 35 +++ 3 files changed, 292 insertions(+), 2 deletions(-) create mode 100755 libraries/render-utils/src/RenderForwardTask.cpp create mode 100755 libraries/render-utils/src/RenderForwardTask.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4ec29b636b..d4061e699b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -97,6 +97,7 @@ #include #include #include +#include #include #include #include @@ -1739,10 +1740,14 @@ void Application::initializeGL() { // Set up the render engine render::CullFunctor cullFunctor = LODManager::shouldRender; _renderEngine->addJob("RenderShadowTask", cullFunctor); - _renderEngine->addJob("RenderDeferredTask", cullFunctor); + static const QString RENDER_FORWARD = "RENDER_FORWARD"; + if (QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD)) { + _renderEngine->addJob("RenderForwardTask", cullFunctor); + } else { + _renderEngine->addJob("RenderDeferredTask", cullFunctor); + } _renderEngine->load(); _renderEngine->registerScene(_main3DScene); - // TODO: Load a cached config file // The UI can't be created until the primary OpenGL // context is created, because it needs to share diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp new file mode 100755 index 0000000000..533b26a5ce --- /dev/null +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -0,0 +1,250 @@ + +// +// RenderForwardTask.cpp +// render-utils/src/ +// +// Created by Zach Pomerantz on 12/13/2016. +// Copyright 2016 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 "RenderForwardTask.h" +#include "RenderDeferredTask.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "LightingModel.h" +#include "DebugDeferredBuffer.h" +#include "DeferredFramebuffer.h" +#include "DeferredLightingEffect.h" +#include "SurfaceGeometryPass.h" +#include "FramebufferCache.h" +#include "HitEffect.h" +#include "TextureCache.h" + +#include "AmbientOcclusionEffect.h" +#include "AntialiasingEffect.h" +#include "ToneMappingEffect.h" +#include "SubsurfaceScattering.h" + +#include + +#include "drawOpaqueStencil_frag.h" + + +using namespace render; +extern void initOverlay3DPipelines(render::ShapePlumber& plumber); +extern void initDeferredPipelines(render::ShapePlumber& plumber); + +RenderForwardTask::RenderForwardTask(CullFunctor cullFunctor) { + // Prepare the ShapePipelines + ShapePlumberPointer shapePlumber = std::make_shared(); + initDeferredPipelines(*shapePlumber); + + // CPU jobs: + // Fetch and cull the items from the scene + const auto spatialSelection = addJob("FetchSceneSelection"); + + cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&){ return true; }; + auto spatialFilter = ItemFilter::Builder::visibleWorldItems().withoutLayered(); + const auto culledSpatialSelection = addJob("CullSceneSelection", spatialSelection, cullFunctor, RenderDetails::ITEM, spatialFilter); + + // Overlays are not culled + const auto nonspatialSelection = addJob("FetchOverlaySelection"); + + // Multi filter visible items into different buckets + const int NUM_FILTERS = 3; + const int OPAQUE_SHAPE_BUCKET = 0; + const int TRANSPARENT_SHAPE_BUCKET = 1; + const int LIGHT_BUCKET = 2; + const int BACKGROUND_BUCKET = 2; + MultiFilterItem::ItemFilterArray spatialFilters = { { + ItemFilter::Builder::opaqueShape(), + ItemFilter::Builder::transparentShape(), + ItemFilter::Builder::light() + } }; + MultiFilterItem::ItemFilterArray nonspatialFilters = { { + ItemFilter::Builder::opaqueShape(), + ItemFilter::Builder::transparentShape(), + ItemFilter::Builder::background() + } }; + const auto filteredSpatialBuckets = addJob>("FilterSceneSelection", culledSpatialSelection, spatialFilters).get::ItemBoundsArray>(); + const auto filteredNonspatialBuckets = addJob>("FilterOverlaySelection", nonspatialSelection, nonspatialFilters).get::ItemBoundsArray>(); + + // Extract / Sort opaques / Transparents / Lights / Overlays + const auto opaques = addJob("DepthSortOpaque", filteredSpatialBuckets[OPAQUE_SHAPE_BUCKET]); + const auto transparents = addJob("DepthSortTransparent", filteredSpatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false)); + const auto lights = filteredSpatialBuckets[LIGHT_BUCKET]; + + const auto overlayOpaques = addJob("DepthSortOverlayOpaque", filteredNonspatialBuckets[OPAQUE_SHAPE_BUCKET]); + const auto overlayTransparents = addJob("DepthSortOverlayTransparent", filteredNonspatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false)); + const auto background = filteredNonspatialBuckets[BACKGROUND_BUCKET]; + + // Prepare deferred, generate the shared Deferred Frame Transform + const auto deferredFrameTransform = addJob("DeferredFrameTransform"); + const auto lightingModel = addJob("LightingModel"); + + + // GPU jobs: Start preparing the primary, deferred and lighting buffer + const auto primaryFramebuffer = addJob("PreparePrimaryBuffer"); + + // const auto fullFrameRangeTimer = addJob("BeginRangeTimer"); + const auto opaqueRangeTimer = addJob("BeginOpaqueRangeTimer", "DrawOpaques"); + + const auto prepareDeferredInputs = PrepareDeferred::Inputs(primaryFramebuffer, lightingModel).hasVarying(); + const auto prepareDeferredOutputs = addJob("PrepareDeferred", prepareDeferredInputs); + const auto deferredFramebuffer = prepareDeferredOutputs.getN(0); + const auto lightingFramebuffer = prepareDeferredOutputs.getN(1); + + // Render opaque objects in DeferredBuffer + const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).hasVarying(); + addJob("DrawOpaqueDeferred", opaqueInputs, shapePlumber); + + // Once opaque is all rendered create stencil background + addJob("DrawOpaqueStencil", deferredFramebuffer); + + addJob("OpaqueRangeTimer", opaqueRangeTimer); + + + // Opaque all rendered + + // Linear Depth Pass + const auto linearDepthPassInputs = LinearDepthPass::Inputs(deferredFrameTransform, deferredFramebuffer).hasVarying(); + const auto linearDepthPassOutputs = addJob("LinearDepth", linearDepthPassInputs); + const auto linearDepthTarget = linearDepthPassOutputs.getN(0); + + // Curvature pass + const auto surfaceGeometryPassInputs = SurfaceGeometryPass::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget).hasVarying(); + const auto surfaceGeometryPassOutputs = addJob("SurfaceGeometry", surfaceGeometryPassInputs); + const auto surfaceGeometryFramebuffer = surfaceGeometryPassOutputs.getN(0); + const auto curvatureFramebuffer = surfaceGeometryPassOutputs.getN(1); + const auto midCurvatureNormalFramebuffer = surfaceGeometryPassOutputs.getN(2); + const auto lowCurvatureNormalFramebuffer = surfaceGeometryPassOutputs.getN(3); + + // Simply update the scattering resource + const auto scatteringResource = addJob("Scattering"); + + // AO job + const auto ambientOcclusionInputs = AmbientOcclusionEffect::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget).hasVarying(); + const auto ambientOcclusionOutputs = addJob("AmbientOcclusion", ambientOcclusionInputs); + const auto ambientOcclusionFramebuffer = ambientOcclusionOutputs.getN(0); + const auto ambientOcclusionUniforms = ambientOcclusionOutputs.getN(1); + + + // Draw Lights just add the lights to the current list of lights to deal with. NOt really gpu job for now. + addJob("DrawLight", lights); + + // Light Clustering + // Create the cluster grid of lights, cpu job for now + const auto lightClusteringPassInputs = LightClusteringPass::Inputs(deferredFrameTransform, lightingModel, linearDepthTarget).hasVarying(); + const auto lightClusters = addJob("LightClustering", lightClusteringPassInputs); + + + // DeferredBuffer is complete, now let's shade it into the LightingBuffer + const auto deferredLightingInputs = RenderDeferred::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, + surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource, lightClusters).hasVarying(); + + addJob("RenderDeferred", deferredLightingInputs); + + // Use Stencil and draw background in Lighting buffer to complete filling in the opaque + const auto backgroundInputs = DrawBackgroundDeferred::Inputs(background, lightingModel).hasVarying(); + addJob("DrawBackgroundDeferred", backgroundInputs); + + + // Render transparent objects forward in LightingBuffer + const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).hasVarying(); + addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber); + + // LIght Cluster Grid Debuging job + { + const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget, lightClusters).hasVarying(); + addJob("DebugLightClusters", debugLightClustersInputs); + } + + const auto toneAndPostRangeTimer = addJob("BeginToneAndPostRangeTimer", "PostToneOverlaysAntialiasing"); + + // Lighting Buffer ready for tone mapping + const auto toneMappingInputs = render::Varying(ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer)); + addJob("ToneMapping", toneMappingInputs); + + // Overlays + const auto overlayOpaquesInputs = DrawOverlay3D::Inputs(overlayOpaques, lightingModel).hasVarying(); + const auto overlayTransparentsInputs = DrawOverlay3D::Inputs(overlayTransparents, lightingModel).hasVarying(); + addJob("DrawOverlay3DOpaque", overlayOpaquesInputs, true); + addJob("DrawOverlay3DTransparent", overlayTransparentsInputs, false); + + + // Debugging stages + { + // Debugging Deferred buffer job + const auto debugFramebuffers = render::Varying(DebugDeferredBuffer::Inputs(deferredFramebuffer, linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer)); + addJob("DebugDeferredBuffer", debugFramebuffers); + + const auto debugSubsurfaceScatteringInputs = DebugSubsurfaceScattering::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, + surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource).hasVarying(); + addJob("DebugScattering", debugSubsurfaceScatteringInputs); + + const auto debugAmbientOcclusionInputs = DebugAmbientOcclusion::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget, ambientOcclusionUniforms).hasVarying(); + addJob("DebugAmbientOcclusion", debugAmbientOcclusionInputs); + + + // Scene Octree Debuging job + { + addJob("DrawSceneOctree", spatialSelection); + addJob("DrawItemSelection", spatialSelection); + } + + // Status icon rendering job + { + // Grab a texture map representing the different status icons and assign that to the drawStatsuJob + auto iconMapPath = PathUtils::resourcesPath() + "icons/statusIconAtlas.svg"; + auto statusIconMap = DependencyManager::get()->getImageTexture(iconMapPath); + addJob("DrawStatus", opaques, DrawStatus(statusIconMap)); + } + } + + + // AA job to be revisited + addJob("Antialiasing", primaryFramebuffer); + + addJob("ToneAndPostRangeTimer", toneAndPostRangeTimer); + + // Blit! + addJob("Blit", primaryFramebuffer); + + // addJob("RangeTimer", fullFrameRangeTimer); + +} + +void RenderForwardTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + // sanity checks + assert(sceneContext); + if (!sceneContext->_scene) { + return; + } + + + // Is it possible that we render without a viewFrustum ? + if (!(renderContext->args && renderContext->args->hasViewFrustum())) { + return; + } + + auto config = std::static_pointer_cast(renderContext->jobConfig); + + for (auto job : _jobs) { + job.run(sceneContext, renderContext); + } +} diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h new file mode 100755 index 0000000000..0d6da2fbd3 --- /dev/null +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -0,0 +1,35 @@ +// +// RenderForwardTask.h +// render-utils/src/ +// +// Created by Zach Pomerantz on 12/13/2016. +// Copyright 2016 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_RenderForwardTask_h +#define hifi_RenderForwardTask_h + +#include +#include +#include "LightingModel.h" + +using RenderForwardTaskConfig = render::GPUTaskConfig; + +class RenderForwardTask : public render::Task { +public: + using Config = RenderForwardTaskConfig; + RenderForwardTask(render::CullFunctor cullFunctor); + + void configure(const Config& config) {} + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + + using JobModel = Model; + +protected: + gpu::RangeTimerPointer _gpuTimer; +}; + +#endif // hifi_RenderForwardTask_h