Merge pull request #14915 from samcake/brown

Case 21190: Introducing msaa to forward renderer
This commit is contained in:
Andrew Meadows 2019-02-15 13:48:33 -08:00 committed by GitHub
commit 7872da6b97
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 146 additions and 16 deletions

View file

@ -246,7 +246,7 @@ public:
struct Flags { struct Flags {
Flags() : Flags() :
frontFaceClockwise(false), depthClampEnable(false), scissorEnable(false), multisampleEnable(false), frontFaceClockwise(false), depthClampEnable(false), scissorEnable(false), multisampleEnable(true),
antialisedLineEnable(true), alphaToCoverageEnable(false), _spare1(0) {} antialisedLineEnable(true), alphaToCoverageEnable(false), _spare1(0) {}
bool frontFaceClockwise : 1; bool frontFaceClockwise : 1;
bool depthClampEnable : 1; bool depthClampEnable : 1;

View file

@ -101,7 +101,7 @@ void DrawLayered3D::run(const RenderContextPointer& renderContext, const Inputs&
} }
} }
void CompositeHUD::run(const RenderContextPointer& renderContext) { void CompositeHUD::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& inputs) {
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_context); assert(renderContext->args->_context);
@ -119,6 +119,9 @@ void CompositeHUD::run(const RenderContextPointer& renderContext) {
renderContext->args->getViewFrustum().evalViewTransform(viewMat); renderContext->args->getViewFrustum().evalViewTransform(viewMat);
batch.setProjectionTransform(projMat); batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat, true); batch.setViewTransform(viewMat, true);
if (inputs) {
batch.setFramebuffer(inputs);
}
if (renderContext->args->_hudOperator) { if (renderContext->args->_hudOperator) {
renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture, renderContext->args->_renderMode == RenderArgs::RenderMode::MIRROR_RENDER_MODE); renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture, renderContext->args->_renderMode == RenderArgs::RenderMode::MIRROR_RENDER_MODE);
} }
@ -197,7 +200,73 @@ void Blit::run(const RenderContextPointer& renderContext, const gpu::Framebuffer
}); });
} }
void ExtractFrustums::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output) {
void ResolveFramebuffer::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) {
RenderArgs* args = renderContext->args;
auto srcFbo = inputs.get0();
auto destFbo = inputs.get1();
if (!destFbo) {
destFbo = args->_blitFramebuffer;
}
outputs = destFbo;
// Check valid src and dest
if (!srcFbo || !destFbo) {
return;
}
// Check valid size for sr and dest
auto frameSize(srcFbo->getSize());
if (destFbo->getSize() != frameSize) {
return;
}
gpu::Vec4i rectSrc;
rectSrc.z = frameSize.x;
rectSrc.w = frameSize.y;
gpu::doInBatch("Resolve", args->_context, [&](gpu::Batch& batch) {
batch.blit(srcFbo, rectSrc, destFbo, rectSrc);
});
}
void ResolveNewFramebuffer::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) {
RenderArgs* args = renderContext->args;
auto srcFbo = inputs;
outputs.reset();
// Check valid src
if (!srcFbo) {
return;
}
// Check valid size for sr and dest
auto frameSize(srcFbo->getSize());
// Resizing framebuffers instead of re-building them seems to cause issues with threaded rendering
if (_outputFramebuffer && _outputFramebuffer->getSize() != frameSize) {
_outputFramebuffer.reset();
}
if (!_outputFramebuffer) {
_outputFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("resolvedNew.out"));
auto colorFormat = gpu::Element::COLOR_SRGBA_32;
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR);
auto colorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler);
_outputFramebuffer->setRenderBuffer(0, colorTexture);
}
gpu::Vec4i rectSrc;
rectSrc.z = frameSize.x;
rectSrc.w = frameSize.y;
gpu::doInBatch("ResolveNew", args->_context, [&](gpu::Batch& batch) { batch.blit(srcFbo, rectSrc, _outputFramebuffer, rectSrc); });
outputs = _outputFramebuffer;
}
void ExtractFrustums::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output) {
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_context); assert(renderContext->args->_context);

View file

@ -77,10 +77,12 @@ protected:
class CompositeHUD { class CompositeHUD {
public: public:
using JobModel = render::Job::Model<CompositeHUD>; // IF specified the input Framebuffer is actively set by the batch of this job before calling the HUDOperator.
// If not, the current Framebuffer is left unchanged.
//using Inputs = gpu::FramebufferPointer;
using JobModel = render::Job::ModelI<CompositeHUD, gpu::FramebufferPointer>;
CompositeHUD() {} void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& inputs);
void run(const render::RenderContextPointer& renderContext);
}; };
class Blit { class Blit {
@ -90,6 +92,28 @@ public:
void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer); void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer);
}; };
class ResolveFramebuffer {
public:
using Inputs = render::VaryingSet2<gpu::FramebufferPointer, gpu::FramebufferPointer>;
using Outputs = gpu::FramebufferPointer;
using JobModel = render::Job::ModelIO<ResolveFramebuffer, Inputs, Outputs>;
void run(const render::RenderContextPointer& renderContext, const Inputs& source, Outputs& dest);
};
class ResolveNewFramebuffer {
public:
using Inputs = gpu::FramebufferPointer;
using Outputs = gpu::FramebufferPointer;
using JobModel = render::Job::ModelIO<ResolveNewFramebuffer, Inputs, Outputs>;
void run(const render::RenderContextPointer& renderContext, const Inputs& source, Outputs& dest);
private:
gpu::FramebufferPointer _outputFramebuffer;
};
class ExtractFrustums { class ExtractFrustums {
public: public:

View file

@ -257,8 +257,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
// Upscale to finale resolution // Upscale to finale resolution
const auto primaryFramebuffer = task.addJob<render::Upsample>("PrimaryBufferUpscale", scaledPrimaryFramebuffer); const auto primaryFramebuffer = task.addJob<render::Upsample>("PrimaryBufferUpscale", scaledPrimaryFramebuffer);
// Composite the HUD and HUD layered objects // Composite the HUD and HUD overlays
task.addJob<CompositeHUD>("HUD"); task.addJob<CompositeHUD>("HUD", primaryFramebuffer);
const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f)); const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f));
const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, nullJitter).asVarying(); const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, nullJitter).asVarying();

View file

@ -126,14 +126,24 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
task.addJob<DebugZoneLighting>("DrawZoneStack", debugZoneInputs); task.addJob<DebugZoneLighting>("DrawZoneStack", debugZoneInputs);
} }
// Just resolve the msaa
const auto resolveInputs =
ResolveFramebuffer::Inputs(framebuffer, static_cast<gpu::FramebufferPointer>(nullptr)).asVarying();
const auto resolvedFramebuffer = task.addJob<ResolveFramebuffer>("Resolve", resolveInputs);
//auto resolvedFramebuffer = task.addJob<ResolveNewFramebuffer>("Resolve", framebuffer);
#if defined(Q_OS_ANDROID)
#else
// Lighting Buffer ready for tone mapping // Lighting Buffer ready for tone mapping
// Forward rendering on GLES doesn't support tonemapping to and from the same FBO, so we specify // Forward rendering on GLES doesn't support tonemapping to and from the same FBO, so we specify
// the output FBO as null, which causes the tonemapping to target the blit framebuffer // the output FBO as null, which causes the tonemapping to target the blit framebuffer
const auto toneMappingInputs = ToneMappingDeferred::Inputs(framebuffer, static_cast<gpu::FramebufferPointer>(nullptr) ).asVarying(); const auto toneMappingInputs = ToneMappingDeferred::Inputs(resolvedFramebuffer, static_cast<gpu::FramebufferPointer>(nullptr)).asVarying();
task.addJob<ToneMappingDeferred>("ToneMapping", toneMappingInputs); task.addJob<ToneMappingDeferred>("ToneMapping", toneMappingInputs);
#endif
// Composite the HUD and HUD layered objects // Layered Overlays
task.addJob<CompositeHUD>("HUD"); // Composite the HUD and HUD overlays
task.addJob<CompositeHUD>("HUD", resolvedFramebuffer);
const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, nullJitter).asVarying(); const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, nullJitter).asVarying();
const auto hudTransparentsInputs = DrawLayered3D::Inputs(hudTransparent, lightingModel, nullJitter).asVarying(); const auto hudTransparentsInputs = DrawLayered3D::Inputs(hudTransparent, lightingModel, nullJitter).asVarying();
@ -145,26 +155,32 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
// task.addJob<Blit>("Blit", framebuffer); // task.addJob<Blit>("Blit", framebuffer);
} }
void PrepareFramebuffer::configure(const Config& config) {
_numSamples = config.getNumSamples();
}
void PrepareFramebuffer::run(const RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer) { void PrepareFramebuffer::run(const RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer) {
glm::uvec2 frameSize(renderContext->args->_viewport.z, renderContext->args->_viewport.w); glm::uvec2 frameSize(renderContext->args->_viewport.z, renderContext->args->_viewport.w);
// Resizing framebuffers instead of re-building them seems to cause issues with threaded rendering // Resizing framebuffers instead of re-building them seems to cause issues with threaded rendering
if (_framebuffer && _framebuffer->getSize() != frameSize) { if (_framebuffer && (_framebuffer->getSize() != frameSize || _framebuffer->getNumSamples() != _numSamples)) {
_framebuffer.reset(); _framebuffer.reset();
} }
if (!_framebuffer) { if (!_framebuffer) {
_framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("forward")); _framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("forward"));
int numSamples = _numSamples;
auto colorFormat = gpu::Element::COLOR_SRGBA_32; auto colorFormat = gpu::Element::COLOR_SRGBA_32;
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR);
auto colorTexture = auto colorTexture =
gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); gpu::Texture::createRenderBufferMultisample(colorFormat, frameSize.x, frameSize.y, numSamples, defaultSampler);
_framebuffer->setRenderBuffer(0, colorTexture); _framebuffer->setRenderBuffer(0, colorTexture);
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format
auto depthTexture = auto depthTexture =
gpu::Texture::createRenderBuffer(depthFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); gpu::Texture::createRenderBufferMultisample(depthFormat, frameSize.x, frameSize.y, numSamples, defaultSampler);
_framebuffer->setDepthStencilBuffer(depthTexture, depthFormat); _framebuffer->setDepthStencilBuffer(depthTexture, depthFormat);
} }

View file

@ -27,16 +27,37 @@ public:
void build(JobModel& task, const render::Varying& input, render::Varying& output); void build(JobModel& task, const render::Varying& input, render::Varying& output);
}; };
class PrepareFramebufferConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(int numSamples WRITE setNumSamples READ getNumSamples NOTIFY dirty)
public:
int getNumSamples() const { return numSamples; }
void setNumSamples(int num) {
numSamples = std::max(1, std::min(32, num));
emit dirty();
}
signals:
void dirty();
protected:
int numSamples{ 4 };
};
class PrepareFramebuffer { class PrepareFramebuffer {
public: public:
using Inputs = gpu::FramebufferPointer; using Inputs = gpu::FramebufferPointer;
using JobModel = render::Job::ModelO<PrepareFramebuffer, Inputs>; using Config = PrepareFramebufferConfig;
using JobModel = render::Job::ModelO<PrepareFramebuffer, Inputs, Config>;
void configure(const Config& config);
void run(const render::RenderContextPointer& renderContext, void run(const render::RenderContextPointer& renderContext,
gpu::FramebufferPointer& framebuffer); gpu::FramebufferPointer& framebuffer);
private: private:
gpu::FramebufferPointer _framebuffer; gpu::FramebufferPointer _framebuffer;
int _numSamples;
}; };
class PrepareForward { class PrepareForward {