Defer batch execution to the end of the frame generation

This commit is contained in:
Bradley Austin Davis 2016-07-26 16:13:48 -07:00
parent fa20898285
commit a9740b803f
6 changed files with 147 additions and 74 deletions

View file

@ -1689,6 +1689,17 @@ void Application::paintGL() {
renderArgs._context->syncCache(); renderArgs._context->syncCache();
} }
auto framebufferCache = DependencyManager::get<FramebufferCache>();
// Final framebuffer that will be handled to the display-plugin
auto finalFramebuffer = framebufferCache->getFramebuffer();
_gpuContext->beginFrame(finalFramebuffer, getHMDSensorPose());
// Reset the gpu::Context Stages
// Back to the default framebuffer;
gpu::doInBatch(_gpuContext, [&](gpu::Batch& batch) {
batch.resetStages();
});
auto inputs = AvatarInputs::getInstance(); auto inputs = AvatarInputs::getInstance();
if (inputs->mirrorVisible()) { if (inputs->mirrorVisible()) {
PerformanceTimer perfTimer("Mirror"); PerformanceTimer perfTimer("Mirror");
@ -1711,10 +1722,6 @@ void Application::paintGL() {
QSize size = getDeviceSize(); QSize size = getDeviceSize();
renderArgs._viewport = glm::ivec4(0, 0, size.width(), size.height()); renderArgs._viewport = glm::ivec4(0, 0, size.width(), size.height());
_applicationOverlay.renderOverlay(&renderArgs); _applicationOverlay.renderOverlay(&renderArgs);
auto overlayTexture = _applicationOverlay.acquireOverlay();
if (overlayTexture) {
displayPlugin->submitOverlayTexture(overlayTexture);
}
} }
glm::vec3 boomOffset; glm::vec3 boomOffset;
@ -1816,12 +1823,8 @@ void Application::paintGL() {
getApplicationCompositor().setFrameInfo(_frameCount, _myCamera.getTransform()); getApplicationCompositor().setFrameInfo(_frameCount, _myCamera.getTransform());
// Primary rendering pass // Primary rendering pass
auto framebufferCache = DependencyManager::get<FramebufferCache>();
const QSize size = framebufferCache->getFrameBufferSize(); const QSize size = framebufferCache->getFrameBufferSize();
// Final framebuffer that will be handled to the display-plugin
auto finalFramebuffer = framebufferCache->getFramebuffer();
{ {
PROFILE_RANGE(__FUNCTION__ "/mainRender"); PROFILE_RANGE(__FUNCTION__ "/mainRender");
PerformanceTimer perfTimer("mainRender"); PerformanceTimer perfTimer("mainRender");
@ -1880,6 +1883,13 @@ void Application::paintGL() {
renderArgs._context->enableStereo(false); renderArgs._context->enableStereo(false);
} }
_gpuContext->endFrame();
gpu::TexturePointer overlayTexture = _applicationOverlay.acquireOverlay();
if (overlayTexture) {
displayPlugin->submitOverlayTexture(overlayTexture);
}
// deliver final composited scene to the display plugin // deliver final composited scene to the display plugin
{ {
PROFILE_RANGE(__FUNCTION__ "/pluginOutput"); PROFILE_RANGE(__FUNCTION__ "/pluginOutput");
@ -1900,11 +1910,6 @@ void Application::paintGL() {
{ {
Stats::getInstance()->setRenderDetails(renderArgs._details); Stats::getInstance()->setRenderDetails(renderArgs._details);
// Reset the gpu::Context Stages
// Back to the default framebuffer;
gpu::doInBatch(renderArgs._context, [&](gpu::Batch& batch) {
batch.resetStages();
});
} }
uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin; uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin;

View file

@ -46,6 +46,33 @@ Batch::Batch() {
_drawCallInfos.reserve(_drawCallInfosMax); _drawCallInfos.reserve(_drawCallInfosMax);
} }
Batch::Batch(const Batch& batch_) {
Batch& batch = *const_cast<Batch*>(&batch_);
_commands.swap(batch._commands);
_commandOffsets.swap(batch._commandOffsets);
_params.swap(batch._params);
_data.swap(batch._data);
_invalidModel = batch._invalidModel;
_currentModel = batch._currentModel;
_objects.swap(batch._objects);
_currentNamedCall = batch._currentNamedCall;
_buffers._items.swap(batch._buffers._items);
_textures._items.swap(batch._textures._items);
_streamFormats._items.swap(batch._streamFormats._items);
_transforms._items.swap(batch._transforms._items);
_pipelines._items.swap(batch._pipelines._items);
_framebuffers._items.swap(batch._framebuffers._items);
_drawCallInfos.swap(batch._drawCallInfos);
_queries._items.swap(batch._queries._items);
_lambdas._items.swap(batch._lambdas._items);
_profileRanges._items.swap(batch._profileRanges._items);
_names._items.swap(batch._names._items);
_namedData.swap(batch._namedData);
_enableStereo = batch._enableStereo;
_enableSkybox = batch._enableSkybox;
}
Batch::~Batch() { Batch::~Batch() {
_commandsMax = std::max(_commands.size(), _commandsMax); _commandsMax = std::max(_commands.size(), _commandsMax);
_commandOffsetsMax = std::max(_commandOffsets.size(), _commandOffsetsMax); _commandOffsetsMax = std::max(_commandOffsets.size(), _commandOffsetsMax);

View file

@ -9,7 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include "Context.h" #include "Context.h"
#include "Frame.h"
using namespace gpu; using namespace gpu;
Context::CreateBackend Context::_createBackendCallback = nullptr; Context::CreateBackend Context::_createBackendCallback = nullptr;
@ -20,6 +20,13 @@ Context::Context() {
if (_createBackendCallback) { if (_createBackendCallback) {
_backend.reset(_createBackendCallback()); _backend.reset(_createBackendCallback());
} }
_frameHandler = [this](Frame& frame){
for (size_t i = 0; i < frame.batches.size(); ++i) {
_backend->_stereo = frame.stereoStates[i];
_backend->render(frame.batches[i]);
}
};
} }
Context::Context(const Context& context) { Context::Context(const Context& context) {
@ -28,6 +35,43 @@ Context::Context(const Context& context) {
Context::~Context() { Context::~Context() {
} }
void Context::setFrameHandler(FrameHandler handler) {
_frameHandler = handler;
}
#define DEFERRED_RENDERING
void Context::beginFrame(const FramebufferPointer& outputFramebuffer, const glm::mat4& renderPose) {
_currentFrame = Frame();
_currentFrame.framebuffer = outputFramebuffer;
_currentFrame.pose = renderPose;
_frameActive = true;
}
void Context::append(Batch& batch) {
if (!_frameActive) {
qWarning() << "Batch executed outside of frame boundaries";
}
#ifdef DEFERRED_RENDERING
_currentFrame.batches.emplace_back(batch);
_currentFrame.stereoStates.emplace_back(_stereo);
#else
_backend->_stereo = _stereo;
_backend->render(batch);
#endif
}
void Context::endFrame() {
#ifdef DEFERRED_RENDERING
if (_frameHandler) {
_frameHandler(_currentFrame);
}
#endif
_currentFrame = Frame();
_frameActive = false;
}
bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings) { bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings) {
if (shader.isProgram() && _makeProgramCallback) { if (shader.isProgram() && _makeProgramCallback) {
return _makeProgramCallback(shader, bindings); return _makeProgramCallback(shader, bindings);
@ -35,36 +79,38 @@ bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings) {
return false; return false;
} }
void Context::render(Batch& batch) {
PROFILE_RANGE(__FUNCTION__);
_backend->render(batch);
}
void Context::enableStereo(bool enable) { void Context::enableStereo(bool enable) {
_backend->enableStereo(enable); _stereo._enable = enable;
} }
bool Context::isStereo() { bool Context::isStereo() {
return _backend->isStereo(); return _stereo._enable;
} }
void Context::setStereoProjections(const mat4 eyeProjections[2]) { void Context::setStereoProjections(const mat4 eyeProjections[2]) {
_backend->setStereoProjections(eyeProjections); for (int i = 0; i < 2; ++i) {
_stereo._eyeProjections[i] = eyeProjections[i];
}
} }
void Context::setStereoViews(const mat4 eyeViews[2]) { void Context::setStereoViews(const mat4 views[2]) {
_backend->setStereoViews(eyeViews); for (int i = 0; i < 2; ++i) {
_stereo._eyeViews[i] = views[i];
}
} }
void Context::getStereoProjections(mat4* eyeProjections) const { void Context::getStereoProjections(mat4* eyeProjections) const {
_backend->getStereoProjections(eyeProjections); for (int i = 0; i < 2; ++i) {
eyeProjections[i] = _stereo._eyeProjections[i];
}
} }
void Context::getStereoViews(mat4* eyeViews) const { void Context::getStereoViews(mat4* eyeViews) const {
_backend->getStereoViews(eyeViews); for (int i = 0; i < 2; ++i) {
eyeViews[i] = _stereo._eyeViews[i];
}
} }
void Context::syncCache() { void Context::syncCache() {
PROFILE_RANGE(__FUNCTION__); PROFILE_RANGE(__FUNCTION__);
_backend->syncCache(); _backend->syncCache();
@ -103,12 +149,12 @@ Backend::TransformCamera Backend::TransformCamera::getEyeCamera(int eye, const S
if (!_stereo._skybox) { if (!_stereo._skybox) {
offsetTransform.postTranslate(-Vec3(_stereo._eyeViews[eye][3])); offsetTransform.postTranslate(-Vec3(_stereo._eyeViews[eye][3]));
} else { } else {
// FIXME: If "skybox" the ipd is set to 0 for now, let s try to propose a better solution for this in the future // FIXME: If "skybox" the ipd is set to 0 for now, let s try to propose a better solution for this in the future
} }
result._projection = _stereo._eyeProjections[eye]; result._projection = _stereo._eyeProjections[eye];
result.recomputeDerived(offsetTransform); result.recomputeDerived(offsetTransform);
result._stereoInfo = Vec4(1.0f, (float) eye, 0.0f, 0.0f); result._stereoInfo = Vec4(1.0f, (float)eye, 0.0f, 0.0f);
return result; return result;
} }
@ -125,7 +171,7 @@ std::atomic<uint32_t> Context::_textureGPUTransferCount{ 0 };
void Context::incrementBufferGPUCount() { void Context::incrementBufferGPUCount() {
_bufferGPUCount++; _bufferGPUCount++;
} }
void Context::decrementBufferGPUCount() { void Context::decrementBufferGPUCount() {
_bufferGPUCount--; _bufferGPUCount--;
} }
void Context::updateBufferGPUMemoryUsage(Size prevObjectSize, Size newObjectSize) { void Context::updateBufferGPUMemoryUsage(Size prevObjectSize, Size newObjectSize) {

View file

@ -16,12 +16,13 @@
#include <GLMHelpers.h> #include <GLMHelpers.h>
#include "Forward.h"
#include "Batch.h" #include "Batch.h"
#include "Resource.h" #include "Resource.h"
#include "Texture.h" #include "Texture.h"
#include "Pipeline.h" #include "Pipeline.h"
#include "Framebuffer.h" #include "Framebuffer.h"
#include "Frame.h"
class QImage; class QImage;
@ -46,51 +47,11 @@ public:
ContextStats(const ContextStats& stats) = default; ContextStats(const ContextStats& stats) = default;
}; };
struct StereoState {
bool _enable{ false };
bool _skybox{ false };
// 0 for left eye, 1 for right eye
uint8_t _pass{ 0 };
mat4 _eyeViews[2];
mat4 _eyeProjections[2];
};
class Backend { class Backend {
public: public:
virtual~ Backend() {}; virtual~ Backend() {};
virtual void render(Batch& batch) = 0; virtual void render(Batch& batch) = 0;
virtual void enableStereo(bool enable) {
_stereo._enable = enable;
}
virtual bool isStereo() {
return _stereo._enable;
}
void setStereoProjections(const mat4 eyeProjections[2]) {
for (int i = 0; i < 2; ++i) {
_stereo._eyeProjections[i] = eyeProjections[i];
}
}
void setStereoViews(const mat4 views[2]) {
for (int i = 0; i < 2; ++i) {
_stereo._eyeViews[i] = views[i];
}
}
void getStereoProjections(mat4* eyeProjections) const {
for (int i = 0; i < 2; ++i) {
eyeProjections[i] = _stereo._eyeProjections[i];
}
}
void getStereoViews(mat4* eyeViews) const {
for (int i = 0; i < 2; ++i) {
eyeViews[i] = _stereo._eyeViews[i];
}
}
virtual void syncCache() = 0; virtual void syncCache() = 0;
virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0; virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0;
@ -137,8 +98,25 @@ public:
static void decrementTextureGPUTransferCount(); static void decrementTextureGPUTransferCount();
protected: protected:
StereoState _stereo; virtual bool isStereo() {
return _stereo._enable;
}
void getStereoProjections(mat4* eyeProjections) const {
for (int i = 0; i < 2; ++i) {
eyeProjections[i] = _stereo._eyeProjections[i];
}
}
void getStereoViews(mat4* eyeViews) const {
for (int i = 0; i < 2; ++i) {
eyeViews[i] = _stereo._eyeViews[i];
}
}
friend class Context;
ContextStats _stats; ContextStats _stats;
StereoState _stereo;
}; };
class Context { class Context {
@ -161,7 +139,10 @@ public:
Context(); Context();
~Context(); ~Context();
void render(Batch& batch); void setFrameHandler(FrameHandler handler);
void beginFrame(const FramebufferPointer& outputFramebuffer, const glm::mat4& renderPose = glm::mat4());
void append(Batch& batch);
void endFrame();
void enableStereo(bool enable = true); void enableStereo(bool enable = true);
bool isStereo(); bool isStereo();
@ -191,6 +172,10 @@ protected:
Context(const Context& context); Context(const Context& context);
std::unique_ptr<Backend> _backend; std::unique_ptr<Backend> _backend;
bool _frameActive { false };
Frame _currentFrame;
FrameHandler _frameHandler;
StereoState _stereo;
// This function can only be called by "static Shader::makeProgram()" // This function can only be called by "static Shader::makeProgram()"
// makeProgramShader(...) make a program shader ready to be used in a Batch. // makeProgramShader(...) make a program shader ready to be used in a Batch.
@ -234,7 +219,7 @@ template<typename F>
void doInBatch(std::shared_ptr<gpu::Context> context, F f) { void doInBatch(std::shared_ptr<gpu::Context> context, F f) {
gpu::Batch batch; gpu::Batch batch;
f(batch); f(batch);
context->render(batch); context->append(batch);
} }
}; };

View file

@ -86,6 +86,15 @@ namespace gpu {
class TextureView; class TextureView;
using TextureViews = std::vector<TextureView>; using TextureViews = std::vector<TextureView>;
struct StereoState {
bool _enable{ false };
bool _skybox{ false };
// 0 for left eye, 1 for right eye
uint8 _pass{ 0 };
Mat4 _eyeViews[2];
Mat4 _eyeProjections[2];
};
namespace gl { namespace gl {
class GLBuffer; class GLBuffer;
} }

View file

@ -18,6 +18,7 @@ public:
glm::mat4 pose; glm::mat4 pose;
/// The collection of batches which make up the frame /// The collection of batches which make up the frame
std::vector<Batch> batches; std::vector<Batch> batches;
std::vector<StereoState> stereoStates;
/// The destination framebuffer in which the results will be placed /// The destination framebuffer in which the results will be placed
FramebufferPointer framebuffer; FramebufferPointer framebuffer;
}; };