From bc59be12efc5d9249d90dc67ff0cb64e6222e7ab Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 13 Dec 2016 19:16:08 -0500 Subject: [PATCH 1/3] 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 From bbb72293924e98d6fc7778f7baf5fe0da1910e10 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 13 Dec 2016 20:47:28 -0500 Subject: [PATCH 2/3] skip graphics config if not in engine --- interface/src/ui/PreferencesDialog.cpp | 33 +++++++++++++------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 2c6440094b..a4cb62cc13 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -292,23 +292,24 @@ void setupPreferences() { { static const QString RENDER("Graphics"); auto renderConfig = qApp->getRenderEngine()->getConfiguration(); + if (renderConfig) { + auto ambientOcclusionConfig = renderConfig->getConfig(); + if (ambientOcclusionConfig) { + auto getter = [ambientOcclusionConfig]()->QString { return ambientOcclusionConfig->getPreset(); }; + auto setter = [ambientOcclusionConfig](QString preset) { ambientOcclusionConfig->setPreset(preset); }; + auto preference = new ComboBoxPreference(RENDER, "Ambient occlusion", getter, setter); + preference->setItems(ambientOcclusionConfig->getPresetList()); + preferences->addPreference(preference); + } - auto ambientOcclusionConfig = renderConfig->getConfig(); - { - auto getter = [ambientOcclusionConfig]()->QString { return ambientOcclusionConfig->getPreset(); }; - auto setter = [ambientOcclusionConfig](QString preset) { ambientOcclusionConfig->setPreset(preset); }; - auto preference = new ComboBoxPreference(RENDER, "Ambient occlusion", getter, setter); - preference->setItems(ambientOcclusionConfig->getPresetList()); - preferences->addPreference(preference); - } - - auto shadowConfig = renderConfig->getConfig(); - { - auto getter = [shadowConfig]()->QString { return shadowConfig->getPreset(); }; - auto setter = [shadowConfig](QString preset) { shadowConfig->setPreset(preset); }; - auto preference = new ComboBoxPreference(RENDER, "Shadows", getter, setter); - preference->setItems(shadowConfig->getPresetList()); - preferences->addPreference(preference); + auto shadowConfig = renderConfig->getConfig(); + if (shadowConfig) { + auto getter = [shadowConfig]()->QString { return shadowConfig->getPreset(); }; + auto setter = [shadowConfig](QString preset) { shadowConfig->setPreset(preset); }; + auto preference = new ComboBoxPreference(RENDER, "Shadows", getter, setter); + preference->setItems(shadowConfig->getPresetList()); + preferences->addPreference(preference); + } } } { From 87a8ad128933097be800b5e0b476d4f7cb4e5792 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 13 Dec 2016 20:48:05 -0500 Subject: [PATCH 3/3] strip forward render task to clear and blit --- .../render-utils/src/RenderForwardTask.cpp | 177 +++++------------- .../render-utils/src/RenderForwardTask.h | 11 +- 2 files changed, 54 insertions(+), 134 deletions(-) diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index 533b26a5ce..da7fcf5cdd 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -93,140 +93,10 @@ RenderForwardTask::RenderForwardTask(CullFunctor cullFunctor) { 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); + const auto framebuffer = addJob("PrepareFramebuffer"); // Blit! - addJob("Blit", primaryFramebuffer); - - // addJob("RangeTimer", fullFrameRangeTimer); - + addJob("Blit", framebuffer); } void RenderForwardTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { @@ -248,3 +118,46 @@ void RenderForwardTask::run(const SceneContextPointer& sceneContext, const Rende job.run(sceneContext, renderContext); } } + +void PrepareFramebuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer) { + auto framebufferCache = DependencyManager::get(); + auto framebufferSize = framebufferCache->getFrameBufferSize(); + glm::uvec2 frameSize(framebufferSize.width(), framebufferSize.height()); + + // Resizing framebuffers instead of re-building them seems to cause issues with threaded rendering + if (_framebuffer && _framebuffer->getSize() != frameSize) { + _framebuffer.reset(); + } + + if (!_framebuffer) { + _framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("forward")); + + auto colorFormat = gpu::Element::COLOR_SRGBA_32; + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + auto colorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, frameSize.x, frameSize.y, defaultSampler)); + _framebuffer->setRenderBuffer(0, colorTexture); + + auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format + auto depthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, frameSize.x, frameSize.y, defaultSampler)); + _framebuffer->setDepthStencilBuffer(depthTexture, depthFormat); + } + + auto args = renderContext->args; + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); + + batch.setFramebuffer(_framebuffer); + batch.clearFramebuffer( + gpu::Framebuffer::BUFFER_COLOR0 | + gpu::Framebuffer::BUFFER_COLOR1 | + gpu::Framebuffer::BUFFER_COLOR2 | + gpu::Framebuffer::BUFFER_COLOR3 | + gpu::Framebuffer::BUFFER_DEPTH | + gpu::Framebuffer::BUFFER_STENCIL, + vec4(vec3(0), 0), 1.0, 0.0, true); + }); + + framebuffer = _framebuffer; +} diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h index 0d6da2fbd3..9c4634a8ee 100755 --- a/libraries/render-utils/src/RenderForwardTask.h +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -27,9 +27,16 @@ public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); using JobModel = Model; +}; -protected: - gpu::RangeTimerPointer _gpuTimer; +class PrepareFramebuffer { +public: + using JobModel = render::Job::ModelO; + + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer); + +private: + gpu::FramebufferPointer _framebuffer; }; #endif // hifi_RenderForwardTask_h